From 9a43556161df84d41bb94c46aea2cb15e5fe0496 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Sat, 3 May 2025 22:55:08 +0000 Subject: [PATCH 01/11] fix: various tweaks --- .pre-commit-config.yaml | 4 +- .rules | 84 + sqlspec/base.py | 4 +- sqlspec/extensions/litestar/handlers.py | 20 +- sqlspec/extensions/litestar/plugin.py | 22 +- sqlspec/utils/sync_tools.py | 204 +- tests/unit/test_utils/test_sync_tools.py | 47 +- uv.lock | 4219 +++++++++++----------- 8 files changed, 2287 insertions(+), 2317 deletions(-) create mode 100644 .rules diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 85eb049..50271d5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ default_language_version: python: "3" repos: - repo: https://github.com/compilerla/conventional-pre-commit - rev: v4.0.0 + rev: v4.1.0 hooks: - id: conventional-pre-commit stages: [commit-msg] @@ -17,7 +17,7 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: "v0.11.6" + rev: "v0.11.8" hooks: - id: ruff args: ["--fix"] diff --git a/.rules b/.rules new file mode 100644 index 0000000..d8533bb --- /dev/null +++ b/.rules @@ -0,0 +1,84 @@ +# SQLSpec Development Guidelines + +## Naming Conventions + +- Private methods start with underscore: `_method_name` +- Configuration methods use "configure": `_configure_connection`, `_configure_pool` +- Connection callbacks use "on_connection_create" +- Configs follow the pattern `{DB}Config` (e.g. `DuckDBConfig`). If the database driver supports Sync and Async connections, use `{DB}SyncConfig` and `{DB}AsyncConfig` +- Each driver should export a type alias of that drivers Connection object (`DuckDBConnection: TypeAlias = DuckDBPyConnection`) +- Driver adapters follow pattern: `{DB}Driver` (e.g. `DuckDBDriver`). If the driver support Sync and Async connections, use `{DB}SyncDriver` and `{DB}AsyncDriver` +- Use Python 3.9+ type hints (this means `tuple` instead of `Tuple`, `dict` vs `Dict`, `list` vs `List`, etc) +- Never use `from __future__ import annotations`. Please stringify type quotes. +- Do not do needless variable assignments to make the linter satisfied. Simple cast or ignore instead of copying. + +## Base Protocol Structure + +- `DatabaseConfigProtocol` is the base for all configs +- Split connection creation into: + - `create_connection()` - public API + - `_create_connection()` - internal implementation + - `_configure_connection()` - post-creation setup + +## Connection Callback Pattern + +```python +on_connection_create: "Optional[Callable[[ConnectionT], Optional[ConnectionT]]]" = None +"""A callable to be called after the connection is created.""" + +def _configure_connection(self, connection: ConnectionT) -> ConnectionT: + """Configure a connection with the on_connection_create callback if set.""" + if self.on_connection_create is not None: + result = self.on_connection_create(connection) + if result is not None: + return result + return connection +``` + +## Config Class Structure + +- Sync/Async variants: + - `NoPoolSyncConfig` + - `NoPoolAsyncConfig` + - `SyncDatabaseConfig` + - `AsyncDatabaseConfig` +- All must implement: + - `create_connection()` + - `_create_connection()` + - `_configure_connection()` + +## Driver Adapter Structure + +- Inherit from appropriate base: + - `SyncDriverAdapterProtocol` + - `AsyncDriverAdapterProtocol` +- Common attributes: + - `connection: ConnectionT` + - `dialect: str` + - `__supports_arrow__: ClassVar[bool]` + +## Type Hints + +- Use `ConnectionT` for connection types +- Use `PoolT` for pool types +- Use `DriverT` for driver types +- Use `ModelDTOT` for model types +- Use `StatementParameterType` for query parameters + +## Error Handling + +- Use `NotFoundError` for missing results +- Use `check_not_found()` helper for result validation + +## SQL Processing + +- Use `_process_sql_params()` for SQL and parameter processing +- Use `SQLStatement` for SQL validation and formatting + +## Testing Requirements + +- Test both sync and async paths +- Test with and without connection pooling +- Test connection callbacks +- Test error cases +- Test type safety diff --git a/sqlspec/base.py b/sqlspec/base.py index ba33389..44a1d1a 100644 --- a/sqlspec/base.py +++ b/sqlspec/base.py @@ -21,7 +21,7 @@ from sqlspec.exceptions import NotFoundError from sqlspec.statement import SQLStatement from sqlspec.typing import ConnectionT, ModelDTOT, PoolT, StatementParameterType, T -from sqlspec.utils.sync_tools import maybe_async_ +from sqlspec.utils.sync_tools import ensure_async_ if TYPE_CHECKING: from contextlib import AbstractAsyncContextManager, AbstractContextManager @@ -206,7 +206,7 @@ def _cleanup_pools(self) -> None: for config in self._configs.values(): if config.support_connection_pooling and config.pool_instance is not None: with contextlib.suppress(Exception): - maybe_async_(config.close_pool)() + ensure_async_(config.close_pool)() @overload def add_config(self, config: "SyncConfigT") -> "type[SyncConfigT]": ... diff --git a/sqlspec/extensions/litestar/handlers.py b/sqlspec/extensions/litestar/handlers.py index 0d7cab1..b23df4f 100644 --- a/sqlspec/extensions/litestar/handlers.py +++ b/sqlspec/extensions/litestar/handlers.py @@ -9,7 +9,7 @@ get_sqlspec_scope_state, set_sqlspec_scope_state, ) -from sqlspec.utils.sync_tools import maybe_async_ +from sqlspec.utils.sync_tools import ensure_async_ if TYPE_CHECKING: from collections.abc import AsyncGenerator, Awaitable, Coroutine @@ -47,7 +47,7 @@ async def handler(message: "Message", scope: "Scope") -> None: connection = get_sqlspec_scope_state(scope, connection_scope_key) if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: with contextlib.suppress(Exception): - await maybe_async_(connection.close)() + await ensure_async_(connection.close)() delete_sqlspec_scope_state(scope, connection_scope_key) return handler @@ -98,13 +98,13 @@ async def handler(message: "Message", scope: "Scope") -> None: if (message["status"] in commit_range or message["status"] in extra_commit_statuses) and message[ "status" ] not in extra_rollback_statuses: - await maybe_async_(connection.commit)() + await ensure_async_(connection.commit)() else: - await maybe_async_(connection.rollback)() + await ensure_async_(connection.rollback)() finally: if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: with contextlib.suppress(Exception): - await maybe_async_(connection.close)() + await ensure_async_(connection.close)() delete_sqlspec_scope_state(scope, connection_scope_key) return handler @@ -126,14 +126,14 @@ def lifespan_handler_maker( @contextlib.asynccontextmanager async def lifespan_handler(app: "Litestar") -> "AsyncGenerator[None, None]": - db_pool = await maybe_async_(config.create_pool)() + db_pool = await ensure_async_(config.create_pool)() app.state.update({pool_key: db_pool}) try: yield finally: app.state.pop(pool_key, None) try: - await maybe_async_(config.close_pool)() + await ensure_async_(config.close_pool)() except Exception as e: # noqa: BLE001 if app.logger: app.logger.warning("Error closing database pool for %s. Error: %s", pool_key, e) @@ -158,7 +158,7 @@ def connection_provider_maker( async def provide_connection(state: "State", scope: "Scope") -> "ConnectionT": connection = get_sqlspec_scope_state(scope, connection_key) if connection is None: - connection = await maybe_async_(config.create_connection)() + connection = await ensure_async_(config.create_connection)() set_sqlspec_scope_state(scope, connection_key, connection) return cast("ConnectionT", connection) @@ -182,7 +182,7 @@ def pool_provider_maker( async def provide_pool(state: "State", scope: "Scope") -> "PoolT": pool = get_sqlspec_scope_state(scope, pool_key) if pool is None: - pool = await maybe_async_(config.create_pool)() + pool = await ensure_async_(config.create_pool)() set_sqlspec_scope_state(scope, pool_key, pool) return cast("PoolT", pool) @@ -206,7 +206,7 @@ def session_provider_maker( async def provide_session(state: "State", scope: "Scope") -> "DriverT": session = get_sqlspec_scope_state(scope, session_key) if session is None: - connection = await maybe_async_(config.create_connection)() + connection = await ensure_async_(config.create_connection)() session = config.driver_type(connection=connection) # pyright: ignore[reportCallIssue] set_sqlspec_scope_state(scope, session_key, session) return cast("DriverT", session) diff --git a/sqlspec/extensions/litestar/plugin.py b/sqlspec/extensions/litestar/plugin.py index 53e72a0..ee915b6 100644 --- a/sqlspec/extensions/litestar/plugin.py +++ b/sqlspec/extensions/litestar/plugin.py @@ -70,18 +70,16 @@ def on_app_init(self, app_config: "AppConfig") -> "AppConfig": The updated :class:`AppConfig <.config.app.AppConfig>` instance. """ self._validate_dependency_keys() - app_config.signature_types.extend( - [ - SQLSpec, - ConnectionT, - PoolT, - DriverT, - DatabaseConfig, - DatabaseConfigProtocol, - SyncConfigT, - AsyncConfigT, - ] - ) + app_config.signature_types.extend([ + SQLSpec, + ConnectionT, + PoolT, + DriverT, + DatabaseConfig, + DatabaseConfigProtocol, + SyncConfigT, + AsyncConfigT, + ]) for c in self._plugin_configs: c.annotation = self.add_config(c.config) app_config.signature_types.append(c.annotation) diff --git a/sqlspec/utils/sync_tools.py b/sqlspec/utils/sync_tools.py index 0fb0b91..a95132d 100644 --- a/sqlspec/utils/sync_tools.py +++ b/sqlspec/utils/sync_tools.py @@ -30,139 +30,6 @@ T = TypeVar("T") -class PendingType: - def __repr__(self) -> str: - return "AsyncPending" - - -Pending = PendingType() - - -class PendingValueError(Exception): - """Exception raised when a value is accessed before it is ready.""" - - -class SoonValue(Generic[T]): - """Holds a value that will be available soon after an async operation.""" - - def __init__(self) -> None: - self._stored_value: Union[T, PendingType] = Pending - - @property - def value(self) -> "T": - if isinstance(self._stored_value, PendingType): - msg = "The return value of this task is still pending." - raise PendingValueError(msg) - return self._stored_value - - @property - def ready(self) -> bool: - return not isinstance(self._stored_value, PendingType) - - -class TaskGroup: - """Manages a group of asyncio tasks, allowing them to be run concurrently.""" - - def __init__(self) -> None: - self._tasks: set[asyncio.Task[Any]] = set() - self._exceptions: list[BaseException] = [] - self._closed = False - - async def __aenter__(self) -> "TaskGroup": - if self._closed: - msg = "Cannot enter a task group that has already been closed." - raise RuntimeError(msg) - return self - - async def __aexit__( - self, - exc_type: "Optional[type[BaseException]]", # noqa: PYI036 - exc_val: "Optional[BaseException]", # noqa: PYI036 - exc_tb: "Optional[TracebackType]", # noqa: PYI036 - ) -> None: - self._closed = True - if exc_val: - self._exceptions.append(exc_val) - - if self._tasks: - await asyncio.wait(self._tasks) - - if self._exceptions: - # Re-raise the first exception encountered. - raise self._exceptions[0] - - def create_task(self, coro: "Coroutine[Any, Any, Any]") -> "asyncio.Task[Any]": - """Create and add a coroutine as a task to the task group. - - Args: - coro (Coroutine): The coroutine to be added as a task. - - Returns: - asyncio.Task: The created asyncio task. - - Raises: - RuntimeError: If the task group has already been closed. - """ - if self._closed: - msg = "Cannot create a task in a task group that has already been closed." - raise RuntimeError(msg) - task = asyncio.create_task(coro) - self._tasks.add(task) - task.add_done_callback(self._tasks.discard) - task.add_done_callback(self._check_result) - return task - - def _check_result(self, task: "asyncio.Task[Any]") -> None: - """Check and store exceptions from a completed task. - - Args: - task (asyncio.Task): The task to check for exceptions. - """ - try: - task.result() # This will raise the exception if one occurred. - except Exception as e: # noqa: BLE001 - self._exceptions.append(e) - - def start_soon_( - self, - async_function: "Callable[ParamSpecT, Awaitable[T]]", - name: object = None, - ) -> "Callable[ParamSpecT, SoonValue[T]]": - """Create a function to start a new task in this task group. - - Args: - async_function (Callable): An async function to call soon. - name (object, optional): Name of the task for introspection and debugging. - - Returns: - Callable: A function that starts the task and returns a SoonValue object. - """ - - @functools.wraps(async_function) - def wrapper(*args: "ParamSpecT.args", **kwargs: "ParamSpecT.kwargs") -> "SoonValue[T]": - partial_f = functools.partial(async_function, *args, **kwargs) - soon_value: SoonValue[T] = SoonValue() - - @functools.wraps(partial_f) - async def value_wrapper(*args: "Any") -> None: - value = await partial_f() - soon_value._stored_value = value # pyright: ignore[reportPrivateUsage] # noqa: SLF001 - - self.create_task(value_wrapper) # type: ignore[arg-type] - return soon_value - - return wrapper - - -def create_task_group() -> "TaskGroup": - """Create a TaskGroup for managing multiple concurrent async tasks. - - Returns: - TaskGroup: A new TaskGroup instance. - """ - return TaskGroup() - - class CapacityLimiter: """Limits the number of concurrent operations using a semaphore.""" @@ -195,7 +62,7 @@ async def __aexit__( self.release() -_default_limiter = CapacityLimiter(40) +_default_limiter = CapacityLimiter(15) def run_(async_function: "Callable[ParamSpecT, Coroutine[Any, Any, ReturnT]]") -> "Callable[ParamSpecT, ReturnT]": @@ -237,6 +104,7 @@ def await_( Args: async_function (Callable): The async function to convert. raise_sync_error (bool, optional): If False, runs in a new event loop if no loop is present. + If True (default), raises RuntimeError if no loop is running. Returns: Callable: A blocking function that runs the async function. @@ -248,12 +116,39 @@ def wrapper(*args: "ParamSpecT.args", **kwargs: "ParamSpecT.kwargs") -> "ReturnT try: loop = asyncio.get_running_loop() except RuntimeError: - loop = None - - if loop is None and raise_sync_error is False: + # No running event loop + if raise_sync_error: + msg = "await_ called without a running event loop and raise_sync_error=True" + raise RuntimeError(msg) from None + return asyncio.run(partial_f()) + else: + # Running in an existing event loop. + if loop.is_running(): + try: + # Check if the current context is within a task managed by this loop + current_task = asyncio.current_task(loop=loop) + except RuntimeError: + # Not running inside a task managed by this loop + current_task = None + + if current_task is not None: + # Called from within the event loop's execution context (a task). + # Blocking here would deadlock the loop. + msg = "await_ cannot be called from within an async task running on the same event loop. Use 'await' instead." + raise RuntimeError(msg) + # Called from a different thread than the loop's thread. + # It's safe to block this thread and wait for the loop. + future = asyncio.run_coroutine_threadsafe(partial_f(), loop) + # This blocks the *calling* thread, not the loop thread. + return future.result() + # This case should ideally not happen if get_running_loop() succeeded + # but the loop isn't running, but handle defensively. + # loop is not running + if raise_sync_error: + msg = "await_ found a non-running loop via get_running_loop()" + raise RuntimeError(msg) + # Fallback to running in a new loop return asyncio.run(partial_f()) - # Running in an existing event loop - return asyncio.run(partial_f()) return wrapper @@ -286,9 +181,17 @@ async def wrapper( return wrapper -def maybe_async_( +def ensure_async_( function: "Callable[ParamSpecT, Union[Awaitable[ReturnT], ReturnT]]", ) -> "Callable[ParamSpecT, Awaitable[ReturnT]]": + """Convert a function to an async one if it is not already. + + Args: + function (Callable): The function to convert. + + Returns: + Callable: An async function that runs the original function. + """ if inspect.iscoroutinefunction(function): return function @@ -301,16 +204,6 @@ async def wrapper(*args: "ParamSpecT.args", **kwargs: "ParamSpecT.kwargs") -> "R return wrapper -def wrap_sync(fn: "Callable[ParamSpecT, ReturnT]") -> "Callable[ParamSpecT, Awaitable[ReturnT]]": - if inspect.iscoroutinefunction(fn): - return fn - - async def wrapped(*args: "ParamSpecT.args", **kwargs: "ParamSpecT.kwargs") -> ReturnT: - return await async_(functools.partial(fn, *args, **kwargs))() - - return wrapped - - class _ContextManagerWrapper(Generic[T]): def __init__(self, cm: AbstractContextManager[T]) -> None: self._cm = cm @@ -327,9 +220,18 @@ async def __aexit__( return self._cm.__exit__(exc_type, exc_val, exc_tb) -def maybe_async_context( +def with_ensure_async_( obj: "Union[AbstractContextManager[T], AbstractAsyncContextManager[T]]", ) -> "AbstractAsyncContextManager[T]": + """Convert a context manager to an async one if it is not already. + + Args: + obj (AbstractContextManager[T] or AbstractAsyncContextManager[T]): The context manager to convert. + + Returns: + AbstractAsyncContextManager[T]: An async context manager that runs the original context manager. + """ + if isinstance(obj, AbstractContextManager): return cast("AbstractAsyncContextManager[T]", _ContextManagerWrapper(obj)) return obj diff --git a/tests/unit/test_utils/test_sync_tools.py b/tests/unit/test_utils/test_sync_tools.py index ec1145a..e860740 100644 --- a/tests/unit/test_utils/test_sync_tools.py +++ b/tests/unit/test_utils/test_sync_tools.py @@ -1,32 +1,25 @@ -import asyncio from collections.abc import AsyncIterator, Iterator from contextlib import asynccontextmanager, contextmanager from typing import TypeVar -import pytest - from sqlspec.utils.sync_tools import ( CapacityLimiter, - PendingValueError, - SoonValue, - TaskGroup, async_, await_, - maybe_async_, - maybe_async_context, + ensure_async_, run_, + with_ensure_async_, ) T = TypeVar("T") -@pytest.mark.asyncio -async def test_maybe_async() -> None: - @maybe_async_ +async def test_ensure_async_() -> None: + @ensure_async_ def sync_func(x: int) -> int: return x * 2 - @maybe_async_ # type: ignore[arg-type] + @ensure_async_ # type: ignore[arg-type] async def async_func(x: int) -> int: return x * 2 @@ -34,7 +27,6 @@ async def async_func(x: int) -> int: assert await async_func(21) == 42 -@pytest.mark.asyncio async def test_maybe_async_context() -> None: @contextmanager def sync_cm() -> Iterator[int]: @@ -44,37 +36,13 @@ def sync_cm() -> Iterator[int]: async def async_cm() -> AsyncIterator[int]: yield 42 - async with maybe_async_context(sync_cm()) as value: + async with with_ensure_async_(sync_cm()) as value: assert value == 42 - async with maybe_async_context(async_cm()) as value: + async with with_ensure_async_(async_cm()) as value: assert value == 42 -@pytest.mark.asyncio -async def test_soon_value() -> None: - soon_value = SoonValue[int]() - assert not soon_value.ready - with pytest.raises(PendingValueError): - _ = soon_value.value - - setattr(soon_value, "_stored_value", 42) - assert soon_value.ready - assert soon_value.value == 42 # type: ignore[unreachable] - - -@pytest.mark.asyncio -async def test_task_group() -> None: - async def sample_task(x: int) -> int: - return x * 2 - - async with TaskGroup() as tg: - task = tg.create_task(sample_task(21)) - await asyncio.wait([task]) - assert task.result() == 42 - - -@pytest.mark.asyncio async def test_capacity_limiter() -> None: limiter = CapacityLimiter(1) @@ -100,7 +68,6 @@ async def async_func(x: int) -> int: assert sync_func(21) == 42 -@pytest.mark.asyncio async def test_async_() -> None: def sync_func(x: int) -> int: return x * 2 diff --git a/uv.lock b/uv.lock index 5abc965..396c3bc 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 1 +revision = 2 requires-python = ">=3.9, <4.0" resolution-markers = [ "python_full_version >= '3.13'", @@ -16,13 +16,13 @@ dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/35/cf/05c630f2c076db860a1c70a1c2edaa6345a2d86090c498f5ad89f99ce727/adbc_driver_bigquery-1.5.0.tar.gz", hash = "sha256:d396d5454739b61e0b988584c25d9c06f7a8ec01a6fa2be46c7086da7016231f", size = 19231 } +sdist = { url = "https://files.pythonhosted.org/packages/35/cf/05c630f2c076db860a1c70a1c2edaa6345a2d86090c498f5ad89f99ce727/adbc_driver_bigquery-1.5.0.tar.gz", hash = "sha256:d396d5454739b61e0b988584c25d9c06f7a8ec01a6fa2be46c7086da7016231f", size = 19231, upload-time = "2025-03-07T00:55:00.94Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/33/1df7ad5f430d07a93f0126028ad0d151a33c80caccbf070e773128771de9/adbc_driver_bigquery-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:db0e666447c46e0d74948ef6a11ef2eff0457e8359d7b3c2be75452f92251cb5", size = 8683381 }, - { url = "https://files.pythonhosted.org/packages/6f/47/5f857fba33cd70949d06757915387a021326955b73fe927d93115e277704/adbc_driver_bigquery-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:446aa7affc30825fd01b8f197f3512f18f04d7480c61188e5f118478f71a2e6e", size = 8211988 }, - { url = "https://files.pythonhosted.org/packages/97/18/a1044bb04d0dac6599cf7b6669c394fbf136485a518230fd7a84389eb9e0/adbc_driver_bigquery-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d21365c0f4816e0f28605f05f88c365df82ab2d13cd7d3bd8d17449baf97770", size = 8079367 }, - { url = "https://files.pythonhosted.org/packages/71/57/65e52fd0d460a85188f5afa96346aba8a6eab2c1a7a330c98efaf176f90c/adbc_driver_bigquery-1.5.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fff37309963e710ffbb65ddf038cd34eef9486c1e155fd2e1afc9f72b418b72", size = 8778798 }, - { url = "https://files.pythonhosted.org/packages/a7/c6/e0f231ef145f30475f7b759ce2c74ed19db0a681295ea69fe55d572ee433/adbc_driver_bigquery-1.5.0-py3-none-win_amd64.whl", hash = "sha256:23652f2275eed25de1d55d4990bff36744544ec3034bb656489425cb197b8d6d", size = 16213586 }, + { url = "https://files.pythonhosted.org/packages/f4/33/1df7ad5f430d07a93f0126028ad0d151a33c80caccbf070e773128771de9/adbc_driver_bigquery-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:db0e666447c46e0d74948ef6a11ef2eff0457e8359d7b3c2be75452f92251cb5", size = 8683381, upload-time = "2025-03-07T00:53:36.707Z" }, + { url = "https://files.pythonhosted.org/packages/6f/47/5f857fba33cd70949d06757915387a021326955b73fe927d93115e277704/adbc_driver_bigquery-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:446aa7affc30825fd01b8f197f3512f18f04d7480c61188e5f118478f71a2e6e", size = 8211988, upload-time = "2025-03-07T00:53:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/97/18/a1044bb04d0dac6599cf7b6669c394fbf136485a518230fd7a84389eb9e0/adbc_driver_bigquery-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d21365c0f4816e0f28605f05f88c365df82ab2d13cd7d3bd8d17449baf97770", size = 8079367, upload-time = "2025-03-07T00:53:40.49Z" }, + { url = "https://files.pythonhosted.org/packages/71/57/65e52fd0d460a85188f5afa96346aba8a6eab2c1a7a330c98efaf176f90c/adbc_driver_bigquery-1.5.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fff37309963e710ffbb65ddf038cd34eef9486c1e155fd2e1afc9f72b418b72", size = 8778798, upload-time = "2025-03-07T00:53:42.568Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c6/e0f231ef145f30475f7b759ce2c74ed19db0a681295ea69fe55d572ee433/adbc_driver_bigquery-1.5.0-py3-none-win_amd64.whl", hash = "sha256:23652f2275eed25de1d55d4990bff36744544ec3034bb656489425cb197b8d6d", size = 16213586, upload-time = "2025-03-07T00:53:45.362Z" }, ] [[package]] @@ -33,13 +33,13 @@ dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/b4/e7a308591f5a0982d77021e00094e8bd3c325c01310338b04cc9f73d59b5/adbc_driver_flightsql-1.5.0.tar.gz", hash = "sha256:5beef9ec4916bce3baa03d376926f62244562fb5b8e9dd424934869bfb4558c5", size = 19924 } +sdist = { url = "https://files.pythonhosted.org/packages/f3/b4/e7a308591f5a0982d77021e00094e8bd3c325c01310338b04cc9f73d59b5/adbc_driver_flightsql-1.5.0.tar.gz", hash = "sha256:5beef9ec4916bce3baa03d376926f62244562fb5b8e9dd424934869bfb4558c5", size = 19924, upload-time = "2025-03-07T00:55:01.751Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/50/657710004d770c0d6c5aa51ba5bfc72f62a75bb64b57d857141ca4c9ad27/adbc_driver_flightsql-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:63df9621ee3fcfdf0d5c5c0d4aa8d8a3834e1b8ced50ccc6d27d25b01beaec57", size = 6560976 }, - { url = "https://files.pythonhosted.org/packages/43/4e/509f18621ddccc22cbc4f58c05e5261b5eeea40bc6a65238fabfcc216485/adbc_driver_flightsql-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93b61b865b7824d1a3f637a8780ac6928f37b4a4987956ec205a0e28ba4ecf03", size = 6178498 }, - { url = "https://files.pythonhosted.org/packages/bd/4d/480db656caad5b7225227c18ffabb76b9ed2b843d50477fb243c2e85293c/adbc_driver_flightsql-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b71399d108a1d0a621f412c86e433a4f7f7a66e8d82df434eaa419f65a2db0ff", size = 6055235 }, - { url = "https://files.pythonhosted.org/packages/5a/7c/53b2eda95f126a0dd42fa899f9a549360a79c75a2f272eb1eac4c3acc740/adbc_driver_flightsql-1.5.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29d9cd05f73d97cf9d9f716dbc521f1057d5d30908e448769290ce6d331b7b2e", size = 6599901 }, - { url = "https://files.pythonhosted.org/packages/5a/27/f48f748d3378866b8c33d4068102497650279a2b80bb8564e154d9fa2382/adbc_driver_flightsql-1.5.0-py3-none-win_amd64.whl", hash = "sha256:bf366ba3541c4c32d15cb899de73c57e0712569ac9ab3c765cdbdf1a5bbd8d96", size = 12257810 }, + { url = "https://files.pythonhosted.org/packages/8f/50/657710004d770c0d6c5aa51ba5bfc72f62a75bb64b57d857141ca4c9ad27/adbc_driver_flightsql-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:63df9621ee3fcfdf0d5c5c0d4aa8d8a3834e1b8ced50ccc6d27d25b01beaec57", size = 6560976, upload-time = "2025-03-07T00:53:47.434Z" }, + { url = "https://files.pythonhosted.org/packages/43/4e/509f18621ddccc22cbc4f58c05e5261b5eeea40bc6a65238fabfcc216485/adbc_driver_flightsql-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93b61b865b7824d1a3f637a8780ac6928f37b4a4987956ec205a0e28ba4ecf03", size = 6178498, upload-time = "2025-03-07T00:53:49.768Z" }, + { url = "https://files.pythonhosted.org/packages/bd/4d/480db656caad5b7225227c18ffabb76b9ed2b843d50477fb243c2e85293c/adbc_driver_flightsql-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b71399d108a1d0a621f412c86e433a4f7f7a66e8d82df434eaa419f65a2db0ff", size = 6055235, upload-time = "2025-03-07T00:53:51.272Z" }, + { url = "https://files.pythonhosted.org/packages/5a/7c/53b2eda95f126a0dd42fa899f9a549360a79c75a2f272eb1eac4c3acc740/adbc_driver_flightsql-1.5.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29d9cd05f73d97cf9d9f716dbc521f1057d5d30908e448769290ce6d331b7b2e", size = 6599901, upload-time = "2025-03-07T00:53:53.332Z" }, + { url = "https://files.pythonhosted.org/packages/5a/27/f48f748d3378866b8c33d4068102497650279a2b80bb8564e154d9fa2382/adbc_driver_flightsql-1.5.0-py3-none-win_amd64.whl", hash = "sha256:bf366ba3541c4c32d15cb899de73c57e0712569ac9ab3c765cdbdf1a5bbd8d96", size = 12257810, upload-time = "2025-03-07T00:53:55.429Z" }, ] [[package]] @@ -49,33 +49,33 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6b/e9/34d91055e13c86ff8a636ed9fd90752e21075541267774bf6ebc3cce7eae/adbc_driver_manager-1.5.0.tar.gz", hash = "sha256:db3f7a0e3f7d9c4df2e117b411407f8b1e0f202d9c2516f42cdf2d44415ac0d4", size = 107714 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/d4/dc1574f810a78c08c045a97cb108a15d5c1e47885c6711775b5edce650de/adbc_driver_manager-1.5.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:872e27c35e209c60a1b151630801847642afaadbd2e45bb2a6a66834c276c210", size = 380840 }, - { url = "https://files.pythonhosted.org/packages/50/3f/904d6324bcee5e9e51fb0e80b5c52fc062b1f2092c778101761e2aabe0b9/adbc_driver_manager-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9260a90bb87ead7634e2ddad6aa2cc90acdf6978450609a05ed0bc15cdbc4113", size = 368033 }, - { url = "https://files.pythonhosted.org/packages/cc/6e/a32e2982afd30edd2eb57b50e803a2daeaa9bef3c889fc867d155f6711e1/adbc_driver_manager-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65b5abe35349ceb3cdd9d30f24e5d757511aa50f28d1944d46e2d3064e88da25", size = 2038386 }, - { url = "https://files.pythonhosted.org/packages/55/0f/6fb1bbfb399ed6b9515f608ba1de5069d5a87d4732869c8922863338f854/adbc_driver_manager-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:917b724181112ad0e7bfbd46f951dae2fb0163884e3fc7c0149fdf571fb5f1ac", size = 2060224 }, - { url = "https://files.pythonhosted.org/packages/f3/50/e3c7c64836860dc8ce0b1b48c415e054a3c81ee584261ff2b6f418c7402a/adbc_driver_manager-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:339280a4314abaf1e5830a57cad1527425b7394e3ac92b3c81a01805f248ae9b", size = 535309 }, - { url = "https://files.pythonhosted.org/packages/68/d0/ad57a4a03817719e9ee5f57878229b6e78b6d841d2a983ab5f7d42b5d2bc/adbc_driver_manager-1.5.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:9e8ae0620a136d1fcee9b10070318bf2bda8692184eecc83c8583fbf58c438c6", size = 381818 }, - { url = "https://files.pythonhosted.org/packages/a2/6a/04286cd20fe5738d08e6b08524787d12a2c031420234903580cf6191807b/adbc_driver_manager-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f547e60a242daf4b9f7b7a9100573e33d86a6128f2248c7f4e958fec70d2413", size = 368715 }, - { url = "https://files.pythonhosted.org/packages/b5/98/0846e39180107821a865079db94b34e65d9771fc6865ba82ba0763e4f96d/adbc_driver_manager-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17f3b3538e751d23a18b8e4aaffdcca4e2de0bff69954b920cebc173d176d5d4", size = 2150181 }, - { url = "https://files.pythonhosted.org/packages/83/c3/91089e985f3436a6cbd52fc9f015af1a8028ca0e508472646c1f4c7daaa6/adbc_driver_manager-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c47a270711db680816378f93083a3a2153d1e3e5a82949ed4e15550a1cf46e2", size = 2164979 }, - { url = "https://files.pythonhosted.org/packages/9f/fe/90909d17b04172aab20ef2da54fc32014219a62e184e10935df5e5a78087/adbc_driver_manager-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:4cef37ddd48c4a3460c53701706132d255511f21dd8f7524566c2654ca16c906", size = 536664 }, - { url = "https://files.pythonhosted.org/packages/8b/02/093ef07a88ad304b07fcfbc8bd452ade6936d03fbe3bd1f1e6636b6340df/adbc_driver_manager-1.5.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:133cd63196d16b42e5b2ba5fe7b6e014848a656f5470819a9a0c75febfa47c0a", size = 381421 }, - { url = "https://files.pythonhosted.org/packages/78/ea/24ffd0e67af5e8b41be6016dbc6ce5493e0c5adcafa310113637617cbf4b/adbc_driver_manager-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bc2b183f82ab46cae347c36ca4ab52c042f7b610c7f5db2f515e22c831c185e", size = 365697 }, - { url = "https://files.pythonhosted.org/packages/bb/ef/6bc3014ad469deadb58a2460732d045aa1d3e55cbe03be03b89f382da90c/adbc_driver_manager-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab827d358756ca313db4351807b9f27afd938bcdbee87861f880a40e449b3216", size = 2129071 }, - { url = "https://files.pythonhosted.org/packages/21/54/d6401e064894685a4fd07ca4b2ba094c4190b35384beedf4ece020f33a34/adbc_driver_manager-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0170739f3b1995ccd1cfa4e108e142c50d3b47a019c9aa1a251f43d497bc93d1", size = 2161129 }, - { url = "https://files.pythonhosted.org/packages/f4/f6/ca520d1a76c8d273b17a9068de14d7fc52d69e03cc3c2aeb807c00d07d9f/adbc_driver_manager-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d1ef71398bc8622ca49224a20f68bd4948e546efdfdfb043b0760dfbd30b6e2", size = 533566 }, - { url = "https://files.pythonhosted.org/packages/51/4a/8c1303f0c6a42059390b8204cf6b9a26710b22db598ef8bee919f5f7097f/adbc_driver_manager-1.5.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:7c097a0dce36f651496e21a3e576857733a47f749de999d1a53901580d530484", size = 379609 }, - { url = "https://files.pythonhosted.org/packages/4b/b9/227cf6905af9fc406a2632fa96c4435a3d9cc3c40ecc09a513fcbf353fe7/adbc_driver_manager-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1efa9d8586020f785d22c3319eb14363df4e0de7a2666449af3f8c47876ecf2f", size = 363410 }, - { url = "https://files.pythonhosted.org/packages/d2/6a/0247a28a1ca64e531d7eff0e229368439b5b86dd29fd6079449eb0380d66/adbc_driver_manager-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7623dd5505f6f7ac4d8948a5ef816aca34ba388730b8690bbe2e7b1de8e7385c", size = 2123347 }, - { url = "https://files.pythonhosted.org/packages/52/66/36a57bda7858b3dfc303df2f0f5be840c778f0c3ea083680e6ae9c7795ff/adbc_driver_manager-1.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:826a4749806d68bc0ae2a490533093f7fb18c12ae353cc136e8f40974e11246d", size = 2156234 }, - { url = "https://files.pythonhosted.org/packages/b6/ac/1fb234f5b5c47088bf8db114b0e64b10f99d287e41e80ebe703482f4b6fc/adbc_driver_manager-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:ce4e0b9805df82213f8130af97320a5544f7a873982104cb81a9474adaf42caf", size = 531676 }, - { url = "https://files.pythonhosted.org/packages/76/84/bb12cc84c7e337e96acde5644cdd250eb9f97c39228aa32d45d02e8e33db/adbc_driver_manager-1.5.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:82c9aad221319d490ddf79ce841206d52fb102a2919a41a4dba5ff759bdf0e6e", size = 382176 }, - { url = "https://files.pythonhosted.org/packages/68/63/d678bc2c3d96bfb4d120fcad6d3be4c0b05922095a0b1129a9e6835c46f7/adbc_driver_manager-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f6296f6a63fa23aecdc14ebbae8cf8491cd52c6299510b6ce0388d66bd4b3aad", size = 369132 }, - { url = "https://files.pythonhosted.org/packages/1a/ee/2cd4a5254072d9cb6d25bf74615d5cf0c93e2cf22d2b96abf5bee5574c2b/adbc_driver_manager-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f81e38e28282edc532c69608c4c4e8de4bf3c5c17d8310863b42a4ed36535958", size = 2044587 }, - { url = "https://files.pythonhosted.org/packages/d7/7d/e24e7fedb09bce131ca5918afc0b2e35806131a3155a3a41d76ceb3ecdc9/adbc_driver_manager-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dac3e7c3f4981839c6afd276bd4502252b29b87571cb8da86a902c959387dae", size = 2059148 }, - { url = "https://files.pythonhosted.org/packages/d1/e4/870a2e1ac08eeb3ae1656c92b64dac8478bd968a8c4f7bacfeff57355a78/adbc_driver_manager-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:81581c5301c65f18230f885dbf6ef8fd60c01787ab7ce7597b0f39f36b134ec4", size = 536826 }, +sdist = { url = "https://files.pythonhosted.org/packages/6b/e9/34d91055e13c86ff8a636ed9fd90752e21075541267774bf6ebc3cce7eae/adbc_driver_manager-1.5.0.tar.gz", hash = "sha256:db3f7a0e3f7d9c4df2e117b411407f8b1e0f202d9c2516f42cdf2d44415ac0d4", size = 107714, upload-time = "2025-03-07T00:55:02.587Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/d4/dc1574f810a78c08c045a97cb108a15d5c1e47885c6711775b5edce650de/adbc_driver_manager-1.5.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:872e27c35e209c60a1b151630801847642afaadbd2e45bb2a6a66834c276c210", size = 380840, upload-time = "2025-03-07T00:53:57.154Z" }, + { url = "https://files.pythonhosted.org/packages/50/3f/904d6324bcee5e9e51fb0e80b5c52fc062b1f2092c778101761e2aabe0b9/adbc_driver_manager-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9260a90bb87ead7634e2ddad6aa2cc90acdf6978450609a05ed0bc15cdbc4113", size = 368033, upload-time = "2025-03-07T00:53:58.797Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6e/a32e2982afd30edd2eb57b50e803a2daeaa9bef3c889fc867d155f6711e1/adbc_driver_manager-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65b5abe35349ceb3cdd9d30f24e5d757511aa50f28d1944d46e2d3064e88da25", size = 2038386, upload-time = "2025-03-07T00:54:00.27Z" }, + { url = "https://files.pythonhosted.org/packages/55/0f/6fb1bbfb399ed6b9515f608ba1de5069d5a87d4732869c8922863338f854/adbc_driver_manager-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:917b724181112ad0e7bfbd46f951dae2fb0163884e3fc7c0149fdf571fb5f1ac", size = 2060224, upload-time = "2025-03-07T00:54:01.689Z" }, + { url = "https://files.pythonhosted.org/packages/f3/50/e3c7c64836860dc8ce0b1b48c415e054a3c81ee584261ff2b6f418c7402a/adbc_driver_manager-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:339280a4314abaf1e5830a57cad1527425b7394e3ac92b3c81a01805f248ae9b", size = 535309, upload-time = "2025-03-07T00:54:02.868Z" }, + { url = "https://files.pythonhosted.org/packages/68/d0/ad57a4a03817719e9ee5f57878229b6e78b6d841d2a983ab5f7d42b5d2bc/adbc_driver_manager-1.5.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:9e8ae0620a136d1fcee9b10070318bf2bda8692184eecc83c8583fbf58c438c6", size = 381818, upload-time = "2025-03-07T00:54:04.421Z" }, + { url = "https://files.pythonhosted.org/packages/a2/6a/04286cd20fe5738d08e6b08524787d12a2c031420234903580cf6191807b/adbc_driver_manager-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f547e60a242daf4b9f7b7a9100573e33d86a6128f2248c7f4e958fec70d2413", size = 368715, upload-time = "2025-03-07T00:54:05.95Z" }, + { url = "https://files.pythonhosted.org/packages/b5/98/0846e39180107821a865079db94b34e65d9771fc6865ba82ba0763e4f96d/adbc_driver_manager-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17f3b3538e751d23a18b8e4aaffdcca4e2de0bff69954b920cebc173d176d5d4", size = 2150181, upload-time = "2025-03-07T00:54:09.034Z" }, + { url = "https://files.pythonhosted.org/packages/83/c3/91089e985f3436a6cbd52fc9f015af1a8028ca0e508472646c1f4c7daaa6/adbc_driver_manager-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c47a270711db680816378f93083a3a2153d1e3e5a82949ed4e15550a1cf46e2", size = 2164979, upload-time = "2025-03-07T00:54:10.46Z" }, + { url = "https://files.pythonhosted.org/packages/9f/fe/90909d17b04172aab20ef2da54fc32014219a62e184e10935df5e5a78087/adbc_driver_manager-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:4cef37ddd48c4a3460c53701706132d255511f21dd8f7524566c2654ca16c906", size = 536664, upload-time = "2025-03-07T00:54:11.688Z" }, + { url = "https://files.pythonhosted.org/packages/8b/02/093ef07a88ad304b07fcfbc8bd452ade6936d03fbe3bd1f1e6636b6340df/adbc_driver_manager-1.5.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:133cd63196d16b42e5b2ba5fe7b6e014848a656f5470819a9a0c75febfa47c0a", size = 381421, upload-time = "2025-03-07T00:54:12.851Z" }, + { url = "https://files.pythonhosted.org/packages/78/ea/24ffd0e67af5e8b41be6016dbc6ce5493e0c5adcafa310113637617cbf4b/adbc_driver_manager-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bc2b183f82ab46cae347c36ca4ab52c042f7b610c7f5db2f515e22c831c185e", size = 365697, upload-time = "2025-03-07T00:54:14.095Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ef/6bc3014ad469deadb58a2460732d045aa1d3e55cbe03be03b89f382da90c/adbc_driver_manager-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab827d358756ca313db4351807b9f27afd938bcdbee87861f880a40e449b3216", size = 2129071, upload-time = "2025-03-07T00:54:15.189Z" }, + { url = "https://files.pythonhosted.org/packages/21/54/d6401e064894685a4fd07ca4b2ba094c4190b35384beedf4ece020f33a34/adbc_driver_manager-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0170739f3b1995ccd1cfa4e108e142c50d3b47a019c9aa1a251f43d497bc93d1", size = 2161129, upload-time = "2025-03-07T00:54:16.537Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f6/ca520d1a76c8d273b17a9068de14d7fc52d69e03cc3c2aeb807c00d07d9f/adbc_driver_manager-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d1ef71398bc8622ca49224a20f68bd4948e546efdfdfb043b0760dfbd30b6e2", size = 533566, upload-time = "2025-03-07T00:54:17.729Z" }, + { url = "https://files.pythonhosted.org/packages/51/4a/8c1303f0c6a42059390b8204cf6b9a26710b22db598ef8bee919f5f7097f/adbc_driver_manager-1.5.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:7c097a0dce36f651496e21a3e576857733a47f749de999d1a53901580d530484", size = 379609, upload-time = "2025-03-07T00:54:19.174Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b9/227cf6905af9fc406a2632fa96c4435a3d9cc3c40ecc09a513fcbf353fe7/adbc_driver_manager-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1efa9d8586020f785d22c3319eb14363df4e0de7a2666449af3f8c47876ecf2f", size = 363410, upload-time = "2025-03-07T00:54:20.653Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6a/0247a28a1ca64e531d7eff0e229368439b5b86dd29fd6079449eb0380d66/adbc_driver_manager-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7623dd5505f6f7ac4d8948a5ef816aca34ba388730b8690bbe2e7b1de8e7385c", size = 2123347, upload-time = "2025-03-07T00:54:21.832Z" }, + { url = "https://files.pythonhosted.org/packages/52/66/36a57bda7858b3dfc303df2f0f5be840c778f0c3ea083680e6ae9c7795ff/adbc_driver_manager-1.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:826a4749806d68bc0ae2a490533093f7fb18c12ae353cc136e8f40974e11246d", size = 2156234, upload-time = "2025-03-07T00:54:23.318Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ac/1fb234f5b5c47088bf8db114b0e64b10f99d287e41e80ebe703482f4b6fc/adbc_driver_manager-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:ce4e0b9805df82213f8130af97320a5544f7a873982104cb81a9474adaf42caf", size = 531676, upload-time = "2025-03-07T00:54:25.168Z" }, + { url = "https://files.pythonhosted.org/packages/76/84/bb12cc84c7e337e96acde5644cdd250eb9f97c39228aa32d45d02e8e33db/adbc_driver_manager-1.5.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:82c9aad221319d490ddf79ce841206d52fb102a2919a41a4dba5ff759bdf0e6e", size = 382176, upload-time = "2025-03-07T00:54:26.341Z" }, + { url = "https://files.pythonhosted.org/packages/68/63/d678bc2c3d96bfb4d120fcad6d3be4c0b05922095a0b1129a9e6835c46f7/adbc_driver_manager-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f6296f6a63fa23aecdc14ebbae8cf8491cd52c6299510b6ce0388d66bd4b3aad", size = 369132, upload-time = "2025-03-07T00:54:27.441Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ee/2cd4a5254072d9cb6d25bf74615d5cf0c93e2cf22d2b96abf5bee5574c2b/adbc_driver_manager-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f81e38e28282edc532c69608c4c4e8de4bf3c5c17d8310863b42a4ed36535958", size = 2044587, upload-time = "2025-03-07T00:54:29.537Z" }, + { url = "https://files.pythonhosted.org/packages/d7/7d/e24e7fedb09bce131ca5918afc0b2e35806131a3155a3a41d76ceb3ecdc9/adbc_driver_manager-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dac3e7c3f4981839c6afd276bd4502252b29b87571cb8da86a902c959387dae", size = 2059148, upload-time = "2025-03-07T00:54:31.067Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e4/870a2e1ac08eeb3ae1656c92b64dac8478bd968a8c4f7bacfeff57355a78/adbc_driver_manager-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:81581c5301c65f18230f885dbf6ef8fd60c01787ab7ce7597b0f39f36b134ec4", size = 536826, upload-time = "2025-03-07T00:54:32.335Z" }, ] [[package]] @@ -86,13 +86,13 @@ dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b5/61/7e6b9fc03fc294bcb9f18495a1f157bb6ee4f365a14d526dfc9977ecef72/adbc_driver_postgresql-1.5.0.tar.gz", hash = "sha256:3fc569ecd816838529e4778d5a5bd3678b6e35204d0b6428335e6bb3549312e8", size = 18400 } +sdist = { url = "https://files.pythonhosted.org/packages/b5/61/7e6b9fc03fc294bcb9f18495a1f157bb6ee4f365a14d526dfc9977ecef72/adbc_driver_postgresql-1.5.0.tar.gz", hash = "sha256:3fc569ecd816838529e4778d5a5bd3678b6e35204d0b6428335e6bb3549312e8", size = 18400, upload-time = "2025-03-07T00:55:03.91Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/c4/8f239c5047640bf15971c34b74c56d190be20c2841c11a196ea63241d360/adbc_driver_postgresql-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:fb359d9a735090f8267b01f455c6ac4646e6595b4c9d4acea5764e77630c86c2", size = 2683354 }, - { url = "https://files.pythonhosted.org/packages/a4/8a/6995f1746ea4db7456699e36c973ac9ddd87f7acbda939c0ca2b01189ded/adbc_driver_postgresql-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2f3e3a9b75c735eb79042e5f393f7b8aa699b3fe4c474b13871f85db7ad43eb3", size = 2997056 }, - { url = "https://files.pythonhosted.org/packages/39/c9/add6659f0df14d001d2933dbbf94511ea507c6a94fd4ae09aed9ab1f1b78/adbc_driver_postgresql-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dfe69557d1af24d0d6c05085f91df825f02ac837f0861528ba5c7aa79e0cf0d", size = 3190202 }, - { url = "https://files.pythonhosted.org/packages/22/dd/5335cee201c4f3e9cc3a101f306d1a09cf5956d44de8c80850bc958b7cd0/adbc_driver_postgresql-1.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b955dc6a53e3f01875659637d875b46bd04bf1ec361524c326c6963f5bc48a", size = 2846677 }, - { url = "https://files.pythonhosted.org/packages/cd/9d/e34bafc8e99c93fd42227ec1bb15d80f5f661beefc30e98b4e3b54ce0792/adbc_driver_postgresql-1.5.0-py3-none-win_amd64.whl", hash = "sha256:251674ada39becb6ae86949c4d0987950d18c9b9ff6a941ff7a96f6eba2e4365", size = 2702604 }, + { url = "https://files.pythonhosted.org/packages/6e/c4/8f239c5047640bf15971c34b74c56d190be20c2841c11a196ea63241d360/adbc_driver_postgresql-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:fb359d9a735090f8267b01f455c6ac4646e6595b4c9d4acea5764e77630c86c2", size = 2683354, upload-time = "2025-03-07T00:54:33.461Z" }, + { url = "https://files.pythonhosted.org/packages/a4/8a/6995f1746ea4db7456699e36c973ac9ddd87f7acbda939c0ca2b01189ded/adbc_driver_postgresql-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2f3e3a9b75c735eb79042e5f393f7b8aa699b3fe4c474b13871f85db7ad43eb3", size = 2997056, upload-time = "2025-03-07T00:54:34.956Z" }, + { url = "https://files.pythonhosted.org/packages/39/c9/add6659f0df14d001d2933dbbf94511ea507c6a94fd4ae09aed9ab1f1b78/adbc_driver_postgresql-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dfe69557d1af24d0d6c05085f91df825f02ac837f0861528ba5c7aa79e0cf0d", size = 3190202, upload-time = "2025-03-07T00:54:36.522Z" }, + { url = "https://files.pythonhosted.org/packages/22/dd/5335cee201c4f3e9cc3a101f306d1a09cf5956d44de8c80850bc958b7cd0/adbc_driver_postgresql-1.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b955dc6a53e3f01875659637d875b46bd04bf1ec361524c326c6963f5bc48a", size = 2846677, upload-time = "2025-03-07T00:54:37.849Z" }, + { url = "https://files.pythonhosted.org/packages/cd/9d/e34bafc8e99c93fd42227ec1bb15d80f5f661beefc30e98b4e3b54ce0792/adbc_driver_postgresql-1.5.0-py3-none-win_amd64.whl", hash = "sha256:251674ada39becb6ae86949c4d0987950d18c9b9ff6a941ff7a96f6eba2e4365", size = 2702604, upload-time = "2025-03-07T00:54:39.499Z" }, ] [[package]] @@ -103,13 +103,13 @@ dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/8f/41c7abe718e95dfbd443c5ca5de11b5c0b5be4f9e451dcb1367eca1f077e/adbc_driver_sqlite-1.5.0.tar.gz", hash = "sha256:bfb401e9bf3532977a4631d28bbff3114c056ef270acf9c038891af81e4d5295", size = 17011 } +sdist = { url = "https://files.pythonhosted.org/packages/5a/8f/41c7abe718e95dfbd443c5ca5de11b5c0b5be4f9e451dcb1367eca1f077e/adbc_driver_sqlite-1.5.0.tar.gz", hash = "sha256:bfb401e9bf3532977a4631d28bbff3114c056ef270acf9c038891af81e4d5295", size = 17011, upload-time = "2025-03-07T00:55:05.552Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/c4/29fd0540ff4fe0c685e03d032642d4d134c2d156a0b048037633fe80a0a8/adbc_driver_sqlite-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:4d58a5907903eb43fc6aa3d30da172b85670d1400af00a34e835071ecb8db320", size = 1040886 }, - { url = "https://files.pythonhosted.org/packages/0f/8d/d8f7d5681309e18f6a7e964aa3c8d3012a84923b5a7e14175011f67cfb4c/adbc_driver_sqlite-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a09f4bbd8eeebc8793603ec8462defb0d85dcbacffbf036d94cd1357bcecaf68", size = 1011230 }, - { url = "https://files.pythonhosted.org/packages/2d/90/3e4f4bbafaf67266e56a503bc4f706370ceb3ff0b3b1cb75dc7126f74d7f/adbc_driver_sqlite-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea30d29b402b259556045f61f9775fb75d86fbb74c8742ff7452545bc7fc1a6", size = 955040 }, - { url = "https://files.pythonhosted.org/packages/83/e3/d26f2e9b02544b51d30f3d6217597a3c1ae0e93b47235bc1033f91ebd024/adbc_driver_sqlite-1.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d91359bdd27a198472374583bd7e0a76d9a1f3973fa6671168e43c80665bae2", size = 976400 }, - { url = "https://files.pythonhosted.org/packages/bb/f1/4ca555bee7f80d8bd74bfeb61462e8c273931f588bf5fdc98ffffa025b6b/adbc_driver_sqlite-1.5.0-py3-none-win_amd64.whl", hash = "sha256:f6ef2e77e8221f243f86b490059c1c25ba1e5c875662287aba15a40f8297d323", size = 862790 }, + { url = "https://files.pythonhosted.org/packages/59/c4/29fd0540ff4fe0c685e03d032642d4d134c2d156a0b048037633fe80a0a8/adbc_driver_sqlite-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:4d58a5907903eb43fc6aa3d30da172b85670d1400af00a34e835071ecb8db320", size = 1040886, upload-time = "2025-03-07T00:54:54.515Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8d/d8f7d5681309e18f6a7e964aa3c8d3012a84923b5a7e14175011f67cfb4c/adbc_driver_sqlite-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a09f4bbd8eeebc8793603ec8462defb0d85dcbacffbf036d94cd1357bcecaf68", size = 1011230, upload-time = "2025-03-07T00:54:55.931Z" }, + { url = "https://files.pythonhosted.org/packages/2d/90/3e4f4bbafaf67266e56a503bc4f706370ceb3ff0b3b1cb75dc7126f74d7f/adbc_driver_sqlite-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea30d29b402b259556045f61f9775fb75d86fbb74c8742ff7452545bc7fc1a6", size = 955040, upload-time = "2025-03-07T00:54:57.097Z" }, + { url = "https://files.pythonhosted.org/packages/83/e3/d26f2e9b02544b51d30f3d6217597a3c1ae0e93b47235bc1033f91ebd024/adbc_driver_sqlite-1.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d91359bdd27a198472374583bd7e0a76d9a1f3973fa6671168e43c80665bae2", size = 976400, upload-time = "2025-03-07T00:54:58.342Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f1/4ca555bee7f80d8bd74bfeb61462e8c273931f588bf5fdc98ffffa025b6b/adbc_driver_sqlite-1.5.0-py3-none-win_amd64.whl", hash = "sha256:f6ef2e77e8221f243f86b490059c1c25ba1e5c875662287aba15a40f8297d323", size = 862790, upload-time = "2025-03-07T00:54:59.631Z" }, ] [[package]] @@ -119,9 +119,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyodbc" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/45/87/3a7580938f217212a574ba0d1af78203fc278fc439815f3fc515a7fdc12b/aioodbc-0.5.0.tar.gz", hash = "sha256:cbccd89ce595c033a49c9e6b4b55bbace7613a104b8a46e3d4c58c4bc4f25075", size = 41298 } +sdist = { url = "https://files.pythonhosted.org/packages/45/87/3a7580938f217212a574ba0d1af78203fc278fc439815f3fc515a7fdc12b/aioodbc-0.5.0.tar.gz", hash = "sha256:cbccd89ce595c033a49c9e6b4b55bbace7613a104b8a46e3d4c58c4bc4f25075", size = 41298, upload-time = "2023-10-28T21:37:29.966Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/80/4d1565bc16b53cd603c73dc4bc770e2e6418d957417e05031314760dc28c/aioodbc-0.5.0-py3-none-any.whl", hash = "sha256:bcaf16f007855fa4bf0ce6754b1f72c6c5a3d544188849577ddd55c5dc42985e", size = 19449 }, + { url = "https://files.pythonhosted.org/packages/b0/80/4d1565bc16b53cd603c73dc4bc770e2e6418d957417e05031314760dc28c/aioodbc-0.5.0-py3-none-any.whl", hash = "sha256:bcaf16f007855fa4bf0ce6754b1f72c6c5a3d544188849577ddd55c5dc42985e", size = 19449, upload-time = "2023-10-28T21:37:28.51Z" }, ] [[package]] @@ -131,9 +131,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/13/7d/8bca2bf9a247c2c5dfeec1d7a5f40db6518f88d314b8bca9da29670d2671/aiosqlite-0.21.0.tar.gz", hash = "sha256:131bb8056daa3bc875608c631c678cda73922a2d4ba8aec373b19f18c17e7aa3", size = 13454 } +sdist = { url = "https://files.pythonhosted.org/packages/13/7d/8bca2bf9a247c2c5dfeec1d7a5f40db6518f88d314b8bca9da29670d2671/aiosqlite-0.21.0.tar.gz", hash = "sha256:131bb8056daa3bc875608c631c678cda73922a2d4ba8aec373b19f18c17e7aa3", size = 13454, upload-time = "2025-02-03T07:30:16.235Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/10/6c25ed6de94c49f88a91fa5018cb4c0f3625f31d5be9f771ebe5cc7cd506/aiosqlite-0.21.0-py3-none-any.whl", hash = "sha256:2549cf4057f95f53dcba16f2b64e8e2791d7e1adedb13197dd8ed77bb226d7d0", size = 15792 }, + { url = "https://files.pythonhosted.org/packages/f5/10/6c25ed6de94c49f88a91fa5018cb4c0f3625f31d5be9f771ebe5cc7cd506/aiosqlite-0.21.0-py3-none-any.whl", hash = "sha256:2549cf4057f95f53dcba16f2b64e8e2791d7e1adedb13197dd8ed77bb226d7d0", size = 15792, upload-time = "2025-02-03T07:30:13.6Z" }, ] [[package]] @@ -143,9 +143,9 @@ source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776 } +sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776, upload-time = "2024-01-10T00:56:10.189Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511 }, + { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511, upload-time = "2024-01-10T00:56:08.388Z" }, ] [[package]] @@ -157,18 +157,18 @@ resolution-markers = [ "python_full_version >= '3.11' and python_full_version < '3.13'", "python_full_version == '3.10.*'", ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929 }, + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, ] [[package]] name = "annotated-types" version = "0.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] [[package]] @@ -181,9 +181,9 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } +sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 }, + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, ] [[package]] @@ -196,9 +196,9 @@ dependencies = [ { name = "platformdirs" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/cc65e31843d7bfda8313a9dc0c77a21e8580b782adca53c7cb3e511fe023/apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36", size = 99219 } +sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/cc65e31843d7bfda8313a9dc0c77a21e8580b782adca53c7cb3e511fe023/apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36", size = 99219, upload-time = "2023-08-14T15:32:41.381Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/7b/2d63664777b3e831ac1b1d8df5bbf0b7c8bee48e57115896080890527b1b/apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e", size = 107989 }, + { url = "https://files.pythonhosted.org/packages/89/7b/2d63664777b3e831ac1b1d8df5bbf0b7c8bee48e57115896080890527b1b/apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e", size = 107989, upload-time = "2023-08-14T15:32:40.064Z" }, ] [[package]] @@ -209,68 +209,68 @@ dependencies = [ { name = "domdf-python-tools" }, { name = "idna" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e5/4c/4f108cfd06923bd897bf992a6ecb6fb122646ee7af94d7f9a64abd071d4c/apeye_core-1.1.5.tar.gz", hash = "sha256:5de72ed3d00cc9b20fea55e54b7ab8f5ef8500eb33a5368bc162a5585e238a55", size = 96511 } +sdist = { url = "https://files.pythonhosted.org/packages/e5/4c/4f108cfd06923bd897bf992a6ecb6fb122646ee7af94d7f9a64abd071d4c/apeye_core-1.1.5.tar.gz", hash = "sha256:5de72ed3d00cc9b20fea55e54b7ab8f5ef8500eb33a5368bc162a5585e238a55", size = 96511, upload-time = "2024-01-30T17:45:48.727Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/9f/fa9971d2a0c6fef64c87ba362a493a4f230eff4ea8dfb9f4c7cbdf71892e/apeye_core-1.1.5-py3-none-any.whl", hash = "sha256:dc27a93f8c9e246b3b238c5ea51edf6115ab2618ef029b9f2d9a190ec8228fbf", size = 99286 }, + { url = "https://files.pythonhosted.org/packages/77/9f/fa9971d2a0c6fef64c87ba362a493a4f230eff4ea8dfb9f4c7cbdf71892e/apeye_core-1.1.5-py3-none-any.whl", hash = "sha256:dc27a93f8c9e246b3b238c5ea51edf6115ab2618ef029b9f2d9a190ec8228fbf", size = 99286, upload-time = "2024-01-30T17:45:46.764Z" }, ] [[package]] name = "async-timeout" version = "5.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274 } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233 }, + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, ] [[package]] name = "asyncmy" version = "0.2.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b5/76/55cc0577f9e838c5a5213bf33159b9e484c9d9820a2bafd4d6bfa631bf86/asyncmy-0.2.10.tar.gz", hash = "sha256:f4b67edadf7caa56bdaf1c2e6cf451150c0a86f5353744deabe4426fe27aff4e", size = 63889 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/c9/412b137c52f6c6437faba27412ccb32721571c42e59bc4f799796316866b/asyncmy-0.2.10-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:c2237c8756b8f374099bd320c53b16f7ec0cee8258f00d72eed5a2cd3d251066", size = 1803880 }, - { url = "https://files.pythonhosted.org/packages/74/f3/c9520f489dc42a594c8ad3cbe2088ec511245a3c55c3333e6fa949838420/asyncmy-0.2.10-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:6e98d4fbf7ea0d99dfecb24968c9c350b019397ba1af9f181d51bb0f6f81919b", size = 1736363 }, - { url = "https://files.pythonhosted.org/packages/52/9c/3c531a414290cbde9313cad54bb525caf6b1055ffa56bb271bf70512b533/asyncmy-0.2.10-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b1b1ee03556c7eda6422afc3aca132982a84706f8abf30f880d642f50670c7ed", size = 4970043 }, - { url = "https://files.pythonhosted.org/packages/03/64/176ed8a79d3a24b2e8ba7a11b429553f29fea20276537651526f3a87660b/asyncmy-0.2.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e2b97672ea3f0b335c0ffd3da1a5727b530f82f5032cd87e86c3aa3ac6df7f3", size = 5168645 }, - { url = "https://files.pythonhosted.org/packages/81/3f/46f126663649784ab6586bc9b482bca432a35588714170621db8d33d76e4/asyncmy-0.2.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c6471ce1f9ae1e6f0d55adfb57c49d0bcf5753a253cccbd33799ddb402fe7da2", size = 4988493 }, - { url = "https://files.pythonhosted.org/packages/5f/c6/acce7ea4b74e092582d65744418940b2b8c661102a22a638f58e7b651c6f/asyncmy-0.2.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:10e2a10fe44a2b216a1ae58fbdafa3fed661a625ec3c030c560c26f6ab618522", size = 5158496 }, - { url = "https://files.pythonhosted.org/packages/d5/01/d8fa0291083e9a0d899addda1f7608da37d28fff9bb4df1bd6f7f37354db/asyncmy-0.2.10-cp310-cp310-win32.whl", hash = "sha256:a791ab117787eb075bc37ed02caa7f3e30cca10f1b09ec7eeb51d733df1d49fc", size = 1624372 }, - { url = "https://files.pythonhosted.org/packages/cf/a0/ad6669fd2870492749c189a72c881716a3727b7f0bc972fc8cea7a40879c/asyncmy-0.2.10-cp310-cp310-win_amd64.whl", hash = "sha256:bd16fdc0964a4a1a19aec9797ca631c3ff2530013fdcd27225fc2e48af592804", size = 1694174 }, - { url = "https://files.pythonhosted.org/packages/72/1a/21b4af0d19862cc991f1095f006981a4f898599060dfa59f136e292b3e9a/asyncmy-0.2.10-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:7af0f1f31f800a8789620c195e92f36cce4def68ee70d625534544d43044ed2a", size = 1806974 }, - { url = "https://files.pythonhosted.org/packages/1d/ce/3579a88123ead38e60e0b6e744224907e3d7a668518f9a46ed584df4f788/asyncmy-0.2.10-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:800116ab85dc53b24f484fb644fefffac56db7367a31e7d62f4097d495105a2c", size = 1738218 }, - { url = "https://files.pythonhosted.org/packages/e2/39/10646bbafce22025be25aa709e83f0cdd3fb9089304cf9d3169a80540850/asyncmy-0.2.10-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:39525e9d7e557b83db268ed14b149a13530e0d09a536943dba561a8a1c94cc07", size = 5346417 }, - { url = "https://files.pythonhosted.org/packages/8f/f8/3fb0d0481def3a0900778f7d04f50028a4a2d987087a2f1e718e6c236e01/asyncmy-0.2.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76e199d6b57918999efc702d2dbb182cb7ba8c604cdfc912517955219b16eaea", size = 5553197 }, - { url = "https://files.pythonhosted.org/packages/82/a5/8281e8c0999fc6303b5b522ee82d1e338157a74f8bbbaa020e392b69156a/asyncmy-0.2.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9ca8fdd7dbbf2d9b4c2d3a5fac42b058707d6a483b71fded29051b8ae198a250", size = 5337915 }, - { url = "https://files.pythonhosted.org/packages/fe/f4/425108f5c6976ceb67b8f95bc73480fe777a95e7a89a29299664f5cb380f/asyncmy-0.2.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0df23db54e38602c803dacf1bbc1dcc4237a87223e659681f00d1a319a4f3826", size = 5524662 }, - { url = "https://files.pythonhosted.org/packages/ff/32/17291b12dce380abbbec888ea9d4e863fd2116530bf2c87c1ab40b39f9d1/asyncmy-0.2.10-cp311-cp311-win32.whl", hash = "sha256:a16633032be020b931acfd7cd1862c7dad42a96ea0b9b28786f2ec48e0a86757", size = 1622375 }, - { url = "https://files.pythonhosted.org/packages/e2/a3/76e65877de5e6fc853373908079adb711f80ed09aab4e152a533e0322375/asyncmy-0.2.10-cp311-cp311-win_amd64.whl", hash = "sha256:cca06212575922216b89218abd86a75f8f7375fc9c28159ea469f860785cdbc7", size = 1696693 }, - { url = "https://files.pythonhosted.org/packages/b8/82/5a4b1aedae9b35f7885f10568437d80507d7a6704b51da2fc960a20c4948/asyncmy-0.2.10-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:42295530c5f36784031f7fa42235ef8dd93a75d9b66904de087e68ff704b4f03", size = 1783558 }, - { url = "https://files.pythonhosted.org/packages/39/24/0fce480680531a29b51e1d2680a540c597e1a113aa1dc58cb7483c123a6b/asyncmy-0.2.10-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:641a853ffcec762905cbeceeb623839c9149b854d5c3716eb9a22c2b505802af", size = 1729268 }, - { url = "https://files.pythonhosted.org/packages/c8/96/74dc1aaf1ab0bde88d3c6b3a70bd25f18796adb4e91b77ad580efe232df5/asyncmy-0.2.10-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c554874223dd36b1cfc15e2cd0090792ea3832798e8fe9e9d167557e9cf31b4d", size = 5343513 }, - { url = "https://files.pythonhosted.org/packages/9a/04/14662ff5b9cfab5cc11dcf91f2316e2f80d88fbd2156e458deef3e72512a/asyncmy-0.2.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd16e84391dde8edb40c57d7db634706cbbafb75e6a01dc8b68a63f8dd9e44ca", size = 5592344 }, - { url = "https://files.pythonhosted.org/packages/7c/ac/3cf0abb3acd4f469bd012a1b4a01968bac07a142fca510da946b6ab1bf4f/asyncmy-0.2.10-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9f6b44c4bf4bb69a2a1d9d26dee302473099105ba95283b479458c448943ed3c", size = 5300819 }, - { url = "https://files.pythonhosted.org/packages/5c/23/6d05254d1c89ad15e7f32eb3df277afc7bbb2220faa83a76bea0b7bc6407/asyncmy-0.2.10-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:16d398b1aad0550c6fe1655b6758455e3554125af8aaf1f5abdc1546078c7257", size = 5548799 }, - { url = "https://files.pythonhosted.org/packages/fe/32/b7ce9782c741b6a821a0d11772f180f431a5c3ba6eaf2e6dfa1c3cbcf4df/asyncmy-0.2.10-cp312-cp312-win32.whl", hash = "sha256:59d2639dcc23939ae82b93b40a683c15a091460a3f77fa6aef1854c0a0af99cc", size = 1597544 }, - { url = "https://files.pythonhosted.org/packages/94/08/7de4f4a17196c355e4706ceba0ab60627541c78011881a7c69f41c6414c5/asyncmy-0.2.10-cp312-cp312-win_amd64.whl", hash = "sha256:4c6674073be97ffb7ac7f909e803008b23e50281131fef4e30b7b2162141a574", size = 1679064 }, - { url = "https://files.pythonhosted.org/packages/12/c8/eaa11a1716ce4505fa4d06d04abd8e1bda3aaa71c7d29209330dbd061b7a/asyncmy-0.2.10-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:244289bd1bea84384866bde50b09fe5b24856640e30a04073eacb71987b7b6ad", size = 1807310 }, - { url = "https://files.pythonhosted.org/packages/3a/50/4137cb6f0e2e57bee6ff71c5cbabea66efb88b90abc9d409609368d8314a/asyncmy-0.2.10-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:6c9d024b160b9f869a21e62c4ef34a7b7a4b5a886ae03019d4182621ea804d2c", size = 1739290 }, - { url = "https://files.pythonhosted.org/packages/cf/e9/46a7315d8a927ac012806c9502fd4d0b210554b415ef4a44319f961475b6/asyncmy-0.2.10-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b57594eea942224626203503f24fa88a47eaab3f13c9f24435091ea910f4b966", size = 4967850 }, - { url = "https://files.pythonhosted.org/packages/98/a2/fc991b329594bb372ddba296c89d7ace34271e35d92260cbea397abec40c/asyncmy-0.2.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:346192941470ac2d315f97afa14c0131ff846c911da14861baf8a1f8ed541664", size = 5169902 }, - { url = "https://files.pythonhosted.org/packages/1c/c6/754aaf8d28ea76cf86cef6d07489f277221dbc8e1fd38490a037a3138e58/asyncmy-0.2.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:957c2b48c5228e5f91fdf389daf38261a7b8989ad0eb0d1ba4e5680ef2a4a078", size = 5012169 }, - { url = "https://files.pythonhosted.org/packages/b2/6e/b66524785b89929da09adb5373ab360cc4ac2d97153dbd5b32e9904ac375/asyncmy-0.2.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:472989d7bfa405c108a7f3c408bbed52306504fb3aa28963d833cb7eeaafece0", size = 5186908 }, - { url = "https://files.pythonhosted.org/packages/90/2f/36fbf0a7555507ce06bf5fa6f743d94f7bc38c1e6bfb5e9ba5dd51001b33/asyncmy-0.2.10-cp39-cp39-win32.whl", hash = "sha256:714b0fdadd72031e972de2bbbd14e35a19d5a7e001594f0c8a69f92f0d05acc9", size = 1626531 }, - { url = "https://files.pythonhosted.org/packages/ff/99/cd737fbc8c1c14a0c39ca6d7e8f482c73a3990ecb150f2e7b2c5f2d665ab/asyncmy-0.2.10-cp39-cp39-win_amd64.whl", hash = "sha256:9fb58645d3da0b91db384f8519b16edc7dc421c966ada8647756318915d63696", size = 1696557 }, - { url = "https://files.pythonhosted.org/packages/83/32/3317d5290737a3c4685343fe37e02567518357c46ed87c51f47139d31ded/asyncmy-0.2.10-pp310-pypy310_pp73-macosx_13_0_x86_64.whl", hash = "sha256:f10c977c60a95bd6ec6b8654e20c8f53bad566911562a7ad7117ca94618f05d3", size = 1627680 }, - { url = "https://files.pythonhosted.org/packages/e9/e1/afeb50deb0554006c48b9f4f7b6b726e0aa42fa96d7cfbd3fdd0800765e2/asyncmy-0.2.10-pp310-pypy310_pp73-macosx_14_0_arm64.whl", hash = "sha256:aab07fbdb9466beaffef136ffabe388f0d295d8d2adb8f62c272f1d4076515b9", size = 1593957 }, - { url = "https://files.pythonhosted.org/packages/be/c1/56d3721e2b2eab84320058c3458da168d143446031eca3799aed481c33d2/asyncmy-0.2.10-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:63144322ade68262201baae73ad0c8a06b98a3c6ae39d1f3f21c41cc5287066a", size = 1756531 }, - { url = "https://files.pythonhosted.org/packages/ac/1a/295f06eb8e5926749265e08da9e2dc0dc14e0244bf36843997a1c8e18a50/asyncmy-0.2.10-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9659d95c6f2a611aec15bdd928950df937bf68bc4bbb68b809ee8924b6756067", size = 1752746 }, - { url = "https://files.pythonhosted.org/packages/ab/09/3a5351acc6273c28333cad8193184de0070c617fd8385fd8ba23d789e08d/asyncmy-0.2.10-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8ced4bd938e95ede0fb9fa54755773df47bdb9f29f142512501e613dd95cf4a4", size = 1614903 }, - { url = "https://files.pythonhosted.org/packages/a3/d1/28829c381e52166563706f2bc5e8043ab8599fc1d7e9c8ab26b21f2b33f4/asyncmy-0.2.10-pp39-pypy39_pp73-macosx_13_0_x86_64.whl", hash = "sha256:4651caaee6f4d7a8eb478a0dc460f8e91ab09a2d8d32444bc2b235544c791947", size = 1625889 }, - { url = "https://files.pythonhosted.org/packages/00/7f/110e9ef7cb38ff599725bbed08b76f656b2eae7505971ebc2a78b20716b9/asyncmy-0.2.10-pp39-pypy39_pp73-macosx_14_0_arm64.whl", hash = "sha256:ac091b327f01c38d91c697c810ba49e5f836890d48f6879ba0738040bb244290", size = 1592247 }, - { url = "https://files.pythonhosted.org/packages/1c/e6/036d5c23193f2c24b8dd4610eeae70380034d9ef37c29785c1624a19c92f/asyncmy-0.2.10-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:e1d2d9387cd3971297486c21098e035c620149c9033369491f58fe4fc08825b6", size = 1754251 }, - { url = "https://files.pythonhosted.org/packages/94/59/f97378316a48168e380948c814b346038f0f72fd99c986c42cba493edc7e/asyncmy-0.2.10-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a760cb486ddb2c936711325236e6b9213564a9bb5deb2f6949dbd16c8e4d739e", size = 1751010 }, - { url = "https://files.pythonhosted.org/packages/24/7b/3f90c33daab8409498a6e57760c6bd23ba3ecef3c684b59c9c6177030073/asyncmy-0.2.10-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1586f26633c05b16bcfc46d86e9875f4941280e12afa79a741cdf77ae4ccfb4d", size = 1613533 }, +sdist = { url = "https://files.pythonhosted.org/packages/b5/76/55cc0577f9e838c5a5213bf33159b9e484c9d9820a2bafd4d6bfa631bf86/asyncmy-0.2.10.tar.gz", hash = "sha256:f4b67edadf7caa56bdaf1c2e6cf451150c0a86f5353744deabe4426fe27aff4e", size = 63889, upload-time = "2024-12-12T14:45:09.2Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/c9/412b137c52f6c6437faba27412ccb32721571c42e59bc4f799796316866b/asyncmy-0.2.10-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:c2237c8756b8f374099bd320c53b16f7ec0cee8258f00d72eed5a2cd3d251066", size = 1803880, upload-time = "2024-12-13T02:36:20.194Z" }, + { url = "https://files.pythonhosted.org/packages/74/f3/c9520f489dc42a594c8ad3cbe2088ec511245a3c55c3333e6fa949838420/asyncmy-0.2.10-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:6e98d4fbf7ea0d99dfecb24968c9c350b019397ba1af9f181d51bb0f6f81919b", size = 1736363, upload-time = "2024-12-13T02:36:41.578Z" }, + { url = "https://files.pythonhosted.org/packages/52/9c/3c531a414290cbde9313cad54bb525caf6b1055ffa56bb271bf70512b533/asyncmy-0.2.10-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b1b1ee03556c7eda6422afc3aca132982a84706f8abf30f880d642f50670c7ed", size = 4970043, upload-time = "2024-12-13T02:35:47.734Z" }, + { url = "https://files.pythonhosted.org/packages/03/64/176ed8a79d3a24b2e8ba7a11b429553f29fea20276537651526f3a87660b/asyncmy-0.2.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e2b97672ea3f0b335c0ffd3da1a5727b530f82f5032cd87e86c3aa3ac6df7f3", size = 5168645, upload-time = "2024-12-13T02:35:50.999Z" }, + { url = "https://files.pythonhosted.org/packages/81/3f/46f126663649784ab6586bc9b482bca432a35588714170621db8d33d76e4/asyncmy-0.2.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c6471ce1f9ae1e6f0d55adfb57c49d0bcf5753a253cccbd33799ddb402fe7da2", size = 4988493, upload-time = "2024-12-13T02:35:54.062Z" }, + { url = "https://files.pythonhosted.org/packages/5f/c6/acce7ea4b74e092582d65744418940b2b8c661102a22a638f58e7b651c6f/asyncmy-0.2.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:10e2a10fe44a2b216a1ae58fbdafa3fed661a625ec3c030c560c26f6ab618522", size = 5158496, upload-time = "2024-12-13T02:35:56.723Z" }, + { url = "https://files.pythonhosted.org/packages/d5/01/d8fa0291083e9a0d899addda1f7608da37d28fff9bb4df1bd6f7f37354db/asyncmy-0.2.10-cp310-cp310-win32.whl", hash = "sha256:a791ab117787eb075bc37ed02caa7f3e30cca10f1b09ec7eeb51d733df1d49fc", size = 1624372, upload-time = "2024-12-13T02:36:14.158Z" }, + { url = "https://files.pythonhosted.org/packages/cf/a0/ad6669fd2870492749c189a72c881716a3727b7f0bc972fc8cea7a40879c/asyncmy-0.2.10-cp310-cp310-win_amd64.whl", hash = "sha256:bd16fdc0964a4a1a19aec9797ca631c3ff2530013fdcd27225fc2e48af592804", size = 1694174, upload-time = "2024-12-13T02:36:17.909Z" }, + { url = "https://files.pythonhosted.org/packages/72/1a/21b4af0d19862cc991f1095f006981a4f898599060dfa59f136e292b3e9a/asyncmy-0.2.10-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:7af0f1f31f800a8789620c195e92f36cce4def68ee70d625534544d43044ed2a", size = 1806974, upload-time = "2024-12-13T02:36:23.375Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ce/3579a88123ead38e60e0b6e744224907e3d7a668518f9a46ed584df4f788/asyncmy-0.2.10-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:800116ab85dc53b24f484fb644fefffac56db7367a31e7d62f4097d495105a2c", size = 1738218, upload-time = "2024-12-13T02:36:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/e2/39/10646bbafce22025be25aa709e83f0cdd3fb9089304cf9d3169a80540850/asyncmy-0.2.10-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:39525e9d7e557b83db268ed14b149a13530e0d09a536943dba561a8a1c94cc07", size = 5346417, upload-time = "2024-12-13T02:36:00.17Z" }, + { url = "https://files.pythonhosted.org/packages/8f/f8/3fb0d0481def3a0900778f7d04f50028a4a2d987087a2f1e718e6c236e01/asyncmy-0.2.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76e199d6b57918999efc702d2dbb182cb7ba8c604cdfc912517955219b16eaea", size = 5553197, upload-time = "2024-12-13T02:36:06.898Z" }, + { url = "https://files.pythonhosted.org/packages/82/a5/8281e8c0999fc6303b5b522ee82d1e338157a74f8bbbaa020e392b69156a/asyncmy-0.2.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9ca8fdd7dbbf2d9b4c2d3a5fac42b058707d6a483b71fded29051b8ae198a250", size = 5337915, upload-time = "2024-12-13T02:36:09.126Z" }, + { url = "https://files.pythonhosted.org/packages/fe/f4/425108f5c6976ceb67b8f95bc73480fe777a95e7a89a29299664f5cb380f/asyncmy-0.2.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0df23db54e38602c803dacf1bbc1dcc4237a87223e659681f00d1a319a4f3826", size = 5524662, upload-time = "2024-12-13T02:36:12.525Z" }, + { url = "https://files.pythonhosted.org/packages/ff/32/17291b12dce380abbbec888ea9d4e863fd2116530bf2c87c1ab40b39f9d1/asyncmy-0.2.10-cp311-cp311-win32.whl", hash = "sha256:a16633032be020b931acfd7cd1862c7dad42a96ea0b9b28786f2ec48e0a86757", size = 1622375, upload-time = "2024-12-13T02:36:22.276Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a3/76e65877de5e6fc853373908079adb711f80ed09aab4e152a533e0322375/asyncmy-0.2.10-cp311-cp311-win_amd64.whl", hash = "sha256:cca06212575922216b89218abd86a75f8f7375fc9c28159ea469f860785cdbc7", size = 1696693, upload-time = "2024-12-13T02:36:26.879Z" }, + { url = "https://files.pythonhosted.org/packages/b8/82/5a4b1aedae9b35f7885f10568437d80507d7a6704b51da2fc960a20c4948/asyncmy-0.2.10-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:42295530c5f36784031f7fa42235ef8dd93a75d9b66904de087e68ff704b4f03", size = 1783558, upload-time = "2024-12-13T02:36:28.922Z" }, + { url = "https://files.pythonhosted.org/packages/39/24/0fce480680531a29b51e1d2680a540c597e1a113aa1dc58cb7483c123a6b/asyncmy-0.2.10-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:641a853ffcec762905cbeceeb623839c9149b854d5c3716eb9a22c2b505802af", size = 1729268, upload-time = "2024-12-13T02:36:50.423Z" }, + { url = "https://files.pythonhosted.org/packages/c8/96/74dc1aaf1ab0bde88d3c6b3a70bd25f18796adb4e91b77ad580efe232df5/asyncmy-0.2.10-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c554874223dd36b1cfc15e2cd0090792ea3832798e8fe9e9d167557e9cf31b4d", size = 5343513, upload-time = "2024-12-13T02:36:17.099Z" }, + { url = "https://files.pythonhosted.org/packages/9a/04/14662ff5b9cfab5cc11dcf91f2316e2f80d88fbd2156e458deef3e72512a/asyncmy-0.2.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd16e84391dde8edb40c57d7db634706cbbafb75e6a01dc8b68a63f8dd9e44ca", size = 5592344, upload-time = "2024-12-13T02:36:21.202Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ac/3cf0abb3acd4f469bd012a1b4a01968bac07a142fca510da946b6ab1bf4f/asyncmy-0.2.10-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9f6b44c4bf4bb69a2a1d9d26dee302473099105ba95283b479458c448943ed3c", size = 5300819, upload-time = "2024-12-13T02:36:24.703Z" }, + { url = "https://files.pythonhosted.org/packages/5c/23/6d05254d1c89ad15e7f32eb3df277afc7bbb2220faa83a76bea0b7bc6407/asyncmy-0.2.10-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:16d398b1aad0550c6fe1655b6758455e3554125af8aaf1f5abdc1546078c7257", size = 5548799, upload-time = "2024-12-13T02:36:29.945Z" }, + { url = "https://files.pythonhosted.org/packages/fe/32/b7ce9782c741b6a821a0d11772f180f431a5c3ba6eaf2e6dfa1c3cbcf4df/asyncmy-0.2.10-cp312-cp312-win32.whl", hash = "sha256:59d2639dcc23939ae82b93b40a683c15a091460a3f77fa6aef1854c0a0af99cc", size = 1597544, upload-time = "2024-12-13T02:36:31.574Z" }, + { url = "https://files.pythonhosted.org/packages/94/08/7de4f4a17196c355e4706ceba0ab60627541c78011881a7c69f41c6414c5/asyncmy-0.2.10-cp312-cp312-win_amd64.whl", hash = "sha256:4c6674073be97ffb7ac7f909e803008b23e50281131fef4e30b7b2162141a574", size = 1679064, upload-time = "2024-12-13T02:36:39.479Z" }, + { url = "https://files.pythonhosted.org/packages/12/c8/eaa11a1716ce4505fa4d06d04abd8e1bda3aaa71c7d29209330dbd061b7a/asyncmy-0.2.10-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:244289bd1bea84384866bde50b09fe5b24856640e30a04073eacb71987b7b6ad", size = 1807310, upload-time = "2024-12-13T02:36:16.401Z" }, + { url = "https://files.pythonhosted.org/packages/3a/50/4137cb6f0e2e57bee6ff71c5cbabea66efb88b90abc9d409609368d8314a/asyncmy-0.2.10-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:6c9d024b160b9f869a21e62c4ef34a7b7a4b5a886ae03019d4182621ea804d2c", size = 1739290, upload-time = "2024-12-13T02:36:32.437Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e9/46a7315d8a927ac012806c9502fd4d0b210554b415ef4a44319f961475b6/asyncmy-0.2.10-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b57594eea942224626203503f24fa88a47eaab3f13c9f24435091ea910f4b966", size = 4967850, upload-time = "2024-12-13T02:35:35.221Z" }, + { url = "https://files.pythonhosted.org/packages/98/a2/fc991b329594bb372ddba296c89d7ace34271e35d92260cbea397abec40c/asyncmy-0.2.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:346192941470ac2d315f97afa14c0131ff846c911da14861baf8a1f8ed541664", size = 5169902, upload-time = "2024-12-13T02:35:37.81Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c6/754aaf8d28ea76cf86cef6d07489f277221dbc8e1fd38490a037a3138e58/asyncmy-0.2.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:957c2b48c5228e5f91fdf389daf38261a7b8989ad0eb0d1ba4e5680ef2a4a078", size = 5012169, upload-time = "2024-12-13T02:35:41.364Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6e/b66524785b89929da09adb5373ab360cc4ac2d97153dbd5b32e9904ac375/asyncmy-0.2.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:472989d7bfa405c108a7f3c408bbed52306504fb3aa28963d833cb7eeaafece0", size = 5186908, upload-time = "2024-12-13T02:35:44.398Z" }, + { url = "https://files.pythonhosted.org/packages/90/2f/36fbf0a7555507ce06bf5fa6f743d94f7bc38c1e6bfb5e9ba5dd51001b33/asyncmy-0.2.10-cp39-cp39-win32.whl", hash = "sha256:714b0fdadd72031e972de2bbbd14e35a19d5a7e001594f0c8a69f92f0d05acc9", size = 1626531, upload-time = "2024-12-13T02:36:07.777Z" }, + { url = "https://files.pythonhosted.org/packages/ff/99/cd737fbc8c1c14a0c39ca6d7e8f482c73a3990ecb150f2e7b2c5f2d665ab/asyncmy-0.2.10-cp39-cp39-win_amd64.whl", hash = "sha256:9fb58645d3da0b91db384f8519b16edc7dc421c966ada8647756318915d63696", size = 1696557, upload-time = "2024-12-13T02:36:10.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/32/3317d5290737a3c4685343fe37e02567518357c46ed87c51f47139d31ded/asyncmy-0.2.10-pp310-pypy310_pp73-macosx_13_0_x86_64.whl", hash = "sha256:f10c977c60a95bd6ec6b8654e20c8f53bad566911562a7ad7117ca94618f05d3", size = 1627680, upload-time = "2024-12-13T02:36:42.605Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e1/afeb50deb0554006c48b9f4f7b6b726e0aa42fa96d7cfbd3fdd0800765e2/asyncmy-0.2.10-pp310-pypy310_pp73-macosx_14_0_arm64.whl", hash = "sha256:aab07fbdb9466beaffef136ffabe388f0d295d8d2adb8f62c272f1d4076515b9", size = 1593957, upload-time = "2024-12-13T02:37:00.344Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/56d3721e2b2eab84320058c3458da168d143446031eca3799aed481c33d2/asyncmy-0.2.10-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:63144322ade68262201baae73ad0c8a06b98a3c6ae39d1f3f21c41cc5287066a", size = 1756531, upload-time = "2024-12-13T02:36:59.477Z" }, + { url = "https://files.pythonhosted.org/packages/ac/1a/295f06eb8e5926749265e08da9e2dc0dc14e0244bf36843997a1c8e18a50/asyncmy-0.2.10-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9659d95c6f2a611aec15bdd928950df937bf68bc4bbb68b809ee8924b6756067", size = 1752746, upload-time = "2024-12-13T02:37:01.999Z" }, + { url = "https://files.pythonhosted.org/packages/ab/09/3a5351acc6273c28333cad8193184de0070c617fd8385fd8ba23d789e08d/asyncmy-0.2.10-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8ced4bd938e95ede0fb9fa54755773df47bdb9f29f142512501e613dd95cf4a4", size = 1614903, upload-time = "2024-12-13T02:36:53Z" }, + { url = "https://files.pythonhosted.org/packages/a3/d1/28829c381e52166563706f2bc5e8043ab8599fc1d7e9c8ab26b21f2b33f4/asyncmy-0.2.10-pp39-pypy39_pp73-macosx_13_0_x86_64.whl", hash = "sha256:4651caaee6f4d7a8eb478a0dc460f8e91ab09a2d8d32444bc2b235544c791947", size = 1625889, upload-time = "2024-12-13T02:36:40.475Z" }, + { url = "https://files.pythonhosted.org/packages/00/7f/110e9ef7cb38ff599725bbed08b76f656b2eae7505971ebc2a78b20716b9/asyncmy-0.2.10-pp39-pypy39_pp73-macosx_14_0_arm64.whl", hash = "sha256:ac091b327f01c38d91c697c810ba49e5f836890d48f6879ba0738040bb244290", size = 1592247, upload-time = "2024-12-13T02:36:58.319Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e6/036d5c23193f2c24b8dd4610eeae70380034d9ef37c29785c1624a19c92f/asyncmy-0.2.10-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:e1d2d9387cd3971297486c21098e035c620149c9033369491f58fe4fc08825b6", size = 1754251, upload-time = "2024-12-13T02:36:52.178Z" }, + { url = "https://files.pythonhosted.org/packages/94/59/f97378316a48168e380948c814b346038f0f72fd99c986c42cba493edc7e/asyncmy-0.2.10-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a760cb486ddb2c936711325236e6b9213564a9bb5deb2f6949dbd16c8e4d739e", size = 1751010, upload-time = "2024-12-13T02:36:56.784Z" }, + { url = "https://files.pythonhosted.org/packages/24/7b/3f90c33daab8409498a6e57760c6bd23ba3ecef3c684b59c9c6177030073/asyncmy-0.2.10-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1586f26633c05b16bcfc46d86e9875f4941280e12afa79a741cdf77ae4ccfb4d", size = 1613533, upload-time = "2024-12-13T02:36:48.203Z" }, ] [[package]] @@ -280,48 +280,48 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "async-timeout", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2f/4c/7c991e080e106d854809030d8584e15b2e996e26f16aee6d757e387bc17d/asyncpg-0.30.0.tar.gz", hash = "sha256:c551e9928ab6707602f44811817f82ba3c446e018bfe1d3abecc8ba5f3eac851", size = 957746 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/07/1650a8c30e3a5c625478fa8aafd89a8dd7d85999bf7169b16f54973ebf2c/asyncpg-0.30.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bfb4dd5ae0699bad2b233672c8fc5ccbd9ad24b89afded02341786887e37927e", size = 673143 }, - { url = "https://files.pythonhosted.org/packages/a0/9a/568ff9b590d0954553c56806766914c149609b828c426c5118d4869111d3/asyncpg-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc1f62c792752a49f88b7e6f774c26077091b44caceb1983509edc18a2222ec0", size = 645035 }, - { url = "https://files.pythonhosted.org/packages/de/11/6f2fa6c902f341ca10403743701ea952bca896fc5b07cc1f4705d2bb0593/asyncpg-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3152fef2e265c9c24eec4ee3d22b4f4d2703d30614b0b6753e9ed4115c8a146f", size = 2912384 }, - { url = "https://files.pythonhosted.org/packages/83/83/44bd393919c504ffe4a82d0aed8ea0e55eb1571a1dea6a4922b723f0a03b/asyncpg-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7255812ac85099a0e1ffb81b10dc477b9973345793776b128a23e60148dd1af", size = 2947526 }, - { url = "https://files.pythonhosted.org/packages/08/85/e23dd3a2b55536eb0ded80c457b0693352262dc70426ef4d4a6fc994fa51/asyncpg-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:578445f09f45d1ad7abddbff2a3c7f7c291738fdae0abffbeb737d3fc3ab8b75", size = 2895390 }, - { url = "https://files.pythonhosted.org/packages/9b/26/fa96c8f4877d47dc6c1864fef5500b446522365da3d3d0ee89a5cce71a3f/asyncpg-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c42f6bb65a277ce4d93f3fba46b91a265631c8df7250592dd4f11f8b0152150f", size = 3015630 }, - { url = "https://files.pythonhosted.org/packages/34/00/814514eb9287614188a5179a8b6e588a3611ca47d41937af0f3a844b1b4b/asyncpg-0.30.0-cp310-cp310-win32.whl", hash = "sha256:aa403147d3e07a267ada2ae34dfc9324e67ccc4cdca35261c8c22792ba2b10cf", size = 568760 }, - { url = "https://files.pythonhosted.org/packages/f0/28/869a7a279400f8b06dd237266fdd7220bc5f7c975348fea5d1e6909588e9/asyncpg-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb622c94db4e13137c4c7f98834185049cc50ee01d8f657ef898b6407c7b9c50", size = 625764 }, - { url = "https://files.pythonhosted.org/packages/4c/0e/f5d708add0d0b97446c402db7e8dd4c4183c13edaabe8a8500b411e7b495/asyncpg-0.30.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5e0511ad3dec5f6b4f7a9e063591d407eee66b88c14e2ea636f187da1dcfff6a", size = 674506 }, - { url = "https://files.pythonhosted.org/packages/6a/a0/67ec9a75cb24a1d99f97b8437c8d56da40e6f6bd23b04e2f4ea5d5ad82ac/asyncpg-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:915aeb9f79316b43c3207363af12d0e6fd10776641a7de8a01212afd95bdf0ed", size = 645922 }, - { url = "https://files.pythonhosted.org/packages/5c/d9/a7584f24174bd86ff1053b14bb841f9e714380c672f61c906eb01d8ec433/asyncpg-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c198a00cce9506fcd0bf219a799f38ac7a237745e1d27f0e1f66d3707c84a5a", size = 3079565 }, - { url = "https://files.pythonhosted.org/packages/a0/d7/a4c0f9660e333114bdb04d1a9ac70db690dd4ae003f34f691139a5cbdae3/asyncpg-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3326e6d7381799e9735ca2ec9fd7be4d5fef5dcbc3cb555d8a463d8460607956", size = 3109962 }, - { url = "https://files.pythonhosted.org/packages/3c/21/199fd16b5a981b1575923cbb5d9cf916fdc936b377e0423099f209e7e73d/asyncpg-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51da377487e249e35bd0859661f6ee2b81db11ad1f4fc036194bc9cb2ead5056", size = 3064791 }, - { url = "https://files.pythonhosted.org/packages/77/52/0004809b3427534a0c9139c08c87b515f1c77a8376a50ae29f001e53962f/asyncpg-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc6d84136f9c4d24d358f3b02be4b6ba358abd09f80737d1ac7c444f36108454", size = 3188696 }, - { url = "https://files.pythonhosted.org/packages/52/cb/fbad941cd466117be58b774a3f1cc9ecc659af625f028b163b1e646a55fe/asyncpg-0.30.0-cp311-cp311-win32.whl", hash = "sha256:574156480df14f64c2d76450a3f3aaaf26105869cad3865041156b38459e935d", size = 567358 }, - { url = "https://files.pythonhosted.org/packages/3c/0a/0a32307cf166d50e1ad120d9b81a33a948a1a5463ebfa5a96cc5606c0863/asyncpg-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:3356637f0bd830407b5597317b3cb3571387ae52ddc3bca6233682be88bbbc1f", size = 629375 }, - { url = "https://files.pythonhosted.org/packages/4b/64/9d3e887bb7b01535fdbc45fbd5f0a8447539833b97ee69ecdbb7a79d0cb4/asyncpg-0.30.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c902a60b52e506d38d7e80e0dd5399f657220f24635fee368117b8b5fce1142e", size = 673162 }, - { url = "https://files.pythonhosted.org/packages/6e/eb/8b236663f06984f212a087b3e849731f917ab80f84450e943900e8ca4052/asyncpg-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aca1548e43bbb9f0f627a04666fedaca23db0a31a84136ad1f868cb15deb6e3a", size = 637025 }, - { url = "https://files.pythonhosted.org/packages/cc/57/2dc240bb263d58786cfaa60920779af6e8d32da63ab9ffc09f8312bd7a14/asyncpg-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c2a2ef565400234a633da0eafdce27e843836256d40705d83ab7ec42074efb3", size = 3496243 }, - { url = "https://files.pythonhosted.org/packages/f4/40/0ae9d061d278b10713ea9021ef6b703ec44698fe32178715a501ac696c6b/asyncpg-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1292b84ee06ac8a2ad8e51c7475aa309245874b61333d97411aab835c4a2f737", size = 3575059 }, - { url = "https://files.pythonhosted.org/packages/c3/75/d6b895a35a2c6506952247640178e5f768eeb28b2e20299b6a6f1d743ba0/asyncpg-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0f5712350388d0cd0615caec629ad53c81e506b1abaaf8d14c93f54b35e3595a", size = 3473596 }, - { url = "https://files.pythonhosted.org/packages/c8/e7/3693392d3e168ab0aebb2d361431375bd22ffc7b4a586a0fc060d519fae7/asyncpg-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db9891e2d76e6f425746c5d2da01921e9a16b5a71a1c905b13f30e12a257c4af", size = 3641632 }, - { url = "https://files.pythonhosted.org/packages/32/ea/15670cea95745bba3f0352341db55f506a820b21c619ee66b7d12ea7867d/asyncpg-0.30.0-cp312-cp312-win32.whl", hash = "sha256:68d71a1be3d83d0570049cd1654a9bdfe506e794ecc98ad0873304a9f35e411e", size = 560186 }, - { url = "https://files.pythonhosted.org/packages/7e/6b/fe1fad5cee79ca5f5c27aed7bd95baee529c1bf8a387435c8ba4fe53d5c1/asyncpg-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:9a0292c6af5c500523949155ec17b7fe01a00ace33b68a476d6b5059f9630305", size = 621064 }, - { url = "https://files.pythonhosted.org/packages/3a/22/e20602e1218dc07692acf70d5b902be820168d6282e69ef0d3cb920dc36f/asyncpg-0.30.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05b185ebb8083c8568ea8a40e896d5f7af4b8554b64d7719c0eaa1eb5a5c3a70", size = 670373 }, - { url = "https://files.pythonhosted.org/packages/3d/b3/0cf269a9d647852a95c06eb00b815d0b95a4eb4b55aa2d6ba680971733b9/asyncpg-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c47806b1a8cbb0a0db896f4cd34d89942effe353a5035c62734ab13b9f938da3", size = 634745 }, - { url = "https://files.pythonhosted.org/packages/8e/6d/a4f31bf358ce8491d2a31bfe0d7bcf25269e80481e49de4d8616c4295a34/asyncpg-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b6fde867a74e8c76c71e2f64f80c64c0f3163e687f1763cfaf21633ec24ec33", size = 3512103 }, - { url = "https://files.pythonhosted.org/packages/96/19/139227a6e67f407b9c386cb594d9628c6c78c9024f26df87c912fabd4368/asyncpg-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46973045b567972128a27d40001124fbc821c87a6cade040cfcd4fa8a30bcdc4", size = 3592471 }, - { url = "https://files.pythonhosted.org/packages/67/e4/ab3ca38f628f53f0fd28d3ff20edff1c975dd1cb22482e0061916b4b9a74/asyncpg-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9110df111cabc2ed81aad2f35394a00cadf4f2e0635603db6ebbd0fc896f46a4", size = 3496253 }, - { url = "https://files.pythonhosted.org/packages/ef/5f/0bf65511d4eeac3a1f41c54034a492515a707c6edbc642174ae79034d3ba/asyncpg-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04ff0785ae7eed6cc138e73fc67b8e51d54ee7a3ce9b63666ce55a0bf095f7ba", size = 3662720 }, - { url = "https://files.pythonhosted.org/packages/e7/31/1513d5a6412b98052c3ed9158d783b1e09d0910f51fbe0e05f56cc370bc4/asyncpg-0.30.0-cp313-cp313-win32.whl", hash = "sha256:ae374585f51c2b444510cdf3595b97ece4f233fde739aa14b50e0d64e8a7a590", size = 560404 }, - { url = "https://files.pythonhosted.org/packages/c8/a4/cec76b3389c4c5ff66301cd100fe88c318563ec8a520e0b2e792b5b84972/asyncpg-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:f59b430b8e27557c3fb9869222559f7417ced18688375825f8f12302c34e915e", size = 621623 }, - { url = "https://files.pythonhosted.org/packages/b4/82/d94f3ed6921136a0ef40a825740eda19437ccdad7d92d924302dca1d5c9e/asyncpg-0.30.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6f4e83f067b35ab5e6371f8a4c93296e0439857b4569850b178a01385e82e9ad", size = 673026 }, - { url = "https://files.pythonhosted.org/packages/4e/db/7db8b73c5d86ec9a21807f405e0698f8f637a8a3ca14b7b6fd4259b66bcf/asyncpg-0.30.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5df69d55add4efcd25ea2a3b02025b669a285b767bfbf06e356d68dbce4234ff", size = 644732 }, - { url = "https://files.pythonhosted.org/packages/eb/a0/1f1910659d08050cb3e8f7d82b32983974798d7fd4ddf7620b8e2023d4ac/asyncpg-0.30.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3479a0d9a852c7c84e822c073622baca862d1217b10a02dd57ee4a7a081f708", size = 2911761 }, - { url = "https://files.pythonhosted.org/packages/4d/53/5aa0d92488ded50bab2b6626430ed9743b0b7e2d864a2b435af1ccbf219a/asyncpg-0.30.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26683d3b9a62836fad771a18ecf4659a30f348a561279d6227dab96182f46144", size = 2946595 }, - { url = "https://files.pythonhosted.org/packages/c5/cd/d6d548d8ee721f4e0f7fbbe509bbac140d556c2e45814d945540c96cf7d4/asyncpg-0.30.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1b982daf2441a0ed314bd10817f1606f1c28b1136abd9e4f11335358c2c631cb", size = 2890135 }, - { url = "https://files.pythonhosted.org/packages/46/f0/28df398b685dabee20235e24880e1f6486d84ae7e6b0d11bdebc17740e7a/asyncpg-0.30.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1c06a3a50d014b303e5f6fc1e5f95eb28d2cee89cf58384b700da621e5d5e547", size = 3011889 }, - { url = "https://files.pythonhosted.org/packages/c8/07/8c7ffe6fe8bccff9b12fcb6410b1b2fa74b917fd8b837806a40217d5228b/asyncpg-0.30.0-cp39-cp39-win32.whl", hash = "sha256:1b11a555a198b08f5c4baa8f8231c74a366d190755aa4f99aacec5970afe929a", size = 569406 }, - { url = "https://files.pythonhosted.org/packages/05/51/f59e4df6d9b8937530d4b9fdee1598b93db40c631fe94ff3ce64207b7a95/asyncpg-0.30.0-cp39-cp39-win_amd64.whl", hash = "sha256:8b684a3c858a83cd876f05958823b68e8d14ec01bb0c0d14a6704c5bf9711773", size = 626581 }, +sdist = { url = "https://files.pythonhosted.org/packages/2f/4c/7c991e080e106d854809030d8584e15b2e996e26f16aee6d757e387bc17d/asyncpg-0.30.0.tar.gz", hash = "sha256:c551e9928ab6707602f44811817f82ba3c446e018bfe1d3abecc8ba5f3eac851", size = 957746, upload-time = "2024-10-20T00:30:41.127Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/07/1650a8c30e3a5c625478fa8aafd89a8dd7d85999bf7169b16f54973ebf2c/asyncpg-0.30.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bfb4dd5ae0699bad2b233672c8fc5ccbd9ad24b89afded02341786887e37927e", size = 673143, upload-time = "2024-10-20T00:29:08.846Z" }, + { url = "https://files.pythonhosted.org/packages/a0/9a/568ff9b590d0954553c56806766914c149609b828c426c5118d4869111d3/asyncpg-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc1f62c792752a49f88b7e6f774c26077091b44caceb1983509edc18a2222ec0", size = 645035, upload-time = "2024-10-20T00:29:12.02Z" }, + { url = "https://files.pythonhosted.org/packages/de/11/6f2fa6c902f341ca10403743701ea952bca896fc5b07cc1f4705d2bb0593/asyncpg-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3152fef2e265c9c24eec4ee3d22b4f4d2703d30614b0b6753e9ed4115c8a146f", size = 2912384, upload-time = "2024-10-20T00:29:13.644Z" }, + { url = "https://files.pythonhosted.org/packages/83/83/44bd393919c504ffe4a82d0aed8ea0e55eb1571a1dea6a4922b723f0a03b/asyncpg-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7255812ac85099a0e1ffb81b10dc477b9973345793776b128a23e60148dd1af", size = 2947526, upload-time = "2024-10-20T00:29:15.871Z" }, + { url = "https://files.pythonhosted.org/packages/08/85/e23dd3a2b55536eb0ded80c457b0693352262dc70426ef4d4a6fc994fa51/asyncpg-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:578445f09f45d1ad7abddbff2a3c7f7c291738fdae0abffbeb737d3fc3ab8b75", size = 2895390, upload-time = "2024-10-20T00:29:19.346Z" }, + { url = "https://files.pythonhosted.org/packages/9b/26/fa96c8f4877d47dc6c1864fef5500b446522365da3d3d0ee89a5cce71a3f/asyncpg-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c42f6bb65a277ce4d93f3fba46b91a265631c8df7250592dd4f11f8b0152150f", size = 3015630, upload-time = "2024-10-20T00:29:21.186Z" }, + { url = "https://files.pythonhosted.org/packages/34/00/814514eb9287614188a5179a8b6e588a3611ca47d41937af0f3a844b1b4b/asyncpg-0.30.0-cp310-cp310-win32.whl", hash = "sha256:aa403147d3e07a267ada2ae34dfc9324e67ccc4cdca35261c8c22792ba2b10cf", size = 568760, upload-time = "2024-10-20T00:29:22.769Z" }, + { url = "https://files.pythonhosted.org/packages/f0/28/869a7a279400f8b06dd237266fdd7220bc5f7c975348fea5d1e6909588e9/asyncpg-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb622c94db4e13137c4c7f98834185049cc50ee01d8f657ef898b6407c7b9c50", size = 625764, upload-time = "2024-10-20T00:29:25.882Z" }, + { url = "https://files.pythonhosted.org/packages/4c/0e/f5d708add0d0b97446c402db7e8dd4c4183c13edaabe8a8500b411e7b495/asyncpg-0.30.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5e0511ad3dec5f6b4f7a9e063591d407eee66b88c14e2ea636f187da1dcfff6a", size = 674506, upload-time = "2024-10-20T00:29:27.988Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a0/67ec9a75cb24a1d99f97b8437c8d56da40e6f6bd23b04e2f4ea5d5ad82ac/asyncpg-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:915aeb9f79316b43c3207363af12d0e6fd10776641a7de8a01212afd95bdf0ed", size = 645922, upload-time = "2024-10-20T00:29:29.391Z" }, + { url = "https://files.pythonhosted.org/packages/5c/d9/a7584f24174bd86ff1053b14bb841f9e714380c672f61c906eb01d8ec433/asyncpg-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c198a00cce9506fcd0bf219a799f38ac7a237745e1d27f0e1f66d3707c84a5a", size = 3079565, upload-time = "2024-10-20T00:29:30.832Z" }, + { url = "https://files.pythonhosted.org/packages/a0/d7/a4c0f9660e333114bdb04d1a9ac70db690dd4ae003f34f691139a5cbdae3/asyncpg-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3326e6d7381799e9735ca2ec9fd7be4d5fef5dcbc3cb555d8a463d8460607956", size = 3109962, upload-time = "2024-10-20T00:29:33.114Z" }, + { url = "https://files.pythonhosted.org/packages/3c/21/199fd16b5a981b1575923cbb5d9cf916fdc936b377e0423099f209e7e73d/asyncpg-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51da377487e249e35bd0859661f6ee2b81db11ad1f4fc036194bc9cb2ead5056", size = 3064791, upload-time = "2024-10-20T00:29:34.677Z" }, + { url = "https://files.pythonhosted.org/packages/77/52/0004809b3427534a0c9139c08c87b515f1c77a8376a50ae29f001e53962f/asyncpg-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc6d84136f9c4d24d358f3b02be4b6ba358abd09f80737d1ac7c444f36108454", size = 3188696, upload-time = "2024-10-20T00:29:36.389Z" }, + { url = "https://files.pythonhosted.org/packages/52/cb/fbad941cd466117be58b774a3f1cc9ecc659af625f028b163b1e646a55fe/asyncpg-0.30.0-cp311-cp311-win32.whl", hash = "sha256:574156480df14f64c2d76450a3f3aaaf26105869cad3865041156b38459e935d", size = 567358, upload-time = "2024-10-20T00:29:37.915Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0a/0a32307cf166d50e1ad120d9b81a33a948a1a5463ebfa5a96cc5606c0863/asyncpg-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:3356637f0bd830407b5597317b3cb3571387ae52ddc3bca6233682be88bbbc1f", size = 629375, upload-time = "2024-10-20T00:29:39.987Z" }, + { url = "https://files.pythonhosted.org/packages/4b/64/9d3e887bb7b01535fdbc45fbd5f0a8447539833b97ee69ecdbb7a79d0cb4/asyncpg-0.30.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c902a60b52e506d38d7e80e0dd5399f657220f24635fee368117b8b5fce1142e", size = 673162, upload-time = "2024-10-20T00:29:41.88Z" }, + { url = "https://files.pythonhosted.org/packages/6e/eb/8b236663f06984f212a087b3e849731f917ab80f84450e943900e8ca4052/asyncpg-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aca1548e43bbb9f0f627a04666fedaca23db0a31a84136ad1f868cb15deb6e3a", size = 637025, upload-time = "2024-10-20T00:29:43.352Z" }, + { url = "https://files.pythonhosted.org/packages/cc/57/2dc240bb263d58786cfaa60920779af6e8d32da63ab9ffc09f8312bd7a14/asyncpg-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c2a2ef565400234a633da0eafdce27e843836256d40705d83ab7ec42074efb3", size = 3496243, upload-time = "2024-10-20T00:29:44.922Z" }, + { url = "https://files.pythonhosted.org/packages/f4/40/0ae9d061d278b10713ea9021ef6b703ec44698fe32178715a501ac696c6b/asyncpg-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1292b84ee06ac8a2ad8e51c7475aa309245874b61333d97411aab835c4a2f737", size = 3575059, upload-time = "2024-10-20T00:29:46.891Z" }, + { url = "https://files.pythonhosted.org/packages/c3/75/d6b895a35a2c6506952247640178e5f768eeb28b2e20299b6a6f1d743ba0/asyncpg-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0f5712350388d0cd0615caec629ad53c81e506b1abaaf8d14c93f54b35e3595a", size = 3473596, upload-time = "2024-10-20T00:29:49.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e7/3693392d3e168ab0aebb2d361431375bd22ffc7b4a586a0fc060d519fae7/asyncpg-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db9891e2d76e6f425746c5d2da01921e9a16b5a71a1c905b13f30e12a257c4af", size = 3641632, upload-time = "2024-10-20T00:29:50.768Z" }, + { url = "https://files.pythonhosted.org/packages/32/ea/15670cea95745bba3f0352341db55f506a820b21c619ee66b7d12ea7867d/asyncpg-0.30.0-cp312-cp312-win32.whl", hash = "sha256:68d71a1be3d83d0570049cd1654a9bdfe506e794ecc98ad0873304a9f35e411e", size = 560186, upload-time = "2024-10-20T00:29:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/7e/6b/fe1fad5cee79ca5f5c27aed7bd95baee529c1bf8a387435c8ba4fe53d5c1/asyncpg-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:9a0292c6af5c500523949155ec17b7fe01a00ace33b68a476d6b5059f9630305", size = 621064, upload-time = "2024-10-20T00:29:53.757Z" }, + { url = "https://files.pythonhosted.org/packages/3a/22/e20602e1218dc07692acf70d5b902be820168d6282e69ef0d3cb920dc36f/asyncpg-0.30.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05b185ebb8083c8568ea8a40e896d5f7af4b8554b64d7719c0eaa1eb5a5c3a70", size = 670373, upload-time = "2024-10-20T00:29:55.165Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b3/0cf269a9d647852a95c06eb00b815d0b95a4eb4b55aa2d6ba680971733b9/asyncpg-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c47806b1a8cbb0a0db896f4cd34d89942effe353a5035c62734ab13b9f938da3", size = 634745, upload-time = "2024-10-20T00:29:57.14Z" }, + { url = "https://files.pythonhosted.org/packages/8e/6d/a4f31bf358ce8491d2a31bfe0d7bcf25269e80481e49de4d8616c4295a34/asyncpg-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b6fde867a74e8c76c71e2f64f80c64c0f3163e687f1763cfaf21633ec24ec33", size = 3512103, upload-time = "2024-10-20T00:29:58.499Z" }, + { url = "https://files.pythonhosted.org/packages/96/19/139227a6e67f407b9c386cb594d9628c6c78c9024f26df87c912fabd4368/asyncpg-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46973045b567972128a27d40001124fbc821c87a6cade040cfcd4fa8a30bcdc4", size = 3592471, upload-time = "2024-10-20T00:30:00.354Z" }, + { url = "https://files.pythonhosted.org/packages/67/e4/ab3ca38f628f53f0fd28d3ff20edff1c975dd1cb22482e0061916b4b9a74/asyncpg-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9110df111cabc2ed81aad2f35394a00cadf4f2e0635603db6ebbd0fc896f46a4", size = 3496253, upload-time = "2024-10-20T00:30:02.794Z" }, + { url = "https://files.pythonhosted.org/packages/ef/5f/0bf65511d4eeac3a1f41c54034a492515a707c6edbc642174ae79034d3ba/asyncpg-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04ff0785ae7eed6cc138e73fc67b8e51d54ee7a3ce9b63666ce55a0bf095f7ba", size = 3662720, upload-time = "2024-10-20T00:30:04.501Z" }, + { url = "https://files.pythonhosted.org/packages/e7/31/1513d5a6412b98052c3ed9158d783b1e09d0910f51fbe0e05f56cc370bc4/asyncpg-0.30.0-cp313-cp313-win32.whl", hash = "sha256:ae374585f51c2b444510cdf3595b97ece4f233fde739aa14b50e0d64e8a7a590", size = 560404, upload-time = "2024-10-20T00:30:06.537Z" }, + { url = "https://files.pythonhosted.org/packages/c8/a4/cec76b3389c4c5ff66301cd100fe88c318563ec8a520e0b2e792b5b84972/asyncpg-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:f59b430b8e27557c3fb9869222559f7417ced18688375825f8f12302c34e915e", size = 621623, upload-time = "2024-10-20T00:30:09.024Z" }, + { url = "https://files.pythonhosted.org/packages/b4/82/d94f3ed6921136a0ef40a825740eda19437ccdad7d92d924302dca1d5c9e/asyncpg-0.30.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6f4e83f067b35ab5e6371f8a4c93296e0439857b4569850b178a01385e82e9ad", size = 673026, upload-time = "2024-10-20T00:30:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/4e/db/7db8b73c5d86ec9a21807f405e0698f8f637a8a3ca14b7b6fd4259b66bcf/asyncpg-0.30.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5df69d55add4efcd25ea2a3b02025b669a285b767bfbf06e356d68dbce4234ff", size = 644732, upload-time = "2024-10-20T00:30:28.393Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a0/1f1910659d08050cb3e8f7d82b32983974798d7fd4ddf7620b8e2023d4ac/asyncpg-0.30.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3479a0d9a852c7c84e822c073622baca862d1217b10a02dd57ee4a7a081f708", size = 2911761, upload-time = "2024-10-20T00:30:30.569Z" }, + { url = "https://files.pythonhosted.org/packages/4d/53/5aa0d92488ded50bab2b6626430ed9743b0b7e2d864a2b435af1ccbf219a/asyncpg-0.30.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26683d3b9a62836fad771a18ecf4659a30f348a561279d6227dab96182f46144", size = 2946595, upload-time = "2024-10-20T00:30:32.244Z" }, + { url = "https://files.pythonhosted.org/packages/c5/cd/d6d548d8ee721f4e0f7fbbe509bbac140d556c2e45814d945540c96cf7d4/asyncpg-0.30.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1b982daf2441a0ed314bd10817f1606f1c28b1136abd9e4f11335358c2c631cb", size = 2890135, upload-time = "2024-10-20T00:30:33.817Z" }, + { url = "https://files.pythonhosted.org/packages/46/f0/28df398b685dabee20235e24880e1f6486d84ae7e6b0d11bdebc17740e7a/asyncpg-0.30.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1c06a3a50d014b303e5f6fc1e5f95eb28d2cee89cf58384b700da621e5d5e547", size = 3011889, upload-time = "2024-10-20T00:30:35.378Z" }, + { url = "https://files.pythonhosted.org/packages/c8/07/8c7ffe6fe8bccff9b12fcb6410b1b2fa74b917fd8b837806a40217d5228b/asyncpg-0.30.0-cp39-cp39-win32.whl", hash = "sha256:1b11a555a198b08f5c4baa8f8231c74a366d190755aa4f99aacec5970afe929a", size = 569406, upload-time = "2024-10-20T00:30:37.644Z" }, + { url = "https://files.pythonhosted.org/packages/05/51/f59e4df6d9b8937530d4b9fdee1598b93db40c631fe94ff3ce64207b7a95/asyncpg-0.30.0-cp39-cp39-win_amd64.whl", hash = "sha256:8b684a3c858a83cd876f05958823b68e8d14ec01bb0c0d14a6704c5bf9711773", size = 626581, upload-time = "2024-10-20T00:30:39.69Z" }, ] [[package]] @@ -332,9 +332,9 @@ dependencies = [ { name = "asyncpg" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8c/54/060d7ccafa322f15676daa5e32d34453e4a0ff24abb1f44182ffddc8a2d2/asyncpg_stubs-0.30.1.tar.gz", hash = "sha256:236b88fca49d0d181939ed35c21f79c9c404bc3cca51f8493f6d55210ecfcaf3", size = 20343 } +sdist = { url = "https://files.pythonhosted.org/packages/8c/54/060d7ccafa322f15676daa5e32d34453e4a0ff24abb1f44182ffddc8a2d2/asyncpg_stubs-0.30.1.tar.gz", hash = "sha256:236b88fca49d0d181939ed35c21f79c9c404bc3cca51f8493f6d55210ecfcaf3", size = 20343, upload-time = "2025-03-14T19:51:55.528Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/51/29715a2551471a9ff4e196f02955e915ccbf7477c90bb2d6e59737d94f1b/asyncpg_stubs-0.30.1-py3-none-any.whl", hash = "sha256:a9d2ed3e53964da6aa6057b46b767b335532b85fa2a0b0ed124922f06d844ae9", size = 26880 }, + { url = "https://files.pythonhosted.org/packages/5f/51/29715a2551471a9ff4e196f02955e915ccbf7477c90bb2d6e59737d94f1b/asyncpg_stubs-0.30.1-py3-none-any.whl", hash = "sha256:a9d2ed3e53964da6aa6057b46b767b335532b85fa2a0b0ed124922f06d844ae9", size = 26880, upload-time = "2025-03-14T19:51:54.267Z" }, ] [[package]] @@ -344,9 +344,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruff" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f9/ff/f5752f43f659ee62dd563af5bb0fe0a63111c3ff4708e9596279385f52bb/auto_pytabs-0.5.0.tar.gz", hash = "sha256:30087831c8be5b2314e663efd06c96b84c096572a060a492540f586362cc4326", size = 15362 } +sdist = { url = "https://files.pythonhosted.org/packages/f9/ff/f5752f43f659ee62dd563af5bb0fe0a63111c3ff4708e9596279385f52bb/auto_pytabs-0.5.0.tar.gz", hash = "sha256:30087831c8be5b2314e663efd06c96b84c096572a060a492540f586362cc4326", size = 15362, upload-time = "2024-08-18T13:02:28.437Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/df/e76dc1261882283f7ae93ebbf75438e85d8bb713a51dbbd5d17fef29e607/auto_pytabs-0.5.0-py3-none-any.whl", hash = "sha256:e59fb6d2f8b41b05d0906a322dd4bb1a86749d429483ec10036587de3657dcc8", size = 13748 }, + { url = "https://files.pythonhosted.org/packages/6e/df/e76dc1261882283f7ae93ebbf75438e85d8bb713a51dbbd5d17fef29e607/auto_pytabs-0.5.0-py3-none-any.whl", hash = "sha256:e59fb6d2f8b41b05d0906a322dd4bb1a86749d429483ec10036587de3657dcc8", size = 13748, upload-time = "2024-08-18T13:02:26.907Z" }, ] [package.optional-dependencies] @@ -365,18 +365,18 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/03/96/92afe8a7912b327c01f0a8b6408c9556ee13b1aba5b98d587ac7327ff32d/autodocsumm-0.2.14.tar.gz", hash = "sha256:2839a9d4facc3c4eccd306c08695540911042b46eeafcdc3203e6d0bab40bc77", size = 46357 } +sdist = { url = "https://files.pythonhosted.org/packages/03/96/92afe8a7912b327c01f0a8b6408c9556ee13b1aba5b98d587ac7327ff32d/autodocsumm-0.2.14.tar.gz", hash = "sha256:2839a9d4facc3c4eccd306c08695540911042b46eeafcdc3203e6d0bab40bc77", size = 46357, upload-time = "2024-10-23T18:51:47.369Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/bc/3f66af9beb683728e06ca08797e4e9d3e44f432f339718cae3ba856a9cad/autodocsumm-0.2.14-py3-none-any.whl", hash = "sha256:3bad8717fc5190802c60392a7ab04b9f3c97aa9efa8b3780b3d81d615bfe5dc0", size = 14640 }, + { url = "https://files.pythonhosted.org/packages/87/bc/3f66af9beb683728e06ca08797e4e9d3e44f432f339718cae3ba856a9cad/autodocsumm-0.2.14-py3-none-any.whl", hash = "sha256:3bad8717fc5190802c60392a7ab04b9f3c97aa9efa8b3780b3d81d615bfe5dc0", size = 14640, upload-time = "2024-10-23T18:51:45.115Z" }, ] [[package]] name = "babel" version = "2.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852 } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537 }, + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, ] [[package]] @@ -387,27 +387,27 @@ dependencies = [ { name = "soupsieve" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067, upload-time = "2025-04-15T17:05:13.836Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285 }, + { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" }, ] [[package]] name = "blinker" version = "1.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460 } +sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458 }, + { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, ] [[package]] name = "bracex" version = "2.5.post1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/6c/57418c4404cd22fe6275b8301ca2b46a8cdaa8157938017a9ae0b3edf363/bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6", size = 26641 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/6c/57418c4404cd22fe6275b8301ca2b46a8cdaa8157938017a9ae0b3edf363/bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6", size = 26641, upload-time = "2024-09-28T21:41:22.017Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558 }, + { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558, upload-time = "2024-09-28T21:41:21.016Z" }, ] [[package]] @@ -425,22 +425,22 @@ dependencies = [ { name = "tomlkit" }, { name = "wcmatch" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/13/0a/544e8eb6d46baa99bf16d180b4ddb4509631fa8476e686c8e6c47681afb4/bump_my_version-1.1.2.tar.gz", hash = "sha256:0122845a78502b5a5a635ca17c1efb3e1ec05e77d72d13b2314186b9806882fb", size = 1120309 } +sdist = { url = "https://files.pythonhosted.org/packages/13/0a/544e8eb6d46baa99bf16d180b4ddb4509631fa8476e686c8e6c47681afb4/bump_my_version-1.1.2.tar.gz", hash = "sha256:0122845a78502b5a5a635ca17c1efb3e1ec05e77d72d13b2314186b9806882fb", size = 1120309, upload-time = "2025-04-12T14:21:02.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/a9/026894e86ce2838d029af1344c71fd57560d1b6e2ce6513c340cbf8e00cb/bump_my_version-1.1.2-py3-none-any.whl", hash = "sha256:71a2a8c3940c87749c4cc404b2ada2fafbeab4e478e0ef54537686905ae58e0d", size = 59495 }, + { url = "https://files.pythonhosted.org/packages/dc/a9/026894e86ce2838d029af1344c71fd57560d1b6e2ce6513c340cbf8e00cb/bump_my_version-1.1.2-py3-none-any.whl", hash = "sha256:71a2a8c3940c87749c4cc404b2ada2fafbeab4e478e0ef54537686905ae58e0d", size = 59495, upload-time = "2025-04-12T14:21:00.872Z" }, ] [[package]] name = "cachecontrol" -version = "0.14.2" +version = "0.14.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "msgpack" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b7/a4/3390ac4dfa1773f661c8780368018230e8207ec4fd3800d2c0c3adee4456/cachecontrol-0.14.2.tar.gz", hash = "sha256:7d47d19f866409b98ff6025b6a0fca8e4c791fb31abbd95f622093894ce903a2", size = 28832 } +sdist = { url = "https://files.pythonhosted.org/packages/58/3a/0cbeb04ea57d2493f3ec5a069a117ab467f85e4a10017c6d854ddcbff104/cachecontrol-0.14.3.tar.gz", hash = "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11", size = 28985, upload-time = "2025-04-30T16:45:06.135Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/63/baffb44ca6876e7b5fc8fe17b24a7c07bf479d604a592182db9af26ea366/cachecontrol-0.14.2-py3-none-any.whl", hash = "sha256:ebad2091bf12d0d200dfc2464330db638c5deb41d546f6d7aca079e87290f3b0", size = 21780 }, + { url = "https://files.pythonhosted.org/packages/81/4c/800b0607b00b3fd20f1087f80ab53d6b4d005515b0f773e4831e37cfa83f/cachecontrol-0.14.3-py3-none-any.whl", hash = "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae", size = 21802, upload-time = "2025-04-30T16:45:03.863Z" }, ] [package.optional-dependencies] @@ -452,18 +452,18 @@ filecache = [ name = "cachetools" version = "5.5.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6c/81/3747dad6b14fa2cf53fcf10548cf5aea6913e96fab41a3c198676f8948a5/cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", size = 28380 } +sdist = { url = "https://files.pythonhosted.org/packages/6c/81/3747dad6b14fa2cf53fcf10548cf5aea6913e96fab41a3c198676f8948a5/cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", size = 28380, upload-time = "2025-02-20T21:01:19.524Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a", size = 10080 }, + { url = "https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a", size = 10080, upload-time = "2025-02-20T21:01:16.647Z" }, ] [[package]] name = "certifi" -version = "2025.1.31" +version = "2025.4.26" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, ] [[package]] @@ -473,149 +473,149 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191 }, - { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592 }, - { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024 }, - { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188 }, - { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571 }, - { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687 }, - { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211 }, - { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325 }, - { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784 }, - { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564 }, - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 }, - { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, - { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, - { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, - { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, - { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, - { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, - { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, - { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, - { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, - { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, - { url = "https://files.pythonhosted.org/packages/b9/ea/8bb50596b8ffbc49ddd7a1ad305035daa770202a6b782fc164647c2673ad/cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", size = 182220 }, - { url = "https://files.pythonhosted.org/packages/ae/11/e77c8cd24f58285a82c23af484cf5b124a376b32644e445960d1a4654c3a/cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", size = 178605 }, - { url = "https://files.pythonhosted.org/packages/ed/65/25a8dc32c53bf5b7b6c2686b42ae2ad58743f7ff644844af7cdb29b49361/cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", size = 424910 }, - { url = "https://files.pythonhosted.org/packages/42/7a/9d086fab7c66bd7c4d0f27c57a1b6b068ced810afc498cc8c49e0088661c/cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", size = 447200 }, - { url = "https://files.pythonhosted.org/packages/da/63/1785ced118ce92a993b0ec9e0d0ac8dc3e5dbfbcaa81135be56c69cabbb6/cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", size = 454565 }, - { url = "https://files.pythonhosted.org/packages/74/06/90b8a44abf3556599cdec107f7290277ae8901a58f75e6fe8f970cd72418/cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", size = 435635 }, - { url = "https://files.pythonhosted.org/packages/bd/62/a1f468e5708a70b1d86ead5bab5520861d9c7eacce4a885ded9faa7729c3/cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", size = 445218 }, - { url = "https://files.pythonhosted.org/packages/5b/95/b34462f3ccb09c2594aa782d90a90b045de4ff1f70148ee79c69d37a0a5a/cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", size = 460486 }, - { url = "https://files.pythonhosted.org/packages/fc/fc/a1e4bebd8d680febd29cf6c8a40067182b64f00c7d105f8f26b5bc54317b/cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", size = 437911 }, - { url = "https://files.pythonhosted.org/packages/e6/c3/21cab7a6154b6a5ea330ae80de386e7665254835b9e98ecc1340b3a7de9a/cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", size = 460632 }, - { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820 }, - { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290 }, +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload-time = "2024-09-04T20:43:30.027Z" }, + { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload-time = "2024-09-04T20:43:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload-time = "2024-09-04T20:43:34.186Z" }, + { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload-time = "2024-09-04T20:43:36.286Z" }, + { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload-time = "2024-09-04T20:43:38.586Z" }, + { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload-time = "2024-09-04T20:43:40.084Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload-time = "2024-09-04T20:43:41.526Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload-time = "2024-09-04T20:43:43.117Z" }, + { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload-time = "2024-09-04T20:43:45.256Z" }, + { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload-time = "2024-09-04T20:43:46.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ea/8bb50596b8ffbc49ddd7a1ad305035daa770202a6b782fc164647c2673ad/cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", size = 182220, upload-time = "2024-09-04T20:45:01.577Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/e77c8cd24f58285a82c23af484cf5b124a376b32644e445960d1a4654c3a/cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", size = 178605, upload-time = "2024-09-04T20:45:03.837Z" }, + { url = "https://files.pythonhosted.org/packages/ed/65/25a8dc32c53bf5b7b6c2686b42ae2ad58743f7ff644844af7cdb29b49361/cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", size = 424910, upload-time = "2024-09-04T20:45:05.315Z" }, + { url = "https://files.pythonhosted.org/packages/42/7a/9d086fab7c66bd7c4d0f27c57a1b6b068ced810afc498cc8c49e0088661c/cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", size = 447200, upload-time = "2024-09-04T20:45:06.903Z" }, + { url = "https://files.pythonhosted.org/packages/da/63/1785ced118ce92a993b0ec9e0d0ac8dc3e5dbfbcaa81135be56c69cabbb6/cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", size = 454565, upload-time = "2024-09-04T20:45:08.975Z" }, + { url = "https://files.pythonhosted.org/packages/74/06/90b8a44abf3556599cdec107f7290277ae8901a58f75e6fe8f970cd72418/cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", size = 435635, upload-time = "2024-09-04T20:45:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/bd/62/a1f468e5708a70b1d86ead5bab5520861d9c7eacce4a885ded9faa7729c3/cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", size = 445218, upload-time = "2024-09-04T20:45:12.366Z" }, + { url = "https://files.pythonhosted.org/packages/5b/95/b34462f3ccb09c2594aa782d90a90b045de4ff1f70148ee79c69d37a0a5a/cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", size = 460486, upload-time = "2024-09-04T20:45:13.935Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fc/a1e4bebd8d680febd29cf6c8a40067182b64f00c7d105f8f26b5bc54317b/cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", size = 437911, upload-time = "2024-09-04T20:45:15.696Z" }, + { url = "https://files.pythonhosted.org/packages/e6/c3/21cab7a6154b6a5ea330ae80de386e7665254835b9e98ecc1340b3a7de9a/cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", size = 460632, upload-time = "2024-09-04T20:45:17.284Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820, upload-time = "2024-09-04T20:45:18.762Z" }, + { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290, upload-time = "2024-09-04T20:45:20.226Z" }, ] [[package]] name = "cfgv" version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, ] [[package]] name = "charset-normalizer" -version = "3.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/58/5580c1716040bc89206c77d8f74418caf82ce519aae06450393ca73475d1/charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", size = 198013 }, - { url = "https://files.pythonhosted.org/packages/d0/11/00341177ae71c6f5159a08168bcb98c6e6d196d372c94511f9f6c9afe0c6/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", size = 141285 }, - { url = "https://files.pythonhosted.org/packages/01/09/11d684ea5819e5a8f5100fb0b38cf8d02b514746607934134d31233e02c8/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", size = 151449 }, - { url = "https://files.pythonhosted.org/packages/08/06/9f5a12939db324d905dc1f70591ae7d7898d030d7662f0d426e2286f68c9/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", size = 143892 }, - { url = "https://files.pythonhosted.org/packages/93/62/5e89cdfe04584cb7f4d36003ffa2936681b03ecc0754f8e969c2becb7e24/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", size = 146123 }, - { url = "https://files.pythonhosted.org/packages/a9/ac/ab729a15c516da2ab70a05f8722ecfccc3f04ed7a18e45c75bbbaa347d61/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", size = 147943 }, - { url = "https://files.pythonhosted.org/packages/03/d2/3f392f23f042615689456e9a274640c1d2e5dd1d52de36ab8f7955f8f050/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", size = 142063 }, - { url = "https://files.pythonhosted.org/packages/f2/e3/e20aae5e1039a2cd9b08d9205f52142329f887f8cf70da3650326670bddf/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", size = 150578 }, - { url = "https://files.pythonhosted.org/packages/8d/af/779ad72a4da0aed925e1139d458adc486e61076d7ecdcc09e610ea8678db/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", size = 153629 }, - { url = "https://files.pythonhosted.org/packages/c2/b6/7aa450b278e7aa92cf7732140bfd8be21f5f29d5bf334ae987c945276639/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", size = 150778 }, - { url = "https://files.pythonhosted.org/packages/39/f4/d9f4f712d0951dcbfd42920d3db81b00dd23b6ab520419626f4023334056/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", size = 146453 }, - { url = "https://files.pythonhosted.org/packages/49/2b/999d0314e4ee0cff3cb83e6bc9aeddd397eeed693edb4facb901eb8fbb69/charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", size = 95479 }, - { url = "https://files.pythonhosted.org/packages/2d/ce/3cbed41cff67e455a386fb5e5dd8906cdda2ed92fbc6297921f2e4419309/charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", size = 102790 }, - { url = "https://files.pythonhosted.org/packages/72/80/41ef5d5a7935d2d3a773e3eaebf0a9350542f2cab4eac59a7a4741fbbbbe/charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", size = 194995 }, - { url = "https://files.pythonhosted.org/packages/7a/28/0b9fefa7b8b080ec492110af6d88aa3dea91c464b17d53474b6e9ba5d2c5/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", size = 139471 }, - { url = "https://files.pythonhosted.org/packages/71/64/d24ab1a997efb06402e3fc07317e94da358e2585165930d9d59ad45fcae2/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", size = 149831 }, - { url = "https://files.pythonhosted.org/packages/37/ed/be39e5258e198655240db5e19e0b11379163ad7070962d6b0c87ed2c4d39/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", size = 142335 }, - { url = "https://files.pythonhosted.org/packages/88/83/489e9504711fa05d8dde1574996408026bdbdbd938f23be67deebb5eca92/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", size = 143862 }, - { url = "https://files.pythonhosted.org/packages/c6/c7/32da20821cf387b759ad24627a9aca289d2822de929b8a41b6241767b461/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", size = 145673 }, - { url = "https://files.pythonhosted.org/packages/68/85/f4288e96039abdd5aeb5c546fa20a37b50da71b5cf01e75e87f16cd43304/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", size = 140211 }, - { url = "https://files.pythonhosted.org/packages/28/a3/a42e70d03cbdabc18997baf4f0227c73591a08041c149e710045c281f97b/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", size = 148039 }, - { url = "https://files.pythonhosted.org/packages/85/e4/65699e8ab3014ecbe6f5c71d1a55d810fb716bbfd74f6283d5c2aa87febf/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", size = 151939 }, - { url = "https://files.pythonhosted.org/packages/b1/82/8e9fe624cc5374193de6860aba3ea8070f584c8565ee77c168ec13274bd2/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", size = 149075 }, - { url = "https://files.pythonhosted.org/packages/3d/7b/82865ba54c765560c8433f65e8acb9217cb839a9e32b42af4aa8e945870f/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", size = 144340 }, - { url = "https://files.pythonhosted.org/packages/b5/b6/9674a4b7d4d99a0d2df9b215da766ee682718f88055751e1e5e753c82db0/charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", size = 95205 }, - { url = "https://files.pythonhosted.org/packages/1e/ab/45b180e175de4402dcf7547e4fb617283bae54ce35c27930a6f35b6bef15/charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", size = 102441 }, - { url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 }, - { url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 }, - { url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 }, - { url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 }, - { url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 }, - { url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 }, - { url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 }, - { url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 }, - { url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 }, - { url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 }, - { url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 }, - { url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 }, - { url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 }, - { url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 }, - { url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 }, - { url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 }, - { url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 }, - { url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 }, - { url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 }, - { url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 }, - { url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 }, - { url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 }, - { url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 }, - { url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 }, - { url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 }, - { url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 }, - { url = "https://files.pythonhosted.org/packages/7f/c0/b913f8f02836ed9ab32ea643c6fe4d3325c3d8627cf6e78098671cafff86/charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", size = 197867 }, - { url = "https://files.pythonhosted.org/packages/0f/6c/2bee440303d705b6fb1e2ec789543edec83d32d258299b16eed28aad48e0/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", size = 141385 }, - { url = "https://files.pythonhosted.org/packages/3d/04/cb42585f07f6f9fd3219ffb6f37d5a39b4fd2db2355b23683060029c35f7/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", size = 151367 }, - { url = "https://files.pythonhosted.org/packages/54/54/2412a5b093acb17f0222de007cc129ec0e0df198b5ad2ce5699355269dfe/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", size = 143928 }, - { url = "https://files.pythonhosted.org/packages/5a/6d/e2773862b043dcf8a221342954f375392bb2ce6487bcd9f2c1b34e1d6781/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", size = 146203 }, - { url = "https://files.pythonhosted.org/packages/b9/f8/ca440ef60d8f8916022859885f231abb07ada3c347c03d63f283bec32ef5/charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", size = 148082 }, - { url = "https://files.pythonhosted.org/packages/04/d2/42fd330901aaa4b805a1097856c2edf5095e260a597f65def493f4b8c833/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", size = 142053 }, - { url = "https://files.pythonhosted.org/packages/9e/af/3a97a4fa3c53586f1910dadfc916e9c4f35eeada36de4108f5096cb7215f/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", size = 150625 }, - { url = "https://files.pythonhosted.org/packages/26/ae/23d6041322a3556e4da139663d02fb1b3c59a23ab2e2b56432bd2ad63ded/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", size = 153549 }, - { url = "https://files.pythonhosted.org/packages/94/22/b8f2081c6a77cb20d97e57e0b385b481887aa08019d2459dc2858ed64871/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", size = 150945 }, - { url = "https://files.pythonhosted.org/packages/c7/0b/c5ec5092747f801b8b093cdf5610e732b809d6cb11f4c51e35fc28d1d389/charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", size = 146595 }, - { url = "https://files.pythonhosted.org/packages/0c/5a/0b59704c38470df6768aa154cc87b1ac7c9bb687990a1559dc8765e8627e/charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", size = 95453 }, - { url = "https://files.pythonhosted.org/packages/85/2d/a9790237cb4d01a6d57afadc8573c8b73c609ade20b80f4cda30802009ee/charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", size = 102811 }, - { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818, upload-time = "2025-05-02T08:31:46.725Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649, upload-time = "2025-05-02T08:31:48.889Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045, upload-time = "2025-05-02T08:31:50.757Z" }, + { url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356, upload-time = "2025-05-02T08:31:52.634Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471, upload-time = "2025-05-02T08:31:56.207Z" }, + { url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317, upload-time = "2025-05-02T08:31:57.613Z" }, + { url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368, upload-time = "2025-05-02T08:31:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491, upload-time = "2025-05-02T08:32:01.219Z" }, + { url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695, upload-time = "2025-05-02T08:32:03.045Z" }, + { url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849, upload-time = "2025-05-02T08:32:04.651Z" }, + { url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091, upload-time = "2025-05-02T08:32:06.719Z" }, + { url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445, upload-time = "2025-05-02T08:32:08.66Z" }, + { url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782, upload-time = "2025-05-02T08:32:10.46Z" }, + { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" }, + { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" }, + { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" }, + { url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" }, + { url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" }, + { url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" }, + { url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" }, + { url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" }, + { url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" }, + { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" }, + { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" }, + { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" }, + { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" }, + { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" }, + { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" }, + { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" }, + { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" }, + { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" }, + { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, + { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, + { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, + { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, + { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, + { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, + { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, + { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, + { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, + { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, + { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, + { url = "https://files.pythonhosted.org/packages/28/f8/dfb01ff6cc9af38552c69c9027501ff5a5117c4cc18dcd27cb5259fa1888/charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", size = 201671, upload-time = "2025-05-02T08:34:12.696Z" }, + { url = "https://files.pythonhosted.org/packages/32/fb/74e26ee556a9dbfe3bd264289b67be1e6d616329403036f6507bb9f3f29c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", size = 144744, upload-time = "2025-05-02T08:34:14.665Z" }, + { url = "https://files.pythonhosted.org/packages/ad/06/8499ee5aa7addc6f6d72e068691826ff093329fe59891e83b092ae4c851c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", size = 154993, upload-time = "2025-05-02T08:34:17.134Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a2/5e4c187680728219254ef107a6949c60ee0e9a916a5dadb148c7ae82459c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", size = 147382, upload-time = "2025-05-02T08:34:19.081Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/56aca740dda674f0cc1ba1418c4d84534be51f639b5f98f538b332dc9a95/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", size = 149536, upload-time = "2025-05-02T08:34:21.073Z" }, + { url = "https://files.pythonhosted.org/packages/53/13/db2e7779f892386b589173dd689c1b1e304621c5792046edd8a978cbf9e0/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", size = 151349, upload-time = "2025-05-02T08:34:23.193Z" }, + { url = "https://files.pythonhosted.org/packages/69/35/e52ab9a276186f729bce7a0638585d2982f50402046e4b0faa5d2c3ef2da/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", size = 146365, upload-time = "2025-05-02T08:34:25.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/af7333f732fc2e7635867d56cb7c349c28c7094910c72267586947561b4b/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", size = 154499, upload-time = "2025-05-02T08:34:27.359Z" }, + { url = "https://files.pythonhosted.org/packages/7a/3d/a5b2e48acef264d71e036ff30bcc49e51bde80219bb628ba3e00cf59baac/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", size = 157735, upload-time = "2025-05-02T08:34:29.798Z" }, + { url = "https://files.pythonhosted.org/packages/85/d8/23e2c112532a29f3eef374375a8684a4f3b8e784f62b01da931186f43494/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", size = 154786, upload-time = "2025-05-02T08:34:31.858Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/93e0169f08ecc20fe82d12254a200dfaceddc1c12a4077bf454ecc597e33/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", size = 150203, upload-time = "2025-05-02T08:34:33.88Z" }, + { url = "https://files.pythonhosted.org/packages/2c/9d/9bf2b005138e7e060d7ebdec7503d0ef3240141587651f4b445bdf7286c2/charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", size = 98436, upload-time = "2025-05-02T08:34:35.907Z" }, + { url = "https://files.pythonhosted.org/packages/6d/24/5849d46cf4311bbf21b424c443b09b459f5b436b1558c04e45dbb7cc478b/charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", size = 105772, upload-time = "2025-05-02T08:34:37.935Z" }, + { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, ] [[package]] @@ -625,88 +625,88 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "coverage" version = "7.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/4f/2251e65033ed2ce1e68f00f91a0294e0f80c80ae8c3ebbe2f12828c4cd53/coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501", size = 811872 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/01/1c5e6ee4ebaaa5e079db933a9a45f61172048c7efa06648445821a201084/coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe", size = 211379 }, - { url = "https://files.pythonhosted.org/packages/e9/16/a463389f5ff916963471f7c13585e5f38c6814607306b3cb4d6b4cf13384/coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28", size = 211814 }, - { url = "https://files.pythonhosted.org/packages/b8/b1/77062b0393f54d79064dfb72d2da402657d7c569cfbc724d56ac0f9c67ed/coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3", size = 240937 }, - { url = "https://files.pythonhosted.org/packages/d7/54/c7b00a23150083c124e908c352db03bcd33375494a4beb0c6d79b35448b9/coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676", size = 238849 }, - { url = "https://files.pythonhosted.org/packages/f7/ec/a6b7cfebd34e7b49f844788fda94713035372b5200c23088e3bbafb30970/coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d", size = 239986 }, - { url = "https://files.pythonhosted.org/packages/21/8c/c965ecef8af54e6d9b11bfbba85d4f6a319399f5f724798498387f3209eb/coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a", size = 239896 }, - { url = "https://files.pythonhosted.org/packages/40/83/070550273fb4c480efa8381735969cb403fa8fd1626d74865bfaf9e4d903/coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c", size = 238613 }, - { url = "https://files.pythonhosted.org/packages/07/76/fbb2540495b01d996d38e9f8897b861afed356be01160ab4e25471f4fed1/coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f", size = 238909 }, - { url = "https://files.pythonhosted.org/packages/a3/7e/76d604db640b7d4a86e5dd730b73e96e12a8185f22b5d0799025121f4dcb/coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f", size = 213948 }, - { url = "https://files.pythonhosted.org/packages/5c/a7/f8ce4aafb4a12ab475b56c76a71a40f427740cf496c14e943ade72e25023/coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23", size = 214844 }, - { url = "https://files.pythonhosted.org/packages/2b/77/074d201adb8383addae5784cb8e2dac60bb62bfdf28b2b10f3a3af2fda47/coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27", size = 211493 }, - { url = "https://files.pythonhosted.org/packages/a9/89/7a8efe585750fe59b48d09f871f0e0c028a7b10722b2172dfe021fa2fdd4/coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea", size = 211921 }, - { url = "https://files.pythonhosted.org/packages/e9/ef/96a90c31d08a3f40c49dbe897df4f1fd51fb6583821a1a1c5ee30cc8f680/coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7", size = 244556 }, - { url = "https://files.pythonhosted.org/packages/89/97/dcd5c2ce72cee9d7b0ee8c89162c24972fb987a111b92d1a3d1d19100c61/coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040", size = 242245 }, - { url = "https://files.pythonhosted.org/packages/b2/7b/b63cbb44096141ed435843bbb251558c8e05cc835c8da31ca6ffb26d44c0/coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543", size = 244032 }, - { url = "https://files.pythonhosted.org/packages/97/e3/7fa8c2c00a1ef530c2a42fa5df25a6971391f92739d83d67a4ee6dcf7a02/coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2", size = 243679 }, - { url = "https://files.pythonhosted.org/packages/4f/b3/e0a59d8df9150c8a0c0841d55d6568f0a9195692136c44f3d21f1842c8f6/coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318", size = 241852 }, - { url = "https://files.pythonhosted.org/packages/9b/82/db347ccd57bcef150c173df2ade97976a8367a3be7160e303e43dd0c795f/coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9", size = 242389 }, - { url = "https://files.pythonhosted.org/packages/21/f6/3f7d7879ceb03923195d9ff294456241ed05815281f5254bc16ef71d6a20/coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c", size = 213997 }, - { url = "https://files.pythonhosted.org/packages/28/87/021189643e18ecf045dbe1e2071b2747901f229df302de01c998eeadf146/coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78", size = 214911 }, - { url = "https://files.pythonhosted.org/packages/aa/12/4792669473297f7973518bec373a955e267deb4339286f882439b8535b39/coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc", size = 211684 }, - { url = "https://files.pythonhosted.org/packages/be/e1/2a4ec273894000ebedd789e8f2fc3813fcaf486074f87fd1c5b2cb1c0a2b/coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6", size = 211935 }, - { url = "https://files.pythonhosted.org/packages/f8/3a/7b14f6e4372786709a361729164125f6b7caf4024ce02e596c4a69bccb89/coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d", size = 245994 }, - { url = "https://files.pythonhosted.org/packages/54/80/039cc7f1f81dcbd01ea796d36d3797e60c106077e31fd1f526b85337d6a1/coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05", size = 242885 }, - { url = "https://files.pythonhosted.org/packages/10/e0/dc8355f992b6cc2f9dcd5ef6242b62a3f73264893bc09fbb08bfcab18eb4/coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a", size = 245142 }, - { url = "https://files.pythonhosted.org/packages/43/1b/33e313b22cf50f652becb94c6e7dae25d8f02e52e44db37a82de9ac357e8/coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6", size = 244906 }, - { url = "https://files.pythonhosted.org/packages/05/08/c0a8048e942e7f918764ccc99503e2bccffba1c42568693ce6955860365e/coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47", size = 243124 }, - { url = "https://files.pythonhosted.org/packages/5b/62/ea625b30623083c2aad645c9a6288ad9fc83d570f9adb913a2abdba562dd/coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe", size = 244317 }, - { url = "https://files.pythonhosted.org/packages/62/cb/3871f13ee1130a6c8f020e2f71d9ed269e1e2124aa3374d2180ee451cee9/coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545", size = 214170 }, - { url = "https://files.pythonhosted.org/packages/88/26/69fe1193ab0bfa1eb7a7c0149a066123611baba029ebb448500abd8143f9/coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b", size = 214969 }, - { url = "https://files.pythonhosted.org/packages/f3/21/87e9b97b568e223f3438d93072479c2f36cc9b3f6b9f7094b9d50232acc0/coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd", size = 211708 }, - { url = "https://files.pythonhosted.org/packages/75/be/882d08b28a0d19c9c4c2e8a1c6ebe1f79c9c839eb46d4fca3bd3b34562b9/coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00", size = 211981 }, - { url = "https://files.pythonhosted.org/packages/7a/1d/ce99612ebd58082fbe3f8c66f6d8d5694976c76a0d474503fa70633ec77f/coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64", size = 245495 }, - { url = "https://files.pythonhosted.org/packages/dc/8d/6115abe97df98db6b2bd76aae395fcc941d039a7acd25f741312ced9a78f/coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067", size = 242538 }, - { url = "https://files.pythonhosted.org/packages/cb/74/2f8cc196643b15bc096d60e073691dadb3dca48418f08bc78dd6e899383e/coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008", size = 244561 }, - { url = "https://files.pythonhosted.org/packages/22/70/c10c77cd77970ac965734fe3419f2c98665f6e982744a9bfb0e749d298f4/coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733", size = 244633 }, - { url = "https://files.pythonhosted.org/packages/38/5a/4f7569d946a07c952688debee18c2bb9ab24f88027e3d71fd25dbc2f9dca/coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323", size = 242712 }, - { url = "https://files.pythonhosted.org/packages/bb/a1/03a43b33f50475a632a91ea8c127f7e35e53786dbe6781c25f19fd5a65f8/coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3", size = 244000 }, - { url = "https://files.pythonhosted.org/packages/6a/89/ab6c43b1788a3128e4d1b7b54214548dcad75a621f9d277b14d16a80d8a1/coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d", size = 214195 }, - { url = "https://files.pythonhosted.org/packages/12/12/6bf5f9a8b063d116bac536a7fb594fc35cb04981654cccb4bbfea5dcdfa0/coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487", size = 214998 }, - { url = "https://files.pythonhosted.org/packages/2a/e6/1e9df74ef7a1c983a9c7443dac8aac37a46f1939ae3499424622e72a6f78/coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25", size = 212541 }, - { url = "https://files.pythonhosted.org/packages/04/51/c32174edb7ee49744e2e81c4b1414ac9df3dacfcb5b5f273b7f285ad43f6/coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42", size = 212767 }, - { url = "https://files.pythonhosted.org/packages/e9/8f/f454cbdb5212f13f29d4a7983db69169f1937e869a5142bce983ded52162/coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502", size = 256997 }, - { url = "https://files.pythonhosted.org/packages/e6/74/2bf9e78b321216d6ee90a81e5c22f912fc428442c830c4077b4a071db66f/coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1", size = 252708 }, - { url = "https://files.pythonhosted.org/packages/92/4d/50d7eb1e9a6062bee6e2f92e78b0998848a972e9afad349b6cdde6fa9e32/coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4", size = 255046 }, - { url = "https://files.pythonhosted.org/packages/40/9e/71fb4e7402a07c4198ab44fc564d09d7d0ffca46a9fb7b0a7b929e7641bd/coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73", size = 256139 }, - { url = "https://files.pythonhosted.org/packages/49/1a/78d37f7a42b5beff027e807c2843185961fdae7fe23aad5a4837c93f9d25/coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a", size = 254307 }, - { url = "https://files.pythonhosted.org/packages/58/e9/8fb8e0ff6bef5e170ee19d59ca694f9001b2ec085dc99b4f65c128bb3f9a/coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883", size = 255116 }, - { url = "https://files.pythonhosted.org/packages/56/b0/d968ecdbe6fe0a863de7169bbe9e8a476868959f3af24981f6a10d2b6924/coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada", size = 214909 }, - { url = "https://files.pythonhosted.org/packages/87/e9/d6b7ef9fecf42dfb418d93544af47c940aa83056c49e6021a564aafbc91f/coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257", size = 216068 }, - { url = "https://files.pythonhosted.org/packages/60/0c/5da94be095239814bf2730a28cffbc48d6df4304e044f80d39e1ae581997/coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f", size = 211377 }, - { url = "https://files.pythonhosted.org/packages/d5/cb/b9e93ebf193a0bb89dbcd4f73d7b0e6ecb7c1b6c016671950e25f041835e/coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a", size = 211803 }, - { url = "https://files.pythonhosted.org/packages/78/1a/cdbfe9e1bb14d3afcaf6bb6e1b9ba76c72666e329cd06865bbd241efd652/coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82", size = 240561 }, - { url = "https://files.pythonhosted.org/packages/59/04/57f1223f26ac018d7ce791bfa65b0c29282de3e041c1cd3ed430cfeac5a5/coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814", size = 238488 }, - { url = "https://files.pythonhosted.org/packages/b7/b1/0f25516ae2a35e265868670384feebe64e7857d9cffeeb3887b0197e2ba2/coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c", size = 239589 }, - { url = "https://files.pythonhosted.org/packages/e0/a4/99d88baac0d1d5a46ceef2dd687aac08fffa8795e4c3e71b6f6c78e14482/coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd", size = 239366 }, - { url = "https://files.pythonhosted.org/packages/ea/9e/1db89e135feb827a868ed15f8fc857160757f9cab140ffee21342c783ceb/coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4", size = 237591 }, - { url = "https://files.pythonhosted.org/packages/1b/6d/ac4d6fdfd0e201bc82d1b08adfacb1e34b40d21a22cdd62cfaf3c1828566/coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899", size = 238572 }, - { url = "https://files.pythonhosted.org/packages/25/5e/917cbe617c230f7f1745b6a13e780a3a1cd1cf328dbcd0fd8d7ec52858cd/coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f", size = 213966 }, - { url = "https://files.pythonhosted.org/packages/bd/93/72b434fe550135869f9ea88dd36068af19afce666db576e059e75177e813/coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3", size = 214852 }, - { url = "https://files.pythonhosted.org/packages/c4/f1/1da77bb4c920aa30e82fa9b6ea065da3467977c2e5e032e38e66f1c57ffd/coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd", size = 203443 }, - { url = "https://files.pythonhosted.org/packages/59/f1/4da7717f0063a222db253e7121bd6a56f6fb1ba439dcc36659088793347c/coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7", size = 203435 }, +sdist = { url = "https://files.pythonhosted.org/packages/19/4f/2251e65033ed2ce1e68f00f91a0294e0f80c80ae8c3ebbe2f12828c4cd53/coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501", size = 811872, upload-time = "2025-03-30T20:36:45.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/01/1c5e6ee4ebaaa5e079db933a9a45f61172048c7efa06648445821a201084/coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe", size = 211379, upload-time = "2025-03-30T20:34:53.904Z" }, + { url = "https://files.pythonhosted.org/packages/e9/16/a463389f5ff916963471f7c13585e5f38c6814607306b3cb4d6b4cf13384/coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28", size = 211814, upload-time = "2025-03-30T20:34:56.959Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b1/77062b0393f54d79064dfb72d2da402657d7c569cfbc724d56ac0f9c67ed/coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3", size = 240937, upload-time = "2025-03-30T20:34:58.751Z" }, + { url = "https://files.pythonhosted.org/packages/d7/54/c7b00a23150083c124e908c352db03bcd33375494a4beb0c6d79b35448b9/coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676", size = 238849, upload-time = "2025-03-30T20:35:00.521Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ec/a6b7cfebd34e7b49f844788fda94713035372b5200c23088e3bbafb30970/coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d", size = 239986, upload-time = "2025-03-30T20:35:02.307Z" }, + { url = "https://files.pythonhosted.org/packages/21/8c/c965ecef8af54e6d9b11bfbba85d4f6a319399f5f724798498387f3209eb/coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a", size = 239896, upload-time = "2025-03-30T20:35:04.141Z" }, + { url = "https://files.pythonhosted.org/packages/40/83/070550273fb4c480efa8381735969cb403fa8fd1626d74865bfaf9e4d903/coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c", size = 238613, upload-time = "2025-03-30T20:35:05.889Z" }, + { url = "https://files.pythonhosted.org/packages/07/76/fbb2540495b01d996d38e9f8897b861afed356be01160ab4e25471f4fed1/coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f", size = 238909, upload-time = "2025-03-30T20:35:07.76Z" }, + { url = "https://files.pythonhosted.org/packages/a3/7e/76d604db640b7d4a86e5dd730b73e96e12a8185f22b5d0799025121f4dcb/coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f", size = 213948, upload-time = "2025-03-30T20:35:09.144Z" }, + { url = "https://files.pythonhosted.org/packages/5c/a7/f8ce4aafb4a12ab475b56c76a71a40f427740cf496c14e943ade72e25023/coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23", size = 214844, upload-time = "2025-03-30T20:35:10.734Z" }, + { url = "https://files.pythonhosted.org/packages/2b/77/074d201adb8383addae5784cb8e2dac60bb62bfdf28b2b10f3a3af2fda47/coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27", size = 211493, upload-time = "2025-03-30T20:35:12.286Z" }, + { url = "https://files.pythonhosted.org/packages/a9/89/7a8efe585750fe59b48d09f871f0e0c028a7b10722b2172dfe021fa2fdd4/coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea", size = 211921, upload-time = "2025-03-30T20:35:14.18Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ef/96a90c31d08a3f40c49dbe897df4f1fd51fb6583821a1a1c5ee30cc8f680/coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7", size = 244556, upload-time = "2025-03-30T20:35:15.616Z" }, + { url = "https://files.pythonhosted.org/packages/89/97/dcd5c2ce72cee9d7b0ee8c89162c24972fb987a111b92d1a3d1d19100c61/coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040", size = 242245, upload-time = "2025-03-30T20:35:18.648Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7b/b63cbb44096141ed435843bbb251558c8e05cc835c8da31ca6ffb26d44c0/coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543", size = 244032, upload-time = "2025-03-30T20:35:20.131Z" }, + { url = "https://files.pythonhosted.org/packages/97/e3/7fa8c2c00a1ef530c2a42fa5df25a6971391f92739d83d67a4ee6dcf7a02/coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2", size = 243679, upload-time = "2025-03-30T20:35:21.636Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b3/e0a59d8df9150c8a0c0841d55d6568f0a9195692136c44f3d21f1842c8f6/coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318", size = 241852, upload-time = "2025-03-30T20:35:23.525Z" }, + { url = "https://files.pythonhosted.org/packages/9b/82/db347ccd57bcef150c173df2ade97976a8367a3be7160e303e43dd0c795f/coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9", size = 242389, upload-time = "2025-03-30T20:35:25.09Z" }, + { url = "https://files.pythonhosted.org/packages/21/f6/3f7d7879ceb03923195d9ff294456241ed05815281f5254bc16ef71d6a20/coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c", size = 213997, upload-time = "2025-03-30T20:35:26.914Z" }, + { url = "https://files.pythonhosted.org/packages/28/87/021189643e18ecf045dbe1e2071b2747901f229df302de01c998eeadf146/coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78", size = 214911, upload-time = "2025-03-30T20:35:28.498Z" }, + { url = "https://files.pythonhosted.org/packages/aa/12/4792669473297f7973518bec373a955e267deb4339286f882439b8535b39/coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc", size = 211684, upload-time = "2025-03-30T20:35:29.959Z" }, + { url = "https://files.pythonhosted.org/packages/be/e1/2a4ec273894000ebedd789e8f2fc3813fcaf486074f87fd1c5b2cb1c0a2b/coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6", size = 211935, upload-time = "2025-03-30T20:35:31.912Z" }, + { url = "https://files.pythonhosted.org/packages/f8/3a/7b14f6e4372786709a361729164125f6b7caf4024ce02e596c4a69bccb89/coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d", size = 245994, upload-time = "2025-03-30T20:35:33.455Z" }, + { url = "https://files.pythonhosted.org/packages/54/80/039cc7f1f81dcbd01ea796d36d3797e60c106077e31fd1f526b85337d6a1/coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05", size = 242885, upload-time = "2025-03-30T20:35:35.354Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/dc8355f992b6cc2f9dcd5ef6242b62a3f73264893bc09fbb08bfcab18eb4/coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a", size = 245142, upload-time = "2025-03-30T20:35:37.121Z" }, + { url = "https://files.pythonhosted.org/packages/43/1b/33e313b22cf50f652becb94c6e7dae25d8f02e52e44db37a82de9ac357e8/coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6", size = 244906, upload-time = "2025-03-30T20:35:39.07Z" }, + { url = "https://files.pythonhosted.org/packages/05/08/c0a8048e942e7f918764ccc99503e2bccffba1c42568693ce6955860365e/coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47", size = 243124, upload-time = "2025-03-30T20:35:40.598Z" }, + { url = "https://files.pythonhosted.org/packages/5b/62/ea625b30623083c2aad645c9a6288ad9fc83d570f9adb913a2abdba562dd/coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe", size = 244317, upload-time = "2025-03-30T20:35:42.204Z" }, + { url = "https://files.pythonhosted.org/packages/62/cb/3871f13ee1130a6c8f020e2f71d9ed269e1e2124aa3374d2180ee451cee9/coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545", size = 214170, upload-time = "2025-03-30T20:35:44.216Z" }, + { url = "https://files.pythonhosted.org/packages/88/26/69fe1193ab0bfa1eb7a7c0149a066123611baba029ebb448500abd8143f9/coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b", size = 214969, upload-time = "2025-03-30T20:35:45.797Z" }, + { url = "https://files.pythonhosted.org/packages/f3/21/87e9b97b568e223f3438d93072479c2f36cc9b3f6b9f7094b9d50232acc0/coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd", size = 211708, upload-time = "2025-03-30T20:35:47.417Z" }, + { url = "https://files.pythonhosted.org/packages/75/be/882d08b28a0d19c9c4c2e8a1c6ebe1f79c9c839eb46d4fca3bd3b34562b9/coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00", size = 211981, upload-time = "2025-03-30T20:35:49.002Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/ce99612ebd58082fbe3f8c66f6d8d5694976c76a0d474503fa70633ec77f/coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64", size = 245495, upload-time = "2025-03-30T20:35:51.073Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8d/6115abe97df98db6b2bd76aae395fcc941d039a7acd25f741312ced9a78f/coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067", size = 242538, upload-time = "2025-03-30T20:35:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/cb/74/2f8cc196643b15bc096d60e073691dadb3dca48418f08bc78dd6e899383e/coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008", size = 244561, upload-time = "2025-03-30T20:35:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/22/70/c10c77cd77970ac965734fe3419f2c98665f6e982744a9bfb0e749d298f4/coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733", size = 244633, upload-time = "2025-03-30T20:35:56.221Z" }, + { url = "https://files.pythonhosted.org/packages/38/5a/4f7569d946a07c952688debee18c2bb9ab24f88027e3d71fd25dbc2f9dca/coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323", size = 242712, upload-time = "2025-03-30T20:35:57.801Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a1/03a43b33f50475a632a91ea8c127f7e35e53786dbe6781c25f19fd5a65f8/coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3", size = 244000, upload-time = "2025-03-30T20:35:59.378Z" }, + { url = "https://files.pythonhosted.org/packages/6a/89/ab6c43b1788a3128e4d1b7b54214548dcad75a621f9d277b14d16a80d8a1/coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d", size = 214195, upload-time = "2025-03-30T20:36:01.005Z" }, + { url = "https://files.pythonhosted.org/packages/12/12/6bf5f9a8b063d116bac536a7fb594fc35cb04981654cccb4bbfea5dcdfa0/coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487", size = 214998, upload-time = "2025-03-30T20:36:03.006Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e6/1e9df74ef7a1c983a9c7443dac8aac37a46f1939ae3499424622e72a6f78/coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25", size = 212541, upload-time = "2025-03-30T20:36:04.638Z" }, + { url = "https://files.pythonhosted.org/packages/04/51/c32174edb7ee49744e2e81c4b1414ac9df3dacfcb5b5f273b7f285ad43f6/coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42", size = 212767, upload-time = "2025-03-30T20:36:06.503Z" }, + { url = "https://files.pythonhosted.org/packages/e9/8f/f454cbdb5212f13f29d4a7983db69169f1937e869a5142bce983ded52162/coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502", size = 256997, upload-time = "2025-03-30T20:36:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e6/74/2bf9e78b321216d6ee90a81e5c22f912fc428442c830c4077b4a071db66f/coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1", size = 252708, upload-time = "2025-03-30T20:36:09.781Z" }, + { url = "https://files.pythonhosted.org/packages/92/4d/50d7eb1e9a6062bee6e2f92e78b0998848a972e9afad349b6cdde6fa9e32/coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4", size = 255046, upload-time = "2025-03-30T20:36:11.409Z" }, + { url = "https://files.pythonhosted.org/packages/40/9e/71fb4e7402a07c4198ab44fc564d09d7d0ffca46a9fb7b0a7b929e7641bd/coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73", size = 256139, upload-time = "2025-03-30T20:36:13.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/1a/78d37f7a42b5beff027e807c2843185961fdae7fe23aad5a4837c93f9d25/coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a", size = 254307, upload-time = "2025-03-30T20:36:16.074Z" }, + { url = "https://files.pythonhosted.org/packages/58/e9/8fb8e0ff6bef5e170ee19d59ca694f9001b2ec085dc99b4f65c128bb3f9a/coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883", size = 255116, upload-time = "2025-03-30T20:36:18.033Z" }, + { url = "https://files.pythonhosted.org/packages/56/b0/d968ecdbe6fe0a863de7169bbe9e8a476868959f3af24981f6a10d2b6924/coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada", size = 214909, upload-time = "2025-03-30T20:36:19.644Z" }, + { url = "https://files.pythonhosted.org/packages/87/e9/d6b7ef9fecf42dfb418d93544af47c940aa83056c49e6021a564aafbc91f/coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257", size = 216068, upload-time = "2025-03-30T20:36:21.282Z" }, + { url = "https://files.pythonhosted.org/packages/60/0c/5da94be095239814bf2730a28cffbc48d6df4304e044f80d39e1ae581997/coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f", size = 211377, upload-time = "2025-03-30T20:36:23.298Z" }, + { url = "https://files.pythonhosted.org/packages/d5/cb/b9e93ebf193a0bb89dbcd4f73d7b0e6ecb7c1b6c016671950e25f041835e/coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a", size = 211803, upload-time = "2025-03-30T20:36:25.74Z" }, + { url = "https://files.pythonhosted.org/packages/78/1a/cdbfe9e1bb14d3afcaf6bb6e1b9ba76c72666e329cd06865bbd241efd652/coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82", size = 240561, upload-time = "2025-03-30T20:36:27.548Z" }, + { url = "https://files.pythonhosted.org/packages/59/04/57f1223f26ac018d7ce791bfa65b0c29282de3e041c1cd3ed430cfeac5a5/coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814", size = 238488, upload-time = "2025-03-30T20:36:29.175Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b1/0f25516ae2a35e265868670384feebe64e7857d9cffeeb3887b0197e2ba2/coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c", size = 239589, upload-time = "2025-03-30T20:36:30.876Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a4/99d88baac0d1d5a46ceef2dd687aac08fffa8795e4c3e71b6f6c78e14482/coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd", size = 239366, upload-time = "2025-03-30T20:36:32.563Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/1db89e135feb827a868ed15f8fc857160757f9cab140ffee21342c783ceb/coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4", size = 237591, upload-time = "2025-03-30T20:36:34.721Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6d/ac4d6fdfd0e201bc82d1b08adfacb1e34b40d21a22cdd62cfaf3c1828566/coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899", size = 238572, upload-time = "2025-03-30T20:36:36.805Z" }, + { url = "https://files.pythonhosted.org/packages/25/5e/917cbe617c230f7f1745b6a13e780a3a1cd1cf328dbcd0fd8d7ec52858cd/coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f", size = 213966, upload-time = "2025-03-30T20:36:38.551Z" }, + { url = "https://files.pythonhosted.org/packages/bd/93/72b434fe550135869f9ea88dd36068af19afce666db576e059e75177e813/coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3", size = 214852, upload-time = "2025-03-30T20:36:40.209Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f1/1da77bb4c920aa30e82fa9b6ea065da3467977c2e5e032e38e66f1c57ffd/coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd", size = 203443, upload-time = "2025-03-30T20:36:41.959Z" }, + { url = "https://files.pythonhosted.org/packages/59/f1/4da7717f0063a222db253e7121bd6a56f6fb1ba439dcc36659088793347c/coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7", size = 203435, upload-time = "2025-03-30T20:36:43.61Z" }, ] [package.optional-dependencies] @@ -716,47 +716,49 @@ toml = [ [[package]] name = "cryptography" -version = "44.0.2" +version = "44.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cd/25/4ce80c78963834b8a9fd1cc1266be5ed8d1840785c0f2e1b73b8d128d505/cryptography-44.0.2.tar.gz", hash = "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0", size = 710807 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/ef/83e632cfa801b221570c5f58c0369db6fa6cef7d9ff859feab1aae1a8a0f/cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7", size = 6676361 }, - { url = "https://files.pythonhosted.org/packages/30/ec/7ea7c1e4c8fc8329506b46c6c4a52e2f20318425d48e0fe597977c71dbce/cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1", size = 3952350 }, - { url = "https://files.pythonhosted.org/packages/27/61/72e3afdb3c5ac510330feba4fc1faa0fe62e070592d6ad00c40bb69165e5/cryptography-44.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb", size = 4166572 }, - { url = "https://files.pythonhosted.org/packages/26/e4/ba680f0b35ed4a07d87f9e98f3ebccb05091f3bf6b5a478b943253b3bbd5/cryptography-44.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843", size = 3958124 }, - { url = "https://files.pythonhosted.org/packages/9c/e8/44ae3e68c8b6d1cbc59040288056df2ad7f7f03bbcaca6b503c737ab8e73/cryptography-44.0.2-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5", size = 3678122 }, - { url = "https://files.pythonhosted.org/packages/27/7b/664ea5e0d1eab511a10e480baf1c5d3e681c7d91718f60e149cec09edf01/cryptography-44.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c", size = 4191831 }, - { url = "https://files.pythonhosted.org/packages/2a/07/79554a9c40eb11345e1861f46f845fa71c9e25bf66d132e123d9feb8e7f9/cryptography-44.0.2-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a", size = 3960583 }, - { url = "https://files.pythonhosted.org/packages/bb/6d/858e356a49a4f0b591bd6789d821427de18432212e137290b6d8a817e9bf/cryptography-44.0.2-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308", size = 4191753 }, - { url = "https://files.pythonhosted.org/packages/b2/80/62df41ba4916067fa6b125aa8c14d7e9181773f0d5d0bd4dcef580d8b7c6/cryptography-44.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688", size = 4079550 }, - { url = "https://files.pythonhosted.org/packages/f3/cd/2558cc08f7b1bb40683f99ff4327f8dcfc7de3affc669e9065e14824511b/cryptography-44.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7", size = 4298367 }, - { url = "https://files.pythonhosted.org/packages/71/59/94ccc74788945bc3bd4cf355d19867e8057ff5fdbcac781b1ff95b700fb1/cryptography-44.0.2-cp37-abi3-win32.whl", hash = "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79", size = 2772843 }, - { url = "https://files.pythonhosted.org/packages/ca/2c/0d0bbaf61ba05acb32f0841853cfa33ebb7a9ab3d9ed8bb004bd39f2da6a/cryptography-44.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa", size = 3209057 }, - { url = "https://files.pythonhosted.org/packages/9e/be/7a26142e6d0f7683d8a382dd963745e65db895a79a280a30525ec92be890/cryptography-44.0.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3", size = 6677789 }, - { url = "https://files.pythonhosted.org/packages/06/88/638865be7198a84a7713950b1db7343391c6066a20e614f8fa286eb178ed/cryptography-44.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639", size = 3951919 }, - { url = "https://files.pythonhosted.org/packages/d7/fc/99fe639bcdf58561dfad1faa8a7369d1dc13f20acd78371bb97a01613585/cryptography-44.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd", size = 4167812 }, - { url = "https://files.pythonhosted.org/packages/53/7b/aafe60210ec93d5d7f552592a28192e51d3c6b6be449e7fd0a91399b5d07/cryptography-44.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181", size = 3958571 }, - { url = "https://files.pythonhosted.org/packages/16/32/051f7ce79ad5a6ef5e26a92b37f172ee2d6e1cce09931646eef8de1e9827/cryptography-44.0.2-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea", size = 3679832 }, - { url = "https://files.pythonhosted.org/packages/78/2b/999b2a1e1ba2206f2d3bca267d68f350beb2b048a41ea827e08ce7260098/cryptography-44.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699", size = 4193719 }, - { url = "https://files.pythonhosted.org/packages/72/97/430e56e39a1356e8e8f10f723211a0e256e11895ef1a135f30d7d40f2540/cryptography-44.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9", size = 3960852 }, - { url = "https://files.pythonhosted.org/packages/89/33/c1cf182c152e1d262cac56850939530c05ca6c8d149aa0dcee490b417e99/cryptography-44.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23", size = 4193906 }, - { url = "https://files.pythonhosted.org/packages/e1/99/87cf26d4f125380dc674233971069bc28d19b07f7755b29861570e513650/cryptography-44.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922", size = 4081572 }, - { url = "https://files.pythonhosted.org/packages/b3/9f/6a3e0391957cc0c5f84aef9fbdd763035f2b52e998a53f99345e3ac69312/cryptography-44.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4", size = 4298631 }, - { url = "https://files.pythonhosted.org/packages/e2/a5/5bc097adb4b6d22a24dea53c51f37e480aaec3465285c253098642696423/cryptography-44.0.2-cp39-abi3-win32.whl", hash = "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5", size = 2773792 }, - { url = "https://files.pythonhosted.org/packages/33/cf/1f7649b8b9a3543e042d3f348e398a061923ac05b507f3f4d95f11938aa9/cryptography-44.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6", size = 3210957 }, - { url = "https://files.pythonhosted.org/packages/99/10/173be140714d2ebaea8b641ff801cbcb3ef23101a2981cbf08057876f89e/cryptography-44.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb", size = 3396886 }, - { url = "https://files.pythonhosted.org/packages/2f/b4/424ea2d0fce08c24ede307cead3409ecbfc2f566725d4701b9754c0a1174/cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41", size = 3892387 }, - { url = "https://files.pythonhosted.org/packages/28/20/8eaa1a4f7c68a1cb15019dbaad59c812d4df4fac6fd5f7b0b9c5177f1edd/cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562", size = 4109922 }, - { url = "https://files.pythonhosted.org/packages/11/25/5ed9a17d532c32b3bc81cc294d21a36c772d053981c22bd678396bc4ae30/cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5", size = 3895715 }, - { url = "https://files.pythonhosted.org/packages/63/31/2aac03b19c6329b62c45ba4e091f9de0b8f687e1b0cd84f101401bece343/cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa", size = 4109876 }, - { url = "https://files.pythonhosted.org/packages/99/ec/6e560908349843718db1a782673f36852952d52a55ab14e46c42c8a7690a/cryptography-44.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d", size = 3131719 }, - { url = "https://files.pythonhosted.org/packages/d6/d7/f30e75a6aa7d0f65031886fa4a1485c2fbfe25a1896953920f6a9cfe2d3b/cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d", size = 3887513 }, - { url = "https://files.pythonhosted.org/packages/9c/b4/7a494ce1032323ca9db9a3661894c66e0d7142ad2079a4249303402d8c71/cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471", size = 4107432 }, - { url = "https://files.pythonhosted.org/packages/45/f8/6b3ec0bc56123b344a8d2b3264a325646d2dcdbdd9848b5e6f3d37db90b3/cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615", size = 3891421 }, - { url = "https://files.pythonhosted.org/packages/57/ff/f3b4b2d007c2a646b0f69440ab06224f9cf37a977a72cdb7b50632174e8a/cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390", size = 4107081 }, +sdist = { url = "https://files.pythonhosted.org/packages/53/d6/1411ab4d6108ab167d06254c5be517681f1e331f90edf1379895bcb87020/cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053", size = 711096, upload-time = "2025-05-02T19:36:04.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/53/c776d80e9d26441bb3868457909b4e74dd9ccabd182e10b2b0ae7a07e265/cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88", size = 6670281, upload-time = "2025-05-02T19:34:50.665Z" }, + { url = "https://files.pythonhosted.org/packages/6a/06/af2cf8d56ef87c77319e9086601bef621bedf40f6f59069e1b6d1ec498c5/cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137", size = 3959305, upload-time = "2025-05-02T19:34:53.042Z" }, + { url = "https://files.pythonhosted.org/packages/ae/01/80de3bec64627207d030f47bf3536889efee8913cd363e78ca9a09b13c8e/cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c", size = 4171040, upload-time = "2025-05-02T19:34:54.675Z" }, + { url = "https://files.pythonhosted.org/packages/bd/48/bb16b7541d207a19d9ae8b541c70037a05e473ddc72ccb1386524d4f023c/cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76", size = 3963411, upload-time = "2025-05-02T19:34:56.61Z" }, + { url = "https://files.pythonhosted.org/packages/42/b2/7d31f2af5591d217d71d37d044ef5412945a8a8e98d5a2a8ae4fd9cd4489/cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359", size = 3689263, upload-time = "2025-05-02T19:34:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/25/50/c0dfb9d87ae88ccc01aad8eb93e23cfbcea6a6a106a9b63a7b14c1f93c75/cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43", size = 4196198, upload-time = "2025-05-02T19:35:00.988Z" }, + { url = "https://files.pythonhosted.org/packages/66/c9/55c6b8794a74da652690c898cb43906310a3e4e4f6ee0b5f8b3b3e70c441/cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01", size = 3966502, upload-time = "2025-05-02T19:35:03.091Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f7/7cb5488c682ca59a02a32ec5f975074084db4c983f849d47b7b67cc8697a/cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d", size = 4196173, upload-time = "2025-05-02T19:35:05.018Z" }, + { url = "https://files.pythonhosted.org/packages/d2/0b/2f789a8403ae089b0b121f8f54f4a3e5228df756e2146efdf4a09a3d5083/cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904", size = 4087713, upload-time = "2025-05-02T19:35:07.187Z" }, + { url = "https://files.pythonhosted.org/packages/1d/aa/330c13655f1af398fc154089295cf259252f0ba5df93b4bc9d9c7d7f843e/cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44", size = 4299064, upload-time = "2025-05-02T19:35:08.879Z" }, + { url = "https://files.pythonhosted.org/packages/10/a8/8c540a421b44fd267a7d58a1fd5f072a552d72204a3f08194f98889de76d/cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d", size = 2773887, upload-time = "2025-05-02T19:35:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/b9/0d/c4b1657c39ead18d76bbd122da86bd95bdc4095413460d09544000a17d56/cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d", size = 3209737, upload-time = "2025-05-02T19:35:12.12Z" }, + { url = "https://files.pythonhosted.org/packages/34/a3/ad08e0bcc34ad436013458d7528e83ac29910943cea42ad7dd4141a27bbb/cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f", size = 6673501, upload-time = "2025-05-02T19:35:13.775Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f0/7491d44bba8d28b464a5bc8cc709f25a51e3eac54c0a4444cf2473a57c37/cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759", size = 3960307, upload-time = "2025-05-02T19:35:15.917Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c8/e5c5d0e1364d3346a5747cdcd7ecbb23ca87e6dea4f942a44e88be349f06/cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645", size = 4170876, upload-time = "2025-05-02T19:35:18.138Z" }, + { url = "https://files.pythonhosted.org/packages/73/96/025cb26fc351d8c7d3a1c44e20cf9a01e9f7cf740353c9c7a17072e4b264/cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2", size = 3964127, upload-time = "2025-05-02T19:35:19.864Z" }, + { url = "https://files.pythonhosted.org/packages/01/44/eb6522db7d9f84e8833ba3bf63313f8e257729cf3a8917379473fcfd6601/cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54", size = 3689164, upload-time = "2025-05-02T19:35:21.449Z" }, + { url = "https://files.pythonhosted.org/packages/68/fb/d61a4defd0d6cee20b1b8a1ea8f5e25007e26aeb413ca53835f0cae2bcd1/cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93", size = 4198081, upload-time = "2025-05-02T19:35:23.187Z" }, + { url = "https://files.pythonhosted.org/packages/1b/50/457f6911d36432a8811c3ab8bd5a6090e8d18ce655c22820994913dd06ea/cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c", size = 3967716, upload-time = "2025-05-02T19:35:25.426Z" }, + { url = "https://files.pythonhosted.org/packages/35/6e/dca39d553075980ccb631955c47b93d87d27f3596da8d48b1ae81463d915/cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f", size = 4197398, upload-time = "2025-05-02T19:35:27.678Z" }, + { url = "https://files.pythonhosted.org/packages/9b/9d/d1f2fe681eabc682067c66a74addd46c887ebacf39038ba01f8860338d3d/cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5", size = 4087900, upload-time = "2025-05-02T19:35:29.312Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f5/3599e48c5464580b73b236aafb20973b953cd2e7b44c7c2533de1d888446/cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b", size = 4301067, upload-time = "2025-05-02T19:35:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/a7/6c/d2c48c8137eb39d0c193274db5c04a75dab20d2f7c3f81a7dcc3a8897701/cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028", size = 2775467, upload-time = "2025-05-02T19:35:33.805Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ad/51f212198681ea7b0deaaf8846ee10af99fba4e894f67b353524eab2bbe5/cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334", size = 3210375, upload-time = "2025-05-02T19:35:35.369Z" }, + { url = "https://files.pythonhosted.org/packages/7f/10/abcf7418536df1eaba70e2cfc5c8a0ab07aa7aa02a5cbc6a78b9d8b4f121/cryptography-44.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:cad399780053fb383dc067475135e41c9fe7d901a97dd5d9c5dfb5611afc0d7d", size = 3393192, upload-time = "2025-05-02T19:35:37.468Z" }, + { url = "https://files.pythonhosted.org/packages/06/59/ecb3ef380f5891978f92a7f9120e2852b1df6f0a849c277b8ea45b865db2/cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:21a83f6f35b9cc656d71b5de8d519f566df01e660ac2578805ab245ffd8523f8", size = 3898419, upload-time = "2025-05-02T19:35:39.065Z" }, + { url = "https://files.pythonhosted.org/packages/bb/d0/35e2313dbb38cf793aa242182ad5bc5ef5c8fd4e5dbdc380b936c7d51169/cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fc3c9babc1e1faefd62704bb46a69f359a9819eb0292e40df3fb6e3574715cd4", size = 4117892, upload-time = "2025-05-02T19:35:40.839Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c8/31fb6e33b56c2c2100d76de3fd820afaa9d4d0b6aea1ccaf9aaf35dc7ce3/cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:e909df4053064a97f1e6565153ff8bb389af12c5c8d29c343308760890560aff", size = 3900855, upload-time = "2025-05-02T19:35:42.599Z" }, + { url = "https://files.pythonhosted.org/packages/43/2a/08cc2ec19e77f2a3cfa2337b429676406d4bb78ddd130a05c458e7b91d73/cryptography-44.0.3-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:dad80b45c22e05b259e33ddd458e9e2ba099c86ccf4e88db7bbab4b747b18d06", size = 4117619, upload-time = "2025-05-02T19:35:44.774Z" }, + { url = "https://files.pythonhosted.org/packages/02/68/fc3d3f84022a75f2ac4b1a1c0e5d6a0c2ea259e14cd4aae3e0e68e56483c/cryptography-44.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:479d92908277bed6e1a1c69b277734a7771c2b78633c224445b5c60a9f4bc1d9", size = 3136570, upload-time = "2025-05-02T19:35:46.94Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4b/c11ad0b6c061902de5223892d680e89c06c7c4d606305eb8de56c5427ae6/cryptography-44.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:896530bc9107b226f265effa7ef3f21270f18a2026bc09fed1ebd7b66ddf6375", size = 3390230, upload-time = "2025-05-02T19:35:49.062Z" }, + { url = "https://files.pythonhosted.org/packages/58/11/0a6bf45d53b9b2290ea3cec30e78b78e6ca29dc101e2e296872a0ffe1335/cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9b4d4a5dbee05a2c390bf212e78b99434efec37b17a4bff42f50285c5c8c9647", size = 3895216, upload-time = "2025-05-02T19:35:51.351Z" }, + { url = "https://files.pythonhosted.org/packages/0a/27/b28cdeb7270e957f0077a2c2bfad1b38f72f1f6d699679f97b816ca33642/cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02f55fb4f8b79c1221b0961488eaae21015b69b210e18c386b69de182ebb1259", size = 4115044, upload-time = "2025-05-02T19:35:53.044Z" }, + { url = "https://files.pythonhosted.org/packages/35/b0/ec4082d3793f03cb248881fecefc26015813199b88f33e3e990a43f79835/cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:dd3db61b8fe5be220eee484a17233287d0be6932d056cf5738225b9c05ef4fff", size = 3898034, upload-time = "2025-05-02T19:35:54.72Z" }, + { url = "https://files.pythonhosted.org/packages/0b/7f/adf62e0b8e8d04d50c9a91282a57628c00c54d4ae75e2b02a223bd1f2613/cryptography-44.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:978631ec51a6bbc0b7e58f23b68a8ce9e5f09721940933e9c217068388789fe5", size = 4114449, upload-time = "2025-05-02T19:35:57.139Z" }, + { url = "https://files.pythonhosted.org/packages/87/62/d69eb4a8ee231f4bf733a92caf9da13f1c81a44e874b1d4080c25ecbb723/cryptography-44.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:5d20cc348cca3a8aa7312f42ab953a56e15323800ca3ab0706b8cd452a3a056c", size = 3134369, upload-time = "2025-05-02T19:35:58.907Z" }, ] [[package]] @@ -766,9 +768,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "more-itertools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/33/9f/329d26121fe165be44b1dfff21aa0dc348f04633931f1d20ed6cf448a236/cssutils-2.11.1.tar.gz", hash = "sha256:0563a76513b6af6eebbe788c3bf3d01c920e46b3f90c8416738c5cfc773ff8e2", size = 711657 } +sdist = { url = "https://files.pythonhosted.org/packages/33/9f/329d26121fe165be44b1dfff21aa0dc348f04633931f1d20ed6cf448a236/cssutils-2.11.1.tar.gz", hash = "sha256:0563a76513b6af6eebbe788c3bf3d01c920e46b3f90c8416738c5cfc773ff8e2", size = 711657, upload-time = "2024-06-04T15:51:39.373Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/ec/bb273b7208c606890dc36540fe667d06ce840a6f62f9fae7e658fcdc90fb/cssutils-2.11.1-py3-none-any.whl", hash = "sha256:a67bfdfdff4f3867fab43698ec4897c1a828eca5973f4073321b3bccaf1199b1", size = 385747 }, + { url = "https://files.pythonhosted.org/packages/a7/ec/bb273b7208c606890dc36540fe667d06ce840a6f62f9fae7e658fcdc90fb/cssutils-2.11.1-py3-none-any.whl", hash = "sha256:a67bfdfdff4f3867fab43698ec4897c1a828eca5973f4073321b3bccaf1199b1", size = 385747, upload-time = "2024-06-04T15:51:37.499Z" }, ] [[package]] @@ -779,18 +781,18 @@ dependencies = [ { name = "cssutils" }, { name = "domdf-python-tools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/24/eb/776eef1f1aa0188c0fc165c3a60b71027539f71f2eedc43ad21b060e9c39/dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719", size = 7845 } +sdist = { url = "https://files.pythonhosted.org/packages/24/eb/776eef1f1aa0188c0fc165c3a60b71027539f71f2eedc43ad21b060e9c39/dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719", size = 7845, upload-time = "2023-11-22T11:09:20.958Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/47/290daabcf91628f4fc0e17c75a1690b354ba067066cd14407712600e609f/dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d", size = 25647 }, + { url = "https://files.pythonhosted.org/packages/fe/47/290daabcf91628f4fc0e17c75a1690b354ba067066cd14407712600e609f/dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d", size = 25647, upload-time = "2023-11-22T11:09:19.221Z" }, ] [[package]] name = "distlib" version = "0.3.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 } +sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, + { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" }, ] [[package]] @@ -802,18 +804,18 @@ dependencies = [ { name = "requests" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834 } +sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774 }, + { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, ] [[package]] name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] [[package]] @@ -824,84 +826,84 @@ dependencies = [ { name = "natsort" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/8b/ab2d8a292bba8fe3135cacc8bfd3576710a14b8f2d0a8cde19130d5c9d21/domdf_python_tools-3.10.0.tar.gz", hash = "sha256:2ae308d2f4f1e9145f5f4ba57f840fbfd1c2983ee26e4824347789649d3ae298", size = 100458 } +sdist = { url = "https://files.pythonhosted.org/packages/36/8b/ab2d8a292bba8fe3135cacc8bfd3576710a14b8f2d0a8cde19130d5c9d21/domdf_python_tools-3.10.0.tar.gz", hash = "sha256:2ae308d2f4f1e9145f5f4ba57f840fbfd1c2983ee26e4824347789649d3ae298", size = 100458, upload-time = "2025-02-12T17:34:05.747Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5b/11/208f72084084d3f6a2ed5ebfdfc846692c3f7ad6dce65e400194924f7eed/domdf_python_tools-3.10.0-py3-none-any.whl", hash = "sha256:5e71c1be71bbcc1f881d690c8984b60e64298ec256903b3147f068bc33090c36", size = 126860 }, + { url = "https://files.pythonhosted.org/packages/5b/11/208f72084084d3f6a2ed5ebfdfc846692c3f7ad6dce65e400194924f7eed/domdf_python_tools-3.10.0-py3-none-any.whl", hash = "sha256:5e71c1be71bbcc1f881d690c8984b60e64298ec256903b3147f068bc33090c36", size = 126860, upload-time = "2025-02-12T17:34:04.093Z" }, ] [[package]] name = "duckdb" version = "1.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/28/b8/0f86278684fb7a1fac7c0c869fc6d68ed005cdc91c963eb4373e0551bc0a/duckdb-1.2.2.tar.gz", hash = "sha256:1e53555dece49201df08645dbfa4510c86440339889667702f936b7d28d39e43", size = 11595514 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/47/d17eecc8bf23519f4385a7ad361482e5791f6b94995a50839f130c469626/duckdb-1.2.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6e5e6c333b550903ff11919ed1154c60c9b9d935db51afdb263babe523a8a69e", size = 15255351 }, - { url = "https://files.pythonhosted.org/packages/bd/d1/317397198e0481339c469441762ce4e563f612479c2be70ddba3c1493bf2/duckdb-1.2.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:c1fcbc579de8e4fa7e34242fd6f419c1a39520073b1fe0c29ed6e60ed5553f38", size = 31925074 }, - { url = "https://files.pythonhosted.org/packages/3d/e2/9f8cfa9d8a8d1370ae2b5cf0c6a34e6adc51be533771fd75b5ff84fb2441/duckdb-1.2.2-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:690885060c4140922ffa2f6935291c6e74ddad0ca2cf33bff66474ce89312ab3", size = 16779904 }, - { url = "https://files.pythonhosted.org/packages/e6/47/3651b1ab62b6e8ce15a1ead5d81d4bc76b09912c2ae0b11aa0bbcbd0209d/duckdb-1.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a382782980643f5ee827990b76f079b22f47786509061c0afac28afaa5b8bf5", size = 18726556 }, - { url = "https://files.pythonhosted.org/packages/6d/66/6b2a433d042a3a5109c1a62a4daaea40b908e7876756aed2837adaf0ca26/duckdb-1.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c33345570ed8c50c9fe340c2767470115cc02d330f25384104cfad1f6e54f5", size = 20195269 }, - { url = "https://files.pythonhosted.org/packages/a3/38/1737151fba968c0e7221b68d11c80ed9ff63edf380d91058426b51f1b233/duckdb-1.2.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b744f8293ce649d802a9eabbf88e4930d672cf9de7d4fc9af5d14ceaeeec5805", size = 18737528 }, - { url = "https://files.pythonhosted.org/packages/b3/37/bfde2ea14353a297e7effe9e4688b4e60a3ec08a9bd67c404c64046e5d9e/duckdb-1.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c8680e81b0c77be9fc968c1dd4cd38395c34b18bb693cbfc7b7742c18221cc9b", size = 22254571 }, - { url = "https://files.pythonhosted.org/packages/f0/42/392736bfd62b5b5f0d9ea15b010c90a8c92c21fdfc4372e46160f3d8f680/duckdb-1.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:fb41f2035a70378b3021f724bb08b047ca4aa475850a3744c442570054af3c52", size = 11366201 }, - { url = "https://files.pythonhosted.org/packages/c1/41/78c63937a4f7a5de7d128203c567303d4813c1109b7d17e6b3959f0882e1/duckdb-1.2.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:081110ffbc9d53c9740ef55482c93b97db2f8030d681d1658827d2e94f77da03", size = 15258298 }, - { url = "https://files.pythonhosted.org/packages/94/b2/91d983ecd67a1b87343e98395ffe7d77c996e1798c1bab339beed4680693/duckdb-1.2.2-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:53a154dbc074604036a537784ce5d1468edf263745a4363ca06fdb922f0d0a99", size = 31933969 }, - { url = "https://files.pythonhosted.org/packages/ad/12/4737b682cbc1b4778ffb37e4f4cdb603676c50aec89d6c9781ec29d3e904/duckdb-1.2.2-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0353f80882c066f7b14451852395b7a360f3d4846a10555c4268eb49144ea11c", size = 16784775 }, - { url = "https://files.pythonhosted.org/packages/71/be/dfb52b579a0b82aa92993aecc100bd951d0bd1850c6a8d47c68953a9de62/duckdb-1.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b134a5002757af1ae44a9ae26c2fe963ffa09eb47a62779ce0c5eeb44bfc2f28", size = 18731124 }, - { url = "https://files.pythonhosted.org/packages/ca/49/153dd6289a3d06e87c3199a5547ccc04c574d167d7f85c1a8196218bf040/duckdb-1.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd9c434127fd1575694e1cf19a393bed301f5d6e80b4bcdae80caa368a61a678", size = 20199712 }, - { url = "https://files.pythonhosted.org/packages/97/ce/f27a7b735a8abb04e2c1efcc05178e25e455539c74d70f76c2845bae8473/duckdb-1.2.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:890f58855d127c25bc3a53f4c24b27e79391c4468c4fcc99bc10d87b5d4bd1c4", size = 18739966 }, - { url = "https://files.pythonhosted.org/packages/d8/f2/a8066267eb5fcd1f535776efde29b6d0fa678d978a7de73f47bc59cc940d/duckdb-1.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a5002305cdd4e76c94b61b50abc5e3f4e32c9cb81116960bb4b74acbbc9c6c8", size = 22255946 }, - { url = "https://files.pythonhosted.org/packages/df/74/8a05ef00c554882d8300c2c261e8f7e7ead74e2b3ff66059599ff2646cf4/duckdb-1.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:cdb9999c6a109aa31196cdd22fc58a810a3d35d08181a25d1bf963988e89f0a5", size = 11368173 }, - { url = "https://files.pythonhosted.org/packages/77/25/549f68e55e1b455bd2daf2e5fc912000a3139fe0395111b3d49b23a2cec1/duckdb-1.2.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f745379f44ad302560688855baaed9739c03b37a331338eda6a4ac655e4eb42f", size = 15271882 }, - { url = "https://files.pythonhosted.org/packages/f6/84/13de7bf9056dcc7a346125d9a9f0f26f76c633db6b54052738f78f828538/duckdb-1.2.2-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:087713fc5958cae5eb59097856b3deaae0def021660c8f2052ec83fa8345174a", size = 31964873 }, - { url = "https://files.pythonhosted.org/packages/0f/53/c8d2d56a801b7843ea87f8533a3634e6b38f06910098a266f8a096bd4c61/duckdb-1.2.2-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:a1f96395319c447a31b9477881bd84b4cb8323d6f86f21ceaef355d22dd90623", size = 16800653 }, - { url = "https://files.pythonhosted.org/packages/bb/36/e25791d879fb93b92a56bf481ce11949ab19109103ae2ba12d64e49355d9/duckdb-1.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6aba3bc0acf4f8d52b94f7746c3b0007b78b517676d482dc516d63f48f967baf", size = 18735524 }, - { url = "https://files.pythonhosted.org/packages/d7/46/4745aa10a1e460f4c8b473eddaffe2c783ac5280e1e5929dd84bd1a1acde/duckdb-1.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5c1556775a9ebaa49b5c8d64718f155ac3e05b34a49e9c99443cf105e8b0371", size = 20210314 }, - { url = "https://files.pythonhosted.org/packages/ff/0d/8563fc5ece36252e3d07dd3d29c7a0a034dcf62f14bed7cdc016d95adcbe/duckdb-1.2.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d625cc7d2faacfb2fc83ebbe001ae75dda175b3d8dce6a51a71c199ffac3627a", size = 18755134 }, - { url = "https://files.pythonhosted.org/packages/11/f1/b7ade7d980eee4fb3ad7469ccf23adb3668a9a28cf3989b24418392d3786/duckdb-1.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:73263f81545c5cb4360fbaf7b22a493e55ddf88fadbe639c43efb7bc8d7554c4", size = 22294397 }, - { url = "https://files.pythonhosted.org/packages/eb/c9/896e8ced7b408df81e015fe0c6497cda46c92d9dfc8bf84b6d13f5dad473/duckdb-1.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:b1c0c4d737fd2ab9681e4e78b9f361e0a827916a730e84fa91e76dca451b14d5", size = 11370381 }, - { url = "https://files.pythonhosted.org/packages/41/31/5e2f68cbd000137f6ed52092ad83a8e9c09eca70c59e0b4c5eb679709997/duckdb-1.2.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:fb9a2c77236fae079185a990434cb9d8432902488ba990235c702fc2692d2dcd", size = 15272507 }, - { url = "https://files.pythonhosted.org/packages/d2/15/aa9078fc897e744e077c0c1510e34db4c809de1d51ddb5cb62e1f9c61312/duckdb-1.2.2-cp313-cp313-macosx_12_0_universal2.whl", hash = "sha256:d8bb89e580cb9a3aaf42e4555bf265d3db9446abfb118e32150e1a5dfa4b5b15", size = 31965548 }, - { url = "https://files.pythonhosted.org/packages/9f/28/943773d44fd97055c59b58dde9182733661c2b6e3b3549f15dc26b2e139e/duckdb-1.2.2-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:88916d7f0532dc926bed84b50408c00dcbe6d2097d0de93c3ff647d8d57b4f83", size = 16800600 }, - { url = "https://files.pythonhosted.org/packages/39/51/2caf01e7791e490290798c8c155d4d702ed61d69e815915b42e72b3e7473/duckdb-1.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30bece4f58a6c7bb0944a02dd1dc6de435a9daf8668fa31a9fe3a9923b20bd65", size = 18735886 }, - { url = "https://files.pythonhosted.org/packages/87/0c/48ae1d485725af3a452303af409a9022d751ecab260cb9ca2f8c9fb670bc/duckdb-1.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bd2c6373b8b54474724c2119f6939c4568c428e1d0be5bcb1f4e3d7f1b7c8bb", size = 20210481 }, - { url = "https://files.pythonhosted.org/packages/69/c7/95fcd7bde0f754ea6700208d36b845379cbd2b28779c0eff4dd4a7396369/duckdb-1.2.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72f688a8b0df7030c5a28ca6072817c1f090979e08d28ee5912dee37c26a7d0c", size = 18756619 }, - { url = "https://files.pythonhosted.org/packages/ad/1b/c9eab9e84d4a70dd5f7e2a93dd6e9d7b4d868d3df755cd58b572d82d6c5d/duckdb-1.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26e9c349f56f7c99341b5c79bbaff5ba12a5414af0261e79bf1a6a2693f152f6", size = 22294667 }, - { url = "https://files.pythonhosted.org/packages/3f/3d/ce68db53084746a4a62695a4cb064e44ce04123f8582bb3afbf6ee944e16/duckdb-1.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1aec7102670e59d83512cf47d32a6c77a79df9df0294c5e4d16b6259851e2e9", size = 11370206 }, - { url = "https://files.pythonhosted.org/packages/a9/a8/9d75eeab4ff76a4e9dae52298cd0c582f513300f3fc34db9520a6db6c4b1/duckdb-1.2.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:25ac669180f88fecca20f300b898e191f81aa674d51dde8a328bdeb28a572ab0", size = 15255341 }, - { url = "https://files.pythonhosted.org/packages/67/52/745839eb1299be96379b52b6cc3783ee330e91ec8d325b157611b9a2d49c/duckdb-1.2.2-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:d42e7e545d1059e6b73d0f0baa9ae34c90684bfd8c862e70b0d8ab92e01e0e3f", size = 31923916 }, - { url = "https://files.pythonhosted.org/packages/0c/6b/0e1da90808ec4f60215c2a2873c5ae5a248337ccccc77c2b5fb71918f7eb/duckdb-1.2.2-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:f3ce127bcecc723f1c7bddbc57f0526d11128cb05bfd81ffcd5e69e2dd5a1624", size = 16778052 }, - { url = "https://files.pythonhosted.org/packages/60/13/04974fdd6106492d6ebbd411c51fca949f73d1a08b5281f9b41c622b0386/duckdb-1.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2418937adb9d6d0ca823bd385b914495294db27bc2963749d54af6708757f679", size = 18727076 }, - { url = "https://files.pythonhosted.org/packages/be/cf/f875823e9eae416928b7e583b2174e826e67c120297880f1dde3a726accc/duckdb-1.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d41f899ce7979e7b3f9097ebce70da5c659db2d81d08c07a72b2b50f869859", size = 20196346 }, - { url = "https://files.pythonhosted.org/packages/b1/3e/b483c5ad2223392474f4d74d42e522b7545a95154c673f81eea4252d7192/duckdb-1.2.2-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:85e90a9c5307cf4d9151844e60c80f492618ea6e9b71081020e7d462e071ac8f", size = 18724393 }, - { url = "https://files.pythonhosted.org/packages/a6/99/349475c08be5abe686d647ca4585287bd01c01b16121f329e05e664630f4/duckdb-1.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:df8c8a4ec998139b8507213c44c50e24f62a36af1cfded87e8972173dc9f8baf", size = 22237700 }, - { url = "https://files.pythonhosted.org/packages/8e/1a/1a9da0336c146750ba1dc9a5ad1ab8c228da4512991e1d5b8f0e07076bd5/duckdb-1.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:6507ad2445cd3479853fb6473164b5eb5b22446d283c9892cfbbd0a85c5f361d", size = 11400288 }, +sdist = { url = "https://files.pythonhosted.org/packages/28/b8/0f86278684fb7a1fac7c0c869fc6d68ed005cdc91c963eb4373e0551bc0a/duckdb-1.2.2.tar.gz", hash = "sha256:1e53555dece49201df08645dbfa4510c86440339889667702f936b7d28d39e43", size = 11595514, upload-time = "2025-04-08T08:47:20.234Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/47/d17eecc8bf23519f4385a7ad361482e5791f6b94995a50839f130c469626/duckdb-1.2.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6e5e6c333b550903ff11919ed1154c60c9b9d935db51afdb263babe523a8a69e", size = 15255351, upload-time = "2025-04-08T08:45:14.845Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d1/317397198e0481339c469441762ce4e563f612479c2be70ddba3c1493bf2/duckdb-1.2.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:c1fcbc579de8e4fa7e34242fd6f419c1a39520073b1fe0c29ed6e60ed5553f38", size = 31925074, upload-time = "2025-04-08T08:45:17.649Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e2/9f8cfa9d8a8d1370ae2b5cf0c6a34e6adc51be533771fd75b5ff84fb2441/duckdb-1.2.2-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:690885060c4140922ffa2f6935291c6e74ddad0ca2cf33bff66474ce89312ab3", size = 16779904, upload-time = "2025-04-08T08:45:21.97Z" }, + { url = "https://files.pythonhosted.org/packages/e6/47/3651b1ab62b6e8ce15a1ead5d81d4bc76b09912c2ae0b11aa0bbcbd0209d/duckdb-1.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a382782980643f5ee827990b76f079b22f47786509061c0afac28afaa5b8bf5", size = 18726556, upload-time = "2025-04-08T08:45:24.353Z" }, + { url = "https://files.pythonhosted.org/packages/6d/66/6b2a433d042a3a5109c1a62a4daaea40b908e7876756aed2837adaf0ca26/duckdb-1.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c33345570ed8c50c9fe340c2767470115cc02d330f25384104cfad1f6e54f5", size = 20195269, upload-time = "2025-04-08T08:45:26.969Z" }, + { url = "https://files.pythonhosted.org/packages/a3/38/1737151fba968c0e7221b68d11c80ed9ff63edf380d91058426b51f1b233/duckdb-1.2.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b744f8293ce649d802a9eabbf88e4930d672cf9de7d4fc9af5d14ceaeeec5805", size = 18737528, upload-time = "2025-04-08T08:45:29.097Z" }, + { url = "https://files.pythonhosted.org/packages/b3/37/bfde2ea14353a297e7effe9e4688b4e60a3ec08a9bd67c404c64046e5d9e/duckdb-1.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c8680e81b0c77be9fc968c1dd4cd38395c34b18bb693cbfc7b7742c18221cc9b", size = 22254571, upload-time = "2025-04-08T08:45:32.369Z" }, + { url = "https://files.pythonhosted.org/packages/f0/42/392736bfd62b5b5f0d9ea15b010c90a8c92c21fdfc4372e46160f3d8f680/duckdb-1.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:fb41f2035a70378b3021f724bb08b047ca4aa475850a3744c442570054af3c52", size = 11366201, upload-time = "2025-04-08T08:45:34.817Z" }, + { url = "https://files.pythonhosted.org/packages/c1/41/78c63937a4f7a5de7d128203c567303d4813c1109b7d17e6b3959f0882e1/duckdb-1.2.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:081110ffbc9d53c9740ef55482c93b97db2f8030d681d1658827d2e94f77da03", size = 15258298, upload-time = "2025-04-08T08:45:36.648Z" }, + { url = "https://files.pythonhosted.org/packages/94/b2/91d983ecd67a1b87343e98395ffe7d77c996e1798c1bab339beed4680693/duckdb-1.2.2-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:53a154dbc074604036a537784ce5d1468edf263745a4363ca06fdb922f0d0a99", size = 31933969, upload-time = "2025-04-08T08:45:39.356Z" }, + { url = "https://files.pythonhosted.org/packages/ad/12/4737b682cbc1b4778ffb37e4f4cdb603676c50aec89d6c9781ec29d3e904/duckdb-1.2.2-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0353f80882c066f7b14451852395b7a360f3d4846a10555c4268eb49144ea11c", size = 16784775, upload-time = "2025-04-08T08:45:42.246Z" }, + { url = "https://files.pythonhosted.org/packages/71/be/dfb52b579a0b82aa92993aecc100bd951d0bd1850c6a8d47c68953a9de62/duckdb-1.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b134a5002757af1ae44a9ae26c2fe963ffa09eb47a62779ce0c5eeb44bfc2f28", size = 18731124, upload-time = "2025-04-08T08:45:44.573Z" }, + { url = "https://files.pythonhosted.org/packages/ca/49/153dd6289a3d06e87c3199a5547ccc04c574d167d7f85c1a8196218bf040/duckdb-1.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd9c434127fd1575694e1cf19a393bed301f5d6e80b4bcdae80caa368a61a678", size = 20199712, upload-time = "2025-04-08T08:45:47.031Z" }, + { url = "https://files.pythonhosted.org/packages/97/ce/f27a7b735a8abb04e2c1efcc05178e25e455539c74d70f76c2845bae8473/duckdb-1.2.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:890f58855d127c25bc3a53f4c24b27e79391c4468c4fcc99bc10d87b5d4bd1c4", size = 18739966, upload-time = "2025-04-08T08:45:49.779Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f2/a8066267eb5fcd1f535776efde29b6d0fa678d978a7de73f47bc59cc940d/duckdb-1.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a5002305cdd4e76c94b61b50abc5e3f4e32c9cb81116960bb4b74acbbc9c6c8", size = 22255946, upload-time = "2025-04-08T08:45:52.274Z" }, + { url = "https://files.pythonhosted.org/packages/df/74/8a05ef00c554882d8300c2c261e8f7e7ead74e2b3ff66059599ff2646cf4/duckdb-1.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:cdb9999c6a109aa31196cdd22fc58a810a3d35d08181a25d1bf963988e89f0a5", size = 11368173, upload-time = "2025-04-08T08:45:54.846Z" }, + { url = "https://files.pythonhosted.org/packages/77/25/549f68e55e1b455bd2daf2e5fc912000a3139fe0395111b3d49b23a2cec1/duckdb-1.2.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f745379f44ad302560688855baaed9739c03b37a331338eda6a4ac655e4eb42f", size = 15271882, upload-time = "2025-04-08T08:45:57.156Z" }, + { url = "https://files.pythonhosted.org/packages/f6/84/13de7bf9056dcc7a346125d9a9f0f26f76c633db6b54052738f78f828538/duckdb-1.2.2-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:087713fc5958cae5eb59097856b3deaae0def021660c8f2052ec83fa8345174a", size = 31964873, upload-time = "2025-04-08T08:45:59.701Z" }, + { url = "https://files.pythonhosted.org/packages/0f/53/c8d2d56a801b7843ea87f8533a3634e6b38f06910098a266f8a096bd4c61/duckdb-1.2.2-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:a1f96395319c447a31b9477881bd84b4cb8323d6f86f21ceaef355d22dd90623", size = 16800653, upload-time = "2025-04-08T08:46:02.527Z" }, + { url = "https://files.pythonhosted.org/packages/bb/36/e25791d879fb93b92a56bf481ce11949ab19109103ae2ba12d64e49355d9/duckdb-1.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6aba3bc0acf4f8d52b94f7746c3b0007b78b517676d482dc516d63f48f967baf", size = 18735524, upload-time = "2025-04-08T08:46:04.842Z" }, + { url = "https://files.pythonhosted.org/packages/d7/46/4745aa10a1e460f4c8b473eddaffe2c783ac5280e1e5929dd84bd1a1acde/duckdb-1.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5c1556775a9ebaa49b5c8d64718f155ac3e05b34a49e9c99443cf105e8b0371", size = 20210314, upload-time = "2025-04-08T08:46:07.052Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0d/8563fc5ece36252e3d07dd3d29c7a0a034dcf62f14bed7cdc016d95adcbe/duckdb-1.2.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d625cc7d2faacfb2fc83ebbe001ae75dda175b3d8dce6a51a71c199ffac3627a", size = 18755134, upload-time = "2025-04-08T08:46:09.274Z" }, + { url = "https://files.pythonhosted.org/packages/11/f1/b7ade7d980eee4fb3ad7469ccf23adb3668a9a28cf3989b24418392d3786/duckdb-1.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:73263f81545c5cb4360fbaf7b22a493e55ddf88fadbe639c43efb7bc8d7554c4", size = 22294397, upload-time = "2025-04-08T08:46:11.476Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c9/896e8ced7b408df81e015fe0c6497cda46c92d9dfc8bf84b6d13f5dad473/duckdb-1.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:b1c0c4d737fd2ab9681e4e78b9f361e0a827916a730e84fa91e76dca451b14d5", size = 11370381, upload-time = "2025-04-08T08:46:13.549Z" }, + { url = "https://files.pythonhosted.org/packages/41/31/5e2f68cbd000137f6ed52092ad83a8e9c09eca70c59e0b4c5eb679709997/duckdb-1.2.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:fb9a2c77236fae079185a990434cb9d8432902488ba990235c702fc2692d2dcd", size = 15272507, upload-time = "2025-04-08T08:46:15.605Z" }, + { url = "https://files.pythonhosted.org/packages/d2/15/aa9078fc897e744e077c0c1510e34db4c809de1d51ddb5cb62e1f9c61312/duckdb-1.2.2-cp313-cp313-macosx_12_0_universal2.whl", hash = "sha256:d8bb89e580cb9a3aaf42e4555bf265d3db9446abfb118e32150e1a5dfa4b5b15", size = 31965548, upload-time = "2025-04-08T08:46:18.593Z" }, + { url = "https://files.pythonhosted.org/packages/9f/28/943773d44fd97055c59b58dde9182733661c2b6e3b3549f15dc26b2e139e/duckdb-1.2.2-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:88916d7f0532dc926bed84b50408c00dcbe6d2097d0de93c3ff647d8d57b4f83", size = 16800600, upload-time = "2025-04-08T08:46:21.51Z" }, + { url = "https://files.pythonhosted.org/packages/39/51/2caf01e7791e490290798c8c155d4d702ed61d69e815915b42e72b3e7473/duckdb-1.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30bece4f58a6c7bb0944a02dd1dc6de435a9daf8668fa31a9fe3a9923b20bd65", size = 18735886, upload-time = "2025-04-08T08:46:24.26Z" }, + { url = "https://files.pythonhosted.org/packages/87/0c/48ae1d485725af3a452303af409a9022d751ecab260cb9ca2f8c9fb670bc/duckdb-1.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bd2c6373b8b54474724c2119f6939c4568c428e1d0be5bcb1f4e3d7f1b7c8bb", size = 20210481, upload-time = "2025-04-08T08:46:26.717Z" }, + { url = "https://files.pythonhosted.org/packages/69/c7/95fcd7bde0f754ea6700208d36b845379cbd2b28779c0eff4dd4a7396369/duckdb-1.2.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72f688a8b0df7030c5a28ca6072817c1f090979e08d28ee5912dee37c26a7d0c", size = 18756619, upload-time = "2025-04-08T08:46:29.035Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1b/c9eab9e84d4a70dd5f7e2a93dd6e9d7b4d868d3df755cd58b572d82d6c5d/duckdb-1.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26e9c349f56f7c99341b5c79bbaff5ba12a5414af0261e79bf1a6a2693f152f6", size = 22294667, upload-time = "2025-04-08T08:46:31.295Z" }, + { url = "https://files.pythonhosted.org/packages/3f/3d/ce68db53084746a4a62695a4cb064e44ce04123f8582bb3afbf6ee944e16/duckdb-1.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1aec7102670e59d83512cf47d32a6c77a79df9df0294c5e4d16b6259851e2e9", size = 11370206, upload-time = "2025-04-08T08:46:33.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/a8/9d75eeab4ff76a4e9dae52298cd0c582f513300f3fc34db9520a6db6c4b1/duckdb-1.2.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:25ac669180f88fecca20f300b898e191f81aa674d51dde8a328bdeb28a572ab0", size = 15255341, upload-time = "2025-04-08T08:46:59.758Z" }, + { url = "https://files.pythonhosted.org/packages/67/52/745839eb1299be96379b52b6cc3783ee330e91ec8d325b157611b9a2d49c/duckdb-1.2.2-cp39-cp39-macosx_12_0_universal2.whl", hash = "sha256:d42e7e545d1059e6b73d0f0baa9ae34c90684bfd8c862e70b0d8ab92e01e0e3f", size = 31923916, upload-time = "2025-04-08T08:47:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/0c/6b/0e1da90808ec4f60215c2a2873c5ae5a248337ccccc77c2b5fb71918f7eb/duckdb-1.2.2-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:f3ce127bcecc723f1c7bddbc57f0526d11128cb05bfd81ffcd5e69e2dd5a1624", size = 16778052, upload-time = "2025-04-08T08:47:06.091Z" }, + { url = "https://files.pythonhosted.org/packages/60/13/04974fdd6106492d6ebbd411c51fca949f73d1a08b5281f9b41c622b0386/duckdb-1.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2418937adb9d6d0ca823bd385b914495294db27bc2963749d54af6708757f679", size = 18727076, upload-time = "2025-04-08T08:47:08.456Z" }, + { url = "https://files.pythonhosted.org/packages/be/cf/f875823e9eae416928b7e583b2174e826e67c120297880f1dde3a726accc/duckdb-1.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d41f899ce7979e7b3f9097ebce70da5c659db2d81d08c07a72b2b50f869859", size = 20196346, upload-time = "2025-04-08T08:47:10.868Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3e/b483c5ad2223392474f4d74d42e522b7545a95154c673f81eea4252d7192/duckdb-1.2.2-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:85e90a9c5307cf4d9151844e60c80f492618ea6e9b71081020e7d462e071ac8f", size = 18724393, upload-time = "2025-04-08T08:47:13.235Z" }, + { url = "https://files.pythonhosted.org/packages/a6/99/349475c08be5abe686d647ca4585287bd01c01b16121f329e05e664630f4/duckdb-1.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:df8c8a4ec998139b8507213c44c50e24f62a36af1cfded87e8972173dc9f8baf", size = 22237700, upload-time = "2025-04-08T08:47:15.63Z" }, + { url = "https://files.pythonhosted.org/packages/8e/1a/1a9da0336c146750ba1dc9a5ad1ab8c228da4512991e1d5b8f0e07076bd5/duckdb-1.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:6507ad2445cd3479853fb6473164b5eb5b22446d283c9892cfbbd0a85c5f361d", size = 11400288, upload-time = "2025-04-08T08:47:17.999Z" }, ] [[package]] name = "eval-type-backport" version = "0.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/ea/8b0ac4469d4c347c6a385ff09dc3c048c2d021696664e26c7ee6791631b5/eval_type_backport-0.2.2.tar.gz", hash = "sha256:f0576b4cf01ebb5bd358d02314d31846af5e07678387486e2c798af0e7d849c1", size = 9079 } +sdist = { url = "https://files.pythonhosted.org/packages/30/ea/8b0ac4469d4c347c6a385ff09dc3c048c2d021696664e26c7ee6791631b5/eval_type_backport-0.2.2.tar.gz", hash = "sha256:f0576b4cf01ebb5bd358d02314d31846af5e07678387486e2c798af0e7d849c1", size = 9079, upload-time = "2024-12-21T20:09:46.005Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/31/55cd413eaccd39125368be33c46de24a1f639f2e12349b0361b4678f3915/eval_type_backport-0.2.2-py3-none-any.whl", hash = "sha256:cb6ad7c393517f476f96d456d0412ea80f0a8cf96f6892834cd9340149111b0a", size = 5830 }, + { url = "https://files.pythonhosted.org/packages/ce/31/55cd413eaccd39125368be33c46de24a1f639f2e12349b0361b4678f3915/eval_type_backport-0.2.2-py3-none-any.whl", hash = "sha256:cb6ad7c393517f476f96d456d0412ea80f0a8cf96f6892834cd9340149111b0a", size = 5830, upload-time = "2024-12-21T20:09:44.175Z" }, ] [[package]] name = "exceptiongroup" version = "1.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883, upload-time = "2024-07-12T22:26:00.161Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453, upload-time = "2024-07-12T22:25:58.476Z" }, ] [[package]] name = "execnet" version = "2.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524 } +sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524, upload-time = "2024-04-08T09:04:19.245Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612 }, + { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612, upload-time = "2024-04-08T09:04:17.414Z" }, ] [[package]] @@ -911,9 +913,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tzdata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ba/a6/b77f42021308ec8b134502343da882c0905d725a4d661c7adeaf7acaf515/faker-37.1.0.tar.gz", hash = "sha256:ad9dc66a3b84888b837ca729e85299a96b58fdaef0323ed0baace93c9614af06", size = 1875707 } +sdist = { url = "https://files.pythonhosted.org/packages/ba/a6/b77f42021308ec8b134502343da882c0905d725a4d661c7adeaf7acaf515/faker-37.1.0.tar.gz", hash = "sha256:ad9dc66a3b84888b837ca729e85299a96b58fdaef0323ed0baace93c9614af06", size = 1875707, upload-time = "2025-03-24T16:14:02.958Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/a1/8936bc8e79af80ca38288dd93ed44ed1f9d63beb25447a4c59e746e01f8d/faker-37.1.0-py3-none-any.whl", hash = "sha256:dc2f730be71cb770e9c715b13374d80dbcee879675121ab51f9683d262ae9a1c", size = 1918783 }, + { url = "https://files.pythonhosted.org/packages/d7/a1/8936bc8e79af80ca38288dd93ed44ed1f9d63beb25447a4c59e746e01f8d/faker-37.1.0-py3-none-any.whl", hash = "sha256:dc2f730be71cb770e9c715b13374d80dbcee879675121ab51f9683d262ae9a1c", size = 1918783, upload-time = "2025-03-24T16:14:00.051Z" }, ] [[package]] @@ -925,100 +927,100 @@ dependencies = [ { name = "starlette" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236 } +sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236, upload-time = "2025-03-23T22:55:43.822Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164 }, + { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload-time = "2025-03-23T22:55:42.101Z" }, ] [[package]] name = "fastnanoid" version = "0.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fa/ba/526d8595043d479a4cc612680dabcbf03b72ec9c21551f66f49b5c1c8aa9/fastnanoid-0.4.1.tar.gz", hash = "sha256:c56185bf4da6959fe229584d526246aafc2297e9e69bd1a5886065f2bc532612", size = 7839 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/17/4e/2884c9cfa143ad8210489f11d48c23bed6277a7793b29f716320133753a6/fastnanoid-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:086e7b79e8ceefc3fc18b4136af2a904288dad8e095ae1851f2ed32025b58f0f", size = 194552 }, - { url = "https://files.pythonhosted.org/packages/ba/5f/f646acbfa04bba326988c029ec0f99f24b838e3b668d475df8bef976ae98/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ee2b9d9351c2b993d44600f4e347ded762708a2cc483a59fbb042d56b650c0e", size = 233701 }, - { url = "https://files.pythonhosted.org/packages/0f/08/ace3e1a07b8674415e5b1dfe51c391853b5a7674ed8cf768ec8146c5b61c/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ecf8e27a1e706ddc8babed6998bbcb28d9625a4f2857f28089bfaf398f27bf0", size = 231891 }, - { url = "https://files.pythonhosted.org/packages/2c/73/926e28b89f73dcfb30b8e12464fb5de94c79fbc1f15976ae0ffb1bbb2a14/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77fd5042be5f15041758ddda75123145112411658e03bcd3abf79f2318f97bfc", size = 261365 }, - { url = "https://files.pythonhosted.org/packages/0b/c0/805f94bbcf9f65b99f914a087f1fabf2437df0849b2d4749119ee6f63a01/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ba551afa02b73137686645537223ad4091c4a9e8e8c10286a5cf5c0c54ccb6d", size = 262593 }, - { url = "https://files.pythonhosted.org/packages/9e/53/4e5713c22fff3ae9c62762cf6a3342f14ebcfc67278afd8c82cf8aa96b3b/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57efcd9774e59f8902ed0c6128e497e2616237092b10e7915860bc9089fc1e5f", size = 227368 }, - { url = "https://files.pythonhosted.org/packages/72/71/3f5806c9f8a37e8e0c54059c2f2b8d808e207e61db7d065e3b0c74db6817/fastnanoid-0.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9abdb225dcaf94b8bec02d2877783d097ea34a3e635a39c0c7b4ab9c72f0601f", size = 234937 }, - { url = "https://files.pythonhosted.org/packages/3d/85/0bd45406bc513d9fe4a63c5b9bb0e8932effd7eaeb6a5d007654c1027317/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a4f94084f1d443acc3e6397a82239a9a15cb41c97e546118b7f07a71b8286331", size = 412001 }, - { url = "https://files.pythonhosted.org/packages/f8/ce/5102614cea37fdd712a3da35fb64cde0cb501fc8f2f957c5e0f0114aaf8c/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3e4dd130f4e1140c812fe9ed5e1ff40d5cfc603a56fc92c36979b52daac79dc1", size = 494252 }, - { url = "https://files.pythonhosted.org/packages/b3/28/4f0f07b4a6eec48761cca926d4f6823586795af4ecfe9e729fb78f381f81/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3570cdfeb7caa33166bafbef79ae3627c785147c03c5ad3d67234921e4f833ee", size = 415651 }, - { url = "https://files.pythonhosted.org/packages/a3/bd/6893d01372ec27b639ef54e1256b52ac0617e3fb14f090b6d0d8ea68347d/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d5eea924e93f2bc1e1d1400c588f2211965d82419921a0e1bbccb65a585aa12", size = 398280 }, - { url = "https://files.pythonhosted.org/packages/63/9d/21daaaa2ec24ef990376303a2140774b908daf8c255f1b2ad6406d3ccac3/fastnanoid-0.4.1-cp310-none-win32.whl", hash = "sha256:b31ea0bf8acae7963ee14f5d5e132562bc539913308aa78b8b1ac4bb1b75011c", size = 98811 }, - { url = "https://files.pythonhosted.org/packages/40/95/58ac4545349e975fd956111874f9412735eede7220a1b2840f0d850da53b/fastnanoid-0.4.1-cp310-none-win_amd64.whl", hash = "sha256:3d58ac0e249b4a8b811c8d512d98450c29d61bfa5b3184fd96f0d08b87d6053c", size = 105875 }, - { url = "https://files.pythonhosted.org/packages/5b/b3/907e7c538fb8d7b187277aaab6de6f4def4f2f13cedc96d83d882ed07909/fastnanoid-0.4.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6cd70d61365546b0d0f7d5dee32032a1e050472338cbcd727a1b8b99d8db9f2c", size = 198462 }, - { url = "https://files.pythonhosted.org/packages/3d/ce/6fe33cd55d2b44ca92c8dcad188b5ca0dd6e3cc4c406ac51f9aa5057e423/fastnanoid-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9cd2d280ce6acaa2b2caf83e6f1f16f5ab909c98ee2ef558311c4b5c2c811b69", size = 194317 }, - { url = "https://files.pythonhosted.org/packages/9d/41/26212a05cf7a9b65246d39fca75656417c78a615062e11599c8b7a704a09/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af1f10ad89a570196699328bbcf39fb91937d2646f44c8feb7965de5125a1830", size = 233399 }, - { url = "https://files.pythonhosted.org/packages/74/81/a1477f74df79a9993455ef677265f65618c8ceb37c285f89191d77def686/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f42cf1f995b72560d610eceaf4ded31d62ec520afcece557c4a25e02e1721ef1", size = 231687 }, - { url = "https://files.pythonhosted.org/packages/1c/36/b0b50671dacc815e19e763f2d6e3a8f3d891509ebd21e78ab928cc1343f1/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03b203d3a0ef9347acdfae10a9f8c0de2542770d347a436d81f59395e73dec16", size = 261198 }, - { url = "https://files.pythonhosted.org/packages/7f/68/f3eae6ff80921f18c0239a9319cefa3537d73dc0cdf861f407d7bc427f23/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ad1c9b058546ba60c94534331bbc32bfc088feb41f8fe24be6b4acc15713dc1", size = 261751 }, - { url = "https://files.pythonhosted.org/packages/4f/1d/1b7449508a1ea387fb3c2cb2a73f13baaf2081633d25c4119f29fc5159f4/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3b309f811b8c9d0ead8a96d37e40734c258c010bea5dec7ea24e824e7934bb8", size = 227076 }, - { url = "https://files.pythonhosted.org/packages/77/ae/3aead74b29a12d8e72f93e5f6f9e4d6203e56961ec5d9a9eac1b849fcf1e/fastnanoid-0.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a29ec0aa8ca23ad88bbf30a449d54946b049b7b26aec514dbc6cc31d0d2581c5", size = 234791 }, - { url = "https://files.pythonhosted.org/packages/b3/f1/02803e861f4e1f7994a848ae43a618408343f7caed5ea6c4cc9e557a3d77/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e243e291d08c7c03d700cc0e8e907c5aef88d099f446d1a2c6659cf21647ed66", size = 411720 }, - { url = "https://files.pythonhosted.org/packages/da/d6/6e887cb7327d52cd6885a54b94ad1046fc2a54508fd6306a324da77c5461/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:be22f19d640cb8c6aef9dd38dc08da593ccc012be0210253777bf87d982900fc", size = 493986 }, - { url = "https://files.pythonhosted.org/packages/07/98/0b2bed65176ba2e0505688ca94dc396ad51072900c3e696da87a30e36f1f/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4488296cd2eb87d6078cfe7fdf72393a87483241456b3ea1bde6225ca477d6d5", size = 415552 }, - { url = "https://files.pythonhosted.org/packages/54/64/b57146c8770c9bf1a8ef791c5edcf1c53b7b2466cb687f6ed1f6859802d9/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:038b1f0626d728c241dafc4eb8469c3f928297025ab5d29e1b5534060e4c9859", size = 398109 }, - { url = "https://files.pythonhosted.org/packages/5e/50/f3bc7005eccce3565bf6132eaa625ac5226242adbb9b5d6faeef8fa077af/fastnanoid-0.4.1-cp311-none-win32.whl", hash = "sha256:0f11ada2493d38a8634762d9eb625928a9fa6ea069a9e1d98d08ca4acd75b2e7", size = 98795 }, - { url = "https://files.pythonhosted.org/packages/7c/24/9be8d080143dbdbcba57e8a93ade8ae68b8adc7a17851b28f343f8efc721/fastnanoid-0.4.1-cp311-none-win_amd64.whl", hash = "sha256:bf092ab330ad8535310938111cf5d24e649a9d600d8895fa9b9a10899be2d6fb", size = 105793 }, - { url = "https://files.pythonhosted.org/packages/fd/cd/e614b91c31176e50fc2beb5a99c4c027df36be7ab000b3a7c7af782a26af/fastnanoid-0.4.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e1970288e8cb7aafbd0b64f8ac8ef947445ca0a22dbcbab490486b1d3671c761", size = 198051 }, - { url = "https://files.pythonhosted.org/packages/4b/db/99ce5dbc4527a1a993612a1b941c949d73123b25b680abfc1a91f1bd5b93/fastnanoid-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5e833d14a5aab861399e7d7967d91883f3a389c216c1adfbacef162cada5c58b", size = 194232 }, - { url = "https://files.pythonhosted.org/packages/ba/08/ab3b573c4b2301476e8177b7a68022dac24272f970c0a658008f10c42f95/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82699d5b3353dca26ace5b587a6d95af7f6e506647c0d620a23fa32558d672a3", size = 232999 }, - { url = "https://files.pythonhosted.org/packages/c6/b2/9e3de343798afb336a914a61b62a0ef18a932c6bc854981b36bece4e94b5/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0924275254c0ce8514d14ed0bfd2629a7d2d180296d7c22ce6ab72590a09c2e3", size = 231391 }, - { url = "https://files.pythonhosted.org/packages/01/92/9c2b7b9a5d8396e6aaba9854559870e1efbda2676806af015611416f22ed/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c576e5096ac66b057dfea31243e8a2ec37fd92c22ac35dde4aca15eb5e54eb7d", size = 260956 }, - { url = "https://files.pythonhosted.org/packages/af/98/eab314e6b056e9b75e80f746288f6059696393ebafbd74fa0a7a724eb504/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67f073167a90cab5df5a89e12f97c90b98b9e14486dce5fb8e780cc30a87031e", size = 261119 }, - { url = "https://files.pythonhosted.org/packages/10/d8/6f24692866831f146255a37e28ae615ef63363b93ba1f9b2e21f7cf7c353/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6fbe8fbcc19644ed12dbb10b76ff67bb3111b0d51f311215514562058226581", size = 226928 }, - { url = "https://files.pythonhosted.org/packages/52/90/618330d6be724ea968950d42087857a4c3faeccec0d503a34bf02a2cab6a/fastnanoid-0.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5eae7c39528884001efc572b89f57093a69bb2732c1b113e5f89047e409f8795", size = 234370 }, - { url = "https://files.pythonhosted.org/packages/96/eb/3b647816a1d30c6426f81ab218d15c33eeabfa02d6fef7856df93e80a3bb/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5cf2f5d1c57c41a0de660d1f2529364f715325ea94c5d01498751f8e56758730", size = 411544 }, - { url = "https://files.pythonhosted.org/packages/2a/bc/84bde22fa83195cf8edcd60c0ece60a9ca15ef5ab4dc11f7ec49e9e11a1a/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:bc9773c8941174ccc60cdc73e3ac265b800f96896a93922991ade01a3017b013", size = 493623 }, - { url = "https://files.pythonhosted.org/packages/26/12/276810b4c3c0383d17fce678f758c884318c0b6e32bbbe5cf8fd7c2593f8/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5c039d9c8da181283af8a3a4ded14d1a285ada3c9a5cb78ed0effb3c1748d93c", size = 415097 }, - { url = "https://files.pythonhosted.org/packages/a3/0f/df4e1385d31e1e478ce0915af8fd2b880cfb0b9fe936a73d05900dfd0803/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5c93ca137bc68d9fd1a2f189c17a6fa8df908311d07a36e9ba66123827fbfb33", size = 397969 }, - { url = "https://files.pythonhosted.org/packages/df/87/2c77f57ff69e754f0d2271ff687e9d35ef5f71e5b7c346f38d236c625dec/fastnanoid-0.4.1-cp312-none-win32.whl", hash = "sha256:54dc50f17fa5078c7868cd12cbc9be01e7d4e40b503a98463a7dd2a01a56c39f", size = 98612 }, - { url = "https://files.pythonhosted.org/packages/14/48/1131c2590dabfce1ddc28b83f906ca4bab7d39c1d904b2454c46b472a9bd/fastnanoid-0.4.1-cp312-none-win_amd64.whl", hash = "sha256:b6d12d1119fed553cdc632e38c54ccbd7cb2f82dcd0b67ebe879da19cfe0c8e1", size = 105889 }, - { url = "https://files.pythonhosted.org/packages/61/f1/26f622d721c71e024cd55faf19531dd69bc25108b1ef326ebece33e9f699/fastnanoid-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e930d7ac5d8512fbe83ef7de46d3ad9d91eb9315b9b68b125d242266825c390", size = 194996 }, - { url = "https://files.pythonhosted.org/packages/62/0a/8f0ab7413788d7e7abd2ea9bb21af914f31b3aa1a97b5faa33eb999a742f/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dc5fdad8b0c748ea66df130de106b02a6fe4933e49f21454272509f534de1f3", size = 234065 }, - { url = "https://files.pythonhosted.org/packages/5c/bf/097e56a91f11f1a95d66a398d64e7b528c65f9c6c96c071ccdcb2180563a/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d6ba7fa984db6263bd895df90416f99e8975a6032477ad1eef326e8e9e4b1624", size = 231972 }, - { url = "https://files.pythonhosted.org/packages/7c/c0/5241bfccc04174f6e836ec721e6d6428eac4e0ab1c10f7efcc10c2024bf2/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:596e8bdd189e51af4a7860d18344f0e08d8cb1fb046063c2a135de774923e1bc", size = 261652 }, - { url = "https://files.pythonhosted.org/packages/84/81/5389aed7c24914fae2a150a38e5f595ff8d4bc4d04a087f1e5e469b068e4/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9058cf974261fa89641c88d56f3a80524a4eeafd0b9022625fe1674198912fa7", size = 262552 }, - { url = "https://files.pythonhosted.org/packages/80/31/e4c9e7654af8e5f815d430fc255c108660ba744f8cc2364333298ec7e40f/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f700fa3c818ccb178efc21543d33689f3deea6f954937294c97d2f1ae111fbc", size = 227269 }, - { url = "https://files.pythonhosted.org/packages/6f/8e/1ef0458822a12634c02db9693e190a1dcc8edac4d8a182c1d4b2c2abf1da/fastnanoid-0.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d124937de815606098d473713f564ed3c9d776ed4592df7ae400384b3cdead76", size = 235495 }, - { url = "https://files.pythonhosted.org/packages/5e/cf/e5eb22103bf032731a49b46e86d8c4ae833723774a4af1a25a136ff0037e/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a11b5af8a79e90e0d196f8f33e290b2ee491d41eafe743e71edb45878cb2b8dd", size = 411927 }, - { url = "https://files.pythonhosted.org/packages/0c/0f/8046a43dd5e83f731d958a92c2c262277f9d3efdfb035fbaec6fde081ad5/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ccf13c32c1ef2def1684e1b424cc29d5727d7bbb1cec15af42cbde031dfe71ae", size = 494256 }, - { url = "https://files.pythonhosted.org/packages/a6/af/c644f011142aafd67b065b18197f3f2da2eae8aacf5a3419056f890606ad/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9b6b75133fd461d15241648e59fcb6bfa490e86108046907a7806f4b928d55b6", size = 415748 }, - { url = "https://files.pythonhosted.org/packages/03/5a/5c925d5ad87c82cc62deefb8b058c4ba9f198167d84ca645c9231774ffff/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:af517e0b993ef1a1afca89160d2bd9764e87f17b2db928a8c1c2cd270cc163d5", size = 398538 }, - { url = "https://files.pythonhosted.org/packages/cd/8c/76140f4102529b5a9f22333fb7390940fbd5a707859a41c253ba0ce7eb44/fastnanoid-0.4.1-cp39-none-win32.whl", hash = "sha256:491832c86d2dc0aa6a31011f428ab01fdfecbda01eae33d853a57eb8cd90d8f6", size = 98742 }, - { url = "https://files.pythonhosted.org/packages/8d/be/d1a24ab16cb2537fd372520c78d8596fcb8f644f19e97fd8f0fe68f463d4/fastnanoid-0.4.1-cp39-none-win_amd64.whl", hash = "sha256:43e6890b71682bc610c7782b484f55dd9ac3f7b3c8c341fa90a906215e225379", size = 105862 }, - { url = "https://files.pythonhosted.org/packages/9b/61/827cc586b6c4211946d90d9eaa1ec055eba9ae31f71393673c4802113831/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4da9c369ad5d1fba8bc4452bfd8e2f40974087a29d66475d8eec281f0386fee9", size = 234444 }, - { url = "https://files.pythonhosted.org/packages/a8/48/cce55a34782bb4ed34292d193f1aba6c3629be92f298011dce16b6dfbd8a/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:359e6f082b348fd37d4e6492f1728948e81758e93de3015bed2a92b58c0c44c3", size = 232612 }, - { url = "https://files.pythonhosted.org/packages/ff/f6/e7fea180533649c548f02d0ace16d76305fbea762026c5367d313f047793/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:823067b5cc527597a07fdeb86d50123824b5c6f41c5bf37d6327f956a247784b", size = 261764 }, - { url = "https://files.pythonhosted.org/packages/a7/3f/37a5c8b875d07d665dfa53bb1ca67d7dbce9517fe8001e4f676e81126126/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:588722f2d43af6fa16ec9e55b9ea480ce3bc111a1c10757cdd2c148f42d12930", size = 263414 }, - { url = "https://files.pythonhosted.org/packages/77/95/3c7acf630d78c82bbdaa12c5a66d7aa508d1b545efb85bbb7d1ac37d0d00/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:927fbe72d03cb705890f880e20240276a22888f8e5a7da1d21d3eefd24348f47", size = 228228 }, - { url = "https://files.pythonhosted.org/packages/97/ce/3f5f5924b236d08d155d3bcb794d63a92075033e2b6ecfe17cbf4614815c/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0c2b6e3a9cd109154b9a80ae6a38d02550358147f5cf13d166f262af5b62f6b", size = 235934 }, - { url = "https://files.pythonhosted.org/packages/a9/cb/3b89fc023f02fe55acbdc4c202050952876c4b118e7caedf034b153d07e2/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:266039637cddf143a07058e139868e3a8ce3108ffcad001cd8c399f260073bec", size = 412662 }, - { url = "https://files.pythonhosted.org/packages/4d/47/723cd630704c499fd7e91548c23658cd08c7f6331e5932c489341c319d19/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:b1dc76cdcad24f00a7a427cf00f4f72b23893b19ce41fd2f0916bb6e5ecd8b22", size = 494897 }, - { url = "https://files.pythonhosted.org/packages/79/87/a1ddf63fdddc17c63e196b3ab7bf997d588683176efe9e97e9a7a72466f1/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:30911cf3ec13d065bcb1672f624237ad39b8eab57a51fa74ebb99e2765d76b35", size = 416140 }, - { url = "https://files.pythonhosted.org/packages/4d/f8/a53cbab4c646f948e7e79100586dddab23cd6ec6e0be02d9a8794c3ba6e8/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0897ce9f40ef8483374c16a3a7ecdfe6feb949b420b1e4b69e8359c254020f03", size = 399208 }, - { url = "https://files.pythonhosted.org/packages/0e/99/a1bfcfd64fd4b9e8599a634c5f42a7c1ea39d151bcd616c583a95843f041/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dcfee2a516fb701751c52c75c51b9d0b5c0eedac01a032a793e96630ef25b0d", size = 234938 }, - { url = "https://files.pythonhosted.org/packages/3a/35/7c7393c06ece7cd27eca843957a71414c66227f1f88249efa78eb6d20e22/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24851db09a54c25fb922096cd6716871bd1f564b1f70f4b04f2ee8f71cd3ecac", size = 233149 }, - { url = "https://files.pythonhosted.org/packages/7c/2b/2ae0a3058c775076e36203bf58417422d399cf2f0df49061d5b577de6942/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c7fb33cf414d3120b46c5b72ad64bc51e2b81bbbc11d4f8aee2f8e1e4f5bb26e", size = 262215 }, - { url = "https://files.pythonhosted.org/packages/b9/95/d67ea1b364195f579ef6c046af35c967e9a6cc33c227dc7e8c36c6028314/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54518cb82914e2ab2dfaa2ef18d71996f04fa026d7c7e7aa815e37dc442ec796", size = 263468 }, - { url = "https://files.pythonhosted.org/packages/a3/a4/c45127919dddef26dfad4a3a6b1d0548d835647bdaf24ec1308f16a2c8db/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16d13f5223ca16e31585fd526c59b05402cf6513a829d5619675badb1dc58424", size = 228442 }, - { url = "https://files.pythonhosted.org/packages/1a/08/bfa9a24d903f34bbc857246bd388101ef99ed7832efa826e31a4ef4957c0/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00dda7a2f34e2d41a6600ae62367472c255573865d294b3941a725ee010c3873", size = 235962 }, - { url = "https://files.pythonhosted.org/packages/a9/b8/da79a09b9ebfe7f502e308fe64acd043060988cf8a5d9322cedc5889a4ea/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0a6b9bed15396c2b7e0bc72350c3ee2a0573d47defe95e387bbd592dbe9d5922", size = 412938 }, - { url = "https://files.pythonhosted.org/packages/bc/54/d7049f90777bf21de4d5ab74b42cedf213bcdff7f0daa318442f18ebb072/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:e69ce0aa186e5236086b40de3814f0719037d2eed66e04bee2c0116ee4fd5501", size = 495351 }, - { url = "https://files.pythonhosted.org/packages/45/03/757a093f34aea99dfa948cd0af82d10196c7b9f2c893fd9c020c9da89ea0/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:e0ab1f5806047e484a64bae131e502bd22b8f1ef740f866adc73c645c8648d1b", size = 416558 }, - { url = "https://files.pythonhosted.org/packages/7b/cb/77d820e6050c1e669ef8661f6b94d0f203242a5e20191802140920420e2b/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:02f427342dfa025d66253fb5176da1f332dcb2784929bc6f12a4dc0f9b9e203c", size = 399506 }, +sdist = { url = "https://files.pythonhosted.org/packages/fa/ba/526d8595043d479a4cc612680dabcbf03b72ec9c21551f66f49b5c1c8aa9/fastnanoid-0.4.1.tar.gz", hash = "sha256:c56185bf4da6959fe229584d526246aafc2297e9e69bd1a5886065f2bc532612", size = 7839, upload-time = "2024-08-11T13:55:06.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/4e/2884c9cfa143ad8210489f11d48c23bed6277a7793b29f716320133753a6/fastnanoid-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:086e7b79e8ceefc3fc18b4136af2a904288dad8e095ae1851f2ed32025b58f0f", size = 194552, upload-time = "2024-08-11T13:54:10.165Z" }, + { url = "https://files.pythonhosted.org/packages/ba/5f/f646acbfa04bba326988c029ec0f99f24b838e3b668d475df8bef976ae98/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ee2b9d9351c2b993d44600f4e347ded762708a2cc483a59fbb042d56b650c0e", size = 233701, upload-time = "2024-08-11T13:53:04.65Z" }, + { url = "https://files.pythonhosted.org/packages/0f/08/ace3e1a07b8674415e5b1dfe51c391853b5a7674ed8cf768ec8146c5b61c/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ecf8e27a1e706ddc8babed6998bbcb28d9625a4f2857f28089bfaf398f27bf0", size = 231891, upload-time = "2024-08-11T13:53:17.541Z" }, + { url = "https://files.pythonhosted.org/packages/2c/73/926e28b89f73dcfb30b8e12464fb5de94c79fbc1f15976ae0ffb1bbb2a14/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77fd5042be5f15041758ddda75123145112411658e03bcd3abf79f2318f97bfc", size = 261365, upload-time = "2024-08-11T13:53:28.954Z" }, + { url = "https://files.pythonhosted.org/packages/0b/c0/805f94bbcf9f65b99f914a087f1fabf2437df0849b2d4749119ee6f63a01/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ba551afa02b73137686645537223ad4091c4a9e8e8c10286a5cf5c0c54ccb6d", size = 262593, upload-time = "2024-08-11T13:53:40.098Z" }, + { url = "https://files.pythonhosted.org/packages/9e/53/4e5713c22fff3ae9c62762cf6a3342f14ebcfc67278afd8c82cf8aa96b3b/fastnanoid-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57efcd9774e59f8902ed0c6128e497e2616237092b10e7915860bc9089fc1e5f", size = 227368, upload-time = "2024-08-11T13:54:01.031Z" }, + { url = "https://files.pythonhosted.org/packages/72/71/3f5806c9f8a37e8e0c54059c2f2b8d808e207e61db7d065e3b0c74db6817/fastnanoid-0.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9abdb225dcaf94b8bec02d2877783d097ea34a3e635a39c0c7b4ab9c72f0601f", size = 234937, upload-time = "2024-08-11T13:53:52.451Z" }, + { url = "https://files.pythonhosted.org/packages/3d/85/0bd45406bc513d9fe4a63c5b9bb0e8932effd7eaeb6a5d007654c1027317/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a4f94084f1d443acc3e6397a82239a9a15cb41c97e546118b7f07a71b8286331", size = 412001, upload-time = "2024-08-11T13:54:17.611Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ce/5102614cea37fdd712a3da35fb64cde0cb501fc8f2f957c5e0f0114aaf8c/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3e4dd130f4e1140c812fe9ed5e1ff40d5cfc603a56fc92c36979b52daac79dc1", size = 494252, upload-time = "2024-08-11T13:54:29.656Z" }, + { url = "https://files.pythonhosted.org/packages/b3/28/4f0f07b4a6eec48761cca926d4f6823586795af4ecfe9e729fb78f381f81/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3570cdfeb7caa33166bafbef79ae3627c785147c03c5ad3d67234921e4f833ee", size = 415651, upload-time = "2024-08-11T13:54:43.282Z" }, + { url = "https://files.pythonhosted.org/packages/a3/bd/6893d01372ec27b639ef54e1256b52ac0617e3fb14f090b6d0d8ea68347d/fastnanoid-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d5eea924e93f2bc1e1d1400c588f2211965d82419921a0e1bbccb65a585aa12", size = 398280, upload-time = "2024-08-11T13:54:54.612Z" }, + { url = "https://files.pythonhosted.org/packages/63/9d/21daaaa2ec24ef990376303a2140774b908daf8c255f1b2ad6406d3ccac3/fastnanoid-0.4.1-cp310-none-win32.whl", hash = "sha256:b31ea0bf8acae7963ee14f5d5e132562bc539913308aa78b8b1ac4bb1b75011c", size = 98811, upload-time = "2024-08-11T13:55:13.951Z" }, + { url = "https://files.pythonhosted.org/packages/40/95/58ac4545349e975fd956111874f9412735eede7220a1b2840f0d850da53b/fastnanoid-0.4.1-cp310-none-win_amd64.whl", hash = "sha256:3d58ac0e249b4a8b811c8d512d98450c29d61bfa5b3184fd96f0d08b87d6053c", size = 105875, upload-time = "2024-08-11T13:55:07.271Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b3/907e7c538fb8d7b187277aaab6de6f4def4f2f13cedc96d83d882ed07909/fastnanoid-0.4.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6cd70d61365546b0d0f7d5dee32032a1e050472338cbcd727a1b8b99d8db9f2c", size = 198462, upload-time = "2024-08-11T13:54:15.196Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ce/6fe33cd55d2b44ca92c8dcad188b5ca0dd6e3cc4c406ac51f9aa5057e423/fastnanoid-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9cd2d280ce6acaa2b2caf83e6f1f16f5ab909c98ee2ef558311c4b5c2c811b69", size = 194317, upload-time = "2024-08-11T13:54:11.383Z" }, + { url = "https://files.pythonhosted.org/packages/9d/41/26212a05cf7a9b65246d39fca75656417c78a615062e11599c8b7a704a09/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af1f10ad89a570196699328bbcf39fb91937d2646f44c8feb7965de5125a1830", size = 233399, upload-time = "2024-08-11T13:53:06.543Z" }, + { url = "https://files.pythonhosted.org/packages/74/81/a1477f74df79a9993455ef677265f65618c8ceb37c285f89191d77def686/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f42cf1f995b72560d610eceaf4ded31d62ec520afcece557c4a25e02e1721ef1", size = 231687, upload-time = "2024-08-11T13:53:18.872Z" }, + { url = "https://files.pythonhosted.org/packages/1c/36/b0b50671dacc815e19e763f2d6e3a8f3d891509ebd21e78ab928cc1343f1/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03b203d3a0ef9347acdfae10a9f8c0de2542770d347a436d81f59395e73dec16", size = 261198, upload-time = "2024-08-11T13:53:30.601Z" }, + { url = "https://files.pythonhosted.org/packages/7f/68/f3eae6ff80921f18c0239a9319cefa3537d73dc0cdf861f407d7bc427f23/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ad1c9b058546ba60c94534331bbc32bfc088feb41f8fe24be6b4acc15713dc1", size = 261751, upload-time = "2024-08-11T13:53:42.734Z" }, + { url = "https://files.pythonhosted.org/packages/4f/1d/1b7449508a1ea387fb3c2cb2a73f13baaf2081633d25c4119f29fc5159f4/fastnanoid-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3b309f811b8c9d0ead8a96d37e40734c258c010bea5dec7ea24e824e7934bb8", size = 227076, upload-time = "2024-08-11T13:54:02.534Z" }, + { url = "https://files.pythonhosted.org/packages/77/ae/3aead74b29a12d8e72f93e5f6f9e4d6203e56961ec5d9a9eac1b849fcf1e/fastnanoid-0.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a29ec0aa8ca23ad88bbf30a449d54946b049b7b26aec514dbc6cc31d0d2581c5", size = 234791, upload-time = "2024-08-11T13:53:53.626Z" }, + { url = "https://files.pythonhosted.org/packages/b3/f1/02803e861f4e1f7994a848ae43a618408343f7caed5ea6c4cc9e557a3d77/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e243e291d08c7c03d700cc0e8e907c5aef88d099f446d1a2c6659cf21647ed66", size = 411720, upload-time = "2024-08-11T13:54:18.931Z" }, + { url = "https://files.pythonhosted.org/packages/da/d6/6e887cb7327d52cd6885a54b94ad1046fc2a54508fd6306a324da77c5461/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:be22f19d640cb8c6aef9dd38dc08da593ccc012be0210253777bf87d982900fc", size = 493986, upload-time = "2024-08-11T13:54:31.235Z" }, + { url = "https://files.pythonhosted.org/packages/07/98/0b2bed65176ba2e0505688ca94dc396ad51072900c3e696da87a30e36f1f/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4488296cd2eb87d6078cfe7fdf72393a87483241456b3ea1bde6225ca477d6d5", size = 415552, upload-time = "2024-08-11T13:54:44.468Z" }, + { url = "https://files.pythonhosted.org/packages/54/64/b57146c8770c9bf1a8ef791c5edcf1c53b7b2466cb687f6ed1f6859802d9/fastnanoid-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:038b1f0626d728c241dafc4eb8469c3f928297025ab5d29e1b5534060e4c9859", size = 398109, upload-time = "2024-08-11T13:54:56.184Z" }, + { url = "https://files.pythonhosted.org/packages/5e/50/f3bc7005eccce3565bf6132eaa625ac5226242adbb9b5d6faeef8fa077af/fastnanoid-0.4.1-cp311-none-win32.whl", hash = "sha256:0f11ada2493d38a8634762d9eb625928a9fa6ea069a9e1d98d08ca4acd75b2e7", size = 98795, upload-time = "2024-08-11T13:55:15.151Z" }, + { url = "https://files.pythonhosted.org/packages/7c/24/9be8d080143dbdbcba57e8a93ade8ae68b8adc7a17851b28f343f8efc721/fastnanoid-0.4.1-cp311-none-win_amd64.whl", hash = "sha256:bf092ab330ad8535310938111cf5d24e649a9d600d8895fa9b9a10899be2d6fb", size = 105793, upload-time = "2024-08-11T13:55:08.456Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cd/e614b91c31176e50fc2beb5a99c4c027df36be7ab000b3a7c7af782a26af/fastnanoid-0.4.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e1970288e8cb7aafbd0b64f8ac8ef947445ca0a22dbcbab490486b1d3671c761", size = 198051, upload-time = "2024-08-11T13:54:16.43Z" }, + { url = "https://files.pythonhosted.org/packages/4b/db/99ce5dbc4527a1a993612a1b941c949d73123b25b680abfc1a91f1bd5b93/fastnanoid-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5e833d14a5aab861399e7d7967d91883f3a389c216c1adfbacef162cada5c58b", size = 194232, upload-time = "2024-08-11T13:54:12.58Z" }, + { url = "https://files.pythonhosted.org/packages/ba/08/ab3b573c4b2301476e8177b7a68022dac24272f970c0a658008f10c42f95/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82699d5b3353dca26ace5b587a6d95af7f6e506647c0d620a23fa32558d672a3", size = 232999, upload-time = "2024-08-11T13:53:08.205Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b2/9e3de343798afb336a914a61b62a0ef18a932c6bc854981b36bece4e94b5/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0924275254c0ce8514d14ed0bfd2629a7d2d180296d7c22ce6ab72590a09c2e3", size = 231391, upload-time = "2024-08-11T13:53:20.537Z" }, + { url = "https://files.pythonhosted.org/packages/01/92/9c2b7b9a5d8396e6aaba9854559870e1efbda2676806af015611416f22ed/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c576e5096ac66b057dfea31243e8a2ec37fd92c22ac35dde4aca15eb5e54eb7d", size = 260956, upload-time = "2024-08-11T13:53:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/af/98/eab314e6b056e9b75e80f746288f6059696393ebafbd74fa0a7a724eb504/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67f073167a90cab5df5a89e12f97c90b98b9e14486dce5fb8e780cc30a87031e", size = 261119, upload-time = "2024-08-11T13:53:43.93Z" }, + { url = "https://files.pythonhosted.org/packages/10/d8/6f24692866831f146255a37e28ae615ef63363b93ba1f9b2e21f7cf7c353/fastnanoid-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6fbe8fbcc19644ed12dbb10b76ff67bb3111b0d51f311215514562058226581", size = 226928, upload-time = "2024-08-11T13:54:03.706Z" }, + { url = "https://files.pythonhosted.org/packages/52/90/618330d6be724ea968950d42087857a4c3faeccec0d503a34bf02a2cab6a/fastnanoid-0.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5eae7c39528884001efc572b89f57093a69bb2732c1b113e5f89047e409f8795", size = 234370, upload-time = "2024-08-11T13:53:54.869Z" }, + { url = "https://files.pythonhosted.org/packages/96/eb/3b647816a1d30c6426f81ab218d15c33eeabfa02d6fef7856df93e80a3bb/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5cf2f5d1c57c41a0de660d1f2529364f715325ea94c5d01498751f8e56758730", size = 411544, upload-time = "2024-08-11T13:54:20.653Z" }, + { url = "https://files.pythonhosted.org/packages/2a/bc/84bde22fa83195cf8edcd60c0ece60a9ca15ef5ab4dc11f7ec49e9e11a1a/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:bc9773c8941174ccc60cdc73e3ac265b800f96896a93922991ade01a3017b013", size = 493623, upload-time = "2024-08-11T13:54:32.965Z" }, + { url = "https://files.pythonhosted.org/packages/26/12/276810b4c3c0383d17fce678f758c884318c0b6e32bbbe5cf8fd7c2593f8/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5c039d9c8da181283af8a3a4ded14d1a285ada3c9a5cb78ed0effb3c1748d93c", size = 415097, upload-time = "2024-08-11T13:54:46.087Z" }, + { url = "https://files.pythonhosted.org/packages/a3/0f/df4e1385d31e1e478ce0915af8fd2b880cfb0b9fe936a73d05900dfd0803/fastnanoid-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5c93ca137bc68d9fd1a2f189c17a6fa8df908311d07a36e9ba66123827fbfb33", size = 397969, upload-time = "2024-08-11T13:54:57.489Z" }, + { url = "https://files.pythonhosted.org/packages/df/87/2c77f57ff69e754f0d2271ff687e9d35ef5f71e5b7c346f38d236c625dec/fastnanoid-0.4.1-cp312-none-win32.whl", hash = "sha256:54dc50f17fa5078c7868cd12cbc9be01e7d4e40b503a98463a7dd2a01a56c39f", size = 98612, upload-time = "2024-08-11T13:55:16.268Z" }, + { url = "https://files.pythonhosted.org/packages/14/48/1131c2590dabfce1ddc28b83f906ca4bab7d39c1d904b2454c46b472a9bd/fastnanoid-0.4.1-cp312-none-win_amd64.whl", hash = "sha256:b6d12d1119fed553cdc632e38c54ccbd7cb2f82dcd0b67ebe879da19cfe0c8e1", size = 105889, upload-time = "2024-08-11T13:55:10Z" }, + { url = "https://files.pythonhosted.org/packages/61/f1/26f622d721c71e024cd55faf19531dd69bc25108b1ef326ebece33e9f699/fastnanoid-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e930d7ac5d8512fbe83ef7de46d3ad9d91eb9315b9b68b125d242266825c390", size = 194996, upload-time = "2024-08-11T13:54:13.907Z" }, + { url = "https://files.pythonhosted.org/packages/62/0a/8f0ab7413788d7e7abd2ea9bb21af914f31b3aa1a97b5faa33eb999a742f/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dc5fdad8b0c748ea66df130de106b02a6fe4933e49f21454272509f534de1f3", size = 234065, upload-time = "2024-08-11T13:53:11.16Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bf/097e56a91f11f1a95d66a398d64e7b528c65f9c6c96c071ccdcb2180563a/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d6ba7fa984db6263bd895df90416f99e8975a6032477ad1eef326e8e9e4b1624", size = 231972, upload-time = "2024-08-11T13:53:23.324Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c0/5241bfccc04174f6e836ec721e6d6428eac4e0ab1c10f7efcc10c2024bf2/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:596e8bdd189e51af4a7860d18344f0e08d8cb1fb046063c2a135de774923e1bc", size = 261652, upload-time = "2024-08-11T13:53:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/84/81/5389aed7c24914fae2a150a38e5f595ff8d4bc4d04a087f1e5e469b068e4/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9058cf974261fa89641c88d56f3a80524a4eeafd0b9022625fe1674198912fa7", size = 262552, upload-time = "2024-08-11T13:53:46.5Z" }, + { url = "https://files.pythonhosted.org/packages/80/31/e4c9e7654af8e5f815d430fc255c108660ba744f8cc2364333298ec7e40f/fastnanoid-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f700fa3c818ccb178efc21543d33689f3deea6f954937294c97d2f1ae111fbc", size = 227269, upload-time = "2024-08-11T13:54:06.258Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8e/1ef0458822a12634c02db9693e190a1dcc8edac4d8a182c1d4b2c2abf1da/fastnanoid-0.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d124937de815606098d473713f564ed3c9d776ed4592df7ae400384b3cdead76", size = 235495, upload-time = "2024-08-11T13:53:57.321Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cf/e5eb22103bf032731a49b46e86d8c4ae833723774a4af1a25a136ff0037e/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a11b5af8a79e90e0d196f8f33e290b2ee491d41eafe743e71edb45878cb2b8dd", size = 411927, upload-time = "2024-08-11T13:54:23.477Z" }, + { url = "https://files.pythonhosted.org/packages/0c/0f/8046a43dd5e83f731d958a92c2c262277f9d3efdfb035fbaec6fde081ad5/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ccf13c32c1ef2def1684e1b424cc29d5727d7bbb1cec15af42cbde031dfe71ae", size = 494256, upload-time = "2024-08-11T13:54:35.758Z" }, + { url = "https://files.pythonhosted.org/packages/a6/af/c644f011142aafd67b065b18197f3f2da2eae8aacf5a3419056f890606ad/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9b6b75133fd461d15241648e59fcb6bfa490e86108046907a7806f4b928d55b6", size = 415748, upload-time = "2024-08-11T13:54:49.031Z" }, + { url = "https://files.pythonhosted.org/packages/03/5a/5c925d5ad87c82cc62deefb8b058c4ba9f198167d84ca645c9231774ffff/fastnanoid-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:af517e0b993ef1a1afca89160d2bd9764e87f17b2db928a8c1c2cd270cc163d5", size = 398538, upload-time = "2024-08-11T13:55:00.091Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8c/76140f4102529b5a9f22333fb7390940fbd5a707859a41c253ba0ce7eb44/fastnanoid-0.4.1-cp39-none-win32.whl", hash = "sha256:491832c86d2dc0aa6a31011f428ab01fdfecbda01eae33d853a57eb8cd90d8f6", size = 98742, upload-time = "2024-08-11T13:55:18.692Z" }, + { url = "https://files.pythonhosted.org/packages/8d/be/d1a24ab16cb2537fd372520c78d8596fcb8f644f19e97fd8f0fe68f463d4/fastnanoid-0.4.1-cp39-none-win_amd64.whl", hash = "sha256:43e6890b71682bc610c7782b484f55dd9ac3f7b3c8c341fa90a906215e225379", size = 105862, upload-time = "2024-08-11T13:55:12.426Z" }, + { url = "https://files.pythonhosted.org/packages/9b/61/827cc586b6c4211946d90d9eaa1ec055eba9ae31f71393673c4802113831/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4da9c369ad5d1fba8bc4452bfd8e2f40974087a29d66475d8eec281f0386fee9", size = 234444, upload-time = "2024-08-11T13:53:13.262Z" }, + { url = "https://files.pythonhosted.org/packages/a8/48/cce55a34782bb4ed34292d193f1aba6c3629be92f298011dce16b6dfbd8a/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:359e6f082b348fd37d4e6492f1728948e81758e93de3015bed2a92b58c0c44c3", size = 232612, upload-time = "2024-08-11T13:53:24.532Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f6/e7fea180533649c548f02d0ace16d76305fbea762026c5367d313f047793/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:823067b5cc527597a07fdeb86d50123824b5c6f41c5bf37d6327f956a247784b", size = 261764, upload-time = "2024-08-11T13:53:35.632Z" }, + { url = "https://files.pythonhosted.org/packages/a7/3f/37a5c8b875d07d665dfa53bb1ca67d7dbce9517fe8001e4f676e81126126/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:588722f2d43af6fa16ec9e55b9ea480ce3bc111a1c10757cdd2c148f42d12930", size = 263414, upload-time = "2024-08-11T13:53:47.975Z" }, + { url = "https://files.pythonhosted.org/packages/77/95/3c7acf630d78c82bbdaa12c5a66d7aa508d1b545efb85bbb7d1ac37d0d00/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:927fbe72d03cb705890f880e20240276a22888f8e5a7da1d21d3eefd24348f47", size = 228228, upload-time = "2024-08-11T13:54:07.435Z" }, + { url = "https://files.pythonhosted.org/packages/97/ce/3f5f5924b236d08d155d3bcb794d63a92075033e2b6ecfe17cbf4614815c/fastnanoid-0.4.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0c2b6e3a9cd109154b9a80ae6a38d02550358147f5cf13d166f262af5b62f6b", size = 235934, upload-time = "2024-08-11T13:53:58.51Z" }, + { url = "https://files.pythonhosted.org/packages/a9/cb/3b89fc023f02fe55acbdc4c202050952876c4b118e7caedf034b153d07e2/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:266039637cddf143a07058e139868e3a8ce3108ffcad001cd8c399f260073bec", size = 412662, upload-time = "2024-08-11T13:54:24.75Z" }, + { url = "https://files.pythonhosted.org/packages/4d/47/723cd630704c499fd7e91548c23658cd08c7f6331e5932c489341c319d19/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:b1dc76cdcad24f00a7a427cf00f4f72b23893b19ce41fd2f0916bb6e5ecd8b22", size = 494897, upload-time = "2024-08-11T13:54:37.315Z" }, + { url = "https://files.pythonhosted.org/packages/79/87/a1ddf63fdddc17c63e196b3ab7bf997d588683176efe9e97e9a7a72466f1/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:30911cf3ec13d065bcb1672f624237ad39b8eab57a51fa74ebb99e2765d76b35", size = 416140, upload-time = "2024-08-11T13:54:50.421Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f8/a53cbab4c646f948e7e79100586dddab23cd6ec6e0be02d9a8794c3ba6e8/fastnanoid-0.4.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0897ce9f40ef8483374c16a3a7ecdfe6feb949b420b1e4b69e8359c254020f03", size = 399208, upload-time = "2024-08-11T13:55:01.697Z" }, + { url = "https://files.pythonhosted.org/packages/0e/99/a1bfcfd64fd4b9e8599a634c5f42a7c1ea39d151bcd616c583a95843f041/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dcfee2a516fb701751c52c75c51b9d0b5c0eedac01a032a793e96630ef25b0d", size = 234938, upload-time = "2024-08-11T13:53:16.158Z" }, + { url = "https://files.pythonhosted.org/packages/3a/35/7c7393c06ece7cd27eca843957a71414c66227f1f88249efa78eb6d20e22/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24851db09a54c25fb922096cd6716871bd1f564b1f70f4b04f2ee8f71cd3ecac", size = 233149, upload-time = "2024-08-11T13:53:27.562Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2b/2ae0a3058c775076e36203bf58417422d399cf2f0df49061d5b577de6942/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c7fb33cf414d3120b46c5b72ad64bc51e2b81bbbc11d4f8aee2f8e1e4f5bb26e", size = 262215, upload-time = "2024-08-11T13:53:38.484Z" }, + { url = "https://files.pythonhosted.org/packages/b9/95/d67ea1b364195f579ef6c046af35c967e9a6cc33c227dc7e8c36c6028314/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54518cb82914e2ab2dfaa2ef18d71996f04fa026d7c7e7aa815e37dc442ec796", size = 263468, upload-time = "2024-08-11T13:53:50.661Z" }, + { url = "https://files.pythonhosted.org/packages/a3/a4/c45127919dddef26dfad4a3a6b1d0548d835647bdaf24ec1308f16a2c8db/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16d13f5223ca16e31585fd526c59b05402cf6513a829d5619675badb1dc58424", size = 228442, upload-time = "2024-08-11T13:54:08.851Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/bfa9a24d903f34bbc857246bd388101ef99ed7832efa826e31a4ef4957c0/fastnanoid-0.4.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00dda7a2f34e2d41a6600ae62367472c255573865d294b3941a725ee010c3873", size = 235962, upload-time = "2024-08-11T13:53:59.821Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b8/da79a09b9ebfe7f502e308fe64acd043060988cf8a5d9322cedc5889a4ea/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0a6b9bed15396c2b7e0bc72350c3ee2a0573d47defe95e387bbd592dbe9d5922", size = 412938, upload-time = "2024-08-11T13:54:27.79Z" }, + { url = "https://files.pythonhosted.org/packages/bc/54/d7049f90777bf21de4d5ab74b42cedf213bcdff7f0daa318442f18ebb072/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:e69ce0aa186e5236086b40de3814f0719037d2eed66e04bee2c0116ee4fd5501", size = 495351, upload-time = "2024-08-11T13:54:40.465Z" }, + { url = "https://files.pythonhosted.org/packages/45/03/757a093f34aea99dfa948cd0af82d10196c7b9f2c893fd9c020c9da89ea0/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:e0ab1f5806047e484a64bae131e502bd22b8f1ef740f866adc73c645c8648d1b", size = 416558, upload-time = "2024-08-11T13:54:53.25Z" }, + { url = "https://files.pythonhosted.org/packages/7b/cb/77d820e6050c1e669ef8661f6b94d0f203242a5e20191802140920420e2b/fastnanoid-0.4.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:02f427342dfa025d66253fb5176da1f332dcb2784929bc6f12a4dc0f9b9e203c", size = 399506, upload-time = "2024-08-11T13:55:04.633Z" }, ] [[package]] name = "filelock" version = "3.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075 } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, ] [[package]] @@ -1033,9 +1035,9 @@ dependencies = [ { name = "jinja2" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824 } +sdist = { url = "https://files.pythonhosted.org/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824, upload-time = "2024-11-13T18:24:38.127Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979 }, + { url = "https://files.pythonhosted.org/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979, upload-time = "2024-11-13T18:24:36.135Z" }, ] [[package]] @@ -1049,9 +1051,9 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/09/5c/085bcb872556934bb119e5e09de54daa07873f6866b8f0303c49e72287f7/google_api_core-2.24.2.tar.gz", hash = "sha256:81718493daf06d96d6bc76a91c23874dbf2fac0adbbf542831b805ee6e974696", size = 163516 } +sdist = { url = "https://files.pythonhosted.org/packages/09/5c/085bcb872556934bb119e5e09de54daa07873f6866b8f0303c49e72287f7/google_api_core-2.24.2.tar.gz", hash = "sha256:81718493daf06d96d6bc76a91c23874dbf2fac0adbbf542831b805ee6e974696", size = 163516, upload-time = "2025-03-10T15:55:26.201Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/95/f472d85adab6e538da2025dfca9e976a0d125cc0af2301f190e77b76e51c/google_api_core-2.24.2-py3-none-any.whl", hash = "sha256:810a63ac95f3c441b7c0e43d344e372887f62ce9071ba972eacf32672e072de9", size = 160061 }, + { url = "https://files.pythonhosted.org/packages/46/95/f472d85adab6e538da2025dfca9e976a0d125cc0af2301f190e77b76e51c/google_api_core-2.24.2-py3-none-any.whl", hash = "sha256:810a63ac95f3c441b7c0e43d344e372887f62ce9071ba972eacf32672e072de9", size = 160061, upload-time = "2025-03-10T15:55:24.386Z" }, ] [package.optional-dependencies] @@ -1069,9 +1071,9 @@ dependencies = [ { name = "pyasn1-modules" }, { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cb/8e/8f45c9a32f73e786e954b8f9761c61422955d23c45d1e8c347f9b4b59e8e/google_auth-2.39.0.tar.gz", hash = "sha256:73222d43cdc35a3aeacbfdcaf73142a97839f10de930550d89ebfe1d0a00cde7", size = 274834 } +sdist = { url = "https://files.pythonhosted.org/packages/cb/8e/8f45c9a32f73e786e954b8f9761c61422955d23c45d1e8c347f9b4b59e8e/google_auth-2.39.0.tar.gz", hash = "sha256:73222d43cdc35a3aeacbfdcaf73142a97839f10de930550d89ebfe1d0a00cde7", size = 274834, upload-time = "2025-04-14T17:44:49.402Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/12/ad37a1ef86006d0a0117fc06a4a00bd461c775356b534b425f00dde208ea/google_auth-2.39.0-py2.py3-none-any.whl", hash = "sha256:0150b6711e97fb9f52fe599f55648950cc4540015565d8fbb31be2ad6e1548a2", size = 212319 }, + { url = "https://files.pythonhosted.org/packages/ce/12/ad37a1ef86006d0a0117fc06a4a00bd461c775356b534b425f00dde208ea/google_auth-2.39.0-py2.py3-none-any.whl", hash = "sha256:0150b6711e97fb9f52fe599f55648950cc4540015565d8fbb31be2ad6e1548a2", size = 212319, upload-time = "2025-04-14T17:44:47.699Z" }, ] [[package]] @@ -1087,9 +1089,9 @@ dependencies = [ { name = "python-dateutil" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/73/91/4c7274f4d5faf13ac000b06353deaf3579575bf0e4bbad07fa68b9f09ba9/google_cloud_bigquery-3.31.0.tar.gz", hash = "sha256:b89dc716dbe4abdb7a4f873f7050100287bc98514e0614c5d54cd6a8e9fb0991", size = 479961 } +sdist = { url = "https://files.pythonhosted.org/packages/73/91/4c7274f4d5faf13ac000b06353deaf3579575bf0e4bbad07fa68b9f09ba9/google_cloud_bigquery-3.31.0.tar.gz", hash = "sha256:b89dc716dbe4abdb7a4f873f7050100287bc98514e0614c5d54cd6a8e9fb0991", size = 479961, upload-time = "2025-03-25T18:54:40.43Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/bc/4cb8c61fc6dd817a4a390b745ec7b305f4578f547a16d09d54c8a790624b/google_cloud_bigquery-3.31.0-py3-none-any.whl", hash = "sha256:97f4a3219854ff01d6a3a57312feecb0b6e13062226b823f867e2d3619c4787b", size = 250099 }, + { url = "https://files.pythonhosted.org/packages/e8/bc/4cb8c61fc6dd817a4a390b745ec7b305f4578f547a16d09d54c8a790624b/google_cloud_bigquery-3.31.0-py3-none-any.whl", hash = "sha256:97f4a3219854ff01d6a3a57312feecb0b6e13062226b823f867e2d3619c4787b", size = 250099, upload-time = "2025-03-25T18:54:38.241Z" }, ] [[package]] @@ -1100,14 +1102,14 @@ dependencies = [ { name = "google-api-core" }, { name = "google-auth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d6/b8/2b53838d2acd6ec6168fd284a990c76695e84c65deee79c9f3a4276f6b4f/google_cloud_core-2.4.3.tar.gz", hash = "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53", size = 35861 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/b8/2b53838d2acd6ec6168fd284a990c76695e84c65deee79c9f3a4276f6b4f/google_cloud_core-2.4.3.tar.gz", hash = "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53", size = 35861, upload-time = "2025-03-10T21:05:38.948Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/40/86/bda7241a8da2d28a754aad2ba0f6776e35b67e37c36ae0c45d49370f1014/google_cloud_core-2.4.3-py2.py3-none-any.whl", hash = "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e", size = 29348 }, + { url = "https://files.pythonhosted.org/packages/40/86/bda7241a8da2d28a754aad2ba0f6776e35b67e37c36ae0c45d49370f1014/google_cloud_core-2.4.3-py2.py3-none-any.whl", hash = "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e", size = 29348, upload-time = "2025-03-10T21:05:37.785Z" }, ] [[package]] name = "google-cloud-spanner" -version = "3.53.0" +version = "3.54.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1118,50 +1120,50 @@ dependencies = [ { name = "protobuf" }, { name = "sqlparse" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/27/eb/cef9263b4ac61a9e967d3d6846c4469151160a1cced891791ce1c6ccddee/google_cloud_spanner-3.53.0.tar.gz", hash = "sha256:0c7be3134b74928cf928d1f73b58c722fc2014346de1240a0cc8ffdd3222f606", size = 659445 } +sdist = { url = "https://files.pythonhosted.org/packages/4a/51/2d0c58b3a873b962192f7d2a293934b8623a2fc4dc3010d0cae67f0bea27/google_cloud_spanner-3.54.0.tar.gz", hash = "sha256:eef44f1207d6fae52819099cadfb225a19596e6551216831de6cbc245725efe4", size = 666352, upload-time = "2025-04-28T20:19:41.204Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/96/52997fc187611a2cf0c64df747fa70ffc0b469f0a367f39bdd078c43db52/google_cloud_spanner-3.53.0-py2.py3-none-any.whl", hash = "sha256:be863394521b44df3c5a118c00c4b7c978d4437adb49e359e39b3d76362a7e60", size = 483101 }, + { url = "https://files.pythonhosted.org/packages/1a/9a/e20a2d5c77832ff3301b5478f4c9fd85ddf99652dbea58f9d3950ccf79c0/google_cloud_spanner-3.54.0-py2.py3-none-any.whl", hash = "sha256:81987b3fc7d9930e03f51bcb6c6567db62838b00bdfa82aeb708584f0536fc0c", size = 485297, upload-time = "2025-04-28T20:19:39.003Z" }, ] [[package]] name = "google-crc32c" version = "1.7.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/ae/87802e6d9f9d69adfaedfcfd599266bf386a54d0be058b532d04c794f76d/google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472", size = 14495 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/69/b1b05cf415df0d86691d6a8b4b7e60ab3a6fb6efb783ee5cd3ed1382bfd3/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:b07d48faf8292b4db7c3d64ab86f950c2e94e93a11fd47271c28ba458e4a0d76", size = 30467 }, - { url = "https://files.pythonhosted.org/packages/44/3d/92f8928ecd671bd5b071756596971c79d252d09b835cdca5a44177fa87aa/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7cc81b3a2fbd932a4313eb53cc7d9dde424088ca3a0337160f35d91826880c1d", size = 30311 }, - { url = "https://files.pythonhosted.org/packages/33/42/c2d15a73df79d45ed6b430b9e801d0bd8e28ac139a9012d7d58af50a385d/google_crc32c-1.7.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c67ca0a1f5b56162951a9dae987988679a7db682d6f97ce0f6381ebf0fbea4c", size = 37889 }, - { url = "https://files.pythonhosted.org/packages/57/ea/ac59c86a3c694afd117bb669bde32aaf17d0de4305d01d706495f09cbf19/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc5319db92daa516b653600794d5b9f9439a9a121f3e162f94b0e1891c7933cb", size = 33028 }, - { url = "https://files.pythonhosted.org/packages/60/44/87e77e8476767a4a93f6cf271157c6d948eacec63688c093580af13b04be/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcdf5a64adb747610140572ed18d011896e3b9ae5195f2514b7ff678c80f1603", size = 38026 }, - { url = "https://files.pythonhosted.org/packages/c8/bf/21ac7bb305cd7c1a6de9c52f71db0868e104a5b573a4977cd9d0ff830f82/google_crc32c-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:754561c6c66e89d55754106739e22fdaa93fafa8da7221b29c8b8e8270c6ec8a", size = 33476 }, - { url = "https://files.pythonhosted.org/packages/f7/94/220139ea87822b6fdfdab4fb9ba81b3fff7ea2c82e2af34adc726085bffc/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6fbab4b935989e2c3610371963ba1b86afb09537fd0c633049be82afe153ac06", size = 30468 }, - { url = "https://files.pythonhosted.org/packages/94/97/789b23bdeeb9d15dc2904660463ad539d0318286d7633fe2760c10ed0c1c/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ed66cbe1ed9cbaaad9392b5259b3eba4a9e565420d734e6238813c428c3336c9", size = 30313 }, - { url = "https://files.pythonhosted.org/packages/81/b8/976a2b843610c211e7ccb3e248996a61e87dbb2c09b1499847e295080aec/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6547b657621b6cbed3562ea7826c3e11cab01cd33b74e1f677690652883e77", size = 33048 }, - { url = "https://files.pythonhosted.org/packages/c9/16/a3842c2cf591093b111d4a5e2bfb478ac6692d02f1b386d2a33283a19dc9/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68e17bad8f7dd9a49181a1f5a8f4b251c6dbc8cc96fb79f1d321dfd57d66f53", size = 32669 }, - { url = "https://files.pythonhosted.org/packages/04/17/ed9aba495916fcf5fe4ecb2267ceb851fc5f273c4e4625ae453350cfd564/google_crc32c-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:6335de12921f06e1f774d0dd1fbea6bf610abe0887a1638f64d694013138be5d", size = 33476 }, - { url = "https://files.pythonhosted.org/packages/dd/b7/787e2453cf8639c94b3d06c9d61f512234a82e1d12d13d18584bd3049904/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2d73a68a653c57281401871dd4aeebbb6af3191dcac751a76ce430df4d403194", size = 30470 }, - { url = "https://files.pythonhosted.org/packages/ed/b4/6042c2b0cbac3ec3a69bb4c49b28d2f517b7a0f4a0232603c42c58e22b44/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:22beacf83baaf59f9d3ab2bbb4db0fb018da8e5aebdce07ef9f09fce8220285e", size = 30315 }, - { url = "https://files.pythonhosted.org/packages/29/ad/01e7a61a5d059bc57b702d9ff6a18b2585ad97f720bd0a0dbe215df1ab0e/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19eafa0e4af11b0a4eb3974483d55d2d77ad1911e6cf6f832e1574f6781fd337", size = 33180 }, - { url = "https://files.pythonhosted.org/packages/3b/a5/7279055cf004561894ed3a7bfdf5bf90a53f28fadd01af7cd166e88ddf16/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d86616faaea68101195c6bdc40c494e4d76f41e07a37ffdef270879c15fb65", size = 32794 }, - { url = "https://files.pythonhosted.org/packages/0f/d6/77060dbd140c624e42ae3ece3df53b9d811000729a5c821b9fd671ceaac6/google_crc32c-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:b7491bdc0c7564fcf48c0179d2048ab2f7c7ba36b84ccd3a3e1c3f7a72d3bba6", size = 33477 }, - { url = "https://files.pythonhosted.org/packages/8b/72/b8d785e9184ba6297a8620c8a37cf6e39b81a8ca01bb0796d7cbb28b3386/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:df8b38bdaf1629d62d51be8bdd04888f37c451564c2042d36e5812da9eff3c35", size = 30467 }, - { url = "https://files.pythonhosted.org/packages/34/25/5f18076968212067c4e8ea95bf3b69669f9fc698476e5f5eb97d5b37999f/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:e42e20a83a29aa2709a0cf271c7f8aefaa23b7ab52e53b322585297bb94d4638", size = 30309 }, - { url = "https://files.pythonhosted.org/packages/92/83/9228fe65bf70e93e419f38bdf6c5ca5083fc6d32886ee79b450ceefd1dbd/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:905a385140bf492ac300026717af339790921f411c0dfd9aa5a9e69a08ed32eb", size = 33133 }, - { url = "https://files.pythonhosted.org/packages/c3/ca/1ea2fd13ff9f8955b85e7956872fdb7050c4ace8a2306a6d177edb9cf7fe/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b211ddaf20f7ebeec5c333448582c224a7c90a9d98826fbab82c0ddc11348e6", size = 32773 }, - { url = "https://files.pythonhosted.org/packages/89/32/a22a281806e3ef21b72db16f948cad22ec68e4bdd384139291e00ff82fe2/google_crc32c-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:0f99eaa09a9a7e642a61e06742856eec8b19fc0037832e03f941fe7cf0c8e4db", size = 33475 }, - { url = "https://files.pythonhosted.org/packages/b8/c5/002975aff514e57fc084ba155697a049b3f9b52225ec3bc0f542871dd524/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d1da0d74ec5634a05f53ef7df18fc646666a25efaaca9fc7dcfd4caf1d98c3", size = 33243 }, - { url = "https://files.pythonhosted.org/packages/61/cb/c585282a03a0cea70fcaa1bf55d5d702d0f2351094d663ec3be1c6c67c52/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10554d4abc5238823112c2ad7e4560f96c7bf3820b202660373d769d9e6e4c9", size = 32870 }, - { url = "https://files.pythonhosted.org/packages/e3/89/940d170a9f24e6e711666a7c5596561358243023b4060869d9adae97a762/google_crc32c-1.7.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:9fc196f0b8d8bd2789352c6a522db03f89e83a0ed6b64315923c396d7a932315", size = 30462 }, - { url = "https://files.pythonhosted.org/packages/42/0c/22bebe2517368e914a63e5378aab74e2b6357eb739d94b6bc0e830979a37/google_crc32c-1.7.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb5e35dcd8552f76eed9461a23de1030920a3c953c1982f324be8f97946e7127", size = 30304 }, - { url = "https://files.pythonhosted.org/packages/36/32/2daf4c46f875aaa3a057ecc8569406979cb29fb1e2389e4f2570d8ed6a5c/google_crc32c-1.7.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2226b6a8da04f1d9e61d3e357f2460b9551c5e6950071437e122c958a18ae14", size = 37734 }, - { url = "https://files.pythonhosted.org/packages/76/b5/b3e220b68d5d265c4aacd2878301fdb2df72715c45ba49acc19f310d4555/google_crc32c-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f2b3522222746fff0e04a9bd0a23ea003ba3cccc8cf21385c564deb1f223242", size = 32869 }, - { url = "https://files.pythonhosted.org/packages/0a/90/2931c3c8d2de1e7cde89945d3ceb2c4258a1f23f0c22c3c1c921c3c026a6/google_crc32c-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bda0fcb632d390e3ea8b6b07bf6b4f4a66c9d02dcd6fbf7ba00a197c143f582", size = 37875 }, - { url = "https://files.pythonhosted.org/packages/30/9e/0aaed8a209ea6fa4b50f66fed2d977f05c6c799e10bb509f5523a5a5c90c/google_crc32c-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:713121af19f1a617054c41f952294764e0c5443d5a5d9034b2cd60f5dd7e0349", size = 33471 }, - { url = "https://files.pythonhosted.org/packages/0b/43/31e57ce04530794917dfe25243860ec141de9fadf4aa9783dffe7dac7c39/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8e9afc74168b0b2232fb32dd202c93e46b7d5e4bf03e66ba5dc273bb3559589", size = 28242 }, - { url = "https://files.pythonhosted.org/packages/eb/f3/8b84cd4e0ad111e63e30eb89453f8dd308e3ad36f42305cf8c202461cdf0/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa8136cc14dd27f34a3221c0f16fd42d8a40e4778273e61a3c19aedaa44daf6b", size = 28049 }, - { url = "https://files.pythonhosted.org/packages/16/1b/1693372bf423ada422f80fd88260dbfd140754adb15cbc4d7e9a68b1cb8e/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85fef7fae11494e747c9fd1359a527e5970fc9603c90764843caabd3a16a0a48", size = 28241 }, - { url = "https://files.pythonhosted.org/packages/fd/3c/2a19a60a473de48717b4efb19398c3f914795b64a96cf3fbe82588044f78/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6efb97eb4369d52593ad6f75e7e10d053cf00c48983f7a973105bc70b0ac4d82", size = 28048 }, +sdist = { url = "https://files.pythonhosted.org/packages/19/ae/87802e6d9f9d69adfaedfcfd599266bf386a54d0be058b532d04c794f76d/google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472", size = 14495, upload-time = "2025-03-26T14:29:13.32Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/69/b1b05cf415df0d86691d6a8b4b7e60ab3a6fb6efb783ee5cd3ed1382bfd3/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:b07d48faf8292b4db7c3d64ab86f950c2e94e93a11fd47271c28ba458e4a0d76", size = 30467, upload-time = "2025-03-26T14:31:11.92Z" }, + { url = "https://files.pythonhosted.org/packages/44/3d/92f8928ecd671bd5b071756596971c79d252d09b835cdca5a44177fa87aa/google_crc32c-1.7.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7cc81b3a2fbd932a4313eb53cc7d9dde424088ca3a0337160f35d91826880c1d", size = 30311, upload-time = "2025-03-26T14:53:14.161Z" }, + { url = "https://files.pythonhosted.org/packages/33/42/c2d15a73df79d45ed6b430b9e801d0bd8e28ac139a9012d7d58af50a385d/google_crc32c-1.7.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c67ca0a1f5b56162951a9dae987988679a7db682d6f97ce0f6381ebf0fbea4c", size = 37889, upload-time = "2025-03-26T14:41:27.83Z" }, + { url = "https://files.pythonhosted.org/packages/57/ea/ac59c86a3c694afd117bb669bde32aaf17d0de4305d01d706495f09cbf19/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc5319db92daa516b653600794d5b9f9439a9a121f3e162f94b0e1891c7933cb", size = 33028, upload-time = "2025-03-26T14:41:29.141Z" }, + { url = "https://files.pythonhosted.org/packages/60/44/87e77e8476767a4a93f6cf271157c6d948eacec63688c093580af13b04be/google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcdf5a64adb747610140572ed18d011896e3b9ae5195f2514b7ff678c80f1603", size = 38026, upload-time = "2025-03-26T14:41:29.921Z" }, + { url = "https://files.pythonhosted.org/packages/c8/bf/21ac7bb305cd7c1a6de9c52f71db0868e104a5b573a4977cd9d0ff830f82/google_crc32c-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:754561c6c66e89d55754106739e22fdaa93fafa8da7221b29c8b8e8270c6ec8a", size = 33476, upload-time = "2025-03-26T14:29:09.086Z" }, + { url = "https://files.pythonhosted.org/packages/f7/94/220139ea87822b6fdfdab4fb9ba81b3fff7ea2c82e2af34adc726085bffc/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6fbab4b935989e2c3610371963ba1b86afb09537fd0c633049be82afe153ac06", size = 30468, upload-time = "2025-03-26T14:32:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/94/97/789b23bdeeb9d15dc2904660463ad539d0318286d7633fe2760c10ed0c1c/google_crc32c-1.7.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ed66cbe1ed9cbaaad9392b5259b3eba4a9e565420d734e6238813c428c3336c9", size = 30313, upload-time = "2025-03-26T14:57:38.758Z" }, + { url = "https://files.pythonhosted.org/packages/81/b8/976a2b843610c211e7ccb3e248996a61e87dbb2c09b1499847e295080aec/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6547b657621b6cbed3562ea7826c3e11cab01cd33b74e1f677690652883e77", size = 33048, upload-time = "2025-03-26T14:41:30.679Z" }, + { url = "https://files.pythonhosted.org/packages/c9/16/a3842c2cf591093b111d4a5e2bfb478ac6692d02f1b386d2a33283a19dc9/google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68e17bad8f7dd9a49181a1f5a8f4b251c6dbc8cc96fb79f1d321dfd57d66f53", size = 32669, upload-time = "2025-03-26T14:41:31.432Z" }, + { url = "https://files.pythonhosted.org/packages/04/17/ed9aba495916fcf5fe4ecb2267ceb851fc5f273c4e4625ae453350cfd564/google_crc32c-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:6335de12921f06e1f774d0dd1fbea6bf610abe0887a1638f64d694013138be5d", size = 33476, upload-time = "2025-03-26T14:29:10.211Z" }, + { url = "https://files.pythonhosted.org/packages/dd/b7/787e2453cf8639c94b3d06c9d61f512234a82e1d12d13d18584bd3049904/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2d73a68a653c57281401871dd4aeebbb6af3191dcac751a76ce430df4d403194", size = 30470, upload-time = "2025-03-26T14:34:31.655Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b4/6042c2b0cbac3ec3a69bb4c49b28d2f517b7a0f4a0232603c42c58e22b44/google_crc32c-1.7.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:22beacf83baaf59f9d3ab2bbb4db0fb018da8e5aebdce07ef9f09fce8220285e", size = 30315, upload-time = "2025-03-26T15:01:54.634Z" }, + { url = "https://files.pythonhosted.org/packages/29/ad/01e7a61a5d059bc57b702d9ff6a18b2585ad97f720bd0a0dbe215df1ab0e/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19eafa0e4af11b0a4eb3974483d55d2d77ad1911e6cf6f832e1574f6781fd337", size = 33180, upload-time = "2025-03-26T14:41:32.168Z" }, + { url = "https://files.pythonhosted.org/packages/3b/a5/7279055cf004561894ed3a7bfdf5bf90a53f28fadd01af7cd166e88ddf16/google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d86616faaea68101195c6bdc40c494e4d76f41e07a37ffdef270879c15fb65", size = 32794, upload-time = "2025-03-26T14:41:33.264Z" }, + { url = "https://files.pythonhosted.org/packages/0f/d6/77060dbd140c624e42ae3ece3df53b9d811000729a5c821b9fd671ceaac6/google_crc32c-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:b7491bdc0c7564fcf48c0179d2048ab2f7c7ba36b84ccd3a3e1c3f7a72d3bba6", size = 33477, upload-time = "2025-03-26T14:29:10.94Z" }, + { url = "https://files.pythonhosted.org/packages/8b/72/b8d785e9184ba6297a8620c8a37cf6e39b81a8ca01bb0796d7cbb28b3386/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:df8b38bdaf1629d62d51be8bdd04888f37c451564c2042d36e5812da9eff3c35", size = 30467, upload-time = "2025-03-26T14:36:06.909Z" }, + { url = "https://files.pythonhosted.org/packages/34/25/5f18076968212067c4e8ea95bf3b69669f9fc698476e5f5eb97d5b37999f/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:e42e20a83a29aa2709a0cf271c7f8aefaa23b7ab52e53b322585297bb94d4638", size = 30309, upload-time = "2025-03-26T15:06:15.318Z" }, + { url = "https://files.pythonhosted.org/packages/92/83/9228fe65bf70e93e419f38bdf6c5ca5083fc6d32886ee79b450ceefd1dbd/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:905a385140bf492ac300026717af339790921f411c0dfd9aa5a9e69a08ed32eb", size = 33133, upload-time = "2025-03-26T14:41:34.388Z" }, + { url = "https://files.pythonhosted.org/packages/c3/ca/1ea2fd13ff9f8955b85e7956872fdb7050c4ace8a2306a6d177edb9cf7fe/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b211ddaf20f7ebeec5c333448582c224a7c90a9d98826fbab82c0ddc11348e6", size = 32773, upload-time = "2025-03-26T14:41:35.19Z" }, + { url = "https://files.pythonhosted.org/packages/89/32/a22a281806e3ef21b72db16f948cad22ec68e4bdd384139291e00ff82fe2/google_crc32c-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:0f99eaa09a9a7e642a61e06742856eec8b19fc0037832e03f941fe7cf0c8e4db", size = 33475, upload-time = "2025-03-26T14:29:11.771Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c5/002975aff514e57fc084ba155697a049b3f9b52225ec3bc0f542871dd524/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d1da0d74ec5634a05f53ef7df18fc646666a25efaaca9fc7dcfd4caf1d98c3", size = 33243, upload-time = "2025-03-26T14:41:35.975Z" }, + { url = "https://files.pythonhosted.org/packages/61/cb/c585282a03a0cea70fcaa1bf55d5d702d0f2351094d663ec3be1c6c67c52/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10554d4abc5238823112c2ad7e4560f96c7bf3820b202660373d769d9e6e4c9", size = 32870, upload-time = "2025-03-26T14:41:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/e3/89/940d170a9f24e6e711666a7c5596561358243023b4060869d9adae97a762/google_crc32c-1.7.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:9fc196f0b8d8bd2789352c6a522db03f89e83a0ed6b64315923c396d7a932315", size = 30462, upload-time = "2025-03-26T14:29:25.969Z" }, + { url = "https://files.pythonhosted.org/packages/42/0c/22bebe2517368e914a63e5378aab74e2b6357eb739d94b6bc0e830979a37/google_crc32c-1.7.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb5e35dcd8552f76eed9461a23de1030920a3c953c1982f324be8f97946e7127", size = 30304, upload-time = "2025-03-26T14:49:16.642Z" }, + { url = "https://files.pythonhosted.org/packages/36/32/2daf4c46f875aaa3a057ecc8569406979cb29fb1e2389e4f2570d8ed6a5c/google_crc32c-1.7.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2226b6a8da04f1d9e61d3e357f2460b9551c5e6950071437e122c958a18ae14", size = 37734, upload-time = "2025-03-26T14:41:37.88Z" }, + { url = "https://files.pythonhosted.org/packages/76/b5/b3e220b68d5d265c4aacd2878301fdb2df72715c45ba49acc19f310d4555/google_crc32c-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f2b3522222746fff0e04a9bd0a23ea003ba3cccc8cf21385c564deb1f223242", size = 32869, upload-time = "2025-03-26T14:41:38.965Z" }, + { url = "https://files.pythonhosted.org/packages/0a/90/2931c3c8d2de1e7cde89945d3ceb2c4258a1f23f0c22c3c1c921c3c026a6/google_crc32c-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bda0fcb632d390e3ea8b6b07bf6b4f4a66c9d02dcd6fbf7ba00a197c143f582", size = 37875, upload-time = "2025-03-26T14:41:41.732Z" }, + { url = "https://files.pythonhosted.org/packages/30/9e/0aaed8a209ea6fa4b50f66fed2d977f05c6c799e10bb509f5523a5a5c90c/google_crc32c-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:713121af19f1a617054c41f952294764e0c5443d5a5d9034b2cd60f5dd7e0349", size = 33471, upload-time = "2025-03-26T14:29:12.578Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/31e57ce04530794917dfe25243860ec141de9fadf4aa9783dffe7dac7c39/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8e9afc74168b0b2232fb32dd202c93e46b7d5e4bf03e66ba5dc273bb3559589", size = 28242, upload-time = "2025-03-26T14:41:42.858Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f3/8b84cd4e0ad111e63e30eb89453f8dd308e3ad36f42305cf8c202461cdf0/google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa8136cc14dd27f34a3221c0f16fd42d8a40e4778273e61a3c19aedaa44daf6b", size = 28049, upload-time = "2025-03-26T14:41:44.651Z" }, + { url = "https://files.pythonhosted.org/packages/16/1b/1693372bf423ada422f80fd88260dbfd140754adb15cbc4d7e9a68b1cb8e/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85fef7fae11494e747c9fd1359a527e5970fc9603c90764843caabd3a16a0a48", size = 28241, upload-time = "2025-03-26T14:41:45.898Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3c/2a19a60a473de48717b4efb19398c3f914795b64a96cf3fbe82588044f78/google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6efb97eb4369d52593ad6f75e7e10d053cf00c48983f7a973105bc70b0ac4d82", size = 28048, upload-time = "2025-03-26T14:41:46.696Z" }, ] [[package]] @@ -1171,9 +1173,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-crc32c" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/5a/0efdc02665dca14e0837b62c8a1a93132c264bd02054a15abb2218afe0ae/google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0", size = 2163099 } +sdist = { url = "https://files.pythonhosted.org/packages/58/5a/0efdc02665dca14e0837b62c8a1a93132c264bd02054a15abb2218afe0ae/google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0", size = 2163099, upload-time = "2024-08-07T22:20:38.555Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/35/b8d3baf8c46695858cb9d8835a53baa1eeb9906ddaf2f728a5f5b640fd1e/google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa", size = 81251 }, + { url = "https://files.pythonhosted.org/packages/82/35/b8d3baf8c46695858cb9d8835a53baa1eeb9906ddaf2f728a5f5b640fd1e/google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa", size = 81251, upload-time = "2024-08-07T22:20:36.409Z" }, ] [[package]] @@ -1183,9 +1185,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903 } +sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903, upload-time = "2025-04-14T10:17:02.924Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530 }, + { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" }, ] [package.optional-dependencies] @@ -1202,9 +1204,9 @@ dependencies = [ { name = "grpcio" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/4e/8d0ca3b035e41fe0b3f31ebbb638356af720335e5a11154c330169b40777/grpc_google_iam_v1-0.14.2.tar.gz", hash = "sha256:b3e1fc387a1a329e41672197d0ace9de22c78dd7d215048c4c78712073f7bd20", size = 16259 } +sdist = { url = "https://files.pythonhosted.org/packages/b9/4e/8d0ca3b035e41fe0b3f31ebbb638356af720335e5a11154c330169b40777/grpc_google_iam_v1-0.14.2.tar.gz", hash = "sha256:b3e1fc387a1a329e41672197d0ace9de22c78dd7d215048c4c78712073f7bd20", size = 16259, upload-time = "2025-03-17T11:40:23.586Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/66/6f/dd9b178aee7835b96c2e63715aba6516a9d50f6bebbd1cc1d32c82a2a6c3/grpc_google_iam_v1-0.14.2-py3-none-any.whl", hash = "sha256:a3171468459770907926d56a440b2bb643eec1d7ba215f48f3ecece42b4d8351", size = 19242 }, + { url = "https://files.pythonhosted.org/packages/66/6f/dd9b178aee7835b96c2e63715aba6516a9d50f6bebbd1cc1d32c82a2a6c3/grpc_google_iam_v1-0.14.2-py3-none-any.whl", hash = "sha256:a3171468459770907926d56a440b2bb643eec1d7ba215f48f3ecece42b4d8351", size = 19242, upload-time = "2025-03-17T11:40:22.648Z" }, ] [[package]] @@ -1214,67 +1216,67 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "grpcio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/28/57449d5567adf4c1d3e216aaca545913fbc21a915f2da6790d6734aac76e/grpc-interceptor-0.15.4.tar.gz", hash = "sha256:1f45c0bcb58b6f332f37c637632247c9b02bc6af0fdceb7ba7ce8d2ebbfb0926", size = 19322 } +sdist = { url = "https://files.pythonhosted.org/packages/9f/28/57449d5567adf4c1d3e216aaca545913fbc21a915f2da6790d6734aac76e/grpc-interceptor-0.15.4.tar.gz", hash = "sha256:1f45c0bcb58b6f332f37c637632247c9b02bc6af0fdceb7ba7ce8d2ebbfb0926", size = 19322, upload-time = "2023-11-16T02:05:42.459Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/15/ac/8d53f230a7443401ce81791ec50a3b0e54924bf615ad287654fa4a2f5cdc/grpc_interceptor-0.15.4-py3-none-any.whl", hash = "sha256:0035f33228693ed3767ee49d937bac424318db173fef4d2d0170b3215f254d9d", size = 20848 }, + { url = "https://files.pythonhosted.org/packages/15/ac/8d53f230a7443401ce81791ec50a3b0e54924bf615ad287654fa4a2f5cdc/grpc_interceptor-0.15.4-py3-none-any.whl", hash = "sha256:0035f33228693ed3767ee49d937bac424318db173fef4d2d0170b3215f254d9d", size = 20848, upload-time = "2023-11-16T02:05:40.913Z" }, ] [[package]] name = "grpcio" version = "1.71.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1c/95/aa11fc09a85d91fbc7dd405dcb2a1e0256989d67bf89fa65ae24b3ba105a/grpcio-1.71.0.tar.gz", hash = "sha256:2b85f7820475ad3edec209d3d89a7909ada16caab05d3f2e08a7e8ae3200a55c", size = 12549828 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/c5/ef610b3f988cc0cc67b765f72b8e2db06a1db14e65acb5ae7810a6b7042e/grpcio-1.71.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:c200cb6f2393468142eb50ab19613229dcc7829b5ccee8b658a36005f6669fdd", size = 5210643 }, - { url = "https://files.pythonhosted.org/packages/bf/de/c84293c961622df302c0d5d07ec6e2d4cd3874ea42f602be2df09c4ad44f/grpcio-1.71.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b2266862c5ad664a380fbbcdbdb8289d71464c42a8c29053820ee78ba0119e5d", size = 11308962 }, - { url = "https://files.pythonhosted.org/packages/7c/38/04c9e0dc8c904570c80faa1f1349b190b63e45d6b2782ec8567b050efa9d/grpcio-1.71.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0ab8b2864396663a5b0b0d6d79495657ae85fa37dcb6498a2669d067c65c11ea", size = 5699236 }, - { url = "https://files.pythonhosted.org/packages/95/96/e7be331d1298fa605ea7c9ceafc931490edd3d5b33c4f695f1a0667f3491/grpcio-1.71.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c30f393f9d5ff00a71bb56de4aa75b8fe91b161aeb61d39528db6b768d7eac69", size = 6339767 }, - { url = "https://files.pythonhosted.org/packages/5d/b7/7e7b7bb6bb18baf156fd4f2f5b254150dcdd6cbf0def1ee427a2fb2bfc4d/grpcio-1.71.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f250ff44843d9a0615e350c77f890082102a0318d66a99540f54769c8766ab73", size = 5943028 }, - { url = "https://files.pythonhosted.org/packages/13/aa/5fb756175995aeb47238d706530772d9a7ac8e73bcca1b47dc145d02c95f/grpcio-1.71.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6d8de076528f7c43a2f576bc311799f89d795aa6c9b637377cc2b1616473804", size = 6031841 }, - { url = "https://files.pythonhosted.org/packages/54/93/172783e01eed61f7f180617b7fa4470f504e383e32af2587f664576a7101/grpcio-1.71.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b91879d6da1605811ebc60d21ab6a7e4bae6c35f6b63a061d61eb818c8168f6", size = 6651039 }, - { url = "https://files.pythonhosted.org/packages/6f/99/62654b220a27ed46d3313252214f4bc66261143dc9b58004085cd0646753/grpcio-1.71.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f71574afdf944e6652203cd1badcda195b2a27d9c83e6d88dc1ce3cfb73b31a5", size = 6198465 }, - { url = "https://files.pythonhosted.org/packages/68/35/96116de833b330abe4412cc94edc68f99ed2fa3e39d8713ff307b3799e81/grpcio-1.71.0-cp310-cp310-win32.whl", hash = "sha256:8997d6785e93308f277884ee6899ba63baafa0dfb4729748200fcc537858a509", size = 3620382 }, - { url = "https://files.pythonhosted.org/packages/b7/09/f32ef637e386f3f2c02effac49699229fa560ce9007682d24e9e212d2eb4/grpcio-1.71.0-cp310-cp310-win_amd64.whl", hash = "sha256:7d6ac9481d9d0d129224f6d5934d5832c4b1cddb96b59e7eba8416868909786a", size = 4280302 }, - { url = "https://files.pythonhosted.org/packages/63/04/a085f3ad4133426f6da8c1becf0749872a49feb625a407a2e864ded3fb12/grpcio-1.71.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:d6aa986318c36508dc1d5001a3ff169a15b99b9f96ef5e98e13522c506b37eef", size = 5210453 }, - { url = "https://files.pythonhosted.org/packages/b4/d5/0bc53ed33ba458de95020970e2c22aa8027b26cc84f98bea7fcad5d695d1/grpcio-1.71.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:d2c170247315f2d7e5798a22358e982ad6eeb68fa20cf7a820bb74c11f0736e7", size = 11347567 }, - { url = "https://files.pythonhosted.org/packages/e3/6d/ce334f7e7a58572335ccd61154d808fe681a4c5e951f8a1ff68f5a6e47ce/grpcio-1.71.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e6f83a583ed0a5b08c5bc7a3fe860bb3c2eac1f03f1f63e0bc2091325605d2b7", size = 5696067 }, - { url = "https://files.pythonhosted.org/packages/05/4a/80befd0b8b1dc2b9ac5337e57473354d81be938f87132e147c4a24a581bd/grpcio-1.71.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be74ddeeb92cc87190e0e376dbc8fc7736dbb6d3d454f2fa1f5be1dee26b9d7", size = 6348377 }, - { url = "https://files.pythonhosted.org/packages/c7/67/cbd63c485051eb78663355d9efd1b896cfb50d4a220581ec2cb9a15cd750/grpcio-1.71.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd0dfbe4d5eb1fcfec9490ca13f82b089a309dc3678e2edabc144051270a66e", size = 5940407 }, - { url = "https://files.pythonhosted.org/packages/98/4b/7a11aa4326d7faa499f764eaf8a9b5a0eb054ce0988ee7ca34897c2b02ae/grpcio-1.71.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a2242d6950dc892afdf9e951ed7ff89473aaf744b7d5727ad56bdaace363722b", size = 6030915 }, - { url = "https://files.pythonhosted.org/packages/eb/a2/cdae2d0e458b475213a011078b0090f7a1d87f9a68c678b76f6af7c6ac8c/grpcio-1.71.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0fa05ee31a20456b13ae49ad2e5d585265f71dd19fbd9ef983c28f926d45d0a7", size = 6648324 }, - { url = "https://files.pythonhosted.org/packages/27/df/f345c8daaa8d8574ce9869f9b36ca220c8845923eb3087e8f317eabfc2a8/grpcio-1.71.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3d081e859fb1ebe176de33fc3adb26c7d46b8812f906042705346b314bde32c3", size = 6197839 }, - { url = "https://files.pythonhosted.org/packages/f2/2c/cd488dc52a1d0ae1bad88b0d203bc302efbb88b82691039a6d85241c5781/grpcio-1.71.0-cp311-cp311-win32.whl", hash = "sha256:d6de81c9c00c8a23047136b11794b3584cdc1460ed7cbc10eada50614baa1444", size = 3619978 }, - { url = "https://files.pythonhosted.org/packages/ee/3f/cf92e7e62ccb8dbdf977499547dfc27133124d6467d3a7d23775bcecb0f9/grpcio-1.71.0-cp311-cp311-win_amd64.whl", hash = "sha256:24e867651fc67717b6f896d5f0cac0ec863a8b5fb7d6441c2ab428f52c651c6b", size = 4282279 }, - { url = "https://files.pythonhosted.org/packages/4c/83/bd4b6a9ba07825bd19c711d8b25874cd5de72c2a3fbf635c3c344ae65bd2/grpcio-1.71.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:0ff35c8d807c1c7531d3002be03221ff9ae15712b53ab46e2a0b4bb271f38537", size = 5184101 }, - { url = "https://files.pythonhosted.org/packages/31/ea/2e0d90c0853568bf714693447f5c73272ea95ee8dad107807fde740e595d/grpcio-1.71.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:b78a99cd1ece4be92ab7c07765a0b038194ded2e0a26fd654591ee136088d8d7", size = 11310927 }, - { url = "https://files.pythonhosted.org/packages/ac/bc/07a3fd8af80467390af491d7dc66882db43884128cdb3cc8524915e0023c/grpcio-1.71.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc1a1231ed23caac1de9f943d031f1bc38d0f69d2a3b243ea0d664fc1fbd7fec", size = 5654280 }, - { url = "https://files.pythonhosted.org/packages/16/af/21f22ea3eed3d0538b6ef7889fce1878a8ba4164497f9e07385733391e2b/grpcio-1.71.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6beeea5566092c5e3c4896c6d1d307fb46b1d4bdf3e70c8340b190a69198594", size = 6312051 }, - { url = "https://files.pythonhosted.org/packages/49/9d/e12ddc726dc8bd1aa6cba67c85ce42a12ba5b9dd75d5042214a59ccf28ce/grpcio-1.71.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5170929109450a2c031cfe87d6716f2fae39695ad5335d9106ae88cc32dc84c", size = 5910666 }, - { url = "https://files.pythonhosted.org/packages/d9/e9/38713d6d67aedef738b815763c25f092e0454dc58e77b1d2a51c9d5b3325/grpcio-1.71.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5b08d03ace7aca7b2fadd4baf291139b4a5f058805a8327bfe9aece7253b6d67", size = 6012019 }, - { url = "https://files.pythonhosted.org/packages/80/da/4813cd7adbae6467724fa46c952d7aeac5e82e550b1c62ed2aeb78d444ae/grpcio-1.71.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f903017db76bf9cc2b2d8bdd37bf04b505bbccad6be8a81e1542206875d0e9db", size = 6637043 }, - { url = "https://files.pythonhosted.org/packages/52/ca/c0d767082e39dccb7985c73ab4cf1d23ce8613387149e9978c70c3bf3b07/grpcio-1.71.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:469f42a0b410883185eab4689060a20488a1a0a00f8bbb3cbc1061197b4c5a79", size = 6186143 }, - { url = "https://files.pythonhosted.org/packages/00/61/7b2c8ec13303f8fe36832c13d91ad4d4ba57204b1c723ada709c346b2271/grpcio-1.71.0-cp312-cp312-win32.whl", hash = "sha256:ad9f30838550695b5eb302add33f21f7301b882937460dd24f24b3cc5a95067a", size = 3604083 }, - { url = "https://files.pythonhosted.org/packages/fd/7c/1e429c5fb26122055d10ff9a1d754790fb067d83c633ff69eddcf8e3614b/grpcio-1.71.0-cp312-cp312-win_amd64.whl", hash = "sha256:652350609332de6dac4ece254e5d7e1ff834e203d6afb769601f286886f6f3a8", size = 4272191 }, - { url = "https://files.pythonhosted.org/packages/04/dd/b00cbb45400d06b26126dcfdbdb34bb6c4f28c3ebbd7aea8228679103ef6/grpcio-1.71.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:cebc1b34ba40a312ab480ccdb396ff3c529377a2fce72c45a741f7215bfe8379", size = 5184138 }, - { url = "https://files.pythonhosted.org/packages/ed/0a/4651215983d590ef53aac40ba0e29dda941a02b097892c44fa3357e706e5/grpcio-1.71.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:85da336e3649a3d2171e82f696b5cad2c6231fdd5bad52616476235681bee5b3", size = 11310747 }, - { url = "https://files.pythonhosted.org/packages/57/a3/149615b247f321e13f60aa512d3509d4215173bdb982c9098d78484de216/grpcio-1.71.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f9a412f55bb6e8f3bb000e020dbc1e709627dcb3a56f6431fa7076b4c1aab0db", size = 5653991 }, - { url = "https://files.pythonhosted.org/packages/ca/56/29432a3e8d951b5e4e520a40cd93bebaa824a14033ea8e65b0ece1da6167/grpcio-1.71.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47be9584729534660416f6d2a3108aaeac1122f6b5bdbf9fd823e11fe6fbaa29", size = 6312781 }, - { url = "https://files.pythonhosted.org/packages/a3/f8/286e81a62964ceb6ac10b10925261d4871a762d2a763fbf354115f9afc98/grpcio-1.71.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9c80ac6091c916db81131d50926a93ab162a7e97e4428ffc186b6e80d6dda4", size = 5910479 }, - { url = "https://files.pythonhosted.org/packages/35/67/d1febb49ec0f599b9e6d4d0d44c2d4afdbed9c3e80deb7587ec788fcf252/grpcio-1.71.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:789d5e2a3a15419374b7b45cd680b1e83bbc1e52b9086e49308e2c0b5bbae6e3", size = 6013262 }, - { url = "https://files.pythonhosted.org/packages/a1/04/f9ceda11755f0104a075ad7163fc0d96e2e3a9fe25ef38adfc74c5790daf/grpcio-1.71.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1be857615e26a86d7363e8a163fade914595c81fec962b3d514a4b1e8760467b", size = 6643356 }, - { url = "https://files.pythonhosted.org/packages/fb/ce/236dbc3dc77cf9a9242adcf1f62538734ad64727fabf39e1346ad4bd5c75/grpcio-1.71.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a76d39b5fafd79ed604c4be0a869ec3581a172a707e2a8d7a4858cb05a5a7637", size = 6186564 }, - { url = "https://files.pythonhosted.org/packages/10/fd/b3348fce9dd4280e221f513dd54024e765b21c348bc475516672da4218e9/grpcio-1.71.0-cp313-cp313-win32.whl", hash = "sha256:74258dce215cb1995083daa17b379a1a5a87d275387b7ffe137f1d5131e2cfbb", size = 3601890 }, - { url = "https://files.pythonhosted.org/packages/be/f8/db5d5f3fc7e296166286c2a397836b8b042f7ad1e11028d82b061701f0f7/grpcio-1.71.0-cp313-cp313-win_amd64.whl", hash = "sha256:22c3bc8d488c039a199f7a003a38cb7635db6656fa96437a8accde8322ce2366", size = 4273308 }, - { url = "https://files.pythonhosted.org/packages/c8/e3/22cb31bbb42de95b35b8f0fb691d8da6e0579e658bb37b86efe2999c702b/grpcio-1.71.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:c6a0a28450c16809f94e0b5bfe52cabff63e7e4b97b44123ebf77f448534d07d", size = 5210667 }, - { url = "https://files.pythonhosted.org/packages/f6/5e/4970fb231e57aad8f41682292343551f58fec5c7a07e261294def3cb8bb6/grpcio-1.71.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:a371e6b6a5379d3692cc4ea1cb92754d2a47bdddeee755d3203d1f84ae08e03e", size = 11336193 }, - { url = "https://files.pythonhosted.org/packages/7f/a4/dd71a5540d5e86526b39c23060b7d3195f3144af3fe291947b30c3fcbdad/grpcio-1.71.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:39983a9245d37394fd59de71e88c4b295eb510a3555e0a847d9965088cdbd033", size = 5699572 }, - { url = "https://files.pythonhosted.org/packages/d0/69/3e3522d7c2c525a60f4bbf811891925ac7594b768b1ac8e6c9d955a72c45/grpcio-1.71.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9182e0063112e55e74ee7584769ec5a0b4f18252c35787f48738627e23a62b97", size = 6339648 }, - { url = "https://files.pythonhosted.org/packages/32/f2/9d864ca8f3949bf507db9c6a18532c150fc03910dd3d3e17fd4bc5d3e462/grpcio-1.71.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693bc706c031aeb848849b9d1c6b63ae6bcc64057984bb91a542332b75aa4c3d", size = 5943469 }, - { url = "https://files.pythonhosted.org/packages/9b/58/aec6ce541b7fb2a9efa15d968db5897c2700bd2da6fb159c1d27515f120c/grpcio-1.71.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:20e8f653abd5ec606be69540f57289274c9ca503ed38388481e98fa396ed0b41", size = 6030255 }, - { url = "https://files.pythonhosted.org/packages/f7/4f/7356b7edd1f622d49e72faaea75a5d6ac7bdde8f4c14dd19bcfbafd56f4c/grpcio-1.71.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8700a2a57771cc43ea295296330daaddc0d93c088f0a35cc969292b6db959bf3", size = 6651120 }, - { url = "https://files.pythonhosted.org/packages/54/10/c1bb13137dc8d1637e2373a85904aa57991e65ef429791bfb8a64a60d5bd/grpcio-1.71.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d35a95f05a8a2cbe8e02be137740138b3b2ea5f80bd004444e4f9a1ffc511e32", size = 6197989 }, - { url = "https://files.pythonhosted.org/packages/0e/dc/0fd537831501df786bc2f9ec5ac1724528a344cd146f6335f7991763eb2b/grpcio-1.71.0-cp39-cp39-win32.whl", hash = "sha256:f9c30c464cb2ddfbc2ddf9400287701270fdc0f14be5f08a1e3939f1e749b455", size = 3620173 }, - { url = "https://files.pythonhosted.org/packages/97/22/b1535291aaa9c046c79a9dc4db125f6b9974d41de154221b72da4e8a005c/grpcio-1.71.0-cp39-cp39-win_amd64.whl", hash = "sha256:63e41b91032f298b3e973b3fa4093cbbc620c875e2da7b93e249d4728b54559a", size = 4280941 }, +sdist = { url = "https://files.pythonhosted.org/packages/1c/95/aa11fc09a85d91fbc7dd405dcb2a1e0256989d67bf89fa65ae24b3ba105a/grpcio-1.71.0.tar.gz", hash = "sha256:2b85f7820475ad3edec209d3d89a7909ada16caab05d3f2e08a7e8ae3200a55c", size = 12549828, upload-time = "2025-03-10T19:28:49.203Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/c5/ef610b3f988cc0cc67b765f72b8e2db06a1db14e65acb5ae7810a6b7042e/grpcio-1.71.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:c200cb6f2393468142eb50ab19613229dcc7829b5ccee8b658a36005f6669fdd", size = 5210643, upload-time = "2025-03-10T19:24:11.278Z" }, + { url = "https://files.pythonhosted.org/packages/bf/de/c84293c961622df302c0d5d07ec6e2d4cd3874ea42f602be2df09c4ad44f/grpcio-1.71.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b2266862c5ad664a380fbbcdbdb8289d71464c42a8c29053820ee78ba0119e5d", size = 11308962, upload-time = "2025-03-10T19:24:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/7c/38/04c9e0dc8c904570c80faa1f1349b190b63e45d6b2782ec8567b050efa9d/grpcio-1.71.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0ab8b2864396663a5b0b0d6d79495657ae85fa37dcb6498a2669d067c65c11ea", size = 5699236, upload-time = "2025-03-10T19:24:17.214Z" }, + { url = "https://files.pythonhosted.org/packages/95/96/e7be331d1298fa605ea7c9ceafc931490edd3d5b33c4f695f1a0667f3491/grpcio-1.71.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c30f393f9d5ff00a71bb56de4aa75b8fe91b161aeb61d39528db6b768d7eac69", size = 6339767, upload-time = "2025-03-10T19:24:18.977Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b7/7e7b7bb6bb18baf156fd4f2f5b254150dcdd6cbf0def1ee427a2fb2bfc4d/grpcio-1.71.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f250ff44843d9a0615e350c77f890082102a0318d66a99540f54769c8766ab73", size = 5943028, upload-time = "2025-03-10T19:24:21.746Z" }, + { url = "https://files.pythonhosted.org/packages/13/aa/5fb756175995aeb47238d706530772d9a7ac8e73bcca1b47dc145d02c95f/grpcio-1.71.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6d8de076528f7c43a2f576bc311799f89d795aa6c9b637377cc2b1616473804", size = 6031841, upload-time = "2025-03-10T19:24:23.912Z" }, + { url = "https://files.pythonhosted.org/packages/54/93/172783e01eed61f7f180617b7fa4470f504e383e32af2587f664576a7101/grpcio-1.71.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b91879d6da1605811ebc60d21ab6a7e4bae6c35f6b63a061d61eb818c8168f6", size = 6651039, upload-time = "2025-03-10T19:24:26.075Z" }, + { url = "https://files.pythonhosted.org/packages/6f/99/62654b220a27ed46d3313252214f4bc66261143dc9b58004085cd0646753/grpcio-1.71.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f71574afdf944e6652203cd1badcda195b2a27d9c83e6d88dc1ce3cfb73b31a5", size = 6198465, upload-time = "2025-03-10T19:24:27.716Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/96116de833b330abe4412cc94edc68f99ed2fa3e39d8713ff307b3799e81/grpcio-1.71.0-cp310-cp310-win32.whl", hash = "sha256:8997d6785e93308f277884ee6899ba63baafa0dfb4729748200fcc537858a509", size = 3620382, upload-time = "2025-03-10T19:24:29.833Z" }, + { url = "https://files.pythonhosted.org/packages/b7/09/f32ef637e386f3f2c02effac49699229fa560ce9007682d24e9e212d2eb4/grpcio-1.71.0-cp310-cp310-win_amd64.whl", hash = "sha256:7d6ac9481d9d0d129224f6d5934d5832c4b1cddb96b59e7eba8416868909786a", size = 4280302, upload-time = "2025-03-10T19:24:31.569Z" }, + { url = "https://files.pythonhosted.org/packages/63/04/a085f3ad4133426f6da8c1becf0749872a49feb625a407a2e864ded3fb12/grpcio-1.71.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:d6aa986318c36508dc1d5001a3ff169a15b99b9f96ef5e98e13522c506b37eef", size = 5210453, upload-time = "2025-03-10T19:24:33.342Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d5/0bc53ed33ba458de95020970e2c22aa8027b26cc84f98bea7fcad5d695d1/grpcio-1.71.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:d2c170247315f2d7e5798a22358e982ad6eeb68fa20cf7a820bb74c11f0736e7", size = 11347567, upload-time = "2025-03-10T19:24:35.215Z" }, + { url = "https://files.pythonhosted.org/packages/e3/6d/ce334f7e7a58572335ccd61154d808fe681a4c5e951f8a1ff68f5a6e47ce/grpcio-1.71.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e6f83a583ed0a5b08c5bc7a3fe860bb3c2eac1f03f1f63e0bc2091325605d2b7", size = 5696067, upload-time = "2025-03-10T19:24:37.988Z" }, + { url = "https://files.pythonhosted.org/packages/05/4a/80befd0b8b1dc2b9ac5337e57473354d81be938f87132e147c4a24a581bd/grpcio-1.71.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be74ddeeb92cc87190e0e376dbc8fc7736dbb6d3d454f2fa1f5be1dee26b9d7", size = 6348377, upload-time = "2025-03-10T19:24:40.361Z" }, + { url = "https://files.pythonhosted.org/packages/c7/67/cbd63c485051eb78663355d9efd1b896cfb50d4a220581ec2cb9a15cd750/grpcio-1.71.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd0dfbe4d5eb1fcfec9490ca13f82b089a309dc3678e2edabc144051270a66e", size = 5940407, upload-time = "2025-03-10T19:24:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/98/4b/7a11aa4326d7faa499f764eaf8a9b5a0eb054ce0988ee7ca34897c2b02ae/grpcio-1.71.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a2242d6950dc892afdf9e951ed7ff89473aaf744b7d5727ad56bdaace363722b", size = 6030915, upload-time = "2025-03-10T19:24:44.463Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a2/cdae2d0e458b475213a011078b0090f7a1d87f9a68c678b76f6af7c6ac8c/grpcio-1.71.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0fa05ee31a20456b13ae49ad2e5d585265f71dd19fbd9ef983c28f926d45d0a7", size = 6648324, upload-time = "2025-03-10T19:24:46.287Z" }, + { url = "https://files.pythonhosted.org/packages/27/df/f345c8daaa8d8574ce9869f9b36ca220c8845923eb3087e8f317eabfc2a8/grpcio-1.71.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3d081e859fb1ebe176de33fc3adb26c7d46b8812f906042705346b314bde32c3", size = 6197839, upload-time = "2025-03-10T19:24:48.565Z" }, + { url = "https://files.pythonhosted.org/packages/f2/2c/cd488dc52a1d0ae1bad88b0d203bc302efbb88b82691039a6d85241c5781/grpcio-1.71.0-cp311-cp311-win32.whl", hash = "sha256:d6de81c9c00c8a23047136b11794b3584cdc1460ed7cbc10eada50614baa1444", size = 3619978, upload-time = "2025-03-10T19:24:50.518Z" }, + { url = "https://files.pythonhosted.org/packages/ee/3f/cf92e7e62ccb8dbdf977499547dfc27133124d6467d3a7d23775bcecb0f9/grpcio-1.71.0-cp311-cp311-win_amd64.whl", hash = "sha256:24e867651fc67717b6f896d5f0cac0ec863a8b5fb7d6441c2ab428f52c651c6b", size = 4282279, upload-time = "2025-03-10T19:24:52.313Z" }, + { url = "https://files.pythonhosted.org/packages/4c/83/bd4b6a9ba07825bd19c711d8b25874cd5de72c2a3fbf635c3c344ae65bd2/grpcio-1.71.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:0ff35c8d807c1c7531d3002be03221ff9ae15712b53ab46e2a0b4bb271f38537", size = 5184101, upload-time = "2025-03-10T19:24:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/31/ea/2e0d90c0853568bf714693447f5c73272ea95ee8dad107807fde740e595d/grpcio-1.71.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:b78a99cd1ece4be92ab7c07765a0b038194ded2e0a26fd654591ee136088d8d7", size = 11310927, upload-time = "2025-03-10T19:24:56.1Z" }, + { url = "https://files.pythonhosted.org/packages/ac/bc/07a3fd8af80467390af491d7dc66882db43884128cdb3cc8524915e0023c/grpcio-1.71.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc1a1231ed23caac1de9f943d031f1bc38d0f69d2a3b243ea0d664fc1fbd7fec", size = 5654280, upload-time = "2025-03-10T19:24:58.55Z" }, + { url = "https://files.pythonhosted.org/packages/16/af/21f22ea3eed3d0538b6ef7889fce1878a8ba4164497f9e07385733391e2b/grpcio-1.71.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6beeea5566092c5e3c4896c6d1d307fb46b1d4bdf3e70c8340b190a69198594", size = 6312051, upload-time = "2025-03-10T19:25:00.682Z" }, + { url = "https://files.pythonhosted.org/packages/49/9d/e12ddc726dc8bd1aa6cba67c85ce42a12ba5b9dd75d5042214a59ccf28ce/grpcio-1.71.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5170929109450a2c031cfe87d6716f2fae39695ad5335d9106ae88cc32dc84c", size = 5910666, upload-time = "2025-03-10T19:25:03.01Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e9/38713d6d67aedef738b815763c25f092e0454dc58e77b1d2a51c9d5b3325/grpcio-1.71.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5b08d03ace7aca7b2fadd4baf291139b4a5f058805a8327bfe9aece7253b6d67", size = 6012019, upload-time = "2025-03-10T19:25:05.174Z" }, + { url = "https://files.pythonhosted.org/packages/80/da/4813cd7adbae6467724fa46c952d7aeac5e82e550b1c62ed2aeb78d444ae/grpcio-1.71.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f903017db76bf9cc2b2d8bdd37bf04b505bbccad6be8a81e1542206875d0e9db", size = 6637043, upload-time = "2025-03-10T19:25:06.987Z" }, + { url = "https://files.pythonhosted.org/packages/52/ca/c0d767082e39dccb7985c73ab4cf1d23ce8613387149e9978c70c3bf3b07/grpcio-1.71.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:469f42a0b410883185eab4689060a20488a1a0a00f8bbb3cbc1061197b4c5a79", size = 6186143, upload-time = "2025-03-10T19:25:08.877Z" }, + { url = "https://files.pythonhosted.org/packages/00/61/7b2c8ec13303f8fe36832c13d91ad4d4ba57204b1c723ada709c346b2271/grpcio-1.71.0-cp312-cp312-win32.whl", hash = "sha256:ad9f30838550695b5eb302add33f21f7301b882937460dd24f24b3cc5a95067a", size = 3604083, upload-time = "2025-03-10T19:25:10.736Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7c/1e429c5fb26122055d10ff9a1d754790fb067d83c633ff69eddcf8e3614b/grpcio-1.71.0-cp312-cp312-win_amd64.whl", hash = "sha256:652350609332de6dac4ece254e5d7e1ff834e203d6afb769601f286886f6f3a8", size = 4272191, upload-time = "2025-03-10T19:25:13.12Z" }, + { url = "https://files.pythonhosted.org/packages/04/dd/b00cbb45400d06b26126dcfdbdb34bb6c4f28c3ebbd7aea8228679103ef6/grpcio-1.71.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:cebc1b34ba40a312ab480ccdb396ff3c529377a2fce72c45a741f7215bfe8379", size = 5184138, upload-time = "2025-03-10T19:25:15.101Z" }, + { url = "https://files.pythonhosted.org/packages/ed/0a/4651215983d590ef53aac40ba0e29dda941a02b097892c44fa3357e706e5/grpcio-1.71.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:85da336e3649a3d2171e82f696b5cad2c6231fdd5bad52616476235681bee5b3", size = 11310747, upload-time = "2025-03-10T19:25:17.201Z" }, + { url = "https://files.pythonhosted.org/packages/57/a3/149615b247f321e13f60aa512d3509d4215173bdb982c9098d78484de216/grpcio-1.71.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f9a412f55bb6e8f3bb000e020dbc1e709627dcb3a56f6431fa7076b4c1aab0db", size = 5653991, upload-time = "2025-03-10T19:25:20.39Z" }, + { url = "https://files.pythonhosted.org/packages/ca/56/29432a3e8d951b5e4e520a40cd93bebaa824a14033ea8e65b0ece1da6167/grpcio-1.71.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47be9584729534660416f6d2a3108aaeac1122f6b5bdbf9fd823e11fe6fbaa29", size = 6312781, upload-time = "2025-03-10T19:25:22.823Z" }, + { url = "https://files.pythonhosted.org/packages/a3/f8/286e81a62964ceb6ac10b10925261d4871a762d2a763fbf354115f9afc98/grpcio-1.71.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9c80ac6091c916db81131d50926a93ab162a7e97e4428ffc186b6e80d6dda4", size = 5910479, upload-time = "2025-03-10T19:25:24.828Z" }, + { url = "https://files.pythonhosted.org/packages/35/67/d1febb49ec0f599b9e6d4d0d44c2d4afdbed9c3e80deb7587ec788fcf252/grpcio-1.71.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:789d5e2a3a15419374b7b45cd680b1e83bbc1e52b9086e49308e2c0b5bbae6e3", size = 6013262, upload-time = "2025-03-10T19:25:26.987Z" }, + { url = "https://files.pythonhosted.org/packages/a1/04/f9ceda11755f0104a075ad7163fc0d96e2e3a9fe25ef38adfc74c5790daf/grpcio-1.71.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1be857615e26a86d7363e8a163fade914595c81fec962b3d514a4b1e8760467b", size = 6643356, upload-time = "2025-03-10T19:25:29.606Z" }, + { url = "https://files.pythonhosted.org/packages/fb/ce/236dbc3dc77cf9a9242adcf1f62538734ad64727fabf39e1346ad4bd5c75/grpcio-1.71.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a76d39b5fafd79ed604c4be0a869ec3581a172a707e2a8d7a4858cb05a5a7637", size = 6186564, upload-time = "2025-03-10T19:25:31.537Z" }, + { url = "https://files.pythonhosted.org/packages/10/fd/b3348fce9dd4280e221f513dd54024e765b21c348bc475516672da4218e9/grpcio-1.71.0-cp313-cp313-win32.whl", hash = "sha256:74258dce215cb1995083daa17b379a1a5a87d275387b7ffe137f1d5131e2cfbb", size = 3601890, upload-time = "2025-03-10T19:25:33.421Z" }, + { url = "https://files.pythonhosted.org/packages/be/f8/db5d5f3fc7e296166286c2a397836b8b042f7ad1e11028d82b061701f0f7/grpcio-1.71.0-cp313-cp313-win_amd64.whl", hash = "sha256:22c3bc8d488c039a199f7a003a38cb7635db6656fa96437a8accde8322ce2366", size = 4273308, upload-time = "2025-03-10T19:25:35.79Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e3/22cb31bbb42de95b35b8f0fb691d8da6e0579e658bb37b86efe2999c702b/grpcio-1.71.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:c6a0a28450c16809f94e0b5bfe52cabff63e7e4b97b44123ebf77f448534d07d", size = 5210667, upload-time = "2025-03-10T19:25:38.344Z" }, + { url = "https://files.pythonhosted.org/packages/f6/5e/4970fb231e57aad8f41682292343551f58fec5c7a07e261294def3cb8bb6/grpcio-1.71.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:a371e6b6a5379d3692cc4ea1cb92754d2a47bdddeee755d3203d1f84ae08e03e", size = 11336193, upload-time = "2025-03-10T19:25:40.568Z" }, + { url = "https://files.pythonhosted.org/packages/7f/a4/dd71a5540d5e86526b39c23060b7d3195f3144af3fe291947b30c3fcbdad/grpcio-1.71.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:39983a9245d37394fd59de71e88c4b295eb510a3555e0a847d9965088cdbd033", size = 5699572, upload-time = "2025-03-10T19:25:43.372Z" }, + { url = "https://files.pythonhosted.org/packages/d0/69/3e3522d7c2c525a60f4bbf811891925ac7594b768b1ac8e6c9d955a72c45/grpcio-1.71.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9182e0063112e55e74ee7584769ec5a0b4f18252c35787f48738627e23a62b97", size = 6339648, upload-time = "2025-03-10T19:25:46.661Z" }, + { url = "https://files.pythonhosted.org/packages/32/f2/9d864ca8f3949bf507db9c6a18532c150fc03910dd3d3e17fd4bc5d3e462/grpcio-1.71.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693bc706c031aeb848849b9d1c6b63ae6bcc64057984bb91a542332b75aa4c3d", size = 5943469, upload-time = "2025-03-10T19:25:48.708Z" }, + { url = "https://files.pythonhosted.org/packages/9b/58/aec6ce541b7fb2a9efa15d968db5897c2700bd2da6fb159c1d27515f120c/grpcio-1.71.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:20e8f653abd5ec606be69540f57289274c9ca503ed38388481e98fa396ed0b41", size = 6030255, upload-time = "2025-03-10T19:25:50.761Z" }, + { url = "https://files.pythonhosted.org/packages/f7/4f/7356b7edd1f622d49e72faaea75a5d6ac7bdde8f4c14dd19bcfbafd56f4c/grpcio-1.71.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8700a2a57771cc43ea295296330daaddc0d93c088f0a35cc969292b6db959bf3", size = 6651120, upload-time = "2025-03-10T19:25:52.877Z" }, + { url = "https://files.pythonhosted.org/packages/54/10/c1bb13137dc8d1637e2373a85904aa57991e65ef429791bfb8a64a60d5bd/grpcio-1.71.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d35a95f05a8a2cbe8e02be137740138b3b2ea5f80bd004444e4f9a1ffc511e32", size = 6197989, upload-time = "2025-03-10T19:25:56.336Z" }, + { url = "https://files.pythonhosted.org/packages/0e/dc/0fd537831501df786bc2f9ec5ac1724528a344cd146f6335f7991763eb2b/grpcio-1.71.0-cp39-cp39-win32.whl", hash = "sha256:f9c30c464cb2ddfbc2ddf9400287701270fdc0f14be5f08a1e3939f1e749b455", size = 3620173, upload-time = "2025-03-10T19:25:58.451Z" }, + { url = "https://files.pythonhosted.org/packages/97/22/b1535291aaa9c046c79a9dc4db125f6b9974d41de154221b72da4e8a005c/grpcio-1.71.0-cp39-cp39-win_amd64.whl", hash = "sha256:63e41b91032f298b3e973b3fa4093cbbc620c875e2da7b93e249d4728b54559a", size = 4280941, upload-time = "2025-03-10T19:26:00.511Z" }, ] [[package]] @@ -1286,18 +1288,18 @@ dependencies = [ { name = "grpcio" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d7/53/a911467bece076020456401f55a27415d2d70d3bc2c37af06b44ea41fc5c/grpcio_status-1.71.0.tar.gz", hash = "sha256:11405fed67b68f406b3f3c7c5ae5104a79d2d309666d10d61b152e91d28fb968", size = 13669 } +sdist = { url = "https://files.pythonhosted.org/packages/d7/53/a911467bece076020456401f55a27415d2d70d3bc2c37af06b44ea41fc5c/grpcio_status-1.71.0.tar.gz", hash = "sha256:11405fed67b68f406b3f3c7c5ae5104a79d2d309666d10d61b152e91d28fb968", size = 13669, upload-time = "2025-03-10T19:29:00.901Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/d6/31fbc43ff097d8c4c9fc3df741431b8018f67bf8dfbe6553a555f6e5f675/grpcio_status-1.71.0-py3-none-any.whl", hash = "sha256:843934ef8c09e3e858952887467f8256aac3910c55f077a359a65b2b3cde3e68", size = 14424 }, + { url = "https://files.pythonhosted.org/packages/ad/d6/31fbc43ff097d8c4c9fc3df741431b8018f67bf8dfbe6553a555f6e5f675/grpcio_status-1.71.0-py3-none-any.whl", hash = "sha256:843934ef8c09e3e858952887467f8256aac3910c55f077a359a65b2b3cde3e68", size = 14424, upload-time = "2025-03-10T19:27:04.967Z" }, ] [[package]] name = "h11" -version = "0.14.0" +version = "0.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, ] [[package]] @@ -1308,22 +1310,22 @@ dependencies = [ { name = "six" }, { name = "webencodings" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215 } +sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215, upload-time = "2020-06-22T23:32:38.834Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173 }, + { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173, upload-time = "2020-06-22T23:32:36.781Z" }, ] [[package]] name = "httpcore" -version = "1.0.8" +version = "1.0.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/45/ad3e1b4d448f22c0cff4f5692f5ed0666658578e358b8d58a19846048059/httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad", size = 85385 } +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/8d/f052b1e336bb2c1fc7ed1aaed898aa570c0b61a09707b108979d9fc6e308/httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be", size = 78732 }, + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, ] [[package]] @@ -1336,48 +1338,48 @@ dependencies = [ { name = "httpcore" }, { name = "idna" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] [[package]] name = "identify" version = "2.6.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0c/83/b6ea0334e2e7327084a46aaaf71f2146fc061a192d6518c0d020120cd0aa/identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8", size = 99201 } +sdist = { url = "https://files.pythonhosted.org/packages/0c/83/b6ea0334e2e7327084a46aaaf71f2146fc061a192d6518c0d020120cd0aa/identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8", size = 99201, upload-time = "2025-04-19T15:10:38.32Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2b/d3/85feeba1d097b81a44bcffa6a0beab7b4dfffe78e82fc54978d3ac380736/identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25", size = 99101 }, + { url = "https://files.pythonhosted.org/packages/2b/d3/85feeba1d097b81a44bcffa6a0beab7b4dfffe78e82fc54978d3ac380736/identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25", size = 99101, upload-time = "2025-04-19T15:10:36.701Z" }, ] [[package]] name = "idna" version = "3.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, ] [[package]] name = "imagesize" version = "1.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026 } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 }, + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, ] [[package]] name = "importlib-metadata" -version = "8.6.1" +version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/33/08/c1395a292bb23fd03bdf572a1357c5a733d3eecbab877641ceacab23db6e/importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580", size = 55767 } +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e", size = 26971 }, + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, ] [[package]] @@ -1387,27 +1389,27 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/8c/f834fbf984f691b4f7ff60f50b514cc3de5cc08abfc3295564dd89c5e2e7/importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c", size = 44693 } +sdist = { url = "https://files.pythonhosted.org/packages/cf/8c/f834fbf984f691b4f7ff60f50b514cc3de5cc08abfc3295564dd89c5e2e7/importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c", size = 44693, upload-time = "2025-01-03T18:51:56.698Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461 }, + { url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461, upload-time = "2025-01-03T18:51:54.306Z" }, ] [[package]] name = "iniconfig" version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] [[package]] name = "itsdangerous" version = "2.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 }, + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, ] [[package]] @@ -1417,9 +1419,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] [[package]] @@ -1442,18 +1444,18 @@ dependencies = [ { name = "rich-click" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b5/c9/d3a431379383cb479d7122017083b9858fe92c6d3333b9d278ed7d559865/litestar-2.15.2.tar.gz", hash = "sha256:de3320e7e412bf09f420b1703cbf04295f1a5377230dad0484d7da8c7ddf5a37", size = 397217 } +sdist = { url = "https://files.pythonhosted.org/packages/b5/c9/d3a431379383cb479d7122017083b9858fe92c6d3333b9d278ed7d559865/litestar-2.15.2.tar.gz", hash = "sha256:de3320e7e412bf09f420b1703cbf04295f1a5377230dad0484d7da8c7ddf5a37", size = 397217, upload-time = "2025-04-06T12:31:43.146Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/db/4ddf71ddb51c70ef4f91bb5c59a84436cecfcfed0e5733f9b31b4b360dbc/litestar-2.15.2-py3-none-any.whl", hash = "sha256:41e7670d67bac70b466008a74eeb2aa63f4f71c09ffade4f603fc00d2bbc771f", size = 571057 }, + { url = "https://files.pythonhosted.org/packages/f4/db/4ddf71ddb51c70ef4f91bb5c59a84436cecfcfed0e5733f9b31b4b360dbc/litestar-2.15.2-py3-none-any.whl", hash = "sha256:41e7670d67bac70b466008a74eeb2aa63f4f71c09ffade4f603fc00d2bbc771f", size = 571057, upload-time = "2025-04-06T12:31:41.338Z" }, ] [[package]] name = "litestar-htmx" version = "0.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c9/0c/06ab03ee497d207dd8cb7588d1940be0b373a8ffdc7be3ec6d7e91c17ae2/litestar_htmx-0.4.1.tar.gz", hash = "sha256:ba2537008eb8cc18bfc8bee5cecb280924c7818bb1c066d79eae4b221696ca08", size = 101877 } +sdist = { url = "https://files.pythonhosted.org/packages/c9/0c/06ab03ee497d207dd8cb7588d1940be0b373a8ffdc7be3ec6d7e91c17ae2/litestar_htmx-0.4.1.tar.gz", hash = "sha256:ba2537008eb8cc18bfc8bee5cecb280924c7818bb1c066d79eae4b221696ca08", size = 101877, upload-time = "2024-12-02T16:01:25.876Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/99/3ea64a79a2f4fea5225ccd0128201a3b8eab5e216b8fba8b778b8c462f29/litestar_htmx-0.4.1-py3-none-any.whl", hash = "sha256:ba2a8ff1e210f21980735b9cde13d239a2b7c3627cb4aeb425d66f4a314d1a59", size = 9970 }, + { url = "https://files.pythonhosted.org/packages/9d/99/3ea64a79a2f4fea5225ccd0128201a3b8eab5e216b8fba8b778b8c462f29/litestar_htmx-0.4.1-py3-none-any.whl", hash = "sha256:ba2a8ff1e210f21980735b9cde13d239a2b7c3627cb4aeb425d66f4a314d1a59", size = 9970, upload-time = "2024-12-02T16:01:22.559Z" }, ] [[package]] @@ -1463,77 +1465,77 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] [[package]] name = "markupsafe" version = "3.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357 }, - { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393 }, - { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732 }, - { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866 }, - { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964 }, - { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977 }, - { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366 }, - { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091 }, - { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065 }, - { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514 }, - { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 }, - { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 }, - { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 }, - { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 }, - { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 }, - { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 }, - { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 }, - { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 }, - { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 }, - { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 }, - { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, - { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, - { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, - { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, - { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, - { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, - { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, - { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, - { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, - { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, - { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, - { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, - { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, - { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, - { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, - { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, - { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, - { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, - { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, - { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, - { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, - { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, - { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, - { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, - { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, - { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, - { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, - { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, - { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, - { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, - { url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", size = 14344 }, - { url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", size = 12389 }, - { url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", size = 21607 }, - { url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", size = 20728 }, - { url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", size = 20826 }, - { url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", size = 21843 }, - { url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", size = 21219 }, - { url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", size = 20946 }, - { url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", size = 15063 }, - { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506 }, +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" }, + { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393, upload-time = "2024-10-18T15:20:52.426Z" }, + { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732, upload-time = "2024-10-18T15:20:53.578Z" }, + { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866, upload-time = "2024-10-18T15:20:55.06Z" }, + { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964, upload-time = "2024-10-18T15:20:55.906Z" }, + { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977, upload-time = "2024-10-18T15:20:57.189Z" }, + { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366, upload-time = "2024-10-18T15:20:58.235Z" }, + { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091, upload-time = "2024-10-18T15:20:59.235Z" }, + { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065, upload-time = "2024-10-18T15:21:00.307Z" }, + { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514, upload-time = "2024-10-18T15:21:01.122Z" }, + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" }, + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", size = 14344, upload-time = "2024-10-18T15:21:43.721Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", size = 12389, upload-time = "2024-10-18T15:21:44.666Z" }, + { url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", size = 21607, upload-time = "2024-10-18T15:21:45.452Z" }, + { url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", size = 20728, upload-time = "2024-10-18T15:21:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", size = 20826, upload-time = "2024-10-18T15:21:47.134Z" }, + { url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", size = 21843, upload-time = "2024-10-18T15:21:48.334Z" }, + { url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", size = 21219, upload-time = "2024-10-18T15:21:49.587Z" }, + { url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", size = 20946, upload-time = "2024-10-18T15:21:50.441Z" }, + { url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", size = 15063, upload-time = "2024-10-18T15:21:51.385Z" }, + { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506, upload-time = "2024-10-18T15:21:52.974Z" }, ] [[package]] @@ -1543,133 +1545,133 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542 } +sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542, upload-time = "2024-09-09T20:27:49.564Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316 }, + { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316, upload-time = "2024-09-09T20:27:48.397Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] name = "more-itertools" -version = "10.6.0" +version = "10.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 } +sdist = { url = "https://files.pythonhosted.org/packages/ce/a0/834b0cebabbfc7e311f30b46c8188790a37f89fc8d756660346fe5abfd09/more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", size = 127671, upload-time = "2025-04-22T14:17:41.838Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 }, + { url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278, upload-time = "2025-04-22T14:17:40.49Z" }, ] [[package]] name = "msgpack" version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/f9/a892a6038c861fa849b11a2bb0502c07bc698ab6ea53359e5771397d883b/msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", size = 150428 }, - { url = "https://files.pythonhosted.org/packages/df/7a/d174cc6a3b6bb85556e6a046d3193294a92f9a8e583cdbd46dc8a1d7e7f4/msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", size = 84131 }, - { url = "https://files.pythonhosted.org/packages/08/52/bf4fbf72f897a23a56b822997a72c16de07d8d56d7bf273242f884055682/msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", size = 81215 }, - { url = "https://files.pythonhosted.org/packages/02/95/dc0044b439b518236aaf012da4677c1b8183ce388411ad1b1e63c32d8979/msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", size = 371229 }, - { url = "https://files.pythonhosted.org/packages/ff/75/09081792db60470bef19d9c2be89f024d366b1e1973c197bb59e6aabc647/msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", size = 378034 }, - { url = "https://files.pythonhosted.org/packages/32/d3/c152e0c55fead87dd948d4b29879b0f14feeeec92ef1fd2ec21b107c3f49/msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", size = 363070 }, - { url = "https://files.pythonhosted.org/packages/d9/2c/82e73506dd55f9e43ac8aa007c9dd088c6f0de2aa19e8f7330e6a65879fc/msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", size = 359863 }, - { url = "https://files.pythonhosted.org/packages/cb/a0/3d093b248837094220e1edc9ec4337de3443b1cfeeb6e0896af8ccc4cc7a/msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", size = 368166 }, - { url = "https://files.pythonhosted.org/packages/e4/13/7646f14f06838b406cf5a6ddbb7e8dc78b4996d891ab3b93c33d1ccc8678/msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", size = 370105 }, - { url = "https://files.pythonhosted.org/packages/67/fa/dbbd2443e4578e165192dabbc6a22c0812cda2649261b1264ff515f19f15/msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", size = 68513 }, - { url = "https://files.pythonhosted.org/packages/24/ce/c2c8fbf0ded750cb63cbcbb61bc1f2dfd69e16dca30a8af8ba80ec182dcd/msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", size = 74687 }, - { url = "https://files.pythonhosted.org/packages/b7/5e/a4c7154ba65d93be91f2f1e55f90e76c5f91ccadc7efc4341e6f04c8647f/msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", size = 150803 }, - { url = "https://files.pythonhosted.org/packages/60/c2/687684164698f1d51c41778c838d854965dd284a4b9d3a44beba9265c931/msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", size = 84343 }, - { url = "https://files.pythonhosted.org/packages/42/ae/d3adea9bb4a1342763556078b5765e666f8fdf242e00f3f6657380920972/msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", size = 81408 }, - { url = "https://files.pythonhosted.org/packages/dc/17/6313325a6ff40ce9c3207293aee3ba50104aed6c2c1559d20d09e5c1ff54/msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", size = 396096 }, - { url = "https://files.pythonhosted.org/packages/a8/a1/ad7b84b91ab5a324e707f4c9761633e357820b011a01e34ce658c1dda7cc/msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", size = 403671 }, - { url = "https://files.pythonhosted.org/packages/bb/0b/fd5b7c0b308bbf1831df0ca04ec76fe2f5bf6319833646b0a4bd5e9dc76d/msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", size = 387414 }, - { url = "https://files.pythonhosted.org/packages/f0/03/ff8233b7c6e9929a1f5da3c7860eccd847e2523ca2de0d8ef4878d354cfa/msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", size = 383759 }, - { url = "https://files.pythonhosted.org/packages/1f/1b/eb82e1fed5a16dddd9bc75f0854b6e2fe86c0259c4353666d7fab37d39f4/msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", size = 394405 }, - { url = "https://files.pythonhosted.org/packages/90/2e/962c6004e373d54ecf33d695fb1402f99b51832631e37c49273cc564ffc5/msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", size = 396041 }, - { url = "https://files.pythonhosted.org/packages/f8/20/6e03342f629474414860c48aeffcc2f7f50ddaf351d95f20c3f1c67399a8/msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", size = 68538 }, - { url = "https://files.pythonhosted.org/packages/aa/c4/5a582fc9a87991a3e6f6800e9bb2f3c82972912235eb9539954f3e9997c7/msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788", size = 74871 }, - { url = "https://files.pythonhosted.org/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421 }, - { url = "https://files.pythonhosted.org/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277 }, - { url = "https://files.pythonhosted.org/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222 }, - { url = "https://files.pythonhosted.org/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971 }, - { url = "https://files.pythonhosted.org/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403 }, - { url = "https://files.pythonhosted.org/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356 }, - { url = "https://files.pythonhosted.org/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028 }, - { url = "https://files.pythonhosted.org/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100 }, - { url = "https://files.pythonhosted.org/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254 }, - { url = "https://files.pythonhosted.org/packages/1c/12/cf07458f35d0d775ff3a2dc5559fa2e1fcd06c46f1ef510e594ebefdca01/msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", size = 69085 }, - { url = "https://files.pythonhosted.org/packages/73/80/2708a4641f7d553a63bc934a3eb7214806b5b39d200133ca7f7afb0a53e8/msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", size = 75347 }, - { url = "https://files.pythonhosted.org/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142 }, - { url = "https://files.pythonhosted.org/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523 }, - { url = "https://files.pythonhosted.org/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556 }, - { url = "https://files.pythonhosted.org/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105 }, - { url = "https://files.pythonhosted.org/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979 }, - { url = "https://files.pythonhosted.org/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816 }, - { url = "https://files.pythonhosted.org/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973 }, - { url = "https://files.pythonhosted.org/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435 }, - { url = "https://files.pythonhosted.org/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082 }, - { url = "https://files.pythonhosted.org/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037 }, - { url = "https://files.pythonhosted.org/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140 }, - { url = "https://files.pythonhosted.org/packages/f7/3b/544a5c5886042b80e1f4847a4757af3430f60d106d8d43bb7be72c9e9650/msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1", size = 150713 }, - { url = "https://files.pythonhosted.org/packages/93/af/d63f25bcccd3d6f06fd518ba4a321f34a4370c67b579ca5c70b4a37721b4/msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48", size = 84277 }, - { url = "https://files.pythonhosted.org/packages/92/9b/5c0dfb0009b9f96328664fecb9f8e4e9c8a1ae919e6d53986c1b813cb493/msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c", size = 81357 }, - { url = "https://files.pythonhosted.org/packages/d1/7c/3a9ee6ec9fc3e47681ad39b4d344ee04ff20a776b594fba92d88d8b68356/msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468", size = 371256 }, - { url = "https://files.pythonhosted.org/packages/f7/0a/8a213cecea7b731c540f25212ba5f9a818f358237ac51a44d448bd753690/msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74", size = 377868 }, - { url = "https://files.pythonhosted.org/packages/1b/94/a82b0db0981e9586ed5af77d6cfb343da05d7437dceaae3b35d346498110/msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846", size = 363370 }, - { url = "https://files.pythonhosted.org/packages/93/fc/6c7f0dcc1c913e14861e16eaf494c07fc1dde454ec726ff8cebcf348ae53/msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346", size = 358970 }, - { url = "https://files.pythonhosted.org/packages/1f/c6/e4a04c0089deace870dabcdef5c9f12798f958e2e81d5012501edaff342f/msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b", size = 366358 }, - { url = "https://files.pythonhosted.org/packages/b6/54/7d8317dac590cf16b3e08e3fb74d2081e5af44eb396f0effa13f17777f30/msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8", size = 370336 }, - { url = "https://files.pythonhosted.org/packages/dc/6f/a5a1f43b6566831e9630e5bc5d86034a8884386297302be128402555dde1/msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd", size = 68683 }, - { url = "https://files.pythonhosted.org/packages/5f/e8/2162621e18dbc36e2bc8492fd0e97b3975f5d89fe0472ae6d5f7fbdd8cf7/msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325", size = 74787 }, +sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260, upload-time = "2024-09-10T04:25:52.197Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/f9/a892a6038c861fa849b11a2bb0502c07bc698ab6ea53359e5771397d883b/msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", size = 150428, upload-time = "2024-09-10T04:25:43.089Z" }, + { url = "https://files.pythonhosted.org/packages/df/7a/d174cc6a3b6bb85556e6a046d3193294a92f9a8e583cdbd46dc8a1d7e7f4/msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", size = 84131, upload-time = "2024-09-10T04:25:30.22Z" }, + { url = "https://files.pythonhosted.org/packages/08/52/bf4fbf72f897a23a56b822997a72c16de07d8d56d7bf273242f884055682/msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", size = 81215, upload-time = "2024-09-10T04:24:54.329Z" }, + { url = "https://files.pythonhosted.org/packages/02/95/dc0044b439b518236aaf012da4677c1b8183ce388411ad1b1e63c32d8979/msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", size = 371229, upload-time = "2024-09-10T04:25:50.907Z" }, + { url = "https://files.pythonhosted.org/packages/ff/75/09081792db60470bef19d9c2be89f024d366b1e1973c197bb59e6aabc647/msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", size = 378034, upload-time = "2024-09-10T04:25:22.097Z" }, + { url = "https://files.pythonhosted.org/packages/32/d3/c152e0c55fead87dd948d4b29879b0f14feeeec92ef1fd2ec21b107c3f49/msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", size = 363070, upload-time = "2024-09-10T04:24:43.957Z" }, + { url = "https://files.pythonhosted.org/packages/d9/2c/82e73506dd55f9e43ac8aa007c9dd088c6f0de2aa19e8f7330e6a65879fc/msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", size = 359863, upload-time = "2024-09-10T04:24:51.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/a0/3d093b248837094220e1edc9ec4337de3443b1cfeeb6e0896af8ccc4cc7a/msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", size = 368166, upload-time = "2024-09-10T04:24:19.907Z" }, + { url = "https://files.pythonhosted.org/packages/e4/13/7646f14f06838b406cf5a6ddbb7e8dc78b4996d891ab3b93c33d1ccc8678/msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", size = 370105, upload-time = "2024-09-10T04:25:35.141Z" }, + { url = "https://files.pythonhosted.org/packages/67/fa/dbbd2443e4578e165192dabbc6a22c0812cda2649261b1264ff515f19f15/msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", size = 68513, upload-time = "2024-09-10T04:24:36.099Z" }, + { url = "https://files.pythonhosted.org/packages/24/ce/c2c8fbf0ded750cb63cbcbb61bc1f2dfd69e16dca30a8af8ba80ec182dcd/msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", size = 74687, upload-time = "2024-09-10T04:24:23.394Z" }, + { url = "https://files.pythonhosted.org/packages/b7/5e/a4c7154ba65d93be91f2f1e55f90e76c5f91ccadc7efc4341e6f04c8647f/msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", size = 150803, upload-time = "2024-09-10T04:24:40.911Z" }, + { url = "https://files.pythonhosted.org/packages/60/c2/687684164698f1d51c41778c838d854965dd284a4b9d3a44beba9265c931/msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", size = 84343, upload-time = "2024-09-10T04:24:50.283Z" }, + { url = "https://files.pythonhosted.org/packages/42/ae/d3adea9bb4a1342763556078b5765e666f8fdf242e00f3f6657380920972/msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", size = 81408, upload-time = "2024-09-10T04:25:12.774Z" }, + { url = "https://files.pythonhosted.org/packages/dc/17/6313325a6ff40ce9c3207293aee3ba50104aed6c2c1559d20d09e5c1ff54/msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", size = 396096, upload-time = "2024-09-10T04:24:37.245Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a1/ad7b84b91ab5a324e707f4c9761633e357820b011a01e34ce658c1dda7cc/msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", size = 403671, upload-time = "2024-09-10T04:25:10.201Z" }, + { url = "https://files.pythonhosted.org/packages/bb/0b/fd5b7c0b308bbf1831df0ca04ec76fe2f5bf6319833646b0a4bd5e9dc76d/msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", size = 387414, upload-time = "2024-09-10T04:25:27.552Z" }, + { url = "https://files.pythonhosted.org/packages/f0/03/ff8233b7c6e9929a1f5da3c7860eccd847e2523ca2de0d8ef4878d354cfa/msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", size = 383759, upload-time = "2024-09-10T04:25:03.366Z" }, + { url = "https://files.pythonhosted.org/packages/1f/1b/eb82e1fed5a16dddd9bc75f0854b6e2fe86c0259c4353666d7fab37d39f4/msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", size = 394405, upload-time = "2024-09-10T04:25:07.348Z" }, + { url = "https://files.pythonhosted.org/packages/90/2e/962c6004e373d54ecf33d695fb1402f99b51832631e37c49273cc564ffc5/msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", size = 396041, upload-time = "2024-09-10T04:25:48.311Z" }, + { url = "https://files.pythonhosted.org/packages/f8/20/6e03342f629474414860c48aeffcc2f7f50ddaf351d95f20c3f1c67399a8/msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", size = 68538, upload-time = "2024-09-10T04:24:29.953Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c4/5a582fc9a87991a3e6f6800e9bb2f3c82972912235eb9539954f3e9997c7/msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788", size = 74871, upload-time = "2024-09-10T04:25:44.823Z" }, + { url = "https://files.pythonhosted.org/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421, upload-time = "2024-09-10T04:25:49.63Z" }, + { url = "https://files.pythonhosted.org/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277, upload-time = "2024-09-10T04:24:48.562Z" }, + { url = "https://files.pythonhosted.org/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222, upload-time = "2024-09-10T04:25:36.49Z" }, + { url = "https://files.pythonhosted.org/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971, upload-time = "2024-09-10T04:24:58.129Z" }, + { url = "https://files.pythonhosted.org/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403, upload-time = "2024-09-10T04:25:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356, upload-time = "2024-09-10T04:25:31.406Z" }, + { url = "https://files.pythonhosted.org/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028, upload-time = "2024-09-10T04:25:17.08Z" }, + { url = "https://files.pythonhosted.org/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100, upload-time = "2024-09-10T04:25:08.993Z" }, + { url = "https://files.pythonhosted.org/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254, upload-time = "2024-09-10T04:25:06.048Z" }, + { url = "https://files.pythonhosted.org/packages/1c/12/cf07458f35d0d775ff3a2dc5559fa2e1fcd06c46f1ef510e594ebefdca01/msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", size = 69085, upload-time = "2024-09-10T04:25:01.494Z" }, + { url = "https://files.pythonhosted.org/packages/73/80/2708a4641f7d553a63bc934a3eb7214806b5b39d200133ca7f7afb0a53e8/msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", size = 75347, upload-time = "2024-09-10T04:25:33.106Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142, upload-time = "2024-09-10T04:24:59.656Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523, upload-time = "2024-09-10T04:25:37.924Z" }, + { url = "https://files.pythonhosted.org/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556, upload-time = "2024-09-10T04:24:28.296Z" }, + { url = "https://files.pythonhosted.org/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105, upload-time = "2024-09-10T04:25:20.153Z" }, + { url = "https://files.pythonhosted.org/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979, upload-time = "2024-09-10T04:25:41.75Z" }, + { url = "https://files.pythonhosted.org/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816, upload-time = "2024-09-10T04:24:45.826Z" }, + { url = "https://files.pythonhosted.org/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973, upload-time = "2024-09-10T04:25:04.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435, upload-time = "2024-09-10T04:24:17.879Z" }, + { url = "https://files.pythonhosted.org/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082, upload-time = "2024-09-10T04:25:18.398Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037, upload-time = "2024-09-10T04:24:52.798Z" }, + { url = "https://files.pythonhosted.org/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140, upload-time = "2024-09-10T04:24:31.288Z" }, + { url = "https://files.pythonhosted.org/packages/f7/3b/544a5c5886042b80e1f4847a4757af3430f60d106d8d43bb7be72c9e9650/msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1", size = 150713, upload-time = "2024-09-10T04:25:23.397Z" }, + { url = "https://files.pythonhosted.org/packages/93/af/d63f25bcccd3d6f06fd518ba4a321f34a4370c67b579ca5c70b4a37721b4/msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48", size = 84277, upload-time = "2024-09-10T04:24:34.656Z" }, + { url = "https://files.pythonhosted.org/packages/92/9b/5c0dfb0009b9f96328664fecb9f8e4e9c8a1ae919e6d53986c1b813cb493/msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c", size = 81357, upload-time = "2024-09-10T04:24:56.603Z" }, + { url = "https://files.pythonhosted.org/packages/d1/7c/3a9ee6ec9fc3e47681ad39b4d344ee04ff20a776b594fba92d88d8b68356/msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468", size = 371256, upload-time = "2024-09-10T04:25:11.473Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0a/8a213cecea7b731c540f25212ba5f9a818f358237ac51a44d448bd753690/msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74", size = 377868, upload-time = "2024-09-10T04:25:24.535Z" }, + { url = "https://files.pythonhosted.org/packages/1b/94/a82b0db0981e9586ed5af77d6cfb343da05d7437dceaae3b35d346498110/msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846", size = 363370, upload-time = "2024-09-10T04:24:21.812Z" }, + { url = "https://files.pythonhosted.org/packages/93/fc/6c7f0dcc1c913e14861e16eaf494c07fc1dde454ec726ff8cebcf348ae53/msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346", size = 358970, upload-time = "2024-09-10T04:24:24.741Z" }, + { url = "https://files.pythonhosted.org/packages/1f/c6/e4a04c0089deace870dabcdef5c9f12798f958e2e81d5012501edaff342f/msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b", size = 366358, upload-time = "2024-09-10T04:25:45.955Z" }, + { url = "https://files.pythonhosted.org/packages/b6/54/7d8317dac590cf16b3e08e3fb74d2081e5af44eb396f0effa13f17777f30/msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8", size = 370336, upload-time = "2024-09-10T04:24:26.918Z" }, + { url = "https://files.pythonhosted.org/packages/dc/6f/a5a1f43b6566831e9630e5bc5d86034a8884386297302be128402555dde1/msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd", size = 68683, upload-time = "2024-09-10T04:24:32.984Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e8/2162621e18dbc36e2bc8492fd0e97b3975f5d89fe0472ae6d5f7fbdd8cf7/msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325", size = 74787, upload-time = "2024-09-10T04:25:14.524Z" }, ] [[package]] name = "msgspec" version = "0.19.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/9b/95d8ce458462b8b71b8a70fa94563b2498b89933689f3a7b8911edfae3d7/msgspec-0.19.0.tar.gz", hash = "sha256:604037e7cd475345848116e89c553aa9a233259733ab51986ac924ab1b976f8e", size = 216934 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/40/817282b42f58399762267b30deb8ac011d8db373f8da0c212c85fbe62b8f/msgspec-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d8dd848ee7ca7c8153462557655570156c2be94e79acec3561cf379581343259", size = 190019 }, - { url = "https://files.pythonhosted.org/packages/92/99/bd7ed738c00f223a8119928661167a89124140792af18af513e6519b0d54/msgspec-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0553bbc77662e5708fe66aa75e7bd3e4b0f209709c48b299afd791d711a93c36", size = 183680 }, - { url = "https://files.pythonhosted.org/packages/e5/27/322badde18eb234e36d4a14122b89edd4e2973cdbc3da61ca7edf40a1ccd/msgspec-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe2c4bf29bf4e89790b3117470dea2c20b59932772483082c468b990d45fb947", size = 209334 }, - { url = "https://files.pythonhosted.org/packages/c6/65/080509c5774a1592b2779d902a70b5fe008532759927e011f068145a16cb/msgspec-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e87ecfa9795ee5214861eab8326b0e75475c2e68a384002aa135ea2a27d909", size = 211551 }, - { url = "https://files.pythonhosted.org/packages/6f/2e/1c23c6b4ca6f4285c30a39def1054e2bee281389e4b681b5e3711bd5a8c9/msgspec-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3c4ec642689da44618f68c90855a10edbc6ac3ff7c1d94395446c65a776e712a", size = 215099 }, - { url = "https://files.pythonhosted.org/packages/83/fe/95f9654518879f3359d1e76bc41189113aa9102452170ab7c9a9a4ee52f6/msgspec-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2719647625320b60e2d8af06b35f5b12d4f4d281db30a15a1df22adb2295f633", size = 218211 }, - { url = "https://files.pythonhosted.org/packages/79/f6/71ca7e87a1fb34dfe5efea8156c9ef59dd55613aeda2ca562f122cd22012/msgspec-0.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:695b832d0091edd86eeb535cd39e45f3919f48d997685f7ac31acb15e0a2ed90", size = 186174 }, - { url = "https://files.pythonhosted.org/packages/24/d4/2ec2567ac30dab072cce3e91fb17803c52f0a37aab6b0c24375d2b20a581/msgspec-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa77046904db764b0462036bc63ef71f02b75b8f72e9c9dd4c447d6da1ed8f8e", size = 187939 }, - { url = "https://files.pythonhosted.org/packages/2b/c0/18226e4328897f4f19875cb62bb9259fe47e901eade9d9376ab5f251a929/msgspec-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:047cfa8675eb3bad68722cfe95c60e7afabf84d1bd8938979dd2b92e9e4a9551", size = 182202 }, - { url = "https://files.pythonhosted.org/packages/81/25/3a4b24d468203d8af90d1d351b77ea3cffb96b29492855cf83078f16bfe4/msgspec-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e78f46ff39a427e10b4a61614a2777ad69559cc8d603a7c05681f5a595ea98f7", size = 209029 }, - { url = "https://files.pythonhosted.org/packages/85/2e/db7e189b57901955239f7689b5dcd6ae9458637a9c66747326726c650523/msgspec-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c7adf191e4bd3be0e9231c3b6dc20cf1199ada2af523885efc2ed218eafd011", size = 210682 }, - { url = "https://files.pythonhosted.org/packages/03/97/7c8895c9074a97052d7e4a1cc1230b7b6e2ca2486714eb12c3f08bb9d284/msgspec-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f04cad4385e20be7c7176bb8ae3dca54a08e9756cfc97bcdb4f18560c3042063", size = 214003 }, - { url = "https://files.pythonhosted.org/packages/61/61/e892997bcaa289559b4d5869f066a8021b79f4bf8e955f831b095f47a4cd/msgspec-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45c8fb410670b3b7eb884d44a75589377c341ec1392b778311acdbfa55187716", size = 216833 }, - { url = "https://files.pythonhosted.org/packages/ce/3d/71b2dffd3a1c743ffe13296ff701ee503feaebc3f04d0e75613b6563c374/msgspec-0.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:70eaef4934b87193a27d802534dc466778ad8d536e296ae2f9334e182ac27b6c", size = 186184 }, - { url = "https://files.pythonhosted.org/packages/b2/5f/a70c24f075e3e7af2fae5414c7048b0e11389685b7f717bb55ba282a34a7/msgspec-0.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f98bd8962ad549c27d63845b50af3f53ec468b6318400c9f1adfe8b092d7b62f", size = 190485 }, - { url = "https://files.pythonhosted.org/packages/89/b0/1b9763938cfae12acf14b682fcf05c92855974d921a5a985ecc197d1c672/msgspec-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:43bbb237feab761b815ed9df43b266114203f53596f9b6e6f00ebd79d178cdf2", size = 183910 }, - { url = "https://files.pythonhosted.org/packages/87/81/0c8c93f0b92c97e326b279795f9c5b956c5a97af28ca0fbb9fd86c83737a/msgspec-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cfc033c02c3e0aec52b71710d7f84cb3ca5eb407ab2ad23d75631153fdb1f12", size = 210633 }, - { url = "https://files.pythonhosted.org/packages/d0/ef/c5422ce8af73928d194a6606f8ae36e93a52fd5e8df5abd366903a5ca8da/msgspec-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d911c442571605e17658ca2b416fd8579c5050ac9adc5e00c2cb3126c97f73bc", size = 213594 }, - { url = "https://files.pythonhosted.org/packages/19/2b/4137bc2ed45660444842d042be2cf5b18aa06efd2cda107cff18253b9653/msgspec-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:757b501fa57e24896cf40a831442b19a864f56d253679f34f260dcb002524a6c", size = 214053 }, - { url = "https://files.pythonhosted.org/packages/9d/e6/8ad51bdc806aac1dc501e8fe43f759f9ed7284043d722b53323ea421c360/msgspec-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5f0f65f29b45e2816d8bded36e6b837a4bf5fb60ec4bc3c625fa2c6da4124537", size = 219081 }, - { url = "https://files.pythonhosted.org/packages/b1/ef/27dd35a7049c9a4f4211c6cd6a8c9db0a50647546f003a5867827ec45391/msgspec-0.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:067f0de1c33cfa0b6a8206562efdf6be5985b988b53dd244a8e06f993f27c8c0", size = 187467 }, - { url = "https://files.pythonhosted.org/packages/3c/cb/2842c312bbe618d8fefc8b9cedce37f773cdc8fa453306546dba2c21fd98/msgspec-0.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f12d30dd6266557aaaf0aa0f9580a9a8fbeadfa83699c487713e355ec5f0bd86", size = 190498 }, - { url = "https://files.pythonhosted.org/packages/58/95/c40b01b93465e1a5f3b6c7d91b10fb574818163740cc3acbe722d1e0e7e4/msgspec-0.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82b2c42c1b9ebc89e822e7e13bbe9d17ede0c23c187469fdd9505afd5a481314", size = 183950 }, - { url = "https://files.pythonhosted.org/packages/e8/f0/5b764e066ce9aba4b70d1db8b087ea66098c7c27d59b9dd8a3532774d48f/msgspec-0.19.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19746b50be214a54239aab822964f2ac81e38b0055cca94808359d779338c10e", size = 210647 }, - { url = "https://files.pythonhosted.org/packages/9d/87/bc14f49bc95c4cb0dd0a8c56028a67c014ee7e6818ccdce74a4862af259b/msgspec-0.19.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60ef4bdb0ec8e4ad62e5a1f95230c08efb1f64f32e6e8dd2ced685bcc73858b5", size = 213563 }, - { url = "https://files.pythonhosted.org/packages/53/2f/2b1c2b056894fbaa975f68f81e3014bb447516a8b010f1bed3fb0e016ed7/msgspec-0.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac7f7c377c122b649f7545810c6cd1b47586e3aa3059126ce3516ac7ccc6a6a9", size = 213996 }, - { url = "https://files.pythonhosted.org/packages/aa/5a/4cd408d90d1417e8d2ce6a22b98a6853c1b4d7cb7669153e4424d60087f6/msgspec-0.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5bc1472223a643f5ffb5bf46ccdede7f9795078194f14edd69e3aab7020d327", size = 219087 }, - { url = "https://files.pythonhosted.org/packages/23/d8/f15b40611c2d5753d1abb0ca0da0c75348daf1252220e5dda2867bd81062/msgspec-0.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:317050bc0f7739cb30d257ff09152ca309bf5a369854bbf1e57dffc310c1f20f", size = 187432 }, - { url = "https://files.pythonhosted.org/packages/ea/d0/323f867eaec1f2236ba30adf613777b1c97a7e8698e2e881656b21871fa4/msgspec-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15c1e86fff77184c20a2932cd9742bf33fe23125fa3fcf332df9ad2f7d483044", size = 189926 }, - { url = "https://files.pythonhosted.org/packages/a8/37/c3e1b39bdae90a7258d77959f5f5e36ad44b40e2be91cff83eea33c54d43/msgspec-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3b5541b2b3294e5ffabe31a09d604e23a88533ace36ac288fa32a420aa38d229", size = 183873 }, - { url = "https://files.pythonhosted.org/packages/cb/a2/48f2c15c7644668e51f4dce99d5f709bd55314e47acb02e90682f5880f35/msgspec-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f5c043ace7962ef188746e83b99faaa9e3e699ab857ca3f367b309c8e2c6b12", size = 209272 }, - { url = "https://files.pythonhosted.org/packages/25/3c/aa339cf08b990c3f07e67b229a3a8aa31bf129ed974b35e5daa0df7d9d56/msgspec-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca06aa08e39bf57e39a258e1996474f84d0dd8130d486c00bec26d797b8c5446", size = 211396 }, - { url = "https://files.pythonhosted.org/packages/c7/00/c7fb9d524327c558b2803973cc3f988c5100a1708879970a9e377bdf6f4f/msgspec-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e695dad6897896e9384cf5e2687d9ae9feaef50e802f93602d35458e20d1fb19", size = 215002 }, - { url = "https://files.pythonhosted.org/packages/3f/bf/d9f9fff026c1248cde84a5ce62b3742e8a63a3c4e811f99f00c8babf7615/msgspec-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3be5c02e1fee57b54130316a08fe40cca53af92999a302a6054cd451700ea7db", size = 218132 }, - { url = "https://files.pythonhosted.org/packages/00/03/b92011210f79794958167a3a3ea64a71135d9a2034cfb7597b545a42606d/msgspec-0.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:0684573a821be3c749912acf5848cce78af4298345cb2d7a8b8948a0a5a27cfe", size = 186301 }, +sdist = { url = "https://files.pythonhosted.org/packages/cf/9b/95d8ce458462b8b71b8a70fa94563b2498b89933689f3a7b8911edfae3d7/msgspec-0.19.0.tar.gz", hash = "sha256:604037e7cd475345848116e89c553aa9a233259733ab51986ac924ab1b976f8e", size = 216934, upload-time = "2024-12-27T17:40:28.597Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/40/817282b42f58399762267b30deb8ac011d8db373f8da0c212c85fbe62b8f/msgspec-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d8dd848ee7ca7c8153462557655570156c2be94e79acec3561cf379581343259", size = 190019, upload-time = "2024-12-27T17:39:13.803Z" }, + { url = "https://files.pythonhosted.org/packages/92/99/bd7ed738c00f223a8119928661167a89124140792af18af513e6519b0d54/msgspec-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0553bbc77662e5708fe66aa75e7bd3e4b0f209709c48b299afd791d711a93c36", size = 183680, upload-time = "2024-12-27T17:39:17.847Z" }, + { url = "https://files.pythonhosted.org/packages/e5/27/322badde18eb234e36d4a14122b89edd4e2973cdbc3da61ca7edf40a1ccd/msgspec-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe2c4bf29bf4e89790b3117470dea2c20b59932772483082c468b990d45fb947", size = 209334, upload-time = "2024-12-27T17:39:19.065Z" }, + { url = "https://files.pythonhosted.org/packages/c6/65/080509c5774a1592b2779d902a70b5fe008532759927e011f068145a16cb/msgspec-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e87ecfa9795ee5214861eab8326b0e75475c2e68a384002aa135ea2a27d909", size = 211551, upload-time = "2024-12-27T17:39:21.767Z" }, + { url = "https://files.pythonhosted.org/packages/6f/2e/1c23c6b4ca6f4285c30a39def1054e2bee281389e4b681b5e3711bd5a8c9/msgspec-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3c4ec642689da44618f68c90855a10edbc6ac3ff7c1d94395446c65a776e712a", size = 215099, upload-time = "2024-12-27T17:39:24.71Z" }, + { url = "https://files.pythonhosted.org/packages/83/fe/95f9654518879f3359d1e76bc41189113aa9102452170ab7c9a9a4ee52f6/msgspec-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2719647625320b60e2d8af06b35f5b12d4f4d281db30a15a1df22adb2295f633", size = 218211, upload-time = "2024-12-27T17:39:27.396Z" }, + { url = "https://files.pythonhosted.org/packages/79/f6/71ca7e87a1fb34dfe5efea8156c9ef59dd55613aeda2ca562f122cd22012/msgspec-0.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:695b832d0091edd86eeb535cd39e45f3919f48d997685f7ac31acb15e0a2ed90", size = 186174, upload-time = "2024-12-27T17:39:29.647Z" }, + { url = "https://files.pythonhosted.org/packages/24/d4/2ec2567ac30dab072cce3e91fb17803c52f0a37aab6b0c24375d2b20a581/msgspec-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa77046904db764b0462036bc63ef71f02b75b8f72e9c9dd4c447d6da1ed8f8e", size = 187939, upload-time = "2024-12-27T17:39:32.347Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/18226e4328897f4f19875cb62bb9259fe47e901eade9d9376ab5f251a929/msgspec-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:047cfa8675eb3bad68722cfe95c60e7afabf84d1bd8938979dd2b92e9e4a9551", size = 182202, upload-time = "2024-12-27T17:39:33.633Z" }, + { url = "https://files.pythonhosted.org/packages/81/25/3a4b24d468203d8af90d1d351b77ea3cffb96b29492855cf83078f16bfe4/msgspec-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e78f46ff39a427e10b4a61614a2777ad69559cc8d603a7c05681f5a595ea98f7", size = 209029, upload-time = "2024-12-27T17:39:35.023Z" }, + { url = "https://files.pythonhosted.org/packages/85/2e/db7e189b57901955239f7689b5dcd6ae9458637a9c66747326726c650523/msgspec-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c7adf191e4bd3be0e9231c3b6dc20cf1199ada2af523885efc2ed218eafd011", size = 210682, upload-time = "2024-12-27T17:39:36.384Z" }, + { url = "https://files.pythonhosted.org/packages/03/97/7c8895c9074a97052d7e4a1cc1230b7b6e2ca2486714eb12c3f08bb9d284/msgspec-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f04cad4385e20be7c7176bb8ae3dca54a08e9756cfc97bcdb4f18560c3042063", size = 214003, upload-time = "2024-12-27T17:39:39.097Z" }, + { url = "https://files.pythonhosted.org/packages/61/61/e892997bcaa289559b4d5869f066a8021b79f4bf8e955f831b095f47a4cd/msgspec-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45c8fb410670b3b7eb884d44a75589377c341ec1392b778311acdbfa55187716", size = 216833, upload-time = "2024-12-27T17:39:41.203Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3d/71b2dffd3a1c743ffe13296ff701ee503feaebc3f04d0e75613b6563c374/msgspec-0.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:70eaef4934b87193a27d802534dc466778ad8d536e296ae2f9334e182ac27b6c", size = 186184, upload-time = "2024-12-27T17:39:43.702Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5f/a70c24f075e3e7af2fae5414c7048b0e11389685b7f717bb55ba282a34a7/msgspec-0.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f98bd8962ad549c27d63845b50af3f53ec468b6318400c9f1adfe8b092d7b62f", size = 190485, upload-time = "2024-12-27T17:39:44.974Z" }, + { url = "https://files.pythonhosted.org/packages/89/b0/1b9763938cfae12acf14b682fcf05c92855974d921a5a985ecc197d1c672/msgspec-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:43bbb237feab761b815ed9df43b266114203f53596f9b6e6f00ebd79d178cdf2", size = 183910, upload-time = "2024-12-27T17:39:46.401Z" }, + { url = "https://files.pythonhosted.org/packages/87/81/0c8c93f0b92c97e326b279795f9c5b956c5a97af28ca0fbb9fd86c83737a/msgspec-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cfc033c02c3e0aec52b71710d7f84cb3ca5eb407ab2ad23d75631153fdb1f12", size = 210633, upload-time = "2024-12-27T17:39:49.099Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ef/c5422ce8af73928d194a6606f8ae36e93a52fd5e8df5abd366903a5ca8da/msgspec-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d911c442571605e17658ca2b416fd8579c5050ac9adc5e00c2cb3126c97f73bc", size = 213594, upload-time = "2024-12-27T17:39:51.204Z" }, + { url = "https://files.pythonhosted.org/packages/19/2b/4137bc2ed45660444842d042be2cf5b18aa06efd2cda107cff18253b9653/msgspec-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:757b501fa57e24896cf40a831442b19a864f56d253679f34f260dcb002524a6c", size = 214053, upload-time = "2024-12-27T17:39:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/9d/e6/8ad51bdc806aac1dc501e8fe43f759f9ed7284043d722b53323ea421c360/msgspec-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5f0f65f29b45e2816d8bded36e6b837a4bf5fb60ec4bc3c625fa2c6da4124537", size = 219081, upload-time = "2024-12-27T17:39:55.142Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ef/27dd35a7049c9a4f4211c6cd6a8c9db0a50647546f003a5867827ec45391/msgspec-0.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:067f0de1c33cfa0b6a8206562efdf6be5985b988b53dd244a8e06f993f27c8c0", size = 187467, upload-time = "2024-12-27T17:39:56.531Z" }, + { url = "https://files.pythonhosted.org/packages/3c/cb/2842c312bbe618d8fefc8b9cedce37f773cdc8fa453306546dba2c21fd98/msgspec-0.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f12d30dd6266557aaaf0aa0f9580a9a8fbeadfa83699c487713e355ec5f0bd86", size = 190498, upload-time = "2024-12-27T17:40:00.427Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/c40b01b93465e1a5f3b6c7d91b10fb574818163740cc3acbe722d1e0e7e4/msgspec-0.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82b2c42c1b9ebc89e822e7e13bbe9d17ede0c23c187469fdd9505afd5a481314", size = 183950, upload-time = "2024-12-27T17:40:04.219Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f0/5b764e066ce9aba4b70d1db8b087ea66098c7c27d59b9dd8a3532774d48f/msgspec-0.19.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19746b50be214a54239aab822964f2ac81e38b0055cca94808359d779338c10e", size = 210647, upload-time = "2024-12-27T17:40:05.606Z" }, + { url = "https://files.pythonhosted.org/packages/9d/87/bc14f49bc95c4cb0dd0a8c56028a67c014ee7e6818ccdce74a4862af259b/msgspec-0.19.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60ef4bdb0ec8e4ad62e5a1f95230c08efb1f64f32e6e8dd2ced685bcc73858b5", size = 213563, upload-time = "2024-12-27T17:40:10.516Z" }, + { url = "https://files.pythonhosted.org/packages/53/2f/2b1c2b056894fbaa975f68f81e3014bb447516a8b010f1bed3fb0e016ed7/msgspec-0.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac7f7c377c122b649f7545810c6cd1b47586e3aa3059126ce3516ac7ccc6a6a9", size = 213996, upload-time = "2024-12-27T17:40:12.244Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5a/4cd408d90d1417e8d2ce6a22b98a6853c1b4d7cb7669153e4424d60087f6/msgspec-0.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5bc1472223a643f5ffb5bf46ccdede7f9795078194f14edd69e3aab7020d327", size = 219087, upload-time = "2024-12-27T17:40:14.881Z" }, + { url = "https://files.pythonhosted.org/packages/23/d8/f15b40611c2d5753d1abb0ca0da0c75348daf1252220e5dda2867bd81062/msgspec-0.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:317050bc0f7739cb30d257ff09152ca309bf5a369854bbf1e57dffc310c1f20f", size = 187432, upload-time = "2024-12-27T17:40:16.256Z" }, + { url = "https://files.pythonhosted.org/packages/ea/d0/323f867eaec1f2236ba30adf613777b1c97a7e8698e2e881656b21871fa4/msgspec-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15c1e86fff77184c20a2932cd9742bf33fe23125fa3fcf332df9ad2f7d483044", size = 189926, upload-time = "2024-12-27T17:40:18.939Z" }, + { url = "https://files.pythonhosted.org/packages/a8/37/c3e1b39bdae90a7258d77959f5f5e36ad44b40e2be91cff83eea33c54d43/msgspec-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3b5541b2b3294e5ffabe31a09d604e23a88533ace36ac288fa32a420aa38d229", size = 183873, upload-time = "2024-12-27T17:40:20.214Z" }, + { url = "https://files.pythonhosted.org/packages/cb/a2/48f2c15c7644668e51f4dce99d5f709bd55314e47acb02e90682f5880f35/msgspec-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f5c043ace7962ef188746e83b99faaa9e3e699ab857ca3f367b309c8e2c6b12", size = 209272, upload-time = "2024-12-27T17:40:21.534Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/aa339cf08b990c3f07e67b229a3a8aa31bf129ed974b35e5daa0df7d9d56/msgspec-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca06aa08e39bf57e39a258e1996474f84d0dd8130d486c00bec26d797b8c5446", size = 211396, upload-time = "2024-12-27T17:40:22.897Z" }, + { url = "https://files.pythonhosted.org/packages/c7/00/c7fb9d524327c558b2803973cc3f988c5100a1708879970a9e377bdf6f4f/msgspec-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e695dad6897896e9384cf5e2687d9ae9feaef50e802f93602d35458e20d1fb19", size = 215002, upload-time = "2024-12-27T17:40:24.341Z" }, + { url = "https://files.pythonhosted.org/packages/3f/bf/d9f9fff026c1248cde84a5ce62b3742e8a63a3c4e811f99f00c8babf7615/msgspec-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3be5c02e1fee57b54130316a08fe40cca53af92999a302a6054cd451700ea7db", size = 218132, upload-time = "2024-12-27T17:40:25.744Z" }, + { url = "https://files.pythonhosted.org/packages/00/03/b92011210f79794958167a3a3ea64a71135d9a2034cfb7597b545a42606d/msgspec-0.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:0684573a821be3c749912acf5848cce78af4298345cb2d7a8b8948a0a5a27cfe", size = 186301, upload-time = "2024-12-27T17:40:27.076Z" }, ] [[package]] @@ -1679,120 +1681,120 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/2c/e367dfb4c6538614a0c9453e510d75d66099edf1c4e69da1b5ce691a1931/multidict-6.4.3.tar.gz", hash = "sha256:3ada0b058c9f213c5f95ba301f922d402ac234f1111a7d8fd70f1b99f3c281ec", size = 89372 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/44/45e798d4cd1b5dfe41ddf36266c7aca6d954e3c7a8b0d599ad555ce2b4f8/multidict-6.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32a998bd8a64ca48616eac5a8c1cc4fa38fb244a3facf2eeb14abe186e0f6cc5", size = 65822 }, - { url = "https://files.pythonhosted.org/packages/10/fb/9ea024f928503f8c758f8463759d21958bf27b1f7a1103df73e5022e6a7c/multidict-6.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a54ec568f1fc7f3c313c2f3b16e5db346bf3660e1309746e7fccbbfded856188", size = 38706 }, - { url = "https://files.pythonhosted.org/packages/6d/eb/7013316febca37414c0e1469fccadcb1a0e4315488f8f57ca5d29b384863/multidict-6.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a7be07e5df178430621c716a63151165684d3e9958f2bbfcb644246162007ab7", size = 37979 }, - { url = "https://files.pythonhosted.org/packages/64/28/5a7bf4e7422613ea80f9ebc529d3845b20a422cfa94d4355504ac98047ee/multidict-6.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b128dbf1c939674a50dd0b28f12c244d90e5015e751a4f339a96c54f7275e291", size = 220233 }, - { url = "https://files.pythonhosted.org/packages/52/05/b4c58850f71befde6a16548968b48331a155a80627750b150bb5962e4dea/multidict-6.4.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9cb19dfd83d35b6ff24a4022376ea6e45a2beba8ef3f0836b8a4b288b6ad685", size = 217762 }, - { url = "https://files.pythonhosted.org/packages/99/a3/393e23bba1e9a00f95b3957acd8f5e3ee3446e78c550f593be25f9de0483/multidict-6.4.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3cf62f8e447ea2c1395afa289b332e49e13d07435369b6f4e41f887db65b40bf", size = 230699 }, - { url = "https://files.pythonhosted.org/packages/9c/a7/52c63069eb1a079f824257bb8045d93e692fa2eb34d08323d1fdbdfc398a/multidict-6.4.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:909f7d43ff8f13d1adccb6a397094adc369d4da794407f8dd592c51cf0eae4b1", size = 226801 }, - { url = "https://files.pythonhosted.org/packages/2c/e9/40d2b73e7d6574d91074d83477a990e3701affbe8b596010d4f5e6c7a6fa/multidict-6.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0bb8f8302fbc7122033df959e25777b0b7659b1fd6bcb9cb6bed76b5de67afef", size = 219833 }, - { url = "https://files.pythonhosted.org/packages/e4/6a/0572b22fe63c632254f55a1c1cb7d29f644002b1d8731d6103a290edc754/multidict-6.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:224b79471b4f21169ea25ebc37ed6f058040c578e50ade532e2066562597b8a9", size = 212920 }, - { url = "https://files.pythonhosted.org/packages/33/fe/c63735db9dece0053868b2d808bcc2592a83ce1830bc98243852a2b34d42/multidict-6.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a7bd27f7ab3204f16967a6f899b3e8e9eb3362c0ab91f2ee659e0345445e0078", size = 225263 }, - { url = "https://files.pythonhosted.org/packages/47/c2/2db296d64d41525110c27ed38fadd5eb571c6b936233e75a5ea61b14e337/multidict-6.4.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:99592bd3162e9c664671fd14e578a33bfdba487ea64bcb41d281286d3c870ad7", size = 214249 }, - { url = "https://files.pythonhosted.org/packages/7e/74/8bc26e54c79f9a0f111350b1b28a9cacaaee53ecafccd53c90e59754d55a/multidict-6.4.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a62d78a1c9072949018cdb05d3c533924ef8ac9bcb06cbf96f6d14772c5cd451", size = 221650 }, - { url = "https://files.pythonhosted.org/packages/af/d7/2ce87606e3799d9a08a941f4c170930a9895886ea8bd0eca75c44baeebe3/multidict-6.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ccdde001578347e877ca4f629450973c510e88e8865d5aefbcb89b852ccc666", size = 231235 }, - { url = "https://files.pythonhosted.org/packages/07/e1/d191a7ad3b90c613fc4b130d07a41c380e249767586148709b54d006ca17/multidict-6.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:eccb67b0e78aa2e38a04c5ecc13bab325a43e5159a181a9d1a6723db913cbb3c", size = 226056 }, - { url = "https://files.pythonhosted.org/packages/24/05/a57490cf6a8d5854f4af2d17dfc54924f37fbb683986e133b76710a36079/multidict-6.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8b6fcf6054fc4114a27aa865f8840ef3d675f9316e81868e0ad5866184a6cba5", size = 220014 }, - { url = "https://files.pythonhosted.org/packages/5c/b1/be04fa9f08c684e9e27cca85b4ab94c10f017ec07c4c631af9c8c10bb275/multidict-6.4.3-cp310-cp310-win32.whl", hash = "sha256:f92c7f62d59373cd93bc9969d2da9b4b21f78283b1379ba012f7ee8127b3152e", size = 35042 }, - { url = "https://files.pythonhosted.org/packages/d9/ca/8888f99892513001fa900eef11bafbf38ff3485109510487de009da85748/multidict-6.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:b57e28dbc031d13916b946719f213c494a517b442d7b48b29443e79610acd887", size = 38506 }, - { url = "https://files.pythonhosted.org/packages/16/e0/53cf7f27eda48fffa53cfd4502329ed29e00efb9e4ce41362cbf8aa54310/multidict-6.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f6f19170197cc29baccd33ccc5b5d6a331058796485857cf34f7635aa25fb0cd", size = 65259 }, - { url = "https://files.pythonhosted.org/packages/44/79/1dcd93ce7070cf01c2ee29f781c42b33c64fce20033808f1cc9ec8413d6e/multidict-6.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2882bf27037eb687e49591690e5d491e677272964f9ec7bc2abbe09108bdfb8", size = 38451 }, - { url = "https://files.pythonhosted.org/packages/f4/35/2292cf29ab5f0d0b3613fad1b75692148959d3834d806be1885ceb49a8ff/multidict-6.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbf226ac85f7d6b6b9ba77db4ec0704fde88463dc17717aec78ec3c8546c70ad", size = 37706 }, - { url = "https://files.pythonhosted.org/packages/f6/d1/6b157110b2b187b5a608b37714acb15ee89ec773e3800315b0107ea648cd/multidict-6.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e329114f82ad4b9dd291bef614ea8971ec119ecd0f54795109976de75c9a852", size = 226669 }, - { url = "https://files.pythonhosted.org/packages/40/7f/61a476450651f177c5570e04bd55947f693077ba7804fe9717ee9ae8de04/multidict-6.4.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1f4e0334d7a555c63f5c8952c57ab6f1c7b4f8c7f3442df689fc9f03df315c08", size = 223182 }, - { url = "https://files.pythonhosted.org/packages/51/7b/eaf7502ac4824cdd8edcf5723e2e99f390c879866aec7b0c420267b53749/multidict-6.4.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:740915eb776617b57142ce0bb13b7596933496e2f798d3d15a20614adf30d229", size = 235025 }, - { url = "https://files.pythonhosted.org/packages/3b/f6/facdbbd73c96b67a93652774edd5778ab1167854fa08ea35ad004b1b70ad/multidict-6.4.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255dac25134d2b141c944b59a0d2f7211ca12a6d4779f7586a98b4b03ea80508", size = 231481 }, - { url = "https://files.pythonhosted.org/packages/70/57/c008e861b3052405eebf921fd56a748322d8c44dcfcab164fffbccbdcdc4/multidict-6.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4e8535bd4d741039b5aad4285ecd9b902ef9e224711f0b6afda6e38d7ac02c7", size = 223492 }, - { url = "https://files.pythonhosted.org/packages/30/4d/7d8440d3a12a6ae5d6b202d6e7f2ac6ab026e04e99aaf1b73f18e6bc34bc/multidict-6.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c433a33be000dd968f5750722eaa0991037be0be4a9d453eba121774985bc8", size = 217279 }, - { url = "https://files.pythonhosted.org/packages/7f/e7/bca0df4dd057597b94138d2d8af04eb3c27396a425b1b0a52e082f9be621/multidict-6.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4eb33b0bdc50acd538f45041f5f19945a1f32b909b76d7b117c0c25d8063df56", size = 228733 }, - { url = "https://files.pythonhosted.org/packages/88/f5/383827c3f1c38d7c92dbad00a8a041760228573b1c542fbf245c37bbca8a/multidict-6.4.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:75482f43465edefd8a5d72724887ccdcd0c83778ded8f0cb1e0594bf71736cc0", size = 218089 }, - { url = "https://files.pythonhosted.org/packages/36/8a/a5174e8a7d8b94b4c8f9c1e2cf5d07451f41368ffe94d05fc957215b8e72/multidict-6.4.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ce5b3082e86aee80b3925ab4928198450d8e5b6466e11501fe03ad2191c6d777", size = 225257 }, - { url = "https://files.pythonhosted.org/packages/8c/76/1d4b7218f0fd00b8e5c90b88df2e45f8af127f652f4e41add947fa54c1c4/multidict-6.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e413152e3212c4d39f82cf83c6f91be44bec9ddea950ce17af87fbf4e32ca6b2", size = 234728 }, - { url = "https://files.pythonhosted.org/packages/64/44/18372a4f6273fc7ca25630d7bf9ae288cde64f29593a078bff450c7170b6/multidict-6.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8aac2eeff69b71f229a405c0a4b61b54bade8e10163bc7b44fcd257949620618", size = 230087 }, - { url = "https://files.pythonhosted.org/packages/0f/ae/28728c314a698d8a6d9491fcacc897077348ec28dd85884d09e64df8a855/multidict-6.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ab583ac203af1d09034be41458feeab7863c0635c650a16f15771e1386abf2d7", size = 223137 }, - { url = "https://files.pythonhosted.org/packages/22/50/785bb2b3fe16051bc91c70a06a919f26312da45c34db97fc87441d61e343/multidict-6.4.3-cp311-cp311-win32.whl", hash = "sha256:1b2019317726f41e81154df636a897de1bfe9228c3724a433894e44cd2512378", size = 34959 }, - { url = "https://files.pythonhosted.org/packages/2f/63/2a22e099ae2f4d92897618c00c73a09a08a2a9aa14b12736965bf8d59fd3/multidict-6.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:43173924fa93c7486402217fab99b60baf78d33806af299c56133a3755f69589", size = 38541 }, - { url = "https://files.pythonhosted.org/packages/fc/bb/3abdaf8fe40e9226ce8a2ba5ecf332461f7beec478a455d6587159f1bf92/multidict-6.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1f1c2f58f08b36f8475f3ec6f5aeb95270921d418bf18f90dffd6be5c7b0e676", size = 64019 }, - { url = "https://files.pythonhosted.org/packages/7e/b5/1b2e8de8217d2e89db156625aa0fe4a6faad98972bfe07a7b8c10ef5dd6b/multidict-6.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:26ae9ad364fc61b936fb7bf4c9d8bd53f3a5b4417142cd0be5c509d6f767e2f1", size = 37925 }, - { url = "https://files.pythonhosted.org/packages/b4/e2/3ca91c112644a395c8eae017144c907d173ea910c913ff8b62549dcf0bbf/multidict-6.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:659318c6c8a85f6ecfc06b4e57529e5a78dfdd697260cc81f683492ad7e9435a", size = 37008 }, - { url = "https://files.pythonhosted.org/packages/60/23/79bc78146c7ac8d1ac766b2770ca2e07c2816058b8a3d5da6caed8148637/multidict-6.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1eb72c741fd24d5a28242ce72bb61bc91f8451877131fa3fe930edb195f7054", size = 224374 }, - { url = "https://files.pythonhosted.org/packages/86/35/77950ed9ebd09136003a85c1926ba42001ca5be14feb49710e4334ee199b/multidict-6.4.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3cd06d88cb7398252284ee75c8db8e680aa0d321451132d0dba12bc995f0adcc", size = 230869 }, - { url = "https://files.pythonhosted.org/packages/49/97/2a33c6e7d90bc116c636c14b2abab93d6521c0c052d24bfcc231cbf7f0e7/multidict-6.4.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4543d8dc6470a82fde92b035a92529317191ce993533c3c0c68f56811164ed07", size = 231949 }, - { url = "https://files.pythonhosted.org/packages/56/ce/e9b5d9fcf854f61d6686ada7ff64893a7a5523b2a07da6f1265eaaea5151/multidict-6.4.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30a3ebdc068c27e9d6081fca0e2c33fdf132ecea703a72ea216b81a66860adde", size = 231032 }, - { url = "https://files.pythonhosted.org/packages/f0/ac/7ced59dcdfeddd03e601edb05adff0c66d81ed4a5160c443e44f2379eef0/multidict-6.4.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b038f10e23f277153f86f95c777ba1958bcd5993194fda26a1d06fae98b2f00c", size = 223517 }, - { url = "https://files.pythonhosted.org/packages/db/e6/325ed9055ae4e085315193a1b58bdb4d7fc38ffcc1f4975cfca97d015e17/multidict-6.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c605a2b2dc14282b580454b9b5d14ebe0668381a3a26d0ac39daa0ca115eb2ae", size = 216291 }, - { url = "https://files.pythonhosted.org/packages/fa/84/eeee6d477dd9dcb7691c3bb9d08df56017f5dd15c730bcc9383dcf201cf4/multidict-6.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8bd2b875f4ca2bb527fe23e318ddd509b7df163407b0fb717df229041c6df5d3", size = 228982 }, - { url = "https://files.pythonhosted.org/packages/82/94/4d1f3e74e7acf8b0c85db350e012dcc61701cd6668bc2440bb1ecb423c90/multidict-6.4.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c2e98c840c9c8e65c0e04b40c6c5066c8632678cd50c8721fdbcd2e09f21a507", size = 226823 }, - { url = "https://files.pythonhosted.org/packages/09/f0/1e54b95bda7cd01080e5732f9abb7b76ab5cc795b66605877caeb2197476/multidict-6.4.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66eb80dd0ab36dbd559635e62fba3083a48a252633164857a1d1684f14326427", size = 222714 }, - { url = "https://files.pythonhosted.org/packages/e7/a2/f6cbca875195bd65a3e53b37ab46486f3cc125bdeab20eefe5042afa31fb/multidict-6.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c23831bdee0a2a3cf21be057b5e5326292f60472fb6c6f86392bbf0de70ba731", size = 233739 }, - { url = "https://files.pythonhosted.org/packages/79/68/9891f4d2b8569554723ddd6154375295f789dc65809826c6fb96a06314fd/multidict-6.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1535cec6443bfd80d028052e9d17ba6ff8a5a3534c51d285ba56c18af97e9713", size = 230809 }, - { url = "https://files.pythonhosted.org/packages/e6/72/a7be29ba1e87e4fc5ceb44dabc7940b8005fd2436a332a23547709315f70/multidict-6.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b73e7227681f85d19dec46e5b881827cd354aabe46049e1a61d2f9aaa4e285a", size = 226934 }, - { url = "https://files.pythonhosted.org/packages/12/c1/259386a9ad6840ff7afc686da96808b503d152ac4feb3a96c651dc4f5abf/multidict-6.4.3-cp312-cp312-win32.whl", hash = "sha256:8eac0c49df91b88bf91f818e0a24c1c46f3622978e2c27035bfdca98e0e18124", size = 35242 }, - { url = "https://files.pythonhosted.org/packages/06/24/c8fdff4f924d37225dc0c56a28b1dca10728fc2233065fafeb27b4b125be/multidict-6.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:11990b5c757d956cd1db7cb140be50a63216af32cd6506329c2c59d732d802db", size = 38635 }, - { url = "https://files.pythonhosted.org/packages/6c/4b/86fd786d03915c6f49998cf10cd5fe6b6ac9e9a071cb40885d2e080fb90d/multidict-6.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a76534263d03ae0cfa721fea40fd2b5b9d17a6f85e98025931d41dc49504474", size = 63831 }, - { url = "https://files.pythonhosted.org/packages/45/05/9b51fdf7aef2563340a93be0a663acba2c428c4daeaf3960d92d53a4a930/multidict-6.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:805031c2f599eee62ac579843555ed1ce389ae00c7e9f74c2a1b45e0564a88dd", size = 37888 }, - { url = "https://files.pythonhosted.org/packages/0b/43/53fc25394386c911822419b522181227ca450cf57fea76e6188772a1bd91/multidict-6.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c56c179839d5dcf51d565132185409d1d5dd8e614ba501eb79023a6cab25576b", size = 36852 }, - { url = "https://files.pythonhosted.org/packages/8a/68/7b99c751e822467c94a235b810a2fd4047d4ecb91caef6b5c60116991c4b/multidict-6.4.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c64f4ddb3886dd8ab71b68a7431ad4aa01a8fa5be5b11543b29674f29ca0ba3", size = 223644 }, - { url = "https://files.pythonhosted.org/packages/80/1b/d458d791e4dd0f7e92596667784fbf99e5c8ba040affe1ca04f06b93ae92/multidict-6.4.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3002a856367c0b41cad6784f5b8d3ab008eda194ed7864aaa58f65312e2abcac", size = 230446 }, - { url = "https://files.pythonhosted.org/packages/e2/46/9793378d988905491a7806d8987862dc5a0bae8a622dd896c4008c7b226b/multidict-6.4.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d75e621e7d887d539d6e1d789f0c64271c250276c333480a9e1de089611f790", size = 231070 }, - { url = "https://files.pythonhosted.org/packages/a7/b8/b127d3e1f8dd2a5bf286b47b24567ae6363017292dc6dec44656e6246498/multidict-6.4.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:995015cf4a3c0d72cbf453b10a999b92c5629eaf3a0c3e1efb4b5c1f602253bb", size = 229956 }, - { url = "https://files.pythonhosted.org/packages/0c/93/f70a4c35b103fcfe1443059a2bb7f66e5c35f2aea7804105ff214f566009/multidict-6.4.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b0fabae7939d09d7d16a711468c385272fa1b9b7fb0d37e51143585d8e72e0", size = 222599 }, - { url = "https://files.pythonhosted.org/packages/63/8c/e28e0eb2fe34921d6aa32bfc4ac75b09570b4d6818cc95d25499fe08dc1d/multidict-6.4.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61ed4d82f8a1e67eb9eb04f8587970d78fe7cddb4e4d6230b77eda23d27938f9", size = 216136 }, - { url = "https://files.pythonhosted.org/packages/72/f5/fbc81f866585b05f89f99d108be5d6ad170e3b6c4d0723d1a2f6ba5fa918/multidict-6.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:062428944a8dc69df9fdc5d5fc6279421e5f9c75a9ee3f586f274ba7b05ab3c8", size = 228139 }, - { url = "https://files.pythonhosted.org/packages/bb/ba/7d196bad6b85af2307d81f6979c36ed9665f49626f66d883d6c64d156f78/multidict-6.4.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b90e27b4674e6c405ad6c64e515a505c6d113b832df52fdacb6b1ffd1fa9a1d1", size = 226251 }, - { url = "https://files.pythonhosted.org/packages/cc/e2/fae46a370dce79d08b672422a33df721ec8b80105e0ea8d87215ff6b090d/multidict-6.4.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7d50d4abf6729921e9613d98344b74241572b751c6b37feed75fb0c37bd5a817", size = 221868 }, - { url = "https://files.pythonhosted.org/packages/26/20/bbc9a3dec19d5492f54a167f08546656e7aef75d181d3d82541463450e88/multidict-6.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:43fe10524fb0a0514be3954be53258e61d87341008ce4914f8e8b92bee6f875d", size = 233106 }, - { url = "https://files.pythonhosted.org/packages/ee/8d/f30ae8f5ff7a2461177f4d8eb0d8f69f27fb6cfe276b54ec4fd5a282d918/multidict-6.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:236966ca6c472ea4e2d3f02f6673ebfd36ba3f23159c323f5a496869bc8e47c9", size = 230163 }, - { url = "https://files.pythonhosted.org/packages/15/e9/2833f3c218d3c2179f3093f766940ded6b81a49d2e2f9c46ab240d23dfec/multidict-6.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:422a5ec315018e606473ba1f5431e064cf8b2a7468019233dcf8082fabad64c8", size = 225906 }, - { url = "https://files.pythonhosted.org/packages/f1/31/6edab296ac369fd286b845fa5dd4c409e63bc4655ed8c9510fcb477e9ae9/multidict-6.4.3-cp313-cp313-win32.whl", hash = "sha256:f901a5aace8e8c25d78960dcc24c870c8d356660d3b49b93a78bf38eb682aac3", size = 35238 }, - { url = "https://files.pythonhosted.org/packages/23/57/2c0167a1bffa30d9a1383c3dab99d8caae985defc8636934b5668830d2ef/multidict-6.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:1c152c49e42277bc9a2f7b78bd5fa10b13e88d1b0328221e7aef89d5c60a99a5", size = 38799 }, - { url = "https://files.pythonhosted.org/packages/c9/13/2ead63b9ab0d2b3080819268acb297bd66e238070aa8d42af12b08cbee1c/multidict-6.4.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:be8751869e28b9c0d368d94f5afcb4234db66fe8496144547b4b6d6a0645cfc6", size = 68642 }, - { url = "https://files.pythonhosted.org/packages/85/45/f1a751e1eede30c23951e2ae274ce8fad738e8a3d5714be73e0a41b27b16/multidict-6.4.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d4b31f8a68dccbcd2c0ea04f0e014f1defc6b78f0eb8b35f2265e8716a6df0c", size = 40028 }, - { url = "https://files.pythonhosted.org/packages/a7/29/fcc53e886a2cc5595cc4560df333cb9630257bda65003a7eb4e4e0d8f9c1/multidict-6.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:032efeab3049e37eef2ff91271884303becc9e54d740b492a93b7e7266e23756", size = 39424 }, - { url = "https://files.pythonhosted.org/packages/f6/f0/056c81119d8b88703971f937b371795cab1407cd3c751482de5bfe1a04a9/multidict-6.4.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e78006af1a7c8a8007e4f56629d7252668344442f66982368ac06522445e375", size = 226178 }, - { url = "https://files.pythonhosted.org/packages/a3/79/3b7e5fea0aa80583d3a69c9d98b7913dfd4fbc341fb10bb2fb48d35a9c21/multidict-6.4.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:daeac9dd30cda8703c417e4fddccd7c4dc0c73421a0b54a7da2713be125846be", size = 222617 }, - { url = "https://files.pythonhosted.org/packages/06/db/3ed012b163e376fc461e1d6a67de69b408339bc31dc83d39ae9ec3bf9578/multidict-6.4.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f6f90700881438953eae443a9c6f8a509808bc3b185246992c4233ccee37fea", size = 227919 }, - { url = "https://files.pythonhosted.org/packages/b1/db/0433c104bca380989bc04d3b841fc83e95ce0c89f680e9ea4251118b52b6/multidict-6.4.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f84627997008390dd15762128dcf73c3365f4ec0106739cde6c20a07ed198ec8", size = 226097 }, - { url = "https://files.pythonhosted.org/packages/c2/95/910db2618175724dd254b7ae635b6cd8d2947a8b76b0376de7b96d814dab/multidict-6.4.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3307b48cd156153b117c0ea54890a3bdbf858a5b296ddd40dc3852e5f16e9b02", size = 220706 }, - { url = "https://files.pythonhosted.org/packages/d1/af/aa176c6f5f1d901aac957d5258d5e22897fe13948d1e69063ae3d5d0ca01/multidict-6.4.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead46b0fa1dcf5af503a46e9f1c2e80b5d95c6011526352fa5f42ea201526124", size = 211728 }, - { url = "https://files.pythonhosted.org/packages/e7/42/d51cc5fc1527c3717d7f85137d6c79bb7a93cd214c26f1fc57523774dbb5/multidict-6.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1748cb2743bedc339d63eb1bca314061568793acd603a6e37b09a326334c9f44", size = 226276 }, - { url = "https://files.pythonhosted.org/packages/28/6b/d836dea45e0b8432343ba4acf9a8ecaa245da4c0960fb7ab45088a5e568a/multidict-6.4.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:acc9fa606f76fc111b4569348cc23a771cb52c61516dcc6bcef46d612edb483b", size = 212069 }, - { url = "https://files.pythonhosted.org/packages/55/34/0ee1a7adb3560e18ee9289c6e5f7db54edc312b13e5c8263e88ea373d12c/multidict-6.4.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:31469d5832b5885adeb70982e531ce86f8c992334edd2f2254a10fa3182ac504", size = 217858 }, - { url = "https://files.pythonhosted.org/packages/04/08/586d652c2f5acefe0cf4e658eedb4d71d4ba6dfd4f189bd81b400fc1bc6b/multidict-6.4.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ba46b51b6e51b4ef7bfb84b82f5db0dc5e300fb222a8a13b8cd4111898a869cf", size = 226988 }, - { url = "https://files.pythonhosted.org/packages/82/e3/cc59c7e2bc49d7f906fb4ffb6d9c3a3cf21b9f2dd9c96d05bef89c2b1fd1/multidict-6.4.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:389cfefb599edf3fcfd5f64c0410da686f90f5f5e2c4d84e14f6797a5a337af4", size = 220435 }, - { url = "https://files.pythonhosted.org/packages/e0/32/5c3a556118aca9981d883f38c4b1bfae646f3627157f70f4068e5a648955/multidict-6.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:64bc2bbc5fba7b9db5c2c8d750824f41c6994e3882e6d73c903c2afa78d091e4", size = 221494 }, - { url = "https://files.pythonhosted.org/packages/b9/3b/1599631f59024b75c4d6e3069f4502409970a336647502aaf6b62fb7ac98/multidict-6.4.3-cp313-cp313t-win32.whl", hash = "sha256:0ecdc12ea44bab2807d6b4a7e5eef25109ab1c82a8240d86d3c1fc9f3b72efd5", size = 41775 }, - { url = "https://files.pythonhosted.org/packages/e8/4e/09301668d675d02ca8e8e1a3e6be046619e30403f5ada2ed5b080ae28d02/multidict-6.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7146a8742ea71b5d7d955bffcef58a9e6e04efba704b52a460134fefd10a8208", size = 45946 }, - { url = "https://files.pythonhosted.org/packages/62/41/609ef2253da5d1686a85456b8315dec648a45a1d547074db225e94b3dd61/multidict-6.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5427a2679e95a642b7f8b0f761e660c845c8e6fe3141cddd6b62005bd133fc21", size = 65724 }, - { url = "https://files.pythonhosted.org/packages/b5/4e/3a2daf9ccbdb503df7b91cbee240fccc96dd3287397b05ed59673b196cde/multidict-6.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24a8caa26521b9ad09732972927d7b45b66453e6ebd91a3c6a46d811eeb7349b", size = 38659 }, - { url = "https://files.pythonhosted.org/packages/04/f8/3a7ec724c51ad9c1534ebb0a60020e24c12b1fe4c60a4fdd0c97a3383cf4/multidict-6.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6b5a272bc7c36a2cd1b56ddc6bff02e9ce499f9f14ee4a45c45434ef083f2459", size = 37927 }, - { url = "https://files.pythonhosted.org/packages/7f/c5/76c9a8cd657b3a44daf08f14faebb558b00fa22698f58ee7fa3876ade2e4/multidict-6.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf74dc5e212b8c75165b435c43eb0d5e81b6b300a938a4eb82827119115e840", size = 217990 }, - { url = "https://files.pythonhosted.org/packages/ac/b9/6ccb5bfc3747546e096f34c8b2ee91ccab0a92fefe7a9addc4ef9055ab4d/multidict-6.4.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9f35de41aec4b323c71f54b0ca461ebf694fb48bec62f65221f52e0017955b39", size = 213431 }, - { url = "https://files.pythonhosted.org/packages/0b/e9/95af61c79ffabb4a4331fe0736280ef30b324b67772fd018faf408d73f7d/multidict-6.4.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae93e0ff43b6f6892999af64097b18561691ffd835e21a8348a441e256592e1f", size = 228087 }, - { url = "https://files.pythonhosted.org/packages/04/d2/bd7454b40e4d0f21771b2aa077c0e3f4dfb965f209ffce21112743cdadaa/multidict-6.4.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e3929269e9d7eff905d6971d8b8c85e7dbc72c18fb99c8eae6fe0a152f2e343", size = 224061 }, - { url = "https://files.pythonhosted.org/packages/7a/f9/b50679179dd909ba28ce49dca551b40a8349aaed64beececd8ab64589b65/multidict-6.4.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb6214fe1750adc2a1b801a199d64b5a67671bf76ebf24c730b157846d0e90d2", size = 216133 }, - { url = "https://files.pythonhosted.org/packages/8f/47/9b77c483a5183ed734d1272cbe685d7313922806d686c63748997374afc1/multidict-6.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d79cf5c0c6284e90f72123f4a3e4add52d6c6ebb4a9054e88df15b8d08444c6", size = 209868 }, - { url = "https://files.pythonhosted.org/packages/6e/b1/c621ed6098e81404098236a08f7be9274e364cdb0fed12de837030235d19/multidict-6.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2427370f4a255262928cd14533a70d9738dfacadb7563bc3b7f704cc2360fc4e", size = 221723 }, - { url = "https://files.pythonhosted.org/packages/3a/9f/77f41726c1a3e5651e37c67aea5736645484834efd06795b2f8d38318890/multidict-6.4.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:fbd8d737867912b6c5f99f56782b8cb81f978a97b4437a1c476de90a3e41c9a1", size = 211008 }, - { url = "https://files.pythonhosted.org/packages/00/66/eec0484c1de91439ce4e054f754f0ecb1c9d1a5fa09a1c12952fb3717ce9/multidict-6.4.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ee1bf613c448997f73fc4efb4ecebebb1c02268028dd4f11f011f02300cf1e8", size = 216800 }, - { url = "https://files.pythonhosted.org/packages/95/58/a8f07841c6db4bdd8d1ae50cc8910cc63b5078b6dae3b196ec654d888060/multidict-6.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:578568c4ba5f2b8abd956baf8b23790dbfdc953e87d5b110bce343b4a54fc9e7", size = 227661 }, - { url = "https://files.pythonhosted.org/packages/2a/a5/c50b9430fe79d4b04efda204f22450a23cb4ae895734940541141a858089/multidict-6.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a059ad6b80de5b84b9fa02a39400319e62edd39d210b4e4f8c4f1243bdac4752", size = 221821 }, - { url = "https://files.pythonhosted.org/packages/99/4c/2b69c52c4b1357d197c38a913fcf45b4200af79adfcdf96d88cb02d18f5b/multidict-6.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dd53893675b729a965088aaadd6a1f326a72b83742b056c1065bdd2e2a42b4df", size = 216332 }, - { url = "https://files.pythonhosted.org/packages/1b/39/63d9bd977aed6a053955b30aad38bbfe1f0f8d7462f80760b498387c91ee/multidict-6.4.3-cp39-cp39-win32.whl", hash = "sha256:abcfed2c4c139f25c2355e180bcc077a7cae91eefbb8b3927bb3f836c9586f1f", size = 35087 }, - { url = "https://files.pythonhosted.org/packages/8f/d4/c6b8936fa9ff5e77fbba9ba431bc380ad0f8e6442a05c7fb6bfe35fdff60/multidict-6.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:b1b389ae17296dd739015d5ddb222ee99fd66adeae910de21ac950e00979d897", size = 38680 }, - { url = "https://files.pythonhosted.org/packages/96/10/7d526c8974f017f1e7ca584c71ee62a638e9334d8d33f27d7cdfc9ae79e4/multidict-6.4.3-py3-none-any.whl", hash = "sha256:59fe01ee8e2a1e8ceb3f6dbb216b09c8d9f4ef1c22c4fc825d045a147fa2ebc9", size = 10400 }, +sdist = { url = "https://files.pythonhosted.org/packages/da/2c/e367dfb4c6538614a0c9453e510d75d66099edf1c4e69da1b5ce691a1931/multidict-6.4.3.tar.gz", hash = "sha256:3ada0b058c9f213c5f95ba301f922d402ac234f1111a7d8fd70f1b99f3c281ec", size = 89372, upload-time = "2025-04-10T22:20:17.956Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/44/45e798d4cd1b5dfe41ddf36266c7aca6d954e3c7a8b0d599ad555ce2b4f8/multidict-6.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32a998bd8a64ca48616eac5a8c1cc4fa38fb244a3facf2eeb14abe186e0f6cc5", size = 65822, upload-time = "2025-04-10T22:17:32.83Z" }, + { url = "https://files.pythonhosted.org/packages/10/fb/9ea024f928503f8c758f8463759d21958bf27b1f7a1103df73e5022e6a7c/multidict-6.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a54ec568f1fc7f3c313c2f3b16e5db346bf3660e1309746e7fccbbfded856188", size = 38706, upload-time = "2025-04-10T22:17:35.028Z" }, + { url = "https://files.pythonhosted.org/packages/6d/eb/7013316febca37414c0e1469fccadcb1a0e4315488f8f57ca5d29b384863/multidict-6.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a7be07e5df178430621c716a63151165684d3e9958f2bbfcb644246162007ab7", size = 37979, upload-time = "2025-04-10T22:17:36.626Z" }, + { url = "https://files.pythonhosted.org/packages/64/28/5a7bf4e7422613ea80f9ebc529d3845b20a422cfa94d4355504ac98047ee/multidict-6.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b128dbf1c939674a50dd0b28f12c244d90e5015e751a4f339a96c54f7275e291", size = 220233, upload-time = "2025-04-10T22:17:37.807Z" }, + { url = "https://files.pythonhosted.org/packages/52/05/b4c58850f71befde6a16548968b48331a155a80627750b150bb5962e4dea/multidict-6.4.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9cb19dfd83d35b6ff24a4022376ea6e45a2beba8ef3f0836b8a4b288b6ad685", size = 217762, upload-time = "2025-04-10T22:17:39.493Z" }, + { url = "https://files.pythonhosted.org/packages/99/a3/393e23bba1e9a00f95b3957acd8f5e3ee3446e78c550f593be25f9de0483/multidict-6.4.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3cf62f8e447ea2c1395afa289b332e49e13d07435369b6f4e41f887db65b40bf", size = 230699, upload-time = "2025-04-10T22:17:41.207Z" }, + { url = "https://files.pythonhosted.org/packages/9c/a7/52c63069eb1a079f824257bb8045d93e692fa2eb34d08323d1fdbdfc398a/multidict-6.4.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:909f7d43ff8f13d1adccb6a397094adc369d4da794407f8dd592c51cf0eae4b1", size = 226801, upload-time = "2025-04-10T22:17:42.62Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e9/40d2b73e7d6574d91074d83477a990e3701affbe8b596010d4f5e6c7a6fa/multidict-6.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0bb8f8302fbc7122033df959e25777b0b7659b1fd6bcb9cb6bed76b5de67afef", size = 219833, upload-time = "2025-04-10T22:17:44.046Z" }, + { url = "https://files.pythonhosted.org/packages/e4/6a/0572b22fe63c632254f55a1c1cb7d29f644002b1d8731d6103a290edc754/multidict-6.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:224b79471b4f21169ea25ebc37ed6f058040c578e50ade532e2066562597b8a9", size = 212920, upload-time = "2025-04-10T22:17:45.48Z" }, + { url = "https://files.pythonhosted.org/packages/33/fe/c63735db9dece0053868b2d808bcc2592a83ce1830bc98243852a2b34d42/multidict-6.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a7bd27f7ab3204f16967a6f899b3e8e9eb3362c0ab91f2ee659e0345445e0078", size = 225263, upload-time = "2025-04-10T22:17:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/47/c2/2db296d64d41525110c27ed38fadd5eb571c6b936233e75a5ea61b14e337/multidict-6.4.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:99592bd3162e9c664671fd14e578a33bfdba487ea64bcb41d281286d3c870ad7", size = 214249, upload-time = "2025-04-10T22:17:48.95Z" }, + { url = "https://files.pythonhosted.org/packages/7e/74/8bc26e54c79f9a0f111350b1b28a9cacaaee53ecafccd53c90e59754d55a/multidict-6.4.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a62d78a1c9072949018cdb05d3c533924ef8ac9bcb06cbf96f6d14772c5cd451", size = 221650, upload-time = "2025-04-10T22:17:50.265Z" }, + { url = "https://files.pythonhosted.org/packages/af/d7/2ce87606e3799d9a08a941f4c170930a9895886ea8bd0eca75c44baeebe3/multidict-6.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ccdde001578347e877ca4f629450973c510e88e8865d5aefbcb89b852ccc666", size = 231235, upload-time = "2025-04-10T22:17:51.579Z" }, + { url = "https://files.pythonhosted.org/packages/07/e1/d191a7ad3b90c613fc4b130d07a41c380e249767586148709b54d006ca17/multidict-6.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:eccb67b0e78aa2e38a04c5ecc13bab325a43e5159a181a9d1a6723db913cbb3c", size = 226056, upload-time = "2025-04-10T22:17:53.092Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/a57490cf6a8d5854f4af2d17dfc54924f37fbb683986e133b76710a36079/multidict-6.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8b6fcf6054fc4114a27aa865f8840ef3d675f9316e81868e0ad5866184a6cba5", size = 220014, upload-time = "2025-04-10T22:17:54.729Z" }, + { url = "https://files.pythonhosted.org/packages/5c/b1/be04fa9f08c684e9e27cca85b4ab94c10f017ec07c4c631af9c8c10bb275/multidict-6.4.3-cp310-cp310-win32.whl", hash = "sha256:f92c7f62d59373cd93bc9969d2da9b4b21f78283b1379ba012f7ee8127b3152e", size = 35042, upload-time = "2025-04-10T22:17:56.615Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ca/8888f99892513001fa900eef11bafbf38ff3485109510487de009da85748/multidict-6.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:b57e28dbc031d13916b946719f213c494a517b442d7b48b29443e79610acd887", size = 38506, upload-time = "2025-04-10T22:17:58.119Z" }, + { url = "https://files.pythonhosted.org/packages/16/e0/53cf7f27eda48fffa53cfd4502329ed29e00efb9e4ce41362cbf8aa54310/multidict-6.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f6f19170197cc29baccd33ccc5b5d6a331058796485857cf34f7635aa25fb0cd", size = 65259, upload-time = "2025-04-10T22:17:59.632Z" }, + { url = "https://files.pythonhosted.org/packages/44/79/1dcd93ce7070cf01c2ee29f781c42b33c64fce20033808f1cc9ec8413d6e/multidict-6.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2882bf27037eb687e49591690e5d491e677272964f9ec7bc2abbe09108bdfb8", size = 38451, upload-time = "2025-04-10T22:18:01.202Z" }, + { url = "https://files.pythonhosted.org/packages/f4/35/2292cf29ab5f0d0b3613fad1b75692148959d3834d806be1885ceb49a8ff/multidict-6.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbf226ac85f7d6b6b9ba77db4ec0704fde88463dc17717aec78ec3c8546c70ad", size = 37706, upload-time = "2025-04-10T22:18:02.276Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d1/6b157110b2b187b5a608b37714acb15ee89ec773e3800315b0107ea648cd/multidict-6.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e329114f82ad4b9dd291bef614ea8971ec119ecd0f54795109976de75c9a852", size = 226669, upload-time = "2025-04-10T22:18:03.436Z" }, + { url = "https://files.pythonhosted.org/packages/40/7f/61a476450651f177c5570e04bd55947f693077ba7804fe9717ee9ae8de04/multidict-6.4.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1f4e0334d7a555c63f5c8952c57ab6f1c7b4f8c7f3442df689fc9f03df315c08", size = 223182, upload-time = "2025-04-10T22:18:04.922Z" }, + { url = "https://files.pythonhosted.org/packages/51/7b/eaf7502ac4824cdd8edcf5723e2e99f390c879866aec7b0c420267b53749/multidict-6.4.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:740915eb776617b57142ce0bb13b7596933496e2f798d3d15a20614adf30d229", size = 235025, upload-time = "2025-04-10T22:18:06.274Z" }, + { url = "https://files.pythonhosted.org/packages/3b/f6/facdbbd73c96b67a93652774edd5778ab1167854fa08ea35ad004b1b70ad/multidict-6.4.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255dac25134d2b141c944b59a0d2f7211ca12a6d4779f7586a98b4b03ea80508", size = 231481, upload-time = "2025-04-10T22:18:07.742Z" }, + { url = "https://files.pythonhosted.org/packages/70/57/c008e861b3052405eebf921fd56a748322d8c44dcfcab164fffbccbdcdc4/multidict-6.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4e8535bd4d741039b5aad4285ecd9b902ef9e224711f0b6afda6e38d7ac02c7", size = 223492, upload-time = "2025-04-10T22:18:09.095Z" }, + { url = "https://files.pythonhosted.org/packages/30/4d/7d8440d3a12a6ae5d6b202d6e7f2ac6ab026e04e99aaf1b73f18e6bc34bc/multidict-6.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c433a33be000dd968f5750722eaa0991037be0be4a9d453eba121774985bc8", size = 217279, upload-time = "2025-04-10T22:18:10.474Z" }, + { url = "https://files.pythonhosted.org/packages/7f/e7/bca0df4dd057597b94138d2d8af04eb3c27396a425b1b0a52e082f9be621/multidict-6.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4eb33b0bdc50acd538f45041f5f19945a1f32b909b76d7b117c0c25d8063df56", size = 228733, upload-time = "2025-04-10T22:18:11.793Z" }, + { url = "https://files.pythonhosted.org/packages/88/f5/383827c3f1c38d7c92dbad00a8a041760228573b1c542fbf245c37bbca8a/multidict-6.4.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:75482f43465edefd8a5d72724887ccdcd0c83778ded8f0cb1e0594bf71736cc0", size = 218089, upload-time = "2025-04-10T22:18:13.153Z" }, + { url = "https://files.pythonhosted.org/packages/36/8a/a5174e8a7d8b94b4c8f9c1e2cf5d07451f41368ffe94d05fc957215b8e72/multidict-6.4.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ce5b3082e86aee80b3925ab4928198450d8e5b6466e11501fe03ad2191c6d777", size = 225257, upload-time = "2025-04-10T22:18:14.654Z" }, + { url = "https://files.pythonhosted.org/packages/8c/76/1d4b7218f0fd00b8e5c90b88df2e45f8af127f652f4e41add947fa54c1c4/multidict-6.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e413152e3212c4d39f82cf83c6f91be44bec9ddea950ce17af87fbf4e32ca6b2", size = 234728, upload-time = "2025-04-10T22:18:16.236Z" }, + { url = "https://files.pythonhosted.org/packages/64/44/18372a4f6273fc7ca25630d7bf9ae288cde64f29593a078bff450c7170b6/multidict-6.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8aac2eeff69b71f229a405c0a4b61b54bade8e10163bc7b44fcd257949620618", size = 230087, upload-time = "2025-04-10T22:18:17.979Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/28728c314a698d8a6d9491fcacc897077348ec28dd85884d09e64df8a855/multidict-6.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ab583ac203af1d09034be41458feeab7863c0635c650a16f15771e1386abf2d7", size = 223137, upload-time = "2025-04-10T22:18:19.362Z" }, + { url = "https://files.pythonhosted.org/packages/22/50/785bb2b3fe16051bc91c70a06a919f26312da45c34db97fc87441d61e343/multidict-6.4.3-cp311-cp311-win32.whl", hash = "sha256:1b2019317726f41e81154df636a897de1bfe9228c3724a433894e44cd2512378", size = 34959, upload-time = "2025-04-10T22:18:20.728Z" }, + { url = "https://files.pythonhosted.org/packages/2f/63/2a22e099ae2f4d92897618c00c73a09a08a2a9aa14b12736965bf8d59fd3/multidict-6.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:43173924fa93c7486402217fab99b60baf78d33806af299c56133a3755f69589", size = 38541, upload-time = "2025-04-10T22:18:22.001Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bb/3abdaf8fe40e9226ce8a2ba5ecf332461f7beec478a455d6587159f1bf92/multidict-6.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1f1c2f58f08b36f8475f3ec6f5aeb95270921d418bf18f90dffd6be5c7b0e676", size = 64019, upload-time = "2025-04-10T22:18:23.174Z" }, + { url = "https://files.pythonhosted.org/packages/7e/b5/1b2e8de8217d2e89db156625aa0fe4a6faad98972bfe07a7b8c10ef5dd6b/multidict-6.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:26ae9ad364fc61b936fb7bf4c9d8bd53f3a5b4417142cd0be5c509d6f767e2f1", size = 37925, upload-time = "2025-04-10T22:18:24.834Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e2/3ca91c112644a395c8eae017144c907d173ea910c913ff8b62549dcf0bbf/multidict-6.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:659318c6c8a85f6ecfc06b4e57529e5a78dfdd697260cc81f683492ad7e9435a", size = 37008, upload-time = "2025-04-10T22:18:26.069Z" }, + { url = "https://files.pythonhosted.org/packages/60/23/79bc78146c7ac8d1ac766b2770ca2e07c2816058b8a3d5da6caed8148637/multidict-6.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1eb72c741fd24d5a28242ce72bb61bc91f8451877131fa3fe930edb195f7054", size = 224374, upload-time = "2025-04-10T22:18:27.714Z" }, + { url = "https://files.pythonhosted.org/packages/86/35/77950ed9ebd09136003a85c1926ba42001ca5be14feb49710e4334ee199b/multidict-6.4.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3cd06d88cb7398252284ee75c8db8e680aa0d321451132d0dba12bc995f0adcc", size = 230869, upload-time = "2025-04-10T22:18:29.162Z" }, + { url = "https://files.pythonhosted.org/packages/49/97/2a33c6e7d90bc116c636c14b2abab93d6521c0c052d24bfcc231cbf7f0e7/multidict-6.4.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4543d8dc6470a82fde92b035a92529317191ce993533c3c0c68f56811164ed07", size = 231949, upload-time = "2025-04-10T22:18:30.679Z" }, + { url = "https://files.pythonhosted.org/packages/56/ce/e9b5d9fcf854f61d6686ada7ff64893a7a5523b2a07da6f1265eaaea5151/multidict-6.4.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30a3ebdc068c27e9d6081fca0e2c33fdf132ecea703a72ea216b81a66860adde", size = 231032, upload-time = "2025-04-10T22:18:32.146Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ac/7ced59dcdfeddd03e601edb05adff0c66d81ed4a5160c443e44f2379eef0/multidict-6.4.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b038f10e23f277153f86f95c777ba1958bcd5993194fda26a1d06fae98b2f00c", size = 223517, upload-time = "2025-04-10T22:18:33.538Z" }, + { url = "https://files.pythonhosted.org/packages/db/e6/325ed9055ae4e085315193a1b58bdb4d7fc38ffcc1f4975cfca97d015e17/multidict-6.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c605a2b2dc14282b580454b9b5d14ebe0668381a3a26d0ac39daa0ca115eb2ae", size = 216291, upload-time = "2025-04-10T22:18:34.962Z" }, + { url = "https://files.pythonhosted.org/packages/fa/84/eeee6d477dd9dcb7691c3bb9d08df56017f5dd15c730bcc9383dcf201cf4/multidict-6.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8bd2b875f4ca2bb527fe23e318ddd509b7df163407b0fb717df229041c6df5d3", size = 228982, upload-time = "2025-04-10T22:18:36.443Z" }, + { url = "https://files.pythonhosted.org/packages/82/94/4d1f3e74e7acf8b0c85db350e012dcc61701cd6668bc2440bb1ecb423c90/multidict-6.4.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c2e98c840c9c8e65c0e04b40c6c5066c8632678cd50c8721fdbcd2e09f21a507", size = 226823, upload-time = "2025-04-10T22:18:37.924Z" }, + { url = "https://files.pythonhosted.org/packages/09/f0/1e54b95bda7cd01080e5732f9abb7b76ab5cc795b66605877caeb2197476/multidict-6.4.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66eb80dd0ab36dbd559635e62fba3083a48a252633164857a1d1684f14326427", size = 222714, upload-time = "2025-04-10T22:18:39.807Z" }, + { url = "https://files.pythonhosted.org/packages/e7/a2/f6cbca875195bd65a3e53b37ab46486f3cc125bdeab20eefe5042afa31fb/multidict-6.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c23831bdee0a2a3cf21be057b5e5326292f60472fb6c6f86392bbf0de70ba731", size = 233739, upload-time = "2025-04-10T22:18:41.341Z" }, + { url = "https://files.pythonhosted.org/packages/79/68/9891f4d2b8569554723ddd6154375295f789dc65809826c6fb96a06314fd/multidict-6.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1535cec6443bfd80d028052e9d17ba6ff8a5a3534c51d285ba56c18af97e9713", size = 230809, upload-time = "2025-04-10T22:18:42.817Z" }, + { url = "https://files.pythonhosted.org/packages/e6/72/a7be29ba1e87e4fc5ceb44dabc7940b8005fd2436a332a23547709315f70/multidict-6.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b73e7227681f85d19dec46e5b881827cd354aabe46049e1a61d2f9aaa4e285a", size = 226934, upload-time = "2025-04-10T22:18:44.311Z" }, + { url = "https://files.pythonhosted.org/packages/12/c1/259386a9ad6840ff7afc686da96808b503d152ac4feb3a96c651dc4f5abf/multidict-6.4.3-cp312-cp312-win32.whl", hash = "sha256:8eac0c49df91b88bf91f818e0a24c1c46f3622978e2c27035bfdca98e0e18124", size = 35242, upload-time = "2025-04-10T22:18:46.193Z" }, + { url = "https://files.pythonhosted.org/packages/06/24/c8fdff4f924d37225dc0c56a28b1dca10728fc2233065fafeb27b4b125be/multidict-6.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:11990b5c757d956cd1db7cb140be50a63216af32cd6506329c2c59d732d802db", size = 38635, upload-time = "2025-04-10T22:18:47.498Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4b/86fd786d03915c6f49998cf10cd5fe6b6ac9e9a071cb40885d2e080fb90d/multidict-6.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a76534263d03ae0cfa721fea40fd2b5b9d17a6f85e98025931d41dc49504474", size = 63831, upload-time = "2025-04-10T22:18:48.748Z" }, + { url = "https://files.pythonhosted.org/packages/45/05/9b51fdf7aef2563340a93be0a663acba2c428c4daeaf3960d92d53a4a930/multidict-6.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:805031c2f599eee62ac579843555ed1ce389ae00c7e9f74c2a1b45e0564a88dd", size = 37888, upload-time = "2025-04-10T22:18:50.021Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/53fc25394386c911822419b522181227ca450cf57fea76e6188772a1bd91/multidict-6.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c56c179839d5dcf51d565132185409d1d5dd8e614ba501eb79023a6cab25576b", size = 36852, upload-time = "2025-04-10T22:18:51.246Z" }, + { url = "https://files.pythonhosted.org/packages/8a/68/7b99c751e822467c94a235b810a2fd4047d4ecb91caef6b5c60116991c4b/multidict-6.4.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c64f4ddb3886dd8ab71b68a7431ad4aa01a8fa5be5b11543b29674f29ca0ba3", size = 223644, upload-time = "2025-04-10T22:18:52.965Z" }, + { url = "https://files.pythonhosted.org/packages/80/1b/d458d791e4dd0f7e92596667784fbf99e5c8ba040affe1ca04f06b93ae92/multidict-6.4.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3002a856367c0b41cad6784f5b8d3ab008eda194ed7864aaa58f65312e2abcac", size = 230446, upload-time = "2025-04-10T22:18:54.509Z" }, + { url = "https://files.pythonhosted.org/packages/e2/46/9793378d988905491a7806d8987862dc5a0bae8a622dd896c4008c7b226b/multidict-6.4.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d75e621e7d887d539d6e1d789f0c64271c250276c333480a9e1de089611f790", size = 231070, upload-time = "2025-04-10T22:18:56.019Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b8/b127d3e1f8dd2a5bf286b47b24567ae6363017292dc6dec44656e6246498/multidict-6.4.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:995015cf4a3c0d72cbf453b10a999b92c5629eaf3a0c3e1efb4b5c1f602253bb", size = 229956, upload-time = "2025-04-10T22:18:59.146Z" }, + { url = "https://files.pythonhosted.org/packages/0c/93/f70a4c35b103fcfe1443059a2bb7f66e5c35f2aea7804105ff214f566009/multidict-6.4.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b0fabae7939d09d7d16a711468c385272fa1b9b7fb0d37e51143585d8e72e0", size = 222599, upload-time = "2025-04-10T22:19:00.657Z" }, + { url = "https://files.pythonhosted.org/packages/63/8c/e28e0eb2fe34921d6aa32bfc4ac75b09570b4d6818cc95d25499fe08dc1d/multidict-6.4.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61ed4d82f8a1e67eb9eb04f8587970d78fe7cddb4e4d6230b77eda23d27938f9", size = 216136, upload-time = "2025-04-10T22:19:02.244Z" }, + { url = "https://files.pythonhosted.org/packages/72/f5/fbc81f866585b05f89f99d108be5d6ad170e3b6c4d0723d1a2f6ba5fa918/multidict-6.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:062428944a8dc69df9fdc5d5fc6279421e5f9c75a9ee3f586f274ba7b05ab3c8", size = 228139, upload-time = "2025-04-10T22:19:04.151Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ba/7d196bad6b85af2307d81f6979c36ed9665f49626f66d883d6c64d156f78/multidict-6.4.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b90e27b4674e6c405ad6c64e515a505c6d113b832df52fdacb6b1ffd1fa9a1d1", size = 226251, upload-time = "2025-04-10T22:19:06.117Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e2/fae46a370dce79d08b672422a33df721ec8b80105e0ea8d87215ff6b090d/multidict-6.4.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7d50d4abf6729921e9613d98344b74241572b751c6b37feed75fb0c37bd5a817", size = 221868, upload-time = "2025-04-10T22:19:07.981Z" }, + { url = "https://files.pythonhosted.org/packages/26/20/bbc9a3dec19d5492f54a167f08546656e7aef75d181d3d82541463450e88/multidict-6.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:43fe10524fb0a0514be3954be53258e61d87341008ce4914f8e8b92bee6f875d", size = 233106, upload-time = "2025-04-10T22:19:09.5Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8d/f30ae8f5ff7a2461177f4d8eb0d8f69f27fb6cfe276b54ec4fd5a282d918/multidict-6.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:236966ca6c472ea4e2d3f02f6673ebfd36ba3f23159c323f5a496869bc8e47c9", size = 230163, upload-time = "2025-04-10T22:19:11Z" }, + { url = "https://files.pythonhosted.org/packages/15/e9/2833f3c218d3c2179f3093f766940ded6b81a49d2e2f9c46ab240d23dfec/multidict-6.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:422a5ec315018e606473ba1f5431e064cf8b2a7468019233dcf8082fabad64c8", size = 225906, upload-time = "2025-04-10T22:19:12.875Z" }, + { url = "https://files.pythonhosted.org/packages/f1/31/6edab296ac369fd286b845fa5dd4c409e63bc4655ed8c9510fcb477e9ae9/multidict-6.4.3-cp313-cp313-win32.whl", hash = "sha256:f901a5aace8e8c25d78960dcc24c870c8d356660d3b49b93a78bf38eb682aac3", size = 35238, upload-time = "2025-04-10T22:19:14.41Z" }, + { url = "https://files.pythonhosted.org/packages/23/57/2c0167a1bffa30d9a1383c3dab99d8caae985defc8636934b5668830d2ef/multidict-6.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:1c152c49e42277bc9a2f7b78bd5fa10b13e88d1b0328221e7aef89d5c60a99a5", size = 38799, upload-time = "2025-04-10T22:19:15.869Z" }, + { url = "https://files.pythonhosted.org/packages/c9/13/2ead63b9ab0d2b3080819268acb297bd66e238070aa8d42af12b08cbee1c/multidict-6.4.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:be8751869e28b9c0d368d94f5afcb4234db66fe8496144547b4b6d6a0645cfc6", size = 68642, upload-time = "2025-04-10T22:19:17.527Z" }, + { url = "https://files.pythonhosted.org/packages/85/45/f1a751e1eede30c23951e2ae274ce8fad738e8a3d5714be73e0a41b27b16/multidict-6.4.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d4b31f8a68dccbcd2c0ea04f0e014f1defc6b78f0eb8b35f2265e8716a6df0c", size = 40028, upload-time = "2025-04-10T22:19:19.465Z" }, + { url = "https://files.pythonhosted.org/packages/a7/29/fcc53e886a2cc5595cc4560df333cb9630257bda65003a7eb4e4e0d8f9c1/multidict-6.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:032efeab3049e37eef2ff91271884303becc9e54d740b492a93b7e7266e23756", size = 39424, upload-time = "2025-04-10T22:19:20.762Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f0/056c81119d8b88703971f937b371795cab1407cd3c751482de5bfe1a04a9/multidict-6.4.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e78006af1a7c8a8007e4f56629d7252668344442f66982368ac06522445e375", size = 226178, upload-time = "2025-04-10T22:19:22.17Z" }, + { url = "https://files.pythonhosted.org/packages/a3/79/3b7e5fea0aa80583d3a69c9d98b7913dfd4fbc341fb10bb2fb48d35a9c21/multidict-6.4.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:daeac9dd30cda8703c417e4fddccd7c4dc0c73421a0b54a7da2713be125846be", size = 222617, upload-time = "2025-04-10T22:19:23.773Z" }, + { url = "https://files.pythonhosted.org/packages/06/db/3ed012b163e376fc461e1d6a67de69b408339bc31dc83d39ae9ec3bf9578/multidict-6.4.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f6f90700881438953eae443a9c6f8a509808bc3b185246992c4233ccee37fea", size = 227919, upload-time = "2025-04-10T22:19:25.35Z" }, + { url = "https://files.pythonhosted.org/packages/b1/db/0433c104bca380989bc04d3b841fc83e95ce0c89f680e9ea4251118b52b6/multidict-6.4.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f84627997008390dd15762128dcf73c3365f4ec0106739cde6c20a07ed198ec8", size = 226097, upload-time = "2025-04-10T22:19:27.183Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/910db2618175724dd254b7ae635b6cd8d2947a8b76b0376de7b96d814dab/multidict-6.4.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3307b48cd156153b117c0ea54890a3bdbf858a5b296ddd40dc3852e5f16e9b02", size = 220706, upload-time = "2025-04-10T22:19:28.882Z" }, + { url = "https://files.pythonhosted.org/packages/d1/af/aa176c6f5f1d901aac957d5258d5e22897fe13948d1e69063ae3d5d0ca01/multidict-6.4.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead46b0fa1dcf5af503a46e9f1c2e80b5d95c6011526352fa5f42ea201526124", size = 211728, upload-time = "2025-04-10T22:19:30.481Z" }, + { url = "https://files.pythonhosted.org/packages/e7/42/d51cc5fc1527c3717d7f85137d6c79bb7a93cd214c26f1fc57523774dbb5/multidict-6.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1748cb2743bedc339d63eb1bca314061568793acd603a6e37b09a326334c9f44", size = 226276, upload-time = "2025-04-10T22:19:32.454Z" }, + { url = "https://files.pythonhosted.org/packages/28/6b/d836dea45e0b8432343ba4acf9a8ecaa245da4c0960fb7ab45088a5e568a/multidict-6.4.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:acc9fa606f76fc111b4569348cc23a771cb52c61516dcc6bcef46d612edb483b", size = 212069, upload-time = "2025-04-10T22:19:34.17Z" }, + { url = "https://files.pythonhosted.org/packages/55/34/0ee1a7adb3560e18ee9289c6e5f7db54edc312b13e5c8263e88ea373d12c/multidict-6.4.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:31469d5832b5885adeb70982e531ce86f8c992334edd2f2254a10fa3182ac504", size = 217858, upload-time = "2025-04-10T22:19:35.879Z" }, + { url = "https://files.pythonhosted.org/packages/04/08/586d652c2f5acefe0cf4e658eedb4d71d4ba6dfd4f189bd81b400fc1bc6b/multidict-6.4.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ba46b51b6e51b4ef7bfb84b82f5db0dc5e300fb222a8a13b8cd4111898a869cf", size = 226988, upload-time = "2025-04-10T22:19:37.434Z" }, + { url = "https://files.pythonhosted.org/packages/82/e3/cc59c7e2bc49d7f906fb4ffb6d9c3a3cf21b9f2dd9c96d05bef89c2b1fd1/multidict-6.4.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:389cfefb599edf3fcfd5f64c0410da686f90f5f5e2c4d84e14f6797a5a337af4", size = 220435, upload-time = "2025-04-10T22:19:39.005Z" }, + { url = "https://files.pythonhosted.org/packages/e0/32/5c3a556118aca9981d883f38c4b1bfae646f3627157f70f4068e5a648955/multidict-6.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:64bc2bbc5fba7b9db5c2c8d750824f41c6994e3882e6d73c903c2afa78d091e4", size = 221494, upload-time = "2025-04-10T22:19:41.447Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3b/1599631f59024b75c4d6e3069f4502409970a336647502aaf6b62fb7ac98/multidict-6.4.3-cp313-cp313t-win32.whl", hash = "sha256:0ecdc12ea44bab2807d6b4a7e5eef25109ab1c82a8240d86d3c1fc9f3b72efd5", size = 41775, upload-time = "2025-04-10T22:19:43.707Z" }, + { url = "https://files.pythonhosted.org/packages/e8/4e/09301668d675d02ca8e8e1a3e6be046619e30403f5ada2ed5b080ae28d02/multidict-6.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7146a8742ea71b5d7d955bffcef58a9e6e04efba704b52a460134fefd10a8208", size = 45946, upload-time = "2025-04-10T22:19:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/62/41/609ef2253da5d1686a85456b8315dec648a45a1d547074db225e94b3dd61/multidict-6.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5427a2679e95a642b7f8b0f761e660c845c8e6fe3141cddd6b62005bd133fc21", size = 65724, upload-time = "2025-04-10T22:19:46.917Z" }, + { url = "https://files.pythonhosted.org/packages/b5/4e/3a2daf9ccbdb503df7b91cbee240fccc96dd3287397b05ed59673b196cde/multidict-6.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24a8caa26521b9ad09732972927d7b45b66453e6ebd91a3c6a46d811eeb7349b", size = 38659, upload-time = "2025-04-10T22:19:48.306Z" }, + { url = "https://files.pythonhosted.org/packages/04/f8/3a7ec724c51ad9c1534ebb0a60020e24c12b1fe4c60a4fdd0c97a3383cf4/multidict-6.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6b5a272bc7c36a2cd1b56ddc6bff02e9ce499f9f14ee4a45c45434ef083f2459", size = 37927, upload-time = "2025-04-10T22:19:49.733Z" }, + { url = "https://files.pythonhosted.org/packages/7f/c5/76c9a8cd657b3a44daf08f14faebb558b00fa22698f58ee7fa3876ade2e4/multidict-6.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf74dc5e212b8c75165b435c43eb0d5e81b6b300a938a4eb82827119115e840", size = 217990, upload-time = "2025-04-10T22:19:51.577Z" }, + { url = "https://files.pythonhosted.org/packages/ac/b9/6ccb5bfc3747546e096f34c8b2ee91ccab0a92fefe7a9addc4ef9055ab4d/multidict-6.4.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9f35de41aec4b323c71f54b0ca461ebf694fb48bec62f65221f52e0017955b39", size = 213431, upload-time = "2025-04-10T22:19:53.37Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e9/95af61c79ffabb4a4331fe0736280ef30b324b67772fd018faf408d73f7d/multidict-6.4.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae93e0ff43b6f6892999af64097b18561691ffd835e21a8348a441e256592e1f", size = 228087, upload-time = "2025-04-10T22:19:55.008Z" }, + { url = "https://files.pythonhosted.org/packages/04/d2/bd7454b40e4d0f21771b2aa077c0e3f4dfb965f209ffce21112743cdadaa/multidict-6.4.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e3929269e9d7eff905d6971d8b8c85e7dbc72c18fb99c8eae6fe0a152f2e343", size = 224061, upload-time = "2025-04-10T22:19:56.643Z" }, + { url = "https://files.pythonhosted.org/packages/7a/f9/b50679179dd909ba28ce49dca551b40a8349aaed64beececd8ab64589b65/multidict-6.4.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb6214fe1750adc2a1b801a199d64b5a67671bf76ebf24c730b157846d0e90d2", size = 216133, upload-time = "2025-04-10T22:19:58.33Z" }, + { url = "https://files.pythonhosted.org/packages/8f/47/9b77c483a5183ed734d1272cbe685d7313922806d686c63748997374afc1/multidict-6.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d79cf5c0c6284e90f72123f4a3e4add52d6c6ebb4a9054e88df15b8d08444c6", size = 209868, upload-time = "2025-04-10T22:20:00.529Z" }, + { url = "https://files.pythonhosted.org/packages/6e/b1/c621ed6098e81404098236a08f7be9274e364cdb0fed12de837030235d19/multidict-6.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2427370f4a255262928cd14533a70d9738dfacadb7563bc3b7f704cc2360fc4e", size = 221723, upload-time = "2025-04-10T22:20:02.696Z" }, + { url = "https://files.pythonhosted.org/packages/3a/9f/77f41726c1a3e5651e37c67aea5736645484834efd06795b2f8d38318890/multidict-6.4.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:fbd8d737867912b6c5f99f56782b8cb81f978a97b4437a1c476de90a3e41c9a1", size = 211008, upload-time = "2025-04-10T22:20:04.418Z" }, + { url = "https://files.pythonhosted.org/packages/00/66/eec0484c1de91439ce4e054f754f0ecb1c9d1a5fa09a1c12952fb3717ce9/multidict-6.4.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ee1bf613c448997f73fc4efb4ecebebb1c02268028dd4f11f011f02300cf1e8", size = 216800, upload-time = "2025-04-10T22:20:06.088Z" }, + { url = "https://files.pythonhosted.org/packages/95/58/a8f07841c6db4bdd8d1ae50cc8910cc63b5078b6dae3b196ec654d888060/multidict-6.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:578568c4ba5f2b8abd956baf8b23790dbfdc953e87d5b110bce343b4a54fc9e7", size = 227661, upload-time = "2025-04-10T22:20:07.807Z" }, + { url = "https://files.pythonhosted.org/packages/2a/a5/c50b9430fe79d4b04efda204f22450a23cb4ae895734940541141a858089/multidict-6.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a059ad6b80de5b84b9fa02a39400319e62edd39d210b4e4f8c4f1243bdac4752", size = 221821, upload-time = "2025-04-10T22:20:09.517Z" }, + { url = "https://files.pythonhosted.org/packages/99/4c/2b69c52c4b1357d197c38a913fcf45b4200af79adfcdf96d88cb02d18f5b/multidict-6.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dd53893675b729a965088aaadd6a1f326a72b83742b056c1065bdd2e2a42b4df", size = 216332, upload-time = "2025-04-10T22:20:11.237Z" }, + { url = "https://files.pythonhosted.org/packages/1b/39/63d9bd977aed6a053955b30aad38bbfe1f0f8d7462f80760b498387c91ee/multidict-6.4.3-cp39-cp39-win32.whl", hash = "sha256:abcfed2c4c139f25c2355e180bcc077a7cae91eefbb8b3927bb3f836c9586f1f", size = 35087, upload-time = "2025-04-10T22:20:12.971Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d4/c6b8936fa9ff5e77fbba9ba431bc380ad0f8e6442a05c7fb6bfe35fdff60/multidict-6.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:b1b389ae17296dd739015d5ddb222ee99fd66adeae910de21ac950e00979d897", size = 38680, upload-time = "2025-04-10T22:20:14.974Z" }, + { url = "https://files.pythonhosted.org/packages/96/10/7d526c8974f017f1e7ca584c71ee62a638e9334d8d33f27d7cdfc9ae79e4/multidict-6.4.3-py3-none-any.whl", hash = "sha256:59fe01ee8e2a1e8ceb3f6dbb216b09c8d9f4ef1c22c4fc825d045a147fa2ebc9", size = 10400, upload-time = "2025-04-10T22:20:16.445Z" }, ] [[package]] name = "multipart" version = "1.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/91/6c93b6a95e6a99ef929a99d019fbf5b5f7fd3368389a0b1ec7ce0a23565b/multipart-1.2.1.tar.gz", hash = "sha256:829b909b67bc1ad1c6d4488fcdc6391c2847842b08323addf5200db88dbe9480", size = 36507 } +sdist = { url = "https://files.pythonhosted.org/packages/df/91/6c93b6a95e6a99ef929a99d019fbf5b5f7fd3368389a0b1ec7ce0a23565b/multipart-1.2.1.tar.gz", hash = "sha256:829b909b67bc1ad1c6d4488fcdc6391c2847842b08323addf5200db88dbe9480", size = 36507, upload-time = "2024-11-29T08:45:48.818Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/d1/3598d1e73385baaab427392856f915487db7aa10abadd436f8f2d3e3b0f9/multipart-1.2.1-py3-none-any.whl", hash = "sha256:c03dc203bc2e67f6b46a599467ae0d87cf71d7530504b2c1ff4a9ea21d8b8c8c", size = 13730 }, + { url = "https://files.pythonhosted.org/packages/cc/d1/3598d1e73385baaab427392856f915487db7aa10abadd436f8f2d3e3b0f9/multipart-1.2.1-py3-none-any.whl", hash = "sha256:c03dc203bc2e67f6b46a599467ae0d87cf71d7530504b2c1ff4a9ea21d8b8c8c", size = 13730, upload-time = "2024-11-29T08:45:44.557Z" }, ] [[package]] @@ -1804,48 +1806,48 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433 }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472 }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424 }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450 }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765 }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701 }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751 }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783 }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618 }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129 }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335 }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935 }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827 }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924 }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176 }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 }, +sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, + { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, + { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, + { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, + { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, + { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, + { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, + { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, + { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, + { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, + { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, + { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, + { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, + { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, + { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, + { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, + { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, + { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, + { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, + { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, + { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, + { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, + { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, + { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, ] [[package]] name = "mypy-extensions" -version = "1.0.0" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] [[package]] @@ -1853,32 +1855,32 @@ name = "mysql-connector-python" version = "9.3.0" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/f8/b36f551601a4b942e2014f80a0bfa5f2f0da30ef2710182cc96d875a5852/mysql_connector_python-9.3.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:f979e712187796ad57cd0bef76666dd48ed4887104775833c9489ea837144ad8", size = 15148231 }, - { url = "https://files.pythonhosted.org/packages/41/ae/abd18c61277ec9e00c36de6a4f53f84003ae9fc34ca6077241a19e2c440f/mysql_connector_python-9.3.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:ee1a901c287471013570e29cdf5ca7159898af31cf3a582180eadd41c96b42c9", size = 15964353 }, - { url = "https://files.pythonhosted.org/packages/0a/98/ce72b24c53327dbe0a2520f8a0828a18726bcb8e4f2012b274a4507bbed3/mysql_connector_python-9.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5508ff6b79d8d46b15791401784a1b5abd10c8e05aec2684c4a50e92c5893cd2", size = 33449033 }, - { url = "https://files.pythonhosted.org/packages/a2/5f/10a89734281ac9d74c7e3bc44f42dbf2105709435ea1bebfbc71e214af18/mysql_connector_python-9.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:d47a0d5b2b9b02f06647d5d7bbb19e237f234d6be91d0e0c935629faacf0797f", size = 33847325 }, - { url = "https://files.pythonhosted.org/packages/58/53/a04fc2186f90fdd2a52d02856f15f2c3c894215799bdaeb313899e75a27b/mysql_connector_python-9.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:e24be22a5d96f3535afa5dd331166b02bf72655ea6ed6a2a0eb548c313548788", size = 16359157 }, - { url = "https://files.pythonhosted.org/packages/65/59/fa9bef2d9a7eafdc5629b82916e4e1e29446c9bbb0b33706988bbf541b18/mysql_connector_python-9.3.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:e8b0131006608e533b8eab20078f9e65486068c984ed3efd28413d350d241f44", size = 15148256 }, - { url = "https://files.pythonhosted.org/packages/14/ae/4ac81d7dc2ce8dff22fd63fa16d4562b113ef0458b04bd958675da3adc74/mysql_connector_python-9.3.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb72fcda90b616f0b2d3dae257441e06e8896b2780c3dddc6a65275ec1408d9a", size = 15964339 }, - { url = "https://files.pythonhosted.org/packages/88/f4/088022373f0b71aae6f3190278423fce1fe0c31ecbddf33eb5c0cbf87c4d/mysql_connector_python-9.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9cc8d3c2f45d16b064b0063db857f8a7187b8659253dd32e3f19df1bf1d55ea0", size = 33456359 }, - { url = "https://files.pythonhosted.org/packages/b9/38/96a602ad402fb71175d83bed3178bd8c16e04251d279e314e0bc53e0b861/mysql_connector_python-9.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:9c898c5f3e34314ed825f2ffdd52d674e03d59c45d02ac8083a8ec5173c1e0f8", size = 33852738 }, - { url = "https://files.pythonhosted.org/packages/ec/55/63567fa4082aa22bad5cecaf16fe3604f026aea40b06d0bf2a9fd75212ff/mysql_connector_python-9.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:f10fe89397e8da81026d8143e17fc5c12ae5e66e51753a0f49e1db179c4f7113", size = 16358431 }, - { url = "https://files.pythonhosted.org/packages/bf/73/b42061ea4c0500edad4f92834ed7d75b1a740d11970e531c5be4dc1af5cd/mysql_connector_python-9.3.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2589af070babdff9c920ee37f929218d80afa704f4e2a99f1ddcb13d19de4450", size = 15151288 }, - { url = "https://files.pythonhosted.org/packages/27/87/9cd7e803c762c5098683c83837d2258c2f83cf82d33fabd1d0eaadae06ee/mysql_connector_python-9.3.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:1916256ecd039f4673715550d28138416bac5962335e06d36f7434c47feb5232", size = 15967397 }, - { url = "https://files.pythonhosted.org/packages/5a/5d/cd63f31bf5d0536ee1e4216fb2f3f57175ca1e0dd37e1e8139083d2156e8/mysql_connector_python-9.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d33e2f88e1d4b15844cfed2bb6e90612525ba2c1af2fb10b4a25b2c89a1fe49a", size = 33457025 }, - { url = "https://files.pythonhosted.org/packages/76/65/9609a96edc0d015d1017176974c42b955cf87ba92cd31765f99cba835715/mysql_connector_python-9.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0aedee809e1f8dbab6b2732f51ee1619b54a56d15b9070655bc31fb822c1a015", size = 33853427 }, - { url = "https://files.pythonhosted.org/packages/c2/da/f81eeb5b63dea3ebe035fbbbdc036ae517155ad73f2e9640ee7c9eace09d/mysql_connector_python-9.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:3853799f4b719357ea25eba05f5f278a158a85a5c8209b3d058947a948bc9262", size = 16358560 }, - { url = "https://files.pythonhosted.org/packages/6a/16/5762061505a0d0d3a333613b6f5d7b8eb3222a689aa32f71ed15f1532ad1/mysql_connector_python-9.3.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9516a4cdbaee3c9200f0e7d9aafb31057692f45c202cdcb43a3f9b37c94e7c84", size = 15151425 }, - { url = "https://files.pythonhosted.org/packages/db/40/22de86e966e648ea0e3e438ad523c86d0cf4866b3841e248726fb4afded8/mysql_connector_python-9.3.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:495798dd34445d749991fb3a2aa87b4205100676939556d8d4aab5d5558e7a1f", size = 15967663 }, - { url = "https://files.pythonhosted.org/packages/4c/19/36983937347b6a58af546950c88a9403cdce944893850e80ffb7f602a099/mysql_connector_python-9.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:be0ef15f6023ae2037347498f005a4471f694f8a6b8384c3194895e153120286", size = 33457288 }, - { url = "https://files.pythonhosted.org/packages/18/12/7ccbc678a130df0f751596b37eddb98b2e40930d0ebc9ee41965ffbf0b92/mysql_connector_python-9.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4364d3a37c449f1c0bb9e52fd4eddc620126b9897b6b9f2fd1b3f33dacc16356", size = 33853838 }, - { url = "https://files.pythonhosted.org/packages/c2/5e/c361caa024ce14ffc1f5b153d90f0febf5e9483a60c4b5c84e1e012363cc/mysql_connector_python-9.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:2a5de57814217077a8672063167b616b1034a37b614b93abcb602cc0b8c6fade", size = 16358561 }, - { url = "https://files.pythonhosted.org/packages/ed/fb/97f8e2cff2fbde6ccc4b6bc7ae38a8e0b85793049940c54fc46408d22ff9/mysql_connector_python-9.3.0-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:8c79b500f1f9f12761426199d0498309ee5d20c94ed94fc8ae356679667f8181", size = 15148298 }, - { url = "https://files.pythonhosted.org/packages/da/63/7544c0cb6f4ec18fe33e7fc67ccba26501383da26d1daf4e5d2900a15c1b/mysql_connector_python-9.3.0-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:d87c9e8b5aa9a16cefebe017ee45ddfbad53e668f94d01fe2e055bb8daab9353", size = 15964350 }, - { url = "https://files.pythonhosted.org/packages/a1/3c/f90e6b7d7b9d74d26048fa00215df76f4581d4d8ea62ba8556080db05d81/mysql_connector_python-9.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ac70a7128f7e690dc0f4376be8366c7e5c8fa47a785232b8abba948576f016ff", size = 33447721 }, - { url = "https://files.pythonhosted.org/packages/eb/c3/7ab2e4c9c6f941544d3751abe37c874faf4a26ebad3c6b7eabe36ac21c70/mysql_connector_python-9.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:66d48ec0ee903a84bcaf5d4d1901ed536fdd90ce6ecae0686f094b4530faf545", size = 33845271 }, - { url = "https://files.pythonhosted.org/packages/9e/17/92c08f2e622267b8a7a92c9c29e2cdb4a8c906917d99db741854e49d9cac/mysql_connector_python-9.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:55d4a8ace6f97d58d9318d1250d903b0d3b100a6b798442a99c4ac966b974d12", size = 16359159 }, - { url = "https://files.pythonhosted.org/packages/23/1d/8c2c6672094b538f4881f7714e5332fdcddd05a7e196cbc9eb4a9b5e9a45/mysql_connector_python-9.3.0-py2.py3-none-any.whl", hash = "sha256:8ab7719d614cf5463521082fab86afc21ada504b538166090e00eeaa1ff729bc", size = 399302 }, + { url = "https://files.pythonhosted.org/packages/59/f8/b36f551601a4b942e2014f80a0bfa5f2f0da30ef2710182cc96d875a5852/mysql_connector_python-9.3.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:f979e712187796ad57cd0bef76666dd48ed4887104775833c9489ea837144ad8", size = 15148231, upload-time = "2025-04-15T11:21:33.974Z" }, + { url = "https://files.pythonhosted.org/packages/41/ae/abd18c61277ec9e00c36de6a4f53f84003ae9fc34ca6077241a19e2c440f/mysql_connector_python-9.3.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:ee1a901c287471013570e29cdf5ca7159898af31cf3a582180eadd41c96b42c9", size = 15964353, upload-time = "2025-04-15T11:21:38.211Z" }, + { url = "https://files.pythonhosted.org/packages/0a/98/ce72b24c53327dbe0a2520f8a0828a18726bcb8e4f2012b274a4507bbed3/mysql_connector_python-9.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5508ff6b79d8d46b15791401784a1b5abd10c8e05aec2684c4a50e92c5893cd2", size = 33449033, upload-time = "2025-04-15T11:21:42.704Z" }, + { url = "https://files.pythonhosted.org/packages/a2/5f/10a89734281ac9d74c7e3bc44f42dbf2105709435ea1bebfbc71e214af18/mysql_connector_python-9.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:d47a0d5b2b9b02f06647d5d7bbb19e237f234d6be91d0e0c935629faacf0797f", size = 33847325, upload-time = "2025-04-15T11:21:48.13Z" }, + { url = "https://files.pythonhosted.org/packages/58/53/a04fc2186f90fdd2a52d02856f15f2c3c894215799bdaeb313899e75a27b/mysql_connector_python-9.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:e24be22a5d96f3535afa5dd331166b02bf72655ea6ed6a2a0eb548c313548788", size = 16359157, upload-time = "2025-04-15T11:21:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/65/59/fa9bef2d9a7eafdc5629b82916e4e1e29446c9bbb0b33706988bbf541b18/mysql_connector_python-9.3.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:e8b0131006608e533b8eab20078f9e65486068c984ed3efd28413d350d241f44", size = 15148256, upload-time = "2025-04-15T11:21:55.05Z" }, + { url = "https://files.pythonhosted.org/packages/14/ae/4ac81d7dc2ce8dff22fd63fa16d4562b113ef0458b04bd958675da3adc74/mysql_connector_python-9.3.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb72fcda90b616f0b2d3dae257441e06e8896b2780c3dddc6a65275ec1408d9a", size = 15964339, upload-time = "2025-04-15T11:21:58.275Z" }, + { url = "https://files.pythonhosted.org/packages/88/f4/088022373f0b71aae6f3190278423fce1fe0c31ecbddf33eb5c0cbf87c4d/mysql_connector_python-9.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9cc8d3c2f45d16b064b0063db857f8a7187b8659253dd32e3f19df1bf1d55ea0", size = 33456359, upload-time = "2025-04-15T11:22:02.594Z" }, + { url = "https://files.pythonhosted.org/packages/b9/38/96a602ad402fb71175d83bed3178bd8c16e04251d279e314e0bc53e0b861/mysql_connector_python-9.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:9c898c5f3e34314ed825f2ffdd52d674e03d59c45d02ac8083a8ec5173c1e0f8", size = 33852738, upload-time = "2025-04-15T11:22:07.685Z" }, + { url = "https://files.pythonhosted.org/packages/ec/55/63567fa4082aa22bad5cecaf16fe3604f026aea40b06d0bf2a9fd75212ff/mysql_connector_python-9.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:f10fe89397e8da81026d8143e17fc5c12ae5e66e51753a0f49e1db179c4f7113", size = 16358431, upload-time = "2025-04-15T11:22:12.263Z" }, + { url = "https://files.pythonhosted.org/packages/bf/73/b42061ea4c0500edad4f92834ed7d75b1a740d11970e531c5be4dc1af5cd/mysql_connector_python-9.3.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2589af070babdff9c920ee37f929218d80afa704f4e2a99f1ddcb13d19de4450", size = 15151288, upload-time = "2025-04-15T18:43:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/27/87/9cd7e803c762c5098683c83837d2258c2f83cf82d33fabd1d0eaadae06ee/mysql_connector_python-9.3.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:1916256ecd039f4673715550d28138416bac5962335e06d36f7434c47feb5232", size = 15967397, upload-time = "2025-04-15T18:43:20.799Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5d/cd63f31bf5d0536ee1e4216fb2f3f57175ca1e0dd37e1e8139083d2156e8/mysql_connector_python-9.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d33e2f88e1d4b15844cfed2bb6e90612525ba2c1af2fb10b4a25b2c89a1fe49a", size = 33457025, upload-time = "2025-04-15T18:43:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/76/65/9609a96edc0d015d1017176974c42b955cf87ba92cd31765f99cba835715/mysql_connector_python-9.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0aedee809e1f8dbab6b2732f51ee1619b54a56d15b9070655bc31fb822c1a015", size = 33853427, upload-time = "2025-04-15T18:43:28.441Z" }, + { url = "https://files.pythonhosted.org/packages/c2/da/f81eeb5b63dea3ebe035fbbbdc036ae517155ad73f2e9640ee7c9eace09d/mysql_connector_python-9.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:3853799f4b719357ea25eba05f5f278a158a85a5c8209b3d058947a948bc9262", size = 16358560, upload-time = "2025-04-15T18:43:32.281Z" }, + { url = "https://files.pythonhosted.org/packages/6a/16/5762061505a0d0d3a333613b6f5d7b8eb3222a689aa32f71ed15f1532ad1/mysql_connector_python-9.3.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9516a4cdbaee3c9200f0e7d9aafb31057692f45c202cdcb43a3f9b37c94e7c84", size = 15151425, upload-time = "2025-04-15T18:43:35.573Z" }, + { url = "https://files.pythonhosted.org/packages/db/40/22de86e966e648ea0e3e438ad523c86d0cf4866b3841e248726fb4afded8/mysql_connector_python-9.3.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:495798dd34445d749991fb3a2aa87b4205100676939556d8d4aab5d5558e7a1f", size = 15967663, upload-time = "2025-04-15T18:43:38.248Z" }, + { url = "https://files.pythonhosted.org/packages/4c/19/36983937347b6a58af546950c88a9403cdce944893850e80ffb7f602a099/mysql_connector_python-9.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:be0ef15f6023ae2037347498f005a4471f694f8a6b8384c3194895e153120286", size = 33457288, upload-time = "2025-04-15T18:43:41.901Z" }, + { url = "https://files.pythonhosted.org/packages/18/12/7ccbc678a130df0f751596b37eddb98b2e40930d0ebc9ee41965ffbf0b92/mysql_connector_python-9.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4364d3a37c449f1c0bb9e52fd4eddc620126b9897b6b9f2fd1b3f33dacc16356", size = 33853838, upload-time = "2025-04-15T18:43:45.505Z" }, + { url = "https://files.pythonhosted.org/packages/c2/5e/c361caa024ce14ffc1f5b153d90f0febf5e9483a60c4b5c84e1e012363cc/mysql_connector_python-9.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:2a5de57814217077a8672063167b616b1034a37b614b93abcb602cc0b8c6fade", size = 16358561, upload-time = "2025-04-15T18:43:49.176Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fb/97f8e2cff2fbde6ccc4b6bc7ae38a8e0b85793049940c54fc46408d22ff9/mysql_connector_python-9.3.0-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:8c79b500f1f9f12761426199d0498309ee5d20c94ed94fc8ae356679667f8181", size = 15148298, upload-time = "2025-04-15T18:43:52.04Z" }, + { url = "https://files.pythonhosted.org/packages/da/63/7544c0cb6f4ec18fe33e7fc67ccba26501383da26d1daf4e5d2900a15c1b/mysql_connector_python-9.3.0-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:d87c9e8b5aa9a16cefebe017ee45ddfbad53e668f94d01fe2e055bb8daab9353", size = 15964350, upload-time = "2025-04-15T18:43:55.222Z" }, + { url = "https://files.pythonhosted.org/packages/a1/3c/f90e6b7d7b9d74d26048fa00215df76f4581d4d8ea62ba8556080db05d81/mysql_connector_python-9.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ac70a7128f7e690dc0f4376be8366c7e5c8fa47a785232b8abba948576f016ff", size = 33447721, upload-time = "2025-04-15T18:43:58.901Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c3/7ab2e4c9c6f941544d3751abe37c874faf4a26ebad3c6b7eabe36ac21c70/mysql_connector_python-9.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:66d48ec0ee903a84bcaf5d4d1901ed536fdd90ce6ecae0686f094b4530faf545", size = 33845271, upload-time = "2025-04-15T18:44:04.111Z" }, + { url = "https://files.pythonhosted.org/packages/9e/17/92c08f2e622267b8a7a92c9c29e2cdb4a8c906917d99db741854e49d9cac/mysql_connector_python-9.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:55d4a8ace6f97d58d9318d1250d903b0d3b100a6b798442a99c4ac966b974d12", size = 16359159, upload-time = "2025-04-15T18:44:08.009Z" }, + { url = "https://files.pythonhosted.org/packages/23/1d/8c2c6672094b538f4881f7714e5332fdcddd05a7e196cbc9eb4a9b5e9a45/mysql_connector_python-9.3.0-py2.py3-none-any.whl", hash = "sha256:8ab7719d614cf5463521082fab86afc21ada504b538166090e00eeaa1ff729bc", size = 399302, upload-time = "2025-04-15T18:44:10.046Z" }, ] [[package]] @@ -1896,9 +1898,9 @@ dependencies = [ { name = "pyyaml", marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/49/64/e2f13dac02f599980798c01156393b781aec983b52a6e4057ee58f07c43a/myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87", size = 92392 } +sdist = { url = "https://files.pythonhosted.org/packages/49/64/e2f13dac02f599980798c01156393b781aec983b52a6e4057ee58f07c43a/myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87", size = 92392, upload-time = "2024-04-28T20:22:42.116Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/de/21aa8394f16add8f7427f0a1326ccd2b3a2a8a3245c9252bc5ac034c6155/myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1", size = 83163 }, + { url = "https://files.pythonhosted.org/packages/e2/de/21aa8394f16add8f7427f0a1326ccd2b3a2a8a3245c9252bc5ac034c6155/myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1", size = 83163, upload-time = "2024-04-28T20:22:39.985Z" }, ] [[package]] @@ -1919,27 +1921,27 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985 } +sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985, upload-time = "2025-02-12T10:53:03.833Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579 }, + { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579, upload-time = "2025-02-12T10:53:02.078Z" }, ] [[package]] name = "natsort" version = "8.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575 } +sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575, upload-time = "2023-06-20T04:17:19.925Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268 }, + { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268, upload-time = "2023-06-20T04:17:17.522Z" }, ] [[package]] name = "nodeenv" version = "1.9.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, ] [[package]] @@ -1949,149 +1951,153 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b8/58/077cb49c20c2de9d4e25225cfaeebeb78658842549b49674f70c2e9fcba1/oracledb-3.1.0.tar.gz", hash = "sha256:f78cf7452128fa564a9819d213573a7c93e3b053b2b2ef505f183ce7e47b1e7b", size = 855816 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/68/6b9b2bb3cd897966264d22217772b5422c6d96eee2f62da8f85289fc181b/oracledb-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:059223b6d485d379e4f8e1ca235f3dd49e7b973eee10569df305eaf55bb5e7e6", size = 4346164 }, - { url = "https://files.pythonhosted.org/packages/78/d7/386db59cb96c3f0b1e9622316ee4edc6aa8cf3317920a95f5f83c879840c/oracledb-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40c0dbbaa31757d1fa26bb578ec82bb6b8382d94144e7d8d1f5b0a4eb32b19db", size = 2699046 }, - { url = "https://files.pythonhosted.org/packages/a6/7c/9f38141ea1947c38ee4cf6d6f895efc926f566982019cdca6b391111d801/oracledb-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e800ebe3172a6b996fb2beef56dab4034a6a1b8206e07f1441d74a0a873af669", size = 2908039 }, - { url = "https://files.pythonhosted.org/packages/6f/3e/cba7c5bf0fb591e2a751464850375e1e0b69c3175035d2c587ae2d270cbe/oracledb-3.1.0-cp310-cp310-win32.whl", hash = "sha256:4da428d5882df1a125ae0e4dc09e2bb4cdf7e77ce2b75b3728cba79e8145b14e", size = 1774760 }, - { url = "https://files.pythonhosted.org/packages/41/22/90478e107f3df49a5783117c549f3abe037179a73bd32129921c52cfb626/oracledb-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:07315cb0cea7d43c52f15e359bcc1e321de7b07e1e10eff5ed7c05cd3703fa7f", size = 2125111 }, - { url = "https://files.pythonhosted.org/packages/68/02/5490500675da3326f36cafd1e132e889345d88c9c350bcdd4178e503dff1/oracledb-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:85642cdae75829e7f6905cb97eb2daea6632734f836af369b6a44408229ef099", size = 4381119 }, - { url = "https://files.pythonhosted.org/packages/66/87/7dc4cbd1bddf8a71840bc9e5af5d7ea24ab6a3e027970b67055a8a8680ba/oracledb-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f256d70e3ddcdce3859d38ff3a2b84101e7090bc5bbc38d7e46dc73902ee7777", size = 2707842 }, - { url = "https://files.pythonhosted.org/packages/eb/b1/ff354fa0fee6477c74cc0bfacdf7774d6a6f3f34ecec4a022c2aabedca8c/oracledb-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c1506d79817e7b9086c98a368e3de96e05e424ab20544191c362075479f1e6e", size = 2921622 }, - { url = "https://files.pythonhosted.org/packages/c0/6c/a75c1d2a5b6241c86d087ae21a0f0ce3307faaaaa6704cdc36106a819d1f/oracledb-3.1.0-cp311-cp311-win32.whl", hash = "sha256:6822fe0c8bfc1f73833d2a03fa6e02f10f3b829f261481b2e60211a9f320d2a4", size = 1776328 }, - { url = "https://files.pythonhosted.org/packages/f0/cd/3d897c683087ffc25f95b04d45da03ed2a1c0bda5d288c349cd34c9267fa/oracledb-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:ff22497be97bd73f3083965960ec812155d6de8232018833c82b3a89182a041a", size = 2132252 }, - { url = "https://files.pythonhosted.org/packages/07/35/eab385f3bb94fb8378061ef37a47f3ac6f05af1c89c39644bb8c7f413441/oracledb-3.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:50f0f129f53e23bcd50a0c2128c1c4684281d14cecdedcdfcd4863bbe83bfa3b", size = 4426462 }, - { url = "https://files.pythonhosted.org/packages/af/86/3982ecdb7033ae27151f574e413fcb29e75b4ea1f097930f8b76fb0aa3ac/oracledb-3.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8357ba48e18f6951c2d71af918e515e45978d5e20b0e7849e1674bd9bac98ab5", size = 2578725 }, - { url = "https://files.pythonhosted.org/packages/d9/c8/62103e3d5229d6fbf443ff2e89978d96468ec4318e3315e321fd0c68108d/oracledb-3.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e386d76759079a026783941a52b15cd5d92512558b0cb9fa3880d94a27d8283", size = 2812651 }, - { url = "https://files.pythonhosted.org/packages/5c/4c/2ef30a3e2acdccfc7bfc9e034080be6fceadf942e91b5a009ed1e76429ee/oracledb-3.1.0-cp312-cp312-win32.whl", hash = "sha256:d682c0bb1b341c2df50e399c29c9d9aee3e6fd469ab9752c1d4336ae3184cfaa", size = 1735430 }, - { url = "https://files.pythonhosted.org/packages/c9/08/3b9ee413cbb3acbf6399ad01f4c2f318bfd556325c5bba077e93da200dd7/oracledb-3.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:f7caaba6690ee98f641b266ea741212eacb729dd9638f6b180d9f3d9bfb15e83", size = 2087637 }, - { url = "https://files.pythonhosted.org/packages/56/48/733a6bb0add900bec4cc14b6dbfb65e202fdfbc48a107f9552db50363d6b/oracledb-3.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:290eb663f27175468b243badefa28bfff7fe520496e48fddc5aa10c0eb46475d", size = 4378913 }, - { url = "https://files.pythonhosted.org/packages/4c/0c/bbc21aae89be316aed9c96fe95533aac790d7c45fd10d31938ad9f1d4c53/oracledb-3.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1ddddb1002689235df3588293ce3637d1f4f616c67852d53cc1e8a4a6722b6b", size = 2556183 }, - { url = "https://files.pythonhosted.org/packages/39/07/759e59e8b3bdc51f39d53ecc434ce604401af5254617ebfac6aeec325e6e/oracledb-3.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2225f5a5952b7bec257941a50c59de7b2a37bc23281d375885bb549a31253259", size = 2791706 }, - { url = "https://files.pythonhosted.org/packages/81/73/35d9faabfdcf2d23ea9eadd548bb11d60e629e5671b5802975e07c6cf8cb/oracledb-3.1.0-cp313-cp313-win32.whl", hash = "sha256:124b172d70e46c6745b2f93c4405bae8e7662e088e38a794b558c094253db3d8", size = 1733200 }, - { url = "https://files.pythonhosted.org/packages/ad/04/46329a8b4d889d65ddc2f6b2f985cff1887ebed504ac6c61267490de4163/oracledb-3.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:5d752aff2d34e48554241be729e0999e397676e3c22fca0652bab46d0db6c4a8", size = 2085788 }, - { url = "https://files.pythonhosted.org/packages/6a/50/c55910a6209b2eda297ac8f3be56376a90cd5efb0e547f909c3838dd4a37/oracledb-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a7f5b351cde7763d89997e1cace21d95921618e24c14e0ab3a06a9b8d9ad0c1a", size = 4352693 }, - { url = "https://files.pythonhosted.org/packages/16/fc/577c621a7e6925b3bc953ded1cc49da80d81720d58c922b687d0a3083158/oracledb-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7ee7645e12989d59b045208c3910163a29d5aef0abc7058668e0a3b3817746d4", size = 2705248 }, - { url = "https://files.pythonhosted.org/packages/60/0d/1dfd845e289bf44cd4b2f36edef2df72b6baa4f55d1e7801f23ad608e255/oracledb-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c8abc70d6dcd98539a02b455ae5dcaa9cbed049f5e4688a086146803d9c451e", size = 2912856 }, - { url = "https://files.pythonhosted.org/packages/9c/e8/f6b1d6ea20b14bd6b52d9b13574c66b3451db1231535bbfacf86efe53aa6/oracledb-3.1.0-cp39-cp39-win32.whl", hash = "sha256:0b8a7baba807a5cb9a839ce2704fcf666e651259606d814b4a11a1566b622550", size = 1777627 }, - { url = "https://files.pythonhosted.org/packages/60/19/ad4cf0ad53806eaeff62f4cf73276994c003ea70d2724028bb851ea57082/oracledb-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:ee7685911b6da4edec553e5d0ab3c376063d7bb96dbd0d150ea6886ba71f1d72", size = 2127402 }, +sdist = { url = "https://files.pythonhosted.org/packages/b8/58/077cb49c20c2de9d4e25225cfaeebeb78658842549b49674f70c2e9fcba1/oracledb-3.1.0.tar.gz", hash = "sha256:f78cf7452128fa564a9819d213573a7c93e3b053b2b2ef505f183ce7e47b1e7b", size = 855816, upload-time = "2025-04-03T17:58:39.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/68/6b9b2bb3cd897966264d22217772b5422c6d96eee2f62da8f85289fc181b/oracledb-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:059223b6d485d379e4f8e1ca235f3dd49e7b973eee10569df305eaf55bb5e7e6", size = 4346164, upload-time = "2025-04-03T17:58:46.725Z" }, + { url = "https://files.pythonhosted.org/packages/78/d7/386db59cb96c3f0b1e9622316ee4edc6aa8cf3317920a95f5f83c879840c/oracledb-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40c0dbbaa31757d1fa26bb578ec82bb6b8382d94144e7d8d1f5b0a4eb32b19db", size = 2699046, upload-time = "2025-04-03T17:58:49.805Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7c/9f38141ea1947c38ee4cf6d6f895efc926f566982019cdca6b391111d801/oracledb-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e800ebe3172a6b996fb2beef56dab4034a6a1b8206e07f1441d74a0a873af669", size = 2908039, upload-time = "2025-04-03T17:58:51.925Z" }, + { url = "https://files.pythonhosted.org/packages/6f/3e/cba7c5bf0fb591e2a751464850375e1e0b69c3175035d2c587ae2d270cbe/oracledb-3.1.0-cp310-cp310-win32.whl", hash = "sha256:4da428d5882df1a125ae0e4dc09e2bb4cdf7e77ce2b75b3728cba79e8145b14e", size = 1774760, upload-time = "2025-04-03T17:58:53.841Z" }, + { url = "https://files.pythonhosted.org/packages/41/22/90478e107f3df49a5783117c549f3abe037179a73bd32129921c52cfb626/oracledb-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:07315cb0cea7d43c52f15e359bcc1e321de7b07e1e10eff5ed7c05cd3703fa7f", size = 2125111, upload-time = "2025-04-03T17:58:55.267Z" }, + { url = "https://files.pythonhosted.org/packages/68/02/5490500675da3326f36cafd1e132e889345d88c9c350bcdd4178e503dff1/oracledb-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:85642cdae75829e7f6905cb97eb2daea6632734f836af369b6a44408229ef099", size = 4381119, upload-time = "2025-04-03T17:58:57.013Z" }, + { url = "https://files.pythonhosted.org/packages/66/87/7dc4cbd1bddf8a71840bc9e5af5d7ea24ab6a3e027970b67055a8a8680ba/oracledb-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f256d70e3ddcdce3859d38ff3a2b84101e7090bc5bbc38d7e46dc73902ee7777", size = 2707842, upload-time = "2025-04-03T17:58:58.971Z" }, + { url = "https://files.pythonhosted.org/packages/eb/b1/ff354fa0fee6477c74cc0bfacdf7774d6a6f3f34ecec4a022c2aabedca8c/oracledb-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c1506d79817e7b9086c98a368e3de96e05e424ab20544191c362075479f1e6e", size = 2921622, upload-time = "2025-04-03T17:59:05.029Z" }, + { url = "https://files.pythonhosted.org/packages/c0/6c/a75c1d2a5b6241c86d087ae21a0f0ce3307faaaaa6704cdc36106a819d1f/oracledb-3.1.0-cp311-cp311-win32.whl", hash = "sha256:6822fe0c8bfc1f73833d2a03fa6e02f10f3b829f261481b2e60211a9f320d2a4", size = 1776328, upload-time = "2025-04-03T17:59:07.102Z" }, + { url = "https://files.pythonhosted.org/packages/f0/cd/3d897c683087ffc25f95b04d45da03ed2a1c0bda5d288c349cd34c9267fa/oracledb-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:ff22497be97bd73f3083965960ec812155d6de8232018833c82b3a89182a041a", size = 2132252, upload-time = "2025-04-03T17:59:09.12Z" }, + { url = "https://files.pythonhosted.org/packages/07/35/eab385f3bb94fb8378061ef37a47f3ac6f05af1c89c39644bb8c7f413441/oracledb-3.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:50f0f129f53e23bcd50a0c2128c1c4684281d14cecdedcdfcd4863bbe83bfa3b", size = 4426462, upload-time = "2025-04-03T17:59:10.827Z" }, + { url = "https://files.pythonhosted.org/packages/af/86/3982ecdb7033ae27151f574e413fcb29e75b4ea1f097930f8b76fb0aa3ac/oracledb-3.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8357ba48e18f6951c2d71af918e515e45978d5e20b0e7849e1674bd9bac98ab5", size = 2578725, upload-time = "2025-04-03T17:59:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/d9/c8/62103e3d5229d6fbf443ff2e89978d96468ec4318e3315e321fd0c68108d/oracledb-3.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e386d76759079a026783941a52b15cd5d92512558b0cb9fa3880d94a27d8283", size = 2812651, upload-time = "2025-04-03T17:59:14.957Z" }, + { url = "https://files.pythonhosted.org/packages/5c/4c/2ef30a3e2acdccfc7bfc9e034080be6fceadf942e91b5a009ed1e76429ee/oracledb-3.1.0-cp312-cp312-win32.whl", hash = "sha256:d682c0bb1b341c2df50e399c29c9d9aee3e6fd469ab9752c1d4336ae3184cfaa", size = 1735430, upload-time = "2025-04-03T17:59:17.197Z" }, + { url = "https://files.pythonhosted.org/packages/c9/08/3b9ee413cbb3acbf6399ad01f4c2f318bfd556325c5bba077e93da200dd7/oracledb-3.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:f7caaba6690ee98f641b266ea741212eacb729dd9638f6b180d9f3d9bfb15e83", size = 2087637, upload-time = "2025-04-03T17:59:19.294Z" }, + { url = "https://files.pythonhosted.org/packages/56/48/733a6bb0add900bec4cc14b6dbfb65e202fdfbc48a107f9552db50363d6b/oracledb-3.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:290eb663f27175468b243badefa28bfff7fe520496e48fddc5aa10c0eb46475d", size = 4378913, upload-time = "2025-04-03T17:59:21.09Z" }, + { url = "https://files.pythonhosted.org/packages/4c/0c/bbc21aae89be316aed9c96fe95533aac790d7c45fd10d31938ad9f1d4c53/oracledb-3.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1ddddb1002689235df3588293ce3637d1f4f616c67852d53cc1e8a4a6722b6b", size = 2556183, upload-time = "2025-04-03T17:59:22.756Z" }, + { url = "https://files.pythonhosted.org/packages/39/07/759e59e8b3bdc51f39d53ecc434ce604401af5254617ebfac6aeec325e6e/oracledb-3.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2225f5a5952b7bec257941a50c59de7b2a37bc23281d375885bb549a31253259", size = 2791706, upload-time = "2025-04-03T17:59:24.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/73/35d9faabfdcf2d23ea9eadd548bb11d60e629e5671b5802975e07c6cf8cb/oracledb-3.1.0-cp313-cp313-win32.whl", hash = "sha256:124b172d70e46c6745b2f93c4405bae8e7662e088e38a794b558c094253db3d8", size = 1733200, upload-time = "2025-04-03T17:59:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/ad/04/46329a8b4d889d65ddc2f6b2f985cff1887ebed504ac6c61267490de4163/oracledb-3.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:5d752aff2d34e48554241be729e0999e397676e3c22fca0652bab46d0db6c4a8", size = 2085788, upload-time = "2025-04-03T17:59:28.21Z" }, + { url = "https://files.pythonhosted.org/packages/6a/50/c55910a6209b2eda297ac8f3be56376a90cd5efb0e547f909c3838dd4a37/oracledb-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a7f5b351cde7763d89997e1cace21d95921618e24c14e0ab3a06a9b8d9ad0c1a", size = 4352693, upload-time = "2025-04-03T17:59:29.803Z" }, + { url = "https://files.pythonhosted.org/packages/16/fc/577c621a7e6925b3bc953ded1cc49da80d81720d58c922b687d0a3083158/oracledb-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7ee7645e12989d59b045208c3910163a29d5aef0abc7058668e0a3b3817746d4", size = 2705248, upload-time = "2025-04-03T17:59:31.848Z" }, + { url = "https://files.pythonhosted.org/packages/60/0d/1dfd845e289bf44cd4b2f36edef2df72b6baa4f55d1e7801f23ad608e255/oracledb-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c8abc70d6dcd98539a02b455ae5dcaa9cbed049f5e4688a086146803d9c451e", size = 2912856, upload-time = "2025-04-03T17:59:33.898Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e8/f6b1d6ea20b14bd6b52d9b13574c66b3451db1231535bbfacf86efe53aa6/oracledb-3.1.0-cp39-cp39-win32.whl", hash = "sha256:0b8a7baba807a5cb9a839ce2704fcf666e651259606d814b4a11a1566b622550", size = 1777627, upload-time = "2025-04-03T17:59:35.465Z" }, + { url = "https://files.pythonhosted.org/packages/60/19/ad4cf0ad53806eaeff62f4cf73276994c003ea70d2724028bb851ea57082/oracledb-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:ee7685911b6da4edec553e5d0ab3c376063d7bb96dbd0d150ea6886ba71f1d72", size = 2127402, upload-time = "2025-04-03T17:59:36.916Z" }, ] [[package]] name = "orjson" -version = "3.10.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/a6/22cb9b03baf167bc2d659c9e74d7580147f36e6a155e633801badfd5a74d/orjson-3.10.16-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4cb473b8e79154fa778fb56d2d73763d977be3dcc140587e07dbc545bbfc38f8", size = 249179 }, - { url = "https://files.pythonhosted.org/packages/d7/ce/3e68cc33020a6ebd8f359b8628b69d2132cd84fea68155c33057e502ee51/orjson-3.10.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:622a8e85eeec1948690409a19ca1c7d9fd8ff116f4861d261e6ae2094fe59a00", size = 138510 }, - { url = "https://files.pythonhosted.org/packages/dc/12/63bee7764ce12052f7c1a1393ce7f26dc392c93081eb8754dd3dce9b7c6b/orjson-3.10.16-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c682d852d0ce77613993dc967e90e151899fe2d8e71c20e9be164080f468e370", size = 132373 }, - { url = "https://files.pythonhosted.org/packages/b3/d5/2998c2f319adcd572f2b03ba2083e8176863d1055d8d713683ddcf927b71/orjson-3.10.16-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c520ae736acd2e32df193bcff73491e64c936f3e44a2916b548da048a48b46b", size = 136774 }, - { url = "https://files.pythonhosted.org/packages/00/03/88c236ae307bd0604623204d4a835e15fbf9c75b8535c8f13ef45abd413f/orjson-3.10.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:134f87c76bfae00f2094d85cfab261b289b76d78c6da8a7a3b3c09d362fd1e06", size = 138030 }, - { url = "https://files.pythonhosted.org/packages/66/ba/3e256ddfeb364f98fd6ac65774844090d356158b2d1de8998db2bf984503/orjson-3.10.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b59afde79563e2cf37cfe62ee3b71c063fd5546c8e662d7fcfc2a3d5031a5c4c", size = 142677 }, - { url = "https://files.pythonhosted.org/packages/2c/71/73a1214bd27baa2ea5184fff4aa6193a114dfb0aa5663dad48fe63e8cd29/orjson-3.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113602f8241daaff05d6fad25bd481d54c42d8d72ef4c831bb3ab682a54d9e15", size = 132798 }, - { url = "https://files.pythonhosted.org/packages/53/ac/0b2f41c0a1e8c095439d0fab3b33103cf41a39be8e6aa2c56298a6034259/orjson-3.10.16-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4fc0077d101f8fab4031e6554fc17b4c2ad8fdbc56ee64a727f3c95b379e31da", size = 135450 }, - { url = "https://files.pythonhosted.org/packages/d9/ca/7524c7b0bc815d426ca134dab54cad519802287b808a3846b047a5b2b7a3/orjson-3.10.16-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9c6bf6ff180cd69e93f3f50380224218cfab79953a868ea3908430bcfaf9cb5e", size = 412356 }, - { url = "https://files.pythonhosted.org/packages/05/1d/3ae2367c255276bf16ff7e1b210dd0af18bc8da20c4e4295755fc7de1268/orjson-3.10.16-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5673eadfa952f95a7cd76418ff189df11b0a9c34b1995dff43a6fdbce5d63bf4", size = 152769 }, - { url = "https://files.pythonhosted.org/packages/d3/2d/8eb10b6b1d30bb69c35feb15e5ba5ac82466cf743d562e3e8047540efd2f/orjson-3.10.16-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5fe638a423d852b0ae1e1a79895851696cb0d9fa0946fdbfd5da5072d9bb9551", size = 137223 }, - { url = "https://files.pythonhosted.org/packages/47/42/f043717930cb2de5fbebe47f308f101bed9ec2b3580b1f99c8284b2f5fe8/orjson-3.10.16-cp310-cp310-win32.whl", hash = "sha256:33af58f479b3c6435ab8f8b57999874b4b40c804c7a36b5cc6b54d8f28e1d3dd", size = 141734 }, - { url = "https://files.pythonhosted.org/packages/67/99/795ad7282b425b9fddcfb8a31bded5dcf84dba78ecb1e7ae716e84e794da/orjson-3.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:0338356b3f56d71293c583350af26f053017071836b07e064e92819ecf1aa055", size = 133779 }, - { url = "https://files.pythonhosted.org/packages/97/29/43f91a5512b5d2535594438eb41c5357865fd5e64dec745d90a588820c75/orjson-3.10.16-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44fcbe1a1884f8bc9e2e863168b0f84230c3d634afe41c678637d2728ea8e739", size = 249180 }, - { url = "https://files.pythonhosted.org/packages/0c/36/2a72d55e266473c19a86d97b7363bb8bf558ab450f75205689a287d5ce61/orjson-3.10.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78177bf0a9d0192e0b34c3d78bcff7fe21d1b5d84aeb5ebdfe0dbe637b885225", size = 138510 }, - { url = "https://files.pythonhosted.org/packages/bb/ad/f86d6f55c1a68b57ff6ea7966bce5f4e5163f2e526ddb7db9fc3c2c8d1c4/orjson-3.10.16-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12824073a010a754bb27330cad21d6e9b98374f497f391b8707752b96f72e741", size = 132373 }, - { url = "https://files.pythonhosted.org/packages/5e/8b/d18f2711493a809f3082a88fda89342bc8e16767743b909cd3c34989fba3/orjson-3.10.16-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddd41007e56284e9867864aa2f29f3136bb1dd19a49ca43c0b4eda22a579cf53", size = 136773 }, - { url = "https://files.pythonhosted.org/packages/a1/dc/ce025f002f8e0749e3f057c4d773a4d4de32b7b4c1fc5a50b429e7532586/orjson-3.10.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0877c4d35de639645de83666458ca1f12560d9fa7aa9b25d8bb8f52f61627d14", size = 138029 }, - { url = "https://files.pythonhosted.org/packages/0e/1b/cf9df85852b91160029d9f26014230366a2b4deb8cc51fabe68e250a8c1a/orjson-3.10.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a09a539e9cc3beead3e7107093b4ac176d015bec64f811afb5965fce077a03c", size = 142677 }, - { url = "https://files.pythonhosted.org/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31b98bc9b40610fec971d9a4d67bb2ed02eec0a8ae35f8ccd2086320c28526ca", size = 132800 }, - { url = "https://files.pythonhosted.org/packages/d6/eb/467f25b580e942fcca1344adef40633b7f05ac44a65a63fc913f9a805d58/orjson-3.10.16-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0ce243f5a8739f3a18830bc62dc2e05b69a7545bafd3e3249f86668b2bcd8e50", size = 135451 }, - { url = "https://files.pythonhosted.org/packages/8d/4b/9d10888038975cb375982e9339d9495bac382d5c976c500b8d6f2c8e2e4e/orjson-3.10.16-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64792c0025bae049b3074c6abe0cf06f23c8e9f5a445f4bab31dc5ca23dbf9e1", size = 412358 }, - { url = "https://files.pythonhosted.org/packages/3b/e2/cfbcfcc4fbe619e0ca9bdbbfccb2d62b540bbfe41e0ee77d44a628594f59/orjson-3.10.16-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea53f7e68eec718b8e17e942f7ca56c6bd43562eb19db3f22d90d75e13f0431d", size = 152772 }, - { url = "https://files.pythonhosted.org/packages/b9/d6/627a1b00569be46173007c11dde3da4618c9bfe18409325b0e3e2a82fe29/orjson-3.10.16-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a741ba1a9488c92227711bde8c8c2b63d7d3816883268c808fbeada00400c164", size = 137225 }, - { url = "https://files.pythonhosted.org/packages/0a/7b/a73c67b505021af845b9f05c7c848793258ea141fa2058b52dd9b067c2b4/orjson-3.10.16-cp311-cp311-win32.whl", hash = "sha256:c7ed2c61bb8226384c3fdf1fb01c51b47b03e3f4536c985078cccc2fd19f1619", size = 141733 }, - { url = "https://files.pythonhosted.org/packages/f4/22/5e8217c48d68c0adbfb181e749d6a733761074e598b083c69a1383d18147/orjson-3.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:cd67d8b3e0e56222a2e7b7f7da9031e30ecd1fe251c023340b9f12caca85ab60", size = 133784 }, - { url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325 }, - { url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621 }, - { url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270 }, - { url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346 }, - { url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845 }, - { url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078 }, - { url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712 }, - { url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136 }, - { url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258 }, - { url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326 }, - { url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800 }, - { url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516 }, - { url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759 }, - { url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944 }, - { url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289 }, - { url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640 }, - { url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286 }, - { url = "https://files.pythonhosted.org/packages/c3/3c/72a22d4b28c076c4016d5a52bd644a8e4d849d3bb0373d9e377f9e3b2250/orjson-3.10.16-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df23f8df3ef9223d1d6748bea63fca55aae7da30a875700809c500a05975522b", size = 132307 }, - { url = "https://files.pythonhosted.org/packages/8a/a2/f1259561bdb6ad7061ff1b95dab082fe32758c4bc143ba8d3d70831f0a06/orjson-3.10.16-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b94dda8dd6d1378f1037d7f3f6b21db769ef911c4567cbaa962bb6dc5021cf90", size = 136739 }, - { url = "https://files.pythonhosted.org/packages/3d/af/c7583c4b34f33d8b8b90cfaab010ff18dd64e7074cc1e117a5f1eff20dcf/orjson-3.10.16-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f12970a26666a8775346003fd94347d03ccb98ab8aa063036818381acf5f523e", size = 138076 }, - { url = "https://files.pythonhosted.org/packages/d7/59/d7fc7fbdd3d4a64c2eae4fc7341a5aa39cf9549bd5e2d7f6d3c07f8b715b/orjson-3.10.16-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a1431a245d856bd56e4d29ea0023eb4d2c8f71efe914beb3dee8ab3f0cd7fb", size = 142643 }, - { url = "https://files.pythonhosted.org/packages/92/0e/3bd8f2197d27601f16b4464ae948826da2bcf128af31230a9dbbad7ceb57/orjson-3.10.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83655cfc247f399a222567d146524674a7b217af7ef8289c0ff53cfe8db09f0", size = 133168 }, - { url = "https://files.pythonhosted.org/packages/af/a8/351fd87b664b02f899f9144d2c3dc848b33ac04a5df05234cbfb9e2a7540/orjson-3.10.16-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa59ae64cb6ddde8f09bdbf7baf933c4cd05734ad84dcf4e43b887eb24e37652", size = 135271 }, - { url = "https://files.pythonhosted.org/packages/ba/b0/a6d42a7d412d867c60c0337d95123517dd5a9370deea705ea1be0f89389e/orjson-3.10.16-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ca5426e5aacc2e9507d341bc169d8af9c3cbe88f4cd4c1cf2f87e8564730eb56", size = 412444 }, - { url = "https://files.pythonhosted.org/packages/79/ec/7572cd4e20863f60996f3f10bc0a6da64a6fd9c35954189a914cec0b7377/orjson-3.10.16-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6fd5da4edf98a400946cd3a195680de56f1e7575109b9acb9493331047157430", size = 152737 }, - { url = "https://files.pythonhosted.org/packages/a9/19/ceb9e8fed5403b2e76a8ac15f581b9d25780a3be3c9b3aa54b7777a210d5/orjson-3.10.16-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:980ecc7a53e567169282a5e0ff078393bac78320d44238da4e246d71a4e0e8f5", size = 137482 }, - { url = "https://files.pythonhosted.org/packages/1b/78/a78bb810f3786579dbbbd94768284cbe8f2fd65167cd7020260679665c17/orjson-3.10.16-cp313-cp313-win32.whl", hash = "sha256:28f79944dd006ac540a6465ebd5f8f45dfdf0948ff998eac7a908275b4c1add6", size = 141714 }, - { url = "https://files.pythonhosted.org/packages/81/9c/b66ce9245ff319df2c3278acd351a3f6145ef34b4a2d7f4b0f739368370f/orjson-3.10.16-cp313-cp313-win_amd64.whl", hash = "sha256:fe0a145e96d51971407cb8ba947e63ead2aa915db59d6631a355f5f2150b56b7", size = 133954 }, - { url = "https://files.pythonhosted.org/packages/33/00/91655baf4fdecf4aff3b56fb77e486306b159bbb77fb80b99bd4a03787a9/orjson-3.10.16-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c35b5c1fb5a5d6d2fea825dec5d3d16bea3c06ac744708a8e1ff41d4ba10cdf1", size = 249535 }, - { url = "https://files.pythonhosted.org/packages/28/8b/306f08148e3c9a6f35f6bc6084e91fb667338b362e710211c4852d472f5a/orjson-3.10.16-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9aac7ecc86218b4b3048c768f227a9452287001d7548500150bb75ee21bf55d", size = 138340 }, - { url = "https://files.pythonhosted.org/packages/57/b6/542ec958fb5dd83a76240e780780422c68b18512e0032fdc260f823b3255/orjson-3.10.16-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6e19f5102fff36f923b6dfdb3236ec710b649da975ed57c29833cb910c5a73ab", size = 132183 }, - { url = "https://files.pythonhosted.org/packages/4c/ea/82d792876e73e57c45a2daf193f90f3cef56348d40d8a78e936d2e0483e5/orjson-3.10.16-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17210490408eb62755a334a6f20ed17c39f27b4f45d89a38cd144cd458eba80b", size = 136603 }, - { url = "https://files.pythonhosted.org/packages/ee/e4/eff4c75080be8285e1e7d8a5ab1c2d5a49a71c767380651074e8bde73463/orjson-3.10.16-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbbe04451db85916e52a9f720bd89bf41f803cf63b038595674691680cbebd1b", size = 137171 }, - { url = "https://files.pythonhosted.org/packages/a7/48/99c3d69f7069fc8e498fc2acac273c16070f58575e493954c4dcafbd975d/orjson-3.10.16-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a966eba501a3a1f309f5a6af32ed9eb8f316fa19d9947bac3e6350dc63a6f0a", size = 142486 }, - { url = "https://files.pythonhosted.org/packages/5b/a8/28678461c7c9704e62005759f0446828478c323c8917d9199a86c438ac42/orjson-3.10.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01e0d22f06c81e6c435723343e1eefc710e0510a35d897856766d475f2a15687", size = 132615 }, - { url = "https://files.pythonhosted.org/packages/03/40/d9bdb7c6978d70fc634e29176ef0fb2f69cb10ed3a3d6a2f24b56c520448/orjson-3.10.16-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7c1e602d028ee285dbd300fb9820b342b937df64d5a3336e1618b354e95a2569", size = 135247 }, - { url = "https://files.pythonhosted.org/packages/5e/50/5d551c93268ef990df5c8c5df82c2c8ef21666e930fa977b4c5645df7e8c/orjson-3.10.16-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:d230e5020666a6725629df81e210dc11c3eae7d52fe909a7157b3875238484f3", size = 412165 }, - { url = "https://files.pythonhosted.org/packages/6f/20/e5bbff4f0871ed4741082c51ea6399b5af5bb6336abb8986fbbf145d1ad4/orjson-3.10.16-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0f8baac07d4555f57d44746a7d80fbe6b2c4fe2ed68136b4abb51cfec512a5e9", size = 152511 }, - { url = "https://files.pythonhosted.org/packages/4c/f8/e3b6c13949f0caaad0cc1cf25c08cb9de210770660b404d60c29f2721b3e/orjson-3.10.16-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:524e48420b90fc66953e91b660b3d05faaf921277d6707e328fde1c218b31250", size = 137057 }, - { url = "https://files.pythonhosted.org/packages/69/a1/4f5ade811b74843e677adc9101b54210a1d5b5e44b58c8683e9303fe7aec/orjson-3.10.16-cp39-cp39-win32.whl", hash = "sha256:a9f614e31423d7292dbca966a53b2d775c64528c7d91424ab2747d8ab8ce5c72", size = 141618 }, - { url = "https://files.pythonhosted.org/packages/d7/78/8db408b16d0cf53a3e9d195bd2866759a7dcd5a89a28e3c9d3c8b8f85649/orjson-3.10.16-cp39-cp39-win_amd64.whl", hash = "sha256:c338dc2296d1ed0d5c5c27dfb22d00b330555cb706c2e0be1e1c3940a0895905", size = 133598 }, +version = "3.10.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/0b/fea456a3ffe74e70ba30e01ec183a9b26bec4d497f61dcfce1b601059c60/orjson-3.10.18.tar.gz", hash = "sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53", size = 5422810, upload-time = "2025-04-29T23:30:08.423Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/16/2ceb9fb7bc2b11b1e4a3ea27794256e93dee2309ebe297fd131a778cd150/orjson-3.10.18-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a45e5d68066b408e4bc383b6e4ef05e717c65219a9e1390abc6155a520cac402", size = 248927, upload-time = "2025-04-29T23:28:08.643Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e1/d3c0a2bba5b9906badd121da449295062b289236c39c3a7801f92c4682b0/orjson-3.10.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be3b9b143e8b9db05368b13b04c84d37544ec85bb97237b3a923f076265ec89c", size = 136995, upload-time = "2025-04-29T23:28:11.503Z" }, + { url = "https://files.pythonhosted.org/packages/d7/51/698dd65e94f153ee5ecb2586c89702c9e9d12f165a63e74eb9ea1299f4e1/orjson-3.10.18-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9b0aa09745e2c9b3bf779b096fa71d1cc2d801a604ef6dd79c8b1bfef52b2f92", size = 132893, upload-time = "2025-04-29T23:28:12.751Z" }, + { url = "https://files.pythonhosted.org/packages/b3/e5/155ce5a2c43a85e790fcf8b985400138ce5369f24ee6770378ee6b691036/orjson-3.10.18-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53a245c104d2792e65c8d225158f2b8262749ffe64bc7755b00024757d957a13", size = 137017, upload-time = "2025-04-29T23:28:14.498Z" }, + { url = "https://files.pythonhosted.org/packages/46/bb/6141ec3beac3125c0b07375aee01b5124989907d61c72c7636136e4bd03e/orjson-3.10.18-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9495ab2611b7f8a0a8a505bcb0f0cbdb5469caafe17b0e404c3c746f9900469", size = 138290, upload-time = "2025-04-29T23:28:16.211Z" }, + { url = "https://files.pythonhosted.org/packages/77/36/6961eca0b66b7809d33c4ca58c6bd4c23a1b914fb23aba2fa2883f791434/orjson-3.10.18-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73be1cbcebadeabdbc468f82b087df435843c809cd079a565fb16f0f3b23238f", size = 142828, upload-time = "2025-04-29T23:28:18.065Z" }, + { url = "https://files.pythonhosted.org/packages/8b/2f/0c646d5fd689d3be94f4d83fa9435a6c4322c9b8533edbb3cd4bc8c5f69a/orjson-3.10.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8936ee2679e38903df158037a2f1c108129dee218975122e37847fb1d4ac68", size = 132806, upload-time = "2025-04-29T23:28:19.782Z" }, + { url = "https://files.pythonhosted.org/packages/ea/af/65907b40c74ef4c3674ef2bcfa311c695eb934710459841b3c2da212215c/orjson-3.10.18-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7115fcbc8525c74e4c2b608129bef740198e9a120ae46184dac7683191042056", size = 135005, upload-time = "2025-04-29T23:28:21.367Z" }, + { url = "https://files.pythonhosted.org/packages/c7/d1/68bd20ac6a32cd1f1b10d23e7cc58ee1e730e80624e3031d77067d7150fc/orjson-3.10.18-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:771474ad34c66bc4d1c01f645f150048030694ea5b2709b87d3bda273ffe505d", size = 413418, upload-time = "2025-04-29T23:28:23.097Z" }, + { url = "https://files.pythonhosted.org/packages/31/31/c701ec0bcc3e80e5cb6e319c628ef7b768aaa24b0f3b4c599df2eaacfa24/orjson-3.10.18-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:7c14047dbbea52886dd87169f21939af5d55143dad22d10db6a7514f058156a8", size = 153288, upload-time = "2025-04-29T23:28:25.02Z" }, + { url = "https://files.pythonhosted.org/packages/d9/31/5e1aa99a10893a43cfc58009f9da840990cc8a9ebb75aa452210ba18587e/orjson-3.10.18-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:641481b73baec8db14fdf58f8967e52dc8bda1f2aba3aa5f5c1b07ed6df50b7f", size = 137181, upload-time = "2025-04-29T23:28:26.318Z" }, + { url = "https://files.pythonhosted.org/packages/bf/8c/daba0ac1b8690011d9242a0f37235f7d17df6d0ad941021048523b76674e/orjson-3.10.18-cp310-cp310-win32.whl", hash = "sha256:607eb3ae0909d47280c1fc657c4284c34b785bae371d007595633f4b1a2bbe06", size = 142694, upload-time = "2025-04-29T23:28:28.092Z" }, + { url = "https://files.pythonhosted.org/packages/16/62/8b687724143286b63e1d0fab3ad4214d54566d80b0ba9d67c26aaf28a2f8/orjson-3.10.18-cp310-cp310-win_amd64.whl", hash = "sha256:8770432524ce0eca50b7efc2a9a5f486ee0113a5fbb4231526d414e6254eba92", size = 134600, upload-time = "2025-04-29T23:28:29.422Z" }, + { url = "https://files.pythonhosted.org/packages/97/c7/c54a948ce9a4278794f669a353551ce7db4ffb656c69a6e1f2264d563e50/orjson-3.10.18-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e0a183ac3b8e40471e8d843105da6fbe7c070faab023be3b08188ee3f85719b8", size = 248929, upload-time = "2025-04-29T23:28:30.716Z" }, + { url = "https://files.pythonhosted.org/packages/9e/60/a9c674ef1dd8ab22b5b10f9300e7e70444d4e3cda4b8258d6c2488c32143/orjson-3.10.18-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:5ef7c164d9174362f85238d0cd4afdeeb89d9e523e4651add6a5d458d6f7d42d", size = 133364, upload-time = "2025-04-29T23:28:32.392Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4e/f7d1bdd983082216e414e6d7ef897b0c2957f99c545826c06f371d52337e/orjson-3.10.18-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd14c5d99cdc7bf93f22b12ec3b294931518aa019e2a147e8aa2f31fd3240f7", size = 136995, upload-time = "2025-04-29T23:28:34.024Z" }, + { url = "https://files.pythonhosted.org/packages/17/89/46b9181ba0ea251c9243b0c8ce29ff7c9796fa943806a9c8b02592fce8ea/orjson-3.10.18-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b672502323b6cd133c4af6b79e3bea36bad2d16bca6c1f645903fce83909a7a", size = 132894, upload-time = "2025-04-29T23:28:35.318Z" }, + { url = "https://files.pythonhosted.org/packages/ca/dd/7bce6fcc5b8c21aef59ba3c67f2166f0a1a9b0317dcca4a9d5bd7934ecfd/orjson-3.10.18-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51f8c63be6e070ec894c629186b1c0fe798662b8687f3d9fdfa5e401c6bd7679", size = 137016, upload-time = "2025-04-29T23:28:36.674Z" }, + { url = "https://files.pythonhosted.org/packages/1c/4a/b8aea1c83af805dcd31c1f03c95aabb3e19a016b2a4645dd822c5686e94d/orjson-3.10.18-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f9478ade5313d724e0495d167083c6f3be0dd2f1c9c8a38db9a9e912cdaf947", size = 138290, upload-time = "2025-04-29T23:28:38.3Z" }, + { url = "https://files.pythonhosted.org/packages/36/d6/7eb05c85d987b688707f45dcf83c91abc2251e0dd9fb4f7be96514f838b1/orjson-3.10.18-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:187aefa562300a9d382b4b4eb9694806e5848b0cedf52037bb5c228c61bb66d4", size = 142829, upload-time = "2025-04-29T23:28:39.657Z" }, + { url = "https://files.pythonhosted.org/packages/d2/78/ddd3ee7873f2b5f90f016bc04062713d567435c53ecc8783aab3a4d34915/orjson-3.10.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da552683bc9da222379c7a01779bddd0ad39dd699dd6300abaf43eadee38334", size = 132805, upload-time = "2025-04-29T23:28:40.969Z" }, + { url = "https://files.pythonhosted.org/packages/8c/09/c8e047f73d2c5d21ead9c180203e111cddeffc0848d5f0f974e346e21c8e/orjson-3.10.18-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e450885f7b47a0231979d9c49b567ed1c4e9f69240804621be87c40bc9d3cf17", size = 135008, upload-time = "2025-04-29T23:28:42.284Z" }, + { url = "https://files.pythonhosted.org/packages/0c/4b/dccbf5055ef8fb6eda542ab271955fc1f9bf0b941a058490293f8811122b/orjson-3.10.18-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5e3c9cc2ba324187cd06287ca24f65528f16dfc80add48dc99fa6c836bb3137e", size = 413419, upload-time = "2025-04-29T23:28:43.673Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f3/1eac0c5e2d6d6790bd2025ebfbefcbd37f0d097103d76f9b3f9302af5a17/orjson-3.10.18-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:50ce016233ac4bfd843ac5471e232b865271d7d9d44cf9d33773bcd883ce442b", size = 153292, upload-time = "2025-04-29T23:28:45.573Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b4/ef0abf64c8f1fabf98791819ab502c2c8c1dc48b786646533a93637d8999/orjson-3.10.18-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3ceff74a8f7ffde0b2785ca749fc4e80e4315c0fd887561144059fb1c138aa7", size = 137182, upload-time = "2025-04-29T23:28:47.229Z" }, + { url = "https://files.pythonhosted.org/packages/a9/a3/6ea878e7b4a0dc5c888d0370d7752dcb23f402747d10e2257478d69b5e63/orjson-3.10.18-cp311-cp311-win32.whl", hash = "sha256:fdba703c722bd868c04702cac4cb8c6b8ff137af2623bc0ddb3b3e6a2c8996c1", size = 142695, upload-time = "2025-04-29T23:28:48.564Z" }, + { url = "https://files.pythonhosted.org/packages/79/2a/4048700a3233d562f0e90d5572a849baa18ae4e5ce4c3ba6247e4ece57b0/orjson-3.10.18-cp311-cp311-win_amd64.whl", hash = "sha256:c28082933c71ff4bc6ccc82a454a2bffcef6e1d7379756ca567c772e4fb3278a", size = 134603, upload-time = "2025-04-29T23:28:50.442Z" }, + { url = "https://files.pythonhosted.org/packages/03/45/10d934535a4993d27e1c84f1810e79ccf8b1b7418cef12151a22fe9bb1e1/orjson-3.10.18-cp311-cp311-win_arm64.whl", hash = "sha256:a6c7c391beaedd3fa63206e5c2b7b554196f14debf1ec9deb54b5d279b1b46f5", size = 131400, upload-time = "2025-04-29T23:28:51.838Z" }, + { url = "https://files.pythonhosted.org/packages/21/1a/67236da0916c1a192d5f4ccbe10ec495367a726996ceb7614eaa687112f2/orjson-3.10.18-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:50c15557afb7f6d63bc6d6348e0337a880a04eaa9cd7c9d569bcb4e760a24753", size = 249184, upload-time = "2025-04-29T23:28:53.612Z" }, + { url = "https://files.pythonhosted.org/packages/b3/bc/c7f1db3b1d094dc0c6c83ed16b161a16c214aaa77f311118a93f647b32dc/orjson-3.10.18-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:356b076f1662c9813d5fa56db7d63ccceef4c271b1fb3dd522aca291375fcf17", size = 133279, upload-time = "2025-04-29T23:28:55.055Z" }, + { url = "https://files.pythonhosted.org/packages/af/84/664657cd14cc11f0d81e80e64766c7ba5c9b7fc1ec304117878cc1b4659c/orjson-3.10.18-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:559eb40a70a7494cd5beab2d73657262a74a2c59aff2068fdba8f0424ec5b39d", size = 136799, upload-time = "2025-04-29T23:28:56.828Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bb/f50039c5bb05a7ab024ed43ba25d0319e8722a0ac3babb0807e543349978/orjson-3.10.18-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3c29eb9a81e2fbc6fd7ddcfba3e101ba92eaff455b8d602bf7511088bbc0eae", size = 132791, upload-time = "2025-04-29T23:28:58.751Z" }, + { url = "https://files.pythonhosted.org/packages/93/8c/ee74709fc072c3ee219784173ddfe46f699598a1723d9d49cbc78d66df65/orjson-3.10.18-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6612787e5b0756a171c7d81ba245ef63a3533a637c335aa7fcb8e665f4a0966f", size = 137059, upload-time = "2025-04-29T23:29:00.129Z" }, + { url = "https://files.pythonhosted.org/packages/6a/37/e6d3109ee004296c80426b5a62b47bcadd96a3deab7443e56507823588c5/orjson-3.10.18-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ac6bd7be0dcab5b702c9d43d25e70eb456dfd2e119d512447468f6405b4a69c", size = 138359, upload-time = "2025-04-29T23:29:01.704Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5d/387dafae0e4691857c62bd02839a3bf3fa648eebd26185adfac58d09f207/orjson-3.10.18-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f72f100cee8dde70100406d5c1abba515a7df926d4ed81e20a9730c062fe9ad", size = 142853, upload-time = "2025-04-29T23:29:03.576Z" }, + { url = "https://files.pythonhosted.org/packages/27/6f/875e8e282105350b9a5341c0222a13419758545ae32ad6e0fcf5f64d76aa/orjson-3.10.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9dca85398d6d093dd41dc0983cbf54ab8e6afd1c547b6b8a311643917fbf4e0c", size = 133131, upload-time = "2025-04-29T23:29:05.753Z" }, + { url = "https://files.pythonhosted.org/packages/48/b2/73a1f0b4790dcb1e5a45f058f4f5dcadc8a85d90137b50d6bbc6afd0ae50/orjson-3.10.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:22748de2a07fcc8781a70edb887abf801bb6142e6236123ff93d12d92db3d406", size = 134834, upload-time = "2025-04-29T23:29:07.35Z" }, + { url = "https://files.pythonhosted.org/packages/56/f5/7ed133a5525add9c14dbdf17d011dd82206ca6840811d32ac52a35935d19/orjson-3.10.18-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3a83c9954a4107b9acd10291b7f12a6b29e35e8d43a414799906ea10e75438e6", size = 413368, upload-time = "2025-04-29T23:29:09.301Z" }, + { url = "https://files.pythonhosted.org/packages/11/7c/439654221ed9c3324bbac7bdf94cf06a971206b7b62327f11a52544e4982/orjson-3.10.18-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:303565c67a6c7b1f194c94632a4a39918e067bd6176a48bec697393865ce4f06", size = 153359, upload-time = "2025-04-29T23:29:10.813Z" }, + { url = "https://files.pythonhosted.org/packages/48/e7/d58074fa0cc9dd29a8fa2a6c8d5deebdfd82c6cfef72b0e4277c4017563a/orjson-3.10.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:86314fdb5053a2f5a5d881f03fca0219bfdf832912aa88d18676a5175c6916b5", size = 137466, upload-time = "2025-04-29T23:29:12.26Z" }, + { url = "https://files.pythonhosted.org/packages/57/4d/fe17581cf81fb70dfcef44e966aa4003360e4194d15a3f38cbffe873333a/orjson-3.10.18-cp312-cp312-win32.whl", hash = "sha256:187ec33bbec58c76dbd4066340067d9ece6e10067bb0cc074a21ae3300caa84e", size = 142683, upload-time = "2025-04-29T23:29:13.865Z" }, + { url = "https://files.pythonhosted.org/packages/e6/22/469f62d25ab5f0f3aee256ea732e72dc3aab6d73bac777bd6277955bceef/orjson-3.10.18-cp312-cp312-win_amd64.whl", hash = "sha256:f9f94cf6d3f9cd720d641f8399e390e7411487e493962213390d1ae45c7814fc", size = 134754, upload-time = "2025-04-29T23:29:15.338Z" }, + { url = "https://files.pythonhosted.org/packages/10/b0/1040c447fac5b91bc1e9c004b69ee50abb0c1ffd0d24406e1350c58a7fcb/orjson-3.10.18-cp312-cp312-win_arm64.whl", hash = "sha256:3d600be83fe4514944500fa8c2a0a77099025ec6482e8087d7659e891f23058a", size = 131218, upload-time = "2025-04-29T23:29:17.324Z" }, + { url = "https://files.pythonhosted.org/packages/04/f0/8aedb6574b68096f3be8f74c0b56d36fd94bcf47e6c7ed47a7bd1474aaa8/orjson-3.10.18-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:69c34b9441b863175cc6a01f2935de994025e773f814412030f269da4f7be147", size = 249087, upload-time = "2025-04-29T23:29:19.083Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f7/7118f965541aeac6844fcb18d6988e111ac0d349c9b80cda53583e758908/orjson-3.10.18-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1ebeda919725f9dbdb269f59bc94f861afbe2a27dce5608cdba2d92772364d1c", size = 133273, upload-time = "2025-04-29T23:29:20.602Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d9/839637cc06eaf528dd8127b36004247bf56e064501f68df9ee6fd56a88ee/orjson-3.10.18-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5adf5f4eed520a4959d29ea80192fa626ab9a20b2ea13f8f6dc58644f6927103", size = 136779, upload-time = "2025-04-29T23:29:22.062Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/f226ecfef31a1f0e7d6bf9a31a0bbaf384c7cbe3fce49cc9c2acc51f902a/orjson-3.10.18-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7592bb48a214e18cd670974f289520f12b7aed1fa0b2e2616b8ed9e069e08595", size = 132811, upload-time = "2025-04-29T23:29:23.602Z" }, + { url = "https://files.pythonhosted.org/packages/73/2d/371513d04143c85b681cf8f3bce743656eb5b640cb1f461dad750ac4b4d4/orjson-3.10.18-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f872bef9f042734110642b7a11937440797ace8c87527de25e0c53558b579ccc", size = 137018, upload-time = "2025-04-29T23:29:25.094Z" }, + { url = "https://files.pythonhosted.org/packages/69/cb/a4d37a30507b7a59bdc484e4a3253c8141bf756d4e13fcc1da760a0b00cb/orjson-3.10.18-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0315317601149c244cb3ecef246ef5861a64824ccbcb8018d32c66a60a84ffbc", size = 138368, upload-time = "2025-04-29T23:29:26.609Z" }, + { url = "https://files.pythonhosted.org/packages/1e/ae/cd10883c48d912d216d541eb3db8b2433415fde67f620afe6f311f5cd2ca/orjson-3.10.18-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0da26957e77e9e55a6c2ce2e7182a36a6f6b180ab7189315cb0995ec362e049", size = 142840, upload-time = "2025-04-29T23:29:28.153Z" }, + { url = "https://files.pythonhosted.org/packages/6d/4c/2bda09855c6b5f2c055034c9eda1529967b042ff8d81a05005115c4e6772/orjson-3.10.18-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb70d489bc79b7519e5803e2cc4c72343c9dc1154258adf2f8925d0b60da7c58", size = 133135, upload-time = "2025-04-29T23:29:29.726Z" }, + { url = "https://files.pythonhosted.org/packages/13/4a/35971fd809a8896731930a80dfff0b8ff48eeb5d8b57bb4d0d525160017f/orjson-3.10.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e9e86a6af31b92299b00736c89caf63816f70a4001e750bda179e15564d7a034", size = 134810, upload-time = "2025-04-29T23:29:31.269Z" }, + { url = "https://files.pythonhosted.org/packages/99/70/0fa9e6310cda98365629182486ff37a1c6578e34c33992df271a476ea1cd/orjson-3.10.18-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c382a5c0b5931a5fc5405053d36c1ce3fd561694738626c77ae0b1dfc0242ca1", size = 413491, upload-time = "2025-04-29T23:29:33.315Z" }, + { url = "https://files.pythonhosted.org/packages/32/cb/990a0e88498babddb74fb97855ae4fbd22a82960e9b06eab5775cac435da/orjson-3.10.18-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8e4b2ae732431127171b875cb2668f883e1234711d3c147ffd69fe5be51a8012", size = 153277, upload-time = "2025-04-29T23:29:34.946Z" }, + { url = "https://files.pythonhosted.org/packages/92/44/473248c3305bf782a384ed50dd8bc2d3cde1543d107138fd99b707480ca1/orjson-3.10.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d808e34ddb24fc29a4d4041dcfafbae13e129c93509b847b14432717d94b44f", size = 137367, upload-time = "2025-04-29T23:29:36.52Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fd/7f1d3edd4ffcd944a6a40e9f88af2197b619c931ac4d3cfba4798d4d3815/orjson-3.10.18-cp313-cp313-win32.whl", hash = "sha256:ad8eacbb5d904d5591f27dee4031e2c1db43d559edb8f91778efd642d70e6bea", size = 142687, upload-time = "2025-04-29T23:29:38.292Z" }, + { url = "https://files.pythonhosted.org/packages/4b/03/c75c6ad46be41c16f4cfe0352a2d1450546f3c09ad2c9d341110cd87b025/orjson-3.10.18-cp313-cp313-win_amd64.whl", hash = "sha256:aed411bcb68bf62e85588f2a7e03a6082cc42e5a2796e06e72a962d7c6310b52", size = 134794, upload-time = "2025-04-29T23:29:40.349Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/f53038a5a72cc4fd0b56c1eafb4ef64aec9685460d5ac34de98ca78b6e29/orjson-3.10.18-cp313-cp313-win_arm64.whl", hash = "sha256:f54c1385a0e6aba2f15a40d703b858bedad36ded0491e55d35d905b2c34a4cc3", size = 131186, upload-time = "2025-04-29T23:29:41.922Z" }, + { url = "https://files.pythonhosted.org/packages/df/db/69488acaa2316788b7e171f024912c6fe8193aa2e24e9cfc7bc41c3669ba/orjson-3.10.18-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c95fae14225edfd699454e84f61c3dd938df6629a00c6ce15e704f57b58433bb", size = 249301, upload-time = "2025-04-29T23:29:44.719Z" }, + { url = "https://files.pythonhosted.org/packages/23/21/d816c44ec5d1482c654e1d23517d935bb2716e1453ff9380e861dc6efdd3/orjson-3.10.18-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5232d85f177f98e0cefabb48b5e7f60cff6f3f0365f9c60631fecd73849b2a82", size = 136786, upload-time = "2025-04-29T23:29:46.517Z" }, + { url = "https://files.pythonhosted.org/packages/a5/9f/f68d8a9985b717e39ba7bf95b57ba173fcd86aeca843229ec60d38f1faa7/orjson-3.10.18-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2783e121cafedf0d85c148c248a20470018b4ffd34494a68e125e7d5857655d1", size = 132711, upload-time = "2025-04-29T23:29:48.605Z" }, + { url = "https://files.pythonhosted.org/packages/b5/63/447f5955439bf7b99bdd67c38a3f689d140d998ac58e3b7d57340520343c/orjson-3.10.18-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e54ee3722caf3db09c91f442441e78f916046aa58d16b93af8a91500b7bbf273", size = 136841, upload-time = "2025-04-29T23:29:50.31Z" }, + { url = "https://files.pythonhosted.org/packages/68/9e/4855972f2be74097242e4681ab6766d36638a079e09d66f3d6a5d1188ce7/orjson-3.10.18-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2daf7e5379b61380808c24f6fc182b7719301739e4271c3ec88f2984a2d61f89", size = 138082, upload-time = "2025-04-29T23:29:51.992Z" }, + { url = "https://files.pythonhosted.org/packages/08/0f/e68431e53a39698d2355faf1f018c60a3019b4b54b4ea6be9dc6b8208a3d/orjson-3.10.18-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f39b371af3add20b25338f4b29a8d6e79a8c7ed0e9dd49e008228a065d07781", size = 142618, upload-time = "2025-04-29T23:29:53.642Z" }, + { url = "https://files.pythonhosted.org/packages/32/da/bdcfff239ddba1b6ef465efe49d7e43cc8c30041522feba9fd4241d47c32/orjson-3.10.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b819ed34c01d88c6bec290e6842966f8e9ff84b7694632e88341363440d4cc0", size = 132627, upload-time = "2025-04-29T23:29:55.318Z" }, + { url = "https://files.pythonhosted.org/packages/0c/28/bc634da09bbe972328f615b0961f1e7d91acb3cc68bddbca9e8dd64e8e24/orjson-3.10.18-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2f6c57debaef0b1aa13092822cbd3698a1fb0209a9ea013a969f4efa36bdea57", size = 134832, upload-time = "2025-04-29T23:29:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/1d/d2/e8ac0c2d0ec782ed8925b4eb33f040cee1f1fbd1d8b268aeb84b94153e49/orjson-3.10.18-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:755b6d61ffdb1ffa1e768330190132e21343757c9aa2308c67257cc81a1a6f5a", size = 413161, upload-time = "2025-04-29T23:29:59.148Z" }, + { url = "https://files.pythonhosted.org/packages/28/f0/397e98c352a27594566e865999dc6b88d6f37d5bbb87b23c982af24114c4/orjson-3.10.18-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ce8d0a875a85b4c8579eab5ac535fb4b2a50937267482be402627ca7e7570ee3", size = 153012, upload-time = "2025-04-29T23:30:01.066Z" }, + { url = "https://files.pythonhosted.org/packages/93/bf/2c7334caeb48bdaa4cae0bde17ea417297ee136598653b1da7ae1f98c785/orjson-3.10.18-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57b5d0673cbd26781bebc2bf86f99dd19bd5a9cb55f71cc4f66419f6b50f3d77", size = 136999, upload-time = "2025-04-29T23:30:02.93Z" }, + { url = "https://files.pythonhosted.org/packages/35/72/4827b1c0c31621c2aa1e661a899cdd2cfac0565c6cd7131890daa4ef7535/orjson-3.10.18-cp39-cp39-win32.whl", hash = "sha256:951775d8b49d1d16ca8818b1f20c4965cae9157e7b562a2ae34d3967b8f21c8e", size = 142560, upload-time = "2025-04-29T23:30:04.805Z" }, + { url = "https://files.pythonhosted.org/packages/72/91/ef8e76868e7eed478887c82f60607a8abf58dadd24e95817229a4b2e2639/orjson-3.10.18-cp39-cp39-win_amd64.whl", hash = "sha256:fdd9d68f83f0bc4406610b1ac68bdcded8c5ee58605cc69e643a06f4d075f429", size = 134455, upload-time = "2025-04-29T23:30:06.588Z" }, ] [[package]] name = "packaging" version = "25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] [[package]] name = "platformdirs" version = "4.3.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291 } +sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291, upload-time = "2025-03-19T20:36:10.989Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499 }, + { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499, upload-time = "2025-03-19T20:36:09.038Z" }, ] [[package]] name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, ] [[package]] name = "polars" -version = "1.27.1" +version = "1.29.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/96/56ab877d3d690bd8e67f5c6aabfd3aa8bc7c33ee901767905f564a6ade36/polars-1.27.1.tar.gz", hash = "sha256:94fcb0216b56cd0594aa777db1760a41ad0dfffed90d2ca446cf9294d2e97f02", size = 4555382 } +sdist = { url = "https://files.pythonhosted.org/packages/0b/92/8d0e80fef779a392b1a736b554ffba62403026bad7df8a9de8b61dce018f/polars-1.29.0.tar.gz", hash = "sha256:d2acb71fce1ff0ea76db5f648abd91a7a6c460fafabce9a2e8175184efa00d02", size = 4582973, upload-time = "2025-04-30T20:57:22.46Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/f4/be965ca4e1372805d0d2313bb4ed8eae88804fc3bfeb6cb0a07c53191bdb/polars-1.27.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ba7ad4f8046d00dd97c1369e46a4b7e00ffcff5d38c0f847ee4b9b1bb182fb18", size = 34756840 }, - { url = "https://files.pythonhosted.org/packages/c0/1a/ae019d323e83c6e8a9b4323f3fea94e047715847dfa4c4cbaf20a6f8444e/polars-1.27.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:339e3948748ad6fa7a42e613c3fb165b497ed797e93fce1aa2cddf00fbc16cac", size = 31616000 }, - { url = "https://files.pythonhosted.org/packages/20/c1/c65924c0ca186f481c02b531f1ec66c34f9bbecc11d70246562bb4949876/polars-1.27.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f801e0d9da198eb97cfb4e8af4242b8396878ff67b655c71570b7e333102b72b", size = 35388976 }, - { url = "https://files.pythonhosted.org/packages/88/c2/37720b8794935f1e77bde439564fa421a41f5fed8111aeb7b9ca0ebafb2d/polars-1.27.1-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:4d18a29c65222451818b63cd397b2e95c20412ea0065d735a20a4a79a7b26e8a", size = 32586083 }, - { url = "https://files.pythonhosted.org/packages/41/3d/1bb108eb278c1eafb303f78c515fb71c9828944eba3fb5c0ac432b9fad28/polars-1.27.1-cp39-abi3-win_amd64.whl", hash = "sha256:a4f832cf478b282d97f8bf86eeae2df66fa1384de1c49bc61f7224a10cc6a5df", size = 35602500 }, - { url = "https://files.pythonhosted.org/packages/0f/5c/cc23daf0a228d6fadbbfc8a8c5165be33157abe5b9d72af3e127e0542857/polars-1.27.1-cp39-abi3-win_arm64.whl", hash = "sha256:4f238ee2e3c5660345cb62c0f731bbd6768362db96c058098359ecffa42c3c6c", size = 31891470 }, + { url = "https://files.pythonhosted.org/packages/e7/5f/b277179cfce1258fecf4ad73cf627f670be41fdf088727090f68ca9c96ff/polars-1.29.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d053ee3217df31468caf2f5ddb9fd0f3a94fd42afdf7d9abe23d9d424adca02b", size = 34206809, upload-time = "2025-04-30T20:56:14.744Z" }, + { url = "https://files.pythonhosted.org/packages/34/e7/634e5cb55ce8bef23ac8ad8e3834c9045f4b3cbdff1fb9e7826d864436e6/polars-1.29.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:14131078e365eae5ccda3e67383cd43c0c0598d7f760bdf1cb4082566c5494ce", size = 31100055, upload-time = "2025-04-30T20:56:19.43Z" }, + { url = "https://files.pythonhosted.org/packages/50/15/0e9072e410731980ebc567c60a0a5f02bc2183310e48704ef83682cdd54c/polars-1.29.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54f6902da333f99208b8d27765d580ba0299b412787c0564275912122c228e40", size = 34828438, upload-time = "2025-04-30T20:56:22.839Z" }, + { url = "https://files.pythonhosted.org/packages/69/c0/90fcaac5c95aa225b3899698289c0424d429ef72248b593f15294f95a35e/polars-1.29.0-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:7a0ac6a11088279af4d715f4b58068835f551fa5368504a53401743006115e78", size = 32073830, upload-time = "2025-04-30T20:56:26.742Z" }, + { url = "https://files.pythonhosted.org/packages/17/ed/e5e570e22a03549a3c5397035a006b2c6343856a9fd15cccb5db39bdfa0a/polars-1.29.0-cp39-abi3-win_amd64.whl", hash = "sha256:f5aac4656e58b1e12f9481950981ef68b5b0e53dd4903bd72472efd2d09a74c8", size = 34971841, upload-time = "2025-04-30T20:56:29.953Z" }, + { url = "https://files.pythonhosted.org/packages/45/fd/9039f609d76b3ebb13777f289502a00b52709aea5c35aed01d1090ac142f/polars-1.29.0-cp39-abi3-win_arm64.whl", hash = "sha256:0c105b07b980b77fe88c3200b015bf4695e53185385f0f244c13e2d1027c7bbf", size = 31298689, upload-time = "2025-04-30T20:56:33.449Z" }, ] [[package]] @@ -2102,9 +2108,9 @@ dependencies = [ { name = "faker" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bd/d0/8ce6a9912a6f1077710ebc46a6aa9a79a64a06b69d2d6b4ccefc9765ce8f/polyfactory-2.21.0.tar.gz", hash = "sha256:a6d8dba91b2515d744cc014b5be48835633f7ccb72519a68f8801759e5b1737a", size = 246314 } +sdist = { url = "https://files.pythonhosted.org/packages/bd/d0/8ce6a9912a6f1077710ebc46a6aa9a79a64a06b69d2d6b4ccefc9765ce8f/polyfactory-2.21.0.tar.gz", hash = "sha256:a6d8dba91b2515d744cc014b5be48835633f7ccb72519a68f8801759e5b1737a", size = 246314, upload-time = "2025-04-18T10:19:33.852Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/ba/c148fba517a0aaccfc4fca5e61bf2a051e084a417403e930dc615886d4e6/polyfactory-2.21.0-py3-none-any.whl", hash = "sha256:9483b764756c8622313d99f375889b1c0d92f09affb05742d7bcfa2b5198d8c5", size = 60875 }, + { url = "https://files.pythonhosted.org/packages/e0/ba/c148fba517a0aaccfc4fca5e61bf2a051e084a417403e930dc615886d4e6/polyfactory-2.21.0-py3-none-any.whl", hash = "sha256:9483b764756c8622313d99f375889b1c0d92f09affb05742d7bcfa2b5198d8c5", size = 60875, upload-time = "2025-04-18T10:19:31.881Z" }, ] [[package]] @@ -2118,9 +2124,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424 } +sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707 }, + { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, ] [[package]] @@ -2130,9 +2136,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "wcwidth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940 } +sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810 }, + { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, ] [[package]] @@ -2142,126 +2148,126 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f4/ac/87285f15f7cce6d4a008f33f1757fb5a13611ea8914eb58c3d0d26243468/proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012", size = 56142 } +sdist = { url = "https://files.pythonhosted.org/packages/f4/ac/87285f15f7cce6d4a008f33f1757fb5a13611ea8914eb58c3d0d26243468/proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012", size = 56142, upload-time = "2025-03-10T15:54:38.843Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/6d/280c4c2ce28b1593a19ad5239c8b826871fc6ec275c21afc8e1820108039/proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", size = 50163 }, + { url = "https://files.pythonhosted.org/packages/4e/6d/280c4c2ce28b1593a19ad5239c8b826871fc6ec275c21afc8e1820108039/proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", size = 50163, upload-time = "2025-03-10T15:54:37.335Z" }, ] [[package]] name = "protobuf" version = "5.29.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/17/7d/b9dca7365f0e2c4fa7c193ff795427cfa6290147e5185ab11ece280a18e7/protobuf-5.29.4.tar.gz", hash = "sha256:4f1dfcd7997b31ef8f53ec82781ff434a28bf71d9102ddde14d076adcfc78c99", size = 424902 } +sdist = { url = "https://files.pythonhosted.org/packages/17/7d/b9dca7365f0e2c4fa7c193ff795427cfa6290147e5185ab11ece280a18e7/protobuf-5.29.4.tar.gz", hash = "sha256:4f1dfcd7997b31ef8f53ec82781ff434a28bf71d9102ddde14d076adcfc78c99", size = 424902, upload-time = "2025-03-19T21:23:24.25Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/b2/043a1a1a20edd134563699b0e91862726a0dc9146c090743b6c44d798e75/protobuf-5.29.4-cp310-abi3-win32.whl", hash = "sha256:13eb236f8eb9ec34e63fc8b1d6efd2777d062fa6aaa68268fb67cf77f6839ad7", size = 422709 }, - { url = "https://files.pythonhosted.org/packages/79/fc/2474b59570daa818de6124c0a15741ee3e5d6302e9d6ce0bdfd12e98119f/protobuf-5.29.4-cp310-abi3-win_amd64.whl", hash = "sha256:bcefcdf3976233f8a502d265eb65ea740c989bacc6c30a58290ed0e519eb4b8d", size = 434506 }, - { url = "https://files.pythonhosted.org/packages/46/de/7c126bbb06aa0f8a7b38aaf8bd746c514d70e6a2a3f6dd460b3b7aad7aae/protobuf-5.29.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:307ecba1d852ec237e9ba668e087326a67564ef83e45a0189a772ede9e854dd0", size = 417826 }, - { url = "https://files.pythonhosted.org/packages/a2/b5/bade14ae31ba871a139aa45e7a8183d869efe87c34a4850c87b936963261/protobuf-5.29.4-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:aec4962f9ea93c431d5714ed1be1c93f13e1a8618e70035ba2b0564d9e633f2e", size = 319574 }, - { url = "https://files.pythonhosted.org/packages/46/88/b01ed2291aae68b708f7d334288ad5fb3e7aa769a9c309c91a0d55cb91b0/protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:d7d3f7d1d5a66ed4942d4fefb12ac4b14a29028b209d4bfb25c68ae172059922", size = 319672 }, - { url = "https://files.pythonhosted.org/packages/8a/b8/c3847343ebd9c7ae0b762de1e173b110689fd334ac8dcf1697ffd9316861/protobuf-5.29.4-cp39-cp39-win32.whl", hash = "sha256:fd32223020cb25a2cc100366f1dedc904e2d71d9322403224cdde5fdced0dabe", size = 422675 }, - { url = "https://files.pythonhosted.org/packages/f0/74/e23e1ab05b27ce0b55f70be90df82076a5c18924d98679110459c52bacd9/protobuf-5.29.4-cp39-cp39-win_amd64.whl", hash = "sha256:678974e1e3a9b975b8bc2447fca458db5f93a2fb6b0c8db46b6675b5b5346812", size = 434594 }, - { url = "https://files.pythonhosted.org/packages/12/fb/a586e0c973c95502e054ac5f81f88394f24ccc7982dac19c515acd9e2c93/protobuf-5.29.4-py3-none-any.whl", hash = "sha256:3fde11b505e1597f71b875ef2fc52062b6a9740e5f7c8997ce878b6009145862", size = 172551 }, + { url = "https://files.pythonhosted.org/packages/9a/b2/043a1a1a20edd134563699b0e91862726a0dc9146c090743b6c44d798e75/protobuf-5.29.4-cp310-abi3-win32.whl", hash = "sha256:13eb236f8eb9ec34e63fc8b1d6efd2777d062fa6aaa68268fb67cf77f6839ad7", size = 422709, upload-time = "2025-03-19T21:23:08.293Z" }, + { url = "https://files.pythonhosted.org/packages/79/fc/2474b59570daa818de6124c0a15741ee3e5d6302e9d6ce0bdfd12e98119f/protobuf-5.29.4-cp310-abi3-win_amd64.whl", hash = "sha256:bcefcdf3976233f8a502d265eb65ea740c989bacc6c30a58290ed0e519eb4b8d", size = 434506, upload-time = "2025-03-19T21:23:11.253Z" }, + { url = "https://files.pythonhosted.org/packages/46/de/7c126bbb06aa0f8a7b38aaf8bd746c514d70e6a2a3f6dd460b3b7aad7aae/protobuf-5.29.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:307ecba1d852ec237e9ba668e087326a67564ef83e45a0189a772ede9e854dd0", size = 417826, upload-time = "2025-03-19T21:23:13.132Z" }, + { url = "https://files.pythonhosted.org/packages/a2/b5/bade14ae31ba871a139aa45e7a8183d869efe87c34a4850c87b936963261/protobuf-5.29.4-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:aec4962f9ea93c431d5714ed1be1c93f13e1a8618e70035ba2b0564d9e633f2e", size = 319574, upload-time = "2025-03-19T21:23:14.531Z" }, + { url = "https://files.pythonhosted.org/packages/46/88/b01ed2291aae68b708f7d334288ad5fb3e7aa769a9c309c91a0d55cb91b0/protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:d7d3f7d1d5a66ed4942d4fefb12ac4b14a29028b209d4bfb25c68ae172059922", size = 319672, upload-time = "2025-03-19T21:23:15.839Z" }, + { url = "https://files.pythonhosted.org/packages/8a/b8/c3847343ebd9c7ae0b762de1e173b110689fd334ac8dcf1697ffd9316861/protobuf-5.29.4-cp39-cp39-win32.whl", hash = "sha256:fd32223020cb25a2cc100366f1dedc904e2d71d9322403224cdde5fdced0dabe", size = 422675, upload-time = "2025-03-19T21:23:19.811Z" }, + { url = "https://files.pythonhosted.org/packages/f0/74/e23e1ab05b27ce0b55f70be90df82076a5c18924d98679110459c52bacd9/protobuf-5.29.4-cp39-cp39-win_amd64.whl", hash = "sha256:678974e1e3a9b975b8bc2447fca458db5f93a2fb6b0c8db46b6675b5b5346812", size = 434594, upload-time = "2025-03-19T21:23:21.514Z" }, + { url = "https://files.pythonhosted.org/packages/12/fb/a586e0c973c95502e054ac5f81f88394f24ccc7982dac19c515acd9e2c93/protobuf-5.29.4-py3-none-any.whl", hash = "sha256:3fde11b505e1597f71b875ef2fc52062b6a9740e5f7c8997ce878b6009145862", size = 172551, upload-time = "2025-03-19T21:23:22.682Z" }, ] [[package]] name = "psqlpy" version = "0.9.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/39/bfa6bec547d9b197b72e547aee1440c300911895798fce00b0439ac8978b/psqlpy-0.9.3.tar.gz", hash = "sha256:f369528a4a1f5c8dea6efe0d469a07a735ab4d07e680faff4508699b183bcc37", size = 269627 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/ca/85ed2d5a927b1c0336e1c5ffc22ec576a9e9edc35a09895d9aa01f165c9b/psqlpy-0.9.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c36efab33733d6fb9064a0c9fb59de4a529376837b080277e6825437bb1efa9", size = 4240144 }, - { url = "https://files.pythonhosted.org/packages/93/72/45efb35a79ce717e282917610b3ff93fddd869d3e7702dfac8852c49b80f/psqlpy-0.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57d9b5054494daaa60a7337351c3f9fc36354bac5764dd868134f9e91cd11245", size = 4476802 }, - { url = "https://files.pythonhosted.org/packages/83/2b/2b25af4cc385bede8e1ba29a0e17ec0e72e8c6318c1c551af536f5216c54/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a32b7f7b700180058ac7b5e7a02bac4c91de1ac94404e2a2a4eb67c91d2369a", size = 4936843 }, - { url = "https://files.pythonhosted.org/packages/28/04/bff643f7bd711b41ccc15f7cadc041291350a3a5d989b07bc42b9515da20/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:40ce3f9b67c7cea8bff8ce7b2f435191f1f064168134c17ba457695278145cd1", size = 4207043 }, - { url = "https://files.pythonhosted.org/packages/04/ba/0e5822e81a7205a4d9cd558f4b0b7d2fae3b2c5ad64b66e08c8ee6fb2404/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e6704cd34d1ed0f0873c448eb206565fdcd3eb0fc435428860aa529ce203bec", size = 4806688 }, - { url = "https://files.pythonhosted.org/packages/c8/7a/e803e1c33ceb0c219c49db4767f1888294e08ddbf58e62bad81189e8f575/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3215cac58e8a6fb867a4cafaac3303d03ace5a623cb2ed7858ee797ab6b2bcd", size = 4651636 }, - { url = "https://files.pythonhosted.org/packages/50/a5/b69d8da7aee1c6c5c40396d832e0d970a3c4fbbe3974296010d7397c207b/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a741e1694325c737f1917fa80ffcda27a3a533c03d033a059b39e5fb85eca6", size = 4775602 }, - { url = "https://files.pythonhosted.org/packages/64/5f/27d3215bab4246d1978eecc74e649e4a12b7fbe895a24cc8ed1f0c6c5d09/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9013962aac0ca16d59e8b7a20856c0838fb09ddbf9a3e5bb2cde2add3c5a89", size = 4825250 }, - { url = "https://files.pythonhosted.org/packages/31/9c/beb520f93f8f5fccb8d09bf9afb5b99b844e89e154de733eb3f54dbcdc82/psqlpy-0.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2bdf0afa1cae9e79553665a906315d7c6421ed587b012ec9c4397e91c200fd7b", size = 4857456 }, - { url = "https://files.pythonhosted.org/packages/89/c4/5344648456b9184ef142baafd216396f2566e7025177070e26afbd52442c/psqlpy-0.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd2c3c3a5b0305d42430cc8af1d5c4130008b9a80cf5bb3fedfd414cd9b95181", size = 4977942 }, - { url = "https://files.pythonhosted.org/packages/5a/52/b376c046d4f4da66d22aa6db62a33fca8ccecc41538beb6640cef0c081b3/psqlpy-0.9.3-cp310-cp310-win32.whl", hash = "sha256:79a0ec837dd314df5af74577f8b5b2fb752e74641a5cb66d58d779d88648d191", size = 3308783 }, - { url = "https://files.pythonhosted.org/packages/08/24/f6552cdaf3e062966e6beac948c4f8daa28d32de9aae68011ebbeadd590b/psqlpy-0.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:ee0d53b33f7b841cd606a8dbbf8b36e809dddee526dc7e226a7d1b1fdb0e3e3b", size = 3721262 }, - { url = "https://files.pythonhosted.org/packages/5e/1a/48bdacd23b7d2e2dd2c74bef7591e35a40795e9071faf672828f947bc9b5/psqlpy-0.9.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:66830960242bdec926ebb697284731f643176f4694419ecc4e48d064545c6e40", size = 4240197 }, - { url = "https://files.pythonhosted.org/packages/4b/48/299439ba665aeafbd053150d77c451254a7ef797c143e9760cfbcfe240c2/psqlpy-0.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:45a12aead3ca4d2b18b114b541289bcb5894bd5746670ee9fe5d783f55a565d4", size = 4477221 }, - { url = "https://files.pythonhosted.org/packages/09/cb/fbddd6c99f770a0fece65a3470d98dc0873a16a6c4e1adda246e5a5e6551/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fec5e579f519b98f5feb9e2148549c48391811e3153156deee7d2bc129f605", size = 4937618 }, - { url = "https://files.pythonhosted.org/packages/6c/c0/4ace3aacbe3a7b9e87a282c3ca2313e25ef7970739e1f8392fa6da5781e7/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11a2b3574e9cf37f49dd5a8376823bb1c416222c133b59873ad2fdb91b0ba25f", size = 4206271 }, - { url = "https://files.pythonhosted.org/packages/eb/1b/194462eddc3373af65c04ed2d6d710f57812937f5361fb8492659e43987f/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92afd8603006a18461d91167eff7ac100029b47034bbdd477f5e3805f9d23ff8", size = 4805586 }, - { url = "https://files.pythonhosted.org/packages/b9/1f/fcdb60dda446b392f27243f9e5f633d4f8a95ab3e222c120d26b6b6ebf47/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71a912328513d6c89a8c3d1be615916ab360075c810ff0445e7c53030ff03186", size = 4653073 }, - { url = "https://files.pythonhosted.org/packages/c9/a7/b82afd9f9950304468cecc9b027fc8248d846764f9f9a0251b3c77c9c0f4/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4861bb23574f2275bbd4f695bd4b2393fe6a5442f0a1bb603ebb6061f9926f9e", size = 4786884 }, - { url = "https://files.pythonhosted.org/packages/29/49/11b42d762702be8624f6e1824a8743eb496951204389f1faaef1b31c60b7/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf151599e516d7b0bbe0f8e2c10d45b7a48a72be2716c9fe7a77ecf41b17e3b9", size = 4823808 }, - { url = "https://files.pythonhosted.org/packages/f5/39/300dfdfa8780e7a1cf0dc5569a489a87f0061a264ce87ffd762351f53d7f/psqlpy-0.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b3fece2b78d568d74435b5ff0f05406bb3a43b1c571a66b7c1909efd52c31508", size = 4857527 }, - { url = "https://files.pythonhosted.org/packages/c1/ec/178c575c45ad4884151d5f741e87ffe00712d491ad8c70413f2a4e95e173/psqlpy-0.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c49ea203ef3007b8dbd12a453dd6d45aa9ffd3e395181e837138d172e30c293", size = 4979751 }, - { url = "https://files.pythonhosted.org/packages/8a/0c/e5ebe4c100ac134ef16ad95469cd38e9654ceca017561789680020149765/psqlpy-0.9.3-cp311-cp311-win32.whl", hash = "sha256:60833a0187dfdd859248bc424326d34b96b74c627e057a286632adbe4fb185a1", size = 3308639 }, - { url = "https://files.pythonhosted.org/packages/90/e8/a0e1b19d7035e5b849ca57b1c201d0243268bd6a215781ebd197ccfdca81/psqlpy-0.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:185d508f9165ae51ed8e659ce8356986523ac14021233162e7b565a1b50e0486", size = 3721553 }, - { url = "https://files.pythonhosted.org/packages/6b/73/f65c655c2c3d89f36a6eb160db86e8aecbe7a0258368d05111b08456a3d6/psqlpy-0.9.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6502545e46f9453a6103152e223f43461ca90e4d6d353b8567b40b45a01d43f8", size = 4226965 }, - { url = "https://files.pythonhosted.org/packages/32/9b/e17f40ecf4c518d83ff4cd742869d769f2a26224531a6fe1dfee88bba210/psqlpy-0.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f447410df05b0b927a8cc995fa011477b291d57f1b8f8ca52ee4a3799b698c8b", size = 4440561 }, - { url = "https://files.pythonhosted.org/packages/6c/62/6f9e6b409c6af33792386ba0e7a2beece6cf96fdffa8739144dfc1c897f4/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b825a3534d6a2810aed9c53873b8a58562bd28afc95506643ec4cc095bdda1a0", size = 4936741 }, - { url = "https://files.pythonhosted.org/packages/ae/d3/9f5ed5a8703dd3b1349f4ff53b03eb4b2589cb0034186cdf8a562a97653c/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842a06192c4d6748aa63df3966b8685630ce1d2f1cdfbe54f95177c2db7436ad", size = 4219026 }, - { url = "https://files.pythonhosted.org/packages/7b/ca/9788d4ad663f6841825f89013414ac28a483bb031417ccf6e5f087065139/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ece78105348c482bbcc1c7504c2067e8baf8ec64600aea40c293880995fb39c", size = 4805613 }, - { url = "https://files.pythonhosted.org/packages/f8/a3/2702d69e47ef26a75c1f8fbf2cfe9e280da45945501998082644f98f1411/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c099c16aa3d224d3b0c6950eabbbf58154f04612522511c3d83a0e97cd689eed", size = 4645177 }, - { url = "https://files.pythonhosted.org/packages/aa/8a/c452f47cc9cabdcd694681ca2c8326ea3887cbf481678266e67de334d984/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb9746cdb5c8ddbbcf952bad67e07f4c46722de072cf6cfd69d8fb67d296156c", size = 4775536 }, - { url = "https://files.pythonhosted.org/packages/c6/1d/fa6f86bf856019b0f48cdc92497afe632e1176d1d12773d5a77971de0096/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4beb0fc66c7924edcf6f842682554910d93376e31d527fa3d055ee24326bd84f", size = 4826617 }, - { url = "https://files.pythonhosted.org/packages/6e/5c/8d85a5295ea236d85213aced33560ff93f8224dd7830d80e6bb37b5488d9/psqlpy-0.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:40e530d71441af61b791723bbf4a198b0da4e95f59d261e67074790564b629e5", size = 4826660 }, - { url = "https://files.pythonhosted.org/packages/d3/dd/d6181320adb9271bb8559c1588cf6c956592dd19876bf09937f8b647e5c6/psqlpy-0.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a74926fa272acc2889f510317894307c2dda7702feb8195a159b564603d0c74c", size = 4946588 }, - { url = "https://files.pythonhosted.org/packages/e0/0c/9fa61aec2daf03e257fe314a2db0671828e1b397b028473b190fac921067/psqlpy-0.9.3-cp312-cp312-win32.whl", hash = "sha256:2b125d06a0c2718b5cf3b9c866ea9bf19764f51c2aa054919534e4767f43b1f8", size = 3293165 }, - { url = "https://files.pythonhosted.org/packages/0a/7c/49717e45df23318bf1ebc6775ad4755e5b2ca7d920aaaeed514900a9fe65/psqlpy-0.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:613facca51bbf0682d863989e7368222e8040b3ce5f5b0ae3ce30d9df4e44d60", size = 3700904 }, - { url = "https://files.pythonhosted.org/packages/4d/70/491f46e652492b22a8038082eae8821c3f74febba3d89eb72efbaa50e41c/psqlpy-0.9.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9c7b371f5bc3e4e60e7f0b34db5c8ec82c6aee3e967f6916251895fc0123015b", size = 4225496 }, - { url = "https://files.pythonhosted.org/packages/2a/e2/83d29c062876383ad016897ecec2d8b67ca36fe3d37f5c25367e83c9a9db/psqlpy-0.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8546854232368d26eb2c7eba64df2765a4b4698d1465a9c20e6af0b61f495558", size = 4438780 }, - { url = "https://files.pythonhosted.org/packages/19/6a/4f520027cf6474f20e45a9292c9e80e297763c82ffb47cc4f9176d286865/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5e83ede139b7c650b5be3019de769db5bab44e72c3365604719222ca9c0825d", size = 4935733 }, - { url = "https://files.pythonhosted.org/packages/84/4d/44165581b4bc0eb7cda0b35da1a72681c38cb67506e18b244e5bd8373d9f/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5441f83b707f698c23b9c498845caabf523248adda1276be4efc58474991ba88", size = 4217304 }, - { url = "https://files.pythonhosted.org/packages/51/0b/357b9f0e303f6378cb5a03b58c5d0be31d219b013f5a670c5fec82ca3fc5/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9070b7a767aa3ad6d16a6b4008b3590e576296d1ef810f11fbf7ad317ca902e", size = 4804254 }, - { url = "https://files.pythonhosted.org/packages/e7/da/3721d5457d64584d521219328210a216790b7a911710864a9260bd2760c2/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2452e0c1b5fa1f4d4b0c73daf277de0785e2a4aaa7d75282b100b2d1758a7677", size = 4644033 }, - { url = "https://files.pythonhosted.org/packages/44/fc/1170684ea74be268d2b27ae7e69517c29f6bd5bafb192bb7f76615d3fa79/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:231f57d6129358bdd828f1a24667c727ac9cd07ae374b76ab9d860bc9778be36", size = 4774739 }, - { url = "https://files.pythonhosted.org/packages/4d/bb/cd369c0d7b9a022b07740167f1d7eae33ccac1a239e10b21306ca6ebc99e/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9d258b4af8593fafd02ec00dd594f0de7cb9c5a6d59bb30c0883bb314046bf4", size = 4826125 }, - { url = "https://files.pythonhosted.org/packages/2c/ff/6bba939bab5e6b7b42aa2b3f8eedb46f7c9d5e5c21e008c856986d594255/psqlpy-0.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a45f42936faa2839b72d8ba6f31c7f22490cf5211a5acfe507655b22110df6e", size = 4826300 }, - { url = "https://files.pythonhosted.org/packages/94/2f/2702b621b8d68683b14d954f5ff2a7a65904a9ae8ea1b62278a1d81cdd84/psqlpy-0.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81f2c9f7f94388d5977e28ab00522ddccd1b880e9f382e350207a80a6c2b790f", size = 4944879 }, - { url = "https://files.pythonhosted.org/packages/46/97/b6dacbe274cbf95419af1c8c6c5f06a0290a22a66b4202cbc493db97d127/psqlpy-0.9.3-cp313-cp313-win32.whl", hash = "sha256:9126f5e942c2a8ed1aefa8a662a2865f7aaf293a7610911fd4a07200c133a27a", size = 3292642 }, - { url = "https://files.pythonhosted.org/packages/ea/55/aaadda7cbdfdbef9f880b57fb25d3cb641e01a71fbd20d76f59a5eddab78/psqlpy-0.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:e438732440dbba845b1f2fcec426cc8a70461d31e81b330efe5ab4e5a83ead52", size = 3700554 }, - { url = "https://files.pythonhosted.org/packages/ae/4d/3395a1a83e4501f9928c83fbfdc88f643158a3224d76d06f6eca837c61a7/psqlpy-0.9.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:583f93e6dcdc5f0c6a9259ed7da686c5a888f10ac8546cdd7e4cacfac5826700", size = 4240939 }, - { url = "https://files.pythonhosted.org/packages/d4/46/610c514db36e83e1f5f9e3f309d30795eff8ef7cba45bc223bea98811fa4/psqlpy-0.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fc690c4b56b5aa3242518309167c78820621fd6b3284951c65d7426218be3f6", size = 4479396 }, - { url = "https://files.pythonhosted.org/packages/0d/36/fe06b173bee1bc09aac918c4759071773d433c04c943a7d161de1c93c87f/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1395fcfdb294d75ee9044b1da60fcaaca3d01c62cfa338f3c18ecd097e0bd738", size = 4937303 }, - { url = "https://files.pythonhosted.org/packages/c8/91/a2187176a1799c2b5d409f6d4fc39c40c2abfd3dfb2d08435c2956a86539/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:033e41fecdfe3b4dee6050d4002c5d619b9325bef4167cc497d644c093ee87f4", size = 4210807 }, - { url = "https://files.pythonhosted.org/packages/b7/d7/313638aee4d3f73c4c07bf37a232d83348c37c251f609881796ee6324267/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fadb57a391db8ac1b172a2f3882796e8f77ef2e01795db9fe96870b3d434116", size = 4807024 }, - { url = "https://files.pythonhosted.org/packages/01/09/64469aa84e596d8c08210ff6e86d7aafb75eedb7ffae12daa75519eb9f97/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7cb7714554cf08e4eaea8fd547dddb65a32927db4c37afd0fbe9a941d839743", size = 4653704 }, - { url = "https://files.pythonhosted.org/packages/e6/47/28eb3014eff4642be833abe1c5c745cd31efd63ef5706528901e9efad820/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ddbcd8438cc439862e05e03f4cf364f76dc51d918fe405878c1acfab1848112c", size = 4789815 }, - { url = "https://files.pythonhosted.org/packages/17/7c/509f51dfae6b4fd4282d2589199ab9a895bb3984bf27244231566d5f8cad/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd086508cf11e3c390f5d6ed638a39e3d2b4186e53e33ffe6af9b37981ef615", size = 4826656 }, - { url = "https://files.pythonhosted.org/packages/b5/79/bb9725575368f46570b646b45da22ef943e97b32e336a485ac169906c1d1/psqlpy-0.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:35aa277d6585ed14936e6c1e4de677564959e379485272906c88090cc5e635dd", size = 4860622 }, - { url = "https://files.pythonhosted.org/packages/d3/69/3d80d7286b116734fa8c256b711a0a9554d31df82f7f33cd52e7772ba77b/psqlpy-0.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:81a25ef924322a15a53ee6c36dd38c3d609d05c96f3cf500af33cd929cbe30a1", size = 4980015 }, - { url = "https://files.pythonhosted.org/packages/6c/09/b9c0f007c6686193a8f6362980c20c1b33e35cf7bac061071a2a84370e7c/psqlpy-0.9.3-cp39-cp39-win32.whl", hash = "sha256:fa1cbd09536576b22e7aa5e312cf802d4e7da2438c48064bf6886028e8977bec", size = 3311353 }, - { url = "https://files.pythonhosted.org/packages/2a/78/181d4f7fbb9f77dce11513b50406ae65484fb5e933143a8c038d73f0a549/psqlpy-0.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:ca15a64cbd4de84c7b9a34f388c70dded46316fac8af851c2f1ba51a755f378f", size = 3722931 }, - { url = "https://files.pythonhosted.org/packages/2b/b0/e5e9c3006523bf9a32d1b3506bb2dfc109101d1d8e9d28badba64af9ff38/psqlpy-0.9.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:8c4a6035ebfba0744b15a5c9a3668b2166393619bfb882a189468966ec45f7f0", size = 4236200 }, - { url = "https://files.pythonhosted.org/packages/97/23/af1bbbe53c04c029a45dd4c65bb19434c152f4c314d2362f5913ecf09c4d/psqlpy-0.9.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:681dee1d030873f08e55b154c8907a2062f0f6e4b10646411f5ce94028eb0642", size = 4474528 }, - { url = "https://files.pythonhosted.org/packages/a3/2a/60cad4acd6be95d0df233f13ac810fb357347f2d224eb2d70471df6c7353/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e26ed13c864b21542eab15f1dfccf02e40fae046076d9c48b3ff062f8406053b", size = 4937463 }, - { url = "https://files.pythonhosted.org/packages/fa/45/ba6e10effa92090ed508988dad48d776f466aa2cbc94c7a16b5f14d75e1e/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1baa0200bcdacc9f61efbd273074395bfc7f32b7f7a30fcebb260ae175545914", size = 4210011 }, - { url = "https://files.pythonhosted.org/packages/bc/fe/cd176b3a342b45d2f10ad24b109db7a069b437f411302b27eaea77cf0b28/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:925677b1c2ea70addbcb28b86ddc826b77a8107ec489e2d191fb74074ea423b2", size = 4806658 }, - { url = "https://files.pythonhosted.org/packages/59/8f/1898a03913f9b697d1b8ae02b3d435a5f05f60e81be5a91934e51044e310/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2c01d44e04f2e9fc7de1c3a8692f38fa22d0a354ce51888b91d8653cae4e0a3", size = 4656552 }, - { url = "https://files.pythonhosted.org/packages/60/4d/b67e4b9ffd963850107befa435e8b38b8e7d4f393ee15964c73706c67b13/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b89fb5906bffa757f76c1ef46ec48e3ec3488d484d95d9bc57503b30107e3041", size = 4788063 }, - { url = "https://files.pythonhosted.org/packages/25/36/ea1a770563db9105624d0ce73d1b16a80d82d9d278383f9b4633b97ea9ec/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c193eeca5dbceb770332197cc77a6e5e6ead210c34c4fff1d8cb8675e42e1f6", size = 4827112 }, - { url = "https://files.pythonhosted.org/packages/94/fe/248438003e8fcd3ba261da0de09b19a679f34c1b0d633222eef4c826729b/psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:eab75d64e3b27a52bcbee690e8651a3b0dbaeef3028a19afad3a848ccb1b2951", size = 4860284 }, - { url = "https://files.pythonhosted.org/packages/7f/43/70111a42df62bf3d1b4053192cd0a3e55f18c2297f8c2732b6baae4b9703/psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:a4f77af73b77bd73285efc0576a3ac087ee0aca39821371ea16d8e2bf9a16c90", size = 4980559 }, - { url = "https://files.pythonhosted.org/packages/c7/95/7089fd34c80e948d7f544c73f2ff1a0c20938024f61323e31a71bd85fe21/psqlpy-0.9.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d7d4c6fcc343e0c0238e767caccb534d08b42d234d96e35aa5ce55d195f81281", size = 4237481 }, - { url = "https://files.pythonhosted.org/packages/5a/ce/5819a1f1e8f69639789b523d227ce07b989b1fc565fed2e3efb3efc67dc2/psqlpy-0.9.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d0220fa8127db04433c2be2a55da1042e4581531a36692c45668c3484bda437", size = 4474728 }, - { url = "https://files.pythonhosted.org/packages/2c/55/daeab10685010204bfb18246fbdab892eeb0a0db94de5bfb3cabd524344b/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbdd68fa7f61e00d7f14f010cd4a7f242935cb9df560181bb947fde75c8c1af5", size = 4938916 }, - { url = "https://files.pythonhosted.org/packages/1d/35/2feb538ee0fa6d3e248727501b911dd99f20c58e65fd03c22d0d047bf7a5/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c1e3c82aeec4c58328c723ef0755c2f02e2d30874ce850e0d7505db8bd90397", size = 4211573 }, - { url = "https://files.pythonhosted.org/packages/dd/4e/588b6c548363dab19bb58d808760f785058cef0af7649c16c80ddaad2eea/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c936f35fa793b421b116aa37040291ff5a33fc54e7f636e7ae946ec987070a94", size = 4809847 }, - { url = "https://files.pythonhosted.org/packages/d6/cc/2aef99aef78b0df24e43790786c0507bb63f4e6fa3e338fbdccb4e1b70e7/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28ee25f791ccbad04269e22a21a79d52609d65298fe9b5300b8fe00fef42bab6", size = 4658403 }, - { url = "https://files.pythonhosted.org/packages/67/33/9d5094a57caddd9ffe2eb176e3e30a367312929323daa333bbc4dd11e3a4/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3a1d90bb1da48649852e636612bb12fa0e3ec07f230446836195054598f0de4", size = 4789341 }, - { url = "https://files.pythonhosted.org/packages/52/5a/3506b0b6731b7e3f6a818fb3dcef7b2f8685254790a7a4bb0a1c9c2ac3cc/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a764bf80ce4e9d284bc11e255aff836894ee55e540c1be20120e67f855d8b07c", size = 4829845 }, - { url = "https://files.pythonhosted.org/packages/6b/fd/cd5e2929cfe3e357694118638fa227cd9dc6b4717b39590e731d0e3bd2ee/psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7939bfa80b649e650b9b4efe9064936837b14082851f1ad95c24548a105277cd", size = 4862164 }, - { url = "https://files.pythonhosted.org/packages/b2/af/e4ca9ccaed96d27c1c753b6d4f16264f0f7a2c752249ea25074f636a6734/psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:23496ed36433c88308f7e85f36091b203bb6c8c655ded639ce1626a1c8319afe", size = 4981643 }, +sdist = { url = "https://files.pythonhosted.org/packages/df/39/bfa6bec547d9b197b72e547aee1440c300911895798fce00b0439ac8978b/psqlpy-0.9.3.tar.gz", hash = "sha256:f369528a4a1f5c8dea6efe0d469a07a735ab4d07e680faff4508699b183bcc37", size = 269627, upload-time = "2025-02-22T18:00:12.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/ca/85ed2d5a927b1c0336e1c5ffc22ec576a9e9edc35a09895d9aa01f165c9b/psqlpy-0.9.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c36efab33733d6fb9064a0c9fb59de4a529376837b080277e6825437bb1efa9", size = 4240144, upload-time = "2025-02-22T17:57:24.357Z" }, + { url = "https://files.pythonhosted.org/packages/93/72/45efb35a79ce717e282917610b3ff93fddd869d3e7702dfac8852c49b80f/psqlpy-0.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57d9b5054494daaa60a7337351c3f9fc36354bac5764dd868134f9e91cd11245", size = 4476802, upload-time = "2025-02-22T17:57:27.872Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/2b25af4cc385bede8e1ba29a0e17ec0e72e8c6318c1c551af536f5216c54/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a32b7f7b700180058ac7b5e7a02bac4c91de1ac94404e2a2a4eb67c91d2369a", size = 4936843, upload-time = "2025-02-22T17:57:30.235Z" }, + { url = "https://files.pythonhosted.org/packages/28/04/bff643f7bd711b41ccc15f7cadc041291350a3a5d989b07bc42b9515da20/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:40ce3f9b67c7cea8bff8ce7b2f435191f1f064168134c17ba457695278145cd1", size = 4207043, upload-time = "2025-02-22T17:57:31.668Z" }, + { url = "https://files.pythonhosted.org/packages/04/ba/0e5822e81a7205a4d9cd558f4b0b7d2fae3b2c5ad64b66e08c8ee6fb2404/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e6704cd34d1ed0f0873c448eb206565fdcd3eb0fc435428860aa529ce203bec", size = 4806688, upload-time = "2025-02-22T17:57:34.063Z" }, + { url = "https://files.pythonhosted.org/packages/c8/7a/e803e1c33ceb0c219c49db4767f1888294e08ddbf58e62bad81189e8f575/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3215cac58e8a6fb867a4cafaac3303d03ace5a623cb2ed7858ee797ab6b2bcd", size = 4651636, upload-time = "2025-02-22T17:57:37.354Z" }, + { url = "https://files.pythonhosted.org/packages/50/a5/b69d8da7aee1c6c5c40396d832e0d970a3c4fbbe3974296010d7397c207b/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a741e1694325c737f1917fa80ffcda27a3a533c03d033a059b39e5fb85eca6", size = 4775602, upload-time = "2025-02-22T17:57:39.796Z" }, + { url = "https://files.pythonhosted.org/packages/64/5f/27d3215bab4246d1978eecc74e649e4a12b7fbe895a24cc8ed1f0c6c5d09/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9013962aac0ca16d59e8b7a20856c0838fb09ddbf9a3e5bb2cde2add3c5a89", size = 4825250, upload-time = "2025-02-22T17:57:43.495Z" }, + { url = "https://files.pythonhosted.org/packages/31/9c/beb520f93f8f5fccb8d09bf9afb5b99b844e89e154de733eb3f54dbcdc82/psqlpy-0.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2bdf0afa1cae9e79553665a906315d7c6421ed587b012ec9c4397e91c200fd7b", size = 4857456, upload-time = "2025-02-22T17:57:45.861Z" }, + { url = "https://files.pythonhosted.org/packages/89/c4/5344648456b9184ef142baafd216396f2566e7025177070e26afbd52442c/psqlpy-0.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd2c3c3a5b0305d42430cc8af1d5c4130008b9a80cf5bb3fedfd414cd9b95181", size = 4977942, upload-time = "2025-02-22T17:57:47.462Z" }, + { url = "https://files.pythonhosted.org/packages/5a/52/b376c046d4f4da66d22aa6db62a33fca8ccecc41538beb6640cef0c081b3/psqlpy-0.9.3-cp310-cp310-win32.whl", hash = "sha256:79a0ec837dd314df5af74577f8b5b2fb752e74641a5cb66d58d779d88648d191", size = 3308783, upload-time = "2025-02-22T17:57:49.924Z" }, + { url = "https://files.pythonhosted.org/packages/08/24/f6552cdaf3e062966e6beac948c4f8daa28d32de9aae68011ebbeadd590b/psqlpy-0.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:ee0d53b33f7b841cd606a8dbbf8b36e809dddee526dc7e226a7d1b1fdb0e3e3b", size = 3721262, upload-time = "2025-02-22T17:57:52.295Z" }, + { url = "https://files.pythonhosted.org/packages/5e/1a/48bdacd23b7d2e2dd2c74bef7591e35a40795e9071faf672828f947bc9b5/psqlpy-0.9.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:66830960242bdec926ebb697284731f643176f4694419ecc4e48d064545c6e40", size = 4240197, upload-time = "2025-02-22T17:57:54.795Z" }, + { url = "https://files.pythonhosted.org/packages/4b/48/299439ba665aeafbd053150d77c451254a7ef797c143e9760cfbcfe240c2/psqlpy-0.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:45a12aead3ca4d2b18b114b541289bcb5894bd5746670ee9fe5d783f55a565d4", size = 4477221, upload-time = "2025-02-22T17:57:56.293Z" }, + { url = "https://files.pythonhosted.org/packages/09/cb/fbddd6c99f770a0fece65a3470d98dc0873a16a6c4e1adda246e5a5e6551/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fec5e579f519b98f5feb9e2148549c48391811e3153156deee7d2bc129f605", size = 4937618, upload-time = "2025-02-22T17:57:58.362Z" }, + { url = "https://files.pythonhosted.org/packages/6c/c0/4ace3aacbe3a7b9e87a282c3ca2313e25ef7970739e1f8392fa6da5781e7/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11a2b3574e9cf37f49dd5a8376823bb1c416222c133b59873ad2fdb91b0ba25f", size = 4206271, upload-time = "2025-02-22T17:58:00.753Z" }, + { url = "https://files.pythonhosted.org/packages/eb/1b/194462eddc3373af65c04ed2d6d710f57812937f5361fb8492659e43987f/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92afd8603006a18461d91167eff7ac100029b47034bbdd477f5e3805f9d23ff8", size = 4805586, upload-time = "2025-02-22T17:58:02.524Z" }, + { url = "https://files.pythonhosted.org/packages/b9/1f/fcdb60dda446b392f27243f9e5f633d4f8a95ab3e222c120d26b6b6ebf47/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71a912328513d6c89a8c3d1be615916ab360075c810ff0445e7c53030ff03186", size = 4653073, upload-time = "2025-02-22T17:58:05.133Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a7/b82afd9f9950304468cecc9b027fc8248d846764f9f9a0251b3c77c9c0f4/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4861bb23574f2275bbd4f695bd4b2393fe6a5442f0a1bb603ebb6061f9926f9e", size = 4786884, upload-time = "2025-02-22T17:58:07.561Z" }, + { url = "https://files.pythonhosted.org/packages/29/49/11b42d762702be8624f6e1824a8743eb496951204389f1faaef1b31c60b7/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf151599e516d7b0bbe0f8e2c10d45b7a48a72be2716c9fe7a77ecf41b17e3b9", size = 4823808, upload-time = "2025-02-22T17:58:09.179Z" }, + { url = "https://files.pythonhosted.org/packages/f5/39/300dfdfa8780e7a1cf0dc5569a489a87f0061a264ce87ffd762351f53d7f/psqlpy-0.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b3fece2b78d568d74435b5ff0f05406bb3a43b1c571a66b7c1909efd52c31508", size = 4857527, upload-time = "2025-02-22T17:58:11.896Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ec/178c575c45ad4884151d5f741e87ffe00712d491ad8c70413f2a4e95e173/psqlpy-0.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c49ea203ef3007b8dbd12a453dd6d45aa9ffd3e395181e837138d172e30c293", size = 4979751, upload-time = "2025-02-22T17:58:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0c/e5ebe4c100ac134ef16ad95469cd38e9654ceca017561789680020149765/psqlpy-0.9.3-cp311-cp311-win32.whl", hash = "sha256:60833a0187dfdd859248bc424326d34b96b74c627e057a286632adbe4fb185a1", size = 3308639, upload-time = "2025-02-22T17:58:15.259Z" }, + { url = "https://files.pythonhosted.org/packages/90/e8/a0e1b19d7035e5b849ca57b1c201d0243268bd6a215781ebd197ccfdca81/psqlpy-0.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:185d508f9165ae51ed8e659ce8356986523ac14021233162e7b565a1b50e0486", size = 3721553, upload-time = "2025-02-22T17:58:16.927Z" }, + { url = "https://files.pythonhosted.org/packages/6b/73/f65c655c2c3d89f36a6eb160db86e8aecbe7a0258368d05111b08456a3d6/psqlpy-0.9.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6502545e46f9453a6103152e223f43461ca90e4d6d353b8567b40b45a01d43f8", size = 4226965, upload-time = "2025-02-22T17:58:18.397Z" }, + { url = "https://files.pythonhosted.org/packages/32/9b/e17f40ecf4c518d83ff4cd742869d769f2a26224531a6fe1dfee88bba210/psqlpy-0.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f447410df05b0b927a8cc995fa011477b291d57f1b8f8ca52ee4a3799b698c8b", size = 4440561, upload-time = "2025-02-22T17:58:20.166Z" }, + { url = "https://files.pythonhosted.org/packages/6c/62/6f9e6b409c6af33792386ba0e7a2beece6cf96fdffa8739144dfc1c897f4/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b825a3534d6a2810aed9c53873b8a58562bd28afc95506643ec4cc095bdda1a0", size = 4936741, upload-time = "2025-02-22T17:58:21.768Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d3/9f5ed5a8703dd3b1349f4ff53b03eb4b2589cb0034186cdf8a562a97653c/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842a06192c4d6748aa63df3966b8685630ce1d2f1cdfbe54f95177c2db7436ad", size = 4219026, upload-time = "2025-02-22T17:58:23.999Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ca/9788d4ad663f6841825f89013414ac28a483bb031417ccf6e5f087065139/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ece78105348c482bbcc1c7504c2067e8baf8ec64600aea40c293880995fb39c", size = 4805613, upload-time = "2025-02-22T17:58:25.732Z" }, + { url = "https://files.pythonhosted.org/packages/f8/a3/2702d69e47ef26a75c1f8fbf2cfe9e280da45945501998082644f98f1411/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c099c16aa3d224d3b0c6950eabbbf58154f04612522511c3d83a0e97cd689eed", size = 4645177, upload-time = "2025-02-22T17:58:27.448Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8a/c452f47cc9cabdcd694681ca2c8326ea3887cbf481678266e67de334d984/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb9746cdb5c8ddbbcf952bad67e07f4c46722de072cf6cfd69d8fb67d296156c", size = 4775536, upload-time = "2025-02-22T17:58:29.366Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1d/fa6f86bf856019b0f48cdc92497afe632e1176d1d12773d5a77971de0096/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4beb0fc66c7924edcf6f842682554910d93376e31d527fa3d055ee24326bd84f", size = 4826617, upload-time = "2025-02-22T17:58:31.099Z" }, + { url = "https://files.pythonhosted.org/packages/6e/5c/8d85a5295ea236d85213aced33560ff93f8224dd7830d80e6bb37b5488d9/psqlpy-0.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:40e530d71441af61b791723bbf4a198b0da4e95f59d261e67074790564b629e5", size = 4826660, upload-time = "2025-02-22T17:58:32.861Z" }, + { url = "https://files.pythonhosted.org/packages/d3/dd/d6181320adb9271bb8559c1588cf6c956592dd19876bf09937f8b647e5c6/psqlpy-0.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a74926fa272acc2889f510317894307c2dda7702feb8195a159b564603d0c74c", size = 4946588, upload-time = "2025-02-22T17:58:34.363Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0c/9fa61aec2daf03e257fe314a2db0671828e1b397b028473b190fac921067/psqlpy-0.9.3-cp312-cp312-win32.whl", hash = "sha256:2b125d06a0c2718b5cf3b9c866ea9bf19764f51c2aa054919534e4767f43b1f8", size = 3293165, upload-time = "2025-02-22T17:58:36.726Z" }, + { url = "https://files.pythonhosted.org/packages/0a/7c/49717e45df23318bf1ebc6775ad4755e5b2ca7d920aaaeed514900a9fe65/psqlpy-0.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:613facca51bbf0682d863989e7368222e8040b3ce5f5b0ae3ce30d9df4e44d60", size = 3700904, upload-time = "2025-02-22T17:58:39.067Z" }, + { url = "https://files.pythonhosted.org/packages/4d/70/491f46e652492b22a8038082eae8821c3f74febba3d89eb72efbaa50e41c/psqlpy-0.9.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9c7b371f5bc3e4e60e7f0b34db5c8ec82c6aee3e967f6916251895fc0123015b", size = 4225496, upload-time = "2025-02-22T17:58:40.629Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e2/83d29c062876383ad016897ecec2d8b67ca36fe3d37f5c25367e83c9a9db/psqlpy-0.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8546854232368d26eb2c7eba64df2765a4b4698d1465a9c20e6af0b61f495558", size = 4438780, upload-time = "2025-02-22T17:58:42.356Z" }, + { url = "https://files.pythonhosted.org/packages/19/6a/4f520027cf6474f20e45a9292c9e80e297763c82ffb47cc4f9176d286865/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5e83ede139b7c650b5be3019de769db5bab44e72c3365604719222ca9c0825d", size = 4935733, upload-time = "2025-02-22T17:58:43.861Z" }, + { url = "https://files.pythonhosted.org/packages/84/4d/44165581b4bc0eb7cda0b35da1a72681c38cb67506e18b244e5bd8373d9f/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5441f83b707f698c23b9c498845caabf523248adda1276be4efc58474991ba88", size = 4217304, upload-time = "2025-02-22T17:58:47.466Z" }, + { url = "https://files.pythonhosted.org/packages/51/0b/357b9f0e303f6378cb5a03b58c5d0be31d219b013f5a670c5fec82ca3fc5/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9070b7a767aa3ad6d16a6b4008b3590e576296d1ef810f11fbf7ad317ca902e", size = 4804254, upload-time = "2025-02-22T17:58:52.052Z" }, + { url = "https://files.pythonhosted.org/packages/e7/da/3721d5457d64584d521219328210a216790b7a911710864a9260bd2760c2/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2452e0c1b5fa1f4d4b0c73daf277de0785e2a4aaa7d75282b100b2d1758a7677", size = 4644033, upload-time = "2025-02-22T17:58:54.563Z" }, + { url = "https://files.pythonhosted.org/packages/44/fc/1170684ea74be268d2b27ae7e69517c29f6bd5bafb192bb7f76615d3fa79/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:231f57d6129358bdd828f1a24667c727ac9cd07ae374b76ab9d860bc9778be36", size = 4774739, upload-time = "2025-02-22T17:58:56.761Z" }, + { url = "https://files.pythonhosted.org/packages/4d/bb/cd369c0d7b9a022b07740167f1d7eae33ccac1a239e10b21306ca6ebc99e/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9d258b4af8593fafd02ec00dd594f0de7cb9c5a6d59bb30c0883bb314046bf4", size = 4826125, upload-time = "2025-02-22T17:58:58.824Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ff/6bba939bab5e6b7b42aa2b3f8eedb46f7c9d5e5c21e008c856986d594255/psqlpy-0.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a45f42936faa2839b72d8ba6f31c7f22490cf5211a5acfe507655b22110df6e", size = 4826300, upload-time = "2025-02-22T17:59:01.393Z" }, + { url = "https://files.pythonhosted.org/packages/94/2f/2702b621b8d68683b14d954f5ff2a7a65904a9ae8ea1b62278a1d81cdd84/psqlpy-0.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81f2c9f7f94388d5977e28ab00522ddccd1b880e9f382e350207a80a6c2b790f", size = 4944879, upload-time = "2025-02-22T17:59:02.903Z" }, + { url = "https://files.pythonhosted.org/packages/46/97/b6dacbe274cbf95419af1c8c6c5f06a0290a22a66b4202cbc493db97d127/psqlpy-0.9.3-cp313-cp313-win32.whl", hash = "sha256:9126f5e942c2a8ed1aefa8a662a2865f7aaf293a7610911fd4a07200c133a27a", size = 3292642, upload-time = "2025-02-22T17:59:04.528Z" }, + { url = "https://files.pythonhosted.org/packages/ea/55/aaadda7cbdfdbef9f880b57fb25d3cb641e01a71fbd20d76f59a5eddab78/psqlpy-0.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:e438732440dbba845b1f2fcec426cc8a70461d31e81b330efe5ab4e5a83ead52", size = 3700554, upload-time = "2025-02-22T17:59:06.16Z" }, + { url = "https://files.pythonhosted.org/packages/ae/4d/3395a1a83e4501f9928c83fbfdc88f643158a3224d76d06f6eca837c61a7/psqlpy-0.9.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:583f93e6dcdc5f0c6a9259ed7da686c5a888f10ac8546cdd7e4cacfac5826700", size = 4240939, upload-time = "2025-02-22T17:59:07.697Z" }, + { url = "https://files.pythonhosted.org/packages/d4/46/610c514db36e83e1f5f9e3f309d30795eff8ef7cba45bc223bea98811fa4/psqlpy-0.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fc690c4b56b5aa3242518309167c78820621fd6b3284951c65d7426218be3f6", size = 4479396, upload-time = "2025-02-22T17:59:10.265Z" }, + { url = "https://files.pythonhosted.org/packages/0d/36/fe06b173bee1bc09aac918c4759071773d433c04c943a7d161de1c93c87f/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1395fcfdb294d75ee9044b1da60fcaaca3d01c62cfa338f3c18ecd097e0bd738", size = 4937303, upload-time = "2025-02-22T17:59:11.964Z" }, + { url = "https://files.pythonhosted.org/packages/c8/91/a2187176a1799c2b5d409f6d4fc39c40c2abfd3dfb2d08435c2956a86539/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:033e41fecdfe3b4dee6050d4002c5d619b9325bef4167cc497d644c093ee87f4", size = 4210807, upload-time = "2025-02-22T17:59:13.691Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d7/313638aee4d3f73c4c07bf37a232d83348c37c251f609881796ee6324267/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fadb57a391db8ac1b172a2f3882796e8f77ef2e01795db9fe96870b3d434116", size = 4807024, upload-time = "2025-02-22T17:59:15.269Z" }, + { url = "https://files.pythonhosted.org/packages/01/09/64469aa84e596d8c08210ff6e86d7aafb75eedb7ffae12daa75519eb9f97/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7cb7714554cf08e4eaea8fd547dddb65a32927db4c37afd0fbe9a941d839743", size = 4653704, upload-time = "2025-02-22T17:59:17.655Z" }, + { url = "https://files.pythonhosted.org/packages/e6/47/28eb3014eff4642be833abe1c5c745cd31efd63ef5706528901e9efad820/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ddbcd8438cc439862e05e03f4cf364f76dc51d918fe405878c1acfab1848112c", size = 4789815, upload-time = "2025-02-22T17:59:19.301Z" }, + { url = "https://files.pythonhosted.org/packages/17/7c/509f51dfae6b4fd4282d2589199ab9a895bb3984bf27244231566d5f8cad/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd086508cf11e3c390f5d6ed638a39e3d2b4186e53e33ffe6af9b37981ef615", size = 4826656, upload-time = "2025-02-22T17:59:20.865Z" }, + { url = "https://files.pythonhosted.org/packages/b5/79/bb9725575368f46570b646b45da22ef943e97b32e336a485ac169906c1d1/psqlpy-0.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:35aa277d6585ed14936e6c1e4de677564959e379485272906c88090cc5e635dd", size = 4860622, upload-time = "2025-02-22T17:59:22.595Z" }, + { url = "https://files.pythonhosted.org/packages/d3/69/3d80d7286b116734fa8c256b711a0a9554d31df82f7f33cd52e7772ba77b/psqlpy-0.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:81a25ef924322a15a53ee6c36dd38c3d609d05c96f3cf500af33cd929cbe30a1", size = 4980015, upload-time = "2025-02-22T17:59:25.203Z" }, + { url = "https://files.pythonhosted.org/packages/6c/09/b9c0f007c6686193a8f6362980c20c1b33e35cf7bac061071a2a84370e7c/psqlpy-0.9.3-cp39-cp39-win32.whl", hash = "sha256:fa1cbd09536576b22e7aa5e312cf802d4e7da2438c48064bf6886028e8977bec", size = 3311353, upload-time = "2025-02-22T17:59:26.953Z" }, + { url = "https://files.pythonhosted.org/packages/2a/78/181d4f7fbb9f77dce11513b50406ae65484fb5e933143a8c038d73f0a549/psqlpy-0.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:ca15a64cbd4de84c7b9a34f388c70dded46316fac8af851c2f1ba51a755f378f", size = 3722931, upload-time = "2025-02-22T17:59:28.527Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b0/e5e9c3006523bf9a32d1b3506bb2dfc109101d1d8e9d28badba64af9ff38/psqlpy-0.9.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:8c4a6035ebfba0744b15a5c9a3668b2166393619bfb882a189468966ec45f7f0", size = 4236200, upload-time = "2025-02-22T17:59:30.257Z" }, + { url = "https://files.pythonhosted.org/packages/97/23/af1bbbe53c04c029a45dd4c65bb19434c152f4c314d2362f5913ecf09c4d/psqlpy-0.9.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:681dee1d030873f08e55b154c8907a2062f0f6e4b10646411f5ce94028eb0642", size = 4474528, upload-time = "2025-02-22T17:59:31.858Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2a/60cad4acd6be95d0df233f13ac810fb357347f2d224eb2d70471df6c7353/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e26ed13c864b21542eab15f1dfccf02e40fae046076d9c48b3ff062f8406053b", size = 4937463, upload-time = "2025-02-22T17:59:34.338Z" }, + { url = "https://files.pythonhosted.org/packages/fa/45/ba6e10effa92090ed508988dad48d776f466aa2cbc94c7a16b5f14d75e1e/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1baa0200bcdacc9f61efbd273074395bfc7f32b7f7a30fcebb260ae175545914", size = 4210011, upload-time = "2025-02-22T17:59:36.162Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fe/cd176b3a342b45d2f10ad24b109db7a069b437f411302b27eaea77cf0b28/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:925677b1c2ea70addbcb28b86ddc826b77a8107ec489e2d191fb74074ea423b2", size = 4806658, upload-time = "2025-02-22T17:59:37.796Z" }, + { url = "https://files.pythonhosted.org/packages/59/8f/1898a03913f9b697d1b8ae02b3d435a5f05f60e81be5a91934e51044e310/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2c01d44e04f2e9fc7de1c3a8692f38fa22d0a354ce51888b91d8653cae4e0a3", size = 4656552, upload-time = "2025-02-22T17:59:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/60/4d/b67e4b9ffd963850107befa435e8b38b8e7d4f393ee15964c73706c67b13/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b89fb5906bffa757f76c1ef46ec48e3ec3488d484d95d9bc57503b30107e3041", size = 4788063, upload-time = "2025-02-22T17:59:41.458Z" }, + { url = "https://files.pythonhosted.org/packages/25/36/ea1a770563db9105624d0ce73d1b16a80d82d9d278383f9b4633b97ea9ec/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c193eeca5dbceb770332197cc77a6e5e6ead210c34c4fff1d8cb8675e42e1f6", size = 4827112, upload-time = "2025-02-22T17:59:43.265Z" }, + { url = "https://files.pythonhosted.org/packages/94/fe/248438003e8fcd3ba261da0de09b19a679f34c1b0d633222eef4c826729b/psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:eab75d64e3b27a52bcbee690e8651a3b0dbaeef3028a19afad3a848ccb1b2951", size = 4860284, upload-time = "2025-02-22T17:59:45.795Z" }, + { url = "https://files.pythonhosted.org/packages/7f/43/70111a42df62bf3d1b4053192cd0a3e55f18c2297f8c2732b6baae4b9703/psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:a4f77af73b77bd73285efc0576a3ac087ee0aca39821371ea16d8e2bf9a16c90", size = 4980559, upload-time = "2025-02-22T17:59:48.6Z" }, + { url = "https://files.pythonhosted.org/packages/c7/95/7089fd34c80e948d7f544c73f2ff1a0c20938024f61323e31a71bd85fe21/psqlpy-0.9.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d7d4c6fcc343e0c0238e767caccb534d08b42d234d96e35aa5ce55d195f81281", size = 4237481, upload-time = "2025-02-22T17:59:51.062Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ce/5819a1f1e8f69639789b523d227ce07b989b1fc565fed2e3efb3efc67dc2/psqlpy-0.9.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d0220fa8127db04433c2be2a55da1042e4581531a36692c45668c3484bda437", size = 4474728, upload-time = "2025-02-22T17:59:52.753Z" }, + { url = "https://files.pythonhosted.org/packages/2c/55/daeab10685010204bfb18246fbdab892eeb0a0db94de5bfb3cabd524344b/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbdd68fa7f61e00d7f14f010cd4a7f242935cb9df560181bb947fde75c8c1af5", size = 4938916, upload-time = "2025-02-22T17:59:54.796Z" }, + { url = "https://files.pythonhosted.org/packages/1d/35/2feb538ee0fa6d3e248727501b911dd99f20c58e65fd03c22d0d047bf7a5/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c1e3c82aeec4c58328c723ef0755c2f02e2d30874ce850e0d7505db8bd90397", size = 4211573, upload-time = "2025-02-22T17:59:56.568Z" }, + { url = "https://files.pythonhosted.org/packages/dd/4e/588b6c548363dab19bb58d808760f785058cef0af7649c16c80ddaad2eea/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c936f35fa793b421b116aa37040291ff5a33fc54e7f636e7ae946ec987070a94", size = 4809847, upload-time = "2025-02-22T17:59:58.865Z" }, + { url = "https://files.pythonhosted.org/packages/d6/cc/2aef99aef78b0df24e43790786c0507bb63f4e6fa3e338fbdccb4e1b70e7/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28ee25f791ccbad04269e22a21a79d52609d65298fe9b5300b8fe00fef42bab6", size = 4658403, upload-time = "2025-02-22T18:00:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/67/33/9d5094a57caddd9ffe2eb176e3e30a367312929323daa333bbc4dd11e3a4/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3a1d90bb1da48649852e636612bb12fa0e3ec07f230446836195054598f0de4", size = 4789341, upload-time = "2025-02-22T18:00:05.161Z" }, + { url = "https://files.pythonhosted.org/packages/52/5a/3506b0b6731b7e3f6a818fb3dcef7b2f8685254790a7a4bb0a1c9c2ac3cc/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a764bf80ce4e9d284bc11e255aff836894ee55e540c1be20120e67f855d8b07c", size = 4829845, upload-time = "2025-02-22T18:00:06.958Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fd/cd5e2929cfe3e357694118638fa227cd9dc6b4717b39590e731d0e3bd2ee/psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7939bfa80b649e650b9b4efe9064936837b14082851f1ad95c24548a105277cd", size = 4862164, upload-time = "2025-02-22T18:00:08.833Z" }, + { url = "https://files.pythonhosted.org/packages/b2/af/e4ca9ccaed96d27c1c753b6d4f16264f0f7a2c752249ea25074f636a6734/psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:23496ed36433c88308f7e85f36091b203bb6c8c655ded639ce1626a1c8319afe", size = 4981643, upload-time = "2025-02-22T18:00:10.595Z" }, ] [[package]] name = "psycopg" -version = "3.2.6" +version = "3.2.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/67/97/eea08f74f1c6dd2a02ee81b4ebfe5b558beb468ebbd11031adbf58d31be0/psycopg-3.2.6.tar.gz", hash = "sha256:16fa094efa2698f260f2af74f3710f781e4a6f226efe9d1fd0c37f384639ed8a", size = 156322 } +sdist = { url = "https://files.pythonhosted.org/packages/fe/16/ca27b38762a630b70243f51eb6a728f903a17cddc4961626fa540577aba6/psycopg-3.2.7.tar.gz", hash = "sha256:9afa609c7ebf139827a38c0bf61be9c024a3ed743f56443de9d38e1efc260bf3", size = 157238, upload-time = "2025-04-30T13:05:22.867Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/7d/0ba52deff71f65df8ec8038adad86ba09368c945424a9bd8145d679a2c6a/psycopg-3.2.6-py3-none-any.whl", hash = "sha256:f3ff5488525890abb0566c429146add66b329e20d6d4835662b920cbbf90ac58", size = 199077 }, + { url = "https://files.pythonhosted.org/packages/cb/eb/6e32d259437125a17b0bc2624e06c86149c618501da1dcbc8539b2684f6f/psycopg-3.2.7-py3-none-any.whl", hash = "sha256:d39747d2d5b9658b69fa462ad21d31f1ba4a5722ad1d0cb952552bc0b4125451", size = 200028, upload-time = "2025-04-30T12:59:32.435Z" }, ] [package.optional-dependencies] @@ -2274,64 +2280,64 @@ pool = [ [[package]] name = "psycopg-binary" -version = "3.2.6" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/7b/48afdcb14bf828c4006f573845fbbd98df701bff9043fbb0b8caab261b6f/psycopg_binary-3.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1b639acb3e24243c23f75700bf6e3af7b76da92523ec7c3196a13aaf0b578453", size = 3868985 }, - { url = "https://files.pythonhosted.org/packages/de/45/9e777c61ef3ac5e7fb42618afbd9f41464c1c396ec85c79c48086ace437a/psycopg_binary-3.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1b5c359173726b38d7acbb9f73270f269591d8031d099c1a70dd3f3d22b0e8a8", size = 3938244 }, - { url = "https://files.pythonhosted.org/packages/d6/93/e48962aca19af1f3d2cb0c2ff890ca305c51d1759a2e89c90a527228cf1d/psycopg_binary-3.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3434efe7c00f505f4c1e531519dac6c701df738ba7a1328eac81118d80019132", size = 4523096 }, - { url = "https://files.pythonhosted.org/packages/fe/52/21f4a9bb7123e07e06a712338eb6cc5794a23a56813deb4a8cd3de8ec91c/psycopg_binary-3.2.6-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bca8d9643191b13193940bbf84d51ac5a747e965c230177258fb02b8043fb7a", size = 4329659 }, - { url = "https://files.pythonhosted.org/packages/9e/72/8da1c98b4e0d4c3649f037101b70ae52e4f821597919dabc72c889e60ca9/psycopg_binary-3.2.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55fa40f11d37e6e5149a282a5fd7e0734ce55c623673bfba638480914fd1414c", size = 4575359 }, - { url = "https://files.pythonhosted.org/packages/83/5a/a85c98a5b2b3f771d7478ac0081b48749d4c07ce41d51f89f592f87cfbeb/psycopg_binary-3.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0690ac1061c655b1bcbe9284d07bf5276bc9c0d788a6c74aaf3b042e64984b83", size = 4287138 }, - { url = "https://files.pythonhosted.org/packages/b0/c3/0abafd3f300e5ff952dd9b3be95b4e2527ae1e2ea7fd7a7421e6bc1c0e37/psycopg_binary-3.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e9a4a9967ff650d2821d5fad6bec7b15f4c2072603e9fa3f89a39f351ade1fd3", size = 3872142 }, - { url = "https://files.pythonhosted.org/packages/0f/16/029aa400c4b7f4b7042307d8a854768463a65326d061ad2145f7b3989ca5/psycopg_binary-3.2.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d6f2894cc7aee8a15fe591e8536911d9c015cb404432cf7bdac2797e54cb2ba8", size = 3340033 }, - { url = "https://files.pythonhosted.org/packages/cd/a1/28e86b832d696ba5fd79c4d704b8ca46b827428f7ea063063ca280a678a4/psycopg_binary-3.2.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:05560c81312d7c2bee95a9860cd25198677f2320fb4a3527bc04e8cae7fcfb64", size = 3438823 }, - { url = "https://files.pythonhosted.org/packages/93/31/73546c999725b397bb7e7fd55f83a9c78787c6fe7fe457e4179d19a115dc/psycopg_binary-3.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4269cd23a485d6dd6eb6b10841c94551a53091cf0b1b6d5247a6a341f53f0d95", size = 3464031 }, - { url = "https://files.pythonhosted.org/packages/85/38/957bd4bdde976c9a38d61896bf9d2c8f5752b98d8f4d879a7902588a8583/psycopg_binary-3.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:7942f35a6f314608720116bcd9de240110ceadffd2ac5c34f68f74a31e52e46a", size = 2792159 }, - { url = "https://files.pythonhosted.org/packages/5a/71/5bfa1ffc4d59f0454b114ce0d017eca269b079ca2753a96302c2117067c7/psycopg_binary-3.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7afe181f6b3eb714362e9b6a2dc2a589bff60471a1d8639fd231a4e426e01523", size = 3876608 }, - { url = "https://files.pythonhosted.org/packages/7e/07/1724d842b876af7bef442f0853d6cbf951264229414e4d0a57b8e3787847/psycopg_binary-3.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34bb0fceba0773dc0bfb53224bb2c0b19dc97ea0a997a223615484cf02cae55c", size = 3942785 }, - { url = "https://files.pythonhosted.org/packages/09/51/a251a356f10c7947bcc2285ebf1541e1c2d851b8db20eb8f29ed3a5974bf/psycopg_binary-3.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54120122d2779dcd307f49e1f921d757fe5dacdced27deab37f277eef0c52a5b", size = 4519448 }, - { url = "https://files.pythonhosted.org/packages/6e/cf/0c92ab1270664a1341e52f5794ecc636b1f4ac67bf1743075091795151f8/psycopg_binary-3.2.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:816aa556f63b2303e66ba6c8888a8b3f3e6e4e47049ec7a4d62c84ac60b091ca", size = 4324382 }, - { url = "https://files.pythonhosted.org/packages/bf/2b/6921bd4a57fe19d4618798a8a8648e1a516c92563c37b2073639fffac5d5/psycopg_binary-3.2.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d19a0ba351eda9a59babf8c7c9d89c7bbc5b26bf096bc349b096bd0dd2482088", size = 4578720 }, - { url = "https://files.pythonhosted.org/packages/5c/30/1034d164e2be09f650a86eccc93625e51568e307c855bf6f94759c298303/psycopg_binary-3.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6e197e01290ef818a092c877025fc28096adbb6d0743e313491a21aab31bd96", size = 4281871 }, - { url = "https://files.pythonhosted.org/packages/c4/d0/67fdf0174c334a9a85a9672590d7da83e85d9cedfc35f473a557e310a1ca/psycopg_binary-3.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:274794b4b29ef426e09086404446b61a146f5e756da71366c5a6d57abec31f7d", size = 3870582 }, - { url = "https://files.pythonhosted.org/packages/9f/4e/3a4fd2d1fd715b11e7287023edde916e1174b58b37873c531f782a49803b/psycopg_binary-3.2.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:69845bdc0db519e1dfc27932cd3d5b1ecb3f72950af52a1987508ab0b52b3b55", size = 3334464 }, - { url = "https://files.pythonhosted.org/packages/4a/22/90a8032276fa5b215ce26cefb44abafa8fb09de396c6dc6f62a5e53fe2ad/psycopg_binary-3.2.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:66c3bed2caf0d1cabcb9365064de183b5209a7cbeaa131e79e68f350c9c963c2", size = 3431945 }, - { url = "https://files.pythonhosted.org/packages/e7/b0/e547e9a851ab19c79869c1d84a533e225d284e70c222720fed4529fcda60/psycopg_binary-3.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e3ae3201fe85c7f901349a2cf52f02ceca4cb97a5e2e2ac8b8a1c9a6eb747bed", size = 3463278 }, - { url = "https://files.pythonhosted.org/packages/e7/ce/e555bd8dd6fce8b34bbc3856125600f0842c85a8364702ebe0dc39372087/psycopg_binary-3.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:58f443b4df2adb59937c96775fadf4967f93d952fbcc82394446985faec11041", size = 2795094 }, - { url = "https://files.pythonhosted.org/packages/a3/c7/220b1273f0befb2cd9fe83d379b3484ae029a88798a90bc0d36f10bea5df/psycopg_binary-3.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f27a46ff0497e882e8c0286e8833c785b4d1a80f23e1bf606f4c90e5f9f3ce75", size = 3857986 }, - { url = "https://files.pythonhosted.org/packages/8a/d8/30176532826cf87c608a6f79dd668bf9aff0cdf8eb80209eddf4c5aa7229/psycopg_binary-3.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b30ee4821ded7de48b8048b14952512588e7c5477b0a5965221e1798afba61a1", size = 3940060 }, - { url = "https://files.pythonhosted.org/packages/54/7c/fa7cd1f057f33f7ae483d6bc5a03ec6eff111f8aa5c678d9aaef92705247/psycopg_binary-3.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e57edf3b1f5427f39660225b01f8e7b97f5cfab132092f014bf1638bc85d81d2", size = 4499082 }, - { url = "https://files.pythonhosted.org/packages/b8/81/1606966f6146187c273993ea6f88f2151b26741df8f4e01349a625983be9/psycopg_binary-3.2.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c5172ce3e4ae7a4fd450070210f801e2ce6bc0f11d1208d29268deb0cda34de", size = 4307509 }, - { url = "https://files.pythonhosted.org/packages/69/ad/01c87aab17a4b89128b8036800d11ab296c7c2c623940cc7e6f2668f375a/psycopg_binary-3.2.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcfab3804c43571a6615e559cdc4c4115785d258a4dd71a721be033f5f5f378d", size = 4547813 }, - { url = "https://files.pythonhosted.org/packages/65/30/f93a193846ee738ffe5d2a4837e7ddeb7279707af81d088cee96cae853a0/psycopg_binary-3.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fa1c920cce16f1205f37b20c685c58b9656b170b8b4c93629100d342d0d118e", size = 4259847 }, - { url = "https://files.pythonhosted.org/packages/8e/73/65c4ae71be86675a62154407c92af4b917146f9ff3baaf0e4166c0734aeb/psycopg_binary-3.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2e118d818101c1608c6b5ba52a6c977614d8f05aa89467501172ba4d10588e11", size = 3846550 }, - { url = "https://files.pythonhosted.org/packages/53/cc/a24626cac3f208c776bb22e15e9a5e483aa81145221e6427e50381f40811/psycopg_binary-3.2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:763319a8bfeca77d31512da71f5a33459b9568a7621c481c3828c62f9c38f351", size = 3320269 }, - { url = "https://files.pythonhosted.org/packages/55/e6/68c76fb9d6c53d5e4170a0c9216c7aa6c2903808f626d84d002b47a16931/psycopg_binary-3.2.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:2fbc05819560389dbece046966bc88e0f2ea77673497e274c4293b8b4c1d0703", size = 3399365 }, - { url = "https://files.pythonhosted.org/packages/b4/2c/55b140f5a2c582dae42ef38502c45ef69c938274242a40bd04c143081029/psycopg_binary-3.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a57f99bb953b4bd6f32d0a9844664e7f6ca5ead9ba40e96635be3cd30794813", size = 3438908 }, - { url = "https://files.pythonhosted.org/packages/ae/f6/589c95cceccee2ab408b6b2e16f1ed6db4536fb24f2f5c9ce568cf43270c/psycopg_binary-3.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:5de6809e19a465dcb9c269675bded46a135f2d600cd99f0735afbb21ddad2af4", size = 2782886 }, - { url = "https://files.pythonhosted.org/packages/bf/32/3d06c478fd3070ac25a49c2e8ca46b6d76b0048fa9fa255b99ee32f32312/psycopg_binary-3.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54af3fbf871baa2eb19df96fd7dc0cbd88e628a692063c3d1ab5cdd00aa04322", size = 3852672 }, - { url = "https://files.pythonhosted.org/packages/34/97/e581030e279500ede3096adb510f0e6071874b97cfc047a9a87b7d71fc77/psycopg_binary-3.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ad5da1e4636776c21eaeacdec42f25fa4612631a12f25cd9ab34ddf2c346ffb9", size = 3936562 }, - { url = "https://files.pythonhosted.org/packages/74/b6/6a8df4cb23c3d327403a83406c06c9140f311cb56c4e4d720ee7abf6fddc/psycopg_binary-3.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7956b9ea56f79cd86eddcfbfc65ae2af1e4fe7932fa400755005d903c709370", size = 4499167 }, - { url = "https://files.pythonhosted.org/packages/e4/5b/950eafef61e5e0b8ddb5afc5b6b279756411aa4bf70a346a6f091ad679bb/psycopg_binary-3.2.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e2efb763188008cf2914820dcb9fb23c10fe2be0d2c97ef0fac7cec28e281d8", size = 4311651 }, - { url = "https://files.pythonhosted.org/packages/72/b9/b366c49afc854c26b3053d4d35376046eea9aebdc48ded18ea249ea1f80c/psycopg_binary-3.2.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b3aab3451679f1e7932270e950259ed48c3b79390022d3f660491c0e65e4838", size = 4547852 }, - { url = "https://files.pythonhosted.org/packages/ab/d4/0e047360e2ea387dc7171ca017ffcee5214a0762f74b9dd982035f2e52fb/psycopg_binary-3.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:849a370ac4e125f55f2ad37f928e588291a67ccf91fa33d0b1e042bb3ee1f986", size = 4261725 }, - { url = "https://files.pythonhosted.org/packages/e3/ea/a1b969804250183900959ebe845d86be7fed2cbd9be58f64cd0fc24b2892/psycopg_binary-3.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:566d4ace928419d91f1eb3227fc9ef7b41cf0ad22e93dd2c3368d693cf144408", size = 3850073 }, - { url = "https://files.pythonhosted.org/packages/e5/71/ec2907342f0675092b76aea74365b56f38d960c4c635984dcfe25d8178c8/psycopg_binary-3.2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f1981f13b10de2f11cfa2f99a8738b35b3f0a0f3075861446894a8d3042430c0", size = 3320323 }, - { url = "https://files.pythonhosted.org/packages/d7/d7/0d2cb4b42f231e2efe8ea1799ce917973d47486212a2c4d33cd331e7ac28/psycopg_binary-3.2.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:36f598300b55b3c983ae8df06473ad27333d2fd9f3e2cfdb913b3a5aaa3a8bcf", size = 3402335 }, - { url = "https://files.pythonhosted.org/packages/66/92/7050c372f78e53eba14695cec6c3a91b2d9ca56feaf0bfe95fe90facf730/psycopg_binary-3.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0f4699fa5fe1fffb0d6b2d14b31fd8c29b7ea7375f89d5989f002aaf21728b21", size = 3440442 }, - { url = "https://files.pythonhosted.org/packages/5f/4c/bebcaf754189283b2f3d457822a3d9b233d08ff50973d8f1e8d51f4d35ed/psycopg_binary-3.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:afe697b8b0071f497c5d4c0f41df9e038391534f5614f7fb3a8c1ca32d66e860", size = 2783465 }, - { url = "https://files.pythonhosted.org/packages/be/ac/5023320c46e0d233faff6cd2d902a60d6c09034f136e7cc0876463a97d50/psycopg_binary-3.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:260c43c329e668606388cee78ec0dab083a25c2c6e6f9cf74a130fd5a27b0f87", size = 3870121 }, - { url = "https://files.pythonhosted.org/packages/8d/2d/63cdd41112c954582d6bb8905970abe5e5a69b53d6dd2a38fc7ec624a6b4/psycopg_binary-3.2.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9870e51fad4684dbdec057fa757d65e61cb2acb16236836e9360044c2a1ec880", size = 3939150 }, - { url = "https://files.pythonhosted.org/packages/a8/c6/0a0fe3b5506d30d597c82b16b8c1e023393a10701109e917c4cb529ccc71/psycopg_binary-3.2.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030e9c3082a931e972b029b3cef085784a3bf7f8e18367ae50d5b809aa6e1d87", size = 4525092 }, - { url = "https://files.pythonhosted.org/packages/0d/66/66c3c05a0535c022b1b8af501aec05161084e6a4ab44edebd99ff82de976/psycopg_binary-3.2.6-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60c9ed291fbd5e777c2c630dcfd10b7a87d68512b0757d5e7406d9c4895a82a", size = 4330350 }, - { url = "https://files.pythonhosted.org/packages/90/f3/15ce9800b54c50ff01af1c39d0a727083bb3640067a54b58631ca6666b24/psycopg_binary-3.2.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e0f4a17a9c376c195e403b4826c18f325bd28f425231d36d1036258bf893e23", size = 4577917 }, - { url = "https://files.pythonhosted.org/packages/a0/aa/ffe622452a43376193d3d1e63b479e0f90ce9732c91366c05a16ce49e513/psycopg_binary-3.2.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac46da609624b16d961f604b3cbc3233ef43211ef1456a188f8c427109c9c3e1", size = 4286328 }, - { url = "https://files.pythonhosted.org/packages/bf/bf/53da912ba8ace3136318718112c5db85bf0ed4f079f92849536a78384875/psycopg_binary-3.2.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e77949b8e7014b85cee0bf6e9e041bcae7719b2693ebf59236368fb0b2a08814", size = 3874534 }, - { url = "https://files.pythonhosted.org/packages/1a/b5/e659e96ffc6846d3f90c4af785c84898e625f974c7f67255688addda6167/psycopg_binary-3.2.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:532322d9ef6e7d178a4f344970b017110633bcc3dc1c3403efcef55aad612517", size = 3339634 }, - { url = "https://files.pythonhosted.org/packages/9b/d6/92858290a8d710a27caf1b92183f4fa2ef3b99c9b6959fc73fd9639b8412/psycopg_binary-3.2.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:880c5fd76dcb50bdcc8f87359e5a6c7eb416697cc9aa02854c91223bd999c045", size = 3437930 }, - { url = "https://files.pythonhosted.org/packages/f7/a5/60b5a6519f58b2deca261d2e4566bce4beeeb30f6e7c3f72e4d8f204dcf6/psycopg_binary-3.2.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3c0cddc7458b8416d77cd8829d0192466502f31d1fb853d58613cf13ac64f41c", size = 3464810 }, - { url = "https://files.pythonhosted.org/packages/27/b6/e48cafe90e46b82b1393276ce6d92ddb7650c39aba8aa0256affbaa94c36/psycopg_binary-3.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:ea158665676f42b19585dfe948071d3c5f28276f84a97522fb2e82c1d9194563", size = 2793902 }, +version = "3.2.7" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/54/e0f97118c57b4c7a94bf5564b22ae1c69bfb348d9a3f1424c1fec24d3ff3/psycopg_binary-3.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:17ab2b4c2722138b7a6eb42d139ad8e5fed792574c1069f27abf8f8ebb0d7f75", size = 3869223, upload-time = "2025-04-30T12:59:37.739Z" }, + { url = "https://files.pythonhosted.org/packages/b9/7c/d261cd9468c2ac2cdc9db5f78ea5768284180d1215b056325e0275237ebb/psycopg_binary-3.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:063f5a56ccab2b9eef58f55437cff78c59c5562ebb5f7453ecd480f038b045dc", size = 3938929, upload-time = "2025-04-30T12:59:43.491Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ce/1f2f6dd4c4e97d01d1029bc20a15e7a2eaf067ee853b17bc18f90c4a7415/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70632c9687731c8d0c9c72fbb73893e82ba4a2cdc8ffdd4c5bbcef51cc9c6b16", size = 4523155, upload-time = "2025-04-30T12:59:48.508Z" }, + { url = "https://files.pythonhosted.org/packages/b4/54/3b33dda4f56cb98ec8801a947372bb9e683e02cbc4f07d2ca06ce596408d/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebca1fd4b59523e3127eba7257bf764e80cddd9444b7f0d2870210ffc80ac688", size = 4329574, upload-time = "2025-04-30T12:59:54.468Z" }, + { url = "https://files.pythonhosted.org/packages/19/6b/57fa8324cfbc1760c568f4f41388ca5e0c9723d942186eb2ce65c2c84e07/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f2371822bc0b35ad735298964d531f95e59cfa2d31b87408f7d63ae78173279c", size = 4577282, upload-time = "2025-04-30T13:00:01.814Z" }, + { url = "https://files.pythonhosted.org/packages/30/54/2214b379b5de17efb79b11daabae5f7327699368447b955f349d0ecd0c00/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b1cd14d99d358483c665355eebb650f5e76f2d41c942fe6d0836b0fe76fbf0", size = 4287541, upload-time = "2025-04-30T13:00:07.623Z" }, + { url = "https://files.pythonhosted.org/packages/36/bb/a30e8733e6e11b22c2cd79c3b3978ee2efa0cf1d9873a46b2beaacbbf2dc/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:82369aa7cfbff19d65182698ee542af75d90c27284201d718f54f7b52480f730", size = 3777464, upload-time = "2025-04-30T13:00:12.947Z" }, + { url = "https://files.pythonhosted.org/packages/50/8c/ba1fe5bce097e8407f747c290f07cd75ecc13be1cd54f362678d8dd46ee3/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:00ba447b23daaacd9391c6a7ee0781e0860af72d0742c4d261df07940d601e29", size = 3336810, upload-time = "2025-04-30T13:00:16.96Z" }, + { url = "https://files.pythonhosted.org/packages/a9/90/18792d169c3daa7edebd7e88b09a6ca8781d766288581f344a3cecfff2b5/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0ccff5f988345dad22146f165e4395b37b9f4f3e3dd42eedad6627e791a8c8b4", size = 3438709, upload-time = "2025-04-30T13:00:21.124Z" }, + { url = "https://files.pythonhosted.org/packages/15/1c/0abde469359ba2129a7a1e4418f7665836ea7b11d8cb5b4b61c97768a473/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82e9ee9943da44a08f737d80c9b3878f9d4916a947cf182cd183f81e825cc41d", size = 3496758, upload-time = "2025-04-30T13:00:26.064Z" }, + { url = "https://files.pythonhosted.org/packages/2f/fe/8e3f19e477da87e29cd938f2ca6b95d24df56bec507c8bbc90493f1aba6b/psycopg_binary-3.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:26b1b7e39fa5139f99cb02a186dfa447c41f7e55c0aebb5f2da6ddf5b6ec5b32", size = 2936268, upload-time = "2025-04-30T13:00:32.129Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ef/ff0578e07d696bc0465c6c97399af416563944ffdbafb23f033bc6f38359/psycopg_binary-3.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d001950bcabb725e003609073b83678962e9308e0b194a5227d6758ba8d46e0", size = 3876901, upload-time = "2025-04-30T13:00:38.307Z" }, + { url = "https://files.pythonhosted.org/packages/e7/66/6095832dcd76bcee4f442bcb862f56d6be2c200304ee67497d892b1a4874/psycopg_binary-3.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57acabe70587b65471b9f42593ec9bb17d317118e0dbe92d7173f0a75939150a", size = 3943982, upload-time = "2025-04-30T13:00:42.476Z" }, + { url = "https://files.pythonhosted.org/packages/7f/d0/c2aa1de7700661b5c4a0c698db42b6c34f69f2fa0c51afa44c053421c55c/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93f3937f293a30310501204bf0833704283675a8819a395bea8e352a5abaee84", size = 4520576, upload-time = "2025-04-30T13:00:47.063Z" }, + { url = "https://files.pythonhosted.org/packages/90/b5/976fcd95b03056812a53bdf58bcdd361eac71163619d51160ce82fc118ce/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72a3fb7cd7da15157bf63792db7346dfe2a07e3bc6ff702c7e8a76719e6efca0", size = 4325008, upload-time = "2025-04-30T13:00:54.407Z" }, + { url = "https://files.pythonhosted.org/packages/15/25/363bce348face3f08ef9515f0c0d39e53202b90c37c54367e6606d926957/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0350ba9a14295b266fba83d5a691511bf4ceb5df863973b525230fd15fd483f2", size = 4581129, upload-time = "2025-04-30T13:01:00.164Z" }, + { url = "https://files.pythonhosted.org/packages/cd/f8/72b081b9691f15d05a4edbc0707de8b9e698e3e0583a69dd0e471cf7ec4f/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de12375a49e70a6ac52431aa92b9c2e4ca01fea4fa872b4cd31e19028e3095d7", size = 4282727, upload-time = "2025-04-30T13:01:04.316Z" }, + { url = "https://files.pythonhosted.org/packages/97/ac/bbd215f0df248cb1f6bec1d580f4b699ec7a1fd82434d651a1a5283fa676/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33bb035e6f9b4911291472d6b5386b283fc835b97d2b1dc57f2ff82f777cb9f2", size = 3775842, upload-time = "2025-04-30T13:01:07.913Z" }, + { url = "https://files.pythonhosted.org/packages/9b/42/f51e420919611ddde52741b5489ab268876887e3577667fce681946681b4/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ed59c833678b55932f78aa60e85691b40fd7d2058ad60ca369fc4f908218c688", size = 3331510, upload-time = "2025-04-30T13:01:11.517Z" }, + { url = "https://files.pythonhosted.org/packages/13/a2/0a6f6b5e6a7cadd7789801f6f93460dd9ef44007205d6e2ffb24e758fb78/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b404c1a091dd034254694ae56111c69f07d54419c5436366c5b3af2aac9dce04", size = 3435475, upload-time = "2025-04-30T13:01:16.446Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c2/115d546c3f570792433aadf248602b8ab3efa27c2cbc8173c15ffd1af1e2/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:25a3527a26b7589434a3eb52ad32b1f67e1af034cb17bd36a77344896d54b403", size = 3495896, upload-time = "2025-04-30T13:01:21.958Z" }, + { url = "https://files.pythonhosted.org/packages/da/b9/7a15a72a38f99054de1e517285ceb1cb3a62d5d404557961c6f8efa9065b/psycopg_binary-3.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:f5a2ebd0772c059e521b70a826a11b962fcba465b001fd655ca6aba10dc9432d", size = 2939079, upload-time = "2025-04-30T13:01:27.446Z" }, + { url = "https://files.pythonhosted.org/packages/c9/f6/00d303cbf258fd0053d8cacbd92c3f73dffe34ba2050cf4d25d677ec70fe/psycopg_binary-3.2.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:76e55ec30b3947b921f267795ffd2f433c65fc8a41adc4939fd9ccfb0f5b0322", size = 3858585, upload-time = "2025-04-30T13:01:34.348Z" }, + { url = "https://files.pythonhosted.org/packages/dc/01/56c5ec8ca159de1e4f6e2bb4663c3f985162ccdc810e29e19727c2849ddd/psycopg_binary-3.2.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff4c97a04eeb11d54d4c8ca22459e2cca9a423e7f397c29ae311c6e7c784d49", size = 3940735, upload-time = "2025-04-30T13:01:38.396Z" }, + { url = "https://files.pythonhosted.org/packages/0d/46/92855fbe7150cdc0e5949430d457d07b89d187f884a611858e2b46166e39/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d1c97a7c57e83b55172b585702744cd6bdad37c7a18cabdf55ba1e5a66ce476", size = 4499775, upload-time = "2025-04-30T13:01:43.129Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5a/e0bd9e2fc450e972cfdb028d7e6bf1b2eaeb36b8110078e54040472927e7/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b394542a8b0706102a86c7006978848cf1748f4191e0e0e32b1f814b63ae7d68", size = 4308131, upload-time = "2025-04-30T13:01:49.44Z" }, + { url = "https://files.pythonhosted.org/packages/fe/45/14935e3b022cd31666a05861c72fc3ce1b2ccf622771dd9f5220fa2a5149/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6a10440bc02ed3a0ac1cb2d61e117273ce20e3d103061452acc7ed2c9a89e53", size = 4548217, upload-time = "2025-04-30T13:01:55.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/57/1bcabf46f45c88fe767b24e3a9a4d15f1bd78195e17179b85975c62f42dc/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8eee57667fdd8a1cd8c4c2dc7350914267baf4d699690d44e439df9ae9148e7a", size = 4260744, upload-time = "2025-04-30T13:02:03.076Z" }, + { url = "https://files.pythonhosted.org/packages/19/b0/c2edd72c05a8a4b73712f4705de137107042466f96ad054454e0b35cf5fe/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fd35ddbbfbe3cbe00a2b578defc7365e5e047e4fa9b803659bd4e8c3962069e7", size = 3752306, upload-time = "2025-04-30T13:02:08.378Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ef/4303e6b5cb48f3802fe85c779af6feb34b8fac371396284118f894cc39d8/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e7f1d2dc575b00d951317b788a2244fdfcdd1503221ebc7e479220f6e3414aa4", size = 3316919, upload-time = "2025-04-30T13:02:15.345Z" }, + { url = "https://files.pythonhosted.org/packages/fe/71/91ae71a868861c93f9d2ab0e38f0f63dda8b0e1db913a739c04df932f658/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:359b2056e1203010c0044c12a3f933d522c613d7ee280d84be3643458f416796", size = 3405507, upload-time = "2025-04-30T13:02:22.115Z" }, + { url = "https://files.pythonhosted.org/packages/37/dd/dc44e86396939625a704d2fdfb2ed081d24034fed33e657ca1e01363e6cc/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:532b5c8a9ec70173812fbba26bbd5cf57c0f1c680907d637ddbb1be15dbf89d7", size = 3472779, upload-time = "2025-04-30T13:02:28.149Z" }, + { url = "https://files.pythonhosted.org/packages/4a/b0/d305977dfb5fbd9194d7a77b6edde8ff6054376b3d10595855de4269dfec/psycopg_binary-3.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:47e9d09b4f898eaf46cd2b7433f9e6faa935246a9d8983b4f88f0a46809abbd2", size = 2926878, upload-time = "2025-04-30T13:02:32.248Z" }, + { url = "https://files.pythonhosted.org/packages/3f/c8/590d8ca19e66810f7943a5c325f18bd29be472d2fa1bbee93905623a26fa/psycopg_binary-3.2.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3b280862c623616e0ced03602c98b44f51ab8cdaaad31f6b3523a2a68b2f92a4", size = 3853314, upload-time = "2025-04-30T13:02:37.469Z" }, + { url = "https://files.pythonhosted.org/packages/38/18/af7db2c61d50f86f38ba6d7e5b6aff4d138b9238f5cb9d6c57b49e80eb21/psycopg_binary-3.2.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:add318f12dc2be4d8a817e70c38cfd23a2af80ff6f871089e63012b62bf96f00", size = 3937308, upload-time = "2025-04-30T13:02:45.584Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a4/d483311c22d4ae7a31dd643926309c480a54252ecb27a8fba654dba1753b/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03994806e62e795b1b286c60bb5d23e1cc3982b06192e87ec4dff0a0f7c528e2", size = 4500116, upload-time = "2025-04-30T13:02:51.525Z" }, + { url = "https://files.pythonhosted.org/packages/82/03/7047b4247a578fe296510e10c1ebcdf42009f4c022f924f697a6145a1062/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77709be5dc45828ca06d9d87fa7b065720fb87b1aa3e72d44177562f1df50ad2", size = 4312005, upload-time = "2025-04-30T13:02:55.806Z" }, + { url = "https://files.pythonhosted.org/packages/5b/a4/28dec7beddea4a93089dfa4692124a057914f0e6f5164712f9ae7ee97a8b/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d959a17ac2f1ff87a191786f66ae452791fbe73cee7375f2dafd2696e605a9", size = 4548230, upload-time = "2025-04-30T13:03:00.174Z" }, + { url = "https://files.pythonhosted.org/packages/51/ac/4b7e86fec44c428f27f28d742c13568419cc3d2a2b4dcc1be9b266ee9123/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:239e24fa33c6213320da0aee72d541e4780adb21753fc692337043c235118cf1", size = 4262584, upload-time = "2025-04-30T13:03:05.347Z" }, + { url = "https://files.pythonhosted.org/packages/05/b6/814805218644a0865c529221cc3413adba25b0d80a7db5f3e50e25c539ce/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d31c0523e0294e008d9031f2f2034a010f043ae8c7af0589d614b0bf6ed6e6aa", size = 3755762, upload-time = "2025-04-30T13:03:10.112Z" }, + { url = "https://files.pythonhosted.org/packages/58/b8/efa94ca4aff949324a52bdf62a9518939375af3048b7d025620d0e385ef8/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a15c88f1695c8dc8b90625931fe86909c74f7770bad7312999ee6babb0143dcc", size = 3319679, upload-time = "2025-04-30T13:03:15.068Z" }, + { url = "https://files.pythonhosted.org/packages/0e/3f/dd3a912abaa4ff2816e9a1e90c775f33315278f7d01621e874f5b5e83ada/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3c02790afcc6d82d1b9d886d9323f955c5c998693966c4c1e6d0ff9a96276a1e", size = 3409378, upload-time = "2025-04-30T13:03:20.422Z" }, + { url = "https://files.pythonhosted.org/packages/35/44/1ee04f0eae2dd9a75cf519792e95a00d5c7eb91b8ec341e2660fd0b4a033/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1d2288a7f1d0dec1ccce50b4470751acb563689048752fdbf7a4a804df3a0e0d", size = 3475892, upload-time = "2025-04-30T13:03:25.686Z" }, + { url = "https://files.pythonhosted.org/packages/11/1e/5133e346f0138f13d04e38f4b3976dc92ab4a1d72fc18f1199552c0bde3c/psycopg_binary-3.2.7-cp313-cp313-win_amd64.whl", hash = "sha256:c3781beaffb33fce17d8f137b003ebd930a7148eab2a1f60628e86c3d67884ea", size = 2927499, upload-time = "2025-04-30T13:03:31.398Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a4/43ed70fc7ca36a17baac3d812b7c9b5b163708331235fa4b5ea7ab4bb1b4/psycopg_binary-3.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:519d7d8f35c5392599a5f5ceb9ebaa50881024fb6ecd32ea55436c8e3cda27cc", size = 3870416, upload-time = "2025-04-30T13:04:22.813Z" }, + { url = "https://files.pythonhosted.org/packages/09/7e/fd89b01a076f179987d0d6ec597e3c01d33736f9106b1345a7e1251d540e/psycopg_binary-3.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef399143d63bd67febe92b923dc6bd56bc8a9c3581a68bc8982eed75963ad169", size = 3939850, upload-time = "2025-04-30T13:04:27.137Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/2612cbf05c2865129db4873159c7d1ae9cc5735da146c7d4cb89a45e7df5/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a34757170706c67be94b248db458d3602269828a067a84bdc536869d35fed5", size = 4523348, upload-time = "2025-04-30T13:04:32.338Z" }, + { url = "https://files.pythonhosted.org/packages/09/4f/cabb879a3c7c4e719c16da757f7c3f1d0e01e08a7d965008ba24559bb358/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05a7265e80b362b93af2dbea0cd8828e6cbbb6daea97f2b0b4f29e61bd34b2e3", size = 4331305, upload-time = "2025-04-30T13:04:39.88Z" }, + { url = "https://files.pythonhosted.org/packages/73/fa/e34932141000129db0a19f385f175f6e471af66cdf92edaf3147fc3d63e2/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2a9aa6ddfd6a8fb5756498ccb7a3a4f9cd87906d9e8ac36b69e116b7104b891", size = 4579977, upload-time = "2025-04-30T13:04:47.795Z" }, + { url = "https://files.pythonhosted.org/packages/c1/11/8b6ec2ed9503334d6753034dca2c5f4c47bc0051309003b8ac5c65daff7a/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69310b8dc1277556711f6818b75a92581ae6c3cd2ca3c9c0798caf15976a8562", size = 4287106, upload-time = "2025-04-30T13:04:55.152Z" }, + { url = "https://files.pythonhosted.org/packages/b8/e6/60a67000de1245a7274033a58092266ab4cdca6c35b28f4a1742b703c6c2/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:73349f876b7288200c576c5c14b29c5f3266fb30598c3723dc57cfe05adf3121", size = 3777676, upload-time = "2025-04-30T13:05:00.871Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f7/1edf068549ba02efa8e2ca09722aa3426b4904fbed5a199344d4b357f749/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a8d3c8df6eb652e8140b24941b4da8bd07bfa7564101e9dee496a28683f7c2f8", size = 3337577, upload-time = "2025-04-30T13:05:07.828Z" }, + { url = "https://files.pythonhosted.org/packages/19/df/d16f79797d64cc6a0846add5ea85a56272a3e0c815ab444397a96494001c/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2321b6edfb4ca38a3446d5e88abe9ce78c04fc616d05a598ffe7cc5e2535c1fc", size = 3439812, upload-time = "2025-04-30T13:05:13.598Z" }, + { url = "https://files.pythonhosted.org/packages/1f/a7/7cfb9f9cd23097354bd721569480cf05840f51bdf6840051f54aca901143/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2cf25feb92dceb5739dd029a047664a02f5df25a5e086d577cae810daf6a302a", size = 3498268, upload-time = "2025-04-30T13:05:17.47Z" }, + { url = "https://files.pythonhosted.org/packages/c3/1d/91b47bea94fbe66a6d69a53f2ede2dfa1c2daa90dd6a6fa9d39251b841f0/psycopg_binary-3.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:ac0b823a0b199d36e0570d5d2a1154ae767073907496a2e436a236e388fc0c97", size = 2938028, upload-time = "2025-04-30T13:05:20.976Z" }, ] [[package]] @@ -2341,67 +2347,80 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/13/1e7850bb2c69a63267c3dbf37387d3f71a00fd0e2fa55c5db14d64ba1af4/psycopg_pool-3.2.6.tar.gz", hash = "sha256:0f92a7817719517212fbfe2fd58b8c35c1850cdd2a80d36b581ba2085d9148e5", size = 29770 } +sdist = { url = "https://files.pythonhosted.org/packages/cf/13/1e7850bb2c69a63267c3dbf37387d3f71a00fd0e2fa55c5db14d64ba1af4/psycopg_pool-3.2.6.tar.gz", hash = "sha256:0f92a7817719517212fbfe2fd58b8c35c1850cdd2a80d36b581ba2085d9148e5", size = 29770, upload-time = "2025-02-26T12:03:47.129Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/fd/4feb52a55c1a4bd748f2acaed1903ab54a723c47f6d0242780f4d97104d4/psycopg_pool-3.2.6-py3-none-any.whl", hash = "sha256:5887318a9f6af906d041a0b1dc1c60f8f0dda8340c2572b74e10907b51ed5da7", size = 38252 }, + { url = "https://files.pythonhosted.org/packages/47/fd/4feb52a55c1a4bd748f2acaed1903ab54a723c47f6d0242780f4d97104d4/psycopg_pool-3.2.6-py3-none-any.whl", hash = "sha256:5887318a9f6af906d041a0b1dc1c60f8f0dda8340c2572b74e10907b51ed5da7", size = 38252, upload-time = "2025-02-26T12:03:45.073Z" }, ] [[package]] name = "pyarrow" -version = "19.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7f/09/a9046344212690f0632b9c709f9bf18506522feb333c894d0de81d62341a/pyarrow-19.0.1.tar.gz", hash = "sha256:3bf266b485df66a400f282ac0b6d1b500b9d2ae73314a153dbe97d6d5cc8a99e", size = 1129437 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/01/b23b514d86b839956238d3f8ef206fd2728eee87ff1b8ce150a5678d9721/pyarrow-19.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:fc28912a2dc924dddc2087679cc8b7263accc71b9ff025a1362b004711661a69", size = 30688914 }, - { url = "https://files.pythonhosted.org/packages/c6/68/218ff7cf4a0652a933e5f2ed11274f724dd43b9813cb18dd72c0a35226a2/pyarrow-19.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:fca15aabbe9b8355800d923cc2e82c8ef514af321e18b437c3d782aa884eaeec", size = 32102866 }, - { url = "https://files.pythonhosted.org/packages/98/01/c295050d183014f4a2eb796d7d2bbfa04b6cccde7258bb68aacf6f18779b/pyarrow-19.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad76aef7f5f7e4a757fddcdcf010a8290958f09e3470ea458c80d26f4316ae89", size = 41147682 }, - { url = "https://files.pythonhosted.org/packages/40/17/a6c3db0b5f3678f33bbb552d2acbc16def67f89a72955b67b0109af23eb0/pyarrow-19.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d03c9d6f2a3dffbd62671ca070f13fc527bb1867b4ec2b98c7eeed381d4f389a", size = 42179192 }, - { url = "https://files.pythonhosted.org/packages/cf/75/c7c8e599300d8cebb6cb339014800e1c720c9db2a3fcb66aa64ec84bac72/pyarrow-19.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:65cf9feebab489b19cdfcfe4aa82f62147218558d8d3f0fc1e9dea0ab8e7905a", size = 40517272 }, - { url = "https://files.pythonhosted.org/packages/ef/c9/68ab123ee1528699c4d5055f645ecd1dd68ff93e4699527249d02f55afeb/pyarrow-19.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:41f9706fbe505e0abc10e84bf3a906a1338905cbbcf1177b71486b03e6ea6608", size = 42069036 }, - { url = "https://files.pythonhosted.org/packages/54/e3/d5cfd7654084e6c0d9c3ce949e5d9e0ccad569ae1e2d5a68a3ec03b2be89/pyarrow-19.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6cb2335a411b713fdf1e82a752162f72d4a7b5dbc588e32aa18383318b05866", size = 25277951 }, - { url = "https://files.pythonhosted.org/packages/a0/55/f1a8d838ec07fe3ca53edbe76f782df7b9aafd4417080eebf0b42aab0c52/pyarrow-19.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:cc55d71898ea30dc95900297d191377caba257612f384207fe9f8293b5850f90", size = 30713987 }, - { url = "https://files.pythonhosted.org/packages/13/12/428861540bb54c98a140ae858a11f71d041ef9e501e6b7eb965ca7909505/pyarrow-19.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:7a544ec12de66769612b2d6988c36adc96fb9767ecc8ee0a4d270b10b1c51e00", size = 32135613 }, - { url = "https://files.pythonhosted.org/packages/2f/8a/23d7cc5ae2066c6c736bce1db8ea7bc9ac3ef97ac7e1c1667706c764d2d9/pyarrow-19.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0148bb4fc158bfbc3d6dfe5001d93ebeed253793fff4435167f6ce1dc4bddeae", size = 41149147 }, - { url = "https://files.pythonhosted.org/packages/a2/7a/845d151bb81a892dfb368bf11db584cf8b216963ccce40a5cf50a2492a18/pyarrow-19.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f24faab6ed18f216a37870d8c5623f9c044566d75ec586ef884e13a02a9d62c5", size = 42178045 }, - { url = "https://files.pythonhosted.org/packages/a7/31/e7282d79a70816132cf6cae7e378adfccce9ae10352d21c2fecf9d9756dd/pyarrow-19.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:4982f8e2b7afd6dae8608d70ba5bd91699077323f812a0448d8b7abdff6cb5d3", size = 40532998 }, - { url = "https://files.pythonhosted.org/packages/b8/82/20f3c290d6e705e2ee9c1fa1d5a0869365ee477e1788073d8b548da8b64c/pyarrow-19.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:49a3aecb62c1be1d822f8bf629226d4a96418228a42f5b40835c1f10d42e4db6", size = 42084055 }, - { url = "https://files.pythonhosted.org/packages/ff/77/e62aebd343238863f2c9f080ad2ef6ace25c919c6ab383436b5b81cbeef7/pyarrow-19.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:008a4009efdb4ea3d2e18f05cd31f9d43c388aad29c636112c2966605ba33466", size = 25283133 }, - { url = "https://files.pythonhosted.org/packages/78/b4/94e828704b050e723f67d67c3535cf7076c7432cd4cf046e4bb3b96a9c9d/pyarrow-19.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:80b2ad2b193e7d19e81008a96e313fbd53157945c7be9ac65f44f8937a55427b", size = 30670749 }, - { url = "https://files.pythonhosted.org/packages/7e/3b/4692965e04bb1df55e2c314c4296f1eb12b4f3052d4cf43d29e076aedf66/pyarrow-19.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:ee8dec072569f43835932a3b10c55973593abc00936c202707a4ad06af7cb294", size = 32128007 }, - { url = "https://files.pythonhosted.org/packages/22/f7/2239af706252c6582a5635c35caa17cb4d401cd74a87821ef702e3888957/pyarrow-19.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d5d1ec7ec5324b98887bdc006f4d2ce534e10e60f7ad995e7875ffa0ff9cb14", size = 41144566 }, - { url = "https://files.pythonhosted.org/packages/fb/e3/c9661b2b2849cfefddd9fd65b64e093594b231b472de08ff658f76c732b2/pyarrow-19.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ad4c0eb4e2a9aeb990af6c09e6fa0b195c8c0e7b272ecc8d4d2b6574809d34", size = 42202991 }, - { url = "https://files.pythonhosted.org/packages/fe/4f/a2c0ed309167ef436674782dfee4a124570ba64299c551e38d3fdaf0a17b/pyarrow-19.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d383591f3dcbe545f6cc62daaef9c7cdfe0dff0fb9e1c8121101cabe9098cfa6", size = 40507986 }, - { url = "https://files.pythonhosted.org/packages/27/2e/29bb28a7102a6f71026a9d70d1d61df926887e36ec797f2e6acfd2dd3867/pyarrow-19.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b4c4156a625f1e35d6c0b2132635a237708944eb41df5fbe7d50f20d20c17832", size = 42087026 }, - { url = "https://files.pythonhosted.org/packages/16/33/2a67c0f783251106aeeee516f4806161e7b481f7d744d0d643d2f30230a5/pyarrow-19.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:5bd1618ae5e5476b7654c7b55a6364ae87686d4724538c24185bbb2952679960", size = 25250108 }, - { url = "https://files.pythonhosted.org/packages/2b/8d/275c58d4b00781bd36579501a259eacc5c6dfb369be4ddeb672ceb551d2d/pyarrow-19.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e45274b20e524ae5c39d7fc1ca2aa923aab494776d2d4b316b49ec7572ca324c", size = 30653552 }, - { url = "https://files.pythonhosted.org/packages/a0/9e/e6aca5cc4ef0c7aec5f8db93feb0bde08dbad8c56b9014216205d271101b/pyarrow-19.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:d9dedeaf19097a143ed6da37f04f4051aba353c95ef507764d344229b2b740ae", size = 32103413 }, - { url = "https://files.pythonhosted.org/packages/6a/fa/a7033f66e5d4f1308c7eb0dfcd2ccd70f881724eb6fd1776657fdf65458f/pyarrow-19.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ebfb5171bb5f4a52319344ebbbecc731af3f021e49318c74f33d520d31ae0c4", size = 41134869 }, - { url = "https://files.pythonhosted.org/packages/2d/92/34d2569be8e7abdc9d145c98dc410db0071ac579b92ebc30da35f500d630/pyarrow-19.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a21d39fbdb948857f67eacb5bbaaf36802de044ec36fbef7a1c8f0dd3a4ab2", size = 42192626 }, - { url = "https://files.pythonhosted.org/packages/0a/1f/80c617b1084fc833804dc3309aa9d8daacd46f9ec8d736df733f15aebe2c/pyarrow-19.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:99bc1bec6d234359743b01e70d4310d0ab240c3d6b0da7e2a93663b0158616f6", size = 40496708 }, - { url = "https://files.pythonhosted.org/packages/e6/90/83698fcecf939a611c8d9a78e38e7fed7792dcc4317e29e72cf8135526fb/pyarrow-19.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1b93ef2c93e77c442c979b0d596af45e4665d8b96da598db145b0fec014b9136", size = 42075728 }, - { url = "https://files.pythonhosted.org/packages/40/49/2325f5c9e7a1c125c01ba0c509d400b152c972a47958768e4e35e04d13d8/pyarrow-19.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:d9d46e06846a41ba906ab25302cf0fd522f81aa2a85a71021826f34639ad31ef", size = 25242568 }, - { url = "https://files.pythonhosted.org/packages/3f/72/135088d995a759d4d916ec4824cb19e066585b4909ebad4ab196177aa825/pyarrow-19.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c0fe3dbbf054a00d1f162fda94ce236a899ca01123a798c561ba307ca38af5f0", size = 30702371 }, - { url = "https://files.pythonhosted.org/packages/2e/01/00beeebd33d6bac701f20816a29d2018eba463616bbc07397fdf99ac4ce3/pyarrow-19.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:96606c3ba57944d128e8a8399da4812f56c7f61de8c647e3470b417f795d0ef9", size = 32116046 }, - { url = "https://files.pythonhosted.org/packages/1f/c9/23b1ea718dfe967cbd986d16cf2a31fe59d015874258baae16d7ea0ccabc/pyarrow-19.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f04d49a6b64cf24719c080b3c2029a3a5b16417fd5fd7c4041f94233af732f3", size = 41091183 }, - { url = "https://files.pythonhosted.org/packages/3a/d4/b4a3aa781a2c715520aa8ab4fe2e7fa49d33a1d4e71c8fc6ab7b5de7a3f8/pyarrow-19.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a9137cf7e1640dce4c190551ee69d478f7121b5c6f323553b319cac936395f6", size = 42171896 }, - { url = "https://files.pythonhosted.org/packages/23/1b/716d4cd5a3cbc387c6e6745d2704c4b46654ba2668260d25c402626c5ddb/pyarrow-19.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:7c1bca1897c28013db5e4c83944a2ab53231f541b9e0c3f4791206d0c0de389a", size = 40464851 }, - { url = "https://files.pythonhosted.org/packages/ed/bd/54907846383dcc7ee28772d7e646f6c34276a17da740002a5cefe90f04f7/pyarrow-19.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:58d9397b2e273ef76264b45531e9d552d8ec8a6688b7390b5be44c02a37aade8", size = 42085744 }, - { url = "https://files.pythonhosted.org/packages/16/26/0ec396ebe98adefaffc0fff8e0dc14c8912e61093226284cf4b76faffd22/pyarrow-19.0.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:b9766a47a9cb56fefe95cb27f535038b5a195707a08bf61b180e642324963b46", size = 30701112 }, - { url = "https://files.pythonhosted.org/packages/ba/10/c35d96686bf7f13e55bb87f06fe06e7d95533c271ef7f9a5a76e26b16fc2/pyarrow-19.0.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:6c5941c1aac89a6c2f2b16cd64fe76bcdb94b2b1e99ca6459de4e6f07638d755", size = 32117180 }, - { url = "https://files.pythonhosted.org/packages/8c/0d/81881a55302b6847ea2ea187517faa039c219d80b55050904e354c2eddde/pyarrow-19.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd44d66093a239358d07c42a91eebf5015aa54fccba959db899f932218ac9cc8", size = 41161334 }, - { url = "https://files.pythonhosted.org/packages/af/17/ea60a07ec6f6bb0740f11715e0d22ab8fdfcc94bc729832321f498370d75/pyarrow-19.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:335d170e050bcc7da867a1ed8ffb8b44c57aaa6e0843b156a501298657b1e972", size = 42190375 }, - { url = "https://files.pythonhosted.org/packages/f2/87/4ef05a088b18082cde4950bdfca752dd31effb3ec201b8026e4816d0f3fa/pyarrow-19.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:1c7556165bd38cf0cd992df2636f8bcdd2d4b26916c6b7e646101aff3c16f76f", size = 40530649 }, - { url = "https://files.pythonhosted.org/packages/59/1e/9fb9a66a64eae4ff332a8f149d803d8c6c556714803d20d54ed2e9524a3b/pyarrow-19.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:699799f9c80bebcf1da0983ba86d7f289c5a2a5c04b945e2f2bcf7e874a91911", size = 42081576 }, - { url = "https://files.pythonhosted.org/packages/1b/ee/c110d8da8bdde8e832ccf1ff90be747cb684874e2dc8acf26840058b0c32/pyarrow-19.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8464c9fbe6d94a7fe1599e7e8965f350fd233532868232ab2596a71586c5a429", size = 25465593 }, +version = "20.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/ee/a7810cb9f3d6e9238e61d312076a9859bf3668fd21c69744de9532383912/pyarrow-20.0.0.tar.gz", hash = "sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1", size = 1125187, upload-time = "2025-04-27T12:34:23.264Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/23/77094eb8ee0dbe88441689cb6afc40ac312a1e15d3a7acc0586999518222/pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7", size = 30832591, upload-time = "2025-04-27T12:27:27.89Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d5/48cc573aff00d62913701d9fac478518f693b30c25f2c157550b0b2565cb/pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4", size = 32273686, upload-time = "2025-04-27T12:27:36.816Z" }, + { url = "https://files.pythonhosted.org/packages/37/df/4099b69a432b5cb412dd18adc2629975544d656df3d7fda6d73c5dba935d/pyarrow-20.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6415a0d0174487456ddc9beaead703d0ded5966129fa4fd3114d76b5d1c5ceae", size = 41337051, upload-time = "2025-04-27T12:27:44.4Z" }, + { url = "https://files.pythonhosted.org/packages/4c/27/99922a9ac1c9226f346e3a1e15e63dee6f623ed757ff2893f9d6994a69d3/pyarrow-20.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15aa1b3b2587e74328a730457068dc6c89e6dcbf438d4369f572af9d320a25ee", size = 42404659, upload-time = "2025-04-27T12:27:51.715Z" }, + { url = "https://files.pythonhosted.org/packages/21/d1/71d91b2791b829c9e98f1e0d85be66ed93aff399f80abb99678511847eaa/pyarrow-20.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5605919fbe67a7948c1f03b9f3727d82846c053cd2ce9303ace791855923fd20", size = 40695446, upload-time = "2025-04-27T12:27:59.643Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ca/ae10fba419a6e94329707487835ec721f5a95f3ac9168500bcf7aa3813c7/pyarrow-20.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a5704f29a74b81673d266e5ec1fe376f060627c2e42c5c7651288ed4b0db29e9", size = 42278528, upload-time = "2025-04-27T12:28:07.297Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a6/aba40a2bf01b5d00cf9cd16d427a5da1fad0fb69b514ce8c8292ab80e968/pyarrow-20.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:00138f79ee1b5aca81e2bdedb91e3739b987245e11fa3c826f9e57c5d102fb75", size = 42918162, upload-time = "2025-04-27T12:28:15.716Z" }, + { url = "https://files.pythonhosted.org/packages/93/6b/98b39650cd64f32bf2ec6d627a9bd24fcb3e4e6ea1873c5e1ea8a83b1a18/pyarrow-20.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f2d67ac28f57a362f1a2c1e6fa98bfe2f03230f7e15927aecd067433b1e70ce8", size = 44550319, upload-time = "2025-04-27T12:28:27.026Z" }, + { url = "https://files.pythonhosted.org/packages/ab/32/340238be1eb5037e7b5de7e640ee22334417239bc347eadefaf8c373936d/pyarrow-20.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4a8b029a07956b8d7bd742ffca25374dd3f634b35e46cc7a7c3fa4c75b297191", size = 25770759, upload-time = "2025-04-27T12:28:33.702Z" }, + { url = "https://files.pythonhosted.org/packages/47/a2/b7930824181ceadd0c63c1042d01fa4ef63eee233934826a7a2a9af6e463/pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0", size = 30856035, upload-time = "2025-04-27T12:28:40.78Z" }, + { url = "https://files.pythonhosted.org/packages/9b/18/c765770227d7f5bdfa8a69f64b49194352325c66a5c3bb5e332dfd5867d9/pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb", size = 32309552, upload-time = "2025-04-27T12:28:47.051Z" }, + { url = "https://files.pythonhosted.org/packages/44/fb/dfb2dfdd3e488bb14f822d7335653092dde150cffc2da97de6e7500681f9/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232", size = 41334704, upload-time = "2025-04-27T12:28:55.064Z" }, + { url = "https://files.pythonhosted.org/packages/58/0d/08a95878d38808051a953e887332d4a76bc06c6ee04351918ee1155407eb/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f", size = 42399836, upload-time = "2025-04-27T12:29:02.13Z" }, + { url = "https://files.pythonhosted.org/packages/f3/cd/efa271234dfe38f0271561086eedcad7bc0f2ddd1efba423916ff0883684/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab", size = 40711789, upload-time = "2025-04-27T12:29:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/46/1f/7f02009bc7fc8955c391defee5348f510e589a020e4b40ca05edcb847854/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62", size = 42301124, upload-time = "2025-04-27T12:29:17.187Z" }, + { url = "https://files.pythonhosted.org/packages/4f/92/692c562be4504c262089e86757a9048739fe1acb4024f92d39615e7bab3f/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c", size = 42916060, upload-time = "2025-04-27T12:29:24.253Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ec/9f5c7e7c828d8e0a3c7ef50ee62eca38a7de2fa6eb1b8fa43685c9414fef/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3", size = 44547640, upload-time = "2025-04-27T12:29:32.782Z" }, + { url = "https://files.pythonhosted.org/packages/54/96/46613131b4727f10fd2ffa6d0d6f02efcc09a0e7374eff3b5771548aa95b/pyarrow-20.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc", size = 25781491, upload-time = "2025-04-27T12:29:38.464Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d6/0c10e0d54f6c13eb464ee9b67a68b8c71bcf2f67760ef5b6fbcddd2ab05f/pyarrow-20.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba", size = 30815067, upload-time = "2025-04-27T12:29:44.384Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e2/04e9874abe4094a06fd8b0cbb0f1312d8dd7d707f144c2ec1e5e8f452ffa/pyarrow-20.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781", size = 32297128, upload-time = "2025-04-27T12:29:52.038Z" }, + { url = "https://files.pythonhosted.org/packages/31/fd/c565e5dcc906a3b471a83273039cb75cb79aad4a2d4a12f76cc5ae90a4b8/pyarrow-20.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199", size = 41334890, upload-time = "2025-04-27T12:29:59.452Z" }, + { url = "https://files.pythonhosted.org/packages/af/a9/3bdd799e2c9b20c1ea6dc6fa8e83f29480a97711cf806e823f808c2316ac/pyarrow-20.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd", size = 42421775, upload-time = "2025-04-27T12:30:06.875Z" }, + { url = "https://files.pythonhosted.org/packages/10/f7/da98ccd86354c332f593218101ae56568d5dcedb460e342000bd89c49cc1/pyarrow-20.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28", size = 40687231, upload-time = "2025-04-27T12:30:13.954Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1b/2168d6050e52ff1e6cefc61d600723870bf569cbf41d13db939c8cf97a16/pyarrow-20.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8", size = 42295639, upload-time = "2025-04-27T12:30:21.949Z" }, + { url = "https://files.pythonhosted.org/packages/b2/66/2d976c0c7158fd25591c8ca55aee026e6d5745a021915a1835578707feb3/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e", size = 42908549, upload-time = "2025-04-27T12:30:29.551Z" }, + { url = "https://files.pythonhosted.org/packages/31/a9/dfb999c2fc6911201dcbf348247f9cc382a8990f9ab45c12eabfd7243a38/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a", size = 44557216, upload-time = "2025-04-27T12:30:36.977Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8e/9adee63dfa3911be2382fb4d92e4b2e7d82610f9d9f668493bebaa2af50f/pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b", size = 25660496, upload-time = "2025-04-27T12:30:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/9b/aa/daa413b81446d20d4dad2944110dcf4cf4f4179ef7f685dd5a6d7570dc8e/pyarrow-20.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:a15532e77b94c61efadde86d10957950392999503b3616b2ffcef7621a002893", size = 30798501, upload-time = "2025-04-27T12:30:48.351Z" }, + { url = "https://files.pythonhosted.org/packages/ff/75/2303d1caa410925de902d32ac215dc80a7ce7dd8dfe95358c165f2adf107/pyarrow-20.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:dd43f58037443af715f34f1322c782ec463a3c8a94a85fdb2d987ceb5658e061", size = 32277895, upload-time = "2025-04-27T12:30:55.238Z" }, + { url = "https://files.pythonhosted.org/packages/92/41/fe18c7c0b38b20811b73d1bdd54b1fccba0dab0e51d2048878042d84afa8/pyarrow-20.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0d288143a8585806e3cc7c39566407aab646fb9ece164609dac1cfff45f6ae", size = 41327322, upload-time = "2025-04-27T12:31:05.587Z" }, + { url = "https://files.pythonhosted.org/packages/da/ab/7dbf3d11db67c72dbf36ae63dcbc9f30b866c153b3a22ef728523943eee6/pyarrow-20.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6953f0114f8d6f3d905d98e987d0924dabce59c3cda380bdfaa25a6201563b4", size = 42411441, upload-time = "2025-04-27T12:31:15.675Z" }, + { url = "https://files.pythonhosted.org/packages/90/c3/0c7da7b6dac863af75b64e2f827e4742161128c350bfe7955b426484e226/pyarrow-20.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:991f85b48a8a5e839b2128590ce07611fae48a904cae6cab1f089c5955b57eb5", size = 40677027, upload-time = "2025-04-27T12:31:24.631Z" }, + { url = "https://files.pythonhosted.org/packages/be/27/43a47fa0ff9053ab5203bb3faeec435d43c0d8bfa40179bfd076cdbd4e1c/pyarrow-20.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:97c8dc984ed09cb07d618d57d8d4b67a5100a30c3818c2fb0b04599f0da2de7b", size = 42281473, upload-time = "2025-04-27T12:31:31.311Z" }, + { url = "https://files.pythonhosted.org/packages/bc/0b/d56c63b078876da81bbb9ba695a596eabee9b085555ed12bf6eb3b7cab0e/pyarrow-20.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9b71daf534f4745818f96c214dbc1e6124d7daf059167330b610fc69b6f3d3e3", size = 42893897, upload-time = "2025-04-27T12:31:39.406Z" }, + { url = "https://files.pythonhosted.org/packages/92/ac/7d4bd020ba9145f354012838692d48300c1b8fe5634bfda886abcada67ed/pyarrow-20.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8b88758f9303fa5a83d6c90e176714b2fd3852e776fc2d7e42a22dd6c2fb368", size = 44543847, upload-time = "2025-04-27T12:31:45.997Z" }, + { url = "https://files.pythonhosted.org/packages/9d/07/290f4abf9ca702c5df7b47739c1b2c83588641ddfa2cc75e34a301d42e55/pyarrow-20.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:30b3051b7975801c1e1d387e17c588d8ab05ced9b1e14eec57915f79869b5031", size = 25653219, upload-time = "2025-04-27T12:31:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/95/df/720bb17704b10bd69dde086e1400b8eefb8f58df3f8ac9cff6c425bf57f1/pyarrow-20.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:ca151afa4f9b7bc45bcc791eb9a89e90a9eb2772767d0b1e5389609c7d03db63", size = 30853957, upload-time = "2025-04-27T12:31:59.215Z" }, + { url = "https://files.pythonhosted.org/packages/d9/72/0d5f875efc31baef742ba55a00a25213a19ea64d7176e0fe001c5d8b6e9a/pyarrow-20.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:4680f01ecd86e0dd63e39eb5cd59ef9ff24a9d166db328679e36c108dc993d4c", size = 32247972, upload-time = "2025-04-27T12:32:05.369Z" }, + { url = "https://files.pythonhosted.org/packages/d5/bc/e48b4fa544d2eea72f7844180eb77f83f2030b84c8dad860f199f94307ed/pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f4c8534e2ff059765647aa69b75d6543f9fef59e2cd4c6d18015192565d2b70", size = 41256434, upload-time = "2025-04-27T12:32:11.814Z" }, + { url = "https://files.pythonhosted.org/packages/c3/01/974043a29874aa2cf4f87fb07fd108828fc7362300265a2a64a94965e35b/pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e1f8a47f4b4ae4c69c4d702cfbdfe4d41e18e5c7ef6f1bb1c50918c1e81c57b", size = 42353648, upload-time = "2025-04-27T12:32:20.766Z" }, + { url = "https://files.pythonhosted.org/packages/68/95/cc0d3634cde9ca69b0e51cbe830d8915ea32dda2157560dda27ff3b3337b/pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:a1f60dc14658efaa927f8214734f6a01a806d7690be4b3232ba526836d216122", size = 40619853, upload-time = "2025-04-27T12:32:28.1Z" }, + { url = "https://files.pythonhosted.org/packages/29/c2/3ad40e07e96a3e74e7ed7cc8285aadfa84eb848a798c98ec0ad009eb6bcc/pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:204a846dca751428991346976b914d6d2a82ae5b8316a6ed99789ebf976551e6", size = 42241743, upload-time = "2025-04-27T12:32:35.792Z" }, + { url = "https://files.pythonhosted.org/packages/eb/cb/65fa110b483339add6a9bc7b6373614166b14e20375d4daa73483755f830/pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f3b117b922af5e4c6b9a9115825726cac7d8b1421c37c2b5e24fbacc8930612c", size = 42839441, upload-time = "2025-04-27T12:32:46.64Z" }, + { url = "https://files.pythonhosted.org/packages/98/7b/f30b1954589243207d7a0fbc9997401044bf9a033eec78f6cb50da3f304a/pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e724a3fd23ae5b9c010e7be857f4405ed5e679db5c93e66204db1a69f733936a", size = 44503279, upload-time = "2025-04-27T12:32:56.503Z" }, + { url = "https://files.pythonhosted.org/packages/37/40/ad395740cd641869a13bcf60851296c89624662575621968dcfafabaa7f6/pyarrow-20.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:82f1ee5133bd8f49d31be1299dc07f585136679666b502540db854968576faf9", size = 25944982, upload-time = "2025-04-27T12:33:04.72Z" }, + { url = "https://files.pythonhosted.org/packages/10/53/421820fa125138c868729b930d4bc487af2c4b01b1c6104818aab7e98f13/pyarrow-20.0.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:1bcbe471ef3349be7714261dea28fe280db574f9d0f77eeccc195a2d161fd861", size = 30844702, upload-time = "2025-04-27T12:33:12.122Z" }, + { url = "https://files.pythonhosted.org/packages/2e/70/fd75e03312b715e90d928fb91ed8d45c9b0520346e5231b1c69293afd4c7/pyarrow-20.0.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:a18a14baef7d7ae49247e75641fd8bcbb39f44ed49a9fc4ec2f65d5031aa3b96", size = 32287180, upload-time = "2025-04-27T12:33:20.597Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e3/21e5758e46219fdedf5e6c800574dd9d17e962e80014cfe08d6d475be863/pyarrow-20.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb497649e505dc36542d0e68eca1a3c94ecbe9799cb67b578b55f2441a247fbc", size = 41351968, upload-time = "2025-04-27T12:33:28.215Z" }, + { url = "https://files.pythonhosted.org/packages/ac/f5/ed6a4c4b11f9215092a35097a985485bb7d879cb79d93d203494e8604f4e/pyarrow-20.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11529a2283cb1f6271d7c23e4a8f9f8b7fd173f7360776b668e509d712a02eec", size = 42415208, upload-time = "2025-04-27T12:33:37.04Z" }, + { url = "https://files.pythonhosted.org/packages/44/e5/466a63668ba25788ee8d38d55f853a60469ae7ad1cda343db9f3f45e0b0a/pyarrow-20.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fc1499ed3b4b57ee4e090e1cea6eb3584793fe3d1b4297bbf53f09b434991a5", size = 40708556, upload-time = "2025-04-27T12:33:46.483Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d7/4c4d4e4cf6e53e16a519366dfe9223ee4a7a38e6e28c1c0d372b38ba3fe7/pyarrow-20.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:db53390eaf8a4dab4dbd6d93c85c5cf002db24902dbff0ca7d988beb5c9dd15b", size = 42291754, upload-time = "2025-04-27T12:33:55.4Z" }, + { url = "https://files.pythonhosted.org/packages/07/d5/79effb32585b7c18897d3047a2163034f3f9c944d12f7b2fd8df6a2edc70/pyarrow-20.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:851c6a8260ad387caf82d2bbf54759130534723e37083111d4ed481cb253cc0d", size = 42936483, upload-time = "2025-04-27T12:34:03.694Z" }, + { url = "https://files.pythonhosted.org/packages/09/5c/f707603552c058b2e9129732de99a67befb1f13f008cc58856304a62c38b/pyarrow-20.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e22f80b97a271f0a7d9cd07394a7d348f80d3ac63ed7cc38b6d1b696ab3b2619", size = 44558895, upload-time = "2025-04-27T12:34:13.26Z" }, + { url = "https://files.pythonhosted.org/packages/26/cc/1eb6a01c1bbc787f596c270c46bcd2273e35154a84afcb1d0cb4cc72457e/pyarrow-20.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:9965a050048ab02409fb7cbbefeedba04d3d67f2cc899eff505cc084345959ca", size = 25785667, upload-time = "2025-04-27T12:34:19.739Z" }, ] [[package]] name = "pyasn1" version = "0.6.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322 } +sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135 }, + { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, ] [[package]] @@ -2411,23 +2430,23 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyasn1" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892 } +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259 }, + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, ] [[package]] name = "pycparser" version = "2.22" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, ] [[package]] name = "pydantic" -version = "2.11.3" +version = "2.11.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -2435,131 +2454,131 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/10/2e/ca897f093ee6c5f3b0bee123ee4465c50e75431c3d5b6a3b44a47134e891/pydantic-2.11.3.tar.gz", hash = "sha256:7471657138c16adad9322fe3070c0116dd6c3ad8d649300e3cbdfe91f4db4ec3", size = 785513 } +sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/1d/407b29780a289868ed696d1616f4aad49d6388e5a77f567dcd2629dcd7b8/pydantic-2.11.3-py3-none-any.whl", hash = "sha256:a082753436a07f9ba1289c6ffa01cd93db3548776088aa917cc43b63f68fa60f", size = 443591 }, + { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, ] [[package]] name = "pydantic-core" -version = "2.33.1" +version = "2.33.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/17/19/ed6a078a5287aea7922de6841ef4c06157931622c89c2a47940837b5eecd/pydantic_core-2.33.1.tar.gz", hash = "sha256:bcc9c6fdb0ced789245b02b7d6603e17d1563064ddcfc36f046b61c0c05dd9df", size = 434395 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/ea/5f572806ab4d4223d11551af814d243b0e3e02cc6913def4d1fe4a5ca41c/pydantic_core-2.33.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3077cfdb6125cc8dab61b155fdd714663e401f0e6883f9632118ec12cf42df26", size = 2044021 }, - { url = "https://files.pythonhosted.org/packages/8c/d1/f86cc96d2aa80e3881140d16d12ef2b491223f90b28b9a911346c04ac359/pydantic_core-2.33.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ffab8b2908d152e74862d276cf5017c81a2f3719f14e8e3e8d6b83fda863927", size = 1861742 }, - { url = "https://files.pythonhosted.org/packages/37/08/fbd2cd1e9fc735a0df0142fac41c114ad9602d1c004aea340169ae90973b/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5183e4f6a2d468787243ebcd70cf4098c247e60d73fb7d68d5bc1e1beaa0c4db", size = 1910414 }, - { url = "https://files.pythonhosted.org/packages/7f/73/3ac217751decbf8d6cb9443cec9b9eb0130eeada6ae56403e11b486e277e/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:398a38d323f37714023be1e0285765f0a27243a8b1506b7b7de87b647b517e48", size = 1996848 }, - { url = "https://files.pythonhosted.org/packages/9a/f5/5c26b265cdcff2661e2520d2d1e9db72d117ea00eb41e00a76efe68cb009/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3776f0001b43acebfa86f8c64019c043b55cc5a6a2e313d728b5c95b46969", size = 2141055 }, - { url = "https://files.pythonhosted.org/packages/5d/14/a9c3cee817ef2f8347c5ce0713e91867a0dceceefcb2973942855c917379/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c566dd9c5f63d22226409553531f89de0cac55397f2ab8d97d6f06cfce6d947e", size = 2753806 }, - { url = "https://files.pythonhosted.org/packages/f2/68/866ce83a51dd37e7c604ce0050ff6ad26de65a7799df89f4db87dd93d1d6/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d5f3acc81452c56895e90643a625302bd6be351e7010664151cc55b7b97f89", size = 2007777 }, - { url = "https://files.pythonhosted.org/packages/b6/a8/36771f4404bb3e49bd6d4344da4dede0bf89cc1e01f3b723c47248a3761c/pydantic_core-2.33.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d3a07fadec2a13274a8d861d3d37c61e97a816beae717efccaa4b36dfcaadcde", size = 2122803 }, - { url = "https://files.pythonhosted.org/packages/18/9c/730a09b2694aa89360d20756369822d98dc2f31b717c21df33b64ffd1f50/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f99aeda58dce827f76963ee87a0ebe75e648c72ff9ba1174a253f6744f518f65", size = 2086755 }, - { url = "https://files.pythonhosted.org/packages/54/8e/2dccd89602b5ec31d1c58138d02340ecb2ebb8c2cac3cc66b65ce3edb6ce/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:902dbc832141aa0ec374f4310f1e4e7febeebc3256f00dc359a9ac3f264a45dc", size = 2257358 }, - { url = "https://files.pythonhosted.org/packages/d1/9c/126e4ac1bfad8a95a9837acdd0963695d69264179ba4ede8b8c40d741702/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fe44d56aa0b00d66640aa84a3cbe80b7a3ccdc6f0b1ca71090696a6d4777c091", size = 2257916 }, - { url = "https://files.pythonhosted.org/packages/7d/ba/91eea2047e681a6853c81c20aeca9dcdaa5402ccb7404a2097c2adf9d038/pydantic_core-2.33.1-cp310-cp310-win32.whl", hash = "sha256:ed3eb16d51257c763539bde21e011092f127a2202692afaeaccb50db55a31383", size = 1923823 }, - { url = "https://files.pythonhosted.org/packages/94/c0/fcdf739bf60d836a38811476f6ecd50374880b01e3014318b6e809ddfd52/pydantic_core-2.33.1-cp310-cp310-win_amd64.whl", hash = "sha256:694ad99a7f6718c1a498dc170ca430687a39894a60327f548e02a9c7ee4b6504", size = 1952494 }, - { url = "https://files.pythonhosted.org/packages/d6/7f/c6298830cb780c46b4f46bb24298d01019ffa4d21769f39b908cd14bbd50/pydantic_core-2.33.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e966fc3caaf9f1d96b349b0341c70c8d6573bf1bac7261f7b0ba88f96c56c24", size = 2044224 }, - { url = "https://files.pythonhosted.org/packages/a8/65/6ab3a536776cad5343f625245bd38165d6663256ad43f3a200e5936afd6c/pydantic_core-2.33.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bfd0adeee563d59c598ceabddf2c92eec77abcb3f4a391b19aa7366170bd9e30", size = 1858845 }, - { url = "https://files.pythonhosted.org/packages/e9/15/9a22fd26ba5ee8c669d4b8c9c244238e940cd5d818649603ca81d1c69861/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91815221101ad3c6b507804178a7bb5cb7b2ead9ecd600041669c8d805ebd595", size = 1910029 }, - { url = "https://files.pythonhosted.org/packages/d5/33/8cb1a62818974045086f55f604044bf35b9342900318f9a2a029a1bec460/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9fea9c1869bb4742d174a57b4700c6dadea951df8b06de40c2fedb4f02931c2e", size = 1997784 }, - { url = "https://files.pythonhosted.org/packages/c0/ca/49958e4df7715c71773e1ea5be1c74544923d10319173264e6db122543f9/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d20eb4861329bb2484c021b9d9a977566ab16d84000a57e28061151c62b349a", size = 2141075 }, - { url = "https://files.pythonhosted.org/packages/7b/a6/0b3a167a9773c79ba834b959b4e18c3ae9216b8319bd8422792abc8a41b1/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb935c5591573ae3201640579f30128ccc10739b45663f93c06796854405505", size = 2745849 }, - { url = "https://files.pythonhosted.org/packages/0b/60/516484135173aa9e5861d7a0663dce82e4746d2e7f803627d8c25dfa5578/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c964fd24e6166420d18fb53996d8c9fd6eac9bf5ae3ec3d03015be4414ce497f", size = 2005794 }, - { url = "https://files.pythonhosted.org/packages/86/70/05b1eb77459ad47de00cf78ee003016da0cedf8b9170260488d7c21e9181/pydantic_core-2.33.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:681d65e9011f7392db5aa002b7423cc442d6a673c635668c227c6c8d0e5a4f77", size = 2123237 }, - { url = "https://files.pythonhosted.org/packages/c7/57/12667a1409c04ae7dc95d3b43158948eb0368e9c790be8b095cb60611459/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e100c52f7355a48413e2999bfb4e139d2977a904495441b374f3d4fb4a170961", size = 2086351 }, - { url = "https://files.pythonhosted.org/packages/57/61/cc6d1d1c1664b58fdd6ecc64c84366c34ec9b606aeb66cafab6f4088974c/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:048831bd363490be79acdd3232f74a0e9951b11b2b4cc058aeb72b22fdc3abe1", size = 2258914 }, - { url = "https://files.pythonhosted.org/packages/d1/0a/edb137176a1f5419b2ddee8bde6a0a548cfa3c74f657f63e56232df8de88/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bdc84017d28459c00db6f918a7272a5190bec3090058334e43a76afb279eac7c", size = 2257385 }, - { url = "https://files.pythonhosted.org/packages/26/3c/48ca982d50e4b0e1d9954919c887bdc1c2b462801bf408613ccc641b3daa/pydantic_core-2.33.1-cp311-cp311-win32.whl", hash = "sha256:32cd11c5914d1179df70406427097c7dcde19fddf1418c787540f4b730289896", size = 1923765 }, - { url = "https://files.pythonhosted.org/packages/33/cd/7ab70b99e5e21559f5de38a0928ea84e6f23fdef2b0d16a6feaf942b003c/pydantic_core-2.33.1-cp311-cp311-win_amd64.whl", hash = "sha256:2ea62419ba8c397e7da28a9170a16219d310d2cf4970dbc65c32faf20d828c83", size = 1950688 }, - { url = "https://files.pythonhosted.org/packages/4b/ae/db1fc237b82e2cacd379f63e3335748ab88b5adde98bf7544a1b1bd10a84/pydantic_core-2.33.1-cp311-cp311-win_arm64.whl", hash = "sha256:fc903512177361e868bc1f5b80ac8c8a6e05fcdd574a5fb5ffeac5a9982b9e89", size = 1908185 }, - { url = "https://files.pythonhosted.org/packages/c8/ce/3cb22b07c29938f97ff5f5bb27521f95e2ebec399b882392deb68d6c440e/pydantic_core-2.33.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1293d7febb995e9d3ec3ea09caf1a26214eec45b0f29f6074abb004723fc1de8", size = 2026640 }, - { url = "https://files.pythonhosted.org/packages/19/78/f381d643b12378fee782a72126ec5d793081ef03791c28a0fd542a5bee64/pydantic_core-2.33.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99b56acd433386c8f20be5c4000786d1e7ca0523c8eefc995d14d79c7a081498", size = 1852649 }, - { url = "https://files.pythonhosted.org/packages/9d/2b/98a37b80b15aac9eb2c6cfc6dbd35e5058a352891c5cce3a8472d77665a6/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35a5ec3fa8c2fe6c53e1b2ccc2454398f95d5393ab398478f53e1afbbeb4d939", size = 1892472 }, - { url = "https://files.pythonhosted.org/packages/4e/d4/3c59514e0f55a161004792b9ff3039da52448f43f5834f905abef9db6e4a/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b172f7b9d2f3abc0efd12e3386f7e48b576ef309544ac3a63e5e9cdd2e24585d", size = 1977509 }, - { url = "https://files.pythonhosted.org/packages/a9/b6/c2c7946ef70576f79a25db59a576bce088bdc5952d1b93c9789b091df716/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9097b9f17f91eea659b9ec58148c0747ec354a42f7389b9d50701610d86f812e", size = 2128702 }, - { url = "https://files.pythonhosted.org/packages/88/fe/65a880f81e3f2a974312b61f82a03d85528f89a010ce21ad92f109d94deb/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc77ec5b7e2118b152b0d886c7514a4653bcb58c6b1d760134a9fab915f777b3", size = 2679428 }, - { url = "https://files.pythonhosted.org/packages/6f/ff/4459e4146afd0462fb483bb98aa2436d69c484737feaceba1341615fb0ac/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3d15245b08fa4a84cefc6c9222e6f37c98111c8679fbd94aa145f9a0ae23d", size = 2008753 }, - { url = "https://files.pythonhosted.org/packages/7c/76/1c42e384e8d78452ededac8b583fe2550c84abfef83a0552e0e7478ccbc3/pydantic_core-2.33.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef99779001d7ac2e2461d8ab55d3373fe7315caefdbecd8ced75304ae5a6fc6b", size = 2114849 }, - { url = "https://files.pythonhosted.org/packages/00/72/7d0cf05095c15f7ffe0eb78914b166d591c0eed72f294da68378da205101/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fc6bf8869e193855e8d91d91f6bf59699a5cdfaa47a404e278e776dd7f168b39", size = 2069541 }, - { url = "https://files.pythonhosted.org/packages/b3/69/94a514066bb7d8be499aa764926937409d2389c09be0b5107a970286ef81/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:b1caa0bc2741b043db7823843e1bde8aaa58a55a58fda06083b0569f8b45693a", size = 2239225 }, - { url = "https://files.pythonhosted.org/packages/84/b0/e390071eadb44b41f4f54c3cef64d8bf5f9612c92686c9299eaa09e267e2/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ec259f62538e8bf364903a7d0d0239447059f9434b284f5536e8402b7dd198db", size = 2248373 }, - { url = "https://files.pythonhosted.org/packages/d6/b2/288b3579ffc07e92af66e2f1a11be3b056fe1214aab314748461f21a31c3/pydantic_core-2.33.1-cp312-cp312-win32.whl", hash = "sha256:e14f369c98a7c15772b9da98987f58e2b509a93235582838bd0d1d8c08b68fda", size = 1907034 }, - { url = "https://files.pythonhosted.org/packages/02/28/58442ad1c22b5b6742b992ba9518420235adced665513868f99a1c2638a5/pydantic_core-2.33.1-cp312-cp312-win_amd64.whl", hash = "sha256:1c607801d85e2e123357b3893f82c97a42856192997b95b4d8325deb1cd0c5f4", size = 1956848 }, - { url = "https://files.pythonhosted.org/packages/a1/eb/f54809b51c7e2a1d9f439f158b8dd94359321abcc98767e16fc48ae5a77e/pydantic_core-2.33.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d13f0276806ee722e70a1c93da19748594f19ac4299c7e41237fc791d1861ea", size = 1903986 }, - { url = "https://files.pythonhosted.org/packages/7a/24/eed3466a4308d79155f1cdd5c7432c80ddcc4530ba8623b79d5ced021641/pydantic_core-2.33.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70af6a21237b53d1fe7b9325b20e65cbf2f0a848cf77bed492b029139701e66a", size = 2033551 }, - { url = "https://files.pythonhosted.org/packages/ab/14/df54b1a0bc9b6ded9b758b73139d2c11b4e8eb43e8ab9c5847c0a2913ada/pydantic_core-2.33.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:282b3fe1bbbe5ae35224a0dbd05aed9ccabccd241e8e6b60370484234b456266", size = 1852785 }, - { url = "https://files.pythonhosted.org/packages/fa/96/e275f15ff3d34bb04b0125d9bc8848bf69f25d784d92a63676112451bfb9/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b315e596282bbb5822d0c7ee9d255595bd7506d1cb20c2911a4da0b970187d3", size = 1897758 }, - { url = "https://files.pythonhosted.org/packages/b7/d8/96bc536e975b69e3a924b507d2a19aedbf50b24e08c80fb00e35f9baaed8/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dfae24cf9921875ca0ca6a8ecb4bb2f13c855794ed0d468d6abbec6e6dcd44a", size = 1986109 }, - { url = "https://files.pythonhosted.org/packages/90/72/ab58e43ce7e900b88cb571ed057b2fcd0e95b708a2e0bed475b10130393e/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dd8ecfde08d8bfadaea669e83c63939af76f4cf5538a72597016edfa3fad516", size = 2129159 }, - { url = "https://files.pythonhosted.org/packages/dc/3f/52d85781406886c6870ac995ec0ba7ccc028b530b0798c9080531b409fdb/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f593494876eae852dc98c43c6f260f45abdbfeec9e4324e31a481d948214764", size = 2680222 }, - { url = "https://files.pythonhosted.org/packages/f4/56/6e2ef42f363a0eec0fd92f74a91e0ac48cd2e49b695aac1509ad81eee86a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948b73114f47fd7016088e5186d13faf5e1b2fe83f5e320e371f035557fd264d", size = 2006980 }, - { url = "https://files.pythonhosted.org/packages/4c/c0/604536c4379cc78359f9ee0aa319f4aedf6b652ec2854953f5a14fc38c5a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11f3864eb516af21b01e25fac915a82e9ddad3bb0fb9e95a246067398b435a4", size = 2120840 }, - { url = "https://files.pythonhosted.org/packages/1f/46/9eb764814f508f0edfb291a0f75d10854d78113fa13900ce13729aaec3ae/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:549150be302428b56fdad0c23c2741dcdb5572413776826c965619a25d9c6bde", size = 2072518 }, - { url = "https://files.pythonhosted.org/packages/42/e3/fb6b2a732b82d1666fa6bf53e3627867ea3131c5f39f98ce92141e3e3dc1/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:495bc156026efafd9ef2d82372bd38afce78ddd82bf28ef5276c469e57c0c83e", size = 2248025 }, - { url = "https://files.pythonhosted.org/packages/5c/9d/fbe8fe9d1aa4dac88723f10a921bc7418bd3378a567cb5e21193a3c48b43/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ec79de2a8680b1a67a07490bddf9636d5c2fab609ba8c57597e855fa5fa4dacd", size = 2254991 }, - { url = "https://files.pythonhosted.org/packages/aa/99/07e2237b8a66438d9b26482332cda99a9acccb58d284af7bc7c946a42fd3/pydantic_core-2.33.1-cp313-cp313-win32.whl", hash = "sha256:ee12a7be1742f81b8a65b36c6921022301d466b82d80315d215c4c691724986f", size = 1915262 }, - { url = "https://files.pythonhosted.org/packages/8a/f4/e457a7849beeed1e5defbcf5051c6f7b3c91a0624dd31543a64fc9adcf52/pydantic_core-2.33.1-cp313-cp313-win_amd64.whl", hash = "sha256:ede9b407e39949d2afc46385ce6bd6e11588660c26f80576c11c958e6647bc40", size = 1956626 }, - { url = "https://files.pythonhosted.org/packages/20/d0/e8d567a7cff7b04e017ae164d98011f1e1894269fe8e90ea187a3cbfb562/pydantic_core-2.33.1-cp313-cp313-win_arm64.whl", hash = "sha256:aa687a23d4b7871a00e03ca96a09cad0f28f443690d300500603bd0adba4b523", size = 1909590 }, - { url = "https://files.pythonhosted.org/packages/ef/fd/24ea4302d7a527d672c5be06e17df16aabfb4e9fdc6e0b345c21580f3d2a/pydantic_core-2.33.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:401d7b76e1000d0dd5538e6381d28febdcacb097c8d340dde7d7fc6e13e9f95d", size = 1812963 }, - { url = "https://files.pythonhosted.org/packages/5f/95/4fbc2ecdeb5c1c53f1175a32d870250194eb2fdf6291b795ab08c8646d5d/pydantic_core-2.33.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aeb055a42d734c0255c9e489ac67e75397d59c6fbe60d155851e9782f276a9c", size = 1986896 }, - { url = "https://files.pythonhosted.org/packages/71/ae/fe31e7f4a62431222d8f65a3bd02e3fa7e6026d154a00818e6d30520ea77/pydantic_core-2.33.1-cp313-cp313t-win_amd64.whl", hash = "sha256:338ea9b73e6e109f15ab439e62cb3b78aa752c7fd9536794112e14bee02c8d18", size = 1931810 }, - { url = "https://files.pythonhosted.org/packages/49/78/b86bad645cc3e8dfa6858c70ec38939bf350e54004837c48de09474b2b9e/pydantic_core-2.33.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5ab77f45d33d264de66e1884fca158bc920cb5e27fd0764a72f72f5756ae8bdb", size = 2044282 }, - { url = "https://files.pythonhosted.org/packages/3b/00/a02531331773b2bf08743d84c6b776bd6a449d23b3ae6b0e3229d568bac4/pydantic_core-2.33.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7aaba1b4b03aaea7bb59e1b5856d734be011d3e6d98f5bcaa98cb30f375f2ad", size = 1877598 }, - { url = "https://files.pythonhosted.org/packages/a1/fa/32cc152b84a1f420f8a7d80161373e8d87d4ffa077e67d6c8aab3ce1a6ab/pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fb66263e9ba8fea2aa85e1e5578980d127fb37d7f2e292773e7bc3a38fb0c7b", size = 1911021 }, - { url = "https://files.pythonhosted.org/packages/5e/87/ea553e0d98bce6c4876f8c50f65cb45597eff6e0aaa8b15813e9972bb19d/pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f2648b9262607a7fb41d782cc263b48032ff7a03a835581abbf7a3bec62bcf5", size = 1997276 }, - { url = "https://files.pythonhosted.org/packages/f7/9b/60cb9f4b52158b3adac0066492bbadd0b8473f4f8da5bcc73972655b76ef/pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:723c5630c4259400818b4ad096735a829074601805d07f8cafc366d95786d331", size = 2141348 }, - { url = "https://files.pythonhosted.org/packages/9b/38/374d254e270d4de0add68a8239f4ed0f444fdd7b766ea69244fb9491dccb/pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d100e3ae783d2167782391e0c1c7a20a31f55f8015f3293647544df3f9c67824", size = 2753708 }, - { url = "https://files.pythonhosted.org/packages/05/a8/fd79111eb5ab9bc4ef98d8fb0b3a2ffdc80107b2c59859a741ab379c96f8/pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177d50460bc976a0369920b6c744d927b0ecb8606fb56858ff542560251b19e5", size = 2008699 }, - { url = "https://files.pythonhosted.org/packages/35/31/2e06619868eb4c18642c5601db420599c1cf9cf50fe868c9ac09cd298e24/pydantic_core-2.33.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3edde68d1a1f9af1273b2fe798997b33f90308fb6d44d8550c89fc6a3647cf6", size = 2123426 }, - { url = "https://files.pythonhosted.org/packages/4a/d0/3531e8783a311802e3db7ee5a1a5ed79e5706e930b1b4e3109ce15eeb681/pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a62c3c3ef6a7e2c45f7853b10b5bc4ddefd6ee3cd31024754a1a5842da7d598d", size = 2087330 }, - { url = "https://files.pythonhosted.org/packages/ac/32/5ff252ed73bacd7677a706ab17723e261a76793f98b305aa20cfc10bbd56/pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:c91dbb0ab683fa0cd64a6e81907c8ff41d6497c346890e26b23de7ee55353f96", size = 2258171 }, - { url = "https://files.pythonhosted.org/packages/c9/f9/e96e00f92b8f5b3e2cddc80c5ee6cf038f8a0f238c44b67b01759943a7b4/pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f466e8bf0a62dc43e068c12166281c2eca72121dd2adc1040f3aa1e21ef8599", size = 2258745 }, - { url = "https://files.pythonhosted.org/packages/54/1e/51c86688e809d94797fdf0efc41514f001caec982a05f62d90c180a9639d/pydantic_core-2.33.1-cp39-cp39-win32.whl", hash = "sha256:ab0277cedb698749caada82e5d099dc9fed3f906a30d4c382d1a21725777a1e5", size = 1923626 }, - { url = "https://files.pythonhosted.org/packages/57/18/c2da959fd8d019b70cadafdda2bf845378ada47973e0bad6cc84f56dbe6e/pydantic_core-2.33.1-cp39-cp39-win_amd64.whl", hash = "sha256:5773da0ee2d17136b1f1c6fbde543398d452a6ad2a7b54ea1033e2daa739b8d2", size = 1953703 }, - { url = "https://files.pythonhosted.org/packages/9c/c7/8b311d5adb0fe00a93ee9b4e92a02b0ec08510e9838885ef781ccbb20604/pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c834f54f8f4640fd7e4b193f80eb25a0602bba9e19b3cd2fc7ffe8199f5ae02", size = 2041659 }, - { url = "https://files.pythonhosted.org/packages/8a/d6/4f58d32066a9e26530daaf9adc6664b01875ae0691570094968aaa7b8fcc/pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:049e0de24cf23766f12cc5cc71d8abc07d4a9deb9061b334b62093dedc7cb068", size = 1873294 }, - { url = "https://files.pythonhosted.org/packages/f7/3f/53cc9c45d9229da427909c751f8ed2bf422414f7664ea4dde2d004f596ba/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a28239037b3d6f16916a4c831a5a0eadf856bdd6d2e92c10a0da3a59eadcf3e", size = 1903771 }, - { url = "https://files.pythonhosted.org/packages/f0/49/bf0783279ce674eb9903fb9ae43f6c614cb2f1c4951370258823f795368b/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d3da303ab5f378a268fa7d45f37d7d85c3ec19769f28d2cc0c61826a8de21fe", size = 2083558 }, - { url = "https://files.pythonhosted.org/packages/9c/5b/0d998367687f986c7d8484a2c476d30f07bf5b8b1477649a6092bd4c540e/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25626fb37b3c543818c14821afe0fd3830bc327a43953bc88db924b68c5723f1", size = 2118038 }, - { url = "https://files.pythonhosted.org/packages/b3/33/039287d410230ee125daee57373ac01940d3030d18dba1c29cd3089dc3ca/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3ab2d36e20fbfcce8f02d73c33a8a7362980cff717926bbae030b93ae46b56c7", size = 2079315 }, - { url = "https://files.pythonhosted.org/packages/1f/85/6d8b2646d99c062d7da2d0ab2faeb0d6ca9cca4c02da6076376042a20da3/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2f9284e11c751b003fd4215ad92d325d92c9cb19ee6729ebd87e3250072cdcde", size = 2249063 }, - { url = "https://files.pythonhosted.org/packages/17/d7/c37d208d5738f7b9ad8f22ae8a727d88ebf9c16c04ed2475122cc3f7224a/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:048c01eee07d37cbd066fc512b9d8b5ea88ceeb4e629ab94b3e56965ad655add", size = 2254631 }, - { url = "https://files.pythonhosted.org/packages/13/e0/bafa46476d328e4553b85ab9b2f7409e7aaef0ce4c937c894821c542d347/pydantic_core-2.33.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5ccd429694cf26af7997595d627dd2637e7932214486f55b8a357edaac9dae8c", size = 2080877 }, - { url = "https://files.pythonhosted.org/packages/0b/76/1794e440c1801ed35415238d2c728f26cd12695df9057154ad768b7b991c/pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a371dc00282c4b84246509a5ddc808e61b9864aa1eae9ecc92bb1268b82db4a", size = 2042858 }, - { url = "https://files.pythonhosted.org/packages/73/b4/9cd7b081fb0b1b4f8150507cd59d27b275c3e22ad60b35cb19ea0977d9b9/pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f59295ecc75a1788af8ba92f2e8c6eeaa5a94c22fc4d151e8d9638814f85c8fc", size = 1873745 }, - { url = "https://files.pythonhosted.org/packages/e1/d7/9ddb7575d4321e40d0363903c2576c8c0c3280ebea137777e5ab58d723e3/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08530b8ac922003033f399128505f513e30ca770527cc8bbacf75a84fcc2c74b", size = 1904188 }, - { url = "https://files.pythonhosted.org/packages/d1/a8/3194ccfe461bb08da19377ebec8cb4f13c9bd82e13baebc53c5c7c39a029/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae370459da6a5466978c0eacf90690cb57ec9d533f8e63e564ef3822bfa04fe", size = 2083479 }, - { url = "https://files.pythonhosted.org/packages/42/c7/84cb569555d7179ca0b3f838cef08f66f7089b54432f5b8599aac6e9533e/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e3de2777e3b9f4d603112f78006f4ae0acb936e95f06da6cb1a45fbad6bdb4b5", size = 2118415 }, - { url = "https://files.pythonhosted.org/packages/3b/67/72abb8c73e0837716afbb58a59cc9e3ae43d1aa8677f3b4bc72c16142716/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a64e81e8cba118e108d7126362ea30e021291b7805d47e4896e52c791be2761", size = 2079623 }, - { url = "https://files.pythonhosted.org/packages/0b/cd/c59707e35a47ba4cbbf153c3f7c56420c58653b5801b055dc52cccc8e2dc/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:52928d8c1b6bda03cc6d811e8923dffc87a2d3c8b3bfd2ce16471c7147a24850", size = 2250175 }, - { url = "https://files.pythonhosted.org/packages/84/32/e4325a6676b0bed32d5b084566ec86ed7fd1e9bcbfc49c578b1755bde920/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1b30d92c9412beb5ac6b10a3eb7ef92ccb14e3f2a8d7732e2d739f58b3aa7544", size = 2254674 }, - { url = "https://files.pythonhosted.org/packages/12/6f/5596dc418f2e292ffc661d21931ab34591952e2843e7168ea5a52591f6ff/pydantic_core-2.33.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f995719707e0e29f0f41a8aa3bcea6e761a36c9136104d3189eafb83f5cec5e5", size = 2080951 }, - { url = "https://files.pythonhosted.org/packages/2d/a8/c2c8f29bd18f7ef52de32a6deb9e3ee87ba18b7b2122636aa9f4438cf627/pydantic_core-2.33.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7edbc454a29fc6aeae1e1eecba4f07b63b8d76e76a748532233c4c167b4cb9ea", size = 2041791 }, - { url = "https://files.pythonhosted.org/packages/08/ad/328081b1c82543ae49d0650048305058583c51f1a9a56a0d6e87bb3a2443/pydantic_core-2.33.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad05b683963f69a1d5d2c2bdab1274a31221ca737dbbceaa32bcb67359453cdd", size = 1873579 }, - { url = "https://files.pythonhosted.org/packages/6e/8a/bc65dbf7e501e88367cdab06a2c1340457c785f0c72288cae737fd80c0fa/pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df6a94bf9452c6da9b5d76ed229a5683d0306ccb91cca8e1eea883189780d568", size = 1904189 }, - { url = "https://files.pythonhosted.org/packages/9a/db/30ca6aefda211fb01ef185ca73cb7a0c6e7fe952c524025c8782b5acd771/pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7965c13b3967909a09ecc91f21d09cfc4576bf78140b988904e94f130f188396", size = 2084446 }, - { url = "https://files.pythonhosted.org/packages/f2/89/a12b55286e30c9f476eab7c53c9249ec76faf70430596496ab0309f28629/pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3f1fdb790440a34f6ecf7679e1863b825cb5ffde858a9197f851168ed08371e5", size = 2118215 }, - { url = "https://files.pythonhosted.org/packages/8e/55/12721c4a8d7951584ad3d9848b44442559cf1876e0bb424148d1060636b3/pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5277aec8d879f8d05168fdd17ae811dd313b8ff894aeeaf7cd34ad28b4d77e33", size = 2079963 }, - { url = "https://files.pythonhosted.org/packages/bd/0c/3391bd5d6ff62ea998db94732528d9bc32c560b0ed861c39119759461946/pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8ab581d3530611897d863d1a649fb0644b860286b4718db919bfd51ece41f10b", size = 2249388 }, - { url = "https://files.pythonhosted.org/packages/d3/5f/3e4feb042998d7886a9b523b372d83955cbc192a07013dcd24276db078ee/pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0483847fa9ad5e3412265c1bd72aad35235512d9ce9d27d81a56d935ef489672", size = 2255226 }, - { url = "https://files.pythonhosted.org/packages/25/f2/1647933efaaad61846109a27619f3704929e758a09e6431b8f932a053d40/pydantic_core-2.33.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:de9e06abe3cc5ec6a2d5f75bc99b0bdca4f5c719a5b34026f8c57efbdecd2ee3", size = 2081073 }, +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" }, + { url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" }, + { url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" }, + { url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" }, + { url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" }, + { url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" }, + { url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" }, + { url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" }, + { url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" }, + { url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" }, + { url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" }, + { url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" }, + { url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" }, + { url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" }, + { url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" }, + { url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" }, + { url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" }, + { url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" }, + { url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" }, + { url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" }, + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, + { url = "https://files.pythonhosted.org/packages/53/ea/bbe9095cdd771987d13c82d104a9c8559ae9aec1e29f139e286fd2e9256e/pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d", size = 2028677, upload-time = "2025-04-23T18:32:27.227Z" }, + { url = "https://files.pythonhosted.org/packages/49/1d/4ac5ed228078737d457a609013e8f7edc64adc37b91d619ea965758369e5/pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954", size = 1864735, upload-time = "2025-04-23T18:32:29.019Z" }, + { url = "https://files.pythonhosted.org/packages/23/9a/2e70d6388d7cda488ae38f57bc2f7b03ee442fbcf0d75d848304ac7e405b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb", size = 1898467, upload-time = "2025-04-23T18:32:31.119Z" }, + { url = "https://files.pythonhosted.org/packages/ff/2e/1568934feb43370c1ffb78a77f0baaa5a8b6897513e7a91051af707ffdc4/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7", size = 1983041, upload-time = "2025-04-23T18:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/01/1a/1a1118f38ab64eac2f6269eb8c120ab915be30e387bb561e3af904b12499/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4", size = 2136503, upload-time = "2025-04-23T18:32:35.519Z" }, + { url = "https://files.pythonhosted.org/packages/5c/da/44754d1d7ae0f22d6d3ce6c6b1486fc07ac2c524ed8f6eca636e2e1ee49b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b", size = 2736079, upload-time = "2025-04-23T18:32:37.659Z" }, + { url = "https://files.pythonhosted.org/packages/4d/98/f43cd89172220ec5aa86654967b22d862146bc4d736b1350b4c41e7c9c03/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3", size = 2006508, upload-time = "2025-04-23T18:32:39.637Z" }, + { url = "https://files.pythonhosted.org/packages/2b/cc/f77e8e242171d2158309f830f7d5d07e0531b756106f36bc18712dc439df/pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a", size = 2113693, upload-time = "2025-04-23T18:32:41.818Z" }, + { url = "https://files.pythonhosted.org/packages/54/7a/7be6a7bd43e0a47c147ba7fbf124fe8aaf1200bc587da925509641113b2d/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782", size = 2074224, upload-time = "2025-04-23T18:32:44.033Z" }, + { url = "https://files.pythonhosted.org/packages/2a/07/31cf8fadffbb03be1cb520850e00a8490c0927ec456e8293cafda0726184/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9", size = 2245403, upload-time = "2025-04-23T18:32:45.836Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8d/bbaf4c6721b668d44f01861f297eb01c9b35f612f6b8e14173cb204e6240/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e", size = 2242331, upload-time = "2025-04-23T18:32:47.618Z" }, + { url = "https://files.pythonhosted.org/packages/bb/93/3cc157026bca8f5006250e74515119fcaa6d6858aceee8f67ab6dc548c16/pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9", size = 1910571, upload-time = "2025-04-23T18:32:49.401Z" }, + { url = "https://files.pythonhosted.org/packages/5b/90/7edc3b2a0d9f0dda8806c04e511a67b0b7a41d2187e2003673a996fb4310/pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3", size = 1956504, upload-time = "2025-04-23T18:32:51.287Z" }, + { url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" }, + { url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" }, + { url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" }, + { url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" }, + { url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" }, + { url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" }, + { url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" }, + { url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" }, + { url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" }, + { url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" }, + { url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" }, + { url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" }, + { url = "https://files.pythonhosted.org/packages/08/98/dbf3fdfabaf81cda5622154fda78ea9965ac467e3239078e0dcd6df159e7/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101", size = 2024034, upload-time = "2025-04-23T18:33:32.843Z" }, + { url = "https://files.pythonhosted.org/packages/8d/99/7810aa9256e7f2ccd492590f86b79d370df1e9292f1f80b000b6a75bd2fb/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64", size = 1858578, upload-time = "2025-04-23T18:33:34.912Z" }, + { url = "https://files.pythonhosted.org/packages/d8/60/bc06fa9027c7006cc6dd21e48dbf39076dc39d9abbaf718a1604973a9670/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d", size = 1892858, upload-time = "2025-04-23T18:33:36.933Z" }, + { url = "https://files.pythonhosted.org/packages/f2/40/9d03997d9518816c68b4dfccb88969756b9146031b61cd37f781c74c9b6a/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535", size = 2068498, upload-time = "2025-04-23T18:33:38.997Z" }, + { url = "https://files.pythonhosted.org/packages/d8/62/d490198d05d2d86672dc269f52579cad7261ced64c2df213d5c16e0aecb1/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d", size = 2108428, upload-time = "2025-04-23T18:33:41.18Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ec/4cd215534fd10b8549015f12ea650a1a973da20ce46430b68fc3185573e8/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6", size = 2069854, upload-time = "2025-04-23T18:33:43.446Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1a/abbd63d47e1d9b0d632fee6bb15785d0889c8a6e0a6c3b5a8e28ac1ec5d2/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca", size = 2237859, upload-time = "2025-04-23T18:33:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/80/1c/fa883643429908b1c90598fd2642af8839efd1d835b65af1f75fba4d94fe/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039", size = 2239059, upload-time = "2025-04-23T18:33:47.735Z" }, + { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] [[package]] name = "pydantic-extra-types" -version = "2.10.3" +version = "2.10.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/53/fa/6b268a47839f8af46ffeb5bb6aee7bded44fbad54e6bf826c11f17aef91a/pydantic_extra_types-2.10.3.tar.gz", hash = "sha256:dcc0a7b90ac9ef1b58876c9b8fdede17fbdde15420de9d571a9fccde2ae175bb", size = 95128 } +sdist = { url = "https://files.pythonhosted.org/packages/d9/33/0cde418479949cd6aa1ac669deffcd1c37d8d9cead99ddb48f344e75f2e3/pydantic_extra_types-2.10.4.tar.gz", hash = "sha256:bf8236a63d061eb3ecb1b2afa78ba0f97e3f67aa11dbbff56ec90491e8772edc", size = 95269, upload-time = "2025-04-28T08:18:34.869Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/0a/f6f8e5f79d188e2f3fa9ecfccfa72538b685985dd5c7c2886c67af70e685/pydantic_extra_types-2.10.3-py3-none-any.whl", hash = "sha256:e8b372752b49019cd8249cc192c62a820d8019f5382a8789d0f887338a59c0f3", size = 37175 }, + { url = "https://files.pythonhosted.org/packages/df/ac/bee195ee49256385fad460ce420aeb42703a648dba487c20b6fd107e42ea/pydantic_extra_types-2.10.4-py3-none-any.whl", hash = "sha256:ce064595af3cab05e39ae062752432dcd0362ff80f7e695b61a3493a4d842db7", size = 37276, upload-time = "2025-04-28T08:18:31.617Z" }, ] [[package]] @@ -2571,139 +2590,139 @@ dependencies = [ { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/67/1d/42628a2c33e93f8e9acbde0d5d735fa0850f3e6a2f8cb1eb6c40b9a732ac/pydantic_settings-2.9.1.tar.gz", hash = "sha256:c509bf79d27563add44e8446233359004ed85066cd096d8b510f715e6ef5d268", size = 163234 } +sdist = { url = "https://files.pythonhosted.org/packages/67/1d/42628a2c33e93f8e9acbde0d5d735fa0850f3e6a2f8cb1eb6c40b9a732ac/pydantic_settings-2.9.1.tar.gz", hash = "sha256:c509bf79d27563add44e8446233359004ed85066cd096d8b510f715e6ef5d268", size = 163234, upload-time = "2025-04-18T16:44:48.265Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/5f/d6d641b490fd3ec2c4c13b4244d68deea3a1b970a97be64f34fb5504ff72/pydantic_settings-2.9.1-py3-none-any.whl", hash = "sha256:59b4f431b1defb26fe620c71a7d3968a710d719f5f4cdbbdb7926edeb770f6ef", size = 44356 }, + { url = "https://files.pythonhosted.org/packages/b6/5f/d6d641b490fd3ec2c4c13b4244d68deea3a1b970a97be64f34fb5504ff72/pydantic_settings-2.9.1-py3-none-any.whl", hash = "sha256:59b4f431b1defb26fe620c71a7d3968a710d719f5f4cdbbdb7926edeb770f6ef", size = 44356, upload-time = "2025-04-18T16:44:46.617Z" }, ] [[package]] name = "pygments" version = "2.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, ] [[package]] name = "pymssql" version = "2.3.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/35/5a0b79369e42fffd5c04e4e74fa90ef034cc5c3f314e14f6d58cac646ccf/pymssql-2.3.4.tar.gz", hash = "sha256:117c82d7aa9021171aa9be98368475519f33d9c32073cdcf9b0d76231abc6436", size = 184604 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/c1/9624556dfc8e72f72c2e2ef6d754e7833eb2ea3ba7673696c4cc601bcea9/pymssql-2.3.4-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:cec30403e10f7e8135c8aea9c764b1f1fc40b64d5d957802c3d537fdb34677e9", size = 2806104 }, - { url = "https://files.pythonhosted.org/packages/1b/d3/6127c0d7d66e166ab18be0d02354486062e21f9d5bb4f170925118b42776/pymssql-2.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35cf87fcd0537272b35a5a683597996fe96bee4554d1944fe990c51d7dcb4143", size = 3927321 }, - { url = "https://files.pythonhosted.org/packages/4e/e9/63aee4c65123af29039c1ac86a71d34bb4b2aac2311325cedfbb1a22d6da/pymssql-2.3.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fdfa946c5c08322dd321a99fff0fe36de63e243a5e525d4935cbf1df4072cda", size = 3933920 }, - { url = "https://files.pythonhosted.org/packages/d8/51/3be7830c19a193c111e882ce6f30be82de5c196a57c9ef15ab7d7e5955a5/pymssql-2.3.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46083224df49a2dbf76f8bd4989cfbabf92e0d381fdcb89539b931d61a265b59", size = 4279543 }, - { url = "https://files.pythonhosted.org/packages/52/87/269cd50837ed827c37273a62e8445458eab94c873ffd27200c20498093be/pymssql-2.3.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:825aec308d258ece4ebebc7a0844276d796024a88775b2c11c128969605c055d", size = 4717796 }, - { url = "https://files.pythonhosted.org/packages/b4/ab/2fa3ed3c5471f7afa5c0e9f14b9820993d55ffdbefb1a1a8dd8a417e33e7/pymssql-2.3.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8746b14a836176ac8dbbed951a5bcfb4c32377f167ae51e2fe3bd170fbf838cb", size = 4015984 }, - { url = "https://files.pythonhosted.org/packages/38/85/95d7ada9ed26890585de6901878b3e1e2d0b13568dc033522a2d2bf85aeb/pymssql-2.3.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:339ac869543b0f0658bd5a6337c7efe87010ded12b69042bc67b716b117b5ce5", size = 4034457 }, - { url = "https://files.pythonhosted.org/packages/d0/4c/fdd9416b6f1e85a88eff31ba12a885d3313a2ca00763766301e80cca9928/pymssql-2.3.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0951c1d17e523dfb22abca653a98df4bec2c6a8a75fa641206c72a5c0d3b1253", size = 4564119 }, - { url = "https://files.pythonhosted.org/packages/24/86/fc7352b38179e52ad6271f20bfd6a695dfd0a34e6da96f8a4a00e7436e94/pymssql-2.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cd1eb757bba516e45dd055edc61aee0cfe540b93e8da1de8bded16220ac1a19", size = 4781324 }, - { url = "https://files.pythonhosted.org/packages/68/3d/c3e754b309a26e778ec461d40b1489ce83de46ec55120a43b029a4726110/pymssql-2.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:523f17ec7b26040a1545b2674d6dde668529b5f930a8dae98379e28e74b1a2ce", size = 2037141 }, - { url = "https://files.pythonhosted.org/packages/bb/20/fb8ab5d4a21be9d8b9e5661d7d1bf218bb04faa5c1a8ee5e9c2dc3d6f98d/pymssql-2.3.4-cp311-cp311-macosx_13_0_universal2.whl", hash = "sha256:70cbf00ef172f864f3334666c824bf9a1c7c0dffc9319263e7fd6ac097ed98cb", size = 3102701 }, - { url = "https://files.pythonhosted.org/packages/5a/12/9eca79b2b55f220029bdb1009b5e66fedfb2d6a82b1868049220cb1a518a/pymssql-2.3.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a417eeab6b7000777db5bcecd391f13d9fa8ec082994650ea9327edafba4a30", size = 4076253 }, - { url = "https://files.pythonhosted.org/packages/55/c4/f8bf22f696992887146015790fe5f418cff808810fe33d7704b519c350e2/pymssql-2.3.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0d10384c428b92f16d46eaeb9f14976e768a22083b68d646e6659b514571d37", size = 4064397 }, - { url = "https://files.pythonhosted.org/packages/26/dc/90eb4178768e5e1a5afb128887daffa206615f0953d3e1513e4af4d91d56/pymssql-2.3.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:318de31ee24ee417df7d454aa75240cef806a029996259c5820057eff4d87fb0", size = 4422625 }, - { url = "https://files.pythonhosted.org/packages/e3/1a/820066ddbc46f1d5f084e2a0aeb830bf8222cd1b9d1fdc7df7a8b7fc80ec/pymssql-2.3.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:502b4b6df757fbe1196eba204d06fb4b55b4fab0019eb23b2dccd51c2ae149a5", size = 4879015 }, - { url = "https://files.pythonhosted.org/packages/a6/7c/dbacd3da9c494afebd09de8a10ab6241654586be202d029c75628957cd99/pymssql-2.3.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:707996a9bee34e2fb9cc87f0d64b87a527884ab6b7dd19496e676b42527fb039", size = 4155544 }, - { url = "https://files.pythonhosted.org/packages/d4/f4/f87086a2580fd9bf8df4cae940b2d6daccb61ab57ce2feac7fe0ae4c4c23/pymssql-2.3.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5de0c70701736a815facc4d1cb943293829b7c5994c6c50bbc9abdf138cf1e4", size = 4188664 }, - { url = "https://files.pythonhosted.org/packages/b8/1d/ed047510378bdf7dadd7d5f4373cff4179135a5c0e561fe15ad00c0b8870/pymssql-2.3.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e1087ad97a10db3f6cc387da9fcbccdbf458054b54f793d9aa61f0da69e32e15", size = 4723365 }, - { url = "https://files.pythonhosted.org/packages/3c/79/2dd758ea7f6dc0d4639c8ba93b46b7a18d54e7f57e9ad82c441cba101c23/pymssql-2.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:107e1b5efc42376b2426fcfadaad2b559d90ba55f634abd1af551e8c88aa9252", size = 4951520 }, - { url = "https://files.pythonhosted.org/packages/8b/b6/a54afeb5df87fc22add90d5d0076cb3ece19b6d6c68b8826400269fab316/pymssql-2.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:e131c6148dd25a89f666ae6156a8a95a6526628955a3cd8326ccf1cba4183d64", size = 2037972 }, - { url = "https://files.pythonhosted.org/packages/bc/89/5a7a4b27ee44b2dc4708de7e897311cb17f15e7c983c299e8bf97ebf98d1/pymssql-2.3.4-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:809b75aaeb9bcd061230bace41e275f80f464f70fcbf5dde2ba7ba8f0eea5298", size = 3075736 }, - { url = "https://files.pythonhosted.org/packages/43/f9/19bbb0026a47043fb239e821e10a75304b12ba986ce4af71cf8986af411c/pymssql-2.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48ab1ee04754fb8ce703b6c154e54fde4f6c7f440766d397b101b748123a12df", size = 4019433 }, - { url = "https://files.pythonhosted.org/packages/a6/ac/3aca13f1f527299db4adef594fb9f14d47d68de91b93a220a67391b8ec87/pymssql-2.3.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e22bb4d5aed85b084e3b9fb5ae3463301dd69c17703cfef72e0aed746452cc9", size = 3993550 }, - { url = "https://files.pythonhosted.org/packages/b9/93/879d92f61afb974f69b9186b16ee6a97adff2abc82777e3b66c9c9efb179/pymssql-2.3.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2c1c8d3632630d52387e5b5b4483027494b5cb8f65401573715b74e7a3f16e5", size = 4381934 }, - { url = "https://files.pythonhosted.org/packages/6c/a6/923769b6dbb4e3a4c07a867e0c7fa8e4b230f675095cd7109d4e3eb9ddf0/pymssql-2.3.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f7f245acbdf89b96a41513ef0214b55a3ba2824f1f3119dd1945443b6cac78d3", size = 4849674 }, - { url = "https://files.pythonhosted.org/packages/7a/2d/c787f061dcd0603905bf8085dda9cddb8c3c03b18d9239d5d18c953eebba/pymssql-2.3.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9484485fb847eb67f828459b0f4857c9725b20c517c2b7f88a9788fd72b76a6a", size = 4076649 }, - { url = "https://files.pythonhosted.org/packages/c1/a2/e55d823e3ab21cf9fc88e4e2424936899392d9d2e6569d5bcce063f84dac/pymssql-2.3.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a0716482cd5ecce07230925593cefd9137959c18aca4c92fc24c243d3c20e38", size = 4139477 }, - { url = "https://files.pythonhosted.org/packages/c7/7c/0fec6587b38081d0d0fca4f9ad31e85ec6c5791879e57f0e559ec6be4d3d/pymssql-2.3.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ba4f988674b361709821c8173a6471aa6e47ee6e45b5a8e30d4dcbde1f62fb0f", size = 4653837 }, - { url = "https://files.pythonhosted.org/packages/5f/7c/77d0251f4b5ad5690226a93547fc8279c1c48bd14e3ccc820f5c580a3b73/pymssql-2.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:51b8ebfbd7d14d5e7c65e76ffaf31584ffabe9fb1bfd2a85f529bd707512e39d", size = 4910914 }, - { url = "https://files.pythonhosted.org/packages/4f/22/1b2ef85804872a5940010d3c012722356af1fa24f8ba6f419c0260881032/pymssql-2.3.4-cp312-cp312-win32.whl", hash = "sha256:c8f5718f5e7d2623eaf35e025d5fa288c5789916809a89f00b42346b888673da", size = 1337991 }, - { url = "https://files.pythonhosted.org/packages/0f/43/c98f34e7b3cd45653fb233a4bee83bffca0cf5e78c290c291cec34faac21/pymssql-2.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:d72b38b5ba66a4072c680447099bb63ac35d0425e9a29ff91b048e563b999be5", size = 2021760 }, - { url = "https://files.pythonhosted.org/packages/63/58/90dbe299359c547fcb037d4a12f2146916213b99a245d01efdf5ade52910/pymssql-2.3.4-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:36ede0bc046e18cb0a5f043828bc441c80ffb2aa4606ce0cfcbf2a3d71266f0a", size = 3064581 }, - { url = "https://files.pythonhosted.org/packages/4b/7c/15e75a74de5e392ea1a9456261632cc312c873f28ac2f9ef39dfefac8cd2/pymssql-2.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d247114853ada387415df303d24d2e990596ce28b23f5b59c46d852cfea0f2ad", size = 4013283 }, - { url = "https://files.pythonhosted.org/packages/2a/29/b9f08676145c3086db11c55b40bd58dfb0d775853f7280c1b2e15fc44fc2/pymssql-2.3.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79881cbe1a5826ddb959ccf8add015e5b82e6afbbf9cf5e281bd794278b2c2eb", size = 3996475 }, - { url = "https://files.pythonhosted.org/packages/ab/cb/54ca973c666e8402f3bf7feaf7e2037b7c80dbd732be67e224f95cb6a1cc/pymssql-2.3.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bfcd63280b0f74124241092bdfd7889925342bcb58b4cde299e4c91cec55436", size = 4377615 }, - { url = "https://files.pythonhosted.org/packages/c1/f2/973dfded45e0df9dcf72bc1b7254cefd5ffb1492f314822020d3c066421f/pymssql-2.3.4-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f3b784563f2b24c4d3f0e250fa9cfe59a22791539725f4d5059139c66f072a14", size = 4839647 }, - { url = "https://files.pythonhosted.org/packages/91/cb/9d9342f0936ff6d58a59446e7449f93cc1134e59f3a1ec075e7b364e82a6/pymssql-2.3.4-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a54a018215cf0cffbaaa6edaa02215ef19fa9c9ff6a2c172e8fa563f577e2e91", size = 4079413 }, - { url = "https://files.pythonhosted.org/packages/9e/f1/79866247539144dcc9e44e9f8ad700bdc78c286863f37d879d71bbfd2c94/pymssql-2.3.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:14f2474fda3c57bc95b9ba146552463571fe77c816cbfb2e64344528d9afb755", size = 4141187 }, - { url = "https://files.pythonhosted.org/packages/9c/2d/c187ebcaeb2832cc7ac85034897eb920b361fd63bf011a5d02b31fe2f840/pymssql-2.3.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:145dc2b73e4fe115e6176866245921ce95a216a8d6cb0d9420c2e05ee2a911a9", size = 4661965 }, - { url = "https://files.pythonhosted.org/packages/77/59/aae5ba396d1c603325112bf7106705e1781e4604381faa45ad55161f2b0f/pymssql-2.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e08f1bc9e4a914c82816e3e5270b53bead13d3444435fc7bddfff9cb302b9982", size = 4903978 }, - { url = "https://files.pythonhosted.org/packages/3f/a9/25ea7056857aabbfd285c397084c571e4486f341ff8e8086b067bc2e2109/pymssql-2.3.4-cp313-cp313-win32.whl", hash = "sha256:e31b507f4669671e8bbdeecf1c1c2ed9c092953a1decfae5af656200a74195d1", size = 1337662 }, - { url = "https://files.pythonhosted.org/packages/a8/17/66414aeb30a4c2a23d29b2b8715d20d23e57c3ac2dd7bfd6fee5aa093e07/pymssql-2.3.4-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:378cb74a67cb177d6864acd446e17afc7ebbc7b3cde9cfee04d7221ec1bc08ef", size = 2806568 }, - { url = "https://files.pythonhosted.org/packages/1c/e7/00a27e73300a172618d5b0cd2f910d4ef434d0c221aa2ff0a507a614ce34/pymssql-2.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ad790becb502b1a981fc83d922813303a1eac7867df62bda2ca12f41b73efd2", size = 3925998 }, - { url = "https://files.pythonhosted.org/packages/c1/fd/22275fbe8c2de5d0112b0809e444be922762a9f12a791ed49a8bec14e59b/pymssql-2.3.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b538838abef0bd45a0cf097dfe661a5b8894804aa0dc2a1da9adacf6e5013b8d", size = 3930500 }, - { url = "https://files.pythonhosted.org/packages/dc/c4/42f22e0d343bf96d84fbab902e2821fdaa7318c54fd6add31be34e6c952d/pymssql-2.3.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e43e8276d7b2977672e4ecff5837d674ace36b646d19c943ce0383f95a48ffe3", size = 4277364 }, - { url = "https://files.pythonhosted.org/packages/e9/90/61b1286b749b6e9fb96a5219e8e9642d3e8300f2e94d66602fa99ecf98bd/pymssql-2.3.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:6dbc315df97bc98a0af2447f44d52e51fd6af892f985db09abc49f24ddb19f3b", size = 4713395 }, - { url = "https://files.pythonhosted.org/packages/3c/fb/fab148cc6ccbebe56a20413927796f536ed13b71e77cdb0d9d53458d31d8/pymssql-2.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d6dd05274ebaee7dda6d86fe4773c5cc91962e6c163c443cb4746c8c678037f", size = 2802822 }, - { url = "https://files.pythonhosted.org/packages/b2/24/9c54e1c58522973bff59caaaae92ffbbe4e6d8a5d782aa02030940a009f0/pymssql-2.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2091f8afb1bff4f398cbd4bb28690e9e63c88f793cd13760a8a7f366525dca0f", size = 2902371 }, - { url = "https://files.pythonhosted.org/packages/b9/69/515b29102d9969b4d25d3127e4b8a1df5a1185be3ed4f83a21291560b368/pymssql-2.3.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2afa69efcf26b8dd960931d4092ad0f0bf2cc92e4bc71ffc10c83ffaebba234d", size = 4014679 }, - { url = "https://files.pythonhosted.org/packages/28/e1/a309673a01c946b1506843b68e7231aa8369cfac1ee89db9004848d56e34/pymssql-2.3.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f59e2c17a19c042782daf41f770f8e63f30dab238b8d77aa51060a735bdb9ac4", size = 4036000 }, - { url = "https://files.pythonhosted.org/packages/83/26/ceab1deed7fce9c335ab4bf41401b5bff50dc47fd02a6c78e8b815616233/pymssql-2.3.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ecc8d8a35dd319e33f4ead45e9843ccaf2353c4c2d82bd17016d4d8f2ee41a79", size = 4562300 }, - { url = "https://files.pythonhosted.org/packages/cc/66/0bf929d6adbd053b43f82c1d0002908123e3614cf782e02353acd18272fd/pymssql-2.3.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dd3c22370652f643d370ab14d6d5b5bde85fb4b43bca1eca6f1105e4218be245", size = 4774300 }, - { url = "https://files.pythonhosted.org/packages/b1/7b/520fc74b072a09af20faa5fb2de988cae5be150611a15f51a96d4c8adbc2/pymssql-2.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:48ea563fd02f25439fe054979ebdb469fbcc15dffdc2c67388b24dca195da313", size = 2037450 }, +sdist = { url = "https://files.pythonhosted.org/packages/83/35/5a0b79369e42fffd5c04e4e74fa90ef034cc5c3f314e14f6d58cac646ccf/pymssql-2.3.4.tar.gz", hash = "sha256:117c82d7aa9021171aa9be98368475519f33d9c32073cdcf9b0d76231abc6436", size = 184604, upload-time = "2025-04-02T02:08:43.503Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/c1/9624556dfc8e72f72c2e2ef6d754e7833eb2ea3ba7673696c4cc601bcea9/pymssql-2.3.4-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:cec30403e10f7e8135c8aea9c764b1f1fc40b64d5d957802c3d537fdb34677e9", size = 2806104, upload-time = "2025-04-02T02:09:11.926Z" }, + { url = "https://files.pythonhosted.org/packages/1b/d3/6127c0d7d66e166ab18be0d02354486062e21f9d5bb4f170925118b42776/pymssql-2.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35cf87fcd0537272b35a5a683597996fe96bee4554d1944fe990c51d7dcb4143", size = 3927321, upload-time = "2025-04-02T03:07:54.233Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e9/63aee4c65123af29039c1ac86a71d34bb4b2aac2311325cedfbb1a22d6da/pymssql-2.3.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fdfa946c5c08322dd321a99fff0fe36de63e243a5e525d4935cbf1df4072cda", size = 3933920, upload-time = "2025-04-02T02:13:13.198Z" }, + { url = "https://files.pythonhosted.org/packages/d8/51/3be7830c19a193c111e882ce6f30be82de5c196a57c9ef15ab7d7e5955a5/pymssql-2.3.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46083224df49a2dbf76f8bd4989cfbabf92e0d381fdcb89539b931d61a265b59", size = 4279543, upload-time = "2025-04-02T02:12:42.467Z" }, + { url = "https://files.pythonhosted.org/packages/52/87/269cd50837ed827c37273a62e8445458eab94c873ffd27200c20498093be/pymssql-2.3.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:825aec308d258ece4ebebc7a0844276d796024a88775b2c11c128969605c055d", size = 4717796, upload-time = "2025-04-02T02:13:01.96Z" }, + { url = "https://files.pythonhosted.org/packages/b4/ab/2fa3ed3c5471f7afa5c0e9f14b9820993d55ffdbefb1a1a8dd8a417e33e7/pymssql-2.3.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8746b14a836176ac8dbbed951a5bcfb4c32377f167ae51e2fe3bd170fbf838cb", size = 4015984, upload-time = "2025-04-02T02:15:10.389Z" }, + { url = "https://files.pythonhosted.org/packages/38/85/95d7ada9ed26890585de6901878b3e1e2d0b13568dc033522a2d2bf85aeb/pymssql-2.3.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:339ac869543b0f0658bd5a6337c7efe87010ded12b69042bc67b716b117b5ce5", size = 4034457, upload-time = "2025-04-02T02:13:39.826Z" }, + { url = "https://files.pythonhosted.org/packages/d0/4c/fdd9416b6f1e85a88eff31ba12a885d3313a2ca00763766301e80cca9928/pymssql-2.3.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0951c1d17e523dfb22abca653a98df4bec2c6a8a75fa641206c72a5c0d3b1253", size = 4564119, upload-time = "2025-04-02T02:15:02.001Z" }, + { url = "https://files.pythonhosted.org/packages/24/86/fc7352b38179e52ad6271f20bfd6a695dfd0a34e6da96f8a4a00e7436e94/pymssql-2.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cd1eb757bba516e45dd055edc61aee0cfe540b93e8da1de8bded16220ac1a19", size = 4781324, upload-time = "2025-04-02T02:13:51.901Z" }, + { url = "https://files.pythonhosted.org/packages/68/3d/c3e754b309a26e778ec461d40b1489ce83de46ec55120a43b029a4726110/pymssql-2.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:523f17ec7b26040a1545b2674d6dde668529b5f930a8dae98379e28e74b1a2ce", size = 2037141, upload-time = "2025-04-02T02:28:05.166Z" }, + { url = "https://files.pythonhosted.org/packages/bb/20/fb8ab5d4a21be9d8b9e5661d7d1bf218bb04faa5c1a8ee5e9c2dc3d6f98d/pymssql-2.3.4-cp311-cp311-macosx_13_0_universal2.whl", hash = "sha256:70cbf00ef172f864f3334666c824bf9a1c7c0dffc9319263e7fd6ac097ed98cb", size = 3102701, upload-time = "2025-04-02T02:10:29.325Z" }, + { url = "https://files.pythonhosted.org/packages/5a/12/9eca79b2b55f220029bdb1009b5e66fedfb2d6a82b1868049220cb1a518a/pymssql-2.3.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a417eeab6b7000777db5bcecd391f13d9fa8ec082994650ea9327edafba4a30", size = 4076253, upload-time = "2025-04-02T03:07:56.805Z" }, + { url = "https://files.pythonhosted.org/packages/55/c4/f8bf22f696992887146015790fe5f418cff808810fe33d7704b519c350e2/pymssql-2.3.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0d10384c428b92f16d46eaeb9f14976e768a22083b68d646e6659b514571d37", size = 4064397, upload-time = "2025-04-02T02:13:14.573Z" }, + { url = "https://files.pythonhosted.org/packages/26/dc/90eb4178768e5e1a5afb128887daffa206615f0953d3e1513e4af4d91d56/pymssql-2.3.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:318de31ee24ee417df7d454aa75240cef806a029996259c5820057eff4d87fb0", size = 4422625, upload-time = "2025-04-02T02:12:44.217Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1a/820066ddbc46f1d5f084e2a0aeb830bf8222cd1b9d1fdc7df7a8b7fc80ec/pymssql-2.3.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:502b4b6df757fbe1196eba204d06fb4b55b4fab0019eb23b2dccd51c2ae149a5", size = 4879015, upload-time = "2025-04-02T02:13:03.368Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7c/dbacd3da9c494afebd09de8a10ab6241654586be202d029c75628957cd99/pymssql-2.3.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:707996a9bee34e2fb9cc87f0d64b87a527884ab6b7dd19496e676b42527fb039", size = 4155544, upload-time = "2025-04-02T02:15:11.693Z" }, + { url = "https://files.pythonhosted.org/packages/d4/f4/f87086a2580fd9bf8df4cae940b2d6daccb61ab57ce2feac7fe0ae4c4c23/pymssql-2.3.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5de0c70701736a815facc4d1cb943293829b7c5994c6c50bbc9abdf138cf1e4", size = 4188664, upload-time = "2025-04-02T02:13:41.566Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1d/ed047510378bdf7dadd7d5f4373cff4179135a5c0e561fe15ad00c0b8870/pymssql-2.3.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e1087ad97a10db3f6cc387da9fcbccdbf458054b54f793d9aa61f0da69e32e15", size = 4723365, upload-time = "2025-04-02T02:15:03.642Z" }, + { url = "https://files.pythonhosted.org/packages/3c/79/2dd758ea7f6dc0d4639c8ba93b46b7a18d54e7f57e9ad82c441cba101c23/pymssql-2.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:107e1b5efc42376b2426fcfadaad2b559d90ba55f634abd1af551e8c88aa9252", size = 4951520, upload-time = "2025-04-02T02:13:53.869Z" }, + { url = "https://files.pythonhosted.org/packages/8b/b6/a54afeb5df87fc22add90d5d0076cb3ece19b6d6c68b8826400269fab316/pymssql-2.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:e131c6148dd25a89f666ae6156a8a95a6526628955a3cd8326ccf1cba4183d64", size = 2037972, upload-time = "2025-04-02T02:20:18.979Z" }, + { url = "https://files.pythonhosted.org/packages/bc/89/5a7a4b27ee44b2dc4708de7e897311cb17f15e7c983c299e8bf97ebf98d1/pymssql-2.3.4-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:809b75aaeb9bcd061230bace41e275f80f464f70fcbf5dde2ba7ba8f0eea5298", size = 3075736, upload-time = "2025-04-02T02:11:44.347Z" }, + { url = "https://files.pythonhosted.org/packages/43/f9/19bbb0026a47043fb239e821e10a75304b12ba986ce4af71cf8986af411c/pymssql-2.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48ab1ee04754fb8ce703b6c154e54fde4f6c7f440766d397b101b748123a12df", size = 4019433, upload-time = "2025-04-02T03:07:58.222Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ac/3aca13f1f527299db4adef594fb9f14d47d68de91b93a220a67391b8ec87/pymssql-2.3.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e22bb4d5aed85b084e3b9fb5ae3463301dd69c17703cfef72e0aed746452cc9", size = 3993550, upload-time = "2025-04-02T02:13:16.433Z" }, + { url = "https://files.pythonhosted.org/packages/b9/93/879d92f61afb974f69b9186b16ee6a97adff2abc82777e3b66c9c9efb179/pymssql-2.3.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2c1c8d3632630d52387e5b5b4483027494b5cb8f65401573715b74e7a3f16e5", size = 4381934, upload-time = "2025-04-02T02:12:45.424Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a6/923769b6dbb4e3a4c07a867e0c7fa8e4b230f675095cd7109d4e3eb9ddf0/pymssql-2.3.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f7f245acbdf89b96a41513ef0214b55a3ba2824f1f3119dd1945443b6cac78d3", size = 4849674, upload-time = "2025-04-02T02:13:05.245Z" }, + { url = "https://files.pythonhosted.org/packages/7a/2d/c787f061dcd0603905bf8085dda9cddb8c3c03b18d9239d5d18c953eebba/pymssql-2.3.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9484485fb847eb67f828459b0f4857c9725b20c517c2b7f88a9788fd72b76a6a", size = 4076649, upload-time = "2025-04-02T02:15:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/c1/a2/e55d823e3ab21cf9fc88e4e2424936899392d9d2e6569d5bcce063f84dac/pymssql-2.3.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a0716482cd5ecce07230925593cefd9137959c18aca4c92fc24c243d3c20e38", size = 4139477, upload-time = "2025-04-02T02:13:42.91Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7c/0fec6587b38081d0d0fca4f9ad31e85ec6c5791879e57f0e559ec6be4d3d/pymssql-2.3.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ba4f988674b361709821c8173a6471aa6e47ee6e45b5a8e30d4dcbde1f62fb0f", size = 4653837, upload-time = "2025-04-02T02:15:05.102Z" }, + { url = "https://files.pythonhosted.org/packages/5f/7c/77d0251f4b5ad5690226a93547fc8279c1c48bd14e3ccc820f5c580a3b73/pymssql-2.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:51b8ebfbd7d14d5e7c65e76ffaf31584ffabe9fb1bfd2a85f529bd707512e39d", size = 4910914, upload-time = "2025-04-02T02:13:55.446Z" }, + { url = "https://files.pythonhosted.org/packages/4f/22/1b2ef85804872a5940010d3c012722356af1fa24f8ba6f419c0260881032/pymssql-2.3.4-cp312-cp312-win32.whl", hash = "sha256:c8f5718f5e7d2623eaf35e025d5fa288c5789916809a89f00b42346b888673da", size = 1337991, upload-time = "2025-04-02T02:29:43.394Z" }, + { url = "https://files.pythonhosted.org/packages/0f/43/c98f34e7b3cd45653fb233a4bee83bffca0cf5e78c290c291cec34faac21/pymssql-2.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:d72b38b5ba66a4072c680447099bb63ac35d0425e9a29ff91b048e563b999be5", size = 2021760, upload-time = "2025-04-02T02:28:06.757Z" }, + { url = "https://files.pythonhosted.org/packages/63/58/90dbe299359c547fcb037d4a12f2146916213b99a245d01efdf5ade52910/pymssql-2.3.4-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:36ede0bc046e18cb0a5f043828bc441c80ffb2aa4606ce0cfcbf2a3d71266f0a", size = 3064581, upload-time = "2025-04-02T02:09:43.911Z" }, + { url = "https://files.pythonhosted.org/packages/4b/7c/15e75a74de5e392ea1a9456261632cc312c873f28ac2f9ef39dfefac8cd2/pymssql-2.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d247114853ada387415df303d24d2e990596ce28b23f5b59c46d852cfea0f2ad", size = 4013283, upload-time = "2025-04-02T03:08:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/2a/29/b9f08676145c3086db11c55b40bd58dfb0d775853f7280c1b2e15fc44fc2/pymssql-2.3.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79881cbe1a5826ddb959ccf8add015e5b82e6afbbf9cf5e281bd794278b2c2eb", size = 3996475, upload-time = "2025-04-02T02:13:18.212Z" }, + { url = "https://files.pythonhosted.org/packages/ab/cb/54ca973c666e8402f3bf7feaf7e2037b7c80dbd732be67e224f95cb6a1cc/pymssql-2.3.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bfcd63280b0f74124241092bdfd7889925342bcb58b4cde299e4c91cec55436", size = 4377615, upload-time = "2025-04-02T02:12:46.677Z" }, + { url = "https://files.pythonhosted.org/packages/c1/f2/973dfded45e0df9dcf72bc1b7254cefd5ffb1492f314822020d3c066421f/pymssql-2.3.4-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f3b784563f2b24c4d3f0e250fa9cfe59a22791539725f4d5059139c66f072a14", size = 4839647, upload-time = "2025-04-02T02:13:07.216Z" }, + { url = "https://files.pythonhosted.org/packages/91/cb/9d9342f0936ff6d58a59446e7449f93cc1134e59f3a1ec075e7b364e82a6/pymssql-2.3.4-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a54a018215cf0cffbaaa6edaa02215ef19fa9c9ff6a2c172e8fa563f577e2e91", size = 4079413, upload-time = "2025-04-02T02:15:14.592Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f1/79866247539144dcc9e44e9f8ad700bdc78c286863f37d879d71bbfd2c94/pymssql-2.3.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:14f2474fda3c57bc95b9ba146552463571fe77c816cbfb2e64344528d9afb755", size = 4141187, upload-time = "2025-04-02T02:13:44.711Z" }, + { url = "https://files.pythonhosted.org/packages/9c/2d/c187ebcaeb2832cc7ac85034897eb920b361fd63bf011a5d02b31fe2f840/pymssql-2.3.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:145dc2b73e4fe115e6176866245921ce95a216a8d6cb0d9420c2e05ee2a911a9", size = 4661965, upload-time = "2025-04-02T02:15:06.727Z" }, + { url = "https://files.pythonhosted.org/packages/77/59/aae5ba396d1c603325112bf7106705e1781e4604381faa45ad55161f2b0f/pymssql-2.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e08f1bc9e4a914c82816e3e5270b53bead13d3444435fc7bddfff9cb302b9982", size = 4903978, upload-time = "2025-04-02T02:13:57.341Z" }, + { url = "https://files.pythonhosted.org/packages/3f/a9/25ea7056857aabbfd285c397084c571e4486f341ff8e8086b067bc2e2109/pymssql-2.3.4-cp313-cp313-win32.whl", hash = "sha256:e31b507f4669671e8bbdeecf1c1c2ed9c092953a1decfae5af656200a74195d1", size = 1337662, upload-time = "2025-04-02T02:21:12.84Z" }, + { url = "https://files.pythonhosted.org/packages/a8/17/66414aeb30a4c2a23d29b2b8715d20d23e57c3ac2dd7bfd6fee5aa093e07/pymssql-2.3.4-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:378cb74a67cb177d6864acd446e17afc7ebbc7b3cde9cfee04d7221ec1bc08ef", size = 2806568, upload-time = "2025-04-02T02:11:25.381Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e7/00a27e73300a172618d5b0cd2f910d4ef434d0c221aa2ff0a507a614ce34/pymssql-2.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ad790becb502b1a981fc83d922813303a1eac7867df62bda2ca12f41b73efd2", size = 3925998, upload-time = "2025-04-02T03:08:02.494Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fd/22275fbe8c2de5d0112b0809e444be922762a9f12a791ed49a8bec14e59b/pymssql-2.3.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b538838abef0bd45a0cf097dfe661a5b8894804aa0dc2a1da9adacf6e5013b8d", size = 3930500, upload-time = "2025-04-02T02:13:19.525Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c4/42f22e0d343bf96d84fbab902e2821fdaa7318c54fd6add31be34e6c952d/pymssql-2.3.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e43e8276d7b2977672e4ecff5837d674ace36b646d19c943ce0383f95a48ffe3", size = 4277364, upload-time = "2025-04-02T02:12:47.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/90/61b1286b749b6e9fb96a5219e8e9642d3e8300f2e94d66602fa99ecf98bd/pymssql-2.3.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:6dbc315df97bc98a0af2447f44d52e51fd6af892f985db09abc49f24ddb19f3b", size = 4713395, upload-time = "2025-04-02T02:13:08.514Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/fab148cc6ccbebe56a20413927796f536ed13b71e77cdb0d9d53458d31d8/pymssql-2.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d6dd05274ebaee7dda6d86fe4773c5cc91962e6c163c443cb4746c8c678037f", size = 2802822, upload-time = "2025-04-02T02:08:50.571Z" }, + { url = "https://files.pythonhosted.org/packages/b2/24/9c54e1c58522973bff59caaaae92ffbbe4e6d8a5d782aa02030940a009f0/pymssql-2.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2091f8afb1bff4f398cbd4bb28690e9e63c88f793cd13760a8a7f366525dca0f", size = 2902371, upload-time = "2025-04-02T02:08:41.497Z" }, + { url = "https://files.pythonhosted.org/packages/b9/69/515b29102d9969b4d25d3127e4b8a1df5a1185be3ed4f83a21291560b368/pymssql-2.3.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2afa69efcf26b8dd960931d4092ad0f0bf2cc92e4bc71ffc10c83ffaebba234d", size = 4014679, upload-time = "2025-04-02T02:15:17.185Z" }, + { url = "https://files.pythonhosted.org/packages/28/e1/a309673a01c946b1506843b68e7231aa8369cfac1ee89db9004848d56e34/pymssql-2.3.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f59e2c17a19c042782daf41f770f8e63f30dab238b8d77aa51060a735bdb9ac4", size = 4036000, upload-time = "2025-04-02T02:13:46.075Z" }, + { url = "https://files.pythonhosted.org/packages/83/26/ceab1deed7fce9c335ab4bf41401b5bff50dc47fd02a6c78e8b815616233/pymssql-2.3.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ecc8d8a35dd319e33f4ead45e9843ccaf2353c4c2d82bd17016d4d8f2ee41a79", size = 4562300, upload-time = "2025-04-02T02:15:08.608Z" }, + { url = "https://files.pythonhosted.org/packages/cc/66/0bf929d6adbd053b43f82c1d0002908123e3614cf782e02353acd18272fd/pymssql-2.3.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dd3c22370652f643d370ab14d6d5b5bde85fb4b43bca1eca6f1105e4218be245", size = 4774300, upload-time = "2025-04-02T02:13:58.892Z" }, + { url = "https://files.pythonhosted.org/packages/b1/7b/520fc74b072a09af20faa5fb2de988cae5be150611a15f51a96d4c8adbc2/pymssql-2.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:48ea563fd02f25439fe054979ebdb469fbcc15dffdc2c67388b24dca195da313", size = 2037450, upload-time = "2025-04-02T02:20:37.693Z" }, ] [[package]] name = "pymysql" version = "1.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/ce59b5e5ed4ce8512f879ff1fa5ab699d211ae2495f1adaa5fbba2a1eada/pymysql-1.1.1.tar.gz", hash = "sha256:e127611aaf2b417403c60bf4dc570124aeb4a57f5f37b8e95ae399a42f904cd0", size = 47678 } +sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/ce59b5e5ed4ce8512f879ff1fa5ab699d211ae2495f1adaa5fbba2a1eada/pymysql-1.1.1.tar.gz", hash = "sha256:e127611aaf2b417403c60bf4dc570124aeb4a57f5f37b8e95ae399a42f904cd0", size = 47678, upload-time = "2024-05-21T11:03:43.722Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/94/e4181a1f6286f545507528c78016e00065ea913276888db2262507693ce5/PyMySQL-1.1.1-py3-none-any.whl", hash = "sha256:4de15da4c61dc132f4fb9ab763063e693d521a80fd0e87943b9a453dd4c19d6c", size = 44972 }, + { url = "https://files.pythonhosted.org/packages/0c/94/e4181a1f6286f545507528c78016e00065ea913276888db2262507693ce5/PyMySQL-1.1.1-py3-none-any.whl", hash = "sha256:4de15da4c61dc132f4fb9ab763063e693d521a80fd0e87943b9a453dd4c19d6c", size = 44972, upload-time = "2024-05-21T11:03:41.216Z" }, ] [[package]] name = "pyodbc" version = "5.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a0/36/a1ac7d23a1611e7ccd4d27df096f3794e8d1e7faa040260d9d41b6fc3185/pyodbc-5.2.0.tar.gz", hash = "sha256:de8be39809c8ddeeee26a4b876a6463529cd487a60d1393eb2a93e9bcd44a8f5", size = 116908 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/30/01/05c4a4ec122c4a8a37fa1be5bdbf6fb23724a2ee3b1b771bb46f710158a9/pyodbc-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eb0850e3e3782f57457feed297e220bb20c3e8fd7550d7a6b6bb96112bd9b6fe", size = 72483 }, - { url = "https://files.pythonhosted.org/packages/73/22/ba718cc5508bdfbb53e1906018d7f597be37241c769dda8a48f52af96fe3/pyodbc-5.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0dae0fb86078c87acf135dbe5afd3c7d15d52ab0db5965c44159e84058c3e2fb", size = 71794 }, - { url = "https://files.pythonhosted.org/packages/24/e4/9d859ea3642059c10a6644a00ccb1f8b8e02c1e4f49ab34250db1273c2c5/pyodbc-5.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6493b9c7506ca964b80ad638d0dc82869df7058255d71f04fdd1405e88bcb36b", size = 332850 }, - { url = "https://files.pythonhosted.org/packages/b9/a7/98c3555c10cfeb343ec7eea69ecb17476aa3ace72131ea8a4a1f8250318c/pyodbc-5.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04de873607fb960e71953c164c83e8e5d9291ce0d69e688e54947b254b04902", size = 336009 }, - { url = "https://files.pythonhosted.org/packages/24/c1/d5b16dd62eb70f281bc90cdc1e3c46af7acda3f0f6afb34553206506ccb2/pyodbc-5.2.0-cp310-cp310-win32.whl", hash = "sha256:74135cb10c1dcdbd99fe429c61539c232140e62939fa7c69b0a373cc552e4a08", size = 62407 }, - { url = "https://files.pythonhosted.org/packages/f5/12/22c83669abee4ca5915aa89172cf1673b58ca05f44dabeb8b0bac9b7fecc/pyodbc-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:d287121eeaa562b9ab3d4c52fa77c793dfedd127049273eb882a05d3d67a8ce8", size = 68874 }, - { url = "https://files.pythonhosted.org/packages/8f/a2/5907ce319a571eb1e271d6a475920edfeacd92da1021bb2a15ed1b7f6ac1/pyodbc-5.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4627779f0a608b51ce2d2fe6d1d395384e65ca36248bf9dbb6d7cf2c8fda1cab", size = 72536 }, - { url = "https://files.pythonhosted.org/packages/e1/b8/bd438ab2bb9481615142784b0c9778079a87ae1bca7a0fe8aabfc088aa9f/pyodbc-5.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d997d3b6551273647825c734158ca8a6f682df269f6b3975f2499c01577ddec", size = 71825 }, - { url = "https://files.pythonhosted.org/packages/8b/82/cf71ae99b511a7f20c380ce470de233a0291fa3798afa74e0adc8fad1675/pyodbc-5.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5102007a8c78dd2fc1c1b6f6147de8cfc020f81013e4b46c33e66aaa7d1bf7b1", size = 342304 }, - { url = "https://files.pythonhosted.org/packages/43/ea/03fe042f4a390df05e753ddd21c6cab006baae1eee71ce230f6e2a883944/pyodbc-5.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e3cbc7075a46c411b531ada557c4aef13d034060a70077717124cabc1717e2d", size = 346186 }, - { url = "https://files.pythonhosted.org/packages/f9/80/48178bb50990147adb72ec9e377e94517a0dfaf2f2a6e3fe477d9a33671f/pyodbc-5.2.0-cp311-cp311-win32.whl", hash = "sha256:de1ee7ec2eb326b7be5e2c4ce20d472c5ef1a6eb838d126d1d26779ff5486e49", size = 62418 }, - { url = "https://files.pythonhosted.org/packages/7c/6b/f0ad7d8a535d58f35f375ffbf367c68d0ec54452a431d23b0ebee4cd44c6/pyodbc-5.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:113f904b9852c12f10c7a3288f5a3563ecdbbefe3ccc829074a9eb8255edcd29", size = 68871 }, - { url = "https://files.pythonhosted.org/packages/26/26/104525b728fedfababd3143426b9d0008c70f0d604a3bf5d4773977d83f4/pyodbc-5.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be43d1ece4f2cf4d430996689d89a1a15aeb3a8da8262527e5ced5aee27e89c3", size = 73014 }, - { url = "https://files.pythonhosted.org/packages/4f/7d/bb632488b603bcd2a6753b858e8bc7dd56146dd19bd72003cc09ae6e3fc0/pyodbc-5.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9f7badd0055221a744d76c11440c0856fd2846ed53b6555cf8f0a8893a3e4b03", size = 72515 }, - { url = "https://files.pythonhosted.org/packages/ab/38/a1b9bfe5a7062672268553c2d6ff93676173b0fb4bd583e8c4f74a0e296f/pyodbc-5.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad633c52f4f4e7691daaa2278d6e6ebb2fe4ae7709e610e22c7dd1a1d620cf8b", size = 348561 }, - { url = "https://files.pythonhosted.org/packages/71/82/ddb1c41c682550116f391aa6cab2052910046a30d63014bbe6d09c4958f4/pyodbc-5.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97d086a8f7a302b74c9c2e77bedf954a603b19168af900d4d3a97322e773df63", size = 353962 }, - { url = "https://files.pythonhosted.org/packages/e5/29/fec0e739d0c1cab155843ed71d0717f5e1694effe3f28d397168f48bcd92/pyodbc-5.2.0-cp312-cp312-win32.whl", hash = "sha256:0e4412f8e608db2a4be5bcc75f9581f386ed6a427dbcb5eac795049ba6fc205e", size = 63050 }, - { url = "https://files.pythonhosted.org/packages/21/7f/3a47e022a97b017ffb73351a1061e4401bcb5aa4fc0162d04f4e5452e4fc/pyodbc-5.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:b1f5686b142759c5b2bdbeaa0692622c2ebb1f10780eb3c174b85f5607fbcf55", size = 69485 }, - { url = "https://files.pythonhosted.org/packages/90/be/e5f8022ec57a7ea6aa3717a3f307a44c3b012fce7ad6ec91aad3e2a56978/pyodbc-5.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:26844d780045bbc3514d5c2f0d89e7fda7df7db0bd24292eb6902046f5730885", size = 72982 }, - { url = "https://files.pythonhosted.org/packages/5c/0e/71111e4f53936b0b99731d9b6acfc8fc95660533a1421447a63d6e519112/pyodbc-5.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:26d2d8fd53b71204c755abc53b0379df4e23fd9a40faf211e1cb87e8a32470f0", size = 72515 }, - { url = "https://files.pythonhosted.org/packages/a5/09/3c06bbc1ebb9ae15f53cefe10774809b67da643883287ba1c44ba053816a/pyodbc-5.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a27996b6d27e275dfb5fe8a34087ba1cacadfd1439e636874ef675faea5149d9", size = 347470 }, - { url = "https://files.pythonhosted.org/packages/a4/35/1c7efd4665e7983169d20175014f68578e0edfcbc4602b0bafcefa522c4a/pyodbc-5.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf42c4bd323b8fd01f1cd900cca2d09232155f9b8f0b9bcd0be66763588ce64", size = 353025 }, - { url = "https://files.pythonhosted.org/packages/6d/c9/736d07fa33572abdc50d858fd9e527d2c8281f3acbb90dff4999a3662edd/pyodbc-5.2.0-cp313-cp313-win32.whl", hash = "sha256:207f16b7e9bf09c591616429ebf2b47127e879aad21167ac15158910dc9bbcda", size = 63052 }, - { url = "https://files.pythonhosted.org/packages/73/2a/3219c8b7fa3788fc9f27b5fc2244017223cf070e5ab370f71c519adf9120/pyodbc-5.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:96d3127f28c0dacf18da7ae009cd48eac532d3dcc718a334b86a3c65f6a5ef5c", size = 69486 }, - { url = "https://files.pythonhosted.org/packages/7c/1a/bec4dd9f65a7c0c1a75641119351f0f402c721bbcea3c4eb684868259467/pyodbc-5.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e8f4ee2c523bbe85124540ffad62a3b62ae481f012e390ef93e0602b6302e5e", size = 72440 }, - { url = "https://files.pythonhosted.org/packages/df/2f/62cce82e4547dc8c4ac3174403e24ed31bdb10bb69ad30e1bb362b960877/pyodbc-5.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:057b8ede91b21d9f0ef58210d1ca1aad704e641ca68ac6b02f109d86b61d7402", size = 71902 }, - { url = "https://files.pythonhosted.org/packages/f0/1a/54d9595f0471c15b1de4766ec3436763aeef980740d484d629afa778c506/pyodbc-5.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0ecbc7067467df95c9b8bd38fb2682c4a13a3402d77dccaddf1e145cea8cc0", size = 329596 }, - { url = "https://files.pythonhosted.org/packages/2d/3a/88bc3bb8c15aefaf98bfadd51dae2fe492486daeb04911d8cf0a6d8dd884/pyodbc-5.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b7f8324fa01c09fe4843ad8adb0b131299ef263a1fb9e63830c9cd1d5c45e4", size = 333575 }, - { url = "https://files.pythonhosted.org/packages/60/75/aedf6d10f66b22302dc3f0181cbef0cc5789f2c2a658343f10ae72f51190/pyodbc-5.2.0-cp39-cp39-win32.whl", hash = "sha256:600ef6f562f609f5612ffaa8a93827249150aa3030c867937c87b24a1608967e", size = 62379 }, - { url = "https://files.pythonhosted.org/packages/d9/9c/b1e367b07904a52f22b8707979bcbda1b5a6056c46e67e0a66241d8138aa/pyodbc-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:b77556349746fb90416a48bd114cd7323f7e2559a4b263dada935f9b406ba59b", size = 68951 }, +sdist = { url = "https://files.pythonhosted.org/packages/a0/36/a1ac7d23a1611e7ccd4d27df096f3794e8d1e7faa040260d9d41b6fc3185/pyodbc-5.2.0.tar.gz", hash = "sha256:de8be39809c8ddeeee26a4b876a6463529cd487a60d1393eb2a93e9bcd44a8f5", size = 116908, upload-time = "2024-10-16T01:40:13.425Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/01/05c4a4ec122c4a8a37fa1be5bdbf6fb23724a2ee3b1b771bb46f710158a9/pyodbc-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eb0850e3e3782f57457feed297e220bb20c3e8fd7550d7a6b6bb96112bd9b6fe", size = 72483, upload-time = "2024-10-16T01:39:23.697Z" }, + { url = "https://files.pythonhosted.org/packages/73/22/ba718cc5508bdfbb53e1906018d7f597be37241c769dda8a48f52af96fe3/pyodbc-5.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0dae0fb86078c87acf135dbe5afd3c7d15d52ab0db5965c44159e84058c3e2fb", size = 71794, upload-time = "2024-10-16T01:39:25.372Z" }, + { url = "https://files.pythonhosted.org/packages/24/e4/9d859ea3642059c10a6644a00ccb1f8b8e02c1e4f49ab34250db1273c2c5/pyodbc-5.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6493b9c7506ca964b80ad638d0dc82869df7058255d71f04fdd1405e88bcb36b", size = 332850, upload-time = "2024-10-16T01:39:27.789Z" }, + { url = "https://files.pythonhosted.org/packages/b9/a7/98c3555c10cfeb343ec7eea69ecb17476aa3ace72131ea8a4a1f8250318c/pyodbc-5.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04de873607fb960e71953c164c83e8e5d9291ce0d69e688e54947b254b04902", size = 336009, upload-time = "2024-10-16T01:39:29.694Z" }, + { url = "https://files.pythonhosted.org/packages/24/c1/d5b16dd62eb70f281bc90cdc1e3c46af7acda3f0f6afb34553206506ccb2/pyodbc-5.2.0-cp310-cp310-win32.whl", hash = "sha256:74135cb10c1dcdbd99fe429c61539c232140e62939fa7c69b0a373cc552e4a08", size = 62407, upload-time = "2024-10-16T01:39:31.894Z" }, + { url = "https://files.pythonhosted.org/packages/f5/12/22c83669abee4ca5915aa89172cf1673b58ca05f44dabeb8b0bac9b7fecc/pyodbc-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:d287121eeaa562b9ab3d4c52fa77c793dfedd127049273eb882a05d3d67a8ce8", size = 68874, upload-time = "2024-10-16T01:39:33.325Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a2/5907ce319a571eb1e271d6a475920edfeacd92da1021bb2a15ed1b7f6ac1/pyodbc-5.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4627779f0a608b51ce2d2fe6d1d395384e65ca36248bf9dbb6d7cf2c8fda1cab", size = 72536, upload-time = "2024-10-16T01:39:34.715Z" }, + { url = "https://files.pythonhosted.org/packages/e1/b8/bd438ab2bb9481615142784b0c9778079a87ae1bca7a0fe8aabfc088aa9f/pyodbc-5.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d997d3b6551273647825c734158ca8a6f682df269f6b3975f2499c01577ddec", size = 71825, upload-time = "2024-10-16T01:39:36.343Z" }, + { url = "https://files.pythonhosted.org/packages/8b/82/cf71ae99b511a7f20c380ce470de233a0291fa3798afa74e0adc8fad1675/pyodbc-5.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5102007a8c78dd2fc1c1b6f6147de8cfc020f81013e4b46c33e66aaa7d1bf7b1", size = 342304, upload-time = "2024-10-16T01:39:37.82Z" }, + { url = "https://files.pythonhosted.org/packages/43/ea/03fe042f4a390df05e753ddd21c6cab006baae1eee71ce230f6e2a883944/pyodbc-5.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e3cbc7075a46c411b531ada557c4aef13d034060a70077717124cabc1717e2d", size = 346186, upload-time = "2024-10-16T01:39:39.3Z" }, + { url = "https://files.pythonhosted.org/packages/f9/80/48178bb50990147adb72ec9e377e94517a0dfaf2f2a6e3fe477d9a33671f/pyodbc-5.2.0-cp311-cp311-win32.whl", hash = "sha256:de1ee7ec2eb326b7be5e2c4ce20d472c5ef1a6eb838d126d1d26779ff5486e49", size = 62418, upload-time = "2024-10-16T01:39:40.797Z" }, + { url = "https://files.pythonhosted.org/packages/7c/6b/f0ad7d8a535d58f35f375ffbf367c68d0ec54452a431d23b0ebee4cd44c6/pyodbc-5.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:113f904b9852c12f10c7a3288f5a3563ecdbbefe3ccc829074a9eb8255edcd29", size = 68871, upload-time = "2024-10-16T01:39:41.997Z" }, + { url = "https://files.pythonhosted.org/packages/26/26/104525b728fedfababd3143426b9d0008c70f0d604a3bf5d4773977d83f4/pyodbc-5.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be43d1ece4f2cf4d430996689d89a1a15aeb3a8da8262527e5ced5aee27e89c3", size = 73014, upload-time = "2024-10-16T01:39:43.332Z" }, + { url = "https://files.pythonhosted.org/packages/4f/7d/bb632488b603bcd2a6753b858e8bc7dd56146dd19bd72003cc09ae6e3fc0/pyodbc-5.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9f7badd0055221a744d76c11440c0856fd2846ed53b6555cf8f0a8893a3e4b03", size = 72515, upload-time = "2024-10-16T01:39:44.506Z" }, + { url = "https://files.pythonhosted.org/packages/ab/38/a1b9bfe5a7062672268553c2d6ff93676173b0fb4bd583e8c4f74a0e296f/pyodbc-5.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad633c52f4f4e7691daaa2278d6e6ebb2fe4ae7709e610e22c7dd1a1d620cf8b", size = 348561, upload-time = "2024-10-16T01:39:45.986Z" }, + { url = "https://files.pythonhosted.org/packages/71/82/ddb1c41c682550116f391aa6cab2052910046a30d63014bbe6d09c4958f4/pyodbc-5.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97d086a8f7a302b74c9c2e77bedf954a603b19168af900d4d3a97322e773df63", size = 353962, upload-time = "2024-10-16T01:39:47.254Z" }, + { url = "https://files.pythonhosted.org/packages/e5/29/fec0e739d0c1cab155843ed71d0717f5e1694effe3f28d397168f48bcd92/pyodbc-5.2.0-cp312-cp312-win32.whl", hash = "sha256:0e4412f8e608db2a4be5bcc75f9581f386ed6a427dbcb5eac795049ba6fc205e", size = 63050, upload-time = "2024-10-16T01:39:48.8Z" }, + { url = "https://files.pythonhosted.org/packages/21/7f/3a47e022a97b017ffb73351a1061e4401bcb5aa4fc0162d04f4e5452e4fc/pyodbc-5.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:b1f5686b142759c5b2bdbeaa0692622c2ebb1f10780eb3c174b85f5607fbcf55", size = 69485, upload-time = "2024-10-16T01:39:49.732Z" }, + { url = "https://files.pythonhosted.org/packages/90/be/e5f8022ec57a7ea6aa3717a3f307a44c3b012fce7ad6ec91aad3e2a56978/pyodbc-5.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:26844d780045bbc3514d5c2f0d89e7fda7df7db0bd24292eb6902046f5730885", size = 72982, upload-time = "2024-10-16T01:39:50.738Z" }, + { url = "https://files.pythonhosted.org/packages/5c/0e/71111e4f53936b0b99731d9b6acfc8fc95660533a1421447a63d6e519112/pyodbc-5.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:26d2d8fd53b71204c755abc53b0379df4e23fd9a40faf211e1cb87e8a32470f0", size = 72515, upload-time = "2024-10-16T01:39:51.86Z" }, + { url = "https://files.pythonhosted.org/packages/a5/09/3c06bbc1ebb9ae15f53cefe10774809b67da643883287ba1c44ba053816a/pyodbc-5.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a27996b6d27e275dfb5fe8a34087ba1cacadfd1439e636874ef675faea5149d9", size = 347470, upload-time = "2024-10-16T01:39:53.594Z" }, + { url = "https://files.pythonhosted.org/packages/a4/35/1c7efd4665e7983169d20175014f68578e0edfcbc4602b0bafcefa522c4a/pyodbc-5.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf42c4bd323b8fd01f1cd900cca2d09232155f9b8f0b9bcd0be66763588ce64", size = 353025, upload-time = "2024-10-16T01:39:55.124Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c9/736d07fa33572abdc50d858fd9e527d2c8281f3acbb90dff4999a3662edd/pyodbc-5.2.0-cp313-cp313-win32.whl", hash = "sha256:207f16b7e9bf09c591616429ebf2b47127e879aad21167ac15158910dc9bbcda", size = 63052, upload-time = "2024-10-16T01:39:56.565Z" }, + { url = "https://files.pythonhosted.org/packages/73/2a/3219c8b7fa3788fc9f27b5fc2244017223cf070e5ab370f71c519adf9120/pyodbc-5.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:96d3127f28c0dacf18da7ae009cd48eac532d3dcc718a334b86a3c65f6a5ef5c", size = 69486, upload-time = "2024-10-16T01:39:57.57Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1a/bec4dd9f65a7c0c1a75641119351f0f402c721bbcea3c4eb684868259467/pyodbc-5.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e8f4ee2c523bbe85124540ffad62a3b62ae481f012e390ef93e0602b6302e5e", size = 72440, upload-time = "2024-10-16T01:40:05.42Z" }, + { url = "https://files.pythonhosted.org/packages/df/2f/62cce82e4547dc8c4ac3174403e24ed31bdb10bb69ad30e1bb362b960877/pyodbc-5.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:057b8ede91b21d9f0ef58210d1ca1aad704e641ca68ac6b02f109d86b61d7402", size = 71902, upload-time = "2024-10-16T01:40:06.379Z" }, + { url = "https://files.pythonhosted.org/packages/f0/1a/54d9595f0471c15b1de4766ec3436763aeef980740d484d629afa778c506/pyodbc-5.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0ecbc7067467df95c9b8bd38fb2682c4a13a3402d77dccaddf1e145cea8cc0", size = 329596, upload-time = "2024-10-16T01:40:07.948Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3a/88bc3bb8c15aefaf98bfadd51dae2fe492486daeb04911d8cf0a6d8dd884/pyodbc-5.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b7f8324fa01c09fe4843ad8adb0b131299ef263a1fb9e63830c9cd1d5c45e4", size = 333575, upload-time = "2024-10-16T01:40:09.898Z" }, + { url = "https://files.pythonhosted.org/packages/60/75/aedf6d10f66b22302dc3f0181cbef0cc5789f2c2a658343f10ae72f51190/pyodbc-5.2.0-cp39-cp39-win32.whl", hash = "sha256:600ef6f562f609f5612ffaa8a93827249150aa3030c867937c87b24a1608967e", size = 62379, upload-time = "2024-10-16T01:40:11.412Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9c/b1e367b07904a52f22b8707979bcbda1b5a6056c46e67e0a66241d8138aa/pyodbc-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:b77556349746fb90416a48bd114cd7323f7e2559a4b263dada935f9b406ba59b", size = 68951, upload-time = "2024-10-16T01:40:12.374Z" }, ] [[package]] name = "pyright" -version = "1.1.399" +version = "1.1.400" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodeenv" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/db/9d/d91d5f6d26b2db95476fefc772e2b9a16d54c6bd0ea6bb5c1b6d635ab8b4/pyright-1.1.399.tar.gz", hash = "sha256:439035d707a36c3d1b443aec980bc37053fbda88158eded24b8eedcf1c7b7a1b", size = 3856954 } +sdist = { url = "https://files.pythonhosted.org/packages/6c/cb/c306618a02d0ee8aed5fb8d0fe0ecfed0dbf075f71468f03a30b5f4e1fe0/pyright-1.1.400.tar.gz", hash = "sha256:b8a3ba40481aa47ba08ffb3228e821d22f7d391f83609211335858bf05686bdb", size = 3846546, upload-time = "2025-04-24T12:55:18.907Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/b5/380380c9e7a534cb1783c70c3e8ac6d1193c599650a55838d0557586796e/pyright-1.1.399-py3-none-any.whl", hash = "sha256:55f9a875ddf23c9698f24208c764465ffdfd38be6265f7faf9a176e1dc549f3b", size = 5592584 }, + { url = "https://files.pythonhosted.org/packages/c8/a5/5d285e4932cf149c90e3c425610c5efaea005475d5f96f1bfdb452956c62/pyright-1.1.400-py3-none-any.whl", hash = "sha256:c80d04f98b5a4358ad3a35e241dbf2a408eee33a40779df365644f8054d2517e", size = 5563460, upload-time = "2025-04-24T12:55:17.002Z" }, ] [[package]] @@ -2718,9 +2737,9 @@ dependencies = [ { name = "pluggy" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, ] [[package]] @@ -2731,9 +2750,9 @@ dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694 }, + { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, ] [[package]] @@ -2744,23 +2763,23 @@ dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857 } +sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload-time = "2025-04-05T14:07:51.592Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841 }, + { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload-time = "2025-04-05T14:07:49.641Z" }, ] [[package]] name = "pytest-databases" -version = "0.12.2" +version = "0.12.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docker" }, { name = "filelock" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/65/12e1e5898d8843472b141eeffe30bb0d7a24ff492c24cb001d91bfc6f864/pytest_databases-0.12.2.tar.gz", hash = "sha256:2a617c5dce2f89b1c64b1391ffa393309e9bef3c6d14c8ca067056aa5d831403", size = 164715 } +sdist = { url = "https://files.pythonhosted.org/packages/e1/fd/9d40469289496163daf311750614f3400784ee83fd234b43567b33f720f7/pytest_databases-0.12.3.tar.gz", hash = "sha256:32ba09675aa478daa0e0f9b1a7cc0fcf1a100b690afc0507b1ccd6c708b08150", size = 164751, upload-time = "2025-04-21T04:47:07.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/dd/79aa47e0866c61940d5c5f88296b8666c84c2a37057c36dad604ed29990c/pytest_databases-0.12.2-py3-none-any.whl", hash = "sha256:8b772c2c5e83bdf8c6fd21712a2873fb9a07db5e7d91662973e393ea2327b0fd", size = 27322 }, + { url = "https://files.pythonhosted.org/packages/38/7c/13ed589f206fcff7c1655315a1fef241545af2a759d398ea1222c66cbf14/pytest_databases-0.12.3-py3-none-any.whl", hash = "sha256:254cb6e258b623c48c231fe4ae7cf0a1f174348c3e02a5d4f90aeaf992d3f8a4", size = 27319, upload-time = "2025-04-21T04:47:05.551Z" }, ] [package.optional-dependencies] @@ -2787,9 +2806,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814 } +sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863 }, + { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, ] [[package]] @@ -2801,9 +2820,9 @@ dependencies = [ { name = "pytest" }, { name = "termcolor" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/ac/5754f5edd6d508bc6493bc37d74b928f102a5fff82d9a80347e180998f08/pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a", size = 14992 } +sdist = { url = "https://files.pythonhosted.org/packages/f5/ac/5754f5edd6d508bc6493bc37d74b928f102a5fff82d9a80347e180998f08/pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a", size = 14992, upload-time = "2024-02-01T18:30:36.735Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/92/fb/889f1b69da2f13691de09a111c16c4766a433382d44aa0ecf221deded44a/pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd", size = 10171 }, + { url = "https://files.pythonhosted.org/packages/92/fb/889f1b69da2f13691de09a111c16c4766a433382d44aa0ecf221deded44a/pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd", size = 10171, upload-time = "2024-02-01T18:30:29.395Z" }, ] [[package]] @@ -2814,9 +2833,9 @@ dependencies = [ { name = "execnet" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/41/c4/3c310a19bc1f1e9ef50075582652673ef2bfc8cd62afef9585683821902f/pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d", size = 84060 } +sdist = { url = "https://files.pythonhosted.org/packages/41/c4/3c310a19bc1f1e9ef50075582652673ef2bfc8cd62afef9585683821902f/pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d", size = 84060, upload-time = "2024-04-28T19:29:54.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/82/1d96bf03ee4c0fdc3c0cbe61470070e659ca78dc0086fb88b66c185e2449/pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", size = 46108 }, + { url = "https://files.pythonhosted.org/packages/6d/82/1d96bf03ee4c0fdc3c0cbe61470070e659ca78dc0086fb88b66c185e2449/pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", size = 46108, upload-time = "2024-04-28T19:29:52.813Z" }, ] [[package]] @@ -2826,18 +2845,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] [[package]] name = "python-dotenv" version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920 } +sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 }, + { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" }, ] [[package]] @@ -2845,73 +2864,73 @@ name = "pywin32" version = "310" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/da/a5f38fffbba2fb99aa4aa905480ac4b8e83ca486659ac8c95bce47fb5276/pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1", size = 8848240 }, - { url = "https://files.pythonhosted.org/packages/aa/fe/d873a773324fa565619ba555a82c9dabd677301720f3660a731a5d07e49a/pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d", size = 9601854 }, - { url = "https://files.pythonhosted.org/packages/3c/84/1a8e3d7a15490d28a5d816efa229ecb4999cdc51a7c30dd8914f669093b8/pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213", size = 8522963 }, - { url = "https://files.pythonhosted.org/packages/f7/b1/68aa2986129fb1011dabbe95f0136f44509afaf072b12b8f815905a39f33/pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd", size = 8784284 }, - { url = "https://files.pythonhosted.org/packages/b3/bd/d1592635992dd8db5bb8ace0551bc3a769de1ac8850200cfa517e72739fb/pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c", size = 9520748 }, - { url = "https://files.pythonhosted.org/packages/90/b1/ac8b1ffce6603849eb45a91cf126c0fa5431f186c2e768bf56889c46f51c/pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582", size = 8455941 }, - { url = "https://files.pythonhosted.org/packages/6b/ec/4fdbe47932f671d6e348474ea35ed94227fb5df56a7c30cbbb42cd396ed0/pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d", size = 8796239 }, - { url = "https://files.pythonhosted.org/packages/e3/e5/b0627f8bb84e06991bea89ad8153a9e50ace40b2e1195d68e9dff6b03d0f/pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060", size = 9503839 }, - { url = "https://files.pythonhosted.org/packages/1f/32/9ccf53748df72301a89713936645a664ec001abd35ecc8578beda593d37d/pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966", size = 8459470 }, - { url = "https://files.pythonhosted.org/packages/1c/09/9c1b978ffc4ae53999e89c19c77ba882d9fce476729f23ef55211ea1c034/pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab", size = 8794384 }, - { url = "https://files.pythonhosted.org/packages/45/3c/b4640f740ffebadd5d34df35fecba0e1cfef8fde9f3e594df91c28ad9b50/pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e", size = 9503039 }, - { url = "https://files.pythonhosted.org/packages/b4/f4/f785020090fb050e7fb6d34b780f2231f302609dc964672f72bfaeb59a28/pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33", size = 8458152 }, - { url = "https://files.pythonhosted.org/packages/a2/cd/d09d434630edb6a0c44ad5079611279a67530296cfe0451e003de7f449ff/pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a", size = 8848099 }, - { url = "https://files.pythonhosted.org/packages/93/ff/2a8c10315ffbdee7b3883ac0d1667e267ca8b3f6f640d81d43b87a82c0c7/pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475", size = 9602031 }, + { url = "https://files.pythonhosted.org/packages/95/da/a5f38fffbba2fb99aa4aa905480ac4b8e83ca486659ac8c95bce47fb5276/pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1", size = 8848240, upload-time = "2025-03-17T00:55:46.783Z" }, + { url = "https://files.pythonhosted.org/packages/aa/fe/d873a773324fa565619ba555a82c9dabd677301720f3660a731a5d07e49a/pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d", size = 9601854, upload-time = "2025-03-17T00:55:48.783Z" }, + { url = "https://files.pythonhosted.org/packages/3c/84/1a8e3d7a15490d28a5d816efa229ecb4999cdc51a7c30dd8914f669093b8/pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213", size = 8522963, upload-time = "2025-03-17T00:55:50.969Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b1/68aa2986129fb1011dabbe95f0136f44509afaf072b12b8f815905a39f33/pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd", size = 8784284, upload-time = "2025-03-17T00:55:53.124Z" }, + { url = "https://files.pythonhosted.org/packages/b3/bd/d1592635992dd8db5bb8ace0551bc3a769de1ac8850200cfa517e72739fb/pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c", size = 9520748, upload-time = "2025-03-17T00:55:55.203Z" }, + { url = "https://files.pythonhosted.org/packages/90/b1/ac8b1ffce6603849eb45a91cf126c0fa5431f186c2e768bf56889c46f51c/pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582", size = 8455941, upload-time = "2025-03-17T00:55:57.048Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ec/4fdbe47932f671d6e348474ea35ed94227fb5df56a7c30cbbb42cd396ed0/pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d", size = 8796239, upload-time = "2025-03-17T00:55:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/e3/e5/b0627f8bb84e06991bea89ad8153a9e50ace40b2e1195d68e9dff6b03d0f/pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060", size = 9503839, upload-time = "2025-03-17T00:56:00.8Z" }, + { url = "https://files.pythonhosted.org/packages/1f/32/9ccf53748df72301a89713936645a664ec001abd35ecc8578beda593d37d/pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966", size = 8459470, upload-time = "2025-03-17T00:56:02.601Z" }, + { url = "https://files.pythonhosted.org/packages/1c/09/9c1b978ffc4ae53999e89c19c77ba882d9fce476729f23ef55211ea1c034/pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab", size = 8794384, upload-time = "2025-03-17T00:56:04.383Z" }, + { url = "https://files.pythonhosted.org/packages/45/3c/b4640f740ffebadd5d34df35fecba0e1cfef8fde9f3e594df91c28ad9b50/pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e", size = 9503039, upload-time = "2025-03-17T00:56:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/b4/f4/f785020090fb050e7fb6d34b780f2231f302609dc964672f72bfaeb59a28/pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33", size = 8458152, upload-time = "2025-03-17T00:56:07.819Z" }, + { url = "https://files.pythonhosted.org/packages/a2/cd/d09d434630edb6a0c44ad5079611279a67530296cfe0451e003de7f449ff/pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a", size = 8848099, upload-time = "2025-03-17T00:55:42.415Z" }, + { url = "https://files.pythonhosted.org/packages/93/ff/2a8c10315ffbdee7b3883ac0d1667e267ca8b3f6f640d81d43b87a82c0c7/pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475", size = 9602031, upload-time = "2025-03-17T00:55:44.512Z" }, ] [[package]] name = "pyyaml" version = "6.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199 }, - { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758 }, - { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463 }, - { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280 }, - { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239 }, - { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802 }, - { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527 }, - { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052 }, - { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774 }, - { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, - { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, - { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, - { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, - { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, - { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, - { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, - { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, - { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, - { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777 }, - { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318 }, - { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891 }, - { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614 }, - { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360 }, - { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006 }, - { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577 }, - { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593 }, - { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312 }, +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, + { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777, upload-time = "2024-08-06T20:33:25.896Z" }, + { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318, upload-time = "2024-08-06T20:33:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891, upload-time = "2024-08-06T20:33:28.974Z" }, + { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614, upload-time = "2024-08-06T20:33:34.157Z" }, + { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360, upload-time = "2024-08-06T20:33:35.84Z" }, + { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006, upload-time = "2024-08-06T20:33:37.501Z" }, + { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577, upload-time = "2024-08-06T20:33:39.389Z" }, + { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593, upload-time = "2024-08-06T20:33:46.63Z" }, + { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312, upload-time = "2024-08-06T20:33:49.073Z" }, ] [[package]] @@ -2921,9 +2940,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "prompt-toolkit" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/b8/d16eb579277f3de9e56e5ad25280fab52fc5774117fb70362e8c2e016559/questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587", size = 26775 } +sdist = { url = "https://files.pythonhosted.org/packages/a8/b8/d16eb579277f3de9e56e5ad25280fab52fc5774117fb70362e8c2e016559/questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587", size = 26775, upload-time = "2024-12-29T11:49:17.802Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/3f/11dd4cd4f39e05128bfd20138faea57bec56f9ffba6185d276e3107ba5b2/questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec", size = 36747 }, + { url = "https://files.pythonhosted.org/packages/ad/3f/11dd4cd4f39e05128bfd20138faea57bec56f9ffba6185d276e3107ba5b2/questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec", size = 36747, upload-time = "2024-12-29T11:49:16.734Z" }, ] [[package]] @@ -2936,9 +2955,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, ] [[package]] @@ -2950,9 +2969,9 @@ dependencies = [ { name = "pygments" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078 } +sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229 }, + { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" }, ] [[package]] @@ -2964,18 +2983,18 @@ dependencies = [ { name = "rich" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/7a/4b78c5997f2a799a8c5c07f3b2145bbcda40115c4d35c76fbadd418a3c89/rich_click-1.8.8.tar.gz", hash = "sha256:547c618dea916620af05d4a6456da797fbde904c97901f44d2f32f89d85d6c84", size = 39066 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/7a/4b78c5997f2a799a8c5c07f3b2145bbcda40115c4d35c76fbadd418a3c89/rich_click-1.8.8.tar.gz", hash = "sha256:547c618dea916620af05d4a6456da797fbde904c97901f44d2f32f89d85d6c84", size = 39066, upload-time = "2025-03-09T23:20:31.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/69/963f0bf44a654f6465bdb66fb5a91051b0d7af9f742b5bd7202607165036/rich_click-1.8.8-py3-none-any.whl", hash = "sha256:205aabd5a98e64ab2c105dee9e368be27480ba004c7dfa2accd0ed44f9f1550e", size = 35747 }, + { url = "https://files.pythonhosted.org/packages/fa/69/963f0bf44a654f6465bdb66fb5a91051b0d7af9f742b5bd7202607165036/rich_click-1.8.8-py3-none-any.whl", hash = "sha256:205aabd5a98e64ab2c105dee9e368be27480ba004c7dfa2accd0ed44f9f1550e", size = 35747, upload-time = "2025-03-09T23:20:29.831Z" }, ] [[package]] name = "roman-numerals-py" version = "3.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017 } +sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017, upload-time = "2025-02-22T07:34:54.333Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742 }, + { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" }, ] [[package]] @@ -2985,9 +3004,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyasn1" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034 } +sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696 }, + { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, ] [[package]] @@ -2997,119 +3016,119 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruamel-yaml-clib", marker = "python_full_version < '3.13' and platform_python_implementation == 'CPython'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447 } +sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447, upload-time = "2025-01-06T14:08:51.334Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729 }, + { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729, upload-time = "2025-01-06T14:08:47.471Z" }, ] [[package]] name = "ruamel-yaml-clib" version = "0.2.12" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5", size = 131301 }, - { url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969", size = 633728 }, - { url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df", size = 722230 }, - { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712 }, - { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936 }, - { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580 }, - { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393 }, - { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326 }, - { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079 }, - { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224 }, - { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480 }, - { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068 }, - { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012 }, - { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352 }, - { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344 }, - { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498 }, - { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205 }, - { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185 }, - { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433 }, - { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362 }, - { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118 }, - { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497 }, - { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042 }, - { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831 }, - { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692 }, - { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777 }, - { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523 }, - { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011 }, - { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488 }, - { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066 }, - { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785 }, - { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017 }, - { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270 }, - { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059 }, - { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583 }, - { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190 }, - { url = "https://files.pythonhosted.org/packages/e5/46/ccdef7a84ad745c37cb3d9a81790f28fbc9adf9c237dba682017b123294e/ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987", size = 131834 }, - { url = "https://files.pythonhosted.org/packages/29/09/932360f30ad1b7b79f08757e0a6fb8c5392a52cdcc182779158fe66d25ac/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45", size = 636120 }, - { url = "https://files.pythonhosted.org/packages/a2/2a/5b27602e7a4344c1334e26bf4739746206b7a60a8acdba33a61473468b73/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519", size = 724914 }, - { url = "https://files.pythonhosted.org/packages/da/1c/23497017c554fc06ff5701b29355522cff850f626337fff35d9ab352cb18/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7", size = 689072 }, - { url = "https://files.pythonhosted.org/packages/68/e6/f3d4ff3223f9ea49c3b7169ec0268e42bd49f87c70c0e3e853895e4a7ae2/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285", size = 667091 }, - { url = "https://files.pythonhosted.org/packages/84/62/ead07043527642491e5011b143f44b81ef80f1025a96069b7210e0f2f0f3/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed", size = 699111 }, - { url = "https://files.pythonhosted.org/packages/52/b3/fe4d84446f7e4887e3bea7ceff0a7df23790b5ed625f830e79ace88ebefb/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7", size = 666365 }, - { url = "https://files.pythonhosted.org/packages/6e/b3/7feb99a00bfaa5c6868617bb7651308afde85e5a0b23cd187fe5de65feeb/ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12", size = 100863 }, - { url = "https://files.pythonhosted.org/packages/93/07/de635108684b7a5bb06e432b0930c5a04b6c59efe73bd966d8db3cc208f2/ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b", size = 118653 }, +sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315, upload-time = "2024-10-20T10:10:56.22Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5", size = 131301, upload-time = "2024-10-20T10:12:35.876Z" }, + { url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969", size = 633728, upload-time = "2024-10-20T10:12:37.858Z" }, + { url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df", size = 722230, upload-time = "2024-10-20T10:12:39.457Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712, upload-time = "2024-10-20T10:12:41.119Z" }, + { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936, upload-time = "2024-10-21T11:26:37.419Z" }, + { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580, upload-time = "2024-10-21T11:26:39.503Z" }, + { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393, upload-time = "2024-12-11T19:58:13.873Z" }, + { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326, upload-time = "2024-10-20T10:12:42.967Z" }, + { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079, upload-time = "2024-10-20T10:12:44.117Z" }, + { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224, upload-time = "2024-10-20T10:12:45.162Z" }, + { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480, upload-time = "2024-10-20T10:12:46.758Z" }, + { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068, upload-time = "2024-10-20T10:12:48.605Z" }, + { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012, upload-time = "2024-10-20T10:12:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352, upload-time = "2024-10-21T11:26:41.438Z" }, + { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344, upload-time = "2024-10-21T11:26:43.62Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498, upload-time = "2024-12-11T19:58:15.592Z" }, + { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205, upload-time = "2024-10-20T10:12:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185, upload-time = "2024-10-20T10:12:54.652Z" }, + { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433, upload-time = "2024-10-20T10:12:55.657Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362, upload-time = "2024-10-20T10:12:57.155Z" }, + { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118, upload-time = "2024-10-20T10:12:58.501Z" }, + { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497, upload-time = "2024-10-20T10:13:00.211Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042, upload-time = "2024-10-21T11:26:46.038Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831, upload-time = "2024-10-21T11:26:47.487Z" }, + { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692, upload-time = "2024-12-11T19:58:17.252Z" }, + { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777, upload-time = "2024-10-20T10:13:01.395Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523, upload-time = "2024-10-20T10:13:02.768Z" }, + { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011, upload-time = "2024-10-20T10:13:04.377Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488, upload-time = "2024-10-20T10:13:05.906Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066, upload-time = "2024-10-20T10:13:07.26Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785, upload-time = "2024-10-20T10:13:08.504Z" }, + { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017, upload-time = "2024-10-21T11:26:48.866Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270, upload-time = "2024-10-21T11:26:50.213Z" }, + { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059, upload-time = "2024-12-11T19:58:18.846Z" }, + { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583, upload-time = "2024-10-20T10:13:09.658Z" }, + { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190, upload-time = "2024-10-20T10:13:10.66Z" }, + { url = "https://files.pythonhosted.org/packages/e5/46/ccdef7a84ad745c37cb3d9a81790f28fbc9adf9c237dba682017b123294e/ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987", size = 131834, upload-time = "2024-10-20T10:13:11.72Z" }, + { url = "https://files.pythonhosted.org/packages/29/09/932360f30ad1b7b79f08757e0a6fb8c5392a52cdcc182779158fe66d25ac/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45", size = 636120, upload-time = "2024-10-20T10:13:12.84Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2a/5b27602e7a4344c1334e26bf4739746206b7a60a8acdba33a61473468b73/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519", size = 724914, upload-time = "2024-10-20T10:13:14.605Z" }, + { url = "https://files.pythonhosted.org/packages/da/1c/23497017c554fc06ff5701b29355522cff850f626337fff35d9ab352cb18/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7", size = 689072, upload-time = "2024-10-20T10:13:15.939Z" }, + { url = "https://files.pythonhosted.org/packages/68/e6/f3d4ff3223f9ea49c3b7169ec0268e42bd49f87c70c0e3e853895e4a7ae2/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285", size = 667091, upload-time = "2024-10-21T11:26:52.274Z" }, + { url = "https://files.pythonhosted.org/packages/84/62/ead07043527642491e5011b143f44b81ef80f1025a96069b7210e0f2f0f3/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed", size = 699111, upload-time = "2024-10-21T11:26:54.294Z" }, + { url = "https://files.pythonhosted.org/packages/52/b3/fe4d84446f7e4887e3bea7ceff0a7df23790b5ed625f830e79ace88ebefb/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7", size = 666365, upload-time = "2024-12-11T19:58:20.444Z" }, + { url = "https://files.pythonhosted.org/packages/6e/b3/7feb99a00bfaa5c6868617bb7651308afde85e5a0b23cd187fe5de65feeb/ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12", size = 100863, upload-time = "2024-10-20T10:13:17.244Z" }, + { url = "https://files.pythonhosted.org/packages/93/07/de635108684b7a5bb06e432b0930c5a04b6c59efe73bd966d8db3cc208f2/ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b", size = 118653, upload-time = "2024-10-20T10:13:18.289Z" }, ] [[package]] name = "ruff" -version = "0.11.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d9/11/bcef6784c7e5d200b8a1f5c2ddf53e5da0efec37e6e5a44d163fb97e04ba/ruff-0.11.6.tar.gz", hash = "sha256:bec8bcc3ac228a45ccc811e45f7eb61b950dbf4cf31a67fa89352574b01c7d79", size = 4010053 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/1f/8848b625100ebcc8740c8bac5b5dd8ba97dd4ee210970e98832092c1635b/ruff-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:d84dcbe74cf9356d1bdb4a78cf74fd47c740bf7bdeb7529068f69b08272239a1", size = 10248105 }, - { url = "https://files.pythonhosted.org/packages/e0/47/c44036e70c6cc11e6ee24399c2a1e1f1e99be5152bd7dff0190e4b325b76/ruff-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9bc583628e1096148011a5d51ff3c836f51899e61112e03e5f2b1573a9b726de", size = 11001494 }, - { url = "https://files.pythonhosted.org/packages/ed/5b/170444061650202d84d316e8f112de02d092bff71fafe060d3542f5bc5df/ruff-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2959049faeb5ba5e3b378709e9d1bf0cab06528b306b9dd6ebd2a312127964a", size = 10352151 }, - { url = "https://files.pythonhosted.org/packages/ff/91/f02839fb3787c678e112c8865f2c3e87cfe1744dcc96ff9fc56cfb97dda2/ruff-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c5d4e30d9d0de7fedbfb3e9e20d134b73a30c1e74b596f40f0629d5c28a193", size = 10541951 }, - { url = "https://files.pythonhosted.org/packages/9e/f3/c09933306096ff7a08abede3cc2534d6fcf5529ccd26504c16bf363989b5/ruff-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4b9a4e1439f7d0a091c6763a100cef8fbdc10d68593df6f3cfa5abdd9246e", size = 10079195 }, - { url = "https://files.pythonhosted.org/packages/e0/0d/a87f8933fccbc0d8c653cfbf44bedda69c9582ba09210a309c066794e2ee/ruff-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5edf270223dd622218256569636dc3e708c2cb989242262fe378609eccf1308", size = 11698918 }, - { url = "https://files.pythonhosted.org/packages/52/7d/8eac0bd083ea8a0b55b7e4628428203441ca68cd55e0b67c135a4bc6e309/ruff-0.11.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f55844e818206a9dd31ff27f91385afb538067e2dc0beb05f82c293ab84f7d55", size = 12319426 }, - { url = "https://files.pythonhosted.org/packages/c2/dc/d0c17d875662d0c86fadcf4ca014ab2001f867621b793d5d7eef01b9dcce/ruff-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d8f782286c5ff562e4e00344f954b9320026d8e3fae2ba9e6948443fafd9ffc", size = 11791012 }, - { url = "https://files.pythonhosted.org/packages/f9/f3/81a1aea17f1065449a72509fc7ccc3659cf93148b136ff2a8291c4bc3ef1/ruff-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01c63ba219514271cee955cd0adc26a4083df1956d57847978383b0e50ffd7d2", size = 13949947 }, - { url = "https://files.pythonhosted.org/packages/61/9f/a3e34de425a668284e7024ee6fd41f452f6fa9d817f1f3495b46e5e3a407/ruff-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15adac20ef2ca296dd3d8e2bedc6202ea6de81c091a74661c3666e5c4c223ff6", size = 11471753 }, - { url = "https://files.pythonhosted.org/packages/df/c5/4a57a86d12542c0f6e2744f262257b2aa5a3783098ec14e40f3e4b3a354a/ruff-0.11.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4dd6b09e98144ad7aec026f5588e493c65057d1b387dd937d7787baa531d9bc2", size = 10417121 }, - { url = "https://files.pythonhosted.org/packages/58/3f/a3b4346dff07ef5b862e2ba06d98fcbf71f66f04cf01d375e871382b5e4b/ruff-0.11.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:45b2e1d6c0eed89c248d024ea95074d0e09988d8e7b1dad8d3ab9a67017a5b03", size = 10073829 }, - { url = "https://files.pythonhosted.org/packages/93/cc/7ed02e0b86a649216b845b3ac66ed55d8aa86f5898c5f1691797f408fcb9/ruff-0.11.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd40de4115b2ec4850302f1a1d8067f42e70b4990b68838ccb9ccd9f110c5e8b", size = 11076108 }, - { url = "https://files.pythonhosted.org/packages/39/5e/5b09840fef0eff1a6fa1dea6296c07d09c17cb6fb94ed5593aa591b50460/ruff-0.11.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:77cda2dfbac1ab73aef5e514c4cbfc4ec1fbef4b84a44c736cc26f61b3814cd9", size = 11512366 }, - { url = "https://files.pythonhosted.org/packages/6f/4c/1cd5a84a412d3626335ae69f5f9de2bb554eea0faf46deb1f0cb48534042/ruff-0.11.6-py3-none-win32.whl", hash = "sha256:5151a871554be3036cd6e51d0ec6eef56334d74dfe1702de717a995ee3d5b287", size = 10485900 }, - { url = "https://files.pythonhosted.org/packages/42/46/8997872bc44d43df986491c18d4418f1caff03bc47b7f381261d62c23442/ruff-0.11.6-py3-none-win_amd64.whl", hash = "sha256:cce85721d09c51f3b782c331b0abd07e9d7d5f775840379c640606d3159cae0e", size = 11558592 }, - { url = "https://files.pythonhosted.org/packages/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766 }, +version = "0.11.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/f6/adcf73711f31c9f5393862b4281c875a462d9f639f4ccdf69dc368311c20/ruff-0.11.8.tar.gz", hash = "sha256:6d742d10626f9004b781f4558154bb226620a7242080e11caeffab1a40e99df8", size = 4086399, upload-time = "2025-05-01T14:53:24.459Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/60/c6aa9062fa518a9f86cb0b85248245cddcd892a125ca00441df77d79ef88/ruff-0.11.8-py3-none-linux_armv6l.whl", hash = "sha256:896a37516c594805e34020c4a7546c8f8a234b679a7716a3f08197f38913e1a3", size = 10272473, upload-time = "2025-05-01T14:52:37.252Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/0325e50d106dc87c00695f7bcd5044c6d252ed5120ebf423773e00270f50/ruff-0.11.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab86d22d3d721a40dd3ecbb5e86ab03b2e053bc93c700dc68d1c3346b36ce835", size = 11040862, upload-time = "2025-05-01T14:52:41.022Z" }, + { url = "https://files.pythonhosted.org/packages/e6/27/b87ea1a7be37fef0adbc7fd987abbf90b6607d96aa3fc67e2c5b858e1e53/ruff-0.11.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:258f3585057508d317610e8a412788cf726efeefa2fec4dba4001d9e6f90d46c", size = 10385273, upload-time = "2025-05-01T14:52:43.551Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f7/3346161570d789045ed47a86110183f6ac3af0e94e7fd682772d89f7f1a1/ruff-0.11.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:727d01702f7c30baed3fc3a34901a640001a2828c793525043c29f7614994a8c", size = 10578330, upload-time = "2025-05-01T14:52:45.48Z" }, + { url = "https://files.pythonhosted.org/packages/c6/c3/327fb950b4763c7b3784f91d3038ef10c13b2d42322d4ade5ce13a2f9edb/ruff-0.11.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3dca977cc4fc8f66e89900fa415ffe4dbc2e969da9d7a54bfca81a128c5ac219", size = 10122223, upload-time = "2025-05-01T14:52:47.675Z" }, + { url = "https://files.pythonhosted.org/packages/de/c7/ba686bce9adfeb6c61cb1bbadc17d58110fe1d602f199d79d4c880170f19/ruff-0.11.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c657fa987d60b104d2be8b052d66da0a2a88f9bd1d66b2254333e84ea2720c7f", size = 11697353, upload-time = "2025-05-01T14:52:50.264Z" }, + { url = "https://files.pythonhosted.org/packages/53/8e/a4fb4a1ddde3c59e73996bb3ac51844ff93384d533629434b1def7a336b0/ruff-0.11.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f2e74b021d0de5eceb8bd32919f6ff8a9b40ee62ed97becd44993ae5b9949474", size = 12375936, upload-time = "2025-05-01T14:52:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/ad/a1/9529cb1e2936e2479a51aeb011307e7229225df9ac64ae064d91ead54571/ruff-0.11.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b5ef39820abc0f2c62111f7045009e46b275f5b99d5e59dda113c39b7f4f38", size = 11850083, upload-time = "2025-05-01T14:52:55.424Z" }, + { url = "https://files.pythonhosted.org/packages/3e/94/8f7eac4c612673ae15a4ad2bc0ee62e03c68a2d4f458daae3de0e47c67ba/ruff-0.11.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1dba3135ca503727aa4648152c0fa67c3b1385d3dc81c75cd8a229c4b2a1458", size = 14005834, upload-time = "2025-05-01T14:52:58.056Z" }, + { url = "https://files.pythonhosted.org/packages/1e/7c/6f63b46b2be870cbf3f54c9c4154d13fac4b8827f22fa05ac835c10835b2/ruff-0.11.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f024d32e62faad0f76b2d6afd141b8c171515e4fb91ce9fd6464335c81244e5", size = 11503713, upload-time = "2025-05-01T14:53:01.244Z" }, + { url = "https://files.pythonhosted.org/packages/3a/91/57de411b544b5fe072779678986a021d87c3ee5b89551f2ca41200c5d643/ruff-0.11.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d365618d3ad747432e1ae50d61775b78c055fee5936d77fb4d92c6f559741948", size = 10457182, upload-time = "2025-05-01T14:53:03.726Z" }, + { url = "https://files.pythonhosted.org/packages/01/49/cfe73e0ce5ecdd3e6f1137bf1f1be03dcc819d1bfe5cff33deb40c5926db/ruff-0.11.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4d9aaa91035bdf612c8ee7266153bcf16005c7c7e2f5878406911c92a31633cb", size = 10101027, upload-time = "2025-05-01T14:53:06.555Z" }, + { url = "https://files.pythonhosted.org/packages/56/21/a5cfe47c62b3531675795f38a0ef1c52ff8de62eaddf370d46634391a3fb/ruff-0.11.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0eba551324733efc76116d9f3a0d52946bc2751f0cd30661564117d6fd60897c", size = 11111298, upload-time = "2025-05-01T14:53:08.825Z" }, + { url = "https://files.pythonhosted.org/packages/36/98/f76225f87e88f7cb669ae92c062b11c0a1e91f32705f829bd426f8e48b7b/ruff-0.11.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:161eb4cff5cfefdb6c9b8b3671d09f7def2f960cee33481dd898caf2bcd02304", size = 11566884, upload-time = "2025-05-01T14:53:11.626Z" }, + { url = "https://files.pythonhosted.org/packages/de/7e/fff70b02e57852fda17bd43f99dda37b9bcf3e1af3d97c5834ff48d04715/ruff-0.11.8-py3-none-win32.whl", hash = "sha256:5b18caa297a786465cc511d7f8be19226acf9c0a1127e06e736cd4e1878c3ea2", size = 10451102, upload-time = "2025-05-01T14:53:14.303Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a9/eaa571eb70648c9bde3120a1d5892597de57766e376b831b06e7c1e43945/ruff-0.11.8-py3-none-win_amd64.whl", hash = "sha256:6e70d11043bef637c5617297bdedec9632af15d53ac1e1ba29c448da9341b0c4", size = 11597410, upload-time = "2025-05-01T14:53:16.571Z" }, + { url = "https://files.pythonhosted.org/packages/cd/be/f6b790d6ae98f1f32c645f8540d5c96248b72343b0a56fab3a07f2941897/ruff-0.11.8-py3-none-win_arm64.whl", hash = "sha256:304432e4c4a792e3da85b7699feb3426a0908ab98bf29df22a31b0cdd098fac2", size = 10713129, upload-time = "2025-05-01T14:53:22.27Z" }, ] [[package]] name = "setuptools" -version = "79.0.0" +version = "80.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/19/fecb7e2825616270f34512b3394cdcf6f45a79b5b6d94fdbd86a509e67b5/setuptools-79.0.0.tar.gz", hash = "sha256:9828422e7541213b0aacb6e10bbf9dd8febeaa45a48570e09b6d100e063fc9f9", size = 1367685 } +sdist = { url = "https://files.pythonhosted.org/packages/51/6c/a3f892949418b5b9aced7396919c75ffb57e38f08b712b565f5eb10677ee/setuptools-80.3.0.tar.gz", hash = "sha256:ec8308eb180b2312062b1c5523204acf872cd8b0a9e6c2ae76431b22bc4065d7", size = 1314475, upload-time = "2025-05-03T09:17:32.334Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/ea/d53f2f8897c46a36df085964d07761ea4c2d1f2cf92019693b6742b7aabb/setuptools-79.0.0-py3-none-any.whl", hash = "sha256:b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a", size = 1256065 }, + { url = "https://files.pythonhosted.org/packages/e6/61/a6239ff35d64e55def020335626894895847cc6659c0f8e1b676c58aad3b/setuptools-80.3.0-py3-none-any.whl", hash = "sha256:a65cffc4fb86167e3020b3ef58e08226baad8b29a3b34ce2c9d07e901bac481d", size = 1200273, upload-time = "2025-05-03T09:17:29.995Z" }, ] [[package]] name = "shibuya" -version = "2025.3.24" +version = "2025.4.25" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/fc/06/c04389568acd779312a87942aa499c27c950e0f5156ae9e594957f13bb3d/shibuya-2025.3.24.tar.gz", hash = "sha256:63ff69697fc3a8b31c03c04617a337fd1c94911295fd3723a406f09d885f6240", size = 80568 } +sdist = { url = "https://files.pythonhosted.org/packages/77/53/9412870bc5aaa99cd1536e552b5d8ef07336c9f911e79022121fc7a11e15/shibuya-2025.4.25.tar.gz", hash = "sha256:398b4541c270709b726f1745178a69ee6a949ad6e582f2ed27240859ee038f8d", size = 80603, upload-time = "2025-04-25T15:06:08.326Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/45/f8dba1ce15e5e6c76ea970d12ecca202acbf3ac2138b45dbd63c71c97121/shibuya-2025.3.24-py3-none-any.whl", hash = "sha256:3eb7d20a028eb1d72d1b13a1133657df8ce3fda5bd6c4514b2967ee21f631896", size = 96236 }, + { url = "https://files.pythonhosted.org/packages/35/c6/af0ed5f26868282bb3d5990a07bf6d7529458bbc6f78fdf2bf9c6c727896/shibuya-2025.4.25-py3-none-any.whl", hash = "sha256:c1174dd7f849a4730b1f8f6c32a6b099b95d64dd77a08a05ea978563ecadfd4b", size = 96262, upload-time = "2025-04-25T15:06:06.524Z" }, ] [[package]] name = "six" version = "1.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] [[package]] @@ -3120,36 +3139,36 @@ dependencies = [ { name = "click" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/57/6fcb8df11e7c76eb87b23bfa931408e47f051c6161749c531b4060a45516/slotscheck-0.19.1.tar.gz", hash = "sha256:6146b7747f8db335a00a66b782f86011b74b995f61746dc5b36a9e77d5326013", size = 16050 } +sdist = { url = "https://files.pythonhosted.org/packages/4b/57/6fcb8df11e7c76eb87b23bfa931408e47f051c6161749c531b4060a45516/slotscheck-0.19.1.tar.gz", hash = "sha256:6146b7747f8db335a00a66b782f86011b74b995f61746dc5b36a9e77d5326013", size = 16050, upload-time = "2024-10-19T13:30:53.369Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/32/bd569256267f80b76b87d21a09795741a175778b954bee1d7b1a89852b6f/slotscheck-0.19.1-py3-none-any.whl", hash = "sha256:bff9926f8d6408ea21b6c6bbaa4389cea1682962e73ee4f30084b6d2b89260ee", size = 16995 }, + { url = "https://files.pythonhosted.org/packages/da/32/bd569256267f80b76b87d21a09795741a175778b954bee1d7b1a89852b6f/slotscheck-0.19.1-py3-none-any.whl", hash = "sha256:bff9926f8d6408ea21b6c6bbaa4389cea1682962e73ee4f30084b6d2b89260ee", size = 16995, upload-time = "2024-10-19T13:30:51.23Z" }, ] [[package]] name = "sniffio" version = "1.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] [[package]] name = "snowballstemmer" version = "2.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699 } +sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699, upload-time = "2021-11-16T18:38:38.009Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 }, + { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, ] [[package]] name = "soupsieve" version = "2.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418 } +sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418, upload-time = "2025-04-20T18:50:08.518Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677 }, + { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, ] [[package]] @@ -3179,9 +3198,9 @@ dependencies = [ { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.10'" }, { name = "tomli", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911 } +sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911, upload-time = "2024-07-20T14:46:56.059Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624 }, + { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624, upload-time = "2024-07-20T14:46:52.142Z" }, ] [[package]] @@ -3210,9 +3229,9 @@ dependencies = [ { name = "sphinxcontrib-serializinghtml", marker = "python_full_version == '3.10.*'" }, { name = "tomli", marker = "python_full_version == '3.10.*'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611 } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125 }, + { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125, upload-time = "2024-10-13T20:27:10.448Z" }, ] [[package]] @@ -3242,9 +3261,9 @@ dependencies = [ { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.11'" }, { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876 } +sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741 }, + { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" }, ] [[package]] @@ -3261,9 +3280,9 @@ dependencies = [ { name = "watchfiles" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a5/2c/155e1de2c1ba96a72e5dba152c509a8b41e047ee5c2def9e9f0d812f8be7/sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1", size = 14023 } +sdist = { url = "https://files.pythonhosted.org/packages/a5/2c/155e1de2c1ba96a72e5dba152c509a8b41e047ee5c2def9e9f0d812f8be7/sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1", size = 14023, upload-time = "2024-10-02T23:15:30.172Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/c0/eba125db38c84d3c74717008fd3cb5000b68cd7e2cbafd1349c6a38c3d3b/sphinx_autobuild-2024.10.3-py3-none-any.whl", hash = "sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa", size = 11908 }, + { url = "https://files.pythonhosted.org/packages/18/c0/eba125db38c84d3c74717008fd3cb5000b68cd7e2cbafd1349c6a38c3d3b/sphinx_autobuild-2024.10.3-py3-none-any.whl", hash = "sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa", size = 11908, upload-time = "2024-10-02T23:15:28.739Z" }, ] [[package]] @@ -3276,9 +3295,9 @@ resolution-markers = [ dependencies = [ { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/cd/03e7b917230dc057922130a79ba0240df1693bfd76727ea33fae84b39138/sphinx_autodoc_typehints-2.3.0.tar.gz", hash = "sha256:535c78ed2d6a1bad393ba9f3dfa2602cf424e2631ee207263e07874c38fde084", size = 40709 } +sdist = { url = "https://files.pythonhosted.org/packages/74/cd/03e7b917230dc057922130a79ba0240df1693bfd76727ea33fae84b39138/sphinx_autodoc_typehints-2.3.0.tar.gz", hash = "sha256:535c78ed2d6a1bad393ba9f3dfa2602cf424e2631ee207263e07874c38fde084", size = 40709, upload-time = "2024-08-29T16:25:48.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/f3/e0a4ce49da4b6f4e4ce84b3c39a0677831884cb9d8a87ccbf1e9e56e53ac/sphinx_autodoc_typehints-2.3.0-py3-none-any.whl", hash = "sha256:3098e2c6d0ba99eacd013eb06861acc9b51c6e595be86ab05c08ee5506ac0c67", size = 19836 }, + { url = "https://files.pythonhosted.org/packages/a0/f3/e0a4ce49da4b6f4e4ce84b3c39a0677831884cb9d8a87ccbf1e9e56e53ac/sphinx_autodoc_typehints-2.3.0-py3-none-any.whl", hash = "sha256:3098e2c6d0ba99eacd013eb06861acc9b51c6e595be86ab05c08ee5506ac0c67", size = 19836, upload-time = "2024-08-29T16:25:46.707Z" }, ] [[package]] @@ -3291,14 +3310,14 @@ resolution-markers = [ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/f0/43c6a5ff3e7b08a8c3b32f81b859f1b518ccc31e45f22e2b41ced38be7b9/sphinx_autodoc_typehints-3.0.1.tar.gz", hash = "sha256:b9b40dd15dee54f6f810c924f863f9cf1c54f9f3265c495140ea01be7f44fa55", size = 36282 } +sdist = { url = "https://files.pythonhosted.org/packages/26/f0/43c6a5ff3e7b08a8c3b32f81b859f1b518ccc31e45f22e2b41ced38be7b9/sphinx_autodoc_typehints-3.0.1.tar.gz", hash = "sha256:b9b40dd15dee54f6f810c924f863f9cf1c54f9f3265c495140ea01be7f44fa55", size = 36282, upload-time = "2025-01-16T18:25:30.958Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/dc/dc46c5c7c566b7ec5e8f860f9c89533bf03c0e6aadc96fb9b337867e4460/sphinx_autodoc_typehints-3.0.1-py3-none-any.whl", hash = "sha256:4b64b676a14b5b79cefb6628a6dc8070e320d4963e8ff640a2f3e9390ae9045a", size = 20245 }, + { url = "https://files.pythonhosted.org/packages/3c/dc/dc46c5c7c566b7ec5e8f860f9c89533bf03c0e6aadc96fb9b337867e4460/sphinx_autodoc_typehints-3.0.1-py3-none-any.whl", hash = "sha256:4b64b676a14b5b79cefb6628a6dc8070e320d4963e8ff640a2f3e9390ae9045a", size = 20245, upload-time = "2025-01-16T18:25:27.394Z" }, ] [[package]] name = "sphinx-autodoc-typehints" -version = "3.1.0" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.13'", @@ -3307,9 +3326,9 @@ resolution-markers = [ dependencies = [ { 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/cb/cc/d38e7260b1bd3af0c84ad8285dfd78236584b74544510584e07963e000ec/sphinx_autodoc_typehints-3.1.0.tar.gz", hash = "sha256:a6b7b0b6df0a380783ce5b29150c2d30352746f027a3e294d37183995d3f23ed", size = 36528 } +sdist = { url = "https://files.pythonhosted.org/packages/93/68/a388a9b8f066cd865d9daa65af589d097efbfab9a8c302d2cb2daa43b52e/sphinx_autodoc_typehints-3.2.0.tar.gz", hash = "sha256:107ac98bc8b4837202c88c0736d59d6da44076e65a0d7d7d543a78631f662a9b", size = 36724, upload-time = "2025-04-25T16:53:25.872Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/14/2f/bc5bed0677ae00b9ca7919968ea675e2f696b6b20f1648262f26a7a6c6b4/sphinx_autodoc_typehints-3.1.0-py3-none-any.whl", hash = "sha256:67bdee7e27ba943976ce92ebc5647a976a7a08f9f689a826c54617b96a423913", size = 20404 }, + { url = "https://files.pythonhosted.org/packages/f7/c7/8aab362e86cbf887e58be749a78d20ad743e1eb2c73c2b13d4761f39a104/sphinx_autodoc_typehints-3.2.0-py3-none-any.whl", hash = "sha256:884b39be23b1d884dcc825d4680c9c6357a476936e3b381a67ae80091984eb49", size = 20563, upload-time = "2025-04-25T16:53:24.492Z" }, ] [[package]] @@ -3323,9 +3342,9 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/db/0a/5b1e8d0579dbb4ca8114e456ca4a68020bfe8e15c7001f3856be4929ab83/sphinx_click-6.0.0.tar.gz", hash = "sha256:f5d664321dc0c6622ff019f1e1c84e58ce0cecfddeb510e004cf60c2a3ab465b", size = 29574 } +sdist = { url = "https://files.pythonhosted.org/packages/db/0a/5b1e8d0579dbb4ca8114e456ca4a68020bfe8e15c7001f3856be4929ab83/sphinx_click-6.0.0.tar.gz", hash = "sha256:f5d664321dc0c6622ff019f1e1c84e58ce0cecfddeb510e004cf60c2a3ab465b", size = 29574, upload-time = "2024-05-15T14:49:17.044Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/d7/8621c4726ad3f788a1db4c0c409044b16edc563f5c9542807b3724037555/sphinx_click-6.0.0-py3-none-any.whl", hash = "sha256:1e0a3c83bcb7c55497751b19d07ebe56b5d7b85eb76dd399cf9061b497adc317", size = 9922 }, + { url = "https://files.pythonhosted.org/packages/d0/d7/8621c4726ad3f788a1db4c0c409044b16edc563f5c9542807b3724037555/sphinx_click-6.0.0-py3-none-any.whl", hash = "sha256:1e0a3c83bcb7c55497751b19d07ebe56b5d7b85eb76dd399cf9061b497adc317", size = 9922, upload-time = "2024-05-15T14:49:15.768Z" }, ] [[package]] @@ -3337,9 +3356,9 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd", size = 23039 } +sdist = { url = "https://files.pythonhosted.org/packages/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd", size = 23039, upload-time = "2023-04-14T08:10:22.998Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/48/1ea60e74949eecb12cdd6ac43987f9fd331156388dcc2319b45e2ebb81bf/sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e", size = 13343 }, + { url = "https://files.pythonhosted.org/packages/9e/48/1ea60e74949eecb12cdd6ac43987f9fd331156388dcc2319b45e2ebb81bf/sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e", size = 13343, upload-time = "2023-04-14T08:10:20.844Z" }, ] [[package]] @@ -3351,9 +3370,9 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/2b/69/b34e0cb5336f09c6866d53b4a19d76c227cdec1bbc7ac4de63ca7d58c9c7/sphinx_design-0.6.1.tar.gz", hash = "sha256:b44eea3719386d04d765c1a8257caca2b3e6f8421d7b3a5e742c0fd45f84e632", size = 2193689 } +sdist = { url = "https://files.pythonhosted.org/packages/2b/69/b34e0cb5336f09c6866d53b4a19d76c227cdec1bbc7ac4de63ca7d58c9c7/sphinx_design-0.6.1.tar.gz", hash = "sha256:b44eea3719386d04d765c1a8257caca2b3e6f8421d7b3a5e742c0fd45f84e632", size = 2193689, upload-time = "2024-08-02T13:48:44.277Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/43/65c0acbd8cc6f50195a3a1fc195c404988b15c67090e73c7a41a9f57d6bd/sphinx_design-0.6.1-py3-none-any.whl", hash = "sha256:b11f37db1a802a183d61b159d9a202314d4d2fe29c163437001324fe2f19549c", size = 2215338 }, + { url = "https://files.pythonhosted.org/packages/c6/43/65c0acbd8cc6f50195a3a1fc195c404988b15c67090e73c7a41a9f57d6bd/sphinx_design-0.6.1-py3-none-any.whl", hash = "sha256:b11f37db1a802a183d61b159d9a202314d4d2fe29c163437001324fe2f19549c", size = 2215338, upload-time = "2024-08-02T13:48:42.106Z" }, ] [[package]] @@ -3365,9 +3384,9 @@ dependencies = [ { name = "markupsafe" }, { name = "standard-imghdr", marker = "python_full_version >= '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/df/27282da6f8c549f765beca9de1a5fc56f9651ed87711a5cac1e914137753/sphinx_jinja2_compat-0.3.0.tar.gz", hash = "sha256:f3c1590b275f42e7a654e081db5e3e5fb97f515608422bde94015ddf795dfe7c", size = 4998 } +sdist = { url = "https://files.pythonhosted.org/packages/26/df/27282da6f8c549f765beca9de1a5fc56f9651ed87711a5cac1e914137753/sphinx_jinja2_compat-0.3.0.tar.gz", hash = "sha256:f3c1590b275f42e7a654e081db5e3e5fb97f515608422bde94015ddf795dfe7c", size = 4998, upload-time = "2024-06-19T10:27:00.781Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/42/2fd09d672eaaa937d6893d8b747d07943f97a6e5e30653aee6ebd339b704/sphinx_jinja2_compat-0.3.0-py3-none-any.whl", hash = "sha256:b1e4006d8e1ea31013fa9946d1b075b0c8d2a42c6e3425e63542c1e9f8be9084", size = 7883 }, + { url = "https://files.pythonhosted.org/packages/6f/42/2fd09d672eaaa937d6893d8b747d07943f97a6e5e30653aee6ebd339b704/sphinx_jinja2_compat-0.3.0-py3-none-any.whl", hash = "sha256:b1e4006d8e1ea31013fa9946d1b075b0c8d2a42c6e3425e63542c1e9f8be9084", size = 7883, upload-time = "2024-06-19T10:26:59.121Z" }, ] [[package]] @@ -3380,7 +3399,7 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/ae/21/62d3a58ff7bd02bbb9245a63d1f0d2e0455522a11a78951d16088569fca8/sphinx-paramlinks-0.6.0.tar.gz", hash = "sha256:746a0816860aa3fff5d8d746efcbec4deead421f152687411db1d613d29f915e", size = 12363 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/21/62d3a58ff7bd02bbb9245a63d1f0d2e0455522a11a78951d16088569fca8/sphinx-paramlinks-0.6.0.tar.gz", hash = "sha256:746a0816860aa3fff5d8d746efcbec4deead421f152687411db1d613d29f915e", size = 12363, upload-time = "2023-08-11T16:09:28.604Z" } [[package]] name = "sphinx-prompt" @@ -3394,9 +3413,9 @@ dependencies = [ { name = "pygments", marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/fb/7a07b8df1ca2418147a6b13e3f6b445071f2565198b45efa631d0d6ef0cd/sphinx_prompt-1.8.0.tar.gz", hash = "sha256:47482f86fcec29662fdfd23e7c04ef03582714195d01f5d565403320084372ed", size = 5121 } +sdist = { url = "https://files.pythonhosted.org/packages/e7/fb/7a07b8df1ca2418147a6b13e3f6b445071f2565198b45efa631d0d6ef0cd/sphinx_prompt-1.8.0.tar.gz", hash = "sha256:47482f86fcec29662fdfd23e7c04ef03582714195d01f5d565403320084372ed", size = 5121, upload-time = "2023-09-14T12:46:13.449Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/49/f890a2668b7cbf375f5528b549c8d36dd2e801b0fbb7b2b5ef65663ecb6c/sphinx_prompt-1.8.0-py3-none-any.whl", hash = "sha256:369ecc633f0711886f9b3a078c83264245be1adf46abeeb9b88b5519e4b51007", size = 7298 }, + { url = "https://files.pythonhosted.org/packages/39/49/f890a2668b7cbf375f5528b549c8d36dd2e801b0fbb7b2b5ef65663ecb6c/sphinx_prompt-1.8.0-py3-none-any.whl", hash = "sha256:369ecc633f0711886f9b3a078c83264245be1adf46abeeb9b88b5519e4b51007", size = 7298, upload-time = "2023-09-14T12:46:12.373Z" }, ] [[package]] @@ -3417,9 +3436,9 @@ dependencies = [ { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "urllib3", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/34/fe/ac4e24f35b5148b31ac717ae7dcc7a2f7ec56eb729e22c7252ed8ad2d9a5/sphinx_prompt-1.9.0.tar.gz", hash = "sha256:471b3c6d466dce780a9b167d9541865fd4e9a80ed46e31b06a52a0529ae995a1", size = 5340 } +sdist = { url = "https://files.pythonhosted.org/packages/34/fe/ac4e24f35b5148b31ac717ae7dcc7a2f7ec56eb729e22c7252ed8ad2d9a5/sphinx_prompt-1.9.0.tar.gz", hash = "sha256:471b3c6d466dce780a9b167d9541865fd4e9a80ed46e31b06a52a0529ae995a1", size = 5340, upload-time = "2024-08-07T15:46:51.428Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/98/e90ca466e0ede452d3e5a8d92b8fb68db6de269856e019ed9cab69440522/sphinx_prompt-1.9.0-py3-none-any.whl", hash = "sha256:fd731446c03f043d1ff6df9f22414495b23067c67011cc21658ea8d36b3575fc", size = 7311 }, + { url = "https://files.pythonhosted.org/packages/76/98/e90ca466e0ede452d3e5a8d92b8fb68db6de269856e019ed9cab69440522/sphinx_prompt-1.9.0-py3-none-any.whl", hash = "sha256:fd731446c03f043d1ff6df9f22414495b23067c67011cc21658ea8d36b3575fc", size = 7311, upload-time = "2024-08-07T15:46:50.329Z" }, ] [[package]] @@ -3433,9 +3452,9 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/27/32/ab475e252dc2b704e82a91141fa404cdd8901a5cf34958fd22afacebfccd/sphinx-tabs-3.4.5.tar.gz", hash = "sha256:ba9d0c1e3e37aaadd4b5678449eb08176770e0fc227e769b6ce747df3ceea531", size = 16070 } +sdist = { url = "https://files.pythonhosted.org/packages/27/32/ab475e252dc2b704e82a91141fa404cdd8901a5cf34958fd22afacebfccd/sphinx-tabs-3.4.5.tar.gz", hash = "sha256:ba9d0c1e3e37aaadd4b5678449eb08176770e0fc227e769b6ce747df3ceea531", size = 16070, upload-time = "2024-01-21T12:13:39.392Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/9f/4ac7dbb9f23a2ff5a10903a4f9e9f43e0ff051f63a313e989c962526e305/sphinx_tabs-3.4.5-py3-none-any.whl", hash = "sha256:92cc9473e2ecf1828ca3f6617d0efc0aa8acb06b08c56ba29d1413f2f0f6cf09", size = 9904 }, + { url = "https://files.pythonhosted.org/packages/20/9f/4ac7dbb9f23a2ff5a10903a4f9e9f43e0ff051f63a313e989c962526e305/sphinx_tabs-3.4.5-py3-none-any.whl", hash = "sha256:92cc9473e2ecf1828ca3f6617d0efc0aa8acb06b08c56ba29d1413f2f0f6cf09", size = 9904, upload-time = "2024-01-21T12:13:37.67Z" }, ] [[package]] @@ -3450,9 +3469,9 @@ dependencies = [ { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "wheel" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f0/df/d151dfbbe588116e450ca7e898750cb218dca6b2e557ced8de6f9bd7242b/sphinx-togglebutton-0.3.2.tar.gz", hash = "sha256:ab0c8b366427b01e4c89802d5d078472c427fa6e9d12d521c34fa0442559dc7a", size = 8324 } +sdist = { url = "https://files.pythonhosted.org/packages/f0/df/d151dfbbe588116e450ca7e898750cb218dca6b2e557ced8de6f9bd7242b/sphinx-togglebutton-0.3.2.tar.gz", hash = "sha256:ab0c8b366427b01e4c89802d5d078472c427fa6e9d12d521c34fa0442559dc7a", size = 8324, upload-time = "2022-07-15T12:08:50.286Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/18/267ce39f29d26cdc7177231428ba823fe5ca94db8c56d1bed69033b364c8/sphinx_togglebutton-0.3.2-py3-none-any.whl", hash = "sha256:9647ba7874b7d1e2d43413d8497153a85edc6ac95a3fea9a75ef9c1e08aaae2b", size = 8249 }, + { url = "https://files.pythonhosted.org/packages/e9/18/267ce39f29d26cdc7177231428ba823fe5ca94db8c56d1bed69033b364c8/sphinx_togglebutton-0.3.2-py3-none-any.whl", hash = "sha256:9647ba7874b7d1e2d43413d8497153a85edc6ac95a3fea9a75ef9c1e08aaae2b", size = 8249, upload-time = "2022-07-15T12:08:48.8Z" }, ] [[package]] @@ -3475,7 +3494,7 @@ dependencies = [ { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-autodoc-typehints", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx-autodoc-typehints", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "sphinx-autodoc-typehints", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-autodoc-typehints", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-jinja2-compat" }, { name = "sphinx-prompt", version = "1.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx-prompt", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, @@ -3483,45 +3502,45 @@ dependencies = [ { name = "tabulate" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/32/e10c272614a1f4d84b680007bd45f9b77db3262ee6c3c61a0e27932a55b7/sphinx_toolbox-3.9.0.tar.gz", hash = "sha256:9ee0603b090762d6eed4d0ec9fa91445e3ef95d40a584af125308541c1bf7b8d", size = 114497 } +sdist = { url = "https://files.pythonhosted.org/packages/df/32/e10c272614a1f4d84b680007bd45f9b77db3262ee6c3c61a0e27932a55b7/sphinx_toolbox-3.9.0.tar.gz", hash = "sha256:9ee0603b090762d6eed4d0ec9fa91445e3ef95d40a584af125308541c1bf7b8d", size = 114497, upload-time = "2025-02-26T13:32:07.253Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/7e/9811c8cf0df10c2b6c9c72667837d731dd4f0dc0d0e68980938c8eb6f7f8/sphinx_toolbox-3.9.0-py3-none-any.whl", hash = "sha256:49024961c7791ad6e9dd39c611f89b5162550afa26ccad087be38388c3dd3c1e", size = 195429 }, + { url = "https://files.pythonhosted.org/packages/5d/7e/9811c8cf0df10c2b6c9c72667837d731dd4f0dc0d0e68980938c8eb6f7f8/sphinx_toolbox-3.9.0-py3-none-any.whl", hash = "sha256:49024961c7791ad6e9dd39c611f89b5162550afa26ccad087be38388c3dd3c1e", size = 195429, upload-time = "2025-02-26T13:32:04.4Z" }, ] [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 }, + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, ] [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 }, + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, ] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 }, + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, ] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 }, + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, ] [[package]] @@ -3534,36 +3553,36 @@ dependencies = [ { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { 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/97/69/bf039237ad260073e8c02f820b3e00dc34f3a2de20aff7861e6b19d2f8c5/sphinxcontrib_mermaid-1.0.0.tar.gz", hash = "sha256:2e8ab67d3e1e2816663f9347d026a8dee4a858acdd4ad32dd1c808893db88146", size = 15153 } +sdist = { url = "https://files.pythonhosted.org/packages/97/69/bf039237ad260073e8c02f820b3e00dc34f3a2de20aff7861e6b19d2f8c5/sphinxcontrib_mermaid-1.0.0.tar.gz", hash = "sha256:2e8ab67d3e1e2816663f9347d026a8dee4a858acdd4ad32dd1c808893db88146", size = 15153, upload-time = "2024-10-12T16:33:03.863Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/c8/784b9ac6ea08aa594c1a4becbd0dbe77186785362e31fd633b8c6ae0197a/sphinxcontrib_mermaid-1.0.0-py3-none-any.whl", hash = "sha256:60b72710ea02087f212028feb09711225fbc2e343a10d34822fe787510e1caa3", size = 9597 }, + { url = "https://files.pythonhosted.org/packages/cd/c8/784b9ac6ea08aa594c1a4becbd0dbe77186785362e31fd633b8c6ae0197a/sphinxcontrib_mermaid-1.0.0-py3-none-any.whl", hash = "sha256:60b72710ea02087f212028feb09711225fbc2e343a10d34822fe787510e1caa3", size = 9597, upload-time = "2024-10-12T16:33:02.303Z" }, ] [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 }, + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, ] [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 }, + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] [[package]] name = "sqlglot" -version = "26.15.0" +version = "26.16.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ac/16/57112d89a61f4329047921b2df09ac3caac1e006153bcfc662157211997f/sqlglot-26.15.0.tar.gz", hash = "sha256:8349b782b8cee8b0ec6d228341a6564de562bdb7d87e7843e4849e9bf576e9a9", size = 5350274 } +sdist = { url = "https://files.pythonhosted.org/packages/38/90/e487ae7c3722896e9b6911ac95e472a0bf37069061fdd3f54181db00ec28/sqlglot-26.16.4.tar.gz", hash = "sha256:0de74266e4ab1286801c40640a8bd99f96c1ec0fc20681f3c55802f39ce4b3ec", size = 5355134, upload-time = "2025-05-02T01:28:55.707Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/27/c1fa18020053a35d1e2c6dddea7c859bc8a0d438063273a02ca417ddd5c8/sqlglot-26.15.0-py3-none-any.whl", hash = "sha256:e4839f989e83b081af636e1f1312105c453b7fc3d440e8e10a5aaa447d16cd48", size = 458109 }, + { url = "https://files.pythonhosted.org/packages/00/b3/f91be0e284bb221d5e52073e3ab73e788e9101d7f7e7561dd771daed7a81/sqlglot-26.16.4-py3-none-any.whl", hash = "sha256:dbff0ace2e21c9169182d6852b8f6eb56d86fc6477354abcb5bda7ab93292975", size = 460033, upload-time = "2025-05-02T01:28:52.589Z" }, ] [package.optional-dependencies] @@ -3575,67 +3594,67 @@ rs = [ name = "sqlglotrs" version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/1a/72690c890410b4da2a96b37305ef4063f9bb24f830208c02329d1f370a12/sqlglotrs-0.4.0.tar.gz", hash = "sha256:b3b73ba1c9c4699de6d9c710f23fbc639651af0ac73eec831bcd298eda059582", size = 15419 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/b3/022d8b1eea627d8bb49b8bd7de4e71efb27f46cb86bb6d371aec8e9aa54d/sqlglotrs-0.4.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:065bea5861d613ee27967cdd76d5176303595d9794e0a2dd4a1027f2ebe6ad91", size = 299788 }, - { url = "https://files.pythonhosted.org/packages/4a/ed/2c577fcbc3c9d85e425e86fe012af59ddbed203d32efc41114b3b846a148/sqlglotrs-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9d033bce2be9db48deebf243610a4b467e76c68a80fd989de18f976712d92424", size = 290131 }, - { url = "https://files.pythonhosted.org/packages/f8/db/430e3d329d28ad1ea6f71dfa9942bbeae8e208aa96c19ad69f837fc54a1f/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac19a13910f112659b2e8b1f6ca03de1c628b40881936d9013159c57cce847f7", size = 326948 }, - { url = "https://files.pythonhosted.org/packages/11/5a/32da4e4c7f72b8a0a30c76d46460a9867d0f94ee2dddcb25db658651e438/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86ec7dc45c830efa5c54a424430ec03f25553038437690ff4b9e0365bcb564fc", size = 333051 }, - { url = "https://files.pythonhosted.org/packages/14/ef/e9d7a54fc0c72d5a8c9e1387faee6799e687c559fc6015828d0513373e71/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69e327cce71f797f073c0c52e77c2087da9b8dc55740b64b6e73ddc138ed38a8", size = 394437 }, - { url = "https://files.pythonhosted.org/packages/83/a5/4f8383b9f7b8496dbde6e2e6896b722767696915bfb0105fbaa8b60e54ca/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8870c4e7e199a2865f80674964e74a45f10466e5b77fea2ca408d24765816e40", size = 385058 }, - { url = "https://files.pythonhosted.org/packages/0e/79/41e728d0c5173cc0756fd4667a52693cc683962a7aea0ef8b01f4184a733/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a689435bf41a09862efe4be447c4f49a406890c58896739623f46e45ed7a8321", size = 332059 }, - { url = "https://files.pythonhosted.org/packages/3f/1f/3c10a3b8957018e0f6ec0c23869f8e50f883fdcf7dde18318e4e66805f94/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9332a3590ef914271e4762a5713a5f0cacf5fd02d69a70336baafbe1ad3b2d0", size = 350954 }, - { url = "https://files.pythonhosted.org/packages/50/93/ca92bc7d38cee72366159345f87529db909f4c86882364087cec802d6f46/sqlglotrs-0.4.0-cp310-cp310-win32.whl", hash = "sha256:27cef20a2169e5378bb3013c889c499a637293b5e871bee225fc3cba47216890", size = 174519 }, - { url = "https://files.pythonhosted.org/packages/17/5f/de62f31e48544b46c8f7e4fcfb175b4e5d00641c6e29c70af65793a8c374/sqlglotrs-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:8dcca8d84ed734d77fe767c54ef7760b3b7b6ca4ca3e60b76af427375dc331c3", size = 189704 }, - { url = "https://files.pythonhosted.org/packages/84/c9/f01d691becbfc8e668b7aefb0d1fa2ef6841650e0c0394d884777ec435b6/sqlglotrs-0.4.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2bba88aba5f99dbd80caedaf820dcdf2699d906900f895b63e596f3fc7cfd134", size = 299654 }, - { url = "https://files.pythonhosted.org/packages/6f/dc/d3ca4048cc7721043808a29bfad7251dc7c62e2b0145bbdf0b978ffe6424/sqlglotrs-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28495248e27e67943d794b4d0b065dd18522b35c8e890a595da36f5d6f856de0", size = 290101 }, - { url = "https://files.pythonhosted.org/packages/e6/39/a1a04779dc4125ae5555b584af057c55a5e50a48e2f4669f6fe255108644/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b168d52d8d14657143c3beafcbb2929df3772595e914cdb80a926e36e727fd", size = 326842 }, - { url = "https://files.pythonhosted.org/packages/9f/bb/482e4d2284710a699534eacab315e907870cadbb2fcd6414ee2b04c3c058/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c120f951d67196301a753225e4b350686fa1bf98ba3504e8e06ba90e2f4eb88", size = 333250 }, - { url = "https://files.pythonhosted.org/packages/35/2c/0a69e059692d20ce2b05367e4d23e21cfb45d8001f9bfa4edb1e529f0a7d/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fa98390de3994c6956120d7323504eb511c78d866981b35cc36c2a3544ead57", size = 394549 }, - { url = "https://files.pythonhosted.org/packages/15/08/f4a8f988623b2813ce311aa19738bfc8b6e80c9756b2c756eb287c904355/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a290aa2bedcc103a422ad9e27134b0973e3caefe08aa6ac6a8528e96c6a119d0", size = 384649 }, - { url = "https://files.pythonhosted.org/packages/18/66/713246e2606b9008588bb1cdc6377ffc2df10aa8fbbf7e7dd5e8c816abe7/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dd563eac836154c0058e851aeb8f750ac8957d67aca850816cb9137df95e088", size = 332020 }, - { url = "https://files.pythonhosted.org/packages/56/49/774d571ea5b3ff0345b2c580b20fcc1e81c206a07a9c3ec89bee7662cf03/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4e055ccf9416ea76855d515ac3621c3e5014f700e7e4c7810f65690adbaf0b", size = 350969 }, - { url = "https://files.pythonhosted.org/packages/cf/cd/36e948f72f8cde21c118b92b3ec1a363569e8d1af92ffaa0a4c9a9468f40/sqlglotrs-0.4.0-cp311-cp311-win32.whl", hash = "sha256:f6225ba2d0713d709448fc89e14b6b2c7c2b27a42b0f20d5d98fb69cc387a111", size = 174461 }, - { url = "https://files.pythonhosted.org/packages/c4/7e/511d59f7f012800a1aa780a28c973fd2576657066724b62a790d7da23df8/sqlglotrs-0.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:e398740d9d6109ae6919f983f7e56e4d314c63d17803556a16771731688b47be", size = 189814 }, - { url = "https://files.pythonhosted.org/packages/3e/98/120acd4301a90a816606e120fa216d7da6b70b85d0895d30fed94760d664/sqlglotrs-0.4.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:69b4e8121d86bccd4e55cbc2822b9eb96da510608df91cbb3701a1e33fb54813", size = 299691 }, - { url = "https://files.pythonhosted.org/packages/cc/30/d6cb97dcfd57ff9bc56d07ade39b46133dad91143d7c676c197fdfb4258a/sqlglotrs-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fa3e5b0c5a976a61ad6219fddb6ef10f603771119a303ba3c5046a6daf89b207", size = 290439 }, - { url = "https://files.pythonhosted.org/packages/9c/73/70e2fc314291fa2543cc54a37869f2df2cfab2f649fd15c3fed4c28b6d62/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24b1a3f5685fd12f376b97734284bdcb4d17d703436993686f45ea275a14d83a", size = 326375 }, - { url = "https://files.pythonhosted.org/packages/27/6c/4a6545301b4c2e944adccf23da2fc1e9aeaf48d95ade73334c9aff0ab91e/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dbeacf80e99c87e2334e9a8af8c6efa06e81ceaf98c9eca22780f6ee286fd190", size = 333105 }, - { url = "https://files.pythonhosted.org/packages/14/cb/7898b1e3678f313b08a6681968ecc70007e87003d436b5e5abd88709e40a/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58046e18d19d122027f0a4496791e8f107e396ce5866ea6973828a4a8c2feef", size = 394334 }, - { url = "https://files.pythonhosted.org/packages/d0/d0/fe5a16e5c3fd445185584bf98d1309fd70dc24ed19cf896e4137e05d8b81/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cab9c83335d33306657461f4ad61cda3df3ef7d3826234508689978f3a02c436", size = 382242 }, - { url = "https://files.pythonhosted.org/packages/8f/a0/667eb1deb9b5a998d610b203dffcf0c6f2d7ca41ed237ea4b9f24ca40970/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b5fcd4897a7453e85dfaecb0451972c874c0e39fe7d2636edd2102c2f441e0", size = 332244 }, - { url = "https://files.pythonhosted.org/packages/2e/b6/2017d4a0805ad75b56d0cff8d5d32974ca709886175d828530bf16301f5f/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e5e00b51a470bbd2fde561313c749220bcaef5293d092ac03983b114b00f35b", size = 350271 }, - { url = "https://files.pythonhosted.org/packages/ce/c3/d5366f836db1a7729fa86105965f8d11771ca7d64a477f612246dbf52c76/sqlglotrs-0.4.0-cp312-cp312-win32.whl", hash = "sha256:c53c78acb15adcc4470c79fdfe90d13c09a61122b12fd9ff679210f37315a038", size = 173762 }, - { url = "https://files.pythonhosted.org/packages/e3/ff/7860811859bef843776a8063297512d95def039db58aecf8126e33d629ea/sqlglotrs-0.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:c9059e7586b19fb426595fe5c2167702bef92aa4562becdcb29f323f9491f2d5", size = 190577 }, - { url = "https://files.pythonhosted.org/packages/31/63/d9407aa1fe4d9e88e6751703d4b6b62b19b8de9131f4980c4682c3e1ff32/sqlglotrs-0.4.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7a10d8cd702f4df9ea4533ddc7a3b1cd1d9cb4c3c150d64cc8a51544599c5051", size = 299227 }, - { url = "https://files.pythonhosted.org/packages/40/e8/b4e142b087d8c657886517d235e628fee5884a7839048ac3bf058d8ae335/sqlglotrs-0.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14ae854d3480e9413bce3eb779e4735512e06f443930a81c525bc96b203c7548", size = 289923 }, - { url = "https://files.pythonhosted.org/packages/24/97/711ea1790142a801186b5539fc8568aafbb9fa9984eb2e5baef3ab6a42fc/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b630583236e22b1504cff416127b5c3ba9569832db0900cdc05066b54e13b726", size = 325831 }, - { url = "https://files.pythonhosted.org/packages/cb/63/037566779c93b723a62883caedb01d2cd62c80a39c15cd5750175fdf6b40/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6e935e0c5511ad1258f2a7cd9a9fb09484fd5c58b250dfb5ab5b6cbe4581de9c", size = 332559 }, - { url = "https://files.pythonhosted.org/packages/84/91/2b6a46f21c0202286817cb4e085ccabe7d5065ff22c3719b8047d068ee62/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18755ddf63bb0b573ed4bb36db779ac98ab63853086d9126f27467bf15c954be", size = 394570 }, - { url = "https://files.pythonhosted.org/packages/82/97/1a222cef008f1998a558638186d217066b57670087f4674fad5444a25f86/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52b89640001564850148fbc9dcb19b3382b41f449c0691498188dac08b9591ff", size = 381390 }, - { url = "https://files.pythonhosted.org/packages/88/89/76fb326578ddef91ed0b37209a10699676a30968ac66fbdd68d3759ba76b/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcac21f1913cdfbd776e207dddb8fd512d165fc721aa30837b0455fe30b01380", size = 332054 }, - { url = "https://files.pythonhosted.org/packages/80/00/ef022442a20ee215d221a49ece36bbe5c47428a6347b8908d71c7b645ffb/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1b0c62bca7b23a56ad927721a75ff80e4b47f761b8830731fa47acd75fd4fe4", size = 350080 }, - { url = "https://files.pythonhosted.org/packages/29/ff/52b35358f6c63e1fe1e6b80d24c41e5da0cfe3e431a9a49499c844414073/sqlglotrs-0.4.0-cp313-cp313-win32.whl", hash = "sha256:48413594321e0e367c8bdf624009f83b244fb5d94c5191ba40845a90ddcaf072", size = 173341 }, - { url = "https://files.pythonhosted.org/packages/12/92/9fe169442a1d1128f7d7ce689856a85db8e939608d708a3264f832636ae7/sqlglotrs-0.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:4c5941cbf28eedb581dfa101c7b04c5fbcb90b0dc8217251f3026d842aa1f038", size = 190136 }, - { url = "https://files.pythonhosted.org/packages/23/e0/9b955c605d9f381081edbce0ad0f1d40b96a0e10b7682861a90fe6cea06f/sqlglotrs-0.4.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:663d5cf377f6e930b1367bf0102e174734577a469c83e486b032157191bec10b", size = 300725 }, - { url = "https://files.pythonhosted.org/packages/f7/71/8fa93e25ec44ed8f3e8e242e24fcb60d84cd1a94980669cab6fa3a5a19ba/sqlglotrs-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:934789ac5b1fbc335edd6f933f8d7f08622267761a36d620572b3ddba5052fbd", size = 291312 }, - { url = "https://files.pythonhosted.org/packages/7a/c9/6dc62130802481fd230b3e08f1f384487e64aeafd2be543d9974d0dd057f/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:605ad9a78729d56ca7e556a0ab203532a890ca376b10eca4b3fad7d66c92d1c2", size = 327155 }, - { url = "https://files.pythonhosted.org/packages/5a/3d/fa193420170728c5d381c5bfdf87b903ed75f531f2ace1c7b3a47469c099/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:22064535810647164fa0e4c3bbb81373f5dc15b5b664a5a2754d60602062bb1b", size = 334695 }, - { url = "https://files.pythonhosted.org/packages/1c/e0/67c14b63b40774d11b5300acd87674d76fc63ab74626f976653e99b5b2ca/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:456a6c9e72414eaebe49f48c70484d4c3400878dbbb2bc55944df2292d16c47e", size = 394847 }, - { url = "https://files.pythonhosted.org/packages/9e/2d/724be628d29e0ead6cf30c342f70ed80a49ebe8f3a983dd8049fd14c2476/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64802ec9bba965c635b9876420c8015af900126a07c9f91a19a81011ed6d7d10", size = 385454 }, - { url = "https://files.pythonhosted.org/packages/d1/20/b6932c1d5cb0113727eec68570e5c6c208a676225dd9b586b2c24348265f/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48732eb680b5e0051e2de4dcefbb80d762950b43c1bd55e6edec17ada01ec42b", size = 332743 }, - { url = "https://files.pythonhosted.org/packages/1f/2f/511fd6513181b1359c1d439689e4b1053face65857483d89f05486ce72bb/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9cdd230b809aacfdc2017b9a2777e5c3e0bce6b48f373c6b0a328ce00c58de2f", size = 352228 }, - { url = "https://files.pythonhosted.org/packages/d5/64/b91afcebcc44739abf29dfd5b85e2107e3ecadb485e88e9d74820b308291/sqlglotrs-0.4.0-cp39-cp39-win32.whl", hash = "sha256:d1bfebb08f7a0e65d9638df0481da79dd05a27309df9894076c860edd0ab9503", size = 175031 }, - { url = "https://files.pythonhosted.org/packages/e6/b4/83402497b705cd76603c7994769a75eded0d63efc63c73c9901ad0ef66e0/sqlglotrs-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:d9a9049e17ee50c7e997bbd065bd2d0e5a8d247e8c101e724cdc07d948704668", size = 190723 }, +sdist = { url = "https://files.pythonhosted.org/packages/51/1a/72690c890410b4da2a96b37305ef4063f9bb24f830208c02329d1f370a12/sqlglotrs-0.4.0.tar.gz", hash = "sha256:b3b73ba1c9c4699de6d9c710f23fbc639651af0ac73eec831bcd298eda059582", size = 15419, upload-time = "2025-02-26T13:05:58.285Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/b3/022d8b1eea627d8bb49b8bd7de4e71efb27f46cb86bb6d371aec8e9aa54d/sqlglotrs-0.4.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:065bea5861d613ee27967cdd76d5176303595d9794e0a2dd4a1027f2ebe6ad91", size = 299788, upload-time = "2025-02-26T13:05:43.878Z" }, + { url = "https://files.pythonhosted.org/packages/4a/ed/2c577fcbc3c9d85e425e86fe012af59ddbed203d32efc41114b3b846a148/sqlglotrs-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9d033bce2be9db48deebf243610a4b467e76c68a80fd989de18f976712d92424", size = 290131, upload-time = "2025-02-26T13:05:30.107Z" }, + { url = "https://files.pythonhosted.org/packages/f8/db/430e3d329d28ad1ea6f71dfa9942bbeae8e208aa96c19ad69f837fc54a1f/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac19a13910f112659b2e8b1f6ca03de1c628b40881936d9013159c57cce847f7", size = 326948, upload-time = "2025-02-26T13:04:07.331Z" }, + { url = "https://files.pythonhosted.org/packages/11/5a/32da4e4c7f72b8a0a30c76d46460a9867d0f94ee2dddcb25db658651e438/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86ec7dc45c830efa5c54a424430ec03f25553038437690ff4b9e0365bcb564fc", size = 333051, upload-time = "2025-02-26T13:04:20.818Z" }, + { url = "https://files.pythonhosted.org/packages/14/ef/e9d7a54fc0c72d5a8c9e1387faee6799e687c559fc6015828d0513373e71/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69e327cce71f797f073c0c52e77c2087da9b8dc55740b64b6e73ddc138ed38a8", size = 394437, upload-time = "2025-02-26T13:04:51.341Z" }, + { url = "https://files.pythonhosted.org/packages/83/a5/4f8383b9f7b8496dbde6e2e6896b722767696915bfb0105fbaa8b60e54ca/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8870c4e7e199a2865f80674964e74a45f10466e5b77fea2ca408d24765816e40", size = 385058, upload-time = "2025-02-26T13:05:05.256Z" }, + { url = "https://files.pythonhosted.org/packages/0e/79/41e728d0c5173cc0756fd4667a52693cc683962a7aea0ef8b01f4184a733/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a689435bf41a09862efe4be447c4f49a406890c58896739623f46e45ed7a8321", size = 332059, upload-time = "2025-02-26T13:05:18.252Z" }, + { url = "https://files.pythonhosted.org/packages/3f/1f/3c10a3b8957018e0f6ec0c23869f8e50f883fdcf7dde18318e4e66805f94/sqlglotrs-0.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9332a3590ef914271e4762a5713a5f0cacf5fd02d69a70336baafbe1ad3b2d0", size = 350954, upload-time = "2025-02-26T13:04:36.164Z" }, + { url = "https://files.pythonhosted.org/packages/50/93/ca92bc7d38cee72366159345f87529db909f4c86882364087cec802d6f46/sqlglotrs-0.4.0-cp310-cp310-win32.whl", hash = "sha256:27cef20a2169e5378bb3013c889c499a637293b5e871bee225fc3cba47216890", size = 174519, upload-time = "2025-02-26T13:06:00.651Z" }, + { url = "https://files.pythonhosted.org/packages/17/5f/de62f31e48544b46c8f7e4fcfb175b4e5d00641c6e29c70af65793a8c374/sqlglotrs-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:8dcca8d84ed734d77fe767c54ef7760b3b7b6ca4ca3e60b76af427375dc331c3", size = 189704, upload-time = "2025-02-26T13:06:11.789Z" }, + { url = "https://files.pythonhosted.org/packages/84/c9/f01d691becbfc8e668b7aefb0d1fa2ef6841650e0c0394d884777ec435b6/sqlglotrs-0.4.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2bba88aba5f99dbd80caedaf820dcdf2699d906900f895b63e596f3fc7cfd134", size = 299654, upload-time = "2025-02-26T13:05:45.336Z" }, + { url = "https://files.pythonhosted.org/packages/6f/dc/d3ca4048cc7721043808a29bfad7251dc7c62e2b0145bbdf0b978ffe6424/sqlglotrs-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28495248e27e67943d794b4d0b065dd18522b35c8e890a595da36f5d6f856de0", size = 290101, upload-time = "2025-02-26T13:05:32.424Z" }, + { url = "https://files.pythonhosted.org/packages/e6/39/a1a04779dc4125ae5555b584af057c55a5e50a48e2f4669f6fe255108644/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b168d52d8d14657143c3beafcbb2929df3772595e914cdb80a926e36e727fd", size = 326842, upload-time = "2025-02-26T13:04:09.778Z" }, + { url = "https://files.pythonhosted.org/packages/9f/bb/482e4d2284710a699534eacab315e907870cadbb2fcd6414ee2b04c3c058/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c120f951d67196301a753225e4b350686fa1bf98ba3504e8e06ba90e2f4eb88", size = 333250, upload-time = "2025-02-26T13:04:24.067Z" }, + { url = "https://files.pythonhosted.org/packages/35/2c/0a69e059692d20ce2b05367e4d23e21cfb45d8001f9bfa4edb1e529f0a7d/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fa98390de3994c6956120d7323504eb511c78d866981b35cc36c2a3544ead57", size = 394549, upload-time = "2025-02-26T13:04:52.881Z" }, + { url = "https://files.pythonhosted.org/packages/15/08/f4a8f988623b2813ce311aa19738bfc8b6e80c9756b2c756eb287c904355/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a290aa2bedcc103a422ad9e27134b0973e3caefe08aa6ac6a8528e96c6a119d0", size = 384649, upload-time = "2025-02-26T13:05:06.864Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/713246e2606b9008588bb1cdc6377ffc2df10aa8fbbf7e7dd5e8c816abe7/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dd563eac836154c0058e851aeb8f750ac8957d67aca850816cb9137df95e088", size = 332020, upload-time = "2025-02-26T13:05:20.31Z" }, + { url = "https://files.pythonhosted.org/packages/56/49/774d571ea5b3ff0345b2c580b20fcc1e81c206a07a9c3ec89bee7662cf03/sqlglotrs-0.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4e055ccf9416ea76855d515ac3621c3e5014f700e7e4c7810f65690adbaf0b", size = 350969, upload-time = "2025-02-26T13:04:37.57Z" }, + { url = "https://files.pythonhosted.org/packages/cf/cd/36e948f72f8cde21c118b92b3ec1a363569e8d1af92ffaa0a4c9a9468f40/sqlglotrs-0.4.0-cp311-cp311-win32.whl", hash = "sha256:f6225ba2d0713d709448fc89e14b6b2c7c2b27a42b0f20d5d98fb69cc387a111", size = 174461, upload-time = "2025-02-26T13:06:02.586Z" }, + { url = "https://files.pythonhosted.org/packages/c4/7e/511d59f7f012800a1aa780a28c973fd2576657066724b62a790d7da23df8/sqlglotrs-0.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:e398740d9d6109ae6919f983f7e56e4d314c63d17803556a16771731688b47be", size = 189814, upload-time = "2025-02-26T13:06:13.87Z" }, + { url = "https://files.pythonhosted.org/packages/3e/98/120acd4301a90a816606e120fa216d7da6b70b85d0895d30fed94760d664/sqlglotrs-0.4.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:69b4e8121d86bccd4e55cbc2822b9eb96da510608df91cbb3701a1e33fb54813", size = 299691, upload-time = "2025-02-26T13:05:47.551Z" }, + { url = "https://files.pythonhosted.org/packages/cc/30/d6cb97dcfd57ff9bc56d07ade39b46133dad91143d7c676c197fdfb4258a/sqlglotrs-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fa3e5b0c5a976a61ad6219fddb6ef10f603771119a303ba3c5046a6daf89b207", size = 290439, upload-time = "2025-02-26T13:05:34.084Z" }, + { url = "https://files.pythonhosted.org/packages/9c/73/70e2fc314291fa2543cc54a37869f2df2cfab2f649fd15c3fed4c28b6d62/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24b1a3f5685fd12f376b97734284bdcb4d17d703436993686f45ea275a14d83a", size = 326375, upload-time = "2025-02-26T13:04:11.319Z" }, + { url = "https://files.pythonhosted.org/packages/27/6c/4a6545301b4c2e944adccf23da2fc1e9aeaf48d95ade73334c9aff0ab91e/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dbeacf80e99c87e2334e9a8af8c6efa06e81ceaf98c9eca22780f6ee286fd190", size = 333105, upload-time = "2025-02-26T13:04:27.328Z" }, + { url = "https://files.pythonhosted.org/packages/14/cb/7898b1e3678f313b08a6681968ecc70007e87003d436b5e5abd88709e40a/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58046e18d19d122027f0a4496791e8f107e396ce5866ea6973828a4a8c2feef", size = 394334, upload-time = "2025-02-26T13:04:54.937Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d0/fe5a16e5c3fd445185584bf98d1309fd70dc24ed19cf896e4137e05d8b81/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cab9c83335d33306657461f4ad61cda3df3ef7d3826234508689978f3a02c436", size = 382242, upload-time = "2025-02-26T13:05:09.247Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a0/667eb1deb9b5a998d610b203dffcf0c6f2d7ca41ed237ea4b9f24ca40970/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b5fcd4897a7453e85dfaecb0451972c874c0e39fe7d2636edd2102c2f441e0", size = 332244, upload-time = "2025-02-26T13:05:22.501Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b6/2017d4a0805ad75b56d0cff8d5d32974ca709886175d828530bf16301f5f/sqlglotrs-0.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e5e00b51a470bbd2fde561313c749220bcaef5293d092ac03983b114b00f35b", size = 350271, upload-time = "2025-02-26T13:04:40.254Z" }, + { url = "https://files.pythonhosted.org/packages/ce/c3/d5366f836db1a7729fa86105965f8d11771ca7d64a477f612246dbf52c76/sqlglotrs-0.4.0-cp312-cp312-win32.whl", hash = "sha256:c53c78acb15adcc4470c79fdfe90d13c09a61122b12fd9ff679210f37315a038", size = 173762, upload-time = "2025-02-26T13:06:03.957Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ff/7860811859bef843776a8063297512d95def039db58aecf8126e33d629ea/sqlglotrs-0.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:c9059e7586b19fb426595fe5c2167702bef92aa4562becdcb29f323f9491f2d5", size = 190577, upload-time = "2025-02-26T13:06:15.661Z" }, + { url = "https://files.pythonhosted.org/packages/31/63/d9407aa1fe4d9e88e6751703d4b6b62b19b8de9131f4980c4682c3e1ff32/sqlglotrs-0.4.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7a10d8cd702f4df9ea4533ddc7a3b1cd1d9cb4c3c150d64cc8a51544599c5051", size = 299227, upload-time = "2025-02-26T13:05:49.102Z" }, + { url = "https://files.pythonhosted.org/packages/40/e8/b4e142b087d8c657886517d235e628fee5884a7839048ac3bf058d8ae335/sqlglotrs-0.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14ae854d3480e9413bce3eb779e4735512e06f443930a81c525bc96b203c7548", size = 289923, upload-time = "2025-02-26T13:05:35.698Z" }, + { url = "https://files.pythonhosted.org/packages/24/97/711ea1790142a801186b5539fc8568aafbb9fa9984eb2e5baef3ab6a42fc/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b630583236e22b1504cff416127b5c3ba9569832db0900cdc05066b54e13b726", size = 325831, upload-time = "2025-02-26T13:04:13.528Z" }, + { url = "https://files.pythonhosted.org/packages/cb/63/037566779c93b723a62883caedb01d2cd62c80a39c15cd5750175fdf6b40/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6e935e0c5511ad1258f2a7cd9a9fb09484fd5c58b250dfb5ab5b6cbe4581de9c", size = 332559, upload-time = "2025-02-26T13:04:28.958Z" }, + { url = "https://files.pythonhosted.org/packages/84/91/2b6a46f21c0202286817cb4e085ccabe7d5065ff22c3719b8047d068ee62/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18755ddf63bb0b573ed4bb36db779ac98ab63853086d9126f27467bf15c954be", size = 394570, upload-time = "2025-02-26T13:04:56.662Z" }, + { url = "https://files.pythonhosted.org/packages/82/97/1a222cef008f1998a558638186d217066b57670087f4674fad5444a25f86/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52b89640001564850148fbc9dcb19b3382b41f449c0691498188dac08b9591ff", size = 381390, upload-time = "2025-02-26T13:05:10.706Z" }, + { url = "https://files.pythonhosted.org/packages/88/89/76fb326578ddef91ed0b37209a10699676a30968ac66fbdd68d3759ba76b/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcac21f1913cdfbd776e207dddb8fd512d165fc721aa30837b0455fe30b01380", size = 332054, upload-time = "2025-02-26T13:05:23.966Z" }, + { url = "https://files.pythonhosted.org/packages/80/00/ef022442a20ee215d221a49ece36bbe5c47428a6347b8908d71c7b645ffb/sqlglotrs-0.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1b0c62bca7b23a56ad927721a75ff80e4b47f761b8830731fa47acd75fd4fe4", size = 350080, upload-time = "2025-02-26T13:04:43.538Z" }, + { url = "https://files.pythonhosted.org/packages/29/ff/52b35358f6c63e1fe1e6b80d24c41e5da0cfe3e431a9a49499c844414073/sqlglotrs-0.4.0-cp313-cp313-win32.whl", hash = "sha256:48413594321e0e367c8bdf624009f83b244fb5d94c5191ba40845a90ddcaf072", size = 173341, upload-time = "2025-02-26T13:06:05.351Z" }, + { url = "https://files.pythonhosted.org/packages/12/92/9fe169442a1d1128f7d7ce689856a85db8e939608d708a3264f832636ae7/sqlglotrs-0.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:4c5941cbf28eedb581dfa101c7b04c5fbcb90b0dc8217251f3026d842aa1f038", size = 190136, upload-time = "2025-02-26T13:06:17.011Z" }, + { url = "https://files.pythonhosted.org/packages/23/e0/9b955c605d9f381081edbce0ad0f1d40b96a0e10b7682861a90fe6cea06f/sqlglotrs-0.4.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:663d5cf377f6e930b1367bf0102e174734577a469c83e486b032157191bec10b", size = 300725, upload-time = "2025-02-26T13:05:56.833Z" }, + { url = "https://files.pythonhosted.org/packages/f7/71/8fa93e25ec44ed8f3e8e242e24fcb60d84cd1a94980669cab6fa3a5a19ba/sqlglotrs-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:934789ac5b1fbc335edd6f933f8d7f08622267761a36d620572b3ddba5052fbd", size = 291312, upload-time = "2025-02-26T13:05:41.582Z" }, + { url = "https://files.pythonhosted.org/packages/7a/c9/6dc62130802481fd230b3e08f1f384487e64aeafd2be543d9974d0dd057f/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:605ad9a78729d56ca7e556a0ab203532a890ca376b10eca4b3fad7d66c92d1c2", size = 327155, upload-time = "2025-02-26T13:04:19.488Z" }, + { url = "https://files.pythonhosted.org/packages/5a/3d/fa193420170728c5d381c5bfdf87b903ed75f531f2ace1c7b3a47469c099/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:22064535810647164fa0e4c3bbb81373f5dc15b5b664a5a2754d60602062bb1b", size = 334695, upload-time = "2025-02-26T13:04:33.816Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e0/67c14b63b40774d11b5300acd87674d76fc63ab74626f976653e99b5b2ca/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:456a6c9e72414eaebe49f48c70484d4c3400878dbbb2bc55944df2292d16c47e", size = 394847, upload-time = "2025-02-26T13:05:02.141Z" }, + { url = "https://files.pythonhosted.org/packages/9e/2d/724be628d29e0ead6cf30c342f70ed80a49ebe8f3a983dd8049fd14c2476/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64802ec9bba965c635b9876420c8015af900126a07c9f91a19a81011ed6d7d10", size = 385454, upload-time = "2025-02-26T13:05:16.837Z" }, + { url = "https://files.pythonhosted.org/packages/d1/20/b6932c1d5cb0113727eec68570e5c6c208a676225dd9b586b2c24348265f/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48732eb680b5e0051e2de4dcefbb80d762950b43c1bd55e6edec17ada01ec42b", size = 332743, upload-time = "2025-02-26T13:05:28.426Z" }, + { url = "https://files.pythonhosted.org/packages/1f/2f/511fd6513181b1359c1d439689e4b1053face65857483d89f05486ce72bb/sqlglotrs-0.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9cdd230b809aacfdc2017b9a2777e5c3e0bce6b48f373c6b0a328ce00c58de2f", size = 352228, upload-time = "2025-02-26T13:04:48.799Z" }, + { url = "https://files.pythonhosted.org/packages/d5/64/b91afcebcc44739abf29dfd5b85e2107e3ecadb485e88e9d74820b308291/sqlglotrs-0.4.0-cp39-cp39-win32.whl", hash = "sha256:d1bfebb08f7a0e65d9638df0481da79dd05a27309df9894076c860edd0ab9503", size = 175031, upload-time = "2025-02-26T13:06:10.395Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b4/83402497b705cd76603c7994769a75eded0d63efc63c73c9901ad0ef66e0/sqlglotrs-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:d9a9049e17ee50c7e997bbd065bd2d0e5a8d247e8c101e724cdc07d948704668", size = 190723, upload-time = "2025-02-26T13:06:21.454Z" }, ] [[package]] name = "sqlparse" version = "0.5.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999 } +sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999, upload-time = "2024-12-10T12:05:30.728Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415 }, + { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" }, ] [[package]] @@ -3757,7 +3776,7 @@ dev = [ { name = "sphinx-autobuild" }, { name = "sphinx-autodoc-typehints", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx-autodoc-typehints", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "sphinx-autodoc-typehints", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-autodoc-typehints", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-click" }, { name = "sphinx-copybutton" }, { name = "sphinx-design" }, @@ -3779,7 +3798,7 @@ doc = [ { name = "sphinx-autobuild" }, { name = "sphinx-autodoc-typehints", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx-autodoc-typehints", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "sphinx-autodoc-typehints", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-autodoc-typehints", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-click" }, { name = "sphinx-copybutton" }, { name = "sphinx-design" }, @@ -3946,9 +3965,9 @@ test = [ name = "standard-imghdr" version = "3.10.14" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/09/d2/2eb5521072c9598886035c65c023f39f7384bcb73eed70794f469e34efac/standard_imghdr-3.10.14.tar.gz", hash = "sha256:2598fe2e7c540dbda34b233295e10957ab8dc8ac6f3bd9eaa8d38be167232e52", size = 5474 } +sdist = { url = "https://files.pythonhosted.org/packages/09/d2/2eb5521072c9598886035c65c023f39f7384bcb73eed70794f469e34efac/standard_imghdr-3.10.14.tar.gz", hash = "sha256:2598fe2e7c540dbda34b233295e10957ab8dc8ac6f3bd9eaa8d38be167232e52", size = 5474, upload-time = "2024-04-21T18:55:10.859Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/d0/9852f70eb01f814843530c053542b72d30e9fbf74da7abb0107e71938389/standard_imghdr-3.10.14-py3-none-any.whl", hash = "sha256:cdf6883163349624dee9a81d2853a20260337c4cd41c04e99c082e01833a08e2", size = 5598 }, + { url = "https://files.pythonhosted.org/packages/fb/d0/9852f70eb01f814843530c053542b72d30e9fbf74da7abb0107e71938389/standard_imghdr-3.10.14-py3-none-any.whl", hash = "sha256:cdf6883163349624dee9a81d2853a20260337c4cd41c04e99c082e01833a08e2", size = 5598, upload-time = "2024-04-21T18:54:48.587Z" }, ] [[package]] @@ -3959,93 +3978,93 @@ dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846 } +sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846, upload-time = "2025-04-13T13:56:17.942Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037 }, + { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037, upload-time = "2025-04-13T13:56:16.21Z" }, ] [[package]] name = "tabulate" version = "0.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090 } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252 }, + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, ] [[package]] name = "termcolor" -version = "3.0.1" +version = "3.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f8/b6/8e2aaa8aeb570b5cc955cd913b083d96c5447bbe27eaf330dfd7cc8e3329/termcolor-3.0.1.tar.gz", hash = "sha256:a6abd5c6e1284cea2934443ba806e70e5ec8fd2449021be55c280f8a3731b611", size = 12935 } +sdist = { url = "https://files.pythonhosted.org/packages/ca/6c/3d75c196ac07ac8749600b60b03f4f6094d54e132c4d94ebac6ee0e0add0/termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970", size = 14324, upload-time = "2025-04-30T11:37:53.791Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/7e/a574ccd49ad07e8b117407bac361f1e096b01f1b620365daf60ff702c936/termcolor-3.0.1-py3-none-any.whl", hash = "sha256:da1ed4ec8a5dc5b2e17476d859febdb3cccb612be1c36e64511a6f2485c10c69", size = 7157 }, + { url = "https://files.pythonhosted.org/packages/4f/bd/de8d508070629b6d84a30d01d57e4a65c69aa7f5abe7560b8fad3b50ea59/termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa", size = 7684, upload-time = "2025-04-30T11:37:52.382Z" }, ] [[package]] name = "tomli" version = "2.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, ] [[package]] name = "tomlkit" version = "0.13.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 } +sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885, upload-time = "2024-08-14T08:19:41.488Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 }, + { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955, upload-time = "2024-08-14T08:19:40.05Z" }, ] [[package]] name = "types-colorama" version = "0.4.15.20240311" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/59/73/0fb0b9fe4964b45b2a06ed41b60c352752626db46aa0fb70a49a9e283a75/types-colorama-0.4.15.20240311.tar.gz", hash = "sha256:a28e7f98d17d2b14fb9565d32388e419f4108f557a7d939a66319969b2b99c7a", size = 5608 } +sdist = { url = "https://files.pythonhosted.org/packages/59/73/0fb0b9fe4964b45b2a06ed41b60c352752626db46aa0fb70a49a9e283a75/types-colorama-0.4.15.20240311.tar.gz", hash = "sha256:a28e7f98d17d2b14fb9565d32388e419f4108f557a7d939a66319969b2b99c7a", size = 5608, upload-time = "2024-03-11T02:15:51.557Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/83/6944b4fa01efb2e63ac62b791a8ddf0fee358f93be9f64b8f152648ad9d3/types_colorama-0.4.15.20240311-py3-none-any.whl", hash = "sha256:6391de60ddc0db3f147e31ecb230006a6823e81e380862ffca1e4695c13a0b8e", size = 5840 }, + { url = "https://files.pythonhosted.org/packages/b7/83/6944b4fa01efb2e63ac62b791a8ddf0fee358f93be9f64b8f152648ad9d3/types_colorama-0.4.15.20240311-py3-none-any.whl", hash = "sha256:6391de60ddc0db3f147e31ecb230006a6823e81e380862ffca1e4695c13a0b8e", size = 5840, upload-time = "2024-03-11T02:15:50.43Z" }, ] [[package]] name = "types-docutils" version = "0.21.0.20241128" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dd/df/64e7ab01a4fc5ce46895dc94e31cffc8b8087c8d91ee54c45ac2d8d82445/types_docutils-0.21.0.20241128.tar.gz", hash = "sha256:4dd059805b83ac6ec5a223699195c4e9eeb0446a4f7f2aeff1759a4a7cc17473", size = 26739 } +sdist = { url = "https://files.pythonhosted.org/packages/dd/df/64e7ab01a4fc5ce46895dc94e31cffc8b8087c8d91ee54c45ac2d8d82445/types_docutils-0.21.0.20241128.tar.gz", hash = "sha256:4dd059805b83ac6ec5a223699195c4e9eeb0446a4f7f2aeff1759a4a7cc17473", size = 26739, upload-time = "2024-11-28T02:54:57.756Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/b6/10ba95739f2cbb9c5bd2f6568148d62b468afe01a94c633e8892a2936d8a/types_docutils-0.21.0.20241128-py3-none-any.whl", hash = "sha256:e0409204009639e9b0bf4521eeabe58b5e574ce9c0db08421c2ac26c32be0039", size = 34677 }, + { url = "https://files.pythonhosted.org/packages/59/b6/10ba95739f2cbb9c5bd2f6568148d62b468afe01a94c633e8892a2936d8a/types_docutils-0.21.0.20241128-py3-none-any.whl", hash = "sha256:e0409204009639e9b0bf4521eeabe58b5e574ce9c0db08421c2ac26c32be0039", size = 34677, upload-time = "2024-11-28T02:54:55.64Z" }, ] [[package]] @@ -4055,18 +4074,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "types-docutils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e6/be/88f777c75022b111f9e9fe4cdb430bf92892fe90188b0fd037601ded2ea1/types_pygments-2.19.0.20250305.tar.gz", hash = "sha256:044c50e80ecd4128c00a7268f20355e16f5c55466d3d49dfda09be920af40b4b", size = 18521 } +sdist = { url = "https://files.pythonhosted.org/packages/e6/be/88f777c75022b111f9e9fe4cdb430bf92892fe90188b0fd037601ded2ea1/types_pygments-2.19.0.20250305.tar.gz", hash = "sha256:044c50e80ecd4128c00a7268f20355e16f5c55466d3d49dfda09be920af40b4b", size = 18521, upload-time = "2025-03-05T02:47:46.463Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/c6/b6d3ad345b76425e46d25a2da1758603d80c3a59405bdcbbbaa86d8c8070/types_pygments-2.19.0.20250305-py3-none-any.whl", hash = "sha256:ca88aae5ec426f9b107c0f7adc36dc096d2882d930a49f679eaf4b8b643db35d", size = 25638 }, + { url = "https://files.pythonhosted.org/packages/6f/c6/b6d3ad345b76425e46d25a2da1758603d80c3a59405bdcbbbaa86d8c8070/types_pygments-2.19.0.20250305-py3-none-any.whl", hash = "sha256:ca88aae5ec426f9b107c0f7adc36dc096d2882d930a49f679eaf4b8b643db35d", size = 25638, upload-time = "2025-03-05T02:47:45.045Z" }, ] [[package]] name = "typing-extensions" version = "4.13.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 }, + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, ] [[package]] @@ -4076,61 +4095,61 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222 } +sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 }, + { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, ] [[package]] name = "tzdata" version = "2025.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 } +sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 }, + { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, ] [[package]] name = "urllib3" version = "2.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672 } +sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 }, + { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, ] [[package]] name = "uuid-utils" version = "0.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/0a/cbdb2eb4845dafeb632d02a18f47b02f87f2ce4f25266f5e3c017976ce89/uuid_utils-0.10.0.tar.gz", hash = "sha256:5db0e1890e8f008657ffe6ded4d9459af724ab114cfe82af1557c87545301539", size = 18828 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/44/54/9d22fa16b19e5d1676eba510f08a9c458d96e2a62ff2c8ebad64251afb18/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d5a4508feefec62456cd6a41bcdde458d56827d908f226803b886d22a3d5e63", size = 573006 }, - { url = "https://files.pythonhosted.org/packages/08/8e/f895c6e52aa603e521fbc13b8626ba5dd99b6e2f5a55aa96ba5b232f4c53/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dbefc2b9113f9dfe56bdae58301a2b3c53792221410d422826f3d1e3e6555fe7", size = 292543 }, - { url = "https://files.pythonhosted.org/packages/b6/58/cc4834f377a5e97d6e184408ad96d13042308de56643b6e24afe1f6f34df/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffc49c33edf87d1ec8112a9b43e4cf55326877716f929c165a2cc307d31c73d5", size = 323340 }, - { url = "https://files.pythonhosted.org/packages/37/e3/6aeddf148f6a7dd7759621b000e8c85382ec83f52ae79b60842d1dc3ab6b/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0636b6208f69d5a4e629707ad2a89a04dfa8d1023e1999181f6830646ca048a1", size = 329653 }, - { url = "https://files.pythonhosted.org/packages/0c/00/dd6c2164ace70b7b1671d9129267df331481d7d1e5f9c5e6a564f07953f6/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc06452856b724df9dedfc161c3582199547da54aeb81915ec2ed54f92d19b0", size = 365471 }, - { url = "https://files.pythonhosted.org/packages/b4/e7/0ab8080fcae5462a7b5e555c1cef3d63457baffb97a59b9bc7b005a3ecb1/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:263b2589111c61decdd74a762e8f850c9e4386fb78d2cf7cb4dfc537054cda1b", size = 325844 }, - { url = "https://files.pythonhosted.org/packages/73/39/52d94e9ef75b03f44b39ffc6ac3167e93e74ef4d010a93d25589d9f48540/uuid_utils-0.10.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a558db48b7096de6b4d2d2210d82bba8586a6d55f99106b03bb7d01dc5c5bcd6", size = 344389 }, - { url = "https://files.pythonhosted.org/packages/7c/29/4824566f62666238290d99c62a58e4ab2a8b9cf2eccf94cebd9b3359131e/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:807465067f3c892514230326ac71a79b28a8dfe2c88ecd2d5675fc844f3c76b5", size = 510078 }, - { url = "https://files.pythonhosted.org/packages/5e/8f/bbcc7130d652462c685f0d3bd26bb214b754215b476340885a4cb50fb89a/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:57423d4a2b9d7b916de6dbd75ba85465a28f9578a89a97f7d3e098d9aa4e5d4a", size = 515937 }, - { url = "https://files.pythonhosted.org/packages/23/f8/34e0c00f5f188604d336713e6a020fcf53b10998e8ab24735a39ab076740/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76d8d660f18ff6b767e319b1b5f927350cd92eafa4831d7ef5b57fdd1d91f974", size = 494111 }, - { url = "https://files.pythonhosted.org/packages/1a/52/b7f0066cc90a7a9c28d54061ed195cd617fde822e5d6ac3ccc88509c3c44/uuid_utils-0.10.0-cp39-abi3-win32.whl", hash = "sha256:6c11a71489338837db0b902b75e1ba7618d5d29f05fde4f68b3f909177dbc226", size = 173520 }, - { url = "https://files.pythonhosted.org/packages/8b/15/f04f58094674d333974243fb45d2c740cf4b79186fb707168e57943c84a3/uuid_utils-0.10.0-cp39-abi3-win_amd64.whl", hash = "sha256:11c55ae64f6c0a7a0c741deae8ca2a4eaa11e9c09dbb7bec2099635696034cf7", size = 182965 }, - { url = "https://files.pythonhosted.org/packages/c9/1f/8f3288797487c82981134732dee13b1ad12082890905476f95994ce49e0f/uuid_utils-0.10.0-pp310-pypy310_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:acea543dfc7b87df749e3e814c54ac739a82ff5e3800d25bd25a3e00599e1554", size = 573053 }, - { url = "https://files.pythonhosted.org/packages/91/28/0eb5190aa39547015d60ce5453cfd37c4d87a48d25026d72044c20cad4fc/uuid_utils-0.10.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0767eefa7b1e96f06cfa9b95758d286240c01bbf19e9d8f1b6043cdbe76cc639", size = 292596 }, - { url = "https://files.pythonhosted.org/packages/e4/27/a451725d5df0db8baaa84adde94bbac4a33c3816a5215740c3f1dbdc46d3/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973fe4bb5258fd2ccb144d8b40c2d3158f16cc856a20527f8b40d14b2ae1dee9", size = 323414 }, - { url = "https://files.pythonhosted.org/packages/22/6b/0edc2ad855cbe07ffd891ec636c6ff57ae3a56cdf0e90467b2edbe5b7b43/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71b8505b67a0d77d0fbd765d8463094a8f447677125da7647bec7ea0b99406f0", size = 329720 }, - { url = "https://files.pythonhosted.org/packages/4b/1d/f73af741d9a4d3168704235ef06fbda823bf2ecf551ac29caa8d7cf8ea2a/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdcb1211bb61476cbef12a87101fa48243e20ed82b2bd324c816b1b5826bd5e", size = 365545 }, - { url = "https://files.pythonhosted.org/packages/b1/06/92104c8ea66a6d645f00520222a52c4b91a444c2c30201ff0036dedfb8da/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c5247f1df040aae71ea313819b563debe69bca7086a2cc6a3ac0eaddd3dadac", size = 325920 }, - { url = "https://files.pythonhosted.org/packages/94/fe/0710e28b94f2311b40757dc43513290134cb4579f79981127c58640d736c/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a50bd29ef89660b93aa07ffa95ac691a0e12832375030569a8bd5c9272f3b8e6", size = 344458 }, - { url = "https://files.pythonhosted.org/packages/0b/8f/c12d449789d756f6c0ed81de060900c0e616f80d1e3944949859921ef1e5/uuid_utils-0.10.0-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a778cd9d8f995b94bba6e51f3ebee5b338fd834b0c4ecc8f932bd23e29db3e19", size = 573049 }, - { url = "https://files.pythonhosted.org/packages/03/ac/85677abca4832417b28e40c7b634820158e29c57da780de2f3a131b6e24d/uuid_utils-0.10.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d3d5b5c5ed66ff923961b9ebb902232cd67f6a7ec6b6f7a58e05e00ff44e3c7f", size = 292587 }, - { url = "https://files.pythonhosted.org/packages/cf/35/7d909b7acfb7eec3af0f671b5fec8ae88fdf60857a4f6344a83d0286837a/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:789ed6335225326c66f5d6162649bed978105a85f232be7811387c395c226801", size = 323412 }, - { url = "https://files.pythonhosted.org/packages/e8/9c/daff11748511fef37d8959bc83fb3f5d50128292a9e10c50c4aa02390cd2/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:05d1aa7b944b719eb1ee472435ae5444a3f8a00eb6350e3b1d1217d738477d33", size = 329716 }, - { url = "https://files.pythonhosted.org/packages/45/2c/30c7ef5dfc07f41854a46a09858419483376091731973ae91ac50392fe17/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa8d8559c2d25d6ac87e0adeee601d2c91ec40b357ab780bcf79061cc23324e6", size = 365539 }, - { url = "https://files.pythonhosted.org/packages/2c/28/196f2b4c2717d865b8a0eb2064f7e69d31533b58a2528edf64b1c18cd943/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0badcbfe3c72b5b30d59c2b12f120923127abd95a0d2aa64ddc1234e495abc2", size = 325916 }, - { url = "https://files.pythonhosted.org/packages/87/a6/485bec297615b530aa967eef7b212a33d02a72441846642d721dedb307fb/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a7c1c494012335113748815156c5b6234c59b0fe0d3a8eede1b1a46f7e25a69", size = 344453 }, +sdist = { url = "https://files.pythonhosted.org/packages/66/0a/cbdb2eb4845dafeb632d02a18f47b02f87f2ce4f25266f5e3c017976ce89/uuid_utils-0.10.0.tar.gz", hash = "sha256:5db0e1890e8f008657ffe6ded4d9459af724ab114cfe82af1557c87545301539", size = 18828, upload-time = "2024-11-21T13:57:40.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/54/9d22fa16b19e5d1676eba510f08a9c458d96e2a62ff2c8ebad64251afb18/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d5a4508feefec62456cd6a41bcdde458d56827d908f226803b886d22a3d5e63", size = 573006, upload-time = "2024-11-21T13:56:50.873Z" }, + { url = "https://files.pythonhosted.org/packages/08/8e/f895c6e52aa603e521fbc13b8626ba5dd99b6e2f5a55aa96ba5b232f4c53/uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dbefc2b9113f9dfe56bdae58301a2b3c53792221410d422826f3d1e3e6555fe7", size = 292543, upload-time = "2024-11-21T13:56:54.677Z" }, + { url = "https://files.pythonhosted.org/packages/b6/58/cc4834f377a5e97d6e184408ad96d13042308de56643b6e24afe1f6f34df/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffc49c33edf87d1ec8112a9b43e4cf55326877716f929c165a2cc307d31c73d5", size = 323340, upload-time = "2024-11-21T13:56:57.665Z" }, + { url = "https://files.pythonhosted.org/packages/37/e3/6aeddf148f6a7dd7759621b000e8c85382ec83f52ae79b60842d1dc3ab6b/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0636b6208f69d5a4e629707ad2a89a04dfa8d1023e1999181f6830646ca048a1", size = 329653, upload-time = "2024-11-21T13:56:59.365Z" }, + { url = "https://files.pythonhosted.org/packages/0c/00/dd6c2164ace70b7b1671d9129267df331481d7d1e5f9c5e6a564f07953f6/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc06452856b724df9dedfc161c3582199547da54aeb81915ec2ed54f92d19b0", size = 365471, upload-time = "2024-11-21T13:57:00.807Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e7/0ab8080fcae5462a7b5e555c1cef3d63457baffb97a59b9bc7b005a3ecb1/uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:263b2589111c61decdd74a762e8f850c9e4386fb78d2cf7cb4dfc537054cda1b", size = 325844, upload-time = "2024-11-21T13:57:02.309Z" }, + { url = "https://files.pythonhosted.org/packages/73/39/52d94e9ef75b03f44b39ffc6ac3167e93e74ef4d010a93d25589d9f48540/uuid_utils-0.10.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a558db48b7096de6b4d2d2210d82bba8586a6d55f99106b03bb7d01dc5c5bcd6", size = 344389, upload-time = "2024-11-21T13:57:03.788Z" }, + { url = "https://files.pythonhosted.org/packages/7c/29/4824566f62666238290d99c62a58e4ab2a8b9cf2eccf94cebd9b3359131e/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:807465067f3c892514230326ac71a79b28a8dfe2c88ecd2d5675fc844f3c76b5", size = 510078, upload-time = "2024-11-21T13:57:06.093Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8f/bbcc7130d652462c685f0d3bd26bb214b754215b476340885a4cb50fb89a/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:57423d4a2b9d7b916de6dbd75ba85465a28f9578a89a97f7d3e098d9aa4e5d4a", size = 515937, upload-time = "2024-11-21T13:57:07.855Z" }, + { url = "https://files.pythonhosted.org/packages/23/f8/34e0c00f5f188604d336713e6a020fcf53b10998e8ab24735a39ab076740/uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76d8d660f18ff6b767e319b1b5f927350cd92eafa4831d7ef5b57fdd1d91f974", size = 494111, upload-time = "2024-11-21T13:57:09.511Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/b7f0066cc90a7a9c28d54061ed195cd617fde822e5d6ac3ccc88509c3c44/uuid_utils-0.10.0-cp39-abi3-win32.whl", hash = "sha256:6c11a71489338837db0b902b75e1ba7618d5d29f05fde4f68b3f909177dbc226", size = 173520, upload-time = "2024-11-21T13:57:11.654Z" }, + { url = "https://files.pythonhosted.org/packages/8b/15/f04f58094674d333974243fb45d2c740cf4b79186fb707168e57943c84a3/uuid_utils-0.10.0-cp39-abi3-win_amd64.whl", hash = "sha256:11c55ae64f6c0a7a0c741deae8ca2a4eaa11e9c09dbb7bec2099635696034cf7", size = 182965, upload-time = "2024-11-21T13:57:13.709Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/8f3288797487c82981134732dee13b1ad12082890905476f95994ce49e0f/uuid_utils-0.10.0-pp310-pypy310_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:acea543dfc7b87df749e3e814c54ac739a82ff5e3800d25bd25a3e00599e1554", size = 573053, upload-time = "2024-11-21T13:57:15.158Z" }, + { url = "https://files.pythonhosted.org/packages/91/28/0eb5190aa39547015d60ce5453cfd37c4d87a48d25026d72044c20cad4fc/uuid_utils-0.10.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0767eefa7b1e96f06cfa9b95758d286240c01bbf19e9d8f1b6043cdbe76cc639", size = 292596, upload-time = "2024-11-21T13:57:16.771Z" }, + { url = "https://files.pythonhosted.org/packages/e4/27/a451725d5df0db8baaa84adde94bbac4a33c3816a5215740c3f1dbdc46d3/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973fe4bb5258fd2ccb144d8b40c2d3158f16cc856a20527f8b40d14b2ae1dee9", size = 323414, upload-time = "2024-11-21T13:57:18.644Z" }, + { url = "https://files.pythonhosted.org/packages/22/6b/0edc2ad855cbe07ffd891ec636c6ff57ae3a56cdf0e90467b2edbe5b7b43/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71b8505b67a0d77d0fbd765d8463094a8f447677125da7647bec7ea0b99406f0", size = 329720, upload-time = "2024-11-21T13:57:21.044Z" }, + { url = "https://files.pythonhosted.org/packages/4b/1d/f73af741d9a4d3168704235ef06fbda823bf2ecf551ac29caa8d7cf8ea2a/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdcb1211bb61476cbef12a87101fa48243e20ed82b2bd324c816b1b5826bd5e", size = 365545, upload-time = "2024-11-21T13:57:22.736Z" }, + { url = "https://files.pythonhosted.org/packages/b1/06/92104c8ea66a6d645f00520222a52c4b91a444c2c30201ff0036dedfb8da/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c5247f1df040aae71ea313819b563debe69bca7086a2cc6a3ac0eaddd3dadac", size = 325920, upload-time = "2024-11-21T13:57:24.604Z" }, + { url = "https://files.pythonhosted.org/packages/94/fe/0710e28b94f2311b40757dc43513290134cb4579f79981127c58640d736c/uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a50bd29ef89660b93aa07ffa95ac691a0e12832375030569a8bd5c9272f3b8e6", size = 344458, upload-time = "2024-11-21T13:57:26.032Z" }, + { url = "https://files.pythonhosted.org/packages/0b/8f/c12d449789d756f6c0ed81de060900c0e616f80d1e3944949859921ef1e5/uuid_utils-0.10.0-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a778cd9d8f995b94bba6e51f3ebee5b338fd834b0c4ecc8f932bd23e29db3e19", size = 573049, upload-time = "2024-11-21T13:57:28.236Z" }, + { url = "https://files.pythonhosted.org/packages/03/ac/85677abca4832417b28e40c7b634820158e29c57da780de2f3a131b6e24d/uuid_utils-0.10.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d3d5b5c5ed66ff923961b9ebb902232cd67f6a7ec6b6f7a58e05e00ff44e3c7f", size = 292587, upload-time = "2024-11-21T13:57:30.682Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/7d909b7acfb7eec3af0f671b5fec8ae88fdf60857a4f6344a83d0286837a/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:789ed6335225326c66f5d6162649bed978105a85f232be7811387c395c226801", size = 323412, upload-time = "2024-11-21T13:57:32.817Z" }, + { url = "https://files.pythonhosted.org/packages/e8/9c/daff11748511fef37d8959bc83fb3f5d50128292a9e10c50c4aa02390cd2/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:05d1aa7b944b719eb1ee472435ae5444a3f8a00eb6350e3b1d1217d738477d33", size = 329716, upload-time = "2024-11-21T13:57:34.539Z" }, + { url = "https://files.pythonhosted.org/packages/45/2c/30c7ef5dfc07f41854a46a09858419483376091731973ae91ac50392fe17/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa8d8559c2d25d6ac87e0adeee601d2c91ec40b357ab780bcf79061cc23324e6", size = 365539, upload-time = "2024-11-21T13:57:36.249Z" }, + { url = "https://files.pythonhosted.org/packages/2c/28/196f2b4c2717d865b8a0eb2064f7e69d31533b58a2528edf64b1c18cd943/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0badcbfe3c72b5b30d59c2b12f120923127abd95a0d2aa64ddc1234e495abc2", size = 325916, upload-time = "2024-11-21T13:57:37.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/a6/485bec297615b530aa967eef7b212a33d02a72441846642d721dedb307fb/uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a7c1c494012335113748815156c5b6234c59b0fe0d3a8eede1b1a46f7e25a69", size = 344453, upload-time = "2024-11-21T13:57:39.623Z" }, ] [[package]] @@ -4142,9 +4161,9 @@ dependencies = [ { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload-time = "2025-04-19T06:02:50.101Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483 }, + { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload-time = "2025-04-19T06:02:48.42Z" }, ] [[package]] @@ -4156,9 +4175,9 @@ dependencies = [ { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/e0/633e369b91bbc664df47dcb5454b6c7cf441e8f5b9d0c250ce9f0546401e/virtualenv-20.30.0.tar.gz", hash = "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8", size = 4346945 } +sdist = { url = "https://files.pythonhosted.org/packages/38/e0/633e369b91bbc664df47dcb5454b6c7cf441e8f5b9d0c250ce9f0546401e/virtualenv-20.30.0.tar.gz", hash = "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8", size = 4346945, upload-time = "2025-03-31T16:33:29.185Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/ed/3cfeb48175f0671ec430ede81f628f9fb2b1084c9064ca67ebe8c0ed6a05/virtualenv-20.30.0-py3-none-any.whl", hash = "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6", size = 4329461 }, + { url = "https://files.pythonhosted.org/packages/4c/ed/3cfeb48175f0671ec430ede81f628f9fb2b1084c9064ca67ebe8c0ed6a05/virtualenv-20.30.0-py3-none-any.whl", hash = "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6", size = 4329461, upload-time = "2025-03-31T16:33:26.758Z" }, ] [[package]] @@ -4168,78 +4187,78 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/03/e2/8ed598c42057de7aa5d97c472254af4906ff0a59a66699d426fc9ef795d7/watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9", size = 94537 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/af/4d/d02e6ea147bb7fff5fd109c694a95109612f419abed46548a930e7f7afa3/watchfiles-1.0.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5c40fe7dd9e5f81e0847b1ea64e1f5dd79dd61afbedb57759df06767ac719b40", size = 405632 }, - { url = "https://files.pythonhosted.org/packages/60/31/9ee50e29129d53a9a92ccf1d3992751dc56fc3c8f6ee721be1c7b9c81763/watchfiles-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c0db396e6003d99bb2d7232c957b5f0b5634bbd1b24e381a5afcc880f7373fb", size = 395734 }, - { url = "https://files.pythonhosted.org/packages/ad/8c/759176c97195306f028024f878e7f1c776bda66ccc5c68fa51e699cf8f1d/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b551d4fb482fc57d852b4541f911ba28957d051c8776e79c3b4a51eb5e2a1b11", size = 455008 }, - { url = "https://files.pythonhosted.org/packages/55/1a/5e977250c795ee79a0229e3b7f5e3a1b664e4e450756a22da84d2f4979fe/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:830aa432ba5c491d52a15b51526c29e4a4b92bf4f92253787f9726fe01519487", size = 459029 }, - { url = "https://files.pythonhosted.org/packages/e6/17/884cf039333605c1d6e296cf5be35fad0836953c3dfd2adb71b72f9dbcd0/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a16512051a822a416b0d477d5f8c0e67b67c1a20d9acecb0aafa3aa4d6e7d256", size = 488916 }, - { url = "https://files.pythonhosted.org/packages/ef/e0/bcb6e64b45837056c0a40f3a2db3ef51c2ced19fda38484fa7508e00632c/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe0cbc787770e52a96c6fda6726ace75be7f840cb327e1b08d7d54eadc3bc85", size = 523763 }, - { url = "https://files.pythonhosted.org/packages/24/e9/f67e9199f3bb35c1837447ecf07e9830ec00ff5d35a61e08c2cd67217949/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d363152c5e16b29d66cbde8fa614f9e313e6f94a8204eaab268db52231fe5358", size = 502891 }, - { url = "https://files.pythonhosted.org/packages/23/ed/a6cf815f215632f5c8065e9c41fe872025ffea35aa1f80499f86eae922db/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee32c9a9bee4d0b7bd7cbeb53cb185cf0b622ac761efaa2eba84006c3b3a614", size = 454921 }, - { url = "https://files.pythonhosted.org/packages/92/4c/e14978599b80cde8486ab5a77a821e8a982ae8e2fcb22af7b0886a033ec8/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29c7fd632ccaf5517c16a5188e36f6612d6472ccf55382db6c7fe3fcccb7f59f", size = 631422 }, - { url = "https://files.pythonhosted.org/packages/b2/1a/9263e34c3458f7614b657f974f4ee61fd72f58adce8b436e16450e054efd/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e637810586e6fe380c8bc1b3910accd7f1d3a9a7262c8a78d4c8fb3ba6a2b3d", size = 625675 }, - { url = "https://files.pythonhosted.org/packages/96/1f/1803a18bd6ab04a0766386a19bcfe64641381a04939efdaa95f0e3b0eb58/watchfiles-1.0.5-cp310-cp310-win32.whl", hash = "sha256:cd47d063fbeabd4c6cae1d4bcaa38f0902f8dc5ed168072874ea11d0c7afc1ff", size = 277921 }, - { url = "https://files.pythonhosted.org/packages/c2/3b/29a89de074a7d6e8b4dc67c26e03d73313e4ecf0d6e97e942a65fa7c195e/watchfiles-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:86c0df05b47a79d80351cd179893f2f9c1b1cae49d96e8b3290c7f4bd0ca0a92", size = 291526 }, - { url = "https://files.pythonhosted.org/packages/39/f4/41b591f59021786ef517e1cdc3b510383551846703e03f204827854a96f8/watchfiles-1.0.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:237f9be419e977a0f8f6b2e7b0475ababe78ff1ab06822df95d914a945eac827", size = 405336 }, - { url = "https://files.pythonhosted.org/packages/ae/06/93789c135be4d6d0e4f63e96eea56dc54050b243eacc28439a26482b5235/watchfiles-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0da39ff917af8b27a4bdc5a97ac577552a38aac0d260a859c1517ea3dc1a7c4", size = 395977 }, - { url = "https://files.pythonhosted.org/packages/d2/db/1cd89bd83728ca37054512d4d35ab69b5f12b8aa2ac9be3b0276b3bf06cc/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfcb3952350e95603f232a7a15f6c5f86c5375e46f0bd4ae70d43e3e063c13d", size = 455232 }, - { url = "https://files.pythonhosted.org/packages/40/90/d8a4d44ffe960517e487c9c04f77b06b8abf05eb680bed71c82b5f2cad62/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b2dddba7a4e6151384e252a5632efcaa9bc5d1c4b567f3cb621306b2ca9f63", size = 459151 }, - { url = "https://files.pythonhosted.org/packages/6c/da/267a1546f26465dead1719caaba3ce660657f83c9d9c052ba98fb8856e13/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cf944fcfc394c5f9de794ce581914900f82ff1f855326f25ebcf24d5397418", size = 489054 }, - { url = "https://files.pythonhosted.org/packages/b1/31/33850dfd5c6efb6f27d2465cc4c6b27c5a6f5ed53c6fa63b7263cf5f60f6/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf6cd9f83d7c023b1aba15d13f705ca7b7d38675c121f3cc4a6e25bd0857ee9", size = 523955 }, - { url = "https://files.pythonhosted.org/packages/09/84/b7d7b67856efb183a421f1416b44ca975cb2ea6c4544827955dfb01f7dc2/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:852de68acd6212cd6d33edf21e6f9e56e5d98c6add46f48244bd479d97c967c6", size = 502234 }, - { url = "https://files.pythonhosted.org/packages/71/87/6dc5ec6882a2254cfdd8b0718b684504e737273903b65d7338efaba08b52/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5730f3aa35e646103b53389d5bc77edfbf578ab6dab2e005142b5b80a35ef25", size = 454750 }, - { url = "https://files.pythonhosted.org/packages/3d/6c/3786c50213451a0ad15170d091570d4a6554976cf0df19878002fc96075a/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:18b3bd29954bc4abeeb4e9d9cf0b30227f0f206c86657674f544cb032296acd5", size = 631591 }, - { url = "https://files.pythonhosted.org/packages/1b/b3/1427425ade4e359a0deacce01a47a26024b2ccdb53098f9d64d497f6684c/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba5552a1b07c8edbf197055bc9d518b8f0d98a1c6a73a293bc0726dce068ed01", size = 625370 }, - { url = "https://files.pythonhosted.org/packages/15/ba/f60e053b0b5b8145d682672024aa91370a29c5c921a88977eb565de34086/watchfiles-1.0.5-cp311-cp311-win32.whl", hash = "sha256:2f1fefb2e90e89959447bc0420fddd1e76f625784340d64a2f7d5983ef9ad246", size = 277791 }, - { url = "https://files.pythonhosted.org/packages/50/ed/7603c4e164225c12c0d4e8700b64bb00e01a6c4eeea372292a3856be33a4/watchfiles-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b6e76ceb1dd18c8e29c73f47d41866972e891fc4cc7ba014f487def72c1cf096", size = 291622 }, - { url = "https://files.pythonhosted.org/packages/a2/c2/99bb7c96b4450e36877fde33690ded286ff555b5a5c1d925855d556968a1/watchfiles-1.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:266710eb6fddc1f5e51843c70e3bebfb0f5e77cf4f27129278c70554104d19ed", size = 283699 }, - { url = "https://files.pythonhosted.org/packages/2a/8c/4f0b9bdb75a1bfbd9c78fad7d8854369283f74fe7cf03eb16be77054536d/watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2", size = 401511 }, - { url = "https://files.pythonhosted.org/packages/dc/4e/7e15825def77f8bd359b6d3f379f0c9dac4eb09dd4ddd58fd7d14127179c/watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f", size = 392715 }, - { url = "https://files.pythonhosted.org/packages/58/65/b72fb817518728e08de5840d5d38571466c1b4a3f724d190cec909ee6f3f/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec", size = 454138 }, - { url = "https://files.pythonhosted.org/packages/3e/a4/86833fd2ea2e50ae28989f5950b5c3f91022d67092bfec08f8300d8b347b/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21", size = 458592 }, - { url = "https://files.pythonhosted.org/packages/38/7e/42cb8df8be9a37e50dd3a818816501cf7a20d635d76d6bd65aae3dbbff68/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512", size = 487532 }, - { url = "https://files.pythonhosted.org/packages/fc/fd/13d26721c85d7f3df6169d8b495fcac8ab0dc8f0945ebea8845de4681dab/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d", size = 522865 }, - { url = "https://files.pythonhosted.org/packages/a1/0d/7f9ae243c04e96c5455d111e21b09087d0eeaf9a1369e13a01c7d3d82478/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6", size = 499887 }, - { url = "https://files.pythonhosted.org/packages/8e/0f/a257766998e26aca4b3acf2ae97dff04b57071e991a510857d3799247c67/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234", size = 454498 }, - { url = "https://files.pythonhosted.org/packages/81/79/8bf142575a03e0af9c3d5f8bcae911ee6683ae93a625d349d4ecf4c8f7df/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2", size = 630663 }, - { url = "https://files.pythonhosted.org/packages/f1/80/abe2e79f610e45c63a70d271caea90c49bbf93eb00fa947fa9b803a1d51f/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663", size = 625410 }, - { url = "https://files.pythonhosted.org/packages/91/6f/bc7fbecb84a41a9069c2c6eb6319f7f7df113adf113e358c57fc1aff7ff5/watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249", size = 277965 }, - { url = "https://files.pythonhosted.org/packages/99/a5/bf1c297ea6649ec59e935ab311f63d8af5faa8f0b86993e3282b984263e3/watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705", size = 291693 }, - { url = "https://files.pythonhosted.org/packages/7f/7b/fd01087cc21db5c47e5beae507b87965db341cce8a86f9eb12bf5219d4e0/watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417", size = 283287 }, - { url = "https://files.pythonhosted.org/packages/c7/62/435766874b704f39b2fecd8395a29042db2b5ec4005bd34523415e9bd2e0/watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d", size = 401531 }, - { url = "https://files.pythonhosted.org/packages/6e/a6/e52a02c05411b9cb02823e6797ef9bbba0bfaf1bb627da1634d44d8af833/watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763", size = 392417 }, - { url = "https://files.pythonhosted.org/packages/3f/53/c4af6819770455932144e0109d4854437769672d7ad897e76e8e1673435d/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40", size = 453423 }, - { url = "https://files.pythonhosted.org/packages/cb/d1/8e88df58bbbf819b8bc5cfbacd3c79e01b40261cad0fc84d1e1ebd778a07/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563", size = 458185 }, - { url = "https://files.pythonhosted.org/packages/ff/70/fffaa11962dd5429e47e478a18736d4e42bec42404f5ee3b92ef1b87ad60/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04", size = 486696 }, - { url = "https://files.pythonhosted.org/packages/39/db/723c0328e8b3692d53eb273797d9a08be6ffb1d16f1c0ba2bdbdc2a3852c/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f", size = 522327 }, - { url = "https://files.pythonhosted.org/packages/cd/05/9fccc43c50c39a76b68343484b9da7b12d42d0859c37c61aec018c967a32/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a", size = 499741 }, - { url = "https://files.pythonhosted.org/packages/23/14/499e90c37fa518976782b10a18b18db9f55ea73ca14641615056f8194bb3/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827", size = 453995 }, - { url = "https://files.pythonhosted.org/packages/61/d9/f75d6840059320df5adecd2c687fbc18960a7f97b55c300d20f207d48aef/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a", size = 629693 }, - { url = "https://files.pythonhosted.org/packages/fc/17/180ca383f5061b61406477218c55d66ec118e6c0c51f02d8142895fcf0a9/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936", size = 624677 }, - { url = "https://files.pythonhosted.org/packages/bf/15/714d6ef307f803f236d69ee9d421763707899d6298d9f3183e55e366d9af/watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc", size = 277804 }, - { url = "https://files.pythonhosted.org/packages/a8/b4/c57b99518fadf431f3ef47a610839e46e5f8abf9814f969859d1c65c02c7/watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11", size = 291087 }, - { url = "https://files.pythonhosted.org/packages/c5/95/94f3dd15557f5553261e407551c5e4d340e50161c55aa30812c79da6cb04/watchfiles-1.0.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2cfb371be97d4db374cba381b9f911dd35bb5f4c58faa7b8b7106c8853e5d225", size = 405686 }, - { url = "https://files.pythonhosted.org/packages/f4/aa/b99e968153f8b70159ecca7b3daf46a6f46d97190bdaa3a449ad31b921d7/watchfiles-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3904d88955fda461ea2531fcf6ef73584ca921415d5cfa44457a225f4a42bc1", size = 396047 }, - { url = "https://files.pythonhosted.org/packages/23/cb/90d3d760ad4bc7290e313fb9236c7d60598627a25a5a72764e48d9652064/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b7a21715fb12274a71d335cff6c71fe7f676b293d322722fe708a9ec81d91f5", size = 456081 }, - { url = "https://files.pythonhosted.org/packages/3e/65/79c6cebe5bcb695cdac145946ad5a09b9f66762549e82fb2d064ea960c95/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dfd6ae1c385ab481766b3c61c44aca2b3cd775f6f7c0fa93d979ddec853d29d5", size = 459838 }, - { url = "https://files.pythonhosted.org/packages/3f/84/699f52632cdaa777f6df7f6f1cc02a23a75b41071b7e6765b9a412495f61/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b659576b950865fdad31fa491d31d37cf78b27113a7671d39f919828587b429b", size = 489753 }, - { url = "https://files.pythonhosted.org/packages/25/68/3241f82ad414fd969de6bf3a93805682e5eb589aeab510322f2aa14462f8/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1909e0a9cd95251b15bff4261de5dd7550885bd172e3536824bf1cf6b121e200", size = 525015 }, - { url = "https://files.pythonhosted.org/packages/85/c4/30d879e252f52b01660f545c193e6b81c48aac2e0eeec71263af3add905b/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:832ccc221927c860e7286c55c9b6ebcc0265d5e072f49c7f6456c7798d2b39aa", size = 503816 }, - { url = "https://files.pythonhosted.org/packages/6b/7d/fa34750f6f4b1a70d96fa6b685fe2948d01e3936328ea528f182943eb373/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fbb6102b3296926d0c62cfc9347f6237fb9400aecd0ba6bbda94cae15f2b3b", size = 456137 }, - { url = "https://files.pythonhosted.org/packages/8f/0c/a1569709aaeccb1dd74b0dd304d0de29e3ea1fdf11e08c78f489628f9ebb/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:15ac96dd567ad6c71c71f7b2c658cb22b7734901546cd50a475128ab557593ca", size = 632673 }, - { url = "https://files.pythonhosted.org/packages/90/b6/645eaaca11f3ac625cf3b6e008e543acf0bf2581f68b5e205a13b05618b6/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b6227351e11c57ae997d222e13f5b6f1f0700d84b8c52304e8675d33a808382", size = 626659 }, - { url = "https://files.pythonhosted.org/packages/3a/c4/e741d9b92b0a2c74b976ff78bbc9a1276b4d904c590878e8fe0ec9fecca5/watchfiles-1.0.5-cp39-cp39-win32.whl", hash = "sha256:974866e0db748ebf1eccab17862bc0f0303807ed9cda465d1324625b81293a18", size = 278471 }, - { url = "https://files.pythonhosted.org/packages/50/1b/36b0cb6add99105f78931994b30bc1dd24118c0e659ab6a3ffe0dd8734d4/watchfiles-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:9848b21ae152fe79c10dd0197304ada8f7b586d3ebc3f27f43c506e5a52a863c", size = 292027 }, - { url = "https://files.pythonhosted.org/packages/1a/03/81f9fcc3963b3fc415cd4b0b2b39ee8cc136c42fb10a36acf38745e9d283/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f59b870db1f1ae5a9ac28245707d955c8721dd6565e7f411024fa374b5362d1d", size = 405947 }, - { url = "https://files.pythonhosted.org/packages/54/97/8c4213a852feb64807ec1d380f42d4fc8bfaef896bdbd94318f8fd7f3e4e/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9475b0093767e1475095f2aeb1d219fb9664081d403d1dff81342df8cd707034", size = 397276 }, - { url = "https://files.pythonhosted.org/packages/78/12/d4464d19860cb9672efa45eec1b08f8472c478ed67dcd30647c51ada7aef/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc533aa50664ebd6c628b2f30591956519462f5d27f951ed03d6c82b2dfd9965", size = 455550 }, - { url = "https://files.pythonhosted.org/packages/90/fb/b07bcdf1034d8edeaef4c22f3e9e3157d37c5071b5f9492ffdfa4ad4bed7/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed1cd825158dcaae36acce7b2db33dcbfd12b30c34317a88b8ed80f0541cc57", size = 455542 }, - { url = "https://files.pythonhosted.org/packages/5b/84/7b69282c0df2bf2dff4e50be2c54669cddf219a5a5fb077891c00c00e5c8/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:554389562c29c2c182e3908b149095051f81d28c2fec79ad6c8997d7d63e0009", size = 405783 }, - { url = "https://files.pythonhosted.org/packages/dd/ae/03fca0545d99b7ea21df49bead7b51e7dca9ce3b45bb6d34530aa18c16a2/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a74add8d7727e6404d5dc4dcd7fac65d4d82f95928bbee0cf5414c900e86773e", size = 397133 }, - { url = "https://files.pythonhosted.org/packages/1a/07/c2b6390003e933b2e187a3f7070c00bd87da8a58d6f2393e039b06a88c2e/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1489f25b051a89fae574505cc26360c8e95e227a9500182a7fe0afcc500ce0", size = 456198 }, - { url = "https://files.pythonhosted.org/packages/46/d3/ecc62cbd7054f0812f3a7ca7c1c9f7ba99ba45efcfc8297a9fcd2c87b31c/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac", size = 456511 }, +sdist = { url = "https://files.pythonhosted.org/packages/03/e2/8ed598c42057de7aa5d97c472254af4906ff0a59a66699d426fc9ef795d7/watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9", size = 94537, upload-time = "2025-04-08T10:36:26.722Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/4d/d02e6ea147bb7fff5fd109c694a95109612f419abed46548a930e7f7afa3/watchfiles-1.0.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5c40fe7dd9e5f81e0847b1ea64e1f5dd79dd61afbedb57759df06767ac719b40", size = 405632, upload-time = "2025-04-08T10:34:41.832Z" }, + { url = "https://files.pythonhosted.org/packages/60/31/9ee50e29129d53a9a92ccf1d3992751dc56fc3c8f6ee721be1c7b9c81763/watchfiles-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c0db396e6003d99bb2d7232c957b5f0b5634bbd1b24e381a5afcc880f7373fb", size = 395734, upload-time = "2025-04-08T10:34:44.236Z" }, + { url = "https://files.pythonhosted.org/packages/ad/8c/759176c97195306f028024f878e7f1c776bda66ccc5c68fa51e699cf8f1d/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b551d4fb482fc57d852b4541f911ba28957d051c8776e79c3b4a51eb5e2a1b11", size = 455008, upload-time = "2025-04-08T10:34:45.617Z" }, + { url = "https://files.pythonhosted.org/packages/55/1a/5e977250c795ee79a0229e3b7f5e3a1b664e4e450756a22da84d2f4979fe/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:830aa432ba5c491d52a15b51526c29e4a4b92bf4f92253787f9726fe01519487", size = 459029, upload-time = "2025-04-08T10:34:46.814Z" }, + { url = "https://files.pythonhosted.org/packages/e6/17/884cf039333605c1d6e296cf5be35fad0836953c3dfd2adb71b72f9dbcd0/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a16512051a822a416b0d477d5f8c0e67b67c1a20d9acecb0aafa3aa4d6e7d256", size = 488916, upload-time = "2025-04-08T10:34:48.571Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e0/bcb6e64b45837056c0a40f3a2db3ef51c2ced19fda38484fa7508e00632c/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe0cbc787770e52a96c6fda6726ace75be7f840cb327e1b08d7d54eadc3bc85", size = 523763, upload-time = "2025-04-08T10:34:50.268Z" }, + { url = "https://files.pythonhosted.org/packages/24/e9/f67e9199f3bb35c1837447ecf07e9830ec00ff5d35a61e08c2cd67217949/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d363152c5e16b29d66cbde8fa614f9e313e6f94a8204eaab268db52231fe5358", size = 502891, upload-time = "2025-04-08T10:34:51.419Z" }, + { url = "https://files.pythonhosted.org/packages/23/ed/a6cf815f215632f5c8065e9c41fe872025ffea35aa1f80499f86eae922db/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee32c9a9bee4d0b7bd7cbeb53cb185cf0b622ac761efaa2eba84006c3b3a614", size = 454921, upload-time = "2025-04-08T10:34:52.67Z" }, + { url = "https://files.pythonhosted.org/packages/92/4c/e14978599b80cde8486ab5a77a821e8a982ae8e2fcb22af7b0886a033ec8/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29c7fd632ccaf5517c16a5188e36f6612d6472ccf55382db6c7fe3fcccb7f59f", size = 631422, upload-time = "2025-04-08T10:34:53.985Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1a/9263e34c3458f7614b657f974f4ee61fd72f58adce8b436e16450e054efd/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e637810586e6fe380c8bc1b3910accd7f1d3a9a7262c8a78d4c8fb3ba6a2b3d", size = 625675, upload-time = "2025-04-08T10:34:55.173Z" }, + { url = "https://files.pythonhosted.org/packages/96/1f/1803a18bd6ab04a0766386a19bcfe64641381a04939efdaa95f0e3b0eb58/watchfiles-1.0.5-cp310-cp310-win32.whl", hash = "sha256:cd47d063fbeabd4c6cae1d4bcaa38f0902f8dc5ed168072874ea11d0c7afc1ff", size = 277921, upload-time = "2025-04-08T10:34:56.318Z" }, + { url = "https://files.pythonhosted.org/packages/c2/3b/29a89de074a7d6e8b4dc67c26e03d73313e4ecf0d6e97e942a65fa7c195e/watchfiles-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:86c0df05b47a79d80351cd179893f2f9c1b1cae49d96e8b3290c7f4bd0ca0a92", size = 291526, upload-time = "2025-04-08T10:34:57.95Z" }, + { url = "https://files.pythonhosted.org/packages/39/f4/41b591f59021786ef517e1cdc3b510383551846703e03f204827854a96f8/watchfiles-1.0.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:237f9be419e977a0f8f6b2e7b0475ababe78ff1ab06822df95d914a945eac827", size = 405336, upload-time = "2025-04-08T10:34:59.359Z" }, + { url = "https://files.pythonhosted.org/packages/ae/06/93789c135be4d6d0e4f63e96eea56dc54050b243eacc28439a26482b5235/watchfiles-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0da39ff917af8b27a4bdc5a97ac577552a38aac0d260a859c1517ea3dc1a7c4", size = 395977, upload-time = "2025-04-08T10:35:00.522Z" }, + { url = "https://files.pythonhosted.org/packages/d2/db/1cd89bd83728ca37054512d4d35ab69b5f12b8aa2ac9be3b0276b3bf06cc/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfcb3952350e95603f232a7a15f6c5f86c5375e46f0bd4ae70d43e3e063c13d", size = 455232, upload-time = "2025-04-08T10:35:01.698Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/d8a4d44ffe960517e487c9c04f77b06b8abf05eb680bed71c82b5f2cad62/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b2dddba7a4e6151384e252a5632efcaa9bc5d1c4b567f3cb621306b2ca9f63", size = 459151, upload-time = "2025-04-08T10:35:03.358Z" }, + { url = "https://files.pythonhosted.org/packages/6c/da/267a1546f26465dead1719caaba3ce660657f83c9d9c052ba98fb8856e13/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cf944fcfc394c5f9de794ce581914900f82ff1f855326f25ebcf24d5397418", size = 489054, upload-time = "2025-04-08T10:35:04.561Z" }, + { url = "https://files.pythonhosted.org/packages/b1/31/33850dfd5c6efb6f27d2465cc4c6b27c5a6f5ed53c6fa63b7263cf5f60f6/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf6cd9f83d7c023b1aba15d13f705ca7b7d38675c121f3cc4a6e25bd0857ee9", size = 523955, upload-time = "2025-04-08T10:35:05.786Z" }, + { url = "https://files.pythonhosted.org/packages/09/84/b7d7b67856efb183a421f1416b44ca975cb2ea6c4544827955dfb01f7dc2/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:852de68acd6212cd6d33edf21e6f9e56e5d98c6add46f48244bd479d97c967c6", size = 502234, upload-time = "2025-04-08T10:35:07.187Z" }, + { url = "https://files.pythonhosted.org/packages/71/87/6dc5ec6882a2254cfdd8b0718b684504e737273903b65d7338efaba08b52/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5730f3aa35e646103b53389d5bc77edfbf578ab6dab2e005142b5b80a35ef25", size = 454750, upload-time = "2025-04-08T10:35:08.859Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6c/3786c50213451a0ad15170d091570d4a6554976cf0df19878002fc96075a/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:18b3bd29954bc4abeeb4e9d9cf0b30227f0f206c86657674f544cb032296acd5", size = 631591, upload-time = "2025-04-08T10:35:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b3/1427425ade4e359a0deacce01a47a26024b2ccdb53098f9d64d497f6684c/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba5552a1b07c8edbf197055bc9d518b8f0d98a1c6a73a293bc0726dce068ed01", size = 625370, upload-time = "2025-04-08T10:35:12.412Z" }, + { url = "https://files.pythonhosted.org/packages/15/ba/f60e053b0b5b8145d682672024aa91370a29c5c921a88977eb565de34086/watchfiles-1.0.5-cp311-cp311-win32.whl", hash = "sha256:2f1fefb2e90e89959447bc0420fddd1e76f625784340d64a2f7d5983ef9ad246", size = 277791, upload-time = "2025-04-08T10:35:13.719Z" }, + { url = "https://files.pythonhosted.org/packages/50/ed/7603c4e164225c12c0d4e8700b64bb00e01a6c4eeea372292a3856be33a4/watchfiles-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b6e76ceb1dd18c8e29c73f47d41866972e891fc4cc7ba014f487def72c1cf096", size = 291622, upload-time = "2025-04-08T10:35:15.071Z" }, + { url = "https://files.pythonhosted.org/packages/a2/c2/99bb7c96b4450e36877fde33690ded286ff555b5a5c1d925855d556968a1/watchfiles-1.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:266710eb6fddc1f5e51843c70e3bebfb0f5e77cf4f27129278c70554104d19ed", size = 283699, upload-time = "2025-04-08T10:35:16.732Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8c/4f0b9bdb75a1bfbd9c78fad7d8854369283f74fe7cf03eb16be77054536d/watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2", size = 401511, upload-time = "2025-04-08T10:35:17.956Z" }, + { url = "https://files.pythonhosted.org/packages/dc/4e/7e15825def77f8bd359b6d3f379f0c9dac4eb09dd4ddd58fd7d14127179c/watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f", size = 392715, upload-time = "2025-04-08T10:35:19.202Z" }, + { url = "https://files.pythonhosted.org/packages/58/65/b72fb817518728e08de5840d5d38571466c1b4a3f724d190cec909ee6f3f/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec", size = 454138, upload-time = "2025-04-08T10:35:20.586Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a4/86833fd2ea2e50ae28989f5950b5c3f91022d67092bfec08f8300d8b347b/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21", size = 458592, upload-time = "2025-04-08T10:35:21.87Z" }, + { url = "https://files.pythonhosted.org/packages/38/7e/42cb8df8be9a37e50dd3a818816501cf7a20d635d76d6bd65aae3dbbff68/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512", size = 487532, upload-time = "2025-04-08T10:35:23.143Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fd/13d26721c85d7f3df6169d8b495fcac8ab0dc8f0945ebea8845de4681dab/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d", size = 522865, upload-time = "2025-04-08T10:35:24.702Z" }, + { url = "https://files.pythonhosted.org/packages/a1/0d/7f9ae243c04e96c5455d111e21b09087d0eeaf9a1369e13a01c7d3d82478/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6", size = 499887, upload-time = "2025-04-08T10:35:25.969Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0f/a257766998e26aca4b3acf2ae97dff04b57071e991a510857d3799247c67/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234", size = 454498, upload-time = "2025-04-08T10:35:27.353Z" }, + { url = "https://files.pythonhosted.org/packages/81/79/8bf142575a03e0af9c3d5f8bcae911ee6683ae93a625d349d4ecf4c8f7df/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2", size = 630663, upload-time = "2025-04-08T10:35:28.685Z" }, + { url = "https://files.pythonhosted.org/packages/f1/80/abe2e79f610e45c63a70d271caea90c49bbf93eb00fa947fa9b803a1d51f/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663", size = 625410, upload-time = "2025-04-08T10:35:30.42Z" }, + { url = "https://files.pythonhosted.org/packages/91/6f/bc7fbecb84a41a9069c2c6eb6319f7f7df113adf113e358c57fc1aff7ff5/watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249", size = 277965, upload-time = "2025-04-08T10:35:32.023Z" }, + { url = "https://files.pythonhosted.org/packages/99/a5/bf1c297ea6649ec59e935ab311f63d8af5faa8f0b86993e3282b984263e3/watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705", size = 291693, upload-time = "2025-04-08T10:35:33.225Z" }, + { url = "https://files.pythonhosted.org/packages/7f/7b/fd01087cc21db5c47e5beae507b87965db341cce8a86f9eb12bf5219d4e0/watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417", size = 283287, upload-time = "2025-04-08T10:35:34.568Z" }, + { url = "https://files.pythonhosted.org/packages/c7/62/435766874b704f39b2fecd8395a29042db2b5ec4005bd34523415e9bd2e0/watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d", size = 401531, upload-time = "2025-04-08T10:35:35.792Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a6/e52a02c05411b9cb02823e6797ef9bbba0bfaf1bb627da1634d44d8af833/watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763", size = 392417, upload-time = "2025-04-08T10:35:37.048Z" }, + { url = "https://files.pythonhosted.org/packages/3f/53/c4af6819770455932144e0109d4854437769672d7ad897e76e8e1673435d/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40", size = 453423, upload-time = "2025-04-08T10:35:38.357Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d1/8e88df58bbbf819b8bc5cfbacd3c79e01b40261cad0fc84d1e1ebd778a07/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563", size = 458185, upload-time = "2025-04-08T10:35:39.708Z" }, + { url = "https://files.pythonhosted.org/packages/ff/70/fffaa11962dd5429e47e478a18736d4e42bec42404f5ee3b92ef1b87ad60/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04", size = 486696, upload-time = "2025-04-08T10:35:41.469Z" }, + { url = "https://files.pythonhosted.org/packages/39/db/723c0328e8b3692d53eb273797d9a08be6ffb1d16f1c0ba2bdbdc2a3852c/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f", size = 522327, upload-time = "2025-04-08T10:35:43.289Z" }, + { url = "https://files.pythonhosted.org/packages/cd/05/9fccc43c50c39a76b68343484b9da7b12d42d0859c37c61aec018c967a32/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a", size = 499741, upload-time = "2025-04-08T10:35:44.574Z" }, + { url = "https://files.pythonhosted.org/packages/23/14/499e90c37fa518976782b10a18b18db9f55ea73ca14641615056f8194bb3/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827", size = 453995, upload-time = "2025-04-08T10:35:46.336Z" }, + { url = "https://files.pythonhosted.org/packages/61/d9/f75d6840059320df5adecd2c687fbc18960a7f97b55c300d20f207d48aef/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a", size = 629693, upload-time = "2025-04-08T10:35:48.161Z" }, + { url = "https://files.pythonhosted.org/packages/fc/17/180ca383f5061b61406477218c55d66ec118e6c0c51f02d8142895fcf0a9/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936", size = 624677, upload-time = "2025-04-08T10:35:49.65Z" }, + { url = "https://files.pythonhosted.org/packages/bf/15/714d6ef307f803f236d69ee9d421763707899d6298d9f3183e55e366d9af/watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc", size = 277804, upload-time = "2025-04-08T10:35:51.093Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b4/c57b99518fadf431f3ef47a610839e46e5f8abf9814f969859d1c65c02c7/watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11", size = 291087, upload-time = "2025-04-08T10:35:52.458Z" }, + { url = "https://files.pythonhosted.org/packages/c5/95/94f3dd15557f5553261e407551c5e4d340e50161c55aa30812c79da6cb04/watchfiles-1.0.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2cfb371be97d4db374cba381b9f911dd35bb5f4c58faa7b8b7106c8853e5d225", size = 405686, upload-time = "2025-04-08T10:35:53.86Z" }, + { url = "https://files.pythonhosted.org/packages/f4/aa/b99e968153f8b70159ecca7b3daf46a6f46d97190bdaa3a449ad31b921d7/watchfiles-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3904d88955fda461ea2531fcf6ef73584ca921415d5cfa44457a225f4a42bc1", size = 396047, upload-time = "2025-04-08T10:35:55.232Z" }, + { url = "https://files.pythonhosted.org/packages/23/cb/90d3d760ad4bc7290e313fb9236c7d60598627a25a5a72764e48d9652064/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b7a21715fb12274a71d335cff6c71fe7f676b293d322722fe708a9ec81d91f5", size = 456081, upload-time = "2025-04-08T10:35:57.102Z" }, + { url = "https://files.pythonhosted.org/packages/3e/65/79c6cebe5bcb695cdac145946ad5a09b9f66762549e82fb2d064ea960c95/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dfd6ae1c385ab481766b3c61c44aca2b3cd775f6f7c0fa93d979ddec853d29d5", size = 459838, upload-time = "2025-04-08T10:35:58.867Z" }, + { url = "https://files.pythonhosted.org/packages/3f/84/699f52632cdaa777f6df7f6f1cc02a23a75b41071b7e6765b9a412495f61/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b659576b950865fdad31fa491d31d37cf78b27113a7671d39f919828587b429b", size = 489753, upload-time = "2025-04-08T10:36:00.237Z" }, + { url = "https://files.pythonhosted.org/packages/25/68/3241f82ad414fd969de6bf3a93805682e5eb589aeab510322f2aa14462f8/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1909e0a9cd95251b15bff4261de5dd7550885bd172e3536824bf1cf6b121e200", size = 525015, upload-time = "2025-04-08T10:36:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/85/c4/30d879e252f52b01660f545c193e6b81c48aac2e0eeec71263af3add905b/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:832ccc221927c860e7286c55c9b6ebcc0265d5e072f49c7f6456c7798d2b39aa", size = 503816, upload-time = "2025-04-08T10:36:03.869Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7d/fa34750f6f4b1a70d96fa6b685fe2948d01e3936328ea528f182943eb373/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fbb6102b3296926d0c62cfc9347f6237fb9400aecd0ba6bbda94cae15f2b3b", size = 456137, upload-time = "2025-04-08T10:36:05.226Z" }, + { url = "https://files.pythonhosted.org/packages/8f/0c/a1569709aaeccb1dd74b0dd304d0de29e3ea1fdf11e08c78f489628f9ebb/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:15ac96dd567ad6c71c71f7b2c658cb22b7734901546cd50a475128ab557593ca", size = 632673, upload-time = "2025-04-08T10:36:06.752Z" }, + { url = "https://files.pythonhosted.org/packages/90/b6/645eaaca11f3ac625cf3b6e008e543acf0bf2581f68b5e205a13b05618b6/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b6227351e11c57ae997d222e13f5b6f1f0700d84b8c52304e8675d33a808382", size = 626659, upload-time = "2025-04-08T10:36:08.18Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c4/e741d9b92b0a2c74b976ff78bbc9a1276b4d904c590878e8fe0ec9fecca5/watchfiles-1.0.5-cp39-cp39-win32.whl", hash = "sha256:974866e0db748ebf1eccab17862bc0f0303807ed9cda465d1324625b81293a18", size = 278471, upload-time = "2025-04-08T10:36:10.546Z" }, + { url = "https://files.pythonhosted.org/packages/50/1b/36b0cb6add99105f78931994b30bc1dd24118c0e659ab6a3ffe0dd8734d4/watchfiles-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:9848b21ae152fe79c10dd0197304ada8f7b586d3ebc3f27f43c506e5a52a863c", size = 292027, upload-time = "2025-04-08T10:36:11.901Z" }, + { url = "https://files.pythonhosted.org/packages/1a/03/81f9fcc3963b3fc415cd4b0b2b39ee8cc136c42fb10a36acf38745e9d283/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f59b870db1f1ae5a9ac28245707d955c8721dd6565e7f411024fa374b5362d1d", size = 405947, upload-time = "2025-04-08T10:36:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/54/97/8c4213a852feb64807ec1d380f42d4fc8bfaef896bdbd94318f8fd7f3e4e/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9475b0093767e1475095f2aeb1d219fb9664081d403d1dff81342df8cd707034", size = 397276, upload-time = "2025-04-08T10:36:15.131Z" }, + { url = "https://files.pythonhosted.org/packages/78/12/d4464d19860cb9672efa45eec1b08f8472c478ed67dcd30647c51ada7aef/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc533aa50664ebd6c628b2f30591956519462f5d27f951ed03d6c82b2dfd9965", size = 455550, upload-time = "2025-04-08T10:36:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/90/fb/b07bcdf1034d8edeaef4c22f3e9e3157d37c5071b5f9492ffdfa4ad4bed7/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed1cd825158dcaae36acce7b2db33dcbfd12b30c34317a88b8ed80f0541cc57", size = 455542, upload-time = "2025-04-08T10:36:18.655Z" }, + { url = "https://files.pythonhosted.org/packages/5b/84/7b69282c0df2bf2dff4e50be2c54669cddf219a5a5fb077891c00c00e5c8/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:554389562c29c2c182e3908b149095051f81d28c2fec79ad6c8997d7d63e0009", size = 405783, upload-time = "2025-04-08T10:36:20.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ae/03fca0545d99b7ea21df49bead7b51e7dca9ce3b45bb6d34530aa18c16a2/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a74add8d7727e6404d5dc4dcd7fac65d4d82f95928bbee0cf5414c900e86773e", size = 397133, upload-time = "2025-04-08T10:36:22.439Z" }, + { url = "https://files.pythonhosted.org/packages/1a/07/c2b6390003e933b2e187a3f7070c00bd87da8a58d6f2393e039b06a88c2e/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1489f25b051a89fae574505cc26360c8e95e227a9500182a7fe0afcc500ce0", size = 456198, upload-time = "2025-04-08T10:36:23.884Z" }, + { url = "https://files.pythonhosted.org/packages/46/d3/ecc62cbd7054f0812f3a7ca7c1c9f7ba99ba45efcfc8297a9fcd2c87b31c/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac", size = 456511, upload-time = "2025-04-08T10:36:25.42Z" }, ] [[package]] @@ -4249,103 +4268,103 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "bracex" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/41/ab/b3a52228538ccb983653c446c1656eddf1d5303b9cb8b9aef6a91299f862/wcmatch-10.0.tar.gz", hash = "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a", size = 115578 } +sdist = { url = "https://files.pythonhosted.org/packages/41/ab/b3a52228538ccb983653c446c1656eddf1d5303b9cb8b9aef6a91299f862/wcmatch-10.0.tar.gz", hash = "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a", size = 115578, upload-time = "2024-09-26T18:39:52.505Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/df/4ee467ab39cc1de4b852c212c1ed3becfec2e486a51ac1ce0091f85f38d7/wcmatch-10.0-py3-none-any.whl", hash = "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a", size = 39347 }, + { url = "https://files.pythonhosted.org/packages/ab/df/4ee467ab39cc1de4b852c212c1ed3becfec2e486a51ac1ce0091f85f38d7/wcmatch-10.0-py3-none-any.whl", hash = "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a", size = 39347, upload-time = "2024-09-26T18:39:51.002Z" }, ] [[package]] name = "wcwidth" version = "0.2.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301 } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, ] [[package]] name = "webencodings" version = "0.5.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721 } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774 }, + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, ] [[package]] name = "websockets" version = "15.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/da/6462a9f510c0c49837bbc9345aca92d767a56c1fb2939e1579df1e1cdcf7/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", size = 175423 }, - { url = "https://files.pythonhosted.org/packages/1c/9f/9d11c1a4eb046a9e106483b9ff69bce7ac880443f00e5ce64261b47b07e7/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", size = 173080 }, - { url = "https://files.pythonhosted.org/packages/d5/4f/b462242432d93ea45f297b6179c7333dd0402b855a912a04e7fc61c0d71f/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", size = 173329 }, - { url = "https://files.pythonhosted.org/packages/6e/0c/6afa1f4644d7ed50284ac59cc70ef8abd44ccf7d45850d989ea7310538d0/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", size = 182312 }, - { url = "https://files.pythonhosted.org/packages/dd/d4/ffc8bd1350b229ca7a4db2a3e1c482cf87cea1baccd0ef3e72bc720caeec/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", size = 181319 }, - { url = "https://files.pythonhosted.org/packages/97/3a/5323a6bb94917af13bbb34009fac01e55c51dfde354f63692bf2533ffbc2/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", size = 181631 }, - { url = "https://files.pythonhosted.org/packages/a6/cc/1aeb0f7cee59ef065724041bb7ed667b6ab1eeffe5141696cccec2687b66/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", size = 182016 }, - { url = "https://files.pythonhosted.org/packages/79/f9/c86f8f7af208e4161a7f7e02774e9d0a81c632ae76db2ff22549e1718a51/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", size = 181426 }, - { url = "https://files.pythonhosted.org/packages/c7/b9/828b0bc6753db905b91df6ae477c0b14a141090df64fb17f8a9d7e3516cf/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", size = 181360 }, - { url = "https://files.pythonhosted.org/packages/89/fb/250f5533ec468ba6327055b7d98b9df056fb1ce623b8b6aaafb30b55d02e/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", size = 176388 }, - { url = "https://files.pythonhosted.org/packages/1c/46/aca7082012768bb98e5608f01658ff3ac8437e563eca41cf068bd5849a5e/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", size = 176830 }, - { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423 }, - { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082 }, - { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330 }, - { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878 }, - { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883 }, - { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252 }, - { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521 }, - { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958 }, - { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918 }, - { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388 }, - { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828 }, - { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437 }, - { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096 }, - { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332 }, - { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152 }, - { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096 }, - { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523 }, - { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790 }, - { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165 }, - { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160 }, - { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, - { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, - { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 }, - { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 }, - { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 }, - { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 }, - { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 }, - { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 }, - { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 }, - { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 }, - { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 }, - { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, - { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, - { url = "https://files.pythonhosted.org/packages/36/db/3fff0bcbe339a6fa6a3b9e3fbc2bfb321ec2f4cd233692272c5a8d6cf801/websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5", size = 175424 }, - { url = "https://files.pythonhosted.org/packages/46/e6/519054c2f477def4165b0ec060ad664ed174e140b0d1cbb9fafa4a54f6db/websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a", size = 173077 }, - { url = "https://files.pythonhosted.org/packages/1a/21/c0712e382df64c93a0d16449ecbf87b647163485ca1cc3f6cbadb36d2b03/websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b", size = 173324 }, - { url = "https://files.pythonhosted.org/packages/1c/cb/51ba82e59b3a664df54beed8ad95517c1b4dc1a913730e7a7db778f21291/websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770", size = 182094 }, - { url = "https://files.pythonhosted.org/packages/fb/0f/bf3788c03fec679bcdaef787518dbe60d12fe5615a544a6d4cf82f045193/websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb", size = 181094 }, - { url = "https://files.pythonhosted.org/packages/5e/da/9fb8c21edbc719b66763a571afbaf206cb6d3736d28255a46fc2fe20f902/websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054", size = 181397 }, - { url = "https://files.pythonhosted.org/packages/2e/65/65f379525a2719e91d9d90c38fe8b8bc62bd3c702ac651b7278609b696c4/websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee", size = 181794 }, - { url = "https://files.pythonhosted.org/packages/d9/26/31ac2d08f8e9304d81a1a7ed2851c0300f636019a57cbaa91342015c72cc/websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed", size = 181194 }, - { url = "https://files.pythonhosted.org/packages/98/72/1090de20d6c91994cd4b357c3f75a4f25ee231b63e03adea89671cc12a3f/websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880", size = 181164 }, - { url = "https://files.pythonhosted.org/packages/2d/37/098f2e1c103ae8ed79b0e77f08d83b0ec0b241cf4b7f2f10edd0126472e1/websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411", size = 176381 }, - { url = "https://files.pythonhosted.org/packages/75/8b/a32978a3ab42cebb2ebdd5b05df0696a09f4d436ce69def11893afa301f0/websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4", size = 176841 }, - { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109 }, - { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343 }, - { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599 }, - { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207 }, - { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155 }, - { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884 }, - { url = "https://files.pythonhosted.org/packages/b7/48/4b67623bac4d79beb3a6bb27b803ba75c1bdedc06bd827e465803690a4b2/websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940", size = 173106 }, - { url = "https://files.pythonhosted.org/packages/ed/f0/adb07514a49fe5728192764e04295be78859e4a537ab8fcc518a3dbb3281/websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e", size = 173339 }, - { url = "https://files.pythonhosted.org/packages/87/28/bd23c6344b18fb43df40d0700f6d3fffcd7cef14a6995b4f976978b52e62/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9", size = 174597 }, - { url = "https://files.pythonhosted.org/packages/6d/79/ca288495863d0f23a60f546f0905ae8f3ed467ad87f8b6aceb65f4c013e4/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b", size = 174205 }, - { url = "https://files.pythonhosted.org/packages/04/e4/120ff3180b0872b1fe6637f6f995bcb009fb5c87d597c1fc21456f50c848/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f", size = 174150 }, - { url = "https://files.pythonhosted.org/packages/cb/c3/30e2f9c539b8da8b1d76f64012f3b19253271a63413b2d3adb94b143407f/websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123", size = 176877 }, - { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/da/6462a9f510c0c49837bbc9345aca92d767a56c1fb2939e1579df1e1cdcf7/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", size = 175423, upload-time = "2025-03-05T20:01:35.363Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/9d11c1a4eb046a9e106483b9ff69bce7ac880443f00e5ce64261b47b07e7/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", size = 173080, upload-time = "2025-03-05T20:01:37.304Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4f/b462242432d93ea45f297b6179c7333dd0402b855a912a04e7fc61c0d71f/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", size = 173329, upload-time = "2025-03-05T20:01:39.668Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0c/6afa1f4644d7ed50284ac59cc70ef8abd44ccf7d45850d989ea7310538d0/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", size = 182312, upload-time = "2025-03-05T20:01:41.815Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d4/ffc8bd1350b229ca7a4db2a3e1c482cf87cea1baccd0ef3e72bc720caeec/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", size = 181319, upload-time = "2025-03-05T20:01:43.967Z" }, + { url = "https://files.pythonhosted.org/packages/97/3a/5323a6bb94917af13bbb34009fac01e55c51dfde354f63692bf2533ffbc2/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", size = 181631, upload-time = "2025-03-05T20:01:46.104Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/1aeb0f7cee59ef065724041bb7ed667b6ab1eeffe5141696cccec2687b66/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", size = 182016, upload-time = "2025-03-05T20:01:47.603Z" }, + { url = "https://files.pythonhosted.org/packages/79/f9/c86f8f7af208e4161a7f7e02774e9d0a81c632ae76db2ff22549e1718a51/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", size = 181426, upload-time = "2025-03-05T20:01:48.949Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/828b0bc6753db905b91df6ae477c0b14a141090df64fb17f8a9d7e3516cf/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", size = 181360, upload-time = "2025-03-05T20:01:50.938Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/250f5533ec468ba6327055b7d98b9df056fb1ce623b8b6aaafb30b55d02e/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", size = 176388, upload-time = "2025-03-05T20:01:52.213Z" }, + { url = "https://files.pythonhosted.org/packages/1c/46/aca7082012768bb98e5608f01658ff3ac8437e563eca41cf068bd5849a5e/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", size = 176830, upload-time = "2025-03-05T20:01:53.922Z" }, + { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423, upload-time = "2025-03-05T20:01:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082, upload-time = "2025-03-05T20:01:57.563Z" }, + { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330, upload-time = "2025-03-05T20:01:59.063Z" }, + { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878, upload-time = "2025-03-05T20:02:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883, upload-time = "2025-03-05T20:02:03.148Z" }, + { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252, upload-time = "2025-03-05T20:02:05.29Z" }, + { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521, upload-time = "2025-03-05T20:02:07.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958, upload-time = "2025-03-05T20:02:09.842Z" }, + { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918, upload-time = "2025-03-05T20:02:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388, upload-time = "2025-03-05T20:02:13.32Z" }, + { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828, upload-time = "2025-03-05T20:02:14.585Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/36/db/3fff0bcbe339a6fa6a3b9e3fbc2bfb321ec2f4cd233692272c5a8d6cf801/websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5", size = 175424, upload-time = "2025-03-05T20:02:56.505Z" }, + { url = "https://files.pythonhosted.org/packages/46/e6/519054c2f477def4165b0ec060ad664ed174e140b0d1cbb9fafa4a54f6db/websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a", size = 173077, upload-time = "2025-03-05T20:02:58.37Z" }, + { url = "https://files.pythonhosted.org/packages/1a/21/c0712e382df64c93a0d16449ecbf87b647163485ca1cc3f6cbadb36d2b03/websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b", size = 173324, upload-time = "2025-03-05T20:02:59.773Z" }, + { url = "https://files.pythonhosted.org/packages/1c/cb/51ba82e59b3a664df54beed8ad95517c1b4dc1a913730e7a7db778f21291/websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770", size = 182094, upload-time = "2025-03-05T20:03:01.827Z" }, + { url = "https://files.pythonhosted.org/packages/fb/0f/bf3788c03fec679bcdaef787518dbe60d12fe5615a544a6d4cf82f045193/websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb", size = 181094, upload-time = "2025-03-05T20:03:03.123Z" }, + { url = "https://files.pythonhosted.org/packages/5e/da/9fb8c21edbc719b66763a571afbaf206cb6d3736d28255a46fc2fe20f902/websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054", size = 181397, upload-time = "2025-03-05T20:03:04.443Z" }, + { url = "https://files.pythonhosted.org/packages/2e/65/65f379525a2719e91d9d90c38fe8b8bc62bd3c702ac651b7278609b696c4/websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee", size = 181794, upload-time = "2025-03-05T20:03:06.708Z" }, + { url = "https://files.pythonhosted.org/packages/d9/26/31ac2d08f8e9304d81a1a7ed2851c0300f636019a57cbaa91342015c72cc/websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed", size = 181194, upload-time = "2025-03-05T20:03:08.844Z" }, + { url = "https://files.pythonhosted.org/packages/98/72/1090de20d6c91994cd4b357c3f75a4f25ee231b63e03adea89671cc12a3f/websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880", size = 181164, upload-time = "2025-03-05T20:03:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/2d/37/098f2e1c103ae8ed79b0e77f08d83b0ec0b241cf4b7f2f10edd0126472e1/websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411", size = 176381, upload-time = "2025-03-05T20:03:12.77Z" }, + { url = "https://files.pythonhosted.org/packages/75/8b/a32978a3ab42cebb2ebdd5b05df0696a09f4d436ce69def11893afa301f0/websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4", size = 176841, upload-time = "2025-03-05T20:03:14.367Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109, upload-time = "2025-03-05T20:03:17.769Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343, upload-time = "2025-03-05T20:03:19.094Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599, upload-time = "2025-03-05T20:03:21.1Z" }, + { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207, upload-time = "2025-03-05T20:03:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155, upload-time = "2025-03-05T20:03:25.321Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884, upload-time = "2025-03-05T20:03:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/48/4b67623bac4d79beb3a6bb27b803ba75c1bdedc06bd827e465803690a4b2/websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940", size = 173106, upload-time = "2025-03-05T20:03:29.404Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f0/adb07514a49fe5728192764e04295be78859e4a537ab8fcc518a3dbb3281/websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e", size = 173339, upload-time = "2025-03-05T20:03:30.755Z" }, + { url = "https://files.pythonhosted.org/packages/87/28/bd23c6344b18fb43df40d0700f6d3fffcd7cef14a6995b4f976978b52e62/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9", size = 174597, upload-time = "2025-03-05T20:03:32.247Z" }, + { url = "https://files.pythonhosted.org/packages/6d/79/ca288495863d0f23a60f546f0905ae8f3ed467ad87f8b6aceb65f4c013e4/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b", size = 174205, upload-time = "2025-03-05T20:03:33.731Z" }, + { url = "https://files.pythonhosted.org/packages/04/e4/120ff3180b0872b1fe6637f6f995bcb009fb5c87d597c1fc21456f50c848/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f", size = 174150, upload-time = "2025-03-05T20:03:35.757Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c3/30e2f9c539b8da8b1d76f64012f3b19253271a63413b2d3adb94b143407f/websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123", size = 176877, upload-time = "2025-03-05T20:03:37.199Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, ] [[package]] @@ -4355,25 +4374,25 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 } +sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925, upload-time = "2024-11-08T15:52:18.093Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 }, + { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" }, ] [[package]] name = "wheel" version = "0.45.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545 } +sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545, upload-time = "2024-11-23T00:18:23.513Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494 }, + { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494, upload-time = "2024-11-23T00:18:21.207Z" }, ] [[package]] name = "zipp" version = "3.21.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545, upload-time = "2024-11-10T15:05:20.202Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630, upload-time = "2024-11-10T15:05:19.275Z" }, ] From a5b523673cbd96711054de51356722c0f6fda1f2 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Thu, 8 May 2025 13:47:33 +0000 Subject: [PATCH 02/11] feat: bind parameter cleanup --- docs/examples/litestar_asyncpg.py | 46 +++ docs/examples/litestar_psycopg.py | 48 +++ pyproject.toml | 6 +- sqlspec/adapters/adbc/driver.py | 129 +++---- sqlspec/adapters/aiosqlite/driver.py | 259 ++++++++----- sqlspec/adapters/asyncmy/driver.py | 175 ++++++--- sqlspec/adapters/asyncpg/driver.py | 466 ++++++++++++------------ sqlspec/adapters/bigquery/driver.py | 70 +++- sqlspec/adapters/duckdb/driver.py | 219 ++++++++--- sqlspec/adapters/oracledb/driver.py | 122 ++++++- sqlspec/adapters/psqlpy/driver.py | 162 ++++---- sqlspec/adapters/psycopg/driver.py | 158 ++++---- sqlspec/adapters/sqlite/driver.py | 287 +++++++++------ sqlspec/base.py | 2 +- sqlspec/extensions/litestar/handlers.py | 6 +- sqlspec/statement.py | 382 ++++++------------- sqlspec/utils/text.py | 39 +- uv.lock | 12 +- 18 files changed, 1507 insertions(+), 1081 deletions(-) create mode 100644 docs/examples/litestar_asyncpg.py create mode 100644 docs/examples/litestar_psycopg.py diff --git a/docs/examples/litestar_asyncpg.py b/docs/examples/litestar_asyncpg.py new file mode 100644 index 0000000..d6a1103 --- /dev/null +++ b/docs/examples/litestar_asyncpg.py @@ -0,0 +1,46 @@ +"""Litestar Asyncpg + +This example demonstrates how to use a Asyncpg database in a Litestar application. + +The example uses the `SQLSpec` extension to create a connection to a Asyncpg database. + +The Asyncpg database also demonstrates how to use the plugin loader and `secrets` configuration manager built into SQLSpec. +""" +# /// script +# dependencies = [ +# "sqlspec[psycopg,asyncpg,performance]", +# "litestar[standard]", +# ] +# /// + +from litestar import Litestar, get + +from sqlspec.adapters.asyncpg import AsyncpgConfig, AsyncpgDriver, AsyncpgPoolConfig +from sqlspec.extensions.litestar import DatabaseConfig, SQLSpec + + +@get("/") +async def simple_asyncpg(db_session: AsyncpgDriver) -> dict[str, str]: + return await db_session.select_one("SELECT 'Hello, world!' AS greeting") + + +sqlspec = SQLSpec( + config=[ + DatabaseConfig( + config=AsyncpgConfig( + pool_config=AsyncpgPoolConfig(dsn="postgres://app:app@localhost:15432/app", min_size=1, max_size=3), + ), + commit_mode="autocommit", + ) + ] +) +app = Litestar(route_handlers=[simple_asyncpg], plugins=[sqlspec]) + +if __name__ == "__main__": + import os + + from litestar.cli import litestar_group + + os.environ["LITESTAR_APP"] = "docs.examples.litestar_asyncpg:app" + + litestar_group() diff --git a/docs/examples/litestar_psycopg.py b/docs/examples/litestar_psycopg.py new file mode 100644 index 0000000..563cc8e --- /dev/null +++ b/docs/examples/litestar_psycopg.py @@ -0,0 +1,48 @@ +"""Litestar Psycopg + +This example demonstrates how to use a Psycopg database in a Litestar application. + +The example uses the `SQLSpec` extension to create a connection to a Psycopg database. + +The Psycopg database also demonstrates how to use the plugin loader and `secrets` configuration manager built into SQLSpec. +""" +# /// script +# dependencies = [ +# "sqlspec[psycopg]", +# "litestar[standard]", +# ] +# /// + +from litestar import Litestar, get + +from sqlspec.adapters.psycopg import PsycopgAsyncConfig, PsycopgAsyncDriver, PsycopgAsyncPoolConfig +from sqlspec.extensions.litestar import DatabaseConfig, SQLSpec + + +@get("/") +async def simple_psycopg(db_session: PsycopgAsyncDriver) -> dict[str, str]: + return await db_session.select_one("SELECT 'Hello, world!' AS greeting") + + +sqlspec = SQLSpec( + config=[ + DatabaseConfig( + config=PsycopgAsyncConfig( + pool_config=PsycopgAsyncPoolConfig( + conninfo="postgres://app:app@localhost:15432/app", min_size=1, max_size=3 + ), + ), + commit_mode="autocommit", + ) + ], +) +app = Litestar(route_handlers=[simple_psycopg], plugins=[sqlspec]) + +if __name__ == "__main__": + import os + + from litestar.cli import litestar_group + + os.environ["LITESTAR_APP"] = "docs.examples.litestar_psycopg:app" + + litestar_group() diff --git a/pyproject.toml b/pyproject.toml index 4d9a9e1..74498fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -318,7 +318,11 @@ select = ["ALL"] convention = "google" [tool.ruff.lint.mccabe] -max-complexity = 18 +max-complexity = 25 + +[tool.ruff.lint.pylint] +max-branches = 20 +max-locals = 20 [tool.ruff.lint.pep8-naming] classmethod-decorators = ["classmethod"] diff --git a/sqlspec/adapters/adbc/driver.py b/sqlspec/adapters/adbc/driver.py index 8b55e1d..6345bb4 100644 --- a/sqlspec/adapters/adbc/driver.py +++ b/sqlspec/adapters/adbc/driver.py @@ -10,8 +10,9 @@ from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import SQLStatement +from sqlspec.statement import PARAM_REGEX from sqlspec.typing import ArrowTable, StatementParameterType +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T @@ -21,18 +22,6 @@ logger = logging.getLogger("sqlspec") -PARAM_REGEX = re.compile( - r"""(?"(?:[^"]|"")*") | # Double-quoted strings - (?P'(?:[^']|'')*') | # Single-quoted strings - (?P--.*?\n|\/\*.*?\*\/) | # SQL comments - (?P[:\$])(?P[a-zA-Z_][a-zA-Z0-9_]*) # :name or $name identifier - ) - """, - re.VERBOSE | re.DOTALL, -) - AdbcConnection = Connection @@ -45,11 +34,11 @@ class AdbcDriver( connection: AdbcConnection __supports_arrow__: ClassVar[bool] = True + dialect: str = "adbc" def __init__(self, connection: "AdbcConnection") -> None: """Initialize the ADBC driver adapter.""" self.connection = connection - self.dialect = self._get_dialect(connection) @staticmethod def _get_dialect(connection: "AdbcConnection") -> str: # noqa: PLR0911 @@ -96,76 +85,54 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # Determine effective parameter type *before* calling SQLStatement - merged_params_type = dict if kwargs else type(parameters) - - # If ADBC + sqlite/duckdb + dictionary params, handle conversion manually - if self.dialect in {"sqlite", "duckdb"} and merged_params_type is dict: - logger.debug( - "ADBC/%s with dict params; bypassing SQLStatement conversion, manually converting to '?' positional.", - self.dialect, - ) - - # Combine parameters and kwargs into the actual dictionary to use - parameter_dict = {} # type: ignore[var-annotated] - if isinstance(parameters, dict): - parameter_dict.update(parameters) - if kwargs: - parameter_dict.update(kwargs) - - # Define regex locally to find :name or $name - - processed_sql_parts: list[str] = [] - ordered_params = [] - last_end = 0 - found_params_regex: list[str] = [] - - for match in PARAM_REGEX.finditer(sql): # Use original sql - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("var_name"): - var_name = match.group("var_name") - leading_char = match.group("lead") # : or $ - found_params_regex.append(var_name) - # Use match span directly for replacement - start = match.start() - end = match.end() + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None - if var_name not in parameter_dict: - msg = f"Named parameter '{leading_char}{var_name}' found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - processed_sql_parts.extend((sql[last_end:start], "?")) # Force ? style - ordered_params.append(parameter_dict[var_name]) - last_end = end - - processed_sql_parts.append(sql[last_end:]) - - if not found_params_regex and parameter_dict: - msg = f"ADBC/{self.dialect}: Dict params provided, but no :name or $name placeholders found. SQL: {sql}" + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for adbc driver." raise ParameterStyleMismatchError(msg) - - # Key validation - provided_keys = set(parameter_dict.keys()) - missing_keys = set(found_params_regex) - provided_keys - if missing_keys: - msg = ( - f"Named parameters found in SQL ({found_params_regex}) but not provided: {missing_keys}. SQL: {sql}" - ) - raise SQLParsingError(msg) - extra_keys = provided_keys - set(found_params_regex) - if extra_keys: - logger.debug("Extra parameters provided for ADBC/%s: %s", self.dialect, extra_keys) - # Allow extra keys - - final_sql = "".join(processed_sql_parts) - final_params = tuple(ordered_params) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="adbc") return final_sql, final_params - # For all other cases (other dialects, or non-dict params for sqlite/duckdb), - # use the standard SQLStatement processing. - stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None) - return stmt.process() + + # Case 2: Sequence parameters - pass through + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar parameter - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + ): + if match.group(5): + has_placeholders = True + break + + if has_placeholders: + msg = f"adbc: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None @overload def select( diff --git a/sqlspec/adapters/aiosqlite/driver.py b/sqlspec/adapters/aiosqlite/driver.py index fb6e34e..9bddb6d 100644 --- a/sqlspec/adapters/aiosqlite/driver.py +++ b/sqlspec/adapters/aiosqlite/driver.py @@ -1,10 +1,15 @@ +import logging +import re from contextlib import asynccontextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload import aiosqlite from sqlspec.base import AsyncDriverAdapterProtocol +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.statement import PARAM_REGEX +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import AsyncGenerator, Sequence @@ -14,6 +19,18 @@ __all__ = ("AiosqliteConnection", "AiosqliteDriver") AiosqliteConnection = aiosqlite.Connection +logger = logging.getLogger("sqlspec") + +# Regex to find '?' placeholders, skipping those inside quotes or SQL comments +QMARK_REGEX = re.compile( + r"""(?P"[^"]*") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) + class AiosqliteDriver( SQLTranslatorMixin["AiosqliteConnection"], @@ -39,6 +56,62 @@ async def _with_cursor(self, connection: "AiosqliteConnection") -> "AsyncGenerat finally: await cursor.close() + def _process_sql_params( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + **kwargs: Any, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for aiosqlite driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="sqlite") + return final_sql, final_params + + # Case 2: Sequence parameters - pass through + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar parameter - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + ): + if match.group(5): + has_placeholders = True + break + + if has_placeholders: + msg = f"aiosqlite: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + # --- Public API Methods --- # @overload async def select( @@ -71,7 +144,7 @@ async def select( connection: Optional["AiosqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": """Fetch data from the database. Returns: @@ -79,15 +152,19 @@ async def select( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - results = await cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if not results: - return [] - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if schema_type is None: - return [dict(zip(column_names, row)) for row in results] # pyright: ignore[reportUnknownArgumentType] - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore[reportUnknownArgumentType] + + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + results = await cursor.fetchall() + if not results: + return [] + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return [dict(zip(column_names, row)) for row in results] + return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] @overload async def select_one( @@ -120,7 +197,7 @@ async def select_one( connection: Optional["AiosqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Union[ModelDTOT, dict[str, Any]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Fetch one row from the database. Returns: @@ -128,14 +205,18 @@ async def select_one( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - result = self.check_not_found(result) - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if schema_type is None: - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType] + + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + result = await cursor.fetchone() + result = self.check_not_found(result) + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload async def select_one_or_none( @@ -168,7 +249,7 @@ async def select_one_or_none( connection: Optional["AiosqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": """Fetch one row from the database. Returns: @@ -176,15 +257,19 @@ async def select_one_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if result is None: - return None - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if schema_type is None: - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType] + + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + result = await cursor.fetchone() + if result is None: + return None + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload async def select_value( @@ -211,27 +296,31 @@ async def select_value( async def select_value( self, sql: str, - parameters: "Optional[StatementParameterType]" = None, + parameters: Optional["StatementParameterType"] = None, /, *, - connection: "Optional[AiosqliteConnection]" = None, + connection: Optional["AiosqliteConnection"] = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": """Fetch a single value from the database. Returns: - The first value from the first row of results, or None if no results. + The first value from the first row of results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType] - result = self.check_not_found(result) - if schema_type is None: - return result[0] - return schema_type(result[0]) # type: ignore[call-arg] + + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + result = await cursor.fetchone() + result = self.check_not_found(result) + + # Return first value from the row + result_value = result[0] + if schema_type is None: + return result_value + return cast("T", schema_type(result_value)) # type: ignore[call-arg] @overload async def select_value_or_none( @@ -258,10 +347,10 @@ async def select_value_or_none( async def select_value_or_none( self, sql: str, - parameters: "Optional[StatementParameterType]" = None, + parameters: Optional["StatementParameterType"] = None, /, *, - connection: "Optional[AiosqliteConnection]" = None, + connection: Optional["AiosqliteConnection"] = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": @@ -272,14 +361,18 @@ async def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType] - if result is None: - return None - if schema_type is None: - return result[0] - return schema_type(result[0]) # type: ignore[call-arg] + + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + result = await cursor.fetchone() + if result is None: + return None + + # Return first value from the row + result_value = result[0] + if schema_type is None: + return result_value + return cast("T", schema_type(result_value)) # type: ignore[call-arg] async def insert_update_delete( self, @@ -298,9 +391,10 @@ async def insert_update_delete( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - return cursor.rowcount if hasattr(cursor, "rowcount") else -1 # pyright: ignore[reportUnknownVariableType, reportGeneralTypeIssues] + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + await connection.commit() + return cursor.rowcount @overload async def insert_update_delete_returning( @@ -333,7 +427,7 @@ async def insert_update_delete_returning( connection: Optional["AiosqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Insert, update, or delete data from the database and return result. Returns: @@ -342,15 +436,18 @@ async def insert_update_delete_returning( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - results = list(await cursor.fetchall()) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if not results: # Check if empty - return None - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, results[0])))) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] - return dict(zip(column_names, results[0])) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] + # Execute the query + cursor = await connection.execute(sql, parameters or ()) + await connection.commit() + result = await cursor.fetchone() + result = self.check_not_found(result) + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) async def execute_script( self, @@ -369,34 +466,18 @@ async def execute_script( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - return "DONE" + # Execute the script + await connection.executescript(sql) + await connection.commit() + return "Script executed successfully." - async def execute_script_returning( - self, - sql: str, - parameters: Optional["StatementParameterType"] = None, - /, - *, - connection: Optional["AiosqliteConnection"] = None, - schema_type: "Optional[type[ModelDTOT]]" = None, - **kwargs: Any, - ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": - """Execute a script and return result. + def _connection(self, connection: Optional["AiosqliteConnection"] = None) -> "AiosqliteConnection": + """Get the connection to use for the operation. + + Args: + connection: Optional connection to use. Returns: - The first row of results. + The connection to use. """ - connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - - async with self._with_cursor(connection) as cursor: - await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - results = list(await cursor.fetchall()) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if not results: # Check if empty - return None - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, results[0])))) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] - return dict(zip(column_names, results[0])) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] + return connection or self.connection diff --git a/sqlspec/adapters/asyncmy/driver.py b/sqlspec/adapters/asyncmy/driver.py index f291f35..5133da2 100644 --- a/sqlspec/adapters/asyncmy/driver.py +++ b/sqlspec/adapters/asyncmy/driver.py @@ -1,12 +1,17 @@ # type: ignore +import logging +import re from collections.abc import AsyncGenerator, Sequence from contextlib import asynccontextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -from asyncmy import Connection +import asyncmy from sqlspec.base import AsyncDriverAdapterProtocol +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.statement import PARAM_REGEX +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from asyncmy.cursors import Cursor @@ -15,7 +20,18 @@ __all__ = ("AsyncmyDriver",) -AsyncmyConnection = Connection +AsyncmyConnection = asyncmy.Connection + +logger = logging.getLogger("sqlspec") + +QMARK_REGEX = re.compile( + r"""(?P\"[^\"]*\") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) class AsyncmyDriver( @@ -39,6 +55,62 @@ async def _with_cursor(connection: "AsyncmyConnection") -> AsyncGenerator["Curso finally: await cursor.close() + def _process_sql_params( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + **kwargs: Any, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for asyncmy driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="mysql") + return final_sql, final_params + + # Case 2: Sequence parameters - pass through + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar parameter - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + ): + if match.group(5): + has_placeholders = True + break + + if has_placeholders: + msg = f"asyncmy: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + # --- Public API Methods --- # @overload async def select( @@ -65,13 +137,13 @@ async def select( async def select( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncmyConnection"] = None, + connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": """Fetch data from the database. Returns: @@ -84,10 +156,9 @@ async def select( results = await cursor.fetchall() if not results: return [] - column_names = [c[0] for c in cursor.description or []] if schema_type is None: - return [dict(zip(column_names, row)) for row in results] - return [schema_type(**dict(zip(column_names, row))) for row in results] + return [dict(zip(cursor.column_names, row)) for row in results] + return [cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, row)))) for row in results] @overload async def select_one( @@ -114,13 +185,13 @@ async def select_one( async def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncmyConnection"] = None, + connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Union[ModelDTOT, dict[str, Any]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Fetch one row from the database. Returns: @@ -132,10 +203,9 @@ async def select_one( await cursor.execute(sql, parameters) result = await cursor.fetchone() result = self.check_not_found(result) - column_names = [c[0] for c in cursor.description or []] if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + return dict(zip(cursor.column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, result)))) @overload async def select_one_or_none( @@ -162,13 +232,13 @@ async def select_one_or_none( async def select_one_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncmyConnection"] = None, + connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": """Fetch one row from the database. Returns: @@ -181,10 +251,9 @@ async def select_one_or_none( result = await cursor.fetchone() if result is None: return None - column_names = [c[0] for c in cursor.description or []] if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + return dict(zip(cursor.column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, result)))) @overload async def select_value( @@ -221,20 +290,19 @@ async def select_value( """Fetch a single value from the database. Returns: - The first value from the first row of results, or None if no results. + The first value from the first row of results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() result = self.check_not_found(result) - - value = result[0] - if schema_type is not None: - return schema_type(value) # type: ignore[call-arg] - return value + # Return first value from the row + result_value = result[0] if result else None + if schema_type is None: + return result_value + return schema_type(result_value) @overload async def select_value_or_none( @@ -275,26 +343,24 @@ async def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() - if result is None: return None - - value = result[0] - if schema_type is not None: - return schema_type(value) # type: ignore[call-arg] - return value + # Return first value from the row + result_value = result[0] if result else None + if schema_type is None: + return result_value + return schema_type(result_value) async def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncmyConnection"] = None, + connection: "Optional[AsyncmyConnection]" = None, **kwargs: Any, ) -> int: """Insert, update, or delete data from the database. @@ -304,7 +370,6 @@ async def insert_update_delete( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) return cursor.rowcount @@ -334,13 +399,13 @@ async def insert_update_delete_returning( async def insert_update_delete_returning( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncmyConnection"] = None, + connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Insert, update, or delete data from the database and return result. Returns: @@ -348,25 +413,21 @@ async def insert_update_delete_returning( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - column_names: list[str] = [] - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() - if result is None: - return None - column_names = [c[0] for c in cursor.description or []] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) - return dict(zip(column_names, result)) + result = self.check_not_found(result) + if schema_type is None: + return dict(zip(cursor.column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, result)))) async def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncmyConnection"] = None, + connection: "Optional[AsyncmyConnection]" = None, **kwargs: Any, ) -> str: """Execute a script. @@ -376,7 +437,17 @@ async def execute_script( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) - return "DONE" + return f"Script executed successfully. Rows affected: {cursor.rowcount}" + + def _connection(self, connection: "Optional[AsyncmyConnection]" = None) -> "AsyncmyConnection": + """Get the connection to use for the operation. + + Args: + connection: Optional connection to use. + + Returns: + The connection to use. + """ + return connection or self.connection diff --git a/sqlspec/adapters/asyncpg/driver.py b/sqlspec/adapters/asyncpg/driver.py index 6d23505..819afa3 100644 --- a/sqlspec/adapters/asyncpg/driver.py +++ b/sqlspec/adapters/asyncpg/driver.py @@ -6,9 +6,9 @@ from typing_extensions import TypeAlias from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.exceptions import SQLParsingError +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, SQLStatement +from sqlspec.statement import PARAM_REGEX if TYPE_CHECKING: from collections.abc import Sequence @@ -26,14 +26,14 @@ # Simplified version, assumes standard SQL quoting/comments QMARK_REGEX = re.compile( r"""(?P"[^"]*") | # Double-quoted strings - (?P\'[^\']*\') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder + (?P\\'[^\\']*\\') | # Single-quoted strings + (?P--[^\\n]*|/\\*.*?\\*/) | # SQL comments (single/multi-line) + (?P\\?) # The question mark placeholder """, re.VERBOSE | re.DOTALL, ) -AsyncpgConnection: TypeAlias = "Union[Connection[Any], PoolConnectionProxy[Any]]" # pyright: ignore[reportMissingTypeArgument] +AsyncpgConnection: TypeAlias = "Union[Connection[Any], PoolConnectionProxy[Any]]" class AsyncpgDriver( @@ -48,27 +48,82 @@ class AsyncpgDriver( def __init__(self, connection: "AsyncpgConnection") -> None: self.connection = connection - def _process_sql_params( # noqa: C901, PLR0912, PLR0915 + def _process_sql_params( # noqa: PLR0912, PLR0915, PLR0914 self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # Use SQLStatement for parameter validation and merging first - # It also handles potential dialect-specific logic if implemented there. - stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None) - sql, parameters = stmt.process() + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None + merged_params_type: Optional[type] = None + + if kwargs: + merged_params_type = dict + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for asyncpg driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params_type = type(parameters) + # Preserve original type (dict, list, tuple, scalar) for now + merged_params = parameters # type: ignore + + # 2. Process based on merged parameter type + + # Case 0: No parameters provided + if merged_params_type is None: + # Basic validation: Check if SQL contains placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # More refined check for '?' outside comments/strings + if QMARK_REGEX.search(sql): + # Check again avoiding comments/strings + if re.search( + r"(? $n conversion + # Manually parse the *original* SQL for :name -> $n conversion for match in PARAM_REGEX.finditer(sql): # Skip matches inside quotes or comments if match.group("dquote") or match.group("squote") or match.group("comment"): @@ -80,127 +135,88 @@ def _process_sql_params( # noqa: C901, PLR0912, PLR0915 start = match.start("var_name") - 1 # Include the ':' end = match.end("var_name") - # SQLStatement should have already validated parameter existence, - # but we double-check here during ordering. - if var_name not in parameters: - # This should ideally not happen if SQLStatement validation is robust. - msg = ( - f"Named parameter ':{var_name}' found in SQL but missing from processed parameters. " - f"Processed SQL: {sql}" - ) + if var_name not in parameter_dict: + msg = f"asyncpg: Named parameter ':{var_name}' found in SQL but not provided. SQL: {sql}" raise SQLParsingError(msg) processed_sql_parts.extend((sql[last_end:start], f"${param_index}")) - ordered_params.append(parameters[var_name]) + ordered_params.append(parameter_dict[var_name]) last_end = end param_index += 1 processed_sql_parts.append(sql[last_end:]) final_sql = "".join(processed_sql_parts) - # --- Validation --- - # Check if named placeholders were found if dict params were provided - # SQLStatement might handle this validation, but a warning here can be useful. - if not found_params_regex and parameters: - logger.warning( - "Dict params provided (%s), but no :name placeholders found. SQL: %s", - list(parameters.keys()), - sql, - ) - # If no placeholders, return original SQL from SQLStatement and empty tuple for asyncpg - return sql, () - - # Additional checks (potentially redundant if SQLStatement covers them): - # 1. Ensure all found placeholders have corresponding params (covered by check inside loop) - # 2. Ensure all provided params correspond to a placeholder - provided_keys = set(parameters.keys()) - found_keys = set(found_params_regex) - unused_keys = provided_keys - found_keys - if unused_keys: - # SQLStatement might handle this, but log a warning just in case. - logger.warning( - "Parameters provided but not used in SQL: %s. SQL: %s", - unused_keys, - sql, - ) - - return final_sql, tuple(ordered_params) # asyncpg expects a sequence - - # Case 2: Parameters are effectively a sequence/scalar (merged by SQLStatement) - if isinstance(parameters, (list, tuple)): - # Parameters are a sequence, need to convert ? -> $n - sequence_processed_parts: list[str] = [] - param_index = 1 - last_end = 0 - qmark_found = False - - # Manually parse the PROCESSED SQL to find '?' outside comments/quotes and convert to $n - for match in QMARK_REGEX.finditer(sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue # Skip quotes and comments + # Validation + if not found_params_regex and parameter_dict: + msg = f"asyncpg: Dictionary parameters provided, but no named placeholders (:name) found. SQL: {sql}" + raise ParameterStyleMismatchError(msg) # Or log warning? - if match.group("qmark"): - qmark_found = True - start = match.start("qmark") - end = match.end("qmark") - sequence_processed_parts.extend((sql[last_end:start], f"${param_index}")) - last_end = end - param_index += 1 + provided_keys = set(parameter_dict.keys()) + required_keys = set(found_params_regex) + missing_keys = required_keys - provided_keys + if missing_keys: + msg = f"asyncpg: Named parameters found in SQL ({required_keys}) but not provided: {missing_keys}. SQL: {sql}" + raise SQLParsingError(msg) + # Allow extra keys - sequence_processed_parts.append(sql[last_end:]) - final_sql = "".join(sequence_processed_parts) + return final_sql, tuple(ordered_params) - # --- Validation --- - # Check if '?' was found if parameters were provided - if parameters and not qmark_found: - # SQLStatement might allow this, log a warning. - logger.warning( - "Sequence/scalar parameters provided, but no '?' placeholders found. SQL: %s", - sql, - ) - # Return PROCESSED SQL from SQLStatement as no conversion happened here - return sql, parameters + # Case 2: Parameters are a sequence or scalar (? style) + if isinstance(merged_params, (list, tuple)): + params_tuple = tuple(merged_params) + final_sql, expected_params = self._convert_qmarks_to_dollar(sql) + actual_params = len(params_tuple) - # Check parameter count match (using count from manual parsing vs count from stmt) - expected_params = param_index - 1 - actual_params = len(parameters) if expected_params != actual_params: msg = ( - f"Parameter count mismatch: Processed SQL expected {expected_params} parameters ('$n'), " - f"but {actual_params} were provided by SQLStatement. " - f"Final Processed SQL: {final_sql}" + f"asyncpg: Parameter count mismatch. SQL requires {expected_params} positional parameters ($n), " + f"but {actual_params} were provided. Processed SQL: {final_sql}" ) raise SQLParsingError(msg) - return final_sql, parameters - - # Case 3: Parameters are None (as determined by SQLStatement) - # processed_params is None - # Check if the SQL contains any placeholders unexpectedly - # Check for :name style - named_placeholders_found = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - named_placeholders_found = True - break - if named_placeholders_found: - msg = f"Processed SQL contains named parameters (:name) but no parameters were provided. SQL: {sql}" + return final_sql, params_tuple + # Scalar + scalar_param_tuple = (merged_params,) + final_sql, expected_params = self._convert_qmarks_to_dollar(sql) + if expected_params != 1: + msg = ( + f"asyncpg: Parameter count mismatch. SQL requires {expected_params} positional parameters ($n), " + f"but 1 (scalar) was provided. Processed SQL: {final_sql}" + ) raise SQLParsingError(msg) + return final_sql, scalar_param_tuple + + @staticmethod + def _convert_qmarks_to_dollar(sql: str) -> tuple[str, int]: + """Converts '?' placeholders to '$n' and counts them. + + Args: + sql (str): The SQL string to process. + + Returns: + tuple[str, int]: A tuple containing the processed SQL string and the number of '?' placeholders found. + """ + processed_parts: list[str] = [] + param_index = 1 + last_end = 0 + qmark_found_count = 0 - # Check for ? style - qmark_placeholders_found = False for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group("qmark"): - qmark_placeholders_found = True - break - if qmark_placeholders_found: - msg = f"Processed SQL contains positional parameters (?) but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) + if match.group("dquote") or match.group("squote") or match.group("comment"): + continue - # No parameters provided and none found in SQL, return original SQL from SQLStatement and empty tuple - return sql, () # asyncpg expects a sequence, even if empty + if match.group("qmark"): + qmark_found_count += 1 + start = match.start("qmark") + end = match.end("qmark") + processed_parts.extend((sql[last_end:start], f"${param_index}")) + last_end = end + param_index += 1 + + processed_parts.append(sql[last_end:]) + final_sql = "".join(processed_parts) + return final_sql, qmark_found_count @overload async def select( @@ -227,35 +243,29 @@ async def select( async def select( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncpgConnection"] = None, + connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": """Fetch data from the database. - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - schema_type: Optional schema class for the result. - **kwargs: Additional keyword arguments. - Returns: List of row data as either model instances or dictionaries. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - - results = await connection.fetch(sql, *parameters) # pyright: ignore - if not results: - return [] - if schema_type is None: - return [dict(row.items()) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - return [cast("ModelDTOT", schema_type(**dict(row.items()))) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] + params = [] if parameters is None else parameters + async with connection.transaction(): + stmt = await connection.prepare(sql) + results = await stmt.fetch(*params) if isinstance(params, (list, tuple)) else await stmt.fetch(params) + if not results: + return [] + if schema_type is None: + return [dict(record) for record in results] + return [cast("ModelDTOT", schema_type(**dict(record))) for record in results] @overload async def select_one( @@ -282,35 +292,28 @@ async def select_one( async def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncpgConnection"] = None, + connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Union[ModelDTOT, dict[str, Any]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Fetch one row from the database. - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - schema_type: Optional schema class for the result. - **kwargs: Additional keyword arguments. - Returns: The first row of the query results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - result = await connection.fetchrow(sql, *parameters) # pyright: ignore - result = self.check_not_found(result) - - if schema_type is None: - # Always return as dictionary - return dict(result.items()) # type: ignore[attr-defined] - return cast("ModelDTOT", schema_type(**dict(result.items()))) # type: ignore[attr-defined] + params = [] if parameters is None else parameters + async with connection.transaction(): + stmt = await connection.prepare(sql) + result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) + result = self.check_not_found(result) + if schema_type is None: + return dict(result) + return cast("ModelDTOT", schema_type(**dict(result))) @overload async def select_one_or_none( @@ -337,35 +340,29 @@ async def select_one_or_none( async def select_one_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncpgConnection"] = None, + connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": """Fetch one row from the database. - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - schema_type: Optional schema class for the result. - **kwargs: Additional keyword arguments. - Returns: The first row of the query results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - result = await connection.fetchrow(sql, *parameters) # pyright: ignore - if result is None: - return None - if schema_type is None: - # Always return as dictionary - return dict(result.items()) - return cast("ModelDTOT", schema_type(**dict(result.items()))) + params = [] if parameters is None else parameters + async with connection.transaction(): + stmt = await connection.prepare(sql) + result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) + if result is None: + return None + if schema_type is None: + return dict(result) + return cast("ModelDTOT", schema_type(**dict(result))) @overload async def select_value( @@ -401,24 +398,20 @@ async def select_value( ) -> "Union[T, Any]": """Fetch a single value from the database. - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - schema_type: Optional schema class for the result. - **kwargs: Additional keyword arguments. - Returns: - The first value from the first row of results, or None if no results. + The first value from the first row of results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - result = await connection.fetchval(sql, *parameters) # pyright: ignore - result = self.check_not_found(result) - if schema_type is None: - return result - return schema_type(result) # type: ignore[call-arg] + params = [] if parameters is None else parameters + async with connection.transaction(): + stmt = await connection.prepare(sql) + result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) + result = self.check_not_found(result) + result_value = result[0] if result else None + if schema_type is not None and callable(schema_type): + return schema_type(result_value) + return result_value @overload async def select_value_or_none( @@ -459,43 +452,42 @@ async def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - result = await connection.fetchval(sql, *parameters) # pyright: ignore - if result is None: - return None - if schema_type is None: - return result - return schema_type(result) # type: ignore[call-arg] + params = [] if parameters is None else parameters + async with connection.transaction(): + stmt = await connection.prepare(sql) + result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) + if result is None: + return None + result_value = result[0] if result else None + if schema_type is not None and callable(schema_type): + return schema_type(result_value) + return result_value async def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncpgConnection"] = None, + connection: "Optional[AsyncpgConnection]" = None, **kwargs: Any, ) -> int: - """Insert, update, or delete data from the database. - - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - **kwargs: Additional keyword arguments. - - Returns: - Row count affected by the operation. - """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - status = await connection.execute(sql, *parameters) # pyright: ignore - # AsyncPG returns a string like "INSERT 0 1" where the last number is the affected rows - try: - return int(status.split()[-1]) # pyright: ignore[reportUnknownMemberType] - except (ValueError, IndexError, AttributeError): - return -1 # Fallback if we can't parse the status + if parameters is None or (isinstance(parameters, (list, tuple)) and not parameters): + result = await connection.execute(sql) + elif isinstance(parameters, dict) or isinstance(parameters, (list, tuple)): + result = await connection.execute(sql, parameters) # type: ignore + else: + # Scalar: wrap in tuple + result = await connection.execute(sql, (parameters,)) # type: ignore + match = re.match(r"^(?:INSERT|UPDATE|DELETE)\s+\d+\s+(\d+)$", result) + if match: + return int(match.group(1)) + match = re.match(r"^(?:INSERT|UPDATE|DELETE)\s+(\d+)$", result) + if match: + return int(match.group(1)) + return 0 @overload async def insert_update_delete_returning( @@ -522,60 +514,48 @@ async def insert_update_delete_returning( async def insert_update_delete_returning( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncpgConnection"] = None, + connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": - """Insert, update, or delete data from the database and return the affected row. - - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - schema_type: Optional schema class for the result. - **kwargs: Additional keyword arguments. + ) -> "Union[dict[str, Any], ModelDTOT]": + """Insert, update, or delete data from the database and return result. Returns: - The affected row data as either a model instance or dictionary. + The first row of results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - result = await connection.fetchrow(sql, *parameters) # pyright: ignore - if result is None: - return None - if schema_type is None: - # Always return as dictionary - return dict(result.items()) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - return cast("ModelDTOT", schema_type(**dict(result.items()))) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType, reportUnknownVariableType] + params = [] if parameters is None else parameters + async with connection.transaction(): + stmt = await connection.prepare(sql) + result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) + result = self.check_not_found(result) + if schema_type is None: + return dict(result) + return cast("ModelDTOT", schema_type(**dict(result))) async def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AsyncpgConnection"] = None, + connection: "Optional[AsyncpgConnection]" = None, **kwargs: Any, ) -> str: - """Execute a script. - - Args: - sql: SQL statement. - parameters: Query parameters. - connection: Optional connection to use. - **kwargs: Additional keyword arguments. - - Returns: - Status message for the operation. - """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} - return await connection.execute(sql, *parameters) # pyright: ignore + if parameters is None or (isinstance(parameters, (list, tuple)) and not parameters): + await connection.execute(sql) + elif isinstance(parameters, dict) or isinstance(parameters, (list, tuple)): + await connection.execute(sql, parameters) # type: ignore + else: + # Scalar: wrap in tuple + await connection.execute(sql, (parameters,)) # type: ignore + return "Script executed successfully." def _connection(self, connection: Optional["AsyncpgConnection"] = None) -> "AsyncpgConnection": """Return the connection to use. If None, use the default connection.""" diff --git a/sqlspec/adapters/bigquery/driver.py b/sqlspec/adapters/bigquery/driver.py index 3ea1f77..f54911d 100644 --- a/sqlspec/adapters/bigquery/driver.py +++ b/sqlspec/adapters/bigquery/driver.py @@ -1,5 +1,7 @@ import contextlib import datetime +import logging +import re from collections.abc import Iterator, Sequence from decimal import Decimal from typing import ( @@ -19,13 +21,15 @@ from google.cloud.exceptions import NotFound from sqlspec.base import SyncDriverAdapterProtocol -from sqlspec.exceptions import NotFoundError, SQLSpecError +from sqlspec.exceptions import NotFoundError, ParameterStyleMismatchError, SQLParsingError, SQLSpecError from sqlspec.mixins import ( SQLTranslatorMixin, SyncArrowBulkOperationsMixin, SyncParquetExportMixin, ) +from sqlspec.statement import PARAM_REGEX from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from google.cloud.bigquery import SchemaField @@ -35,6 +39,8 @@ BigQueryConnection = Client +logger = logging.getLogger("sqlspec") + class BigQueryDriver( SyncDriverAdapterProtocol["BigQueryConnection"], @@ -55,7 +61,7 @@ def __init__(self, connection: "BigQueryConnection", **kwargs: Any) -> None: ) @staticmethod - def _get_bq_param_type(value: Any) -> "tuple[Optional[str], Optional[str]]": # noqa: PLR0911, PLR0912 + def _get_bq_param_type(value: Any) -> "tuple[Optional[str], Optional[str]]": # noqa: PLR0911 if isinstance(value, bool): return "BOOL", None if isinstance(value, int): @@ -105,7 +111,63 @@ def _get_bq_param_type(value: Any) -> "tuple[Optional[str], Optional[str]]": # return None, None # Unsupported type - def _run_query_job( # noqa: C901, PLR0912, PLR0915 (User change) + def _process_sql_params( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + **kwargs: Any, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for bigquery driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="bigquery") + return final_sql, final_params + + # Case 2: Sequence parameters - pass through + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar parameter - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + ): + if match.group(5): + has_placeholders = True + break + + if has_placeholders: + msg = f"bigquery: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + + def _run_query_job( # noqa: PLR0912, PLR0915 (User change) self, sql: str, parameters: "Optional[StatementParameterType]" = None, @@ -578,7 +640,7 @@ def execute_script( # --- Mixin Implementations --- - def select_arrow( # pyright: ignore # noqa: PLR0912 + def select_arrow( # pyright: ignore self, sql: str, parameters: "Optional[StatementParameterType]" = None, diff --git a/sqlspec/adapters/duckdb/driver.py b/sqlspec/adapters/duckdb/driver.py index de409ac..516dbdb 100644 --- a/sqlspec/adapters/duckdb/driver.py +++ b/sqlspec/adapters/duckdb/driver.py @@ -1,11 +1,16 @@ +import logging +import re from contextlib import contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload from duckdb import DuckDBPyConnection from sqlspec.base import SyncDriverAdapterProtocol +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.statement import PARAM_REGEX from sqlspec.typing import ArrowTable, StatementParameterType +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import Generator, Sequence @@ -14,8 +19,20 @@ __all__ = ("DuckDBConnection", "DuckDBDriver") +logger = logging.getLogger("sqlspec") + DuckDBConnection = DuckDBPyConnection +# Regex to find '?' placeholders, skipping those inside quotes or SQL comments +QMARK_REGEX = re.compile( + r"""(?P"[^"]*") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) + class DuckDBDriver( SyncArrowBulkOperationsMixin["DuckDBConnection"], @@ -32,7 +49,6 @@ def __init__(self, connection: "DuckDBConnection", use_cursor: bool = True) -> N self.connection = connection self.use_cursor = use_cursor - # --- Helper Methods --- # def _cursor(self, connection: "DuckDBConnection") -> "DuckDBConnection": if self.use_cursor: return connection.cursor() @@ -49,6 +65,67 @@ def _with_cursor(self, connection: "DuckDBConnection") -> "Generator[DuckDBConne else: yield connection + def _process_sql_params( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + **kwargs: Any, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + """Process SQL and parameters for DuckDB. + + DuckDB supports both named (:name) and positional (?) parameters. + This method merges parameters and validates them. + """ + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for DuckDB driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="duckdb") + return final_sql, final_params + + # Case 2: Sequence parameters - pass through + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar parameter - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|('(?:[^']|'')*')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + ): + if match.group(5): + has_placeholders = True + break + + if has_placeholders: + msg = f"duckdb: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + # --- Public API Methods --- # @overload def select( @@ -75,26 +152,29 @@ def select( def select( self, sql: str, - parameters: "Optional[StatementParameterType]" = None, + parameters: Optional["StatementParameterType"] = None, /, *, - connection: "Optional[DuckDBConnection]" = None, + connection: Optional["DuckDBConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": + """Fetch data from the database. + + Returns: + List of row data as either model instances or dictionaries. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - results = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] + cursor.execute(sql, [] if parameters is None else parameters) + results = cursor.fetchall() if not results: return [] - - column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - - if schema_type is not None: - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore[reportUnknownArgumentType] - return [dict(zip(column_names, row)) for row in results] # pyright: ignore[reportUnknownArgumentType] + column_names = [column[0] for column in cursor.description or []] + if schema_type is None: + return [dict(zip(column_names, row)) for row in results] + return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] @overload def select_one( @@ -121,25 +201,28 @@ def select_one( def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["DuckDBConnection"] = None, + connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Union[ModelDTOT, dict[str, Any]]": + ) -> "Union[dict[str, Any], ModelDTOT]": + """Fetch one row from the database. + + Returns: + The first row of the query results. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - result = self.check_not_found(result) # pyright: ignore - - column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType] - # Always return dictionaries - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + cursor.execute(sql, [] if parameters is None else parameters) + result = cursor.fetchone() + result = self.check_not_found(result) + column_names = [column[0] for column in cursor.description or []] + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload def select_one_or_none( @@ -169,22 +252,26 @@ def select_one_or_none( parameters: Optional["StatementParameterType"] = None, /, *, - connection: Optional["DuckDBConnection"] = None, + connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": + """Fetch one row from the database. + + Returns: + The first row of the query results, or None if no results. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] + cursor.execute(sql, [] if parameters is None else parameters) + result = cursor.fetchone() if result is None: return None - - column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType] - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + column_names = [column[0] for column in cursor.description or []] + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload def select_value( @@ -218,15 +305,21 @@ def select_value( schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": + """Fetch a single value from the database. + + Returns: + The first value from the first row of results. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - result = self.check_not_found(result) # pyright: ignore + cursor.execute(sql, [] if parameters is None else parameters) + result = cursor.fetchone() + result = self.check_not_found(result) + result_value = result[0] if schema_type is None: - return result[0] # pyright: ignore - return schema_type(result[0]) # type: ignore[call-arg] + return result_value + return cast("T", schema_type(result_value)) # type: ignore[call-arg] @overload def select_value_or_none( @@ -263,28 +356,29 @@ def select_value_or_none( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] + cursor.execute(sql, [] if parameters is None else parameters) + result = cursor.fetchone() if result is None: return None if schema_type is None: - return result[0] # pyright: ignore + return result[0] return schema_type(result[0]) # type: ignore[call-arg] def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["DuckDBConnection"] = None, + connection: "Optional[DuckDBConnection]" = None, **kwargs: Any, ) -> int: connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - return getattr(cursor, "rowcount", -1) # pyright: ignore[reportUnknownMemberType] + params = [] if parameters is None else parameters + cursor.execute(sql, params) + return getattr(cursor, "rowcount", -1) @overload def insert_update_delete_returning( @@ -321,14 +415,14 @@ def insert_update_delete_returning( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - result = self.check_not_found(result) # pyright: ignore - column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] + params = [] if parameters is None else parameters + cursor.execute(sql, params) + result = cursor.fetchall() + result = self.check_not_found(result) + column_names = [col[0] for col in cursor.description or []] if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result[0])))) # pyright: ignore[reportUnknownArgumentType] - # Always return dictionaries - return dict(zip(column_names, result[0])) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result[0])))) + return dict(zip(column_names, result[0])) def execute_script( self, @@ -342,8 +436,9 @@ def execute_script( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - return cast("str", getattr(cursor, "statusmessage", "DONE")) # pyright: ignore[reportUnknownMemberType] + params = [] if parameters is None else parameters + cursor.execute(sql, params) + return cast("str", getattr(cursor, "statusmessage", "DONE")) # --- Arrow Bulk Operations --- @@ -359,5 +454,17 @@ def select_arrow( # pyright: ignore[reportUnknownParameterType] connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - return cast("ArrowTable", cursor.fetch_arrow_table()) # pyright: ignore[reportUnknownMemberType] + params = [] if parameters is None else parameters + cursor.execute(sql, params) + return cast("ArrowTable", cursor.fetch_arrow_table()) + + def _connection(self, connection: "Optional[DuckDBConnection]" = None) -> "DuckDBConnection": + """Get the connection to use for the operation. + + Args: + connection: Optional connection to use. + + Returns: + The connection to use. + """ + return connection or self.connection diff --git a/sqlspec/adapters/oracledb/driver.py b/sqlspec/adapters/oracledb/driver.py index 52c2e2a..7228824 100644 --- a/sqlspec/adapters/oracledb/driver.py +++ b/sqlspec/adapters/oracledb/driver.py @@ -1,11 +1,16 @@ +import logging +import re from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload from oracledb import AsyncConnection, AsyncCursor, Connection, Cursor from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import AsyncArrowBulkOperationsMixin, SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.statement import PARAM_REGEX from sqlspec.typing import ArrowTable, StatementParameterType, T +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence @@ -17,8 +22,122 @@ OracleSyncConnection = Connection OracleAsyncConnection = AsyncConnection +logger = logging.getLogger("sqlspec") + +# Regex to find '?' placeholders, skipping those inside quotes or SQL comments +QMARK_REGEX = re.compile( + r"""(?P"[^"]*") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) + + +class OracleDriverBase: + """Base class for Oracle drivers with common functionality.""" + + dialect: str = "oracle" + + def _process_sql_params( # noqa: PLR6301 + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + **kwargs: Any, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + """Process SQL and parameters for Oracle. + + Oracle natively supports both named (:name) and positional parameters. + This method merges parameters and validates them. + + Raises: + ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. + SQLParsingError: If parameter count mismatch is detected. + + Returns: + A tuple of (sql, parameters) ready for execution. + """ + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for Oracle driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="oracle") + return final_sql, final_params + + # Case 2: Sequence parameters - check count and pass through + if isinstance(merged_params, (list, tuple)): + # Count ? placeholders + qmark_count = 0 + for match in QMARK_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "qmark" + ): + qmark_count += 1 + + # Validate + actual_count = len(merged_params) + if qmark_count > 0 and qmark_count != actual_count: + msg = f"oracle: Parameter count mismatch. SQL expects {qmark_count} positional parameters ('?'), but {actual_count} were provided. SQL: {sql}" + raise SQLParsingError(msg) + + return sql, merged_params + + # Case 3: Scalar parameter - wrap in tuple + # Special handling for scalar values with ? placeholder + if merged_params is not None: + qmark_count = 0 + for match in QMARK_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "qmark" + ): + qmark_count += 1 + + if qmark_count > 1: + msg = f"oracle: Parameter count mismatch. SQL expects {qmark_count} positional parameters ('?'), but 1 scalar was provided. SQL: {sql}" + raise SQLParsingError(msg) + + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in QMARK_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "qmark" + ): + has_placeholders = True + break + + if has_placeholders: + msg = f"oracle: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + class OracleSyncDriver( + OracleDriverBase, SyncArrowBulkOperationsMixin["OracleSyncConnection"], SQLTranslatorMixin["OracleSyncConnection"], SyncDriverAdapterProtocol["OracleSyncConnection"], @@ -26,7 +145,6 @@ class OracleSyncDriver( """Oracle Sync Driver Adapter.""" connection: "OracleSyncConnection" - dialect: str = "oracle" def __init__(self, connection: "OracleSyncConnection") -> None: self.connection = connection @@ -434,6 +552,7 @@ def select_arrow( # pyright: ignore[reportUnknownParameterType] class OracleAsyncDriver( + OracleDriverBase, AsyncArrowBulkOperationsMixin["OracleAsyncConnection"], SQLTranslatorMixin["OracleAsyncConnection"], AsyncDriverAdapterProtocol["OracleAsyncConnection"], @@ -441,7 +560,6 @@ class OracleAsyncDriver( """Oracle Async Driver Adapter.""" connection: "OracleAsyncConnection" - dialect: str = "oracle" def __init__(self, connection: "OracleAsyncConnection") -> None: self.connection = connection diff --git a/sqlspec/adapters/psqlpy/driver.py b/sqlspec/adapters/psqlpy/driver.py index c38dcad..d124a93 100644 --- a/sqlspec/adapters/psqlpy/driver.py +++ b/sqlspec/adapters/psqlpy/driver.py @@ -1,4 +1,4 @@ -# ruff: noqa: PLR0915, PLR0914, PLR0912, C901 +# ruff: noqa: PLR0915, PLR0912, C901 """Psqlpy Driver Implementation.""" import logging @@ -9,9 +9,10 @@ from psqlpy.exceptions import RustPSQLDriverPyBaseError from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.exceptions import SQLParsingError +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, SQLStatement +from sqlspec.statement import PARAM_REGEX +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import Sequence @@ -59,81 +60,86 @@ def _process_sql_params( psqlpy uses $1, $2 style parameters natively. This method converts '?' (tuple/list) and ':name' (dict) styles to $n. - It relies on SQLStatement for initial parameter validation and merging. - - Args: - sql: The SQL to process. - parameters: The parameters to process. - kwargs: Additional keyword arguments. - - Raises: - SQLParsingError: If the SQL is invalid. - - Returns: - A tuple of the processed SQL and parameters. """ - stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None) - sql, parameters = stmt.process() - - # Case 1: Parameters are a dictionary - if isinstance(parameters, dict): - processed_sql_parts: list[str] = [] - ordered_params = [] - last_end = 0 - param_index = 1 - found_params_regex: list[str] = [] - + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for psqlpy driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, _ = bind_parameters(sql, merged_params, dialect="postgres") + # psqlpy expects positional parameters, so convert dict to tuple in order of appearance + # We'll use regex to find order for now + param_names = [] for match in PARAM_REGEX.finditer(sql): if match.group("dquote") or match.group("squote") or match.group("comment"): continue + if match.group("var_name"): + param_names.append(match.group("var_name")) + ordered_params = tuple(merged_params[name] for name in param_names) + # Replace :name with $1, $2, ... + for idx, name in enumerate(param_names, 1): + final_sql = final_sql.replace(f":{name}", f"${idx}") + return final_sql, ordered_params + + # Case b: Sequence or scalar parameters (? style) + if isinstance(merged_params, (list, tuple)): + sequence_processed_parts: list[str] = [] + param_index = 1 + last_end = 0 + qmark_count = 0 - if match.group("var_name"): # Finds :var_name - var_name = match.group("var_name") - found_params_regex.append(var_name) - start = match.start("var_name") - 1 - end = match.end("var_name") - - if var_name not in parameters: - msg = f"Named parameter ':{var_name}' missing from parameters. SQL: {sql}" - raise SQLParsingError(msg) + for match in QMARK_REGEX.finditer(sql): + if match.group("dquote") or match.group("squote") or match.group("comment"): + continue - processed_sql_parts.extend((sql[last_end:start], f"${param_index}")) - ordered_params.append(parameters[var_name]) + if match.group("qmark"): + qmark_count += 1 + start = match.start("qmark") + end = match.end("qmark") + sequence_processed_parts.extend((sql[last_end:start], f"${param_index}")) last_end = end param_index += 1 - processed_sql_parts.append(sql[last_end:]) - final_sql = "".join(processed_sql_parts) - - if not found_params_regex and parameters: - logger.warning( - "Dict params provided (%s), but no :name placeholders found. SQL: %s", - list(parameters.keys()), - sql, - ) - return sql, () + sequence_processed_parts.append(sql[last_end:]) + final_sql = "".join(sequence_processed_parts) - provided_keys = set(parameters.keys()) - found_keys = set(found_params_regex) - unused_keys = provided_keys - found_keys - if unused_keys: - logger.warning("Unused parameters provided: %s. SQL: %s", unused_keys, sql) + # Validation + if not qmark_count and merged_params: + msg = f"psqlpy: Sequence parameters provided, but no '?' placeholders found in SQL: {sql}" + raise ParameterStyleMismatchError(msg) - return final_sql, tuple(ordered_params) + actual_count = len(merged_params) + if qmark_count != actual_count: + msg = f"psqlpy: Parameter count mismatch. SQL expects {qmark_count} positional parameters ('?'), but {actual_count} were provided. SQL: {sql}" + raise SQLParsingError(msg) - # Case 2: Parameters are a sequence/scalar - if isinstance(parameters, (list, tuple)): + return final_sql, merged_params + # Case c: Scalar + # Convert to a one-element tuple + if merged_params is not None: + scalar_param_tuple = (merged_params,) sequence_processed_parts: list[str] = [] param_index = 1 last_end = 0 - qmark_found = False + qmark_count = 0 for match in QMARK_REGEX.finditer(sql): if match.group("dquote") or match.group("squote") or match.group("comment"): continue if match.group("qmark"): - qmark_found = True + qmark_count += 1 start = match.start("qmark") end = match.end("qmark") sequence_processed_parts.extend((sql[last_end:start], f"${param_index}")) @@ -143,34 +149,34 @@ def _process_sql_params( sequence_processed_parts.append(sql[last_end:]) final_sql = "".join(sequence_processed_parts) - if parameters and not qmark_found: - logger.warning("Sequence parameters provided, but no '?' placeholders found. SQL: %s", sql) - return sql, parameters - - expected_params = param_index - 1 - actual_params = len(parameters) - if expected_params != actual_params: - msg = f"Parameter count mismatch: Expected {expected_params}, got {actual_params}. SQL: {final_sql}" + # Validation - for scalar, we expect exactly one placeholder + if qmark_count != 1: + msg = f"psqlpy: Parameter count mismatch. SQL expects 1 positional parameter ('?') for scalar input, but found {qmark_count}. SQL: {sql}" raise SQLParsingError(msg) - return final_sql, parameters - - # Case 3: Parameters are None - if PARAM_REGEX.search(sql) or QMARK_REGEX.search(sql): - # Perform a simpler check if any placeholders might exist if no params are given - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - msg = f"SQL contains named parameters (:name) but no parameters provided. SQL: {sql}" - raise SQLParsingError(msg) + return final_sql, scalar_param_tuple + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders for match in QMARK_REGEX.finditer(sql): if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( "qmark" ): - msg = f"SQL contains positional parameters (?) but no parameters provided. SQL: {sql}" - raise SQLParsingError(msg) + has_placeholders = True + break + if has_placeholders: + msg = f"psqlpy: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) return sql, () # --- Public API Methods --- # diff --git a/sqlspec/adapters/psycopg/driver.py b/sqlspec/adapters/psycopg/driver.py index ab77604..5dcde1d 100644 --- a/sqlspec/adapters/psycopg/driver.py +++ b/sqlspec/adapters/psycopg/driver.py @@ -1,4 +1,5 @@ import logging +import re from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload @@ -6,9 +7,10 @@ from psycopg.rows import dict_row from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol -from sqlspec.exceptions import SQLParsingError +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, SQLStatement +from sqlspec.statement import PARAM_REGEX +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence @@ -22,6 +24,16 @@ PsycopgSyncConnection = Connection PsycopgAsyncConnection = AsyncConnection +# Regex to find '?' placeholders, skipping those inside quotes or SQL comments +QMARK_REGEX = re.compile( + r"""(?P"[^"]*") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) + class PsycopgDriverBase: dialect: str @@ -34,49 +46,54 @@ def _process_sql_params( **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters, converting :name -> %(name)s if needed.""" - stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None) - processed_sql, processed_params = stmt.process() - - if isinstance(processed_params, dict): - parameter_dict = processed_params - processed_sql_parts: list[str] = [] - last_end = 0 - found_params_regex: list[str] = [] - - for match in PARAM_REGEX.finditer(processed_sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("var_name"): - var_name = match.group("var_name") - found_params_regex.append(var_name) - start = match.start("var_name") - 1 - end = match.end("var_name") - - if var_name not in parameter_dict: - msg = ( - f"Named parameter ':{var_name}' found in SQL but missing from processed parameters. " - f"Processed SQL: {processed_sql}" - ) - raise SQLParsingError(msg) - - processed_sql_parts.extend((processed_sql[last_end:start], f"%({var_name})s")) - last_end = end - - processed_sql_parts.append(processed_sql[last_end:]) - final_sql = "".join(processed_sql_parts) - - if not found_params_regex and parameter_dict: - logger.warning( - "Dict params provided (%s), but no :name placeholders found. SQL: %s", - list(parameter_dict.keys()), - processed_sql, - ) - return processed_sql, parameter_dict - - return final_sql, parameter_dict - - return processed_sql, processed_params + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = f"Cannot mix positional parameters with keyword arguments for {self.dialect} driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="postgres") + return final_sql, final_params + + # Case 2: Sequence parameters - leave as is (psycopg handles '%s' placeholders with tuple/list) + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in QMARK_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "qmark" + ): + has_placeholders = True + break + + if has_placeholders: + msg = f"psycopg: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None class PsycopgSyncDriver( @@ -92,57 +109,6 @@ class PsycopgSyncDriver( def __init__(self, connection: "PsycopgSyncConnection") -> None: self.connection = connection - def _process_sql_params( - self, - sql: str, - parameters: "Optional[StatementParameterType]" = None, - /, - **kwargs: Any, - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None) - processed_sql, processed_params = stmt.process() - - if isinstance(processed_params, dict): - parameter_dict = processed_params - processed_sql_parts: list[str] = [] - last_end = 0 - found_params_regex: list[str] = [] - - for match in PARAM_REGEX.finditer(processed_sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("var_name"): - var_name = match.group("var_name") - found_params_regex.append(var_name) - start = match.start("var_name") - 1 - end = match.end("var_name") - - if var_name not in parameter_dict: - msg = ( - f"Named parameter ':{var_name}' found in SQL but missing from processed parameters. " - f"Processed SQL: {processed_sql}" - ) - raise SQLParsingError(msg) - - processed_sql_parts.extend((processed_sql[last_end:start], f"%({var_name})s")) - last_end = end - - processed_sql_parts.append(processed_sql[last_end:]) - final_sql = "".join(processed_sql_parts) - - if not found_params_regex and parameter_dict: - logger.warning( - "Dict params provided (%s), but no :name placeholders found. SQL: %s", - list(parameter_dict.keys()), - processed_sql, - ) - return processed_sql, parameter_dict - - return final_sql, parameter_dict - - return processed_sql, processed_params - @staticmethod @contextmanager def _with_cursor(connection: "PsycopgSyncConnection") -> "Generator[Any, None, None]": diff --git a/sqlspec/adapters/sqlite/driver.py b/sqlspec/adapters/sqlite/driver.py index 5f353ab..fbaaf86 100644 --- a/sqlspec/adapters/sqlite/driver.py +++ b/sqlspec/adapters/sqlite/driver.py @@ -1,10 +1,15 @@ +import logging +import re import sqlite3 from contextlib import contextmanager from sqlite3 import Cursor from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload from sqlspec.base import SyncDriverAdapterProtocol +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.statement import PARAM_REGEX +from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import Generator, Sequence @@ -13,8 +18,20 @@ __all__ = ("SqliteConnection", "SqliteDriver") +logger = logging.getLogger("sqlspec") + SqliteConnection = sqlite3.Connection +# Regex to find '?' placeholders, skipping those inside quotes or SQL comments +QMARK_REGEX = re.compile( + r"""(?P"[^"]*") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) + class SqliteDriver( SQLTranslatorMixin["SqliteConnection"], @@ -40,6 +57,67 @@ def _with_cursor(self, connection: "SqliteConnection") -> "Generator[Cursor, Non finally: cursor.close() + def _process_sql_params( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + **kwargs: Any, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + """Process SQL and parameters for SQLite. + + SQLite supports both named (:name) and positional (?) parameters. + This method merges parameters and validates them. + """ + # 1. Merge parameters and kwargs + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + + if kwargs: + if isinstance(parameters, dict): + merged_params = {**parameters, **kwargs} + elif parameters is not None: + msg = "Cannot mix positional parameters with keyword arguments for SQLite driver." + raise ParameterStyleMismatchError(msg) + else: + merged_params = kwargs + elif parameters is not None: + merged_params = parameters # type: ignore + + # Use bind_parameters for named parameters + if isinstance(merged_params, dict): + final_sql, final_params = bind_parameters(sql, merged_params, dialect="sqlite") + return final_sql, final_params + + # Case 2: Sequence parameters - pass through + if isinstance(merged_params, (list, tuple)): + return sql, merged_params + # Case 3: Scalar parameter - wrap in tuple + if merged_params is not None: + return sql, (merged_params,) + + # Case 0: No parameters provided + # Basic validation for placeholders + has_placeholders = False + for match in PARAM_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "var_name" + ): + has_placeholders = True + break + if not has_placeholders: + # Check for ? style placeholders + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|('(?:[^']|'')*')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + ): + if match.group(5): + has_placeholders = True + break + + if has_placeholders: + msg = f"sqlite: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + # --- Public API Methods --- # @overload def select( @@ -72,7 +150,7 @@ def select( connection: Optional["SqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": """Fetch data from the database. Returns: @@ -80,18 +158,20 @@ def select( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - results = cursor.fetchall() - if not results: - return [] - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is not None: - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore[reportUnknownArgumentType] - return [dict(zip(column_names, row)) for row in results] # pyright: ignore[reportUnknownArgumentType] + + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + results = cursor.fetchall() + if not results: + return [] + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return [dict(zip(column_names, row)) for row in results] + return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] @overload def select_one( @@ -124,7 +204,7 @@ def select_one( connection: Optional["SqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Union[ModelDTOT, dict[str, Any]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Fetch one row from the database. Returns: @@ -132,17 +212,19 @@ def select_one( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - result = cursor.fetchone() - result = self.check_not_found(result) - column_names = [c[0] for c in cursor.description or []] - if schema_type is None: - return dict(zip(column_names, result)) - return schema_type(**dict(zip(column_names, result))) # type: ignore[return-value] + + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + result = self.check_not_found(result) + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload def select_one_or_none( @@ -175,26 +257,28 @@ def select_one_or_none( connection: Optional["SqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": + ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": """Fetch one row from the database. Returns: - The first row of the query results. + The first row of the query results, or None if no results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - result = cursor.fetchone() - if result is None: - return None - column_names = [c[0] for c in cursor.description or []] - if schema_type is None: - return dict(zip(column_names, result)) - return schema_type(**dict(zip(column_names, result))) # type: ignore[return-value] + + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + if result is None: + return None + + # Get column names + column_names = [column[0] for column in cursor.description] + + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload def select_value( @@ -221,30 +305,32 @@ def select_value( def select_value( self, sql: str, - parameters: "Optional[StatementParameterType]" = None, + parameters: Optional["StatementParameterType"] = None, /, *, - connection: "Optional[SqliteConnection]" = None, + connection: Optional["SqliteConnection"] = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": """Fetch a single value from the database. Returns: - The first value from the first row of results, or None if no results. + The first value from the first row of results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - result = cursor.fetchone() - result = self.check_not_found(result) - if schema_type is None: - return result[0] - return schema_type(result[0]) # type: ignore[call-arg] + + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + result = self.check_not_found(result) + + # Return first value from the row + result_value = result[0] + if schema_type is None: + return result_value + return cast("T", schema_type(result_value)) # type: ignore[call-arg] @overload def select_value_or_none( @@ -271,10 +357,10 @@ def select_value_or_none( def select_value_or_none( self, sql: str, - parameters: "Optional[StatementParameterType]" = None, + parameters: Optional["StatementParameterType"] = None, /, *, - connection: "Optional[SqliteConnection]" = None, + connection: Optional["SqliteConnection"] = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": @@ -285,17 +371,19 @@ def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - result = cursor.fetchone() - if result is None: - return None - if schema_type is None: - return result[0] - return schema_type(result[0]) # type: ignore[call-arg] + + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + if result is None: + return None + + # Return first value from the row + result_value = result[0] + if schema_type is None: + return result_value + return cast("T", schema_type(result_value)) # type: ignore[call-arg] def insert_update_delete( self, @@ -314,12 +402,11 @@ def insert_update_delete( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - return cursor.rowcount if hasattr(cursor, "rowcount") else -1 + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + connection.commit() + return cursor.rowcount @overload def insert_update_delete_returning( @@ -352,7 +439,7 @@ def insert_update_delete_returning( connection: Optional["SqliteConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": + ) -> "Union[dict[str, Any], ModelDTOT]": """Insert, update, or delete data from the database and return result. Returns: @@ -361,31 +448,19 @@ def insert_update_delete_returning( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) - result = cursor.fetchall() - if len(result) == 0: - return None - - # Get column names from cursor description - column_names = [c[0] for c in cursor.description or []] - - # Get the first row's values - ensure we're getting the actual values - row_values = result[0] + # Execute the query + cursor = connection.cursor() + cursor.execute(sql, parameters or []) + connection.commit() + result = cursor.fetchone() + result = self.check_not_found(result) - # Debug print to see what we're getting + # Get column names + column_names = [column[0] for column in cursor.description] - # Create dictionary mapping column names to values - result_dict = {} - for i, col_name in enumerate(column_names): - result_dict[col_name] = row_values[i] - - if schema_type is not None: - return cast("ModelDTOT", schema_type(**result_dict)) - return result_dict + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) def execute_script( self, @@ -404,11 +479,19 @@ def execute_script( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # The _process_sql_params handles parameter formatting for the dialect. - with self._with_cursor(connection) as cursor: - if not parameters: - cursor.execute(sql) # pyright: ignore[reportUnknownMemberType] - else: - cursor.execute(sql, parameters) + # Execute the script + cursor = connection.cursor() + cursor.executescript(sql) + connection.commit() + return "Script executed successfully." + + def _connection(self, connection: Optional["SqliteConnection"] = None) -> "SqliteConnection": + """Get the connection to use for the operation. - return cast("str", cursor.statusmessage) if hasattr(cursor, "statusmessage") else "DONE" # pyright: ignore[reportUnknownMemberType,reportAttributeAccessIssue] + Args: + connection: Optional connection to use. + + Returns: + The connection to use. + """ + return connection or self.connection diff --git a/sqlspec/base.py b/sqlspec/base.py index 44a1d1a..2e88904 100644 --- a/sqlspec/base.py +++ b/sqlspec/base.py @@ -546,7 +546,7 @@ def _process_sql_params( A tuple containing the processed SQL query and parameters. """ # Instantiate SQLStatement with parameters and kwargs for internal merging - stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None) + stmt = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs or None) # Process uses the merged parameters internally return stmt.process() diff --git a/sqlspec/extensions/litestar/handlers.py b/sqlspec/extensions/litestar/handlers.py index b23df4f..df9a67a 100644 --- a/sqlspec/extensions/litestar/handlers.py +++ b/sqlspec/extensions/litestar/handlers.py @@ -46,8 +46,7 @@ async def handler(message: "Message", scope: "Scope") -> None: """ connection = get_sqlspec_scope_state(scope, connection_scope_key) if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: - with contextlib.suppress(Exception): - await ensure_async_(connection.close)() + await ensure_async_(connection.close)() delete_sqlspec_scope_state(scope, connection_scope_key) return handler @@ -103,8 +102,7 @@ async def handler(message: "Message", scope: "Scope") -> None: await ensure_async_(connection.rollback)() finally: if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: - with contextlib.suppress(Exception): - await ensure_async_(connection.close)() + await ensure_async_(connection.close)() delete_sqlspec_scope_state(scope, connection_scope_key) return handler diff --git a/sqlspec/statement.py b/sqlspec/statement.py index a02896d..bb7b611 100644 --- a/sqlspec/statement.py +++ b/sqlspec/statement.py @@ -2,7 +2,6 @@ import logging import re from dataclasses import dataclass -from functools import cached_property from typing import ( Any, Optional, @@ -42,8 +41,6 @@ class SQLStatement: a clean interface for parameter binding and SQL statement formatting. """ - dialect: str - """The SQL dialect to use for parsing (e.g., 'postgres', 'mysql'). Defaults to 'postgres' if None.""" sql: str """The raw SQL statement.""" parameters: Optional[StatementParameterType] = None @@ -73,45 +70,54 @@ def __post_init__(self) -> None: def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process the SQL statement and merged parameters for execution. + This method validates the parameters against the SQL statement using sqlglot + parsing but returns the *original* SQL string and the merged parameters. + The actual formatting of SQL placeholders and parameter structures for the + DBAPI driver is delegated to the specific adapter. + Returns: - A tuple containing the processed SQL string and the processed parameters - ready for database driver execution. + A tuple containing the *original* SQL string and the merged/validated + parameters (dict, tuple, list, or None). Raises: - SQLParsingError: If the SQL statement contains parameter placeholders, but no parameters were provided. - - Returns: - A tuple containing the processed SQL string and the processed parameters - ready for database driver execution. + SQLParsingError: If the SQL statement contains parameter placeholders + but no parameters were provided, or if parsing fails unexpectedly. """ + # Parse the SQL to find expected parameters + try: + expression = self._parse_sql() + # Find all parameter expressions (:name, ?, etc.) + sql_params = list(expression.find_all(exp.Parameter)) + except SQLParsingError as e: + # If parsing fails, we cannot validate accurately. + # Let adapters handle potentially valid but unparseable SQL. + # Log the parsing error for debugging. + logger.debug( + "SQL parsing failed during validation: %s. Returning original SQL and parameters for adapter.", e + ) + # Return original SQL and parameters for the adapter to attempt processing + # (Adapters might use regex or other means if parsing fails) + return self.sql, self._merged_parameters + if self._merged_parameters is None: - # Validate that the SQL doesn't expect parameters if none were provided - # Parse ONLY if we need to validate - try: # Add try/except in case parsing fails even here - expression = self._parse_sql() - except SQLParsingError: - # If parsing fails, we can't validate, but maybe that's okay if no params were passed? - # Log a warning? For now, let the original error propagate if needed. - # Or, maybe assume it's okay if _merged_parameters is None? - # Let's re-raise for now, as unparsable SQL is usually bad. - logger.warning("SQL statement is unparsable: %s", self.sql) - return self.sql, None - if list(expression.find_all(exp.Parameter)): - msg = "SQL statement contains parameter placeholders, but no parameters were provided." + # If no parameters were provided, but the parsed SQL expects them, raise an error. + if sql_params: + placeholder_types = {"named" if p.name else "positional" for p in sql_params} + msg = f"SQL statement contains {', '.join(placeholder_types)} parameter placeholders, but no parameters were provided. SQL: {self.sql}" raise SQLParsingError(msg) + # No parameters provided and none found in SQL - OK return self.sql, None + # Validate provided parameters against parsed SQL parameters if isinstance(self._merged_parameters, dict): - # Pass only the dict, parsing happens inside - return self._process_dict_params(self._merged_parameters) + self._validate_dict_params(sql_params, self._merged_parameters) + elif isinstance(self._merged_parameters, (tuple, list)): + self._validate_sequence_params(sql_params, self._merged_parameters) + else: # Scalar parameter + self._validate_scalar_param(sql_params, self._merged_parameters) - if isinstance(self._merged_parameters, (tuple, list)): - # Pass only the sequence, parsing happens inside if needed for validation - return self._process_sequence_params(self._merged_parameters) - - # Assume it's a single scalar value otherwise - # Pass only the value, parsing happens inside for validation - return self._process_scalar_param(self._merged_parameters) + # Return the original SQL and the merged parameters for the adapter to process + return self.sql, self._merged_parameters def _parse_sql(self) -> exp.Expression: """Parse the SQL using sqlglot. @@ -122,252 +128,98 @@ def _parse_sql(self) -> exp.Expression: Returns: The parsed SQL expression. """ - parse_dialect = self.dialect or "postgres" + # Use a generic dialect or try autodetection if specific dialect knowledge is removed. + # For validation purposes, 'postgres' is often a good lenient default. + # Alternatively, let the caller (adapter) provide the dialect if needed for parsing hints. + # For now, let's keep it simple and assume a generic parse works for validation. try: - read_dialect = parse_dialect or None - return sqlglot.parse_one(self.sql, read=read_dialect) + # Removed read=self.dialect as self.dialect is removed. + # parse_one without 'read' uses the standard dialect by default. + return sqlglot.parse_one(self.sql) except Exception as e: - # Ensure the original sqlglot error message is included error_detail = str(e) - msg = f"Failed to parse SQL with dialect '{parse_dialect or 'auto-detected'}': {error_detail}\nSQL: {self.sql}" + # Removed dialect from error message + msg = f"Failed to parse SQL for validation: {error_detail}\nSQL: {self.sql}" raise SQLParsingError(msg) from e - def _process_dict_params( - self, - parameter_dict: dict[str, Any], - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Processes dictionary parameters based on dialect capabilities. - - Raises: - ParameterStyleMismatchError: If the SQL statement contains unnamed placeholders (e.g., '?') in the SQL query. - SQLParsingError: If the SQL statement contains named parameters, but no parameters were provided. - - Returns: - A tuple containing the processed SQL string and the processed parameters - ready for database driver execution. - """ - # Attempt to parse with sqlglot first (for other dialects like postgres, mysql) - named_sql_params: Optional[list[exp.Parameter]] = None - unnamed_sql_params: Optional[list[exp.Parameter]] = None - sqlglot_parsed_ok = False - # --- Dialect-Specific Bypasses for Native Handling --- - if self.dialect == "sqlite": # Handles :name natively - return self.sql, parameter_dict - - # Add bypass for postgres handled by specific adapters (e.g., asyncpg) - if self.dialect == "postgres": - # The adapter (e.g., asyncpg) will handle :name -> $n conversion. - # SQLStatement just validates parameters against the original SQL here. - # Perform validation using regex if sqlglot parsing fails, otherwise use sqlglot. - try: - expression = self._parse_sql() - sql_params = list(expression.find_all(exp.Parameter)) - named_sql_params = [p for p in sql_params if p.name] - unnamed_sql_params = [p for p in sql_params if not p.name] - - if unnamed_sql_params: - msg = "Cannot use dictionary parameters with unnamed placeholders (e.g., '?') found by sqlglot for postgres." - raise ParameterStyleMismatchError(msg) - - # Validate keys using sqlglot results - required_keys = {p.name for p in named_sql_params} - provided_keys = set(parameter_dict.keys()) - missing_keys = required_keys - provided_keys - if missing_keys: - msg = ( - f"Named parameters found in SQL (via sqlglot) but not provided: {missing_keys}. SQL: {self.sql}" - ) - raise SQLParsingError(msg) # noqa: TRY301 - # Allow extra keys - - except SQLParsingError as e: - logger.debug("SQLglot parsing failed for postgres dict params, attempting regex validation: %s", e) - # Regex validation fallback (without conversion) - postgres_found_params_regex: list[str] = [] - for match in PARAM_REGEX.finditer(self.sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - if match.group("var_name"): - var_name = match.group("var_name") - postgres_found_params_regex.append(var_name) - if var_name not in parameter_dict: - msg = f"Named parameter ':{var_name}' found in SQL (via regex) but not provided. SQL: {self.sql}" - raise SQLParsingError(msg) # noqa: B904 - - if not postgres_found_params_regex and parameter_dict: - msg = f"Dictionary parameters provided, but no named placeholders (:name) found via regex. SQL: {self.sql}" - raise ParameterStyleMismatchError(msg) # noqa: B904 - # Allow extra keys with regex check too - - # Return the *original* SQL and the processed dict for the adapter to handle - return self.sql, parameter_dict - - if self.dialect == "duckdb": # Handles $name natively (and :name via driver? Check driver docs) - # Bypass sqlglot/regex checks. Trust user SQL ($name or ?) + dict for DuckDB driver. - # We lose :name -> $name conversion *if* sqlglot parsing fails, but avoid errors on valid $name SQL. - return self.sql, parameter_dict - # --- End Bypasses --- - - try: - expression = self._parse_sql() - sql_params = list(expression.find_all(exp.Parameter)) - named_sql_params = [p for p in sql_params if p.name] - unnamed_sql_params = [p for p in sql_params if not p.name] - sqlglot_parsed_ok = True - logger.debug("SQLglot parsed dict params successfully for: %s", self.sql) - except SQLParsingError as e: - logger.debug("SQLglot parsing failed for dict params, attempting regex fallback: %s", e) - # Proceed using regex fallback below + def _validate_dict_params(self, sql_params: list[exp.Parameter], parameter_dict: dict[str, Any]) -> None: + """Validates dictionary parameters against parsed SQL parameters.""" + named_sql_params = [p for p in sql_params if p.name] + unnamed_sql_params = [p for p in sql_params if not p.name] - # Check for unnamed placeholders if parsing worked - if sqlglot_parsed_ok and unnamed_sql_params: - msg = "Cannot use dictionary parameters with unnamed placeholders (e.g., '?') found by sqlglot." + if unnamed_sql_params: + msg = f"Dictionary parameters provided, but found unnamed placeholders (e.g., '?') in SQL: {self.sql}" raise ParameterStyleMismatchError(msg) - # Determine if we need to use regex fallback - # Use fallback if: parsing failed OR (parsing worked BUT found no named params when a dict was provided) - use_regex_fallback = not sqlglot_parsed_ok or (not named_sql_params and parameter_dict) - - if use_regex_fallback: - # Regex fallback logic for :name -> self.param_style conversion - # ... (regex fallback code as implemented previously) ... - logger.debug("Using regex fallback for dict param processing: %s", self.sql) - # --- Regex Fallback Logic --- - regex_processed_sql_parts: list[str] = [] - ordered_params = [] - last_end = 0 - regex_found_params: list[str] = [] - - for match in PARAM_REGEX.finditer(self.sql): - # Skip matches that are comments or quoted strings - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("var_name"): - var_name = match.group("var_name") - regex_found_params.append(var_name) - # Get start and end from the match object for the :var_name part - # The var_name group itself doesn't include the leading :, so adjust start. - start = match.start("var_name") - 1 - end = match.end("var_name") - - if var_name not in parameter_dict: - msg = ( - f"Named parameter ':{var_name}' found in SQL (via regex) but not provided. SQL: {self.sql}" - ) - raise SQLParsingError(msg) - - regex_processed_sql_parts.extend((self.sql[last_end:start], self.param_style)) # Use target style - ordered_params.append(parameter_dict[var_name]) - last_end = end - - regex_processed_sql_parts.append(self.sql[last_end:]) - - # Validation with regex results - if not regex_found_params and parameter_dict: - msg = f"Dictionary parameters provided, but no named placeholders (e.g., :name) found via regex in the SQL query for dialect '{self.dialect}'. SQL: {self.sql}" + if not named_sql_params and parameter_dict: + # Check with regex as a fallback confirmation if sqlglot finds no named params + regex_found = any( + match.group("var_name") + for match in PARAM_REGEX.finditer(self.sql) + if not (match.group("dquote") or match.group("squote") or match.group("comment")) + ) + if not regex_found: + msg = f"Dictionary parameters provided, but no named placeholders (e.g., ':name') found in SQL: {self.sql}" raise ParameterStyleMismatchError(msg) + # SQLglot didn't find named params but regex did - log warning, proceed. + logger.warning( + "SQLglot found no named parameters, but regex did. Proceeding with validation. SQL: %s", self.sql + ) - provided_keys = set(parameter_dict.keys()) - missing_keys = set(regex_found_params) - provided_keys # Should be caught above, but double check - if missing_keys: - msg = f"Named parameters found in SQL (via regex) but not provided: {missing_keys}. SQL: {self.sql}" - raise SQLParsingError(msg) - - extra_keys = provided_keys - set(regex_found_params) - if extra_keys: - # Allow extra keys - pass - - return "".join(regex_processed_sql_parts), tuple(ordered_params) - - # Sqlglot Logic (if parsing worked and found params) - # ... (sqlglot logic as implemented previously, including :name -> %s conversion) ... - logger.debug("Using sqlglot results for dict param processing: %s", self.sql) - - # Ensure named_sql_params is iterable, default to empty list if None (shouldn't happen ideally) - active_named_params = named_sql_params or [] - - if not active_named_params and not parameter_dict: - # No SQL params found by sqlglot, no provided params dict -> OK - return self.sql, () - - # Validation with sqlglot results - required_keys = {p.name for p in active_named_params} # Use active_named_params + required_keys = {p.name for p in named_sql_params} provided_keys = set(parameter_dict.keys()) missing_keys = required_keys - provided_keys if missing_keys: - msg = f"Named parameters found in SQL (via sqlglot) but not provided: {missing_keys}. SQL: {self.sql}" + msg = f"Named parameters found in SQL but not provided: {missing_keys}. SQL: {self.sql}" raise SQLParsingError(msg) - extra_keys = provided_keys - required_keys - if extra_keys: - pass # Allow extra keys - - # Note: DuckDB handled by bypass above if sqlglot fails. - # This block handles successful sqlglot parse for other dialects. - # We don't need the specific DuckDB $name conversion here anymore, - # as the bypass handles the native $name case. - # The general logic converts :name -> self.param_style for dialects like postgres. - # if self.dialect == "duckdb": ... (Removed specific block here) - - # For other dialects requiring positional conversion (using sqlglot param info): - sqlglot_processed_parts: list[str] = [] - ordered_params = [] - last_end = 0 - for param in active_named_params: # Use active_named_params - start = param.this.this.start - end = param.this.this.end - sqlglot_processed_parts.extend((self.sql[last_end:start], self.param_style)) - ordered_params.append(parameter_dict[param.name]) - last_end = end - sqlglot_processed_parts.append(self.sql[last_end:]) - return "".join(sqlglot_processed_parts), tuple(ordered_params) - - def _process_sequence_params( - self, params: Union[tuple[Any, ...], list[Any]] - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Processes a sequence of parameters. - - Returns: - A tuple containing the processed SQL string and the processed parameters - ready for database driver execution. - """ - return self.sql, params - - def _process_scalar_param( - self, param_value: Any - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Processes a single scalar parameter value. - - Returns: - A tuple containing the processed SQL string and the processed parameters - ready for database driver execution. - """ - return self.sql, (param_value,) - - @cached_property - def param_style(self) -> str: - """Get the parameter style based on the dialect. - - Returns: - The parameter style placeholder for the dialect. - """ - dialect = self.dialect - - # Map dialects to parameter styles for placeholder replacement - # Note: Used when converting named params (:name) for dialects needing positional. - # Dialects supporting named params natively (SQLite, DuckDB) are handled via bypasses. - dialect_to_param_style = { - "postgres": "%s", - "mysql": "%s", - "oracle": ":1", - "mssql": "?", - "bigquery": "?", - "snowflake": "?", - "cockroach": "%s", - "db2": "?", - } - # Default to '?' for unknown/unhandled dialects or when dialect=None is forced - return dialect_to_param_style.get(dialect, "?") + # Allow extra keys, as they might be used by the adapter or driver internally + # extra_keys = provided_keys - required_keys + # if extra_keys: + # logger.debug("Extra parameters provided but not found in SQL: %s", extra_keys) + + def _validate_sequence_params( + self, sql_params: list[exp.Parameter], params: Union[tuple[Any, ...], list[Any]] + ) -> None: + """Validates sequence parameters against parsed SQL parameters.""" + named_sql_params = [p for p in sql_params if p.name] + unnamed_sql_params = [p for p in sql_params if not p.name] + + if named_sql_params: + # No need to store msg if we are raising immediately + raise ParameterStyleMismatchError( + f"Sequence parameters provided, but found named placeholders (e.g., ':name') in SQL: {self.sql}" + ) + + expected_count = len(unnamed_sql_params) + actual_count = len(params) + + if expected_count != actual_count: + # Double-check with regex if counts mismatch, as parsing might miss some complex cases + # Simple regex for '?' outside comments/strings needed here + regex_count = 0 + for match in re.finditer( + r"(\"(?:[^\"]|\"\")*\")|('(?:[^']|'')*')|(--.*?\\n)|(\\/\\*.*?\\*\\/)|(\\?)", self.sql, re.DOTALL + ): + if match.group(5): # Group 5 is the question mark + regex_count += 1 + + if regex_count != actual_count: + # No need to store msg if we are raising immediately + raise SQLParsingError( + f"Parameter count mismatch. SQL expects {expected_count} (sqlglot) / {regex_count} (regex) positional parameters, " + f"but {actual_count} were provided. SQL: {self.sql}" + ) + # Counts mismatch with sqlglot but match with simple regex - log warning, proceed. + logger.warning( + "Parameter count mismatch (sqlglot: %d, provided: %d), but regex count (%d) matches provided. Proceeding. SQL: %s", + expected_count, + actual_count, + regex_count, + self.sql, + ) + + def _validate_scalar_param(self, sql_params: list[exp.Parameter], param_value: Any) -> None: + """Validates a single scalar parameter against parsed SQL parameters.""" + self._validate_sequence_params(sql_params, (param_value,)) # Treat scalar as a single-element sequence diff --git a/sqlspec/utils/text.py b/sqlspec/utils/text.py index 4e11f6f..6995a08 100644 --- a/sqlspec/utils/text.py +++ b/sqlspec/utils/text.py @@ -1,14 +1,20 @@ """General utility functions.""" +import logging import re import unicodedata -from typing import Optional +from typing import Any, Optional, Union + +import sqlglot __all__ = ( + "bind_parameters", "check_email", "slugify", ) +logger = logging.getLogger("sqlspec") + def check_email(email: str) -> str: """Validate an email.""" @@ -43,3 +49,34 @@ def slugify(value: str, allow_unicode: bool = False, separator: "Optional[str]" if separator is not None: return re.sub(r"[-\s]+", "-", value).strip("-_").replace("-", separator) return re.sub(r"[-\s]+", "-", value).strip("-_") + + +def bind_parameters( + sql: str, + parameters: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None, + dialect: str = "generic", +) -> tuple[str, Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]]]: + """Bind parameters to SQL using SQLGlot with fallback to original SQL/params. + + Args: + sql: The SQL query string. + parameters: The parameters to bind (dict, list, tuple, or None). + dialect: The SQL dialect for parameter substitution. + + Returns: + A tuple of (possibly rewritten SQL, parameters for driver). + """ + if not parameters: + return sql, None + + try: + # For named parameters (dict) + if isinstance(parameters, dict): + bound_sql = sqlglot.transpile(sql, args=parameters, write=dialect)[0] + return bound_sql, parameters # Keep dict for drivers that need it + # For positional parameters (list/tuple), just return as is for now + # (could extend to support ? -> $1, $2, etc. if needed) + return sql, parameters + except Exception as e: + logger.debug(f"SQLGlot parameter binding failed: {e}. Using original SQL and parameters.") + return sql, parameters diff --git a/uv.lock b/uv.lock index 396c3bc..b5f0c20 100644 --- a/uv.lock +++ b/uv.lock @@ -1426,7 +1426,7 @@ wheels = [ [[package]] name = "litestar" -version = "2.15.2" +version = "2.16.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1444,9 +1444,9 @@ dependencies = [ { name = "rich-click" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b5/c9/d3a431379383cb479d7122017083b9858fe92c6d3333b9d278ed7d559865/litestar-2.15.2.tar.gz", hash = "sha256:de3320e7e412bf09f420b1703cbf04295f1a5377230dad0484d7da8c7ddf5a37", size = 397217, upload-time = "2025-04-06T12:31:43.146Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/4e/3376d5737a4c2e26fb2991a046265c38335b134d3e04e93c6d754e962e4e/litestar-2.16.0.tar.gz", hash = "sha256:f65c0d543bfec12b7433dff624322936f30bbdfb54ad3c5b7ef22ab2d092be2d", size = 399637, upload-time = "2025-05-04T11:00:46.654Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/db/4ddf71ddb51c70ef4f91bb5c59a84436cecfcfed0e5733f9b31b4b360dbc/litestar-2.15.2-py3-none-any.whl", hash = "sha256:41e7670d67bac70b466008a74eeb2aa63f4f71c09ffade4f603fc00d2bbc771f", size = 571057, upload-time = "2025-04-06T12:31:41.338Z" }, + { url = "https://files.pythonhosted.org/packages/9a/dc/4d1018577683918cd24a58228c90833f71f792aafcfffb44905c9062f737/litestar-2.16.0-py3-none-any.whl", hash = "sha256:8a48557198556f01d3d70da3859a471aa56595a4a344362d9529ed65804e3ee4", size = 573158, upload-time = "2025-05-04T11:00:44.558Z" }, ] [[package]] @@ -3101,11 +3101,11 @@ wheels = [ [[package]] name = "setuptools" -version = "80.3.0" +version = "80.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/6c/a3f892949418b5b9aced7396919c75ffb57e38f08b712b565f5eb10677ee/setuptools-80.3.0.tar.gz", hash = "sha256:ec8308eb180b2312062b1c5523204acf872cd8b0a9e6c2ae76431b22bc4065d7", size = 1314475, upload-time = "2025-05-03T09:17:32.334Z" } +sdist = { url = "https://files.pythonhosted.org/packages/70/dc/3976b322de9d2e87ed0007cf04cc7553969b6c7b3f48a565d0333748fbcd/setuptools-80.3.1.tar.gz", hash = "sha256:31e2c58dbb67c99c289f51c16d899afedae292b978f8051efaf6262d8212f927", size = 1315082, upload-time = "2025-05-04T18:47:04.397Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/61/a6239ff35d64e55def020335626894895847cc6659c0f8e1b676c58aad3b/setuptools-80.3.0-py3-none-any.whl", hash = "sha256:a65cffc4fb86167e3020b3ef58e08226baad8b29a3b34ce2c9d07e901bac481d", size = 1200273, upload-time = "2025-05-03T09:17:29.995Z" }, + { url = "https://files.pythonhosted.org/packages/53/7e/5d8af3317ddbf9519b687bd1c39d8737fde07d97f54df65553faca5cffb1/setuptools-80.3.1-py3-none-any.whl", hash = "sha256:ea8e00d7992054c4c592aeb892f6ad51fe1b4d90cc6947cc45c45717c40ec537", size = 1201172, upload-time = "2025-05-04T18:47:02.575Z" }, ] [[package]] From 4f92f06c046a18f74dac1796ac883f575b27194e Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Fri, 9 May 2025 02:32:50 +0000 Subject: [PATCH 03/11] fix: the tests --- sqlspec/adapters/adbc/config.py | 2 +- sqlspec/adapters/adbc/driver.py | 371 ++++++++++++++++++++++---- sqlspec/adapters/aiosqlite/driver.py | 65 ++--- sqlspec/adapters/asyncmy/driver.py | 68 +++-- sqlspec/adapters/asyncpg/driver.py | 225 +++++++++------- sqlspec/adapters/bigquery/driver.py | 13 +- sqlspec/adapters/duckdb/driver.py | 48 ++-- sqlspec/adapters/oracledb/driver.py | 17 +- sqlspec/adapters/psqlpy/driver.py | 56 ++-- sqlspec/adapters/psycopg/driver.py | 44 +-- sqlspec/adapters/sqlite/driver.py | 179 ++++++------- sqlspec/extensions/litestar/plugin.py | 22 +- sqlspec/statement.py | 62 +++-- sqlspec/utils/text.py | 11 +- 14 files changed, 721 insertions(+), 462 deletions(-) diff --git a/sqlspec/adapters/adbc/config.py b/sqlspec/adapters/adbc/config.py index 36c69a6..fe87ed2 100644 --- a/sqlspec/adapters/adbc/config.py +++ b/sqlspec/adapters/adbc/config.py @@ -38,7 +38,7 @@ class AdbcConfig(NoPoolSyncConfig["AdbcConnection", "AdbcDriver"]): pool_instance: None = field(init=False, default=None, hash=False) """No connection pool is used for ADBC connections""" - def _set_adbc(self) -> str: # noqa: PLR0912 + def _set_adbc(self) -> str: """Identify the driver type based on the URI (if provided) or preset driver name. Raises: diff --git a/sqlspec/adapters/adbc/driver.py b/sqlspec/adapters/adbc/driver.py index 6345bb4..04733e7 100644 --- a/sqlspec/adapters/adbc/driver.py +++ b/sqlspec/adapters/adbc/driver.py @@ -1,18 +1,19 @@ +# ruff: noqa: PLR0915, C901, PLR0912, PLR0911 import contextlib import logging -import re from collections.abc import Generator, Sequence from contextlib import contextmanager from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union, cast, overload +import sqlglot from adbc_driver_manager.dbapi import Connection, Cursor +from sqlglot import exp as sqlglot_exp from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import AT_NAME_REGEX, DOLLAR_NAME_REGEX, PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, StatementParameterType -from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T @@ -21,7 +22,6 @@ logger = logging.getLogger("sqlspec") - AdbcConnection = Connection @@ -41,7 +41,7 @@ def __init__(self, connection: "AdbcConnection") -> None: self.connection = connection @staticmethod - def _get_dialect(connection: "AdbcConnection") -> str: # noqa: PLR0911 + def _get_dialect(connection: "AdbcConnection") -> str: """Get the database dialect based on the driver name. Args: @@ -78,16 +78,121 @@ def _with_cursor(self, connection: "AdbcConnection") -> Generator["Cursor", None with contextlib.suppress(Exception): cursor.close() # type: ignore[no-untyped-call] + def _extract_colon_param_names(self, sql: str) -> list[str]: + try: + param_names = self._extract_param_names_sqlglot(sql) + + except Exception: # Catches sqlglot parsing errors or the deliberate RuntimeError # noqa: BLE001 + msg = f"ADBC: sqlglot parsing for :name params failed. Falling back to PARAM_REGEX. SQL: {sql}" + logger.debug(msg) + param_names = self._extract_param_names_regex(sql) + return param_names + + @staticmethod + def _extract_param_names_regex(sql: str) -> list[str]: + param_names: list[str] = [] + param_names.extend( + var_name + for match in PARAM_REGEX.finditer(sql) + if not (match.group("dquote") or match.group("squote") or match.group("comment")) + and (var_name := match.group("var_name")) + ) + return param_names + + @staticmethod + def _extract_param_names_sqlglot(sql: str) -> list[str]: + parsed_sql = sqlglot.parse_one(sql, read="mysql") + param_names: list[str] = [node.name for node in parsed_sql.find_all(sqlglot_exp.Parameter) if node.name] + if not param_names: + msg = "Sqlglot found no :name parameters via parsing." + raise SQLParsingError(msg) + return param_names + + @staticmethod + def _extract_duckdb_dollar_param_names(sql: str) -> list[str]: + # DOLLAR_NAME_REGEX is specifically compiled to find $ followed by a letter + # (e.g., (?P[a-zA-Z_][a-zA-Z0-9_]*)), so it won't match $1, $2 etc. + param_names: list[str] = [ + var_name + for match in DOLLAR_NAME_REGEX.finditer(sql) + if not (match.group("dquote") or match.group("squote") or match.group("comment")) + and (var_name := match.group("var_name")) + ] + return param_names + + @staticmethod + def _extract_bigquery_at_param_names(sql: str) -> list[str]: + param_names: list[str] = [] + try: + parsed_sql = sqlglot.parse_one(sql, read="bigquery") + # @foo is often Parameter in sqlglot for BQ + param_names.extend(node.name for node in parsed_sql.find_all(sqlglot_exp.Parameter) if node.name) + except Exception as e: # noqa: BLE001 + msg = f"ADBC (bigquery): sqlglot failed to parse for @name params: {e}. Falling back to AT_NAME_REGEX. SQL: {sql}" + logger.debug(msg) + param_names.extend( + var_name + for match in AT_NAME_REGEX.finditer(sql) + if not (match.group("dquote") or match.group("squote") or match.group("comment")) + and (var_name := match.group("var_name")) + ) + return param_names + + @staticmethod + def _build_ordered_param_tuple( + param_names: list[str], + params_dict: dict[str, Any], + dialect_for_error_msg: str, + sql_for_error_msg: str, + placeholder_prefix_for_error_msg: str, + ) -> tuple[Any, ...]: + # If dict is empty, return empty tuple even if param_names is not (implies SQL has placeholders but no params were actually needed/provided) + if not params_dict: + return () + + # If dict is provided, but no placeholders were found in SQL to order them by + if not param_names and params_dict: + msg = ( + f"ADBC {dialect_for_error_msg}: Dictionary parameters provided ({list(params_dict.keys())}), but no recognizable " + f"'{placeholder_prefix_for_error_msg}name' placeholders found in SQL to determine order. SQL: {sql_for_error_msg}" + ) + raise SQLParsingError(msg) + + params_values_list: list[Any] = [] + missing_keys: list[str] = [] + for name in param_names: + if name in params_dict: + params_values_list.append(params_dict[name]) + else: + missing_keys.append(name) + + if missing_keys: + # Format missing keys string properly + missing_keys_fmt = ", ".join([f"{placeholder_prefix_for_error_msg}{k}" for k in missing_keys]) + msg = ( + f"ADBC {dialect_for_error_msg}: Missing data for parameter(s) {missing_keys_fmt} " + f"found in SQL but not provided in dictionary. SQL: {sql_for_error_msg}" + ) + raise SQLParsingError(msg) + + # Check for unused keys provided in the dictionary + unused_keys = set(params_dict.keys()) - set(param_names) + if unused_keys: + msg = f"ADBC {dialect_for_error_msg}: Parameters provided in dictionary but not found in SQL: {sorted(unused_keys)}. SQL: {sql_for_error_msg}" + logger.warning(msg) + raise SQLParsingError(msg) + + return tuple(params_values_list) + def _process_sql_params( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any, - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + ) -> "tuple[str, Optional[tuple[Any, ...]]]": # Always returns tuple or None for params # 1. Merge parameters and kwargs merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None - if kwargs: if isinstance(parameters, dict): merged_params = {**parameters, **kwargs} @@ -97,42 +202,208 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters - # Use bind_parameters for named parameters + # --- Dictionary Parameters Handling --- if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="adbc") - return final_sql, final_params + # Handle empty dictionary case cleanly + if not merged_params: + # Check if SQL actually requires parameters + if ( + self._extract_colon_param_names(sql) + or self._extract_duckdb_dollar_param_names(sql) + or self._extract_bigquery_at_param_names(sql) + ): + msg = f"ADBC: SQL contains named placeholders but parameter dictionary is empty. SQL: {sql}" + raise SQLParsingError(msg) + return sql, () # Return SQL as is, with empty tuple for params + + actual_adbc_dialect = self._get_dialect(self.connection) + sql_to_execute: str = sql + ordered_param_names: list[str] = [] + placeholder_prefix = ":" # Default prefix for error messages + + # Determine parameter order based on original SQL style (:name > $name > @name) + ordered_param_names = self._extract_colon_param_names(sql) + if not ordered_param_names: + if actual_adbc_dialect == "duckdb": + ordered_param_names = self._extract_duckdb_dollar_param_names(sql) + placeholder_prefix = "$" if ordered_param_names else ":" + elif actual_adbc_dialect == "bigquery": + ordered_param_names = self._extract_bigquery_at_param_names(sql) + placeholder_prefix = "@" if ordered_param_names else ":" + # Add elif for other native styles here if necessary + + # Build the ordered tuple (raises error if inconsistent) + params_tuple = self._build_ordered_param_tuple( + ordered_param_names, merged_params, actual_adbc_dialect, sql, placeholder_prefix + ) + + # Transpile SQL syntax if necessary for target dialect/param style + if actual_adbc_dialect in {"duckdb", "sqlite"}: + if actual_adbc_dialect == "duckdb": + msg = ( + f"ADBC (duckdb) PRE-TRANSPILE DictCase: SQL='{sql}', " + f"placeholder_prefix='{placeholder_prefix}', " + f"ordered_param_names='{ordered_param_names}', " + f"params_tuple='{params_tuple}'" + ) + logger.debug(msg) + try: + read_dialect_for_transpile = "duckdb" if placeholder_prefix == "$" else "mysql" + has_qmarks = any( + True + for m in QMARK_REGEX.finditer(sql) + if not (m.group("dquote") or m.group("squote") or m.group("comment")) and m.group("qmark") + ) + + if not has_qmarks and ordered_param_names: + target_write_dialect = actual_adbc_dialect + msg = f"ADBC ({target_write_dialect}) DEBUG: Transpiling Dict Params. Read='{read_dialect_for_transpile}', Write='{target_write_dialect}'. SQL='{sql}'" + logger.debug(msg) + sql_to_execute = sqlglot.transpile( + sql, read=read_dialect_for_transpile, write=target_write_dialect, pretty=False + )[0] + msg = f"ADBC ({target_write_dialect}) DEBUG: Transpile Dict Result='{sql_to_execute}'" + logger.debug(msg) + elif has_qmarks: + sql_to_execute = sql + else: # No named params and no qmarks + sql_to_execute = sql + except Exception as e: + msg = ( + f"ADBC ({actual_adbc_dialect}): Failed to transpile SQL to 'qmark' style " + f"when using dictionary parameters. Error: {e}. Original SQL: {sql}" + ) + logger.warning(msg) + raise SQLParsingError(msg) from e + else: + # Transpile to the native style (e.g., @name for BQ). Use `args` to allow sqlglot type handling. + try: + sql_to_execute = sqlglot.transpile(sql, args=merged_params, write=actual_adbc_dialect)[0] + except Exception as e: # noqa: BLE001 + msg = f"ADBC ({actual_adbc_dialect}): Failed to transpile SQL to native style: {e}. Using original SQL. SQL: {sql}" + logger.warning(msg) + sql_to_execute = sql - # Case 2: Sequence parameters - pass through - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar parameter - wrap in tuple - if merged_params is not None: - return sql, (merged_params,) + return sql_to_execute, params_tuple - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" + # --- Sequence/Scalar Parameters Handling --- + if isinstance(merged_params, (list, tuple)): + actual_adbc_dialect = self._get_dialect(self.connection) + colon_names = self._extract_colon_param_names(sql) + # Other named param styles are not typically mixed with sequence params by users for SQLite. + # We focus on :name for this special SQLite handling. + + if colon_names and actual_adbc_dialect == "sqlite": + # SQLite: SQL has :name, params are a tuple. Map them. + if len(colon_names) != len(merged_params): + msg = ( + f"ADBC (sqlite): Tuple parameter count ({len(merged_params)}) does not match " + f"named placeholder count ({len(colon_names)}) in SQL: {sql}" + ) + raise SQLParsingError(msg) + # Parameters are already a tuple (merged_params) and in the correct order by convention. + # We just need to transpile the SQL. + try: + msg = f"ADBC (sqlite) DEBUG: Transpiling Tuple/Scalar. Read='mysql', Write='sqlite'. SQL='{sql}'" + logger.debug(msg) + sql_to_execute = sqlglot.transpile(sql, read="mysql", write="sqlite", pretty=False)[0] + msg = f"ADBC (sqlite) DEBUG: Transpile Tuple/Scalar Result='{sql_to_execute}'" + logger.debug(msg) + + # Return the transpiled SQL with the original parameters (as tuple) + # If execution reached here, merged_params must have been a list/tuple based on the outer check + return sql_to_execute, tuple(merged_params) + + except Exception as e: + # Determine original param type for error message more reliably + param_type_str = "tuple/list" if isinstance(parameters, (list, tuple)) else "unknown" + msg = ( + f"ADBC (sqlite): Failed to transpile SQL with :name to 'qmark' style " + f"when using {param_type_str} parameters. Error: {e}. Original SQL: {sql}" + ) + logger.exception(msg) + raise SQLParsingError(msg) from e + elif ( + colon_names + or self._extract_duckdb_dollar_param_names(sql) + or self._extract_bigquery_at_param_names(sql) ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL + # For other dialects, or if not SQLite with :name, this is a mismatch. + msg = f"ADBC: Sequence/tuple parameters provided, but SQL contains named placeholders (:name, $name, @name). SQL: {sql}" + raise ParameterStyleMismatchError(msg) + + # If no named placeholders were found, or if it's SQLite and we handled :name above, + # we assume the SQL is qmark or some other positional style compatible with the tuple. + return sql, tuple(merged_params) + + # --- Scalar Parameters Handling (Separate Block) --- + if merged_params is not None and not isinstance(merged_params, (list, tuple, dict)): # type: ignore[unreachable] + actual_adbc_dialect = self._get_dialect(self.connection) # type: ignore[unreachable] + colon_names = self._extract_colon_param_names(sql) + + if colon_names and actual_adbc_dialect == "sqlite": + # SQLite: SQL has :name, param is scalar. + if len(colon_names) != 1: + msg = f"ADBC (sqlite): Scalar parameter provided, but SQL has {len(colon_names)} named placeholders (expected 1). SQL: {sql}" + raise SQLParsingError(msg) + # Parameter is scalar (merged_params). Wrap in a tuple. + # Transpile SQL. + try: + msg = f"ADBC (sqlite) DEBUG: Transpiling Scalar. Read='mysql', Write='sqlite'. SQL='{sql}'" + logger.debug(msg) + sql_to_execute = sqlglot.transpile(sql, read="mysql", write="sqlite", pretty=False)[0] + msg = f"ADBC (sqlite) DEBUG: Transpile Scalar Result='{sql_to_execute}'" + logger.debug(msg) + + except Exception as e: + msg = ( + f"ADBC (sqlite): Failed to transpile SQL with :name to 'qmark' style " + f"when using a scalar parameter. Error: {e}. Original SQL: {sql}" + ) + logger.exception(msg) + raise SQLParsingError(msg) from e + else: + return sql_to_execute, (merged_params,) # Return scalar wrapped in tuple + elif ( + colon_names + or self._extract_duckdb_dollar_param_names(sql) + or self._extract_bigquery_at_param_names(sql) ): - if match.group(5): - has_placeholders = True - break + # For other dialects, or if not SQLite with :name, this is a mismatch. + msg = f"ADBC: Scalar parameter provided, but SQL contains named placeholders. SQL: {sql}" + raise ParameterStyleMismatchError(msg) - if has_placeholders: - msg = f"adbc: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + # If no named placeholders, or if it's SQLite and we handled :name, + # check for qmark count for scalar. + qmark_count = sum( + 1 + for m in QMARK_REGEX.finditer(sql) + if not (m.group("dquote") or m.group("squote") or m.group("comment")) and m.group("qmark") + ) + if qmark_count != 1: + msg = f"ADBC: Scalar parameter provided, but SQL contains {qmark_count} qmark ('?') placeholders (expected 1). SQL: {sql}" + raise SQLParsingError(msg) + return sql, (merged_params,) + + # --- No Parameters Provided Validation --- + if merged_params is None: + has_placeholders = bool( + self._extract_colon_param_names(sql) + or self._extract_duckdb_dollar_param_names(sql) + or self._extract_bigquery_at_param_names(sql) + or any( + True + for m in QMARK_REGEX.finditer(sql) + if not (m.group("dquote") or m.group("squote") or m.group("comment")) and m.group("qmark") + ) + ) + if has_placeholders: + msg = f"ADBC: SQL statement appears to contain parameter placeholders, but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + + return sql, None # No parameters provided, and none found/needed @overload def select( @@ -210,10 +481,10 @@ def select_one( def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AdbcConnection"] = None, + connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[ModelDTOT, dict[str, Any]]": @@ -307,10 +578,10 @@ def select_value( def select_value( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AdbcConnection"] = None, + connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": @@ -354,10 +625,10 @@ def select_value_or_none( def select_value_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AdbcConnection"] = None, + connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": @@ -380,10 +651,10 @@ def select_value_or_none( def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AdbcConnection"] = None, + connection: "Optional[AdbcConnection]" = None, **kwargs: Any, ) -> int: """Insert, update, or delete data from the database. @@ -423,10 +694,10 @@ def insert_update_delete_returning( def insert_update_delete_returning( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AdbcConnection"] = None, + connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": @@ -456,10 +727,10 @@ def insert_update_delete_returning( def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AdbcConnection"] = None, + connection: "Optional[AdbcConnection]" = None, **kwargs: Any, ) -> str: """Execute a script. @@ -490,9 +761,9 @@ def select_arrow( # pyright: ignore[reportUnknownParameterType] Returns: The results of the query as an Apache Arrow Table. """ - conn = self._connection(connection) + connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - with self._with_cursor(conn) as cursor: + with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] return cast("ArrowTable", cursor.fetch_arrow_table()) # pyright: ignore[reportUnknownMemberType] diff --git a/sqlspec/adapters/aiosqlite/driver.py b/sqlspec/adapters/aiosqlite/driver.py index 9bddb6d..ffdae01 100644 --- a/sqlspec/adapters/aiosqlite/driver.py +++ b/sqlspec/adapters/aiosqlite/driver.py @@ -1,5 +1,4 @@ import logging -import re from contextlib import asynccontextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload @@ -8,7 +7,7 @@ from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: @@ -21,16 +20,6 @@ logger = logging.getLogger("sqlspec") -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - class AiosqliteDriver( SQLTranslatorMixin["AiosqliteConnection"], @@ -75,7 +64,7 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): @@ -87,7 +76,7 @@ def _process_sql_params( return sql, merged_params # Case 3: Scalar parameter - wrap in tuple if merged_params is not None: - return sql, (merged_params,) + return sql, (merged_params,) # type: ignore[unreachable] # Case 0: No parameters provided # Basic validation for placeholders @@ -100,10 +89,8 @@ def _process_sql_params( break if not has_placeholders: # Check for ? style placeholders - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL - ): - if match.group(5): + for match in QMARK_REGEX.finditer(sql): + if match.group("qmark"): has_placeholders = True break @@ -138,10 +125,10 @@ async def select( async def select( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": @@ -191,10 +178,10 @@ async def select_one( async def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[dict[str, Any], ModelDTOT]": @@ -243,10 +230,10 @@ async def select_one_or_none( async def select_one_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": @@ -296,10 +283,10 @@ async def select_value( async def select_value( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": @@ -320,7 +307,7 @@ async def select_value( result_value = result[0] if schema_type is None: return result_value - return cast("T", schema_type(result_value)) # type: ignore[call-arg] + return schema_type(result_value) # type: ignore[call-arg] @overload async def select_value_or_none( @@ -347,10 +334,10 @@ async def select_value_or_none( async def select_value_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": @@ -372,15 +359,15 @@ async def select_value_or_none( result_value = result[0] if schema_type is None: return result_value - return cast("T", schema_type(result_value)) # type: ignore[call-arg] + return schema_type(result_value) # type: ignore[call-arg] async def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, **kwargs: Any, ) -> int: """Insert, update, or delete data from the database. @@ -421,10 +408,10 @@ async def insert_update_delete_returning( async def insert_update_delete_returning( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[dict[str, Any], ModelDTOT]": @@ -438,8 +425,10 @@ async def insert_update_delete_returning( # Execute the query cursor = await connection.execute(sql, parameters or ()) - await connection.commit() result = await cursor.fetchone() + await connection.commit() + await cursor.close() + result = self.check_not_found(result) # Get column names @@ -452,10 +441,10 @@ async def insert_update_delete_returning( async def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["AiosqliteConnection"] = None, + connection: "Optional[AiosqliteConnection]" = None, **kwargs: Any, ) -> str: """Execute a script. @@ -471,7 +460,7 @@ async def execute_script( await connection.commit() return "Script executed successfully." - def _connection(self, connection: Optional["AiosqliteConnection"] = None) -> "AiosqliteConnection": + def _connection(self, connection: "Optional[AiosqliteConnection]" = None) -> "AiosqliteConnection": """Get the connection to use for the operation. Args: diff --git a/sqlspec/adapters/asyncmy/driver.py b/sqlspec/adapters/asyncmy/driver.py index 5133da2..3581c6e 100644 --- a/sqlspec/adapters/asyncmy/driver.py +++ b/sqlspec/adapters/asyncmy/driver.py @@ -1,16 +1,15 @@ # type: ignore import logging -import re from collections.abc import AsyncGenerator, Sequence from contextlib import asynccontextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import asyncmy +from asyncmy import Connection from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: @@ -20,19 +19,10 @@ __all__ = ("AsyncmyDriver",) -AsyncmyConnection = asyncmy.Connection +AsyncmyConnection = Connection logger = logging.getLogger("sqlspec") -QMARK_REGEX = re.compile( - r"""(?P\"[^\"]*\") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - class AsyncmyDriver( SQLTranslatorMixin["AsyncmyConnection"], @@ -99,10 +89,10 @@ def _process_sql_params( break if not has_placeholders: # Check for ? style placeholders - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL - ): - if match.group(5): + for match in QMARK_REGEX.finditer(sql): + if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( + "qmark" + ): has_placeholders = True break @@ -156,9 +146,10 @@ async def select( results = await cursor.fetchall() if not results: return [] + column_names = [c[0] for c in cursor.description or []] if schema_type is None: - return [dict(zip(cursor.column_names, row)) for row in results] - return [cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, row)))) for row in results] + return [dict(zip(column_names, row)) for row in results] + return [schema_type(**dict(zip(column_names, row))) for row in results] @overload async def select_one( @@ -203,9 +194,10 @@ async def select_one( await cursor.execute(sql, parameters) result = await cursor.fetchone() result = self.check_not_found(result) + column_names = [c[0] for c in cursor.description or []] if schema_type is None: - return dict(zip(cursor.column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, result)))) + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload async def select_one_or_none( @@ -251,9 +243,10 @@ async def select_one_or_none( result = await cursor.fetchone() if result is None: return None + column_names = [c[0] for c in cursor.description or []] if schema_type is None: - return dict(zip(cursor.column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, result)))) + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload async def select_value( @@ -298,11 +291,10 @@ async def select_value( await cursor.execute(sql, parameters) result = await cursor.fetchone() result = self.check_not_found(result) - # Return first value from the row - result_value = result[0] if result else None - if schema_type is None: - return result_value - return schema_type(result_value) + value = result[0] + if schema_type is not None: + return schema_type(value) # type: ignore[call-arg] + return value @overload async def select_value_or_none( @@ -348,11 +340,10 @@ async def select_value_or_none( result = await cursor.fetchone() if result is None: return None - # Return first value from the row - result_value = result[0] if result else None - if schema_type is None: - return result_value - return schema_type(result_value) + value = result[0] + if schema_type is not None: + return schema_type(value) # type: ignore[call-arg] + return value async def insert_update_delete( self, @@ -413,13 +404,16 @@ async def insert_update_delete_returning( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() - result = self.check_not_found(result) - if schema_type is None: - return dict(zip(cursor.column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(cursor.column_names, result)))) + if result is None: + return None + column_names = [c[0] for c in cursor.description or []] + if schema_type is not None: + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + return dict(zip(column_names, result)) async def execute_script( self, diff --git a/sqlspec/adapters/asyncpg/driver.py b/sqlspec/adapters/asyncpg/driver.py index 819afa3..c5f83d9 100644 --- a/sqlspec/adapters/asyncpg/driver.py +++ b/sqlspec/adapters/asyncpg/driver.py @@ -8,7 +8,7 @@ from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX if TYPE_CHECKING: from collections.abc import Sequence @@ -22,19 +22,11 @@ logger = logging.getLogger("sqlspec") -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -# Simplified version, assumes standard SQL quoting/comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P\\'[^\\']*\\') | # Single-quoted strings - (?P--[^\\n]*|/\\*.*?\\*/) | # SQL comments (single/multi-line) - (?P\\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - AsyncpgConnection: TypeAlias = "Union[Connection[Any], PoolConnectionProxy[Any]]" +# Compile the row count regex once for efficiency +ROWCOUNT_REGEX = re.compile(r"^(?:INSERT|UPDATE|DELETE) \d+ (\d+)$") + class AsyncpgDriver( SQLTranslatorMixin["AsyncpgConnection"], @@ -48,7 +40,7 @@ class AsyncpgDriver( def __init__(self, connection: "AsyncpgConnection") -> None: self.connection = connection - def _process_sql_params( # noqa: PLR0912, PLR0915, PLR0914 + def _process_sql_params( # noqa: PLR0912, PLR0915 self, sql: str, parameters: "Optional[StatementParameterType]" = None, @@ -71,7 +63,7 @@ def _process_sql_params( # noqa: PLR0912, PLR0915, PLR0914 elif parameters is not None: merged_params_type = type(parameters) # Preserve original type (dict, list, tuple, scalar) for now - merged_params = parameters # type: ignore + merged_params = parameters # 2. Process based on merged parameter type @@ -86,14 +78,12 @@ def _process_sql_params( # noqa: PLR0912, PLR0915, PLR0914 has_placeholders = True break if not has_placeholders: - # More refined check for '?' outside comments/strings - if QMARK_REGEX.search(sql): - # Check again avoiding comments/strings - if re.search( - r"(? "Sequence[Union[dict[str, Any], ModelDTOT]]": """Fetch data from the database. + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments. + Returns: List of row data as either model instances or dictionaries. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - params = [] if parameters is None else parameters - async with connection.transaction(): - stmt = await connection.prepare(sql) - results = await stmt.fetch(*params) if isinstance(params, (list, tuple)) else await stmt.fetch(params) - if not results: - return [] - if schema_type is None: - return [dict(record) for record in results] - return [cast("ModelDTOT", schema_type(**dict(record))) for record in results] + parameters = parameters if parameters is not None else {} + + results = await connection.fetch(sql, *parameters) # pyright: ignore + if not results: + return [] + if schema_type is None: + return [dict(row.items()) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] + return [cast("ModelDTOT", schema_type(**dict(row.items()))) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] @overload async def select_one( @@ -301,19 +297,26 @@ async def select_one( ) -> "Union[dict[str, Any], ModelDTOT]": """Fetch one row from the database. + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments. + Returns: The first row of the query results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - params = [] if parameters is None else parameters - async with connection.transaction(): - stmt = await connection.prepare(sql) - result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) - result = self.check_not_found(result) - if schema_type is None: - return dict(result) - return cast("ModelDTOT", schema_type(**dict(result))) + parameters = parameters if parameters is not None else {} + result = await connection.fetchrow(sql, *parameters) # pyright: ignore + result = self.check_not_found(result) + + if schema_type is None: + # Always return as dictionary + return dict(result.items()) # type: ignore[attr-defined] + return cast("ModelDTOT", schema_type(**dict(result.items()))) # type: ignore[attr-defined] @overload async def select_one_or_none( @@ -349,20 +352,26 @@ async def select_one_or_none( ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": """Fetch one row from the database. + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments. + Returns: The first row of the query results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - params = [] if parameters is None else parameters - async with connection.transaction(): - stmt = await connection.prepare(sql) - result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) - if result is None: - return None - if schema_type is None: - return dict(result) - return cast("ModelDTOT", schema_type(**dict(result))) + parameters = parameters if parameters is not None else {} + result = await connection.fetchrow(sql, *parameters) # pyright: ignore + if result is None: + return None + if schema_type is None: + # Always return as dictionary + return dict(result.items()) + return cast("ModelDTOT", schema_type(**dict(result.items()))) @overload async def select_value( @@ -398,20 +407,24 @@ async def select_value( ) -> "Union[T, Any]": """Fetch a single value from the database. + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments. + Returns: - The first value from the first row of results. + The first value from the first row of results, or None if no results. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - params = [] if parameters is None else parameters - async with connection.transaction(): - stmt = await connection.prepare(sql) - result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) - result = self.check_not_found(result) - result_value = result[0] if result else None - if schema_type is not None and callable(schema_type): - return schema_type(result_value) - return result_value + parameters = parameters if parameters is not None else {} + result = await connection.fetchval(sql, *parameters) # pyright: ignore + result = self.check_not_found(result) + if schema_type is None: + return result + return schema_type(result) # type: ignore[call-arg] @overload async def select_value_or_none( @@ -452,39 +465,40 @@ async def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - params = [] if parameters is None else parameters - async with connection.transaction(): - stmt = await connection.prepare(sql) - result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) - if result is None: - return None - result_value = result[0] if result else None - if schema_type is not None and callable(schema_type): - return schema_type(result_value) - return result_value + parameters = parameters if parameters is not None else {} + result = await connection.fetchval(sql, *parameters) # pyright: ignore + if result is None: + return None + if schema_type is None: + return result + return schema_type(result) # type: ignore[call-arg] async def insert_update_delete( self, sql: str, - parameters: "Optional[StatementParameterType]" = None, + parameters: Optional["StatementParameterType"] = None, /, *, - connection: "Optional[AsyncpgConnection]" = None, + connection: Optional["AsyncpgConnection"] = None, **kwargs: Any, ) -> int: + """Insert, update, or delete data from the database. + + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + **kwargs: Additional keyword arguments. + + Returns: + Row count affected by the operation. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - if parameters is None or (isinstance(parameters, (list, tuple)) and not parameters): - result = await connection.execute(sql) - elif isinstance(parameters, dict) or isinstance(parameters, (list, tuple)): - result = await connection.execute(sql, parameters) # type: ignore - else: - # Scalar: wrap in tuple - result = await connection.execute(sql, (parameters,)) # type: ignore - match = re.match(r"^(?:INSERT|UPDATE|DELETE)\s+\d+\s+(\d+)$", result) - if match: - return int(match.group(1)) - match = re.match(r"^(?:INSERT|UPDATE|DELETE)\s+(\d+)$", result) + parameters = parameters if parameters is not None else {} + result = await connection.execute(sql, *parameters) # pyright: ignore + # asyncpg returns e.g. 'INSERT 0 1', 'UPDATE 0 2', etc. + match = ROWCOUNT_REGEX.match(result) if match: return int(match.group(1)) return 0 @@ -520,22 +534,28 @@ async def insert_update_delete_returning( connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Union[dict[str, Any], ModelDTOT]": - """Insert, update, or delete data from the database and return result. + ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": + """Insert, update, or delete data from the database and return the affected row. + + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments. Returns: - The first row of results. + The affected row data as either a model instance or dictionary. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - params = [] if parameters is None else parameters - async with connection.transaction(): - stmt = await connection.prepare(sql) - result = await stmt.fetchrow(*params) if isinstance(params, (list, tuple)) else await stmt.fetchrow(params) - result = self.check_not_found(result) - if schema_type is None: - return dict(result) - return cast("ModelDTOT", schema_type(**dict(result))) + parameters = parameters if parameters is not None else {} + result = await connection.fetchrow(sql, *parameters) # pyright: ignore + if result is None: + return None + if schema_type is None: + return dict(result.items()) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] + return cast("ModelDTOT", schema_type(**dict(result.items()))) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType, reportUnknownVariableType] async def execute_script( self, @@ -546,17 +566,22 @@ async def execute_script( connection: "Optional[AsyncpgConnection]" = None, **kwargs: Any, ) -> str: + """Execute a script. + + Args: + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + **kwargs: Additional keyword arguments. + + Returns: + Status message for the operation. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - if parameters is None or (isinstance(parameters, (list, tuple)) and not parameters): - await connection.execute(sql) - elif isinstance(parameters, dict) or isinstance(parameters, (list, tuple)): - await connection.execute(sql, parameters) # type: ignore - else: - # Scalar: wrap in tuple - await connection.execute(sql, (parameters,)) # type: ignore - return "Script executed successfully." - - def _connection(self, connection: Optional["AsyncpgConnection"] = None) -> "AsyncpgConnection": + parameters = parameters if parameters is not None else {} + return await connection.execute(sql, *parameters) # pyright: ignore + + def _connection(self, connection: "Optional[AsyncpgConnection]" = None) -> "AsyncpgConnection": """Return the connection to use. If None, use the default connection.""" return connection if connection is not None else self.connection diff --git a/sqlspec/adapters/bigquery/driver.py b/sqlspec/adapters/bigquery/driver.py index f54911d..54f3517 100644 --- a/sqlspec/adapters/bigquery/driver.py +++ b/sqlspec/adapters/bigquery/driver.py @@ -1,7 +1,6 @@ import contextlib import datetime import logging -import re from collections.abc import Iterator, Sequence from decimal import Decimal from typing import ( @@ -27,7 +26,7 @@ SyncArrowBulkOperationsMixin, SyncParquetExportMixin, ) -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T from sqlspec.utils.text import bind_parameters @@ -130,7 +129,7 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): @@ -142,7 +141,7 @@ def _process_sql_params( return sql, merged_params # Case 3: Scalar parameter - wrap in tuple if merged_params is not None: - return sql, (merged_params,) + return sql, (merged_params,) # type: ignore[unreachable] # Case 0: No parameters provided # Basic validation for placeholders @@ -155,10 +154,8 @@ def _process_sql_params( break if not has_placeholders: # Check for ? style placeholders - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|(\'(?:[^\']|\'\')*\')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL - ): - if match.group(5): + for match in QMARK_REGEX.finditer(sql): + if match.group("qmark"): has_placeholders = True break diff --git a/sqlspec/adapters/duckdb/driver.py b/sqlspec/adapters/duckdb/driver.py index 516dbdb..acf3355 100644 --- a/sqlspec/adapters/duckdb/driver.py +++ b/sqlspec/adapters/duckdb/driver.py @@ -1,5 +1,4 @@ import logging -import re from contextlib import contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload @@ -8,7 +7,7 @@ from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, StatementParameterType from sqlspec.utils.text import bind_parameters @@ -23,16 +22,6 @@ DuckDBConnection = DuckDBPyConnection -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - class DuckDBDriver( SyncArrowBulkOperationsMixin["DuckDBConnection"], @@ -76,6 +65,18 @@ def _process_sql_params( DuckDB supports both named (:name) and positional (?) parameters. This method merges parameters and validates them. + + Args: + sql: The SQL statement to process. + parameters: The parameters to process. + **kwargs: Additional keyword arguments. + + Raises: + ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. + SQLParsingError: If SQL contains parameter placeholders, but no parameters were provided. + + Returns: + A tuple of the processed SQL and parameters. """ # 1. Merge parameters and kwargs merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None @@ -89,7 +90,7 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): @@ -101,7 +102,7 @@ def _process_sql_params( return sql, merged_params # Case 3: Scalar parameter - wrap in tuple if merged_params is not None: - return sql, (merged_params,) + return sql, (merged_params,) # type: ignore[unreachable] # Case 0: No parameters provided # Basic validation for placeholders @@ -113,11 +114,8 @@ def _process_sql_params( has_placeholders = True break if not has_placeholders: - # Check for ? style placeholders - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|('(?:[^']|'')*')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL - ): - if match.group(5): + for match in QMARK_REGEX.finditer(sql): + if match.group("qmark"): has_placeholders = True break @@ -152,10 +150,10 @@ def select( def select( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["DuckDBConnection"] = None, + connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": @@ -249,7 +247,7 @@ def select_one_or_none( def select_one_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, connection: "Optional[DuckDBConnection]" = None, @@ -319,7 +317,7 @@ def select_value( result_value = result[0] if schema_type is None: return result_value - return cast("T", schema_type(result_value)) # type: ignore[call-arg] + return schema_type(result_value) # type: ignore[call-arg] @overload def select_value_or_none( @@ -427,10 +425,10 @@ def insert_update_delete_returning( def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["DuckDBConnection"] = None, + connection: "Optional[DuckDBConnection]" = None, **kwargs: Any, ) -> str: connection = self._connection(connection) diff --git a/sqlspec/adapters/oracledb/driver.py b/sqlspec/adapters/oracledb/driver.py index 7228824..c53ee02 100644 --- a/sqlspec/adapters/oracledb/driver.py +++ b/sqlspec/adapters/oracledb/driver.py @@ -1,5 +1,4 @@ import logging -import re from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload @@ -8,7 +7,7 @@ from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import AsyncArrowBulkOperationsMixin, SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, StatementParameterType, T from sqlspec.utils.text import bind_parameters @@ -24,23 +23,13 @@ logger = logging.getLogger("sqlspec") -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - class OracleDriverBase: """Base class for Oracle drivers with common functionality.""" dialect: str = "oracle" - def _process_sql_params( # noqa: PLR6301 + def _process_sql_params( self, sql: str, parameters: "Optional[StatementParameterType]" = None, @@ -71,7 +60,7 @@ def _process_sql_params( # noqa: PLR6301 else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): diff --git a/sqlspec/adapters/psqlpy/driver.py b/sqlspec/adapters/psqlpy/driver.py index d124a93..ca63799 100644 --- a/sqlspec/adapters/psqlpy/driver.py +++ b/sqlspec/adapters/psqlpy/driver.py @@ -1,8 +1,7 @@ -# ruff: noqa: PLR0915, PLR0912, C901 +# ruff: noqa: PLR0915, PLR0912, C901, PLR6301 """Psqlpy Driver Implementation.""" import logging -import re from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload from psqlpy import Connection, QueryResult @@ -11,7 +10,7 @@ from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: @@ -25,15 +24,6 @@ PsqlpyConnection = Connection -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P\'[^\']*\') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) logger = logging.getLogger("sqlspec") @@ -60,6 +50,18 @@ def _process_sql_params( psqlpy uses $1, $2 style parameters natively. This method converts '?' (tuple/list) and ':name' (dict) styles to $n. + + Args: + sql: The SQL statement to process. + parameters: The parameters to process. + **kwargs: Additional keyword arguments. + + Raises: + ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. + SQLParsingError: If SQL contains parameter placeholders, but no parameters were provided. + + Returns: + A tuple of the processed SQL and parameters. """ # 1. Merge parameters and kwargs merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None @@ -73,7 +75,7 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): @@ -129,7 +131,7 @@ def _process_sql_params( # Convert to a one-element tuple if merged_params is not None: scalar_param_tuple = (merged_params,) - sequence_processed_parts: list[str] = [] + sequence_processed_parts = [] param_index = 1 last_end = 0 qmark_count = 0 @@ -205,10 +207,10 @@ async def select( async def select( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["PsqlpyConnection"] = None, + connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": @@ -247,10 +249,10 @@ async def select_one( async def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["PsqlpyConnection"] = None, + connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[ModelDTOT, dict[str, Any]]": @@ -290,10 +292,10 @@ async def select_one_or_none( async def select_one_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["PsqlpyConnection"] = None, + connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": @@ -403,10 +405,10 @@ async def select_value_or_none( async def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["PsqlpyConnection"] = None, + connection: "Optional[PsqlpyConnection]" = None, **kwargs: Any, ) -> int: connection = self._connection(connection) @@ -443,10 +445,10 @@ async def insert_update_delete_returning( async def insert_update_delete_returning( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["PsqlpyConnection"] = None, + connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": @@ -468,10 +470,10 @@ async def insert_update_delete_returning( async def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["PsqlpyConnection"] = None, + connection: "Optional[PsqlpyConnection]" = None, **kwargs: Any, ) -> str: connection = self._connection(connection) @@ -481,7 +483,7 @@ async def execute_script( await connection.execute(sql, parameters=parameters) return sql - def _connection(self, connection: Optional["PsqlpyConnection"] = None) -> "PsqlpyConnection": + def _connection(self, connection: "Optional[PsqlpyConnection]" = None) -> "PsqlpyConnection": """Get the connection to use. Args: diff --git a/sqlspec/adapters/psycopg/driver.py b/sqlspec/adapters/psycopg/driver.py index 5dcde1d..d496066 100644 --- a/sqlspec/adapters/psycopg/driver.py +++ b/sqlspec/adapters/psycopg/driver.py @@ -7,10 +7,9 @@ from psycopg.rows import dict_row from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError +from sqlspec.exceptions import ParameterStyleMismatchError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX -from sqlspec.utils.text import bind_parameters +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence @@ -24,15 +23,8 @@ PsycopgSyncConnection = Connection PsycopgAsyncConnection = AsyncConnection -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) +# Compile the parameter name regex once for efficiency +PARAM_NAME_REGEX = re.compile(r":([a-zA-Z_][a-zA-Z0-9_]*)") class PsycopgDriverBase: @@ -45,7 +37,6 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Process SQL and parameters, converting :name -> %(name)s if needed.""" # 1. Merge parameters and kwargs merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None @@ -58,13 +49,13 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="postgres") - return final_sql, final_params - + # Always convert :name to %(name)s for psycopg + sql_converted = PARAM_NAME_REGEX.sub(lambda m: f"%({m.group(1)})s", sql) + return sql_converted, merged_params # Case 2: Sequence parameters - leave as is (psycopg handles '%s' placeholders with tuple/list) if isinstance(merged_params, (list, tuple)): return sql, merged_params @@ -81,18 +72,17 @@ def _process_sql_params( ): has_placeholders = True break + has_qmark = False if not has_placeholders: - # Check for ? style placeholders for match in QMARK_REGEX.finditer(sql): if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( "qmark" ): - has_placeholders = True + has_qmark = True break - - if has_placeholders: + if has_placeholders or has_qmark: msg = f"psycopg: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) + raise ParameterStyleMismatchError(msg) return sql, None @@ -720,14 +710,9 @@ async def insert_update_delete( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) - try: - rowcount = int(cursor.rowcount) - except (TypeError, ValueError): - rowcount = -1 - return rowcount + return getattr(cursor, "rowcount", -1) # pyright: ignore[reportUnknownMemberType] @overload async def insert_update_delete_returning( @@ -768,14 +753,11 @@ async def insert_update_delete_returning( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() - if result is None: return None - if schema_type is not None: return cast("ModelDTOT", schema_type(**result)) # pyright: ignore[reportUnknownArgumentType] return cast("dict[str, Any]", result) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] diff --git a/sqlspec/adapters/sqlite/driver.py b/sqlspec/adapters/sqlite/driver.py index fbaaf86..1f8e49e 100644 --- a/sqlspec/adapters/sqlite/driver.py +++ b/sqlspec/adapters/sqlite/driver.py @@ -1,5 +1,4 @@ import logging -import re import sqlite3 from contextlib import contextmanager from sqlite3 import Cursor @@ -8,7 +7,7 @@ from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX +from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: @@ -22,16 +21,6 @@ SqliteConnection = sqlite3.Connection -# Regex to find '?' placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P"[^"]*") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - class SqliteDriver( SQLTranslatorMixin["SqliteConnection"], @@ -81,7 +70,7 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # Use bind_parameters for named parameters if isinstance(merged_params, dict): @@ -93,7 +82,7 @@ def _process_sql_params( return sql, merged_params # Case 3: Scalar parameter - wrap in tuple if merged_params is not None: - return sql, (merged_params,) + return sql, (merged_params,) # type: ignore[unreachable] # Case 0: No parameters provided # Basic validation for placeholders @@ -106,10 +95,8 @@ def _process_sql_params( break if not has_placeholders: # Check for ? style placeholders - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|('(?:[^']|'')*')|(--.*?\n)|(\/\*.*?\*\/)|(\?)", sql, re.DOTALL - ): - if match.group(5): + for match in QMARK_REGEX.finditer(sql): + if match.group("qmark"): has_placeholders = True break @@ -144,10 +131,10 @@ def select( def select( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Sequence[Union[dict[str, Any], ModelDTOT]]": @@ -159,19 +146,18 @@ def select( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the query - cursor = connection.cursor() - cursor.execute(sql, parameters or []) - results = cursor.fetchall() - if not results: - return [] + with self._with_cursor(connection) as cursor: + cursor.execute(sql, parameters or []) + results = cursor.fetchall() + if not results: + return [] - # Get column names - column_names = [column[0] for column in cursor.description] + # Get column names + column_names = [column[0] for column in cursor.description] - if schema_type is None: - return [dict(zip(column_names, row)) for row in results] - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] + if schema_type is None: + return [dict(zip(column_names, row)) for row in results] + return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] @overload def select_one( @@ -198,10 +184,10 @@ def select_one( def select_one( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[dict[str, Any], ModelDTOT]": @@ -251,10 +237,10 @@ def select_one_or_none( def select_one_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": @@ -266,19 +252,18 @@ def select_one_or_none( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the query - cursor = connection.cursor() - cursor.execute(sql, parameters or []) - result = cursor.fetchone() - if result is None: - return None + with self._with_cursor(connection) as cursor: + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + if result is None: + return None - # Get column names - column_names = [column[0] for column in cursor.description] + # Get column names + column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) @overload def select_value( @@ -305,10 +290,10 @@ def select_value( def select_value( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": @@ -320,17 +305,16 @@ def select_value( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the query - cursor = connection.cursor() - cursor.execute(sql, parameters or []) - result = cursor.fetchone() - result = self.check_not_found(result) + with self._with_cursor(connection) as cursor: + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + result = self.check_not_found(result) - # Return first value from the row - result_value = result[0] - if schema_type is None: - return result_value - return cast("T", schema_type(result_value)) # type: ignore[call-arg] + # Return first value from the row + result_value = result[0] + if schema_type is None: + return result_value + return schema_type(result_value) # type: ignore[call-arg] @overload def select_value_or_none( @@ -357,10 +341,10 @@ def select_value_or_none( def select_value_or_none( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": @@ -372,26 +356,25 @@ def select_value_or_none( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the query - cursor = connection.cursor() - cursor.execute(sql, parameters or []) - result = cursor.fetchone() - if result is None: - return None + with self._with_cursor(connection) as cursor: + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + if result is None: + return None - # Return first value from the row - result_value = result[0] - if schema_type is None: - return result_value - return cast("T", schema_type(result_value)) # type: ignore[call-arg] + # Return first value from the row + result_value = result[0] + if schema_type is None: + return result_value + return schema_type(result_value) # type: ignore[call-arg] def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, **kwargs: Any, ) -> int: """Insert, update, or delete data from the database. @@ -402,11 +385,10 @@ def insert_update_delete( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the query - cursor = connection.cursor() - cursor.execute(sql, parameters or []) - connection.commit() - return cursor.rowcount + with self._with_cursor(connection) as cursor: + cursor.execute(sql, parameters or []) + connection.commit() + return cursor.rowcount @overload def insert_update_delete_returning( @@ -433,10 +415,10 @@ def insert_update_delete_returning( def insert_update_delete_returning( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[dict[str, Any], ModelDTOT]": @@ -448,27 +430,25 @@ def insert_update_delete_returning( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the query - cursor = connection.cursor() - cursor.execute(sql, parameters or []) - connection.commit() - result = cursor.fetchone() - result = self.check_not_found(result) - - # Get column names - column_names = [column[0] for column in cursor.description] + with self._with_cursor(connection) as cursor: + cursor.execute(sql, parameters or []) + result = cursor.fetchone() + result = self.check_not_found(result) + connection.commit() + # Get column names + column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + if schema_type is None: + return dict(zip(column_names, result)) + return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) def execute_script( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, *, - connection: Optional["SqliteConnection"] = None, + connection: "Optional[SqliteConnection]" = None, **kwargs: Any, ) -> str: """Execute a script. @@ -479,13 +459,12 @@ def execute_script( connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - # Execute the script - cursor = connection.cursor() - cursor.executescript(sql) - connection.commit() - return "Script executed successfully." + with self._with_cursor(connection) as cursor: + cursor.executescript(sql) + connection.commit() + return "Script executed successfully." - def _connection(self, connection: Optional["SqliteConnection"] = None) -> "SqliteConnection": + def _connection(self, connection: "Optional[SqliteConnection]" = None) -> "SqliteConnection": """Get the connection to use for the operation. Args: diff --git a/sqlspec/extensions/litestar/plugin.py b/sqlspec/extensions/litestar/plugin.py index ee915b6..53e72a0 100644 --- a/sqlspec/extensions/litestar/plugin.py +++ b/sqlspec/extensions/litestar/plugin.py @@ -70,16 +70,18 @@ def on_app_init(self, app_config: "AppConfig") -> "AppConfig": The updated :class:`AppConfig <.config.app.AppConfig>` instance. """ self._validate_dependency_keys() - app_config.signature_types.extend([ - SQLSpec, - ConnectionT, - PoolT, - DriverT, - DatabaseConfig, - DatabaseConfigProtocol, - SyncConfigT, - AsyncConfigT, - ]) + app_config.signature_types.extend( + [ + SQLSpec, + ConnectionT, + PoolT, + DriverT, + DatabaseConfig, + DatabaseConfigProtocol, + SyncConfigT, + AsyncConfigT, + ] + ) for c in self._plugin_configs: c.annotation = self.add_config(c.config) app_config.signature_types.append(c.annotation) diff --git a/sqlspec/statement.py b/sqlspec/statement.py index bb7b611..6b8568c 100644 --- a/sqlspec/statement.py +++ b/sqlspec/statement.py @@ -32,6 +32,45 @@ re.VERBOSE | re.DOTALL, ) +# Regex to find ? placeholders, skipping those inside quotes or SQL comments +QMARK_REGEX = re.compile( + r"""(?P\"[^\"]*\") | # Double-quoted strings + (?P'[^']*') | # Single-quoted strings + (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) + (?P\?) # The question mark placeholder + """, + re.VERBOSE | re.DOTALL, +) + + +# Regex for $name style, avoiding comments/strings +# Lookbehind ensures it's not preceded by a word char or another $ +DOLLAR_NAME_REGEX = re.compile( + r"""(?"(?:[^"]|"")*") | # Double-quoted strings + (?P'(?:[^']|'')*') | # Single-quoted strings + (?P--.*?\n|\/\*.*?\*\/) | # SQL comments + \$ (?P[a-zA-Z_][a-zA-Z0-9_]*) # $var_name identifier + ) + """, + re.VERBOSE | re.DOTALL, +) + +# Regex for @name style, avoiding comments/strings +# Lookbehind ensures it's not preceded by a word char or another @ +AT_NAME_REGEX = re.compile( + r"""(?"(?:[^"]|"")*") | # Double-quoted strings + (?P'(?:[^']|'')*') | # Single-quoted strings + (?P--.*?\n|\/\*.*?\*\/) | # SQL comments + @ (?P[a-zA-Z_][a-zA-Z0-9_]*) # @var_name identifier + ) + """, + re.VERBOSE | re.DOTALL, +) + @dataclass() class SQLStatement: @@ -90,7 +129,7 @@ def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict sql_params = list(expression.find_all(exp.Parameter)) except SQLParsingError as e: # If parsing fails, we cannot validate accurately. - # Let adapters handle potentially valid but unparseable SQL. + # Let adapters handle potentially valid but unparsable SQL. # Log the parsing error for debugging. logger.debug( "SQL parsing failed during validation: %s. Returning original SQL and parameters for adapter.", e @@ -174,11 +213,6 @@ def _validate_dict_params(self, sql_params: list[exp.Parameter], parameter_dict: msg = f"Named parameters found in SQL but not provided: {missing_keys}. SQL: {self.sql}" raise SQLParsingError(msg) - # Allow extra keys, as they might be used by the adapter or driver internally - # extra_keys = provided_keys - required_keys - # if extra_keys: - # logger.debug("Extra parameters provided but not found in SQL: %s", extra_keys) - def _validate_sequence_params( self, sql_params: list[exp.Parameter], params: Union[tuple[Any, ...], list[Any]] ) -> None: @@ -188,29 +222,25 @@ def _validate_sequence_params( if named_sql_params: # No need to store msg if we are raising immediately - raise ParameterStyleMismatchError( - f"Sequence parameters provided, but found named placeholders (e.g., ':name') in SQL: {self.sql}" - ) + msg = f"Sequence parameters provided, but found named placeholders (e.g., ':name') in SQL: {self.sql}" + raise ParameterStyleMismatchError(msg) expected_count = len(unnamed_sql_params) actual_count = len(params) if expected_count != actual_count: # Double-check with regex if counts mismatch, as parsing might miss some complex cases - # Simple regex for '?' outside comments/strings needed here regex_count = 0 - for match in re.finditer( - r"(\"(?:[^\"]|\"\")*\")|('(?:[^']|'')*')|(--.*?\\n)|(\\/\\*.*?\\*\\/)|(\\?)", self.sql, re.DOTALL - ): - if match.group(5): # Group 5 is the question mark + for match in QMARK_REGEX.finditer(self.sql): + if match.group("qmark"): regex_count += 1 if regex_count != actual_count: - # No need to store msg if we are raising immediately - raise SQLParsingError( + msg = ( f"Parameter count mismatch. SQL expects {expected_count} (sqlglot) / {regex_count} (regex) positional parameters, " f"but {actual_count} were provided. SQL: {self.sql}" ) + raise SQLParsingError(msg) # Counts mismatch with sqlglot but match with simple regex - log warning, proceed. logger.warning( "Parameter count mismatch (sqlglot: %d, provided: %d), but regex count (%d) matches provided. Proceeding. SQL: %s", diff --git a/sqlspec/utils/text.py b/sqlspec/utils/text.py index 6995a08..e624d47 100644 --- a/sqlspec/utils/text.py +++ b/sqlspec/utils/text.py @@ -74,9 +74,10 @@ def bind_parameters( if isinstance(parameters, dict): bound_sql = sqlglot.transpile(sql, args=parameters, write=dialect)[0] return bound_sql, parameters # Keep dict for drivers that need it - # For positional parameters (list/tuple), just return as is for now - # (could extend to support ? -> $1, $2, etc. if needed) - return sql, parameters - except Exception as e: - logger.debug(f"SQLGlot parameter binding failed: {e}. Using original SQL and parameters.") + except Exception as e: # noqa: BLE001 + msg = f"SQLGlot parameter binding failed: {e}. Using original SQL and parameters." + logger.debug(msg) return sql, parameters + # For positional parameters (list/tuple), just return as is for now + # (could extend to support ? -> $1, $2, etc. if needed) + return sql, parameters From e626eca044c9d843dbcf49673466e79bb107d367 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Sat, 10 May 2025 00:07:35 +0000 Subject: [PATCH 04/11] feat: updates --- pyproject.toml | 2 + sqlspec/adapters/adbc/driver.py | 567 +++++++++--------- sqlspec/adapters/aiosqlite/driver.py | 206 +++++-- sqlspec/adapters/asyncmy/driver.py | 200 ++++-- sqlspec/adapters/asyncpg/driver.py | 282 ++++----- sqlspec/adapters/bigquery/driver.py | 135 +++-- sqlspec/adapters/duckdb/driver.py | 186 ++++-- sqlspec/adapters/oracledb/driver.py | 225 ++++--- sqlspec/adapters/psqlpy/driver.py | 260 ++++---- sqlspec/adapters/psycopg/driver.py | 193 ++++-- sqlspec/adapters/sqlite/driver.py | 156 +++-- sqlspec/extensions/litestar/config.py | 10 +- sqlspec/extensions/litestar/handlers.py | 223 +++++-- sqlspec/statement.py | 270 +++++---- .../test_oracledb/test_driver_sync.py | 12 + tests/unit/test_statement.py | 287 +++++++++ 16 files changed, 2166 insertions(+), 1048 deletions(-) create mode 100644 tests/unit/test_statement.py diff --git a/pyproject.toml b/pyproject.toml index 74498fd..0d5cc9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -260,6 +260,8 @@ reportPrivateUsage = false reportUnknownArgumentType = false reportUnknownMemberType = false reportUnknownVariableType = false +reportUnnecessaryComparison = false +reportUnnecessaryIsInstance = false reportUnnecessaryTypeIgnoreComments = true root = "." diff --git a/sqlspec/adapters/adbc/driver.py b/sqlspec/adapters/adbc/driver.py index 04733e7..d39f99e 100644 --- a/sqlspec/adapters/adbc/driver.py +++ b/sqlspec/adapters/adbc/driver.py @@ -12,7 +12,6 @@ from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import AT_NAME_REGEX, DOLLAR_NAME_REGEX, PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, StatementParameterType if TYPE_CHECKING: @@ -39,6 +38,7 @@ class AdbcDriver( def __init__(self, connection: "AdbcConnection") -> None: """Initialize the ADBC driver adapter.""" self.connection = connection + self.dialect = self._get_dialect(connection) # Store detected dialect @staticmethod def _get_dialect(connection: "AdbcConnection") -> str: @@ -78,112 +78,6 @@ def _with_cursor(self, connection: "AdbcConnection") -> Generator["Cursor", None with contextlib.suppress(Exception): cursor.close() # type: ignore[no-untyped-call] - def _extract_colon_param_names(self, sql: str) -> list[str]: - try: - param_names = self._extract_param_names_sqlglot(sql) - - except Exception: # Catches sqlglot parsing errors or the deliberate RuntimeError # noqa: BLE001 - msg = f"ADBC: sqlglot parsing for :name params failed. Falling back to PARAM_REGEX. SQL: {sql}" - logger.debug(msg) - param_names = self._extract_param_names_regex(sql) - return param_names - - @staticmethod - def _extract_param_names_regex(sql: str) -> list[str]: - param_names: list[str] = [] - param_names.extend( - var_name - for match in PARAM_REGEX.finditer(sql) - if not (match.group("dquote") or match.group("squote") or match.group("comment")) - and (var_name := match.group("var_name")) - ) - return param_names - - @staticmethod - def _extract_param_names_sqlglot(sql: str) -> list[str]: - parsed_sql = sqlglot.parse_one(sql, read="mysql") - param_names: list[str] = [node.name for node in parsed_sql.find_all(sqlglot_exp.Parameter) if node.name] - if not param_names: - msg = "Sqlglot found no :name parameters via parsing." - raise SQLParsingError(msg) - return param_names - - @staticmethod - def _extract_duckdb_dollar_param_names(sql: str) -> list[str]: - # DOLLAR_NAME_REGEX is specifically compiled to find $ followed by a letter - # (e.g., (?P[a-zA-Z_][a-zA-Z0-9_]*)), so it won't match $1, $2 etc. - param_names: list[str] = [ - var_name - for match in DOLLAR_NAME_REGEX.finditer(sql) - if not (match.group("dquote") or match.group("squote") or match.group("comment")) - and (var_name := match.group("var_name")) - ] - return param_names - - @staticmethod - def _extract_bigquery_at_param_names(sql: str) -> list[str]: - param_names: list[str] = [] - try: - parsed_sql = sqlglot.parse_one(sql, read="bigquery") - # @foo is often Parameter in sqlglot for BQ - param_names.extend(node.name for node in parsed_sql.find_all(sqlglot_exp.Parameter) if node.name) - except Exception as e: # noqa: BLE001 - msg = f"ADBC (bigquery): sqlglot failed to parse for @name params: {e}. Falling back to AT_NAME_REGEX. SQL: {sql}" - logger.debug(msg) - param_names.extend( - var_name - for match in AT_NAME_REGEX.finditer(sql) - if not (match.group("dquote") or match.group("squote") or match.group("comment")) - and (var_name := match.group("var_name")) - ) - return param_names - - @staticmethod - def _build_ordered_param_tuple( - param_names: list[str], - params_dict: dict[str, Any], - dialect_for_error_msg: str, - sql_for_error_msg: str, - placeholder_prefix_for_error_msg: str, - ) -> tuple[Any, ...]: - # If dict is empty, return empty tuple even if param_names is not (implies SQL has placeholders but no params were actually needed/provided) - if not params_dict: - return () - - # If dict is provided, but no placeholders were found in SQL to order them by - if not param_names and params_dict: - msg = ( - f"ADBC {dialect_for_error_msg}: Dictionary parameters provided ({list(params_dict.keys())}), but no recognizable " - f"'{placeholder_prefix_for_error_msg}name' placeholders found in SQL to determine order. SQL: {sql_for_error_msg}" - ) - raise SQLParsingError(msg) - - params_values_list: list[Any] = [] - missing_keys: list[str] = [] - for name in param_names: - if name in params_dict: - params_values_list.append(params_dict[name]) - else: - missing_keys.append(name) - - if missing_keys: - # Format missing keys string properly - missing_keys_fmt = ", ".join([f"{placeholder_prefix_for_error_msg}{k}" for k in missing_keys]) - msg = ( - f"ADBC {dialect_for_error_msg}: Missing data for parameter(s) {missing_keys_fmt} " - f"found in SQL but not provided in dictionary. SQL: {sql_for_error_msg}" - ) - raise SQLParsingError(msg) - - # Check for unused keys provided in the dictionary - unused_keys = set(params_dict.keys()) - set(param_names) - if unused_keys: - msg = f"ADBC {dialect_for_error_msg}: Parameters provided in dictionary but not found in SQL: {sorted(unused_keys)}. SQL: {sql_for_error_msg}" - logger.warning(msg) - raise SQLParsingError(msg) - - return tuple(params_values_list) - def _process_sql_params( self, sql: str, @@ -192,7 +86,7 @@ def _process_sql_params( **kwargs: Any, ) -> "tuple[str, Optional[tuple[Any, ...]]]": # Always returns tuple or None for params # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + merged_params: Optional[Union[dict[str, Any], Sequence[Any], Any]] = None # Allow Any for scalar if kwargs: if isinstance(parameters, dict): merged_params = {**parameters, **kwargs} @@ -203,207 +97,298 @@ def _process_sql_params( merged_params = kwargs elif parameters is not None: merged_params = parameters + # else merged_params remains None + + # 2. SQLGlot Parsing - Use the determined dialect for reading if possible + # For ADBC, the input SQL style might be generic, so a neutral read dialect or auto-detection might be safer initially. + # However, self.dialect is set in __init__ based on the connection. + # If the input SQL is guaranteed to match self.dialect, this is fine. + # If SQL can be :name style while dialect is e.g. postgres, sqlglot needs to know. + # Defaulting to parsing with the target dialect; an explicit read_dialect can be added if needed. + try: + # The `read` dialect might need to be more flexible if input SQL doesn't match target ADBC driver dialect. + # For now, assume input SQL should be somewhat compatible or generic enough for sqlglot to parse with target dialect hints. + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"ADBC ({self.dialect}): Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + sql_named_param_nodes = [ + node for node in parsed_expression.find_all(sqlglot_exp.Parameter) if node.name and not node.name.isdigit() + ] + sql_placeholder_nodes = list( + parsed_expression.find_all(sqlglot_exp.Placeholder) + ) # Represents '?' and also ':name' for some dialects + + # More robust detection of numeric parameters (e.g., $1, :1) + sql_numeric_nodes = [] + for node in parsed_expression.find_all(sqlglot_exp.Parameter): + is_numeric = False + if node.name and isinstance(node.name, str) and node.name.isdigit(): # e.g. @1 + is_numeric = True + elif not node.name and node.this: + # Combined and corrected multi-line condition + is_identifier_numeric = ( + isinstance(node.this, sqlglot_exp.Identifier) + and node.this.this + and isinstance(node.this.this, str) + and node.this.this.isdigit() + ) + if ( + (isinstance(node.this, str) and node.this.isdigit()) + or is_identifier_numeric + or isinstance(node.this, sqlglot.exp.Number) + ): # Corrected: sqlglot.exp.Number + is_numeric = True + if is_numeric: + sql_numeric_nodes.append(node) + + # Numeric placeholders like :1, :2 (parsed as Placeholder(this="1")) + numeric_placeholder_nodes = [ + p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and p_node.this.isdigit() + ] + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or sql_placeholder_nodes or sql_numeric_nodes: + placeholder_types = set() + if sql_named_param_nodes: + placeholder_types.add("named (e.g., :name, @name, $name)") + if sql_placeholder_nodes: + placeholder_types.add("positional ('?')") + if sql_numeric_nodes: + placeholder_types.add("numeric (e.g., $1, :1)") + msg = ( + f"ADBC ({self.dialect}): SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + # ADBC execute often expects list/tuple for parameters argument, even if empty. + return sql, () + + final_sql: str + final_params_seq: list[Any] = [] + + target_dialect = self.dialect # Dialect determined from ADBC connection - # --- Dictionary Parameters Handling --- if isinstance(merged_params, dict): - # Handle empty dictionary case cleanly - if not merged_params: - # Check if SQL actually requires parameters - if ( - self._extract_colon_param_names(sql) - or self._extract_duckdb_dollar_param_names(sql) - or self._extract_bigquery_at_param_names(sql) + has_qmark_placeholders = any( + p_node.this is None # Removed isinstance check as p_node is already known to be Placeholder + for p_node in sql_placeholder_nodes + ) + + if has_qmark_placeholders or numeric_placeholder_nodes or sql_numeric_nodes: + msg = ( + f"ADBC ({target_dialect}): Dictionary parameters provided, but SQL uses positional " + f"placeholders ('?', $N, or :N). Use named placeholders (e.g. :name, @name, $name)." + ) + raise ParameterStyleMismatchError(msg) + + # Validate keys + colon_named_placeholder_nodes = [ + p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and not p_node.this.isdigit() + ] + all_ast_named_params = {node.name for node in sql_named_param_nodes if node.name} + all_ast_named_params.update( + node.this for node in colon_named_placeholder_nodes if isinstance(node.this, str) + ) + + provided_keys = set(merged_params.keys()) + missing_keys = all_ast_named_params - provided_keys + if missing_keys: + msg = f"ADBC ({target_dialect}): Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" + raise SQLParsingError(msg) + extra_keys = provided_keys - all_ast_named_params + if extra_keys: + logger.warning( + f"ADBC ({target_dialect}): Parameters {extra_keys} provided but not found in SQL. Behavior depends on underlying driver. SQL: {sql}" + ) + + # Transformation logic: convert all named styles to '?' and populate final_params_seq + final_params_seq.clear() + + def _convert_any_named_to_qmark(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: + param_name_to_check = None + if isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit(): + param_name_to_check = node.name + elif ( + isinstance(node, sqlglot_exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit() ): - msg = f"ADBC: SQL contains named placeholders but parameter dictionary is empty. SQL: {sql}" - raise SQLParsingError(msg) - return sql, () # Return SQL as is, with empty tuple for params - - actual_adbc_dialect = self._get_dialect(self.connection) - sql_to_execute: str = sql - ordered_param_names: list[str] = [] - placeholder_prefix = ":" # Default prefix for error messages - - # Determine parameter order based on original SQL style (:name > $name > @name) - ordered_param_names = self._extract_colon_param_names(sql) - if not ordered_param_names: - if actual_adbc_dialect == "duckdb": - ordered_param_names = self._extract_duckdb_dollar_param_names(sql) - placeholder_prefix = "$" if ordered_param_names else ":" - elif actual_adbc_dialect == "bigquery": - ordered_param_names = self._extract_bigquery_at_param_names(sql) - placeholder_prefix = "@" if ordered_param_names else ":" - # Add elif for other native styles here if necessary - - # Build the ordered tuple (raises error if inconsistent) - params_tuple = self._build_ordered_param_tuple( - ordered_param_names, merged_params, actual_adbc_dialect, sql, placeholder_prefix + param_name_to_check = node.this + + if param_name_to_check and param_name_to_check in merged_params: # merged_params is a dict here + final_params_seq.append(merged_params[param_name_to_check]) + return sqlglot_exp.Placeholder() # Anonymous placeholder '?' + return node + + transformed_expression = parsed_expression.transform(_convert_any_named_to_qmark, copy=True) + final_sql = transformed_expression.sql(dialect=target_dialect) + + elif isinstance(merged_params, (list, tuple)): + # Collect all types of placeholders from SQL + qmark_placeholders_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) + + # Named placeholders from sqlglot_exp.Parameter (e.g., @name, $name) + # sql_named_param_nodes is already defined + + # Named placeholders from sqlglot_exp.Placeholder (e.g., :name) + colon_named_placeholder_nodes = [ + p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and not p_node.this.isdigit() + ] + + # Numeric placeholders (e.g., $1, :1) - from both Parameter and Placeholder nodes + # numeric_placeholder_nodes and sql_numeric_nodes are already defined + + # Get all named parameters in order of appearance in the AST + ordered_named_params_in_ast = [] + # We need to iterate through the AST to get them in order. find_all gives traversal order. + for node in parsed_expression.find_all(sqlglot_exp.Parameter, sqlglot_exp.Placeholder): + if isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit(): + ordered_named_params_in_ast.append(node.name) + elif ( + isinstance(node, sqlglot_exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit() + ): + ordered_named_params_in_ast.append(node.this) + + # Remove duplicates while preserving order for mapping if needed (though duplicates might be intended by user in some complex SQLs) + # For now, let's assume unique placeholders for mapping tuple to names. If SQL has duplicate named params, + # this logic might need adjustment or clarification on expected behavior. + # A simpler approach for now: just count unique types. + + has_any_named_placeholders = bool(sql_named_param_nodes or colon_named_placeholder_nodes) + has_any_positional_or_numeric = bool( + qmark_placeholders_count or numeric_placeholder_nodes or sql_numeric_nodes ) - # Transpile SQL syntax if necessary for target dialect/param style - if actual_adbc_dialect in {"duckdb", "sqlite"}: - if actual_adbc_dialect == "duckdb": - msg = ( - f"ADBC (duckdb) PRE-TRANSPILE DictCase: SQL='{sql}', " - f"placeholder_prefix='{placeholder_prefix}', " - f"ordered_param_names='{ordered_param_names}', " - f"params_tuple='{params_tuple}'" - ) - logger.debug(msg) - try: - read_dialect_for_transpile = "duckdb" if placeholder_prefix == "$" else "mysql" - has_qmarks = any( - True - for m in QMARK_REGEX.finditer(sql) - if not (m.group("dquote") or m.group("squote") or m.group("comment")) and m.group("qmark") - ) + if has_any_named_placeholders: + if has_any_positional_or_numeric: + msg = f"ADBC ({target_dialect}): Sequence parameters provided, but SQL mixes named and positional/numeric placeholders. This is not supported." + raise ParameterStyleMismatchError(msg) - if not has_qmarks and ordered_param_names: - target_write_dialect = actual_adbc_dialect - msg = f"ADBC ({target_write_dialect}) DEBUG: Transpiling Dict Params. Read='{read_dialect_for_transpile}', Write='{target_write_dialect}'. SQL='{sql}'" - logger.debug(msg) - sql_to_execute = sqlglot.transpile( - sql, read=read_dialect_for_transpile, write=target_write_dialect, pretty=False - )[0] - msg = f"ADBC ({target_write_dialect}) DEBUG: Transpile Dict Result='{sql_to_execute}'" - logger.debug(msg) - elif has_qmarks: - sql_to_execute = sql - else: # No named params and no qmarks - sql_to_execute = sql - except Exception as e: - msg = ( - f"ADBC ({actual_adbc_dialect}): Failed to transpile SQL to 'qmark' style " - f"when using dictionary parameters. Error: {e}. Original SQL: {sql}" - ) - logger.warning(msg) - raise SQLParsingError(msg) from e - else: - # Transpile to the native style (e.g., @name for BQ). Use `args` to allow sqlglot type handling. - try: - sql_to_execute = sqlglot.transpile(sql, args=merged_params, write=actual_adbc_dialect)[0] - except Exception as e: # noqa: BLE001 - msg = f"ADBC ({actual_adbc_dialect}): Failed to transpile SQL to native style: {e}. Using original SQL. SQL: {sql}" - logger.warning(msg) - sql_to_execute = sql - - return sql_to_execute, params_tuple - - # --- Sequence/Scalar Parameters Handling --- - if isinstance(merged_params, (list, tuple)): - actual_adbc_dialect = self._get_dialect(self.connection) - colon_names = self._extract_colon_param_names(sql) - # Other named param styles are not typically mixed with sequence params by users for SQLite. - # We focus on :name for this special SQLite handling. - - if colon_names and actual_adbc_dialect == "sqlite": - # SQLite: SQL has :name, params are a tuple. Map them. - if len(colon_names) != len(merged_params): + # SQL has only named placeholders. Try to map sequence params to them by order. + # Re-extract ordered unique named parameter *names* for mapping. + # find_all preserves order. To get unique names in order: + unique_ordered_named_param_names = list( + dict.fromkeys(ordered_named_params_in_ast) + ) # Python 3.7+ dict preserves insertion order + + if len(unique_ordered_named_param_names) != len(merged_params): msg = ( - f"ADBC (sqlite): Tuple parameter count ({len(merged_params)}) does not match " - f"named placeholder count ({len(colon_names)}) in SQL: {sql}" + f"ADBC ({target_dialect}): Sequence parameters provided (count: {len(merged_params)}), " + f"but SQL has {len(unique_ordered_named_param_names)} unique named placeholders. Counts must match." ) raise SQLParsingError(msg) - # Parameters are already a tuple (merged_params) and in the correct order by convention. - # We just need to transpile the SQL. - try: - msg = f"ADBC (sqlite) DEBUG: Transpiling Tuple/Scalar. Read='mysql', Write='sqlite'. SQL='{sql}'" - logger.debug(msg) - sql_to_execute = sqlglot.transpile(sql, read="mysql", write="sqlite", pretty=False)[0] - msg = f"ADBC (sqlite) DEBUG: Transpile Tuple/Scalar Result='{sql_to_execute}'" - logger.debug(msg) - - # Return the transpiled SQL with the original parameters (as tuple) - # If execution reached here, merged_params must have been a list/tuple based on the outer check - return sql_to_execute, tuple(merged_params) - - except Exception as e: - # Determine original param type for error message more reliably - param_type_str = "tuple/list" if isinstance(parameters, (list, tuple)) else "unknown" - msg = ( - f"ADBC (sqlite): Failed to transpile SQL with :name to 'qmark' style " - f"when using {param_type_str} parameters. Error: {e}. Original SQL: {sql}" - ) - logger.exception(msg) - raise SQLParsingError(msg) from e - elif ( - colon_names - or self._extract_duckdb_dollar_param_names(sql) - or self._extract_bigquery_at_param_names(sql) - ): - # For other dialects, or if not SQLite with :name, this is a mismatch. - msg = f"ADBC: Sequence/tuple parameters provided, but SQL contains named placeholders (:name, $name, @name). SQL: {sql}" - raise ParameterStyleMismatchError(msg) - - # If no named placeholders were found, or if it's SQLite and we handled :name above, - # we assume the SQL is qmark or some other positional style compatible with the tuple. - return sql, tuple(merged_params) - # --- Scalar Parameters Handling (Separate Block) --- - if merged_params is not None and not isinstance(merged_params, (list, tuple, dict)): # type: ignore[unreachable] - actual_adbc_dialect = self._get_dialect(self.connection) # type: ignore[unreachable] - colon_names = self._extract_colon_param_names(sql) - - if colon_names and actual_adbc_dialect == "sqlite": - # SQLite: SQL has :name, param is scalar. - if len(colon_names) != 1: - msg = f"ADBC (sqlite): Scalar parameter provided, but SQL has {len(colon_names)} named placeholders (expected 1). SQL: {sql}" - raise SQLParsingError(msg) - # Parameter is scalar (merged_params). Wrap in a tuple. - # Transpile SQL. - try: - msg = f"ADBC (sqlite) DEBUG: Transpiling Scalar. Read='mysql', Write='sqlite'. SQL='{sql}'" - logger.debug(msg) - sql_to_execute = sqlglot.transpile(sql, read="mysql", write="sqlite", pretty=False)[0] - msg = f"ADBC (sqlite) DEBUG: Transpile Scalar Result='{sql_to_execute}'" - logger.debug(msg) - - except Exception as e: + # Create a temporary dict from named params and sequence values + temp_dict_params = dict(zip(unique_ordered_named_param_names, merged_params)) + + # Now, use the same transformation as the dict instance block + final_params_seq.clear() + + def _convert_any_named_to_qmark_for_seq(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: + param_name_to_check = None + if isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit(): + param_name_to_check = node.name + elif ( + isinstance(node, sqlglot_exp.Placeholder) + and isinstance(node.this, str) + and not node.this.isdigit() + ): + param_name_to_check = node.this + + if param_name_to_check and param_name_to_check in temp_dict_params: + final_params_seq.append(temp_dict_params[param_name_to_check]) + return sqlglot_exp.Placeholder() # Anonymous placeholder '?' + return node + + transformed_expression = parsed_expression.transform(_convert_any_named_to_qmark_for_seq, copy=True) + final_sql = transformed_expression.sql(dialect=target_dialect) + + elif has_any_positional_or_numeric: # SQL has only positional/numeric (or qmark) placeholders + final_sql = parsed_expression.sql( + dialect=target_dialect + ) # Ensure it's in target dialect form (e.g. ? -> $1) + expected_param_count = ( + qmark_placeholders_count + len(numeric_placeholder_nodes) + len(sql_numeric_nodes) + ) + if expected_param_count != len(merged_params): msg = ( - f"ADBC (sqlite): Failed to transpile SQL with :name to 'qmark' style " - f"when using a scalar parameter. Error: {e}. Original SQL: {sql}" + f"ADBC ({target_dialect}): Parameter count mismatch. SQL expects {expected_param_count} " + f"positional parameters, but {len(merged_params)} were provided. SQL: {sql}, Processed SQL: {final_sql}" ) - logger.exception(msg) - raise SQLParsingError(msg) from e - else: - return sql_to_execute, (merged_params,) # Return scalar wrapped in tuple - elif ( - colon_names - or self._extract_duckdb_dollar_param_names(sql) - or self._extract_bigquery_at_param_names(sql) - ): - # For other dialects, or if not SQLite with :name, this is a mismatch. - msg = f"ADBC: Scalar parameter provided, but SQL contains named placeholders. SQL: {sql}" + raise SQLParsingError(msg) + final_params_seq.extend(merged_params) + else: # No placeholders in SQL, but sequence params provided + if merged_params: # If params is not an empty tuple/list + msg = f"ADBC ({target_dialect}): Sequence parameters provided, but SQL has no placeholders." + raise SQLParsingError(msg) + # If merged_params is empty sequence and no placeholders, that's fine. + final_sql = sql # No transformation needed + # final_params_seq remains empty, which is correct + + elif merged_params is not None: # Scalar parameter + qmark_placeholders_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) + colon_named_placeholder_nodes = [ + p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and not p_node.this.isdigit() + ] + + total_named_placeholders = len(sql_named_param_nodes) + len(colon_named_placeholder_nodes) + total_positional_or_numeric_placeholders = ( + qmark_placeholders_count + len(numeric_placeholder_nodes) + len(sql_numeric_nodes) + ) + + if total_named_placeholders > 0 and total_positional_or_numeric_placeholders > 0: + # SQL mixes named and positional/numeric types, not allowed with scalar param. + msg = ( + f"ADBC ({target_dialect}): Scalar parameter provided, but SQL mixes named and positional/numeric " + f"placeholders. Use a single placeholder of one type." + ) raise ParameterStyleMismatchError(msg) - # If no named placeholders, or if it's SQLite and we handled :name, - # check for qmark count for scalar. - qmark_count = sum( - 1 - for m in QMARK_REGEX.finditer(sql) - if not (m.group("dquote") or m.group("squote") or m.group("comment")) and m.group("qmark") - ) - if qmark_count != 1: - msg = f"ADBC: Scalar parameter provided, but SQL contains {qmark_count} qmark ('?') placeholders (expected 1). SQL: {sql}" + if total_named_placeholders == 1 and total_positional_or_numeric_placeholders == 0: + # Case: Scalar param with exactly one NAMED placeholder (e.g., :name, @name) + final_params_seq.clear() + single_named_param_name = None + if sql_named_param_nodes: # @name style + single_named_param_name = sql_named_param_nodes[0].name + elif colon_named_placeholder_nodes: # :name style + single_named_param_name = colon_named_placeholder_nodes[0].this + + def _convert_the_one_named_to_qmark(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: + # This function assumes single_named_param_name is correctly identified + if (isinstance(node, sqlglot_exp.Parameter) and node.name == single_named_param_name) or ( + isinstance(node, sqlglot_exp.Placeholder) and node.this == single_named_param_name + ): + final_params_seq.append(merged_params) # Directly use scalar + return sqlglot_exp.Placeholder() # Anonymous placeholder '?' + return node + + transformed_expression = parsed_expression.transform(_convert_the_one_named_to_qmark, copy=True) + final_sql = transformed_expression.sql(dialect=target_dialect) + + elif total_positional_or_numeric_placeholders == 1 and total_named_placeholders == 0: + # Case: Scalar param with exactly one POSITIONAL/NUMERIC placeholder (e.g., ?, $1) + final_sql = parsed_expression.sql(dialect=target_dialect) # Ensure correct dialect form (e.g. ? -> $1) + final_params_seq.append(merged_params) + + elif total_named_placeholders == 0 and total_positional_or_numeric_placeholders == 0: + # Case: Scalar param, but SQL has NO placeholders at all. + msg = f"ADBC ({target_dialect}): Scalar parameter provided, but SQL has no parameter placeholders." raise SQLParsingError(msg) - return sql, (merged_params,) - # --- No Parameters Provided Validation --- - if merged_params is None: - has_placeholders = bool( - self._extract_colon_param_names(sql) - or self._extract_duckdb_dollar_param_names(sql) - or self._extract_bigquery_at_param_names(sql) - or any( - True - for m in QMARK_REGEX.finditer(sql) - if not (m.group("dquote") or m.group("squote") or m.group("comment")) and m.group("qmark") + else: + # Any other scenario: e.g. multiple named, multiple positional, etc. + msg = ( + f"ADBC ({target_dialect}): Scalar parameter provided, but SQL placeholder configuration is invalid. " + f"Found {total_named_placeholders} named and {total_positional_or_numeric_placeholders} positional/numeric placeholders. " + f"Expected exactly one placeholder of a consistent type for a scalar parameter." ) - ) - if has_placeholders: - msg = f"ADBC: SQL statement appears to contain parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) + raise ParameterStyleMismatchError(msg) + + else: + return sql, () - return sql, None # No parameters provided, and none found/needed + return final_sql, tuple(final_params_seq) @overload def select( diff --git a/sqlspec/adapters/aiosqlite/driver.py b/sqlspec/adapters/aiosqlite/driver.py index ffdae01..62066f8 100644 --- a/sqlspec/adapters/aiosqlite/driver.py +++ b/sqlspec/adapters/aiosqlite/driver.py @@ -3,12 +3,13 @@ from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload import aiosqlite +import sqlglot +from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX -from sqlspec.utils.text import bind_parameters +from sqlspec.statement import SQLStatement if TYPE_CHECKING: from collections.abc import AsyncGenerator, Sequence @@ -52,52 +53,169 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for aiosqlite driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters + # 1. Use SQLStatement for initial processing and validation + stmt = SQLStatement(sql, parameters, kwargs=kwargs) + original_sql, merged_params = stmt.process() # `process` returns original_sql and merged_params + + if merged_params is None: + return original_sql, None + + try: + parsed_expression = sqlglot.parse_one(original_sql, read=self.dialect) + except Exception as e: + msg = f"aiosqlite: Failed to re-parse SQL with sqlglot after SQLStatement validation: {e}. SQL: {original_sql}" + raise SQLParsingError(msg) from e + + final_sql: str = original_sql + final_params_tuple: Optional[tuple[Any, ...]] = None - # Use bind_parameters for named parameters if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="sqlite") - return final_sql, final_params - - # Case 2: Sequence parameters - pass through - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar parameter - wrap in tuple - if merged_params is not None: - return sql, (merged_params,) # type: ignore[unreachable] - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in QMARK_REGEX.finditer(sql): - if match.group("qmark"): - has_placeholders = True + actual_named_placeholders_in_ast: dict[str, Union[exp.Parameter, exp.Placeholder]] = {} + has_true_qmark_placeholders = False + + for node in parsed_expression.find_all(exp.Placeholder, exp.Parameter): + if isinstance(node, exp.Parameter) and node.name and not node.name.isdigit(): + actual_named_placeholders_in_ast[node.name] = node + elif isinstance(node, exp.Placeholder) and node.this and not node.this.isdigit(): # :name + actual_named_placeholders_in_ast[node.this] = node + elif isinstance(node, exp.Placeholder) and node.this is None: # ? + has_true_qmark_placeholders = True + + if has_true_qmark_placeholders: + msg = "aiosqlite: Dictionary parameters provided, but SQL uses '?' placeholders. Use named placeholders (e.g., :name)." + raise ParameterStyleMismatchError(msg) + + if not actual_named_placeholders_in_ast and merged_params: + # If merged_params is not empty and no named placeholders found. + msg = "aiosqlite: Dictionary parameters provided, but no recognizable named placeholders found in SQL." + raise ParameterStyleMismatchError(msg) + if not actual_named_placeholders_in_ast and not merged_params: + # Empty dict params and no named placeholders, this is fine, but should have been caught by merged_params is None earlier if truly no params. + # If merged_params is an empty dict, it implies user intended named params but provided none. + # However, if SQL also has no named params, it could be a query without params. + # This path should be less common due to the `merged_params is None` check. + pass # Allowing empty dict with SQL that has no named params found by sqlglot. + + sql_param_names_in_ast = set(actual_named_placeholders_in_ast.keys()) + provided_keys = set(merged_params.keys()) + + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"aiosqlite: Named parameters {missing_keys} found in SQL but not provided. SQL: {original_sql}" + raise SQLParsingError(msg) + + extra_keys = provided_keys - sql_param_names_in_ast + if extra_keys: + logger.warning( + f"aiosqlite: Parameters {extra_keys} provided but not found in SQL. They will be ignored. SQL: {original_sql}" + ) + + ordered_param_values: list[Any] = [] + + def _convert_named_to_qmark(node_transform: exp.Expression) -> exp.Expression: + param_name = None + if ( + isinstance(node_transform, exp.Parameter) + and node_transform.name + and not node_transform.name.isdigit() + ): + param_name = node_transform.name + elif ( + isinstance(node_transform, exp.Placeholder) + and node_transform.this + and not node_transform.this.isdigit() + ): + param_name = node_transform.this + + if param_name and param_name in merged_params: + ordered_param_values.append(merged_params[param_name]) + return exp.Placeholder() # Represents '?' + return node_transform + + transformed_expression = parsed_expression.transform(_convert_named_to_qmark, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) + final_params_tuple = tuple(ordered_param_values) + + elif isinstance(merged_params, (list, tuple)): + # Logic for sequence parameters (should be largely correct now thanks to SQLStatement updates) + # SQLStatement already validated that if sequence params are given, SQL doesn't have named placeholders. + # It also validated counts if it could parse qmarks. The main task here is to ensure dialect-specific SQL. + sql_placeholder_nodes = list( + parsed_expression.find_all(exp.Placeholder) + ) # Re-fetch for this block if needed + sql_numeric_param_nodes = [ # Simplified numeric detection for sqlite context, primarily expecting ? + node + for node in parsed_expression.find_all(exp.Parameter) + if (node.name and node.name.isdigit()) + or (not node.name and node.this and isinstance(node.this, str) and node.this.isdigit()) + ] + qmark_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) + numeric_count = len(sql_numeric_param_nodes) + # For aiosqlite (sqlite), we primarily expect '?' (qmark). $N is not native. + # SQLStatement should have validated this. If SQL had $N, it should be an error from SQLStatement if dialect is sqlite. + # Here, we just ensure final SQL is in '?' form if it wasn't already. + + # This check is somewhat redundant if SQLStatement.process() worked correctly. + # It should have raised ParameterStyleMismatchError if named params were in SQL with sequence input. + has_named_placeholders_in_ast = False + for node in parsed_expression.find_all(exp.Placeholder, exp.Parameter): + if (isinstance(node, exp.Parameter) and node.name and not node.name.isdigit()) or ( + isinstance(node, exp.Placeholder) and node.this and not node.this.isdigit() + ): + has_named_placeholders_in_ast = True + break + if has_named_placeholders_in_ast: + msg = f"aiosqlite: Sequence parameters provided, but SQL unexpectedly contains named placeholders after SQLStatement validation. SQL: {original_sql}" + raise ParameterStyleMismatchError(msg) + + expected_qmarks = qmark_count + numeric_count # Should primarily be qmark_count for sqlite + if expected_qmarks != len(merged_params): + # This might indicate SQLStatement's regex fallback was used and sqlglot count differs. + # Or, the SQL is malformed in a way that bypasses SQLStatement's initial validation for sequence params. + msg = ( + f"aiosqlite: Parameter count mismatch after SQLStatement validation. " + f"SQL (re-parsed) expects {expected_qmarks} positional placeholders, but {len(merged_params)} were provided. SQL: {original_sql}" + ) + # Check if SQLStatement validation should have caught this. This is more of an internal consistency check. + logger.warning(msg) # Log as warning, as SQLStatement might have allowed it based on regex. + # If we proceed, it might lead to runtime errors from aiosqlite. For now, we proceed with params as is. + + final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures '?' for sqlite + final_params_tuple = tuple(merged_params) + + elif merged_params is not None: # Scalar parameter + # Similar to sequence, SQLStatement should have validated this. + # Expecting one 'qmark' placeholder. + sql_placeholder_nodes = list(parsed_expression.find_all(exp.Placeholder)) # Re-fetch for this block + sql_numeric_param_nodes = [ # Simplified numeric detection for sqlite context + node + for node in parsed_expression.find_all(exp.Parameter) + if (node.name and node.name.isdigit()) + or (not node.name and node.this and isinstance(node.this, str) and node.this.isdigit()) + ] + qmark_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) + numeric_count = len(sql_numeric_param_nodes) + + has_named_placeholders_in_ast = False + for node in parsed_expression.find_all(exp.Placeholder, exp.Parameter): + if (isinstance(node, exp.Parameter) and node.name and not node.name.isdigit()) or ( + isinstance(node, exp.Placeholder) and node.this and not node.this.isdigit() + ): + has_named_placeholders_in_ast = True break + if has_named_placeholders_in_ast: + msg = f"aiosqlite: Scalar parameter provided, but SQL unexpectedly contains named placeholders after SQLStatement validation. SQL: {original_sql}" + raise ParameterStyleMismatchError(msg) + + expected_qmarks = qmark_count + numeric_count + if expected_qmarks != 1: + msg = f"aiosqlite: Scalar parameter provided, but SQL (re-parsed) expects {expected_qmarks} positional placeholders (expected 1). SQL: {original_sql}" + raise SQLParsingError(msg) + + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params_tuple = (merged_params,) - if has_placeholders: - msg = f"aiosqlite: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + return final_sql, final_params_tuple # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/asyncmy/driver.py b/sqlspec/adapters/asyncmy/driver.py index 3581c6e..5df44c9 100644 --- a/sqlspec/adapters/asyncmy/driver.py +++ b/sqlspec/adapters/asyncmy/driver.py @@ -4,13 +4,13 @@ from contextlib import asynccontextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot from asyncmy import Connection +from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX -from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from asyncmy.cursors import Cursor @@ -53,7 +53,7 @@ def _process_sql_params( **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None if kwargs: if isinstance(parameters, dict): @@ -64,42 +64,170 @@ def _process_sql_params( else: merged_params = kwargs elif parameters is not None: - merged_params = parameters # type: ignore + merged_params = parameters # type: ignore[assignment] + # else merged_params remains None + + # Check if the SQL contains MySQL format placeholders (%s) + # If so, we'll use a simpler approach rather than SQLGlot parsing + # as SQLGlot doesn't correctly handle %s parameters (treats them as modulo operations) + format_placeholders_count = sql.count("%s") + + if format_placeholders_count > 0: + # Simple MySQL format placeholder handling + if merged_params is None: + if format_placeholders_count > 0: + msg = f"asyncmy: SQL statement contains {format_placeholders_count} format placeholders ('%s'), but no parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + return sql, None + + if isinstance(merged_params, (list, tuple)): + if len(merged_params) != format_placeholders_count: + msg = f"asyncmy: Parameter count mismatch. SQL expects {format_placeholders_count} '%s' placeholders, but {len(merged_params)} parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) + # MySQL/asyncmy uses %s for format placeholders, so we can just pass the SQL as-is + return sql, tuple(merged_params) + + if isinstance(merged_params, dict): + msg = "asyncmy: Dictionary parameters provided with '%s' placeholders. MySQL format placeholders require tuple/list parameters." + raise ParameterStyleMismatchError(msg) - # Use bind_parameters for named parameters - if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="mysql") - return final_sql, final_params - - # Case 2: Sequence parameters - pass through - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar parameter - wrap in tuple - if merged_params is not None: + # Scalar parameter + if format_placeholders_count != 1: + msg = f"asyncmy: Scalar parameter provided, but SQL expects {format_placeholders_count} '%s' placeholders. Expected 1. SQL: {sql}" + raise SQLParsingError(msg) return sql, (merged_params,) - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - has_placeholders = True - break - - if has_placeholders: - msg = f"asyncmy: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + # Continue with SQLGlot parsing for non-%s cases (like ? or named parameters) + try: + # self.dialect is "mysql" + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + # If parsing fails but we have %s placeholders, it might be due to SQLGlot not handling %s correctly + # In this case, use the simple approach for format placeholders + if format_placeholders_count > 0: + if merged_params is None: + return sql, None + + if isinstance(merged_params, (list, tuple)): + if len(merged_params) != format_placeholders_count: + msg = f"asyncmy: Parameter count mismatch. SQL expects {format_placeholders_count} '%s' placeholders, but {len(merged_params)} parameters were provided. SQL: {sql}" + raise SQLParsingError(msg) from e + return sql, tuple(merged_params) + + if isinstance(merged_params, dict): + msg = "asyncmy: Dictionary parameters provided with '%s' placeholders. MySQL format placeholders require tuple/list parameters." + raise ParameterStyleMismatchError(msg) from e + + # Scalar parameter + if format_placeholders_count != 1: + msg = f"asyncmy: Scalar parameter provided, but SQL expects {format_placeholders_count} '%s' placeholders. Expected 1. SQL: {sql}" + raise SQLParsingError(msg) from e + return sql, (merged_params,) + # If no %s placeholders, then it's a genuine SQLGlot parsing error + msg = f"asyncmy: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # From here, we're handling named parameters or ? placeholders only + # exp.Parameter with .name for :name, @name, etc. + # exp.Placeholder for '?'. + sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] + sql_placeholder_nodes = list(parsed_expression.find_all(exp.Placeholder)) + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or sql_placeholder_nodes: + placeholder_types = set() + if sql_named_param_nodes: + placeholder_types.add("named (e.g., :name)") + if sql_placeholder_nodes: + placeholder_types.add("positional ('?')") + msg = ( + f"asyncmy: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + return sql, None # asyncmy can take None + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None + # asyncmy execute takes `args: Any | tuple[Any, ...] | list[Any] | dict[str, Any] | None` + # We will aim to return a tuple for sequence/scalar, or dict for named (if driver supports it natively and sql matches) + # However, for consistency and to ensure broad compatibility if asyncmy prefers one over other internally for qmark, let's convert named to qmark/tuple. + + if isinstance(merged_params, dict): + # Dictionary parameters. Convert to qmark style for asyncmy. + if sql_placeholder_nodes: + msg = "asyncmy: Dictionary parameters provided, but SQL uses positional placeholders ('?'). Use named placeholders (e.g., :name)." + raise ParameterStyleMismatchError(msg) + + if not sql_named_param_nodes: + msg = "asyncmy: Dictionary parameters provided, but no named placeholders (e.g., :name) found by sqlglot to convert to '?'." + raise ParameterStyleMismatchError(msg) + + ordered_param_values: list[Any] = [] + sql_param_names_in_ast = {node.name for node in sql_named_param_nodes if node.name} + provided_keys = set(merged_params.keys()) + + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"asyncmy: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" + raise SQLParsingError(msg) + + extra_keys = provided_keys - sql_param_names_in_ast + if extra_keys: + logger.warning( + f"asyncmy: Parameters {extra_keys} provided but not found in SQL. They will be ignored during qmark conversion. SQL: {sql}" + ) + + def _convert_named_to_qmark(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Parameter) and node.name: + param_name = node.name + if param_name in merged_params: # type: ignore[operator] + ordered_param_values.append(merged_params[param_name]) # type: ignore[index] + return exp.Placeholder() # Represents '?' for MySQL dialect generation + return node + + transformed_expression = parsed_expression.transform(_convert_named_to_qmark, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) # MySQL dialect makes '?' + final_params = tuple(ordered_param_values) + + elif isinstance(merged_params, (list, tuple)): + # Sequence parameters. SQL should use '?' + if sql_named_param_nodes: + msg = "asyncmy: Sequence parameters provided, but SQL contains named placeholders. Use '?'." + raise ParameterStyleMismatchError(msg) + + expected_param_count = len(sql_placeholder_nodes) + if expected_param_count != len(merged_params): + msg = ( + f"asyncmy: Parameter count mismatch. SQL expects {expected_param_count} positional placeholders ('?'), " + f"but {len(merged_params)} were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = tuple(merged_params) + + elif merged_params is not None: # Scalar parameter + if sql_named_param_nodes: + msg = "asyncmy: Scalar parameter provided, but SQL uses named placeholders. Use a single '?'." + raise ParameterStyleMismatchError(msg) + + expected_param_count = len(sql_placeholder_nodes) + if expected_param_count != 1: + msg = ( + f"asyncmy: Scalar parameter provided, but SQL expects {expected_param_count} positional placeholders. " + f"Expected 1. SQL: {sql}" + ) + raise SQLParsingError(msg) + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = (merged_params,) + + else: # Should be caught by 'merged_params is None' earlier + final_sql = sql + final_params = None + + return final_sql, final_params # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/asyncpg/driver.py b/sqlspec/adapters/asyncpg/driver.py index c5f83d9..0f5184b 100644 --- a/sqlspec/adapters/asyncpg/driver.py +++ b/sqlspec/adapters/asyncpg/driver.py @@ -2,13 +2,15 @@ import re from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot from asyncpg import Connection +from sqlglot import exp from typing_extensions import TypeAlias from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX +from sqlspec.statement import SQLStatement if TYPE_CHECKING: from collections.abc import Sequence @@ -40,173 +42,141 @@ class AsyncpgDriver( def __init__(self, connection: "AsyncpgConnection") -> None: self.connection = connection - def _process_sql_params( # noqa: PLR0912, PLR0915 + def _process_sql_params( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None - merged_params_type: Optional[type] = None - - if kwargs: - merged_params_type = dict - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for asyncpg driver." + # First, use SQLStatement for parameter validation + statement = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs) + sql, validated_params = statement.process() + + if validated_params is None: + return sql, () # asyncpg expects an empty tuple for no params + + # Now use SQLGlot for PostgreSQL-specific parameter handling + try: + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"asyncpg: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Find different types of parameter nodes in the AST + # Traditional named parameters (e.g., @name, $name) + sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] + + # For PostgreSQL dialect, ':name' gets parsed as Placeholder with this='name' + colon_named_placeholder_nodes = [ + node + for node in parsed_expression.find_all(exp.Placeholder) + if isinstance(node.this, str) and not node.this.isdigit() + ] + + # Anonymous placeholders (?) + question_mark_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] + + # PostgreSQL-specific dollar-numeric parameters like $1, $2 + sql_numeric_dollar_nodes = [ + node + for node in parsed_expression.find_all(exp.Parameter) + if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() + ] + + final_params_seq = [] + + if isinstance(validated_params, dict): + # Dictionary parameters - convert named parameters to PostgreSQL style ($n) + if question_mark_nodes or sql_numeric_dollar_nodes: + msg = "asyncpg: Dictionary parameters provided, but SQL uses positional placeholders. Use named placeholders (e.g., :name)." raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params_type = type(parameters) - # Preserve original type (dict, list, tuple, scalar) for now - merged_params = parameters - - # 2. Process based on merged parameter type - - # Case 0: No parameters provided - if merged_params_type is None: - # Basic validation: Check if SQL contains placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - has_placeholders = True - break - - if has_placeholders: - msg = f"asyncpg: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, () # asyncpg expects a sequence, even if empty - - # Case 1: Parameters are effectively a dictionary - if merged_params_type is dict: - parameter_dict = cast("dict[str, Any]", merged_params) - processed_sql_parts: list[str] = [] - ordered_params = [] - last_end = 0 - param_index = 1 - found_params_regex: list[str] = [] - has_qmark = False - - # Check for qmarks first, as they are invalid with dict params - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - has_qmark = True - break - if has_qmark: + + # With PostgreSQL dialect, :name is parsed as Placeholder, not Parameter + if not sql_named_param_nodes and not colon_named_placeholder_nodes: + msg = "asyncpg: Dictionary parameters provided, but no named placeholders found in SQL by sqlglot." + raise ParameterStyleMismatchError(msg) + + # Transform both types of named parameters to $n placeholders + def _convert_named_to_dollar(node: exp.Expression) -> exp.Expression: + param_name = None + if isinstance(node, exp.Parameter) and node.name: + param_name = node.name + elif isinstance(node, exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit(): + param_name = node.this + + if param_name and param_name in validated_params: + final_params_seq.append(validated_params[param_name]) + # Create a Parameter node that PostgreSQL will interpret as a positional parameter ($n) + # The position is determined by the order in final_params_seq + return exp.Parameter(this=str(len(final_params_seq))) + return node + + transformed_expression = parsed_expression.transform(_convert_named_to_dollar, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) + + elif hasattr(validated_params, "__iter__") and not isinstance(validated_params, (str, bytes, dict)): + # Sequence parameters (list or tuple) + if sql_named_param_nodes or colon_named_placeholder_nodes: msg = ( - f"asyncpg: Cannot use dictionary parameters with positional placeholders ('?') found in SQL: {sql}" + "asyncpg: Sequence parameters provided, but SQL contains named placeholders. Use '?' placeholders." ) raise ParameterStyleMismatchError(msg) - # Manually parse the *original* SQL for :name -> $n conversion - for match in PARAM_REGEX.finditer(sql): - # Skip matches inside quotes or comments - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("var_name"): # Finds :var_name - var_name = match.group("var_name") - found_params_regex.append(var_name) - start = match.start("var_name") - 1 # Include the ':' - end = match.end("var_name") - - if var_name not in parameter_dict: - msg = f"asyncpg: Named parameter ':{var_name}' found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - processed_sql_parts.extend((sql[last_end:start], f"${param_index}")) - ordered_params.append(parameter_dict[var_name]) - last_end = end - param_index += 1 - - processed_sql_parts.append(sql[last_end:]) - final_sql = "".join(processed_sql_parts) - - # Validation - if not found_params_regex and parameter_dict: - msg = f"asyncpg: Dictionary parameters provided, but no named placeholders (:name) found. SQL: {sql}" - raise ParameterStyleMismatchError(msg) # Or log warning? - - provided_keys = set(parameter_dict.keys()) - required_keys = set(found_params_regex) - missing_keys = required_keys - provided_keys - if missing_keys: - msg = f"asyncpg: Named parameters found in SQL ({required_keys}) but not provided: {missing_keys}. SQL: {sql}" + # Count placeholders for validation + total_placeholders = len(question_mark_nodes) + len(sql_numeric_dollar_nodes) + if total_placeholders != len(validated_params): + msg = ( + f"asyncpg: Parameter count mismatch. SQL expects {total_placeholders} placeholders, " + f"but {len(validated_params)} parameters were provided. SQL: {sql}" + ) raise SQLParsingError(msg) - # Allow extra keys - return final_sql, tuple(ordered_params) - - # Case 2: Parameters are a sequence or scalar (? style) - if isinstance(merged_params, (list, tuple)): - params_tuple = tuple(merged_params) - final_sql, expected_params = self._convert_qmarks_to_dollar(sql) - actual_params = len(params_tuple) + # For PostgreSQL, convert ? to $n + def _convert_qmark_to_dollar(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Placeholder) and node.this is None: + position = len(final_params_seq) + 1 # PostgreSQL positions are 1-indexed + final_params_seq.append(validated_params[position - 1]) + return exp.Parameter(this=str(position)) + return node + + transformed_expression = parsed_expression.transform(_convert_qmark_to_dollar, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) + + # If we didn't add any parameters via transformation (e.g., SQL already uses $n style), + # just add all parameters in order + if not final_params_seq and validated_params: + final_params_seq.extend(validated_params) + + else: # Scalar parameter + if sql_named_param_nodes or colon_named_placeholder_nodes: + msg = "asyncpg: Scalar parameter provided, but SQL contains named placeholders. Use a '?' placeholder." + raise ParameterStyleMismatchError(msg) - if expected_params != actual_params: + total_placeholders = len(question_mark_nodes) + len(sql_numeric_dollar_nodes) + if total_placeholders != 1: msg = ( - f"asyncpg: Parameter count mismatch. SQL requires {expected_params} positional parameters ($n), " - f"but {actual_params} were provided. Processed SQL: {final_sql}" + f"asyncpg: Scalar parameter provided, but SQL expects {total_placeholders} placeholders. " + f"Expected exactly 1. SQL: {sql}" ) raise SQLParsingError(msg) - return final_sql, params_tuple - # Scalar - scalar_param_tuple = (merged_params,) - final_sql, expected_params = self._convert_qmarks_to_dollar(sql) - if expected_params != 1: - msg = ( - f"asyncpg: Parameter count mismatch. SQL requires {expected_params} positional parameters ($n), " - f"but 1 (scalar) was provided. Processed SQL: {final_sql}" - ) - raise SQLParsingError(msg) - return final_sql, scalar_param_tuple - - @staticmethod - def _convert_qmarks_to_dollar(sql: str) -> tuple[str, int]: - """Converts '?' placeholders to '$n' and counts them. + # Convert single ? to $1 + def _convert_single_qmark_to_dollar(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Placeholder) and node.this is None: + final_params_seq.append(validated_params) + return exp.Parameter(this="1") + return node - Args: - sql (str): The SQL string to process. + transformed_expression = parsed_expression.transform(_convert_single_qmark_to_dollar, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) - Returns: - tuple[str, int]: A tuple containing the processed SQL string and the number of '?' placeholders found. - """ - processed_parts: list[str] = [] - param_index = 1 - last_end = 0 - qmark_found_count = 0 - - for match in QMARK_REGEX.finditer(sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("qmark"): - qmark_found_count += 1 - start = match.start("qmark") - end = match.end("qmark") - processed_parts.extend((sql[last_end:start], f"${param_index}")) - last_end = end - param_index += 1 - - processed_parts.append(sql[last_end:]) - final_sql = "".join(processed_parts) - return final_sql, qmark_found_count + # If we didn't add the parameter via transformation (e.g., SQL already uses $1), + # add it directly + if not final_params_seq: + final_params_seq.append(validated_params) + + return final_sql, tuple(final_params_seq) @overload async def select( @@ -254,7 +224,7 @@ async def select( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () results = await connection.fetch(sql, *parameters) # pyright: ignore if not results: @@ -309,7 +279,7 @@ async def select_one( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () result = await connection.fetchrow(sql, *parameters) # pyright: ignore result = self.check_not_found(result) @@ -364,7 +334,7 @@ async def select_one_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () result = await connection.fetchrow(sql, *parameters) # pyright: ignore if result is None: return None @@ -419,7 +389,7 @@ async def select_value( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () result = await connection.fetchval(sql, *parameters) # pyright: ignore result = self.check_not_found(result) if schema_type is None: @@ -465,7 +435,7 @@ async def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () result = await connection.fetchval(sql, *parameters) # pyright: ignore if result is None: return None @@ -495,7 +465,7 @@ async def insert_update_delete( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () result = await connection.execute(sql, *parameters) # pyright: ignore # asyncpg returns e.g. 'INSERT 0 1', 'UPDATE 0 2', etc. match = ROWCOUNT_REGEX.match(result) @@ -549,7 +519,7 @@ async def insert_update_delete_returning( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () result = await connection.fetchrow(sql, *parameters) # pyright: ignore if result is None: return None @@ -579,7 +549,7 @@ async def execute_script( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - parameters = parameters if parameters is not None else {} + parameters = parameters if parameters is not None else () return await connection.execute(sql, *parameters) # pyright: ignore def _connection(self, connection: "Optional[AsyncpgConnection]" = None) -> "AsyncpgConnection": diff --git a/sqlspec/adapters/bigquery/driver.py b/sqlspec/adapters/bigquery/driver.py index 54f3517..9e0df1a 100644 --- a/sqlspec/adapters/bigquery/driver.py +++ b/sqlspec/adapters/bigquery/driver.py @@ -18,6 +18,7 @@ from google.cloud.bigquery import Client from google.cloud.bigquery.job import QueryJob, QueryJobConfig from google.cloud.exceptions import NotFound +from sqlglot import exp from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import NotFoundError, ParameterStyleMismatchError, SQLParsingError, SQLSpecError @@ -26,9 +27,7 @@ SyncArrowBulkOperationsMixin, SyncParquetExportMixin, ) -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T -from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from google.cloud.bigquery import SchemaField @@ -117,52 +116,118 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + """Process SQL and parameters for BigQuery using sqlglot for parsing and validation. + + BigQuery uses named (@name) or positional (?) parameters. + This method merges input parameters, validates them against the parsed SQL structure, + and returns the SQL (potentially normalized by sqlglot) and merged parameters. + Actual creation of BigQuery QueryParameter objects is handled later. + """ # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar if kwargs: if isinstance(parameters, dict): merged_params = {**parameters, **kwargs} elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for bigquery driver." + msg = "Cannot mix positional parameters with keyword arguments for BigQuery driver." raise ParameterStyleMismatchError(msg) else: merged_params = kwargs elif parameters is not None: merged_params = parameters + # else merged_params remains None + + # 2. SQLGlot Parsing + try: + # self.dialect is "bigquery" + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"bigquery: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Identify parameter types from AST + # BigQuery's @name are exp.Parameter with a name. '?' are exp.Placeholder. + sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] + sql_placeholder_nodes = list(parsed_expression.find_all(exp.Placeholder)) + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or sql_placeholder_nodes: + placeholder_types = set() + if sql_named_param_nodes: + placeholder_types.add("named (e.g., @name)") + if sql_placeholder_nodes: + placeholder_types.add("positional ('?')") + msg = ( + f"bigquery: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + # Return original SQL if no params and no placeholders found by sqlglot + # _run_query_job may still transpile it if not a script. + return sql, None + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None + + # Generate SQL using BigQuery dialect. This normalizes syntax if input was, e.g. :name. + # The actual BQ param objects are created in _run_query_job. + final_sql = parsed_expression.sql(dialect=self.dialect) - # Use bind_parameters for named parameters if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="bigquery") - return final_sql, final_params - - # Case 2: Sequence parameters - pass through - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar parameter - wrap in tuple - if merged_params is not None: - return sql, (merged_params,) # type: ignore[unreachable] - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in QMARK_REGEX.finditer(sql): - if match.group("qmark"): - has_placeholders = True - break - - if has_placeholders: - msg = f"bigquery: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + if sql_placeholder_nodes: + msg = "bigquery: Dictionary parameters provided, but SQL uses positional '?' placeholders. Use named @params." + raise ParameterStyleMismatchError(msg) + if not sql_named_param_nodes and not any(f"@{key}" in sql for key in merged_params): + # If sqlglot found no :name (common input) or @name (native BQ) + # and the raw SQL doesn't contain @key for the provided dict keys. + msg = "bigquery: Dictionary parameters provided, but no recognizable named placeholders (e.g., @name or :name) found." + raise ParameterStyleMismatchError(msg) + + # Validate keys only if sqlglot identified specific named parameters from a known style like :name + if sql_named_param_nodes: + sql_param_names_in_ast = {node.name for node in sql_named_param_nodes if node.name} + provided_keys = set(merged_params.keys()) + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"bigquery: Named parameters {missing_keys} (from :name style) found in SQL but not provided. SQL: {sql}" + raise SQLParsingError(msg) + extra_keys = provided_keys - sql_param_names_in_ast + if extra_keys: + msg = f"bigquery: Parameters {extra_keys} provided but not found as :name style in SQL. Ensure they match @name style if used. SQL: {sql}" + logger.warning(msg) + final_params = merged_params # Pass dict; _run_query_job will make BQ params + + elif isinstance(merged_params, (list, tuple)): + if sql_named_param_nodes: + msg = "bigquery: Sequence parameters provided, but SQL uses named placeholders. Use '?' placeholders." + raise ParameterStyleMismatchError(msg) + + if len(sql_placeholder_nodes) != len(merged_params): + msg = ( + f"bigquery: Parameter count mismatch. SQL expects {len(sql_placeholder_nodes)} '?' placeholders, " + f"but {len(merged_params)} were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + final_params = tuple(merged_params) + + elif merged_params is not None: # Scalar parameter + if sql_named_param_nodes: + msg = "bigquery: Scalar parameter provided, but SQL uses named placeholders. Use a single '?'." + raise ParameterStyleMismatchError(msg) + if len(sql_placeholder_nodes) != 1: + msg = ( + f"bigquery: Scalar parameter provided, but SQL expects {len(sql_placeholder_nodes)} '?' placeholders. " + f"Expected 1. SQL: {sql}" + ) + raise SQLParsingError(msg) + final_params = (merged_params,) + + else: # Should be caught by 'merged_params is None' earlier + final_params = None # Should align with the `return sql, None` path earlier + + return final_sql, final_params def _run_query_job( # noqa: PLR0912, PLR0915 (User change) self, diff --git a/sqlspec/adapters/duckdb/driver.py b/sqlspec/adapters/duckdb/driver.py index acf3355..61f9f64 100644 --- a/sqlspec/adapters/duckdb/driver.py +++ b/sqlspec/adapters/duckdb/driver.py @@ -2,14 +2,14 @@ from contextlib import contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot from duckdb import DuckDBPyConnection +from sqlglot import exp from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, StatementParameterType -from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import Generator, Sequence @@ -63,23 +63,12 @@ def _process_sql_params( ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters for DuckDB. - DuckDB supports both named (:name) and positional (?) parameters. - This method merges parameters and validates them. - - Args: - sql: The SQL statement to process. - parameters: The parameters to process. - **kwargs: Additional keyword arguments. - - Raises: - ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. - SQLParsingError: If SQL contains parameter placeholders, but no parameters were provided. - - Returns: - A tuple of the processed SQL and parameters. + DuckDB supports both named (:name, $name) and positional (?) parameters. + This method merges parameters, validates them, and ensures SQL is in a + consistent format for the duckdb driver using sqlglot. """ # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar if kwargs: if isinstance(parameters, dict): @@ -91,38 +80,141 @@ def _process_sql_params( merged_params = kwargs elif parameters is not None: merged_params = parameters + # else merged_params remains None + + # Special case: if merged_params is an empty dict, treat it as None for parameterless queries + if isinstance(merged_params, dict) and not merged_params: + merged_params = None + + # 2. SQLGlot Parsing + try: + # self.dialect is "duckdb" + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"duckdb: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Traditional named parameters (e.g., @name, $name) parsed as Parameter nodes + sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] + + # Named placeholders parsed as Placeholder nodes (e.g., :name, $name in some dialects) + named_placeholder_nodes = [ + node + for node in parsed_expression.find_all(exp.Placeholder) + if isinstance(node.this, str) and not node.this.isdigit() + ] + + # Anonymous placeholders (?) parsed as Placeholder nodes with this=None + qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] + + # DuckDB also uses $N for positional, sqlglot might parse these as exp.Parameter without name and numeric .this + sql_dollar_numeric_nodes = [ + node + for node in parsed_expression.find_all(exp.Parameter) + if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() + ] + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes or sql_dollar_numeric_nodes: + placeholder_types = set() + if sql_named_param_nodes or named_placeholder_nodes: + placeholder_types.add("named (e.g., :name, $name)") + if qmark_placeholder_nodes: + placeholder_types.add("qmark ('?')") + if sql_dollar_numeric_nodes: + placeholder_types.add("numeric ($N)") + msg = ( + f"duckdb: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + return sql, None # DuckDB can take None + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - # Use bind_parameters for named parameters if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="duckdb") - return final_sql, final_params - - # Case 2: Sequence parameters - pass through - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar parameter - wrap in tuple - if merged_params is not None: - return sql, (merged_params,) # type: ignore[unreachable] - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - for match in QMARK_REGEX.finditer(sql): - if match.group("qmark"): - has_placeholders = True - break - - if has_placeholders: - msg = f"duckdb: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + # Dictionary parameters. DuckDB client handles :name and $name if SQL uses them. + # sqlglot's "duckdb" dialect should preserve/generate these. + if qmark_placeholder_nodes or sql_dollar_numeric_nodes: + msg = "duckdb: Dictionary parameters provided, but SQL uses positional placeholders ('?' or $N). Use named placeholders." + raise ParameterStyleMismatchError(msg) + + if not sql_named_param_nodes and not named_placeholder_nodes: + msg = "duckdb: Dictionary parameters provided, but no named placeholders (e.g., :name, $name) found by sqlglot." + raise ParameterStyleMismatchError(msg) + + # Collect parameter names from both types of nodes + sql_param_names_in_ast = set() + + # Get names from Parameter nodes + sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) + + # Get names from Placeholder nodes + sql_param_names_in_ast.update(node.this for node in named_placeholder_nodes if isinstance(node.this, str)) + + provided_keys = set(merged_params.keys()) + + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"duckdb: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" + raise SQLParsingError(msg) + + extra_keys = provided_keys - sql_param_names_in_ast + if extra_keys: + logger.warning( + f"duckdb: Parameters {extra_keys} provided but not found in SQL. DuckDB might ignore them. SQL: {sql}" + ) + + # Generate SQL with duckdb dialect to ensure consistent named param style if input was varied. + # e.g. if input was :name, output for duckdb might be $name or vice-versa, sqlglot handles this. + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = merged_params # Pass the dict directly to DuckDB + + elif isinstance(merged_params, (list, tuple)): + # Sequence parameters. DuckDB uses '?'. + # sqlglot's "duckdb" dialect should generate '?' from exp.Placeholder. + if sql_named_param_nodes or named_placeholder_nodes: + msg = ( + "duckdb: Sequence parameters provided, but SQL uses named placeholders. Use '?' or $N placeholders." + ) + raise ParameterStyleMismatchError(msg) + + # If SQL already has $N, it's a mismatch for unnamed sequence params + if sql_dollar_numeric_nodes: + msg = "duckdb: Sequence parameters provided, but SQL uses $N style. Use '?' placeholders for unnamed sequences." + raise ParameterStyleMismatchError(msg) + + if len(qmark_placeholder_nodes) != len(merged_params): + msg = ( + f"duckdb: Parameter count mismatch. SQL expects {len(qmark_placeholder_nodes)} '?' placeholders, " + f"but {len(merged_params)} were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + + final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures qmark style from placeholders + final_params = tuple(merged_params) + + elif merged_params is not None: # Scalar parameter + if sql_named_param_nodes or named_placeholder_nodes or sql_dollar_numeric_nodes: + msg = "duckdb: Scalar parameter provided, but SQL uses named or $N placeholders. Use a single '?'." + raise ParameterStyleMismatchError(msg) + + if len(qmark_placeholder_nodes) != 1: + msg = ( + f"duckdb: Scalar parameter provided, but SQL expects {len(qmark_placeholder_nodes)} '?' placeholders. " + f"Expected 1. SQL: {sql}" + ) + raise SQLParsingError(msg) + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = (merged_params,) + + else: # Should be caught by 'merged_params is None' earlier + final_sql = sql + final_params = None + + return final_sql, final_params # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/oracledb/driver.py b/sqlspec/adapters/oracledb/driver.py index c53ee02..4716aea 100644 --- a/sqlspec/adapters/oracledb/driver.py +++ b/sqlspec/adapters/oracledb/driver.py @@ -2,14 +2,14 @@ from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot from oracledb import AsyncConnection, AsyncCursor, Connection, Cursor +from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import AsyncArrowBulkOperationsMixin, SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX from sqlspec.typing import ArrowTable, StatementParameterType, T -from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence @@ -35,94 +35,181 @@ def _process_sql_params( parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any, - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Process SQL and parameters for Oracle. + ) -> "tuple[str, Optional[Union[tuple[Any, ...], dict[str, Any]]]]": + """Process SQL and parameters for OracleDB. - Oracle natively supports both named (:name) and positional parameters. - This method merges parameters and validates them. - - Raises: - ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. - SQLParsingError: If parameter count mismatch is detected. - - Returns: - A tuple of (sql, parameters) ready for execution. + OracleDB supports both named (:name) and positional (?, :1, etc.) parameters. + This method merges parameters, validates them, and ensures SQL is in a + consistent format for the OracleDB driver using sqlglot. """ # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar if kwargs: if isinstance(parameters, dict): merged_params = {**parameters, **kwargs} elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for Oracle driver." + msg = "Cannot mix positional parameters with keyword arguments for OracleDB driver." raise ParameterStyleMismatchError(msg) else: merged_params = kwargs elif parameters is not None: merged_params = parameters + # else merged_params remains None + + # Special case: if merged_params is an empty dict, treat it as None for parameterless queries + if isinstance(merged_params, dict) and not merged_params: + merged_params = None + + # 2. SQLGlot Parsing + try: + # self.dialect is "oracle" + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"oracledb: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Traditional named parameters (e.g., :name as Parameter nodes) + sql_named_param_nodes = [ + node for node in parsed_expression.find_all(exp.Parameter) if node.name and not node.name.isdigit() + ] + + # Named placeholders parsed as Placeholder nodes (e.g., :name might be here in some dialects) + named_placeholder_nodes = [ + node + for node in parsed_expression.find_all(exp.Placeholder) + if isinstance(node.this, str) and not node.this.isdigit() + ] + + # Anonymous placeholders (?) + qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] + + # Oracle positional parameters (:1, :2, etc.) + numeric_param_nodes = [ + node for node in parsed_expression.find_all(exp.Parameter) if node.name and node.name.isdigit() + ] + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes or numeric_param_nodes: + placeholder_types = set() + if sql_named_param_nodes or named_placeholder_nodes: + placeholder_types.add("named (e.g., :name)") + if qmark_placeholder_nodes: + placeholder_types.add("qmark ('?')") + if numeric_param_nodes: + placeholder_types.add("positional (:n)") + msg = ( + f"oracledb: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + return sql, None # OracleDB can handle None + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - # Use bind_parameters for named parameters if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="oracle") - return final_sql, final_params - - # Case 2: Sequence parameters - check count and pass through - if isinstance(merged_params, (list, tuple)): - # Count ? placeholders - qmark_count = 0 - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - qmark_count += 1 - - # Validate - actual_count = len(merged_params) - if qmark_count > 0 and qmark_count != actual_count: - msg = f"oracle: Parameter count mismatch. SQL expects {qmark_count} positional parameters ('?'), but {actual_count} were provided. SQL: {sql}" + # Dictionary parameters. OracleDB can take dict for :name params. + if qmark_placeholder_nodes or numeric_param_nodes: + msg = "oracledb: Dictionary parameters provided, but SQL uses positional placeholders ('?' or :n). Use named placeholders (e.g., :name)." + raise ParameterStyleMismatchError(msg) + + if not sql_named_param_nodes and not named_placeholder_nodes: + msg = "oracledb: Dictionary parameters provided, but no named placeholders (e.g., :name) found by sqlglot." + raise ParameterStyleMismatchError(msg) + + # Collect parameter names from both types of nodes + sql_param_names_in_ast = set() + + # Get names from Parameter nodes + sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) + + # Get names from Placeholder nodes + sql_param_names_in_ast.update(node.this for node in named_placeholder_nodes if isinstance(node.this, str)) + + provided_keys = set(merged_params.keys()) + + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"oracledb: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" raise SQLParsingError(msg) - return sql, merged_params + extra_keys = provided_keys - sql_param_names_in_ast + if extra_keys: + logger.warning( + f"oracledb: Parameters {extra_keys} provided but not found in SQL. They will be ignored. SQL: {sql}" + ) + + # Generate SQL with oracle dialect for named params + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = merged_params # OracleDB works with dict directly + + elif isinstance(merged_params, (list, tuple)): + # Sequence parameters. OracleDB can take tuple where SQL has ? or :n. + # Ideally transform all to :n style for consistency with oracle dialect. + if sql_named_param_nodes or named_placeholder_nodes: + msg = "oracledb: Sequence parameters provided, but SQL contains named placeholders. Use positional placeholders ('?' or ':n')." + raise ParameterStyleMismatchError(msg) + + total_positional = len(qmark_placeholder_nodes) + len(numeric_param_nodes) + if total_positional != len(merged_params): + msg = ( + f"oracledb: Parameter count mismatch. SQL expects {total_positional} " + f"positional placeholders, but {len(merged_params)} parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + + # Transform '?' to :n if needed for consistency + counter: list[int] = [0] # Use list to make counter mutable in nested function + + def _convert_qmark_to_param(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Placeholder) and node.this is None: + counter[0] += 1 + return exp.Parameter(this=exp.Identifier(this=str(counter[0]))) + return node + + if qmark_placeholder_nodes: + # Transform and regenerate SQL + transformed_expression = parsed_expression.transform(_convert_qmark_to_param, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) + else: + final_sql = parsed_expression.sql(dialect=self.dialect) + + final_params = tuple(merged_params) # OracleDB expects tuple for positional params - # Case 3: Scalar parameter - wrap in tuple - # Special handling for scalar values with ? placeholder - if merged_params is not None: - qmark_count = 0 - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - qmark_count += 1 + elif merged_params is not None: # Scalar parameter + if sql_named_param_nodes or named_placeholder_nodes: + msg = "oracledb: Scalar parameter provided, but SQL contains named placeholders. Use a single positional placeholder ('?' or ':1')." + raise ParameterStyleMismatchError(msg) - if qmark_count > 1: - msg = f"oracle: Parameter count mismatch. SQL expects {qmark_count} positional parameters ('?'), but 1 scalar was provided. SQL: {sql}" + total_positional = len(qmark_placeholder_nodes) + len(numeric_param_nodes) + if total_positional != 1: + msg = ( + f"oracledb: Scalar parameter provided, but SQL expects {total_positional} " + f"positional placeholders. Expected 1. SQL: {sql}" + ) raise SQLParsingError(msg) - return sql, (merged_params,) - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - has_placeholders = True - break - - if has_placeholders: - msg = f"oracle: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + # Transform '?' to :1 if needed for consistency with oracle dialect + if qmark_placeholder_nodes: + transformed_expression = parsed_expression.transform( + lambda node: exp.Parameter(this=exp.Identifier(this="1")) + if isinstance(node, exp.Placeholder) and node.this is None + else node, + copy=True, + ) + final_sql = transformed_expression.sql(dialect=self.dialect) + else: + final_sql = parsed_expression.sql(dialect=self.dialect) + + final_params = (merged_params,) # OracleDB expects tuple for scalar + + else: # Should be caught by 'merged_params is None' earlier + final_sql = sql + final_params = None + + return final_sql, final_params class OracleSyncDriver( diff --git a/sqlspec/adapters/psqlpy/driver.py b/sqlspec/adapters/psqlpy/driver.py index ca63799..208e0c6 100644 --- a/sqlspec/adapters/psqlpy/driver.py +++ b/sqlspec/adapters/psqlpy/driver.py @@ -1,17 +1,18 @@ -# ruff: noqa: PLR0915, PLR0912, C901, PLR6301 +# ruff: noqa: PLR0915 """Psqlpy Driver Implementation.""" import logging from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot from psqlpy import Connection, QueryResult from psqlpy.exceptions import RustPSQLDriverPyBaseError +from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX -from sqlspec.utils.text import bind_parameters +from sqlspec.statement import SQLStatement if TYPE_CHECKING: from collections.abc import Sequence @@ -45,141 +46,152 @@ def _process_sql_params( parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any, - ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + ) -> "tuple[str, Optional[Union[tuple[Any, ...], dict[str, Any]]]]": """Process SQL and parameters for psqlpy. - psqlpy uses $1, $2 style parameters natively. - This method converts '?' (tuple/list) and ':name' (dict) styles to $n. - Args: - sql: The SQL statement to process. - parameters: The parameters to process. + sql: SQL statement. + parameters: Query parameters. **kwargs: Additional keyword arguments. - Raises: - ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. - SQLParsingError: If SQL contains parameter placeholders, but no parameters were provided. - Returns: - A tuple of the processed SQL and parameters. + The SQL statement and parameters. + + Raises: + ParameterStyleMismatchError: If the parameter style doesn't match the SQL statement. + SQLParsingError: If the SQL parsing fails. """ - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for psqlpy driver." + # First, use SQLStatement for parameter validation + statement = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs) + sql, validated_params = statement.process() + + if validated_params is None: + return sql, None # psqlpy can handle None + + # Now use SQLGlot for PostgreSQL-specific parameter handling + try: + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"psqlpy: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Traditional named parameters (e.g., @name, $name) + sql_named_param_nodes = [ + node for node in parsed_expression.find_all(exp.Parameter) if node.name and not node.name.isdigit() + ] + + # Named placeholders (e.g., :name which are parsed as Placeholder with this="name") + named_placeholder_nodes = [ + node + for node in parsed_expression.find_all(exp.Placeholder) + if isinstance(node.this, str) and not node.this.isdigit() + ] + + # Anonymous placeholders (?) + qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] + + # PostgreSQL-specific dollar-numeric parameters like $1, $2 + sql_numeric_dollar_nodes = [ + node + for node in parsed_expression.find_all(exp.Parameter) + if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() + ] + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None + + if isinstance(validated_params, dict): + # Dictionary parameters - need to convert named parameters from :name to $n style + if qmark_placeholder_nodes or sql_numeric_dollar_nodes: + msg = "psqlpy: Dictionary parameters provided, but SQL uses positional placeholders. Use named placeholders (e.g., :name)." raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters - - # Use bind_parameters for named parameters - if isinstance(merged_params, dict): - final_sql, _ = bind_parameters(sql, merged_params, dialect="postgres") - # psqlpy expects positional parameters, so convert dict to tuple in order of appearance - # We'll use regex to find order for now - param_names = [] - for match in PARAM_REGEX.finditer(sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - if match.group("var_name"): - param_names.append(match.group("var_name")) - ordered_params = tuple(merged_params[name] for name in param_names) - # Replace :name with $1, $2, ... - for idx, name in enumerate(param_names, 1): - final_sql = final_sql.replace(f":{name}", f"${idx}") - return final_sql, ordered_params - - # Case b: Sequence or scalar parameters (? style) - if isinstance(merged_params, (list, tuple)): - sequence_processed_parts: list[str] = [] - param_index = 1 - last_end = 0 - qmark_count = 0 - - for match in QMARK_REGEX.finditer(sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("qmark"): - qmark_count += 1 - start = match.start("qmark") - end = match.end("qmark") - sequence_processed_parts.extend((sql[last_end:start], f"${param_index}")) - last_end = end - param_index += 1 - - sequence_processed_parts.append(sql[last_end:]) - final_sql = "".join(sequence_processed_parts) - - # Validation - if not qmark_count and merged_params: - msg = f"psqlpy: Sequence parameters provided, but no '?' placeholders found in SQL: {sql}" + + if not sql_named_param_nodes and not named_placeholder_nodes: + msg = "psqlpy: Dictionary parameters provided, but no named placeholders found in SQL by sqlglot." + raise ParameterStyleMismatchError(msg) + + # Transform named parameters to $n placeholders for psqlpy + param_seq = [] + + def _convert_named_to_dollar(node: exp.Expression) -> exp.Expression: + param_name = None + if isinstance(node, exp.Parameter) and node.name: + param_name = node.name + elif isinstance(node, exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit(): + param_name = node.this + + if param_name and param_name in validated_params: + param_seq.append(validated_params[param_name]) + # Create a Parameter node that PostgreSQL will interpret as a positional parameter ($n) + return exp.Parameter(this=str(len(param_seq))) + return node + + transformed_expression = parsed_expression.transform(_convert_named_to_dollar, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) + final_params = tuple(param_seq) + + elif hasattr(validated_params, "__iter__") and not isinstance(validated_params, (str, bytes, dict)): + # Sequence parameters (list or tuple) + if sql_named_param_nodes or named_placeholder_nodes: + msg = "psqlpy: Sequence parameters provided, but SQL contains named placeholders. Use positional placeholders ('?' or '$1')." raise ParameterStyleMismatchError(msg) - actual_count = len(merged_params) - if qmark_count != actual_count: - msg = f"psqlpy: Parameter count mismatch. SQL expects {qmark_count} positional parameters ('?'), but {actual_count} were provided. SQL: {sql}" + # Count placeholders for validation + total_positional_params = len(qmark_placeholder_nodes) + len(sql_numeric_dollar_nodes) + if total_positional_params != len(validated_params): + msg = ( + f"psqlpy: Parameter count mismatch. SQL expects {total_positional_params} " + f"positional placeholders, but {len(validated_params)} parameters were provided. SQL: {sql}" + ) raise SQLParsingError(msg) - return final_sql, merged_params - # Case c: Scalar - # Convert to a one-element tuple - if merged_params is not None: - scalar_param_tuple = (merged_params,) - sequence_processed_parts = [] - param_index = 1 - last_end = 0 - qmark_count = 0 - - for match in QMARK_REGEX.finditer(sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - - if match.group("qmark"): - qmark_count += 1 - start = match.start("qmark") - end = match.end("qmark") - sequence_processed_parts.extend((sql[last_end:start], f"${param_index}")) - last_end = end - param_index += 1 - - sequence_processed_parts.append(sql[last_end:]) - final_sql = "".join(sequence_processed_parts) - - # Validation - for scalar, we expect exactly one placeholder - if qmark_count != 1: - msg = f"psqlpy: Parameter count mismatch. SQL expects 1 positional parameter ('?') for scalar input, but found {qmark_count}. SQL: {sql}" + param_seq = list(validated_params) + + # Convert question marks to $n parameters + if qmark_placeholder_nodes: + counter = [0] # Make it mutable for the inner function + + def _convert_qmark_to_dollar(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Placeholder) and node.this is None: + counter[0] += 1 + return exp.Parameter(this=str(counter[0])) + return node + + transformed_expression = parsed_expression.transform(_convert_qmark_to_dollar, copy=True) + final_sql = transformed_expression.sql(dialect=self.dialect) + else: + final_sql = parsed_expression.sql(dialect=self.dialect) + + final_params = tuple(param_seq) + + else: # Scalar parameter (if validated_params is not None and not a sequence) + if sql_named_param_nodes or named_placeholder_nodes: + msg = "psqlpy: Scalar parameter provided, but SQL contains named placeholders. Use a single positional placeholder ('?' or '$1')." + raise ParameterStyleMismatchError(msg) + + total_positional_params = len(qmark_placeholder_nodes) + len(sql_numeric_dollar_nodes) + if total_positional_params != 1: + msg = ( + f"psqlpy: Scalar parameter provided, but SQL expects {total_positional_params} " + f"positional placeholders. Expected 1. SQL: {sql}" + ) raise SQLParsingError(msg) - return final_sql, scalar_param_tuple - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - has_placeholders = True - break - - if has_placeholders: - msg = f"psqlpy: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, () + # For scalar parameter with question mark, convert to $1 + if qmark_placeholder_nodes: + transformed_expression = parsed_expression.transform( + lambda node: exp.Parameter(this="1") + if isinstance(node, exp.Placeholder) and node.this is None + else node, + copy=True, + ) + final_sql = transformed_expression.sql(dialect=self.dialect) + else: + final_sql = parsed_expression.sql(dialect=self.dialect) + + final_params = (validated_params,) # psqlpy expects a tuple for $1 + + return final_sql, final_params # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/psycopg/driver.py b/sqlspec/adapters/psycopg/driver.py index d496066..312fc74 100644 --- a/sqlspec/adapters/psycopg/driver.py +++ b/sqlspec/adapters/psycopg/driver.py @@ -1,15 +1,15 @@ import logging -import re from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot from psycopg import AsyncConnection, Connection from psycopg.rows import dict_row +from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError +from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence @@ -23,9 +23,6 @@ PsycopgSyncConnection = Connection PsycopgAsyncConnection = AsyncConnection -# Compile the parameter name regex once for efficiency -PARAM_NAME_REGEX = re.compile(r":([a-zA-Z_][a-zA-Z0-9_]*)") - class PsycopgDriverBase: dialect: str @@ -38,52 +35,168 @@ def _process_sql_params( **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], Sequence[Any]]] = None + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None if kwargs: if isinstance(parameters, dict): merged_params = {**parameters, **kwargs} elif parameters is not None: - msg = f"Cannot mix positional parameters with keyword arguments for {self.dialect} driver." + msg = "Cannot mix positional parameters with keyword arguments for psycopg driver." raise ParameterStyleMismatchError(msg) else: merged_params = kwargs elif parameters is not None: merged_params = parameters + # else merged_params remains None + + # Special case: if merged_params is an empty dict, treat it as None for parameterless queries + if isinstance(merged_params, dict) and not merged_params: + merged_params = None + + # 2. SQLGlot Parsing + try: + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"psycopg: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Traditional named parameters (e.g., @name, $name) + sql_named_param_nodes = [ + node for node in parsed_expression.find_all(exp.Parameter) if node.name and not node.name.isdigit() + ] + + # Named placeholders (e.g., :name which are parsed as Placeholder with this="name") + named_placeholder_nodes = [ + node + for node in parsed_expression.find_all(exp.Placeholder) + if isinstance(node.this, str) and not node.this.isdigit() + ] + + # Anonymous placeholders (?) + qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] + + # Numeric dollar params (e.g., $1, $2) + sql_numeric_dollar_nodes = [ + node + for node in parsed_expression.find_all(exp.Parameter) + if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() + ] + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes or sql_numeric_dollar_nodes: + placeholder_types = set() + if sql_named_param_nodes or named_placeholder_nodes: + placeholder_types.add("named (e.g., :name)") + if qmark_placeholder_nodes: + placeholder_types.add("qmark ('?')") + if sql_numeric_dollar_nodes: + placeholder_types.add("numeric ($n)") + msg = ( + f"psycopg: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + return sql, None # psycopg can take None for params + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - # Use bind_parameters for named parameters if isinstance(merged_params, dict): - # Always convert :name to %(name)s for psycopg - sql_converted = PARAM_NAME_REGEX.sub(lambda m: f"%({m.group(1)})s", sql) - return sql_converted, merged_params - # Case 2: Sequence parameters - leave as is (psycopg handles '%s' placeholders with tuple/list) - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar - wrap in tuple - if merged_params is not None: - return sql, (merged_params,) - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - has_qmark = False - if not has_placeholders: - for match in QMARK_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "qmark" - ): - has_qmark = True - break - if has_placeholders or has_qmark: - msg = f"psycopg: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise ParameterStyleMismatchError(msg) - return sql, None + # Dictionary parameters. Aim for %(name)s style for psycopg. + if qmark_placeholder_nodes or sql_numeric_dollar_nodes: + msg = "psycopg: Dictionary parameters provided, but SQL uses positional placeholders ('?' or $n). Use named placeholders for dictionary params (e.g. :name, which will be converted to %(name)s)." + raise ParameterStyleMismatchError(msg) + + if not sql_named_param_nodes and not named_placeholder_nodes and "%(" not in sql: + msg = "psycopg: Dictionary parameters provided, but no standard named placeholders (e.g., :name) found to convert to %(name)s, and SQL does not appear to be pyformat already." + raise ParameterStyleMismatchError(msg) + + if sql_named_param_nodes or named_placeholder_nodes: + # Collect parameter names from both types of nodes + sql_param_names_in_ast = set() + + # Get names from Parameter nodes + sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) + + # Get names from Placeholder nodes + sql_param_names_in_ast.update( + node.this for node in named_placeholder_nodes if isinstance(node.this, str) + ) + + provided_keys = set(merged_params.keys()) + + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"psycopg: Named parameters {missing_keys} (from :name style) found in SQL but not provided. SQL: {sql}" + raise SQLParsingError(msg) + + try: + final_sql = parsed_expression.sql(dialect=self.dialect, pyformat=True) + except Exception as e: + logger.exception("psycopg: Failed to generate pyformat SQL with sqlglot: %s. SQL: %s", e, sql) + if "%(" in sql: + final_sql = sql + else: + msg = f"psycopg: Error generating pyformat SQL: {e}" + raise SQLParsingError(msg) from e + + final_params = merged_params + + elif isinstance(merged_params, (list, tuple)): + # Sequence parameters. Aim for %s style. + if sql_named_param_nodes or named_placeholder_nodes: + msg = "psycopg: Sequence parameters provided, but SQL contains named placeholders. Use '?' or '%s' for sequence parameters." + raise ParameterStyleMismatchError(msg) + if sql_numeric_dollar_nodes: + msg = "psycopg: Sequence parameters provided, but SQL uses $n style. Use '?' or '%s' for psycopg." + raise ParameterStyleMismatchError(msg) + + expected_param_count = len(qmark_placeholder_nodes) + if expected_param_count == 0 and "%s" in sql and not qmark_placeholder_nodes: + logger.debug( + "psycopg: No '?' found, but '%s' present with sequence params. Assuming intended for '%s' style. Count validation relies on psycopg." + ) + elif expected_param_count != len(merged_params) and not ("%s" in sql and expected_param_count == 0): + if not ("%s" in sql and len(merged_params) > 0 and expected_param_count == 0): + msg = ( + f"psycopg: Parameter count mismatch. SQL (based on '?' count) expects " + f"{expected_param_count} positional placeholders, but {len(merged_params)} were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = tuple(merged_params) + + elif merged_params is not None: # Scalar parameter + if sql_named_param_nodes or named_placeholder_nodes: + msg = "psycopg: Scalar parameter provided, but SQL uses named placeholders. Use a single '?' or '%s'." + raise ParameterStyleMismatchError(msg) + if sql_numeric_dollar_nodes: + msg = "psycopg: Scalar parameter provided, but SQL uses $n style. Use '?' or '%s' for psycopg." + raise ParameterStyleMismatchError(msg) + + expected_param_count = len(qmark_placeholder_nodes) + if expected_param_count == 0 and "%s" in sql and not qmark_placeholder_nodes: + logger.debug( + "psycopg: No '?' for scalar, but '%s' present. Assuming '%s' style. Count relies on psycopg." + ) + elif expected_param_count != 1 and not ("%s" in sql and expected_param_count == 0): + if not ("%s" in sql and expected_param_count == 0): # Avoid error if it might be a single %s + msg = ( + f"psycopg: Scalar parameter provided, but SQL expects {expected_param_count} " + f"positional placeholders ('?' or '%s'). Expected 1. SQL: {sql}" + ) + raise SQLParsingError(msg) + + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = (merged_params,) + + else: # Should be caught by 'merged_params is None' earlier + final_sql = sql + final_params = None + + return final_sql, final_params class PsycopgSyncDriver( diff --git a/sqlspec/adapters/sqlite/driver.py b/sqlspec/adapters/sqlite/driver.py index 1f8e49e..1ddadb9 100644 --- a/sqlspec/adapters/sqlite/driver.py +++ b/sqlspec/adapters/sqlite/driver.py @@ -4,11 +4,12 @@ from sqlite3 import Cursor from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +import sqlglot +from sqlglot import exp + from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin -from sqlspec.statement import PARAM_REGEX, QMARK_REGEX -from sqlspec.utils.text import bind_parameters if TYPE_CHECKING: from collections.abc import Generator, Sequence @@ -56,10 +57,11 @@ def _process_sql_params( """Process SQL and parameters for SQLite. SQLite supports both named (:name) and positional (?) parameters. - This method merges parameters and validates them. + This method merges parameters, validates them, and ensures SQL is in a consistent + format for the sqlite driver using sqlglot. """ # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None + merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar if kwargs: if isinstance(parameters, dict): @@ -71,39 +73,123 @@ def _process_sql_params( merged_params = kwargs elif parameters is not None: merged_params = parameters + # else merged_params remains None + + # Special case: if merged_params is an empty dict, treat it as None for parameterless queries + if isinstance(merged_params, dict) and not merged_params: + merged_params = None + + # 2. SQLGlot Parsing + try: + # self.dialect is "sqlite" + parsed_expression = sqlglot.parse_one(sql, read=self.dialect) + except Exception as e: + msg = f"sqlite: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" + raise SQLParsingError(msg) from e + + # Traditional named parameters (e.g., @name) + sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] + + # Named placeholders parsed as Placeholder nodes (e.g., :name in some dialects) + named_placeholder_nodes = [ + node + for node in parsed_expression.find_all(exp.Placeholder) + if isinstance(node.this, str) and not node.this.isdigit() + ] + + # Anonymous placeholders (?) + qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] + + # 3. Handle No Parameters Case + if merged_params is None: + if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes: + placeholder_types = set() + if sql_named_param_nodes or named_placeholder_nodes: + placeholder_types.add("named (e.g., :name, @name)") + if qmark_placeholder_nodes: + placeholder_types.add("qmark ('?')") + msg = ( + f"sqlite: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " + f"parameter placeholders, but no parameters were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + return sql, None # SQLite can take None + + final_sql: str + final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - # Use bind_parameters for named parameters if isinstance(merged_params, dict): - final_sql, final_params = bind_parameters(sql, merged_params, dialect="sqlite") - return final_sql, final_params - - # Case 2: Sequence parameters - pass through - if isinstance(merged_params, (list, tuple)): - return sql, merged_params - # Case 3: Scalar parameter - wrap in tuple - if merged_params is not None: - return sql, (merged_params,) # type: ignore[unreachable] - - # Case 0: No parameters provided - # Basic validation for placeholders - has_placeholders = False - for match in PARAM_REGEX.finditer(sql): - if not (match.group("dquote") or match.group("squote") or match.group("comment")) and match.group( - "var_name" - ): - has_placeholders = True - break - if not has_placeholders: - # Check for ? style placeholders - for match in QMARK_REGEX.finditer(sql): - if match.group("qmark"): - has_placeholders = True - break - - if has_placeholders: - msg = f"sqlite: SQL contains parameter placeholders, but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + # Dictionary parameters. SQLite client handles :name natively. + if qmark_placeholder_nodes: + msg = "sqlite: Dictionary parameters provided, but SQL uses positional placeholders ('?'). Use named placeholders (e.g., :name)." + raise ParameterStyleMismatchError(msg) + + if not sql_named_param_nodes and not named_placeholder_nodes: + msg = ( + "sqlite: Dictionary parameters provided, but no named placeholders (e.g., :name) found by sqlglot." + ) + raise ParameterStyleMismatchError(msg) + + # Collect parameter names from both types of nodes + sql_param_names_in_ast = set() + + # Get names from Parameter nodes + sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) + + # Get names from Placeholder nodes + sql_param_names_in_ast.update(node.this for node in named_placeholder_nodes if isinstance(node.this, str)) + + provided_keys = set(merged_params.keys()) + + missing_keys = sql_param_names_in_ast - provided_keys + if missing_keys: + msg = f"sqlite: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" + raise SQLParsingError(msg) + + extra_keys = provided_keys - sql_param_names_in_ast + if extra_keys: + msg = f"sqlite: Parameters {extra_keys} provided but not found in SQL. SQLite might ignore them. SQL: {sql}" + logger.warning(msg) + + # Generate SQL with sqlite dialect for named params + final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures consistent named param style + final_params = merged_params # SQLite handles dict directly + + elif isinstance(merged_params, (list, tuple)): + # Sequence parameters. SQLite uses '?'. + if sql_named_param_nodes or named_placeholder_nodes: + msg = "sqlite: Sequence parameters provided, but SQL uses named placeholders. Use '?' for sequence parameters." + raise ParameterStyleMismatchError(msg) + + if len(qmark_placeholder_nodes) != len(merged_params): + msg = ( + f"sqlite: Parameter count mismatch. SQL expects {len(qmark_placeholder_nodes)} '?' placeholders, " + f"but {len(merged_params)} were provided. SQL: {sql}" + ) + raise SQLParsingError(msg) + + final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures '?' style + final_params = tuple(merged_params) # SQLite can take a tuple + + elif merged_params is not None: # Scalar parameter + if sql_named_param_nodes or named_placeholder_nodes: + msg = "sqlite: Scalar parameter provided, but SQL uses named placeholders. Use a single '?'." + raise ParameterStyleMismatchError(msg) + + if len(qmark_placeholder_nodes) != 1: + msg = ( + f"sqlite: Scalar parameter provided, but SQL expects {len(qmark_placeholder_nodes)} '?' placeholders. " + f"Expected 1. SQL: {sql}" + ) + raise SQLParsingError(msg) + final_sql = parsed_expression.sql(dialect=self.dialect) + final_params = (merged_params,) # SQLite needs a tuple for a scalar + + else: # Should be caught by 'merged_params is None' earlier + final_sql = sql + final_params = None + + return final_sql, final_params # --- Public API Methods --- # @overload diff --git a/sqlspec/extensions/litestar/config.py b/sqlspec/extensions/litestar/config.py index a39834c..85e6d4f 100644 --- a/sqlspec/extensions/litestar/config.py +++ b/sqlspec/extensions/litestar/config.py @@ -74,6 +74,10 @@ def __post_init__(self) -> None: msg = f"Invalid commit mode: {self.commit_mode}" # type: ignore[unreachable] raise ImproperConfigurationError(detail=msg) self.lifespan_handler = lifespan_handler_maker(config=self.config, pool_key=self.pool_key) - self.connection_provider = connection_provider_maker(connection_key=self.connection_key, config=self.config) - self.pool_provider = pool_provider_maker(pool_key=self.pool_key, config=self.config) - self.session_provider = session_provider_maker(session_key=self.session_key, config=self.config) + self.connection_provider = connection_provider_maker( + connection_key=self.connection_key, pool_key=self.pool_key, config=self.config + ) + self.pool_provider = pool_provider_maker(config=self.config, pool_key=self.pool_key) + self.session_provider = session_provider_maker( + session_key=self.session_key, connection_key=self.connection_key, pool_key=self.pool_key, config=self.config + ) diff --git a/sqlspec/extensions/litestar/handlers.py b/sqlspec/extensions/litestar/handlers.py index df9a67a..ef8fc6a 100644 --- a/sqlspec/extensions/litestar/handlers.py +++ b/sqlspec/extensions/litestar/handlers.py @@ -1,3 +1,6 @@ +# sqlspec/extensions/litestar/handlers.py +"""ASGI Message handlers and dependency providers for the Litestar SQLSpec extension.""" + import contextlib from typing import TYPE_CHECKING, Any, Callable, Optional, cast @@ -28,21 +31,21 @@ def manual_handler_maker(connection_scope_key: str) -> "Callable[[Message, Scope], Coroutine[Any, Any, None]]": - """Set up the handler to issue a transaction commit or rollback based on specified status codes + """Set up the handler to close the connection. + Args: - connection_scope_key: The key to use within the application state + connection_scope_key: The key used to store the connection in the ASGI scope. Returns: - The handler callable + The handler callable. """ async def handler(message: "Message", scope: "Scope") -> None: - """Handle commit/rollback, closing and cleaning up sessions before sending. + """Handle closing and cleaning up connections before sending the response. Args: - message: ASGI-``Message`` - scope: An ASGI-``Scope`` - + message: ASGI Message. + scope: ASGI Scope. """ connection = get_sqlspec_scope_state(scope, connection_scope_key) if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: @@ -58,18 +61,19 @@ def autocommit_handler_maker( extra_commit_statuses: "Optional[set[int]]" = None, extra_rollback_statuses: "Optional[set[int]]" = None, ) -> "Callable[[Message, Scope], Coroutine[Any, Any, None]]": - """Set up the handler to issue a transaction commit or rollback based on specified status codes + """Set up the handler to issue a transaction commit or rollback based on response status codes. + Args: - commit_on_redirect: Issue a commit when the response status is a redirect (``3XX``) - extra_commit_statuses: A set of additional status codes that trigger a commit - extra_rollback_statuses: A set of additional status codes that trigger a rollback - connection_scope_key: The key to use within the application state + connection_scope_key: The key used to store the connection in the ASGI scope. + commit_on_redirect: Issue a commit when the response status is a redirect (3XX). + extra_commit_statuses: A set of additional status codes that trigger a commit. + extra_rollback_statuses: A set of additional status codes that trigger a rollback. Raises: - ImproperConfigurationError: If extra_commit_statuses and extra_rollback_statuses share any status codes + ImproperConfigurationError: If extra_commit_statuses and extra_rollback_statuses share status codes. Returns: - The handler callable + The handler callable. """ if extra_commit_statuses is None: extra_commit_statuses = set() @@ -84,12 +88,11 @@ def autocommit_handler_maker( commit_range = range(200, 400 if commit_on_redirect else 300) async def handler(message: "Message", scope: "Scope") -> None: - """Handle commit/rollback, closing and cleaning up sessions before sending. + """Handle commit/rollback, closing and cleaning up connections before sending. Args: - message: ASGI-``litestar.types.Message`` - scope: An ASGI-``litestar.types.Scope`` - + message: ASGI Message. + scope: ASGI Scope. """ connection = get_sqlspec_scope_state(scope, connection_scope_key) try: @@ -112,18 +115,28 @@ def lifespan_handler_maker( config: "DatabaseConfigProtocol[Any, Any, Any]", pool_key: str, ) -> "Callable[[Litestar], AbstractAsyncContextManager[None]]": - """Build the lifespan handler for the database configuration. + """Build the lifespan handler for managing the database connection pool. + + The pool is created on application startup and closed on shutdown. Args: - config: The database configuration. - pool_key: The key to use for the connection pool within Litestar. + config: The database configuration object. + pool_key: The key under which the connection pool will be stored in `app.state`. Returns: - The generated lifespan handler for the connection. + The generated lifespan handler. """ @contextlib.asynccontextmanager async def lifespan_handler(app: "Litestar") -> "AsyncGenerator[None, None]": + """Manages the database pool lifecycle. + + Args: + app: The Litestar application instance. + + Yields: + The generated lifespan handler. + """ db_pool = await ensure_async_(config.create_pool)() app.state.update({pool_key: db_pool}) try: @@ -133,78 +146,166 @@ async def lifespan_handler(app: "Litestar") -> "AsyncGenerator[None, None]": try: await ensure_async_(config.close_pool)() except Exception as e: # noqa: BLE001 - if app.logger: + if app.logger: # pragma: no cover app.logger.warning("Error closing database pool for %s. Error: %s", pool_key, e) return lifespan_handler -def connection_provider_maker( - connection_key: str, - config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", -) -> "Callable[[State,Scope], Awaitable[ConnectionT]]": - """Build the connection provider for the database configuration. +def pool_provider_maker( + config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", pool_key: str +) -> "Callable[[State, Scope], Awaitable[PoolT]]": + """Build the pool provider to inject the application-level database pool. Args: - connection_key: The dependency key to use for the session within Litestar. - config: The database configuration. + config: The database configuration object. + pool_key: The key used to store the connection pool in `app.state`. Returns: - The generated connection provider for the connection. + The generated pool provider. """ - async def provide_connection(state: "State", scope: "Scope") -> "ConnectionT": - connection = get_sqlspec_scope_state(scope, connection_key) - if connection is None: - connection = await ensure_async_(config.create_connection)() - set_sqlspec_scope_state(scope, connection_key, connection) - return cast("ConnectionT", connection) + async def provide_pool(state: "State", scope: "Scope") -> "PoolT": # pylint: disable=unused-argument + """Provides the database pool from `app.state`. - return provide_connection + Args: + state: The Litestar application State object. + scope: The ASGI scope (unused for app-level pool). -def pool_provider_maker( - pool_key: str, - config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", -) -> "Callable[[State,Scope], Awaitable[PoolT]]": - """Build the pool provider for the database configuration. + Returns: + The database connection pool. + + Raises: + ImproperConfigurationError: If the pool is not found in `app.state`. + """ + # The pool is stored in app.state by the lifespan handler. + # state.get(key) accesses app.state[key] + db_pool = state.get(pool_key) + if db_pool is None: + # This case should ideally not happen if the lifespan handler ran correctly. + msg = ( + f"Database pool with key '{pool_key}' not found in application state. " + "Ensure the SQLSpec lifespan handler is correctly configured and has run." + ) + raise ImproperConfigurationError(msg) + return cast("PoolT", db_pool) + + return provide_pool + + +def connection_provider_maker( + connection_key: str, # Key for storing connection in request scope + pool_key: str, # Key for retrieving pool from app state + config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", # Needed for acquire_connection_from_pool +) -> "Callable[[State, Scope], Awaitable[ConnectionT]]": + """Build the connection provider to inject a database connection acquired from the pool. Args: - pool_key: The dependency key to use for the pool within Litestar. - config: The database configuration. + connection_key: The key to store the acquired connection in the ASGI scope for reuse + within the same request. + pool_key: The key used to retrieve the connection pool from `app.state`. + config: The database configuration object, expected to have a method + for acquiring connections from a pool instance. Returns: - The generated connection pool for the database. + The generated connection provider. """ - async def provide_pool(state: "State", scope: "Scope") -> "PoolT": - pool = get_sqlspec_scope_state(scope, pool_key) - if pool is None: - pool = await ensure_async_(config.create_pool)() - set_sqlspec_scope_state(scope, pool_key, pool) - return cast("PoolT", pool) + async def provide_connection(state: "State", scope: "Scope") -> "ConnectionT": + """Provides a database connection from the application pool. - return provide_pool + A connection is acquired from the pool and stored in the request scope + to be reused if the dependency is requested multiple times in the same request. + The `before_send` handler is responsible for closing this connection (returning it to the pool). + + Args: + state: The Litestar application State object. + scope: The ASGI scope. + + Returns: + A database connection. + + Raises: + ImproperConfigurationError: If the pool is not found or cannot provide a connection. + """ + # Check if a connection is already stored in the current request's scope + connection = get_sqlspec_scope_state(scope, connection_key) + if connection is None: + # Get the application-level pool from app.state + db_pool = state.get(pool_key) + if db_pool is None: + msg = f"Database pool with key '{pool_key}' not found in application state. Cannot create a connection." + raise ImproperConfigurationError(msg) + + # Acquire a new connection from the pool. + # This relies on the DatabaseConfigProtocol's `acquire_connection_from_pool` method. + if not hasattr(config, "acquire_connection_from_pool"): + msg = ( + f"The DatabaseConfigProtocol implementation for dialect '{config.dialect_name}' " # type: ignore[attr-defined] + "is missing the 'acquire_connection_from_pool' method, " + "which is required for pooled connection management." + ) + raise ImproperConfigurationError(msg) + connection = await ensure_async_(config.acquire_connection_from_pool(db_pool)) # type: ignore[attr-defined] + set_sqlspec_scope_state(scope, connection_key, connection) + return cast("ConnectionT", connection) + + return provide_connection def session_provider_maker( - session_key: str, - config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", -) -> "Callable[[State,Scope], Awaitable[DriverT]]": - """Build the session provider for the database configuration. + config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", session_key: str, connection_key: str, pool_key: str +) -> "Callable[[State, Scope], Awaitable[DriverT]]": + """Build the session provider (DriverT instance) using a pooled connection. Args: - session_key: The dependency key to use for the session within Litestar. - config: The database configuration. + session_key: The key to store the DriverT instance in the ASGI scope. + connection_key: The key for the underlying ConnectionT in the ASGI scope. This + ensures the same connection instance is used and managed. + pool_key: The key to retrieve the connection pool from `app.state`. + config: The database configuration object. Returns: - The generated session provider for the database. + The generated session provider. """ async def provide_session(state: "State", scope: "Scope") -> "DriverT": + """Provides a DriverT instance (session) wrapping a pooled database connection. + + The underlying connection is managed (acquired and stored in scope) similarly + to `provide_connection`. + + Args: + state: The Litestar application State object. + scope: The ASGI scope. + + Returns: + A DriverT instance. + + Raises: + ImproperConfigurationError: If the pool is not found or cannot provide a connection. + """ session = get_sqlspec_scope_state(scope, session_key) if session is None: - connection = await ensure_async_(config.create_connection)() + # Get or create the underlying connection for this request scope + connection = get_sqlspec_scope_state(scope, connection_key) + if connection is None: + db_pool = state.get(pool_key) + if db_pool is None: + msg = f"Database pool with key '{pool_key}' not found in application state while trying to create a session." + raise ImproperConfigurationError(msg) + if not hasattr(config, "acquire_connection_from_pool"): + msg = ( + f"The DatabaseConfigProtocol implementation for dialect '{config.dialect_name}' " # type: ignore[attr-defined] + "is missing the 'acquire_connection_from_pool' method, " + "which is required for pooled connection management." + ) + raise ImproperConfigurationError(msg) + connection = await ensure_async_(config.acquire_connection_from_pool(db_pool)) # type: ignore[attr-defined] + set_sqlspec_scope_state(scope, connection_key, connection) + + # Create the driver/session instance with the (pooled) connection session = config.driver_type(connection=connection) # pyright: ignore[reportCallIssue] set_sqlspec_scope_state(scope, session_key, session) return cast("DriverT", session) diff --git a/sqlspec/statement.py b/sqlspec/statement.py index 6b8568c..25246a5 100644 --- a/sqlspec/statement.py +++ b/sqlspec/statement.py @@ -18,54 +18,55 @@ logger = logging.getLogger("sqlspec") -# Regex to find :param style placeholders, skipping those inside quotes or SQL comments -# Adapted from previous version in psycopg adapter -PARAM_REGEX = re.compile( - r"""(?"(?:[^"]|"")*") | # Double-quoted strings (support SQL standard escaping "") - (?P'(?:[^']|'')*') | # Single-quoted strings (support SQL standard escaping '') - (?P--.*?\n|\/\*.*?\*\/) | # SQL comments (single line or multi-line) - : (?P[a-zA-Z_][a-zA-Z0-9_]*) # :var_name identifier - ) - """, - re.VERBOSE | re.DOTALL, -) - -# Regex to find ? placeholders, skipping those inside quotes or SQL comments -QMARK_REGEX = re.compile( - r"""(?P\"[^\"]*\") | # Double-quoted strings - (?P'[^']*') | # Single-quoted strings - (?P--[^\n]*|/\*.*?\*/) | # SQL comments (single/multi-line) - (?P\?) # The question mark placeholder - """, - re.VERBOSE | re.DOTALL, -) - - -# Regex for $name style, avoiding comments/strings -# Lookbehind ensures it's not preceded by a word char or another $ -DOLLAR_NAME_REGEX = re.compile( - r"""(?"(?:[^"]|"")*") | # Double-quoted strings - (?P'(?:[^']|'')*') | # Single-quoted strings - (?P--.*?\n|\/\*.*?\*\/) | # SQL comments - \$ (?P[a-zA-Z_][a-zA-Z0-9_]*) # $var_name identifier - ) - """, - re.VERBOSE | re.DOTALL, -) - -# Regex for @name style, avoiding comments/strings -# Lookbehind ensures it's not preceded by a word char or another @ -AT_NAME_REGEX = re.compile( - r"""(?"(?:[^"]|"")*") | # Double-quoted strings - (?P'(?:[^']|'')*') | # Single-quoted strings - (?P--.*?\n|\/\*.*?\*\/) | # SQL comments - @ (?P[a-zA-Z_][a-zA-Z0-9_]*) # @var_name identifier +CONSOLIDATED_PARAM_REGEX = re.compile( + r""" + # Fields to skip (matched first, then ignored in processing logic) + (?P"(?:[^"]|"")*") | # Double-quoted strings (SQL standard "" escaping) + (?P'(?:[^']|'')*') | # Single-quoted strings (SQL standard '' escaping) + (?P--.*?\n|\/\*.*?\*\/) | # SQL comments (single-line or multi-line) + + # Actual placeholders - attempt to match one of these + (?: # Non-capturing group for colon-numeric POSITIONAL parameter (e.g., :1, :23) + (?[1-9][0-9]*) # Captured number (1-9 followed by 0 or more digits) + ) | + (?: # Non-capturing group for colon-prefixed named parameter (e.g., :name) + (?[a-zA-Z_][a-zA-Z0-9_]*) # Captured variable name + ) | + (?: # Non-capturing group for question mark positional parameter (e.g., ?) + # Needs careful lookaround if we want to avoid matching e.g. JSON operators '?|' + # For now, keeping it simple as SQL '?' is usually well-spaced or at end of comparisons. + # A full context-aware parse (like sqlglot) is primary, this is a fallback. + (?P\?) # Captured question mark + ) | + (?: # Non-capturing group for dollar-prefixed NAMED parameter (e.g., $name) - PRIORITIZE THIS OVER $n + (?[a-zA-Z_][a-zA-Z0-9_]*) # Captured variable name (must start with letter/underscore) + ) | + (?: # Non-capturing group for at-symbol-prefixed named parameter (e.g., @name) + (?[a-zA-Z_][a-zA-Z0-9_]*) # Captured variable name + ) | + (?: # Non-capturing group for pyformat named parameter (e.g., %(name)s) + (?[a-zA-Z_][a-zA-Z0-9_]*)\) # Captured variable name inside parentheses + [a-zA-Z] # Type specifier (e.g., s, d, f) - simple match for any letter + ) | + (?: # Non-capturing group for format/printf POSITIONAL parameter (e.g., %s, %d) - AFTER pyformat + (?[a-zA-Z]) # Captured type specifier (s, d, f, etc.) + ) | + (?: # Non-capturing group for numeric dollar POSITIONAL parameter (e.g., $1, $2) + (?[1-9][0-9]*) # Captured number (1-9 followed by 0 or more digits) ) """, re.VERBOSE | re.DOTALL, @@ -125,35 +126,41 @@ def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict # Parse the SQL to find expected parameters try: expression = self._parse_sql() - # Find all parameter expressions (:name, ?, etc.) - sql_params = list(expression.find_all(exp.Parameter)) + # Find all parameter expressions (:name, ?, @name, $1, etc.) + # These are nodes that sqlglot considers as bind parameters. + all_sqlglot_placeholders = list(expression.find_all(exp.Placeholder, exp.Parameter)) except SQLParsingError as e: - # If parsing fails, we cannot validate accurately. - # Let adapters handle potentially valid but unparsable SQL. - # Log the parsing error for debugging. logger.debug( "SQL parsing failed during validation: %s. Returning original SQL and parameters for adapter.", e ) - # Return original SQL and parameters for the adapter to attempt processing - # (Adapters might use regex or other means if parsing fails) return self.sql, self._merged_parameters if self._merged_parameters is None: # If no parameters were provided, but the parsed SQL expects them, raise an error. - if sql_params: - placeholder_types = {"named" if p.name else "positional" for p in sql_params} - msg = f"SQL statement contains {', '.join(placeholder_types)} parameter placeholders, but no parameters were provided. SQL: {self.sql}" + if all_sqlglot_placeholders: + placeholder_types_desc = [] + for p_node in all_sqlglot_placeholders: + if isinstance(p_node, exp.Parameter) and p_node.name: + placeholder_types_desc.append(f"named (e.g., :{p_node.name}, @{p_node.name})") + elif isinstance(p_node, exp.Placeholder) and p_node.this and not p_node.this.isdigit(): + placeholder_types_desc.append(f"named (e.g., :{p_node.this})") + elif isinstance(p_node, exp.Placeholder) and p_node.this is None: + placeholder_types_desc.append("positional (?)") + # Add more descriptions for other types like numeric $1 if necessary + # Make unique descriptions + desc_str = ", ".join(sorted(set(placeholder_types_desc))) or "unknown" + msg = f"SQL statement contains {desc_str} parameter placeholders, but no parameters were provided. SQL: {self.sql}" raise SQLParsingError(msg) # No parameters provided and none found in SQL - OK return self.sql, None # Validate provided parameters against parsed SQL parameters if isinstance(self._merged_parameters, dict): - self._validate_dict_params(sql_params, self._merged_parameters) + self._validate_dict_params(all_sqlglot_placeholders, self._merged_parameters) elif isinstance(self._merged_parameters, (tuple, list)): - self._validate_sequence_params(sql_params, self._merged_parameters) + self._validate_sequence_params(all_sqlglot_placeholders, self._merged_parameters) else: # Scalar parameter - self._validate_scalar_param(sql_params, self._merged_parameters) + self._validate_scalar_param(all_sqlglot_placeholders, self._merged_parameters) # Return the original SQL and the merged parameters for the adapter to process return self.sql, self._merged_parameters @@ -181,75 +188,124 @@ def _parse_sql(self) -> exp.Expression: msg = f"Failed to parse SQL for validation: {error_detail}\nSQL: {self.sql}" raise SQLParsingError(msg) from e - def _validate_dict_params(self, sql_params: list[exp.Parameter], parameter_dict: dict[str, Any]) -> None: - """Validates dictionary parameters against parsed SQL parameters.""" - named_sql_params = [p for p in sql_params if p.name] - unnamed_sql_params = [p for p in sql_params if not p.name] - - if unnamed_sql_params: - msg = f"Dictionary parameters provided, but found unnamed placeholders (e.g., '?') in SQL: {self.sql}" + def _validate_dict_params( + self, all_sqlglot_placeholders: list[Union[exp.Parameter, exp.Placeholder]], parameter_dict: dict[str, Any] + ) -> None: + sqlglot_named_params: dict[str, Union[exp.Parameter, exp.Placeholder]] = {} + has_positional_qmark = False + + for p_node in all_sqlglot_placeholders: + if ( + isinstance(p_node, exp.Parameter) and p_node.name and not p_node.name.isdigit() + ): # @name, $name (non-numeric) + sqlglot_named_params[p_node.name] = p_node + elif isinstance(p_node, exp.Placeholder) and p_node.this and not p_node.this.isdigit(): # :name + sqlglot_named_params[p_node.this] = p_node + elif isinstance(p_node, exp.Placeholder) and p_node.this is None: # ? + has_positional_qmark = True + # Ignores numeric placeholders like $1, :1 for dict validation for now + + if has_positional_qmark: + msg = f"Dictionary parameters provided, but found unnamed placeholders ('?') in SQL: {self.sql}" raise ParameterStyleMismatchError(msg) - if not named_sql_params and parameter_dict: - # Check with regex as a fallback confirmation if sqlglot finds no named params - regex_found = any( - match.group("var_name") - for match in PARAM_REGEX.finditer(self.sql) - if not (match.group("dquote") or match.group("squote") or match.group("comment")) - ) - if not regex_found: - msg = f"Dictionary parameters provided, but no named placeholders (e.g., ':name') found in SQL: {self.sql}" + # Regex check as a fallback (can be simplified or removed if sqlglot is trusted) + regex_named_placeholders_found = False + for match in CONSOLIDATED_PARAM_REGEX.finditer(self.sql): + if match.group("dquote") or match.group("squote") or match.group("comment"): + continue + if match.group("var_colon") or match.group("var_dollar") or match.group("var_at"): + regex_named_placeholders_found = True + + if not sqlglot_named_params and parameter_dict: + if not regex_named_placeholders_found: + msg = f"Dictionary parameters provided, but no named placeholders (e.g., ':name', '$name', '@name') found by sqlglot or regex in SQL: {self.sql}" raise ParameterStyleMismatchError(msg) - # SQLglot didn't find named params but regex did - log warning, proceed. logger.warning( "SQLglot found no named parameters, but regex did. Proceeding with validation. SQL: %s", self.sql ) - required_keys = {p.name for p in named_sql_params} + required_keys = set(sqlglot_named_params.keys()) provided_keys = set(parameter_dict.keys()) missing_keys = required_keys - provided_keys if missing_keys: - msg = f"Named parameters found in SQL but not provided: {missing_keys}. SQL: {self.sql}" + msg = f"Named parameters found in SQL by sqlglot but not provided: {missing_keys}. SQL: {self.sql}" raise SQLParsingError(msg) def _validate_sequence_params( - self, sql_params: list[exp.Parameter], params: Union[tuple[Any, ...], list[Any]] + self, + all_sqlglot_placeholders: list[Union[exp.Parameter, exp.Placeholder]], + params: Union[tuple[Any, ...], list[Any]], ) -> None: - """Validates sequence parameters against parsed SQL parameters.""" - named_sql_params = [p for p in sql_params if p.name] - unnamed_sql_params = [p for p in sql_params if not p.name] - - if named_sql_params: - # No need to store msg if we are raising immediately - msg = f"Sequence parameters provided, but found named placeholders (e.g., ':name') in SQL: {self.sql}" + sqlglot_named_param_names = [] # For detecting named params + sqlglot_positional_count = 0 # For counting ?, $1, :1 etc. + + for p_node in all_sqlglot_placeholders: + if isinstance(p_node, exp.Parameter) and p_node.name and not p_node.name.isdigit(): # @name, $name + sqlglot_named_param_names.append(p_node.name) + elif isinstance(p_node, exp.Placeholder) and p_node.this and not p_node.this.isdigit(): # :name + sqlglot_named_param_names.append(p_node.this) + elif isinstance(p_node, exp.Placeholder) and p_node.this is None: # ? + sqlglot_positional_count += 1 + elif isinstance(p_node, exp.Parameter) and ( # noqa: PLR0916 + (p_node.name and p_node.name.isdigit()) + or ( + not p_node.name + and p_node.this + and isinstance(p_node.this, (str, exp.Identifier, exp.Number)) + and str(p_node.this).isdigit() + ) + ): + # $1, :1 style (parsed as Parameter with name="1" or this="1" or this=Identifier(this="1") or this=Number(this=1)) + sqlglot_positional_count += 1 + elif ( + isinstance(p_node, exp.Placeholder) and p_node.this and p_node.this.isdigit() + ): # :1 style (Placeholder with this="1") + sqlglot_positional_count += 1 + + # Regex check (can be simplified if sqlglot part is robust) + regex_named_placeholders_found = False + for match in CONSOLIDATED_PARAM_REGEX.finditer(self.sql): + if match.group("dquote") or match.group("squote") or match.group("comment"): + continue + if match.group("var_colon") or match.group("var_dollar") or match.group("var_at"): + regex_named_placeholders_found = True + + if sqlglot_named_param_names or regex_named_placeholders_found: + found_by = [] + if sqlglot_named_param_names: + found_by.append(f"sqlglot ({', '.join(sorted(set(sqlglot_named_param_names)))})") + if regex_named_placeholders_found and not sqlglot_named_param_names: + found_by.append("regex") + msg = ( + f"Sequence parameters provided, but found named placeholders " + f"by {', '.join(found_by)} in SQL: {self.sql}" + ) raise ParameterStyleMismatchError(msg) - expected_count = len(unnamed_sql_params) - actual_count = len(params) + expected_count_sqlglot = sqlglot_positional_count + actual_count_provided = len(params) - if expected_count != actual_count: - # Double-check with regex if counts mismatch, as parsing might miss some complex cases - regex_count = 0 - for match in QMARK_REGEX.finditer(self.sql): - if match.group("qmark"): - regex_count += 1 - - if regex_count != actual_count: + if expected_count_sqlglot != actual_count_provided: + if sqlglot_positional_count != actual_count_provided: msg = ( - f"Parameter count mismatch. SQL expects {expected_count} (sqlglot) / {regex_count} (regex) positional parameters, " - f"but {actual_count} were provided. SQL: {self.sql}" + f"Parameter count mismatch. SQL expects {expected_count_sqlglot} (sqlglot) / {sqlglot_positional_count} (regex) positional '?' parameters, " + f"but {actual_count_provided} were provided. SQL: {self.sql}" ) raise SQLParsingError(msg) - # Counts mismatch with sqlglot but match with simple regex - log warning, proceed. logger.warning( - "Parameter count mismatch (sqlglot: %d, provided: %d), but regex count (%d) matches provided. Proceeding. SQL: %s", - expected_count, - actual_count, - regex_count, + "Parameter count mismatch (sqlglot: %d, provided: %d), but regex count for '?' (%d) matches provided. Proceeding. SQL: %s", + expected_count_sqlglot, + actual_count_provided, + sqlglot_positional_count, self.sql, ) - def _validate_scalar_param(self, sql_params: list[exp.Parameter], param_value: Any) -> None: + def _validate_scalar_param( + self, all_sqlglot_placeholders: list[Union[exp.Parameter, exp.Placeholder]], param_value: Any + ) -> None: """Validates a single scalar parameter against parsed SQL parameters.""" - self._validate_sequence_params(sql_params, (param_value,)) # Treat scalar as a single-element sequence + self._validate_sequence_params( + all_sqlglot_placeholders, (param_value,) + ) # Treat scalar as a single-element sequence diff --git a/tests/integration/test_adapters/test_oracledb/test_driver_sync.py b/tests/integration/test_adapters/test_oracledb/test_driver_sync.py index 9ae0ba7..78299ce 100644 --- a/tests/integration/test_adapters/test_oracledb/test_driver_sync.py +++ b/tests/integration/test_adapters/test_oracledb/test_driver_sync.py @@ -84,6 +84,10 @@ def test_sync_insert_returning(oracle_sync_session: OracleSyncConfig, params: An def test_sync_select(oracle_sync_session: OracleSyncConfig, params: Any, style: ParamStyle) -> None: """Test synchronous select functionality with Oracle parameter styles.""" with oracle_sync_session.provide_session() as driver: + # Manual cleanup at start of test + driver.execute_script( + "BEGIN EXECUTE IMMEDIATE 'DROP TABLE test_table'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;" + ) sql = """ CREATE TABLE test_table ( id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY, @@ -125,6 +129,10 @@ def test_sync_select(oracle_sync_session: OracleSyncConfig, params: Any, style: def test_sync_select_value(oracle_sync_session: OracleSyncConfig, params: Any, style: ParamStyle) -> None: """Test synchronous select_value functionality with Oracle parameter styles.""" with oracle_sync_session.provide_session() as driver: + # Manual cleanup at start of test + driver.execute_script( + "BEGIN EXECUTE IMMEDIATE 'DROP TABLE test_table'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;" + ) sql = """ CREATE TABLE test_table ( id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY, @@ -155,6 +163,10 @@ def test_sync_select_value(oracle_sync_session: OracleSyncConfig, params: Any, s def test_sync_select_arrow(oracle_sync_session: OracleSyncConfig) -> None: """Test synchronous select_arrow functionality.""" with oracle_sync_session.provide_session() as driver: + # Manual cleanup at start of test + driver.execute_script( + "BEGIN EXECUTE IMMEDIATE 'DROP TABLE test_table'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;" + ) sql = """ CREATE TABLE test_table ( id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY, diff --git a/tests/unit/test_statement.py b/tests/unit/test_statement.py new file mode 100644 index 0000000..798708a --- /dev/null +++ b/tests/unit/test_statement.py @@ -0,0 +1,287 @@ +# ruff: noqa: ERA001 +# --- Test Case Groups --- + +BASIC_PARAMETER_CASES = [ + ("Colon named", "SELECT * FROM users WHERE id = :id", [("var_colon_named", "id")]), + ("Colon numeric", "SELECT * FROM users WHERE id = :12", [("var_colon_numeric", "12")]), + ("Question mark", "SELECT * FROM users WHERE id = ?", [("var_qmark", "?")]), + ("Dollar named", "SELECT * FROM products WHERE name = $name", [("var_dollar", "name")]), + ("Dollar numeric", "SELECT * FROM products WHERE id = $12", [("var_numeric", "12")]), + ("At named", "SELECT * FROM employees WHERE email = @email", [("var_at", "email")]), + ("Pyformat named", "INSERT INTO logs (message) VALUES (%(msg)s)", [("var_pyformat", "msg")]), + ("Format type", "SELECT name FROM users WHERE status = %s", [("var_format_type", "s")]), +] + +COMMENTS_AND_STRINGS_CASES = [ + ("Inside single quotes", "SELECT * FROM users WHERE notes = 'param: :value, other: ?'", []), + ("Inside double quotes", 'SELECT * FROM users WHERE description = "param: :value, other: ?"', []), + ("Single quotes with escaped quote", "SELECT 'It''s value: :not_param' FROM test", []), + ("Double quotes with escaped quote", 'SELECT "It""s value: :not_param" FROM test', []), + ("Inside single-line comment", "SELECT * FROM users; -- id = :id, name = $name, status = ?", []), + ("Inside multi-line comment", "SELECT * FROM users; /* id = :id, name = $name, status = ? */", []), + ( + "Multi-line comment with params", + "/* \n :param1 \n ? \n $param2 \n @param3 \n %(param4)s \n %d \n $5 \n */ SELECT 1", + [], + ), +] + +MIXED_AND_MULTIPLE_CASES = [ + ( + "Mixed parameters", + "SELECT * FROM orders WHERE id = :order_id AND customer_id = @customer AND product_id = $prod AND user_id = ? AND tracking_code = %(track)s AND status = %s AND region_id = $1", + [ + ("var_colon_named", "order_id"), + ("var_at", "customer"), + ("var_dollar", "prod"), + ("var_qmark", "?"), + ("var_pyformat", "track"), + ("var_format_type", "s"), + ("var_numeric", "1"), + ], + ), + ("Multiple colon named", "SELECT :value1, :value2", [("var_colon_named", "value1"), ("var_colon_named", "value2")]), + ("Multiple question mark", "SELECT ?, ?", [("var_qmark", "?"), ("var_qmark", "?")]), + ( + "Multiple dollar (numeric and named)", + "SELECT $1, $2, $name_val", + [("var_numeric", "1"), ("var_numeric", "2"), ("var_dollar", "name_val")], + ), + ( + "Multiple percent (format and pyformat)", + "SELECT %s, %(name_val)s, %d", + [("var_format_type", "s"), ("var_pyformat", "name_val"), ("var_format_type", "d")], + ), +] + +EDGE_CASES = [ + ( + "Complex with comment and quotes", + "SELECT data->>'key' as val, :param1 FROM test WHERE id = $1; -- :ignored_param 'text' /* :ignored2 */", + [("var_colon_named", "param1"), ("var_numeric", "1")], + ), + ( + "Param after escaped quote", + "SELECT * FROM test WHERE name = 'it''s a test :not_a_param' AND value = :param_actual", + [("var_colon_named", "param_actual")], + ), + ( + "Param after single line comment", + "SELECT * FROM test WHERE name = 'foo' -- :param_in_comment \n AND id = :actual_param", + [("var_colon_named", "actual_param")], + ), + ( + "Param after multi-line comment", + "SELECT * FROM test /* \n multiline comment with :param \n */ WHERE id = :actual_param2", + [("var_colon_named", "actual_param2")], + ), + ( + "All ignored, one real param at end", + "SELECT 'abc :np1', \"def :np2\", -- :np3 \n /* :np4 */ :real_param", + [("var_colon_named", "real_param")], + ), +] + +NAMING_VARIATIONS = [ + ( + "Colon named with numbers", + "SELECT 1 from table where value = :value_1_numeric", + [("var_colon_named", "value_1_numeric")], + ), + ("Colon numeric only", "SELECT 1 from table where value = :123", [("var_colon_numeric", "123")]), + ( + "Dollar named with numbers", + "SELECT 1 from table where value = $value_1_numeric", + [("var_dollar", "value_1_numeric")], + ), + ("Dollar numeric only", "SELECT 1 from table where value = $123", [("var_numeric", "123")]), + ("At named with numbers", "SELECT 1 from table where value = @value_1_numeric", [("var_at", "value_1_numeric")]), + ( + "Pyformat named with numbers", + "SELECT 1 from table where value = %(value_1_pyformat)s", + [("var_pyformat", "value_1_pyformat")], + ), + ("Format type (d)", "SELECT 1 from table where value = %d", [("var_format_type", "d")]), +] + +LOOKAROUND_SYNTAX_CASES = [ + ("SQL cast ::text", "SELECT foo FROM bar WHERE baz = mycol::text", [("var_colon_named", "text")]), + ("SQL cast ::numeric", "SELECT foo FROM bar WHERE baz = mycol::12", [("var_colon_numeric", "12")]), + ( + "Double percent format type %s%s", + "SELECT foo FROM bar WHERE baz = %s%s", + [("var_format_type", "s"), ("var_format_type", "s")], + ), + ( + "Double pyformat %(n)s%(a)s", + "SELECT foo FROM bar WHERE baz = %(name)s%(another)s", + [("var_pyformat", "name"), ("var_pyformat", "another")], + ), +] + +PERCENT_STYLE_EDGE_CASES = [ + ("Single %s", "SELECT %s", [("var_format_type", "s")]), + ("Double %%s (escaped %)", "SELECT %%s", []), + ("Triple %%%s (literal % + param %s)", "SELECT %%%s", [("var_format_type", "s")]), + ("Quadruple %%%%s (two literal %%)", "SELECT %%%%s", []), + ("Single %(name)s", "SELECT %(name)s", [("var_pyformat", "name")]), + ("Double %%(name)s", "SELECT %%(name)s", []), + ("Triple %%%(name)s", "SELECT %%%(name)s", [("var_pyformat", "name")]), +] + +DOLLAR_AT_COLON_EDGE_CASES = [ + ("Single $name", "SELECT $name", [("var_dollar", "name")]), + ("Double $$name (not a var)", "SELECT $$name", []), + ("Triple $$$name (literal $ + var)", "SELECT $$$name", [("var_dollar", "name")]), + ("Single $1", "SELECT $1", [("var_numeric", "1")]), + ("Double $$1 (not a var)", "SELECT $$1", []), + ("Triple $$$1 (literal $ + var)", "SELECT $$$1", [("var_numeric", "1")]), + ("Single @name", "SELECT @name", [("var_at", "name")]), + ("Double @@name (not a var)", "SELECT @@name", []), + ("Triple @@@name (literal @ + var)", "SELECT @@@name", [("var_at", "name")]), + ("word:name (not a var)", "SELECT word:name FROM t", []), + ("_val:name (not a var)", "SELECT _val:name FROM t", []), + ("val_val:name (not a var)", "SELECT val_val:name FROM t", []), + ("word:1 (not a var)", "SELECT word:1 FROM t", []), + ("::name (handled by cast test)", "SELECT foo::name", [("var_colon_named", "name")]), +] + +POSTGRES_JSON_OP_CASES = [ + ("Postgres JSON op ??", "SELECT * FROM test WHERE json_col ?? 'key'", [("var_qmark", "?"), ("var_qmark", "?")]), + ( + "Postgres JSON op ?? with param", + "SELECT id FROM test WHERE json_col ?? 'key' AND id = ?", + [("var_qmark", "?"), ("var_qmark", "?"), ("var_qmark", "?")], + ), + ( + "Postgres JSON op ?|", + "SELECT data FROM test WHERE tags ?| array['tag1'] AND id = ?", + [("var_qmark", "?"), ("var_qmark", "?")], + ), + ( + "Postgres JSON op ?&", + "SELECT data FROM test WHERE tags ?& array['tag1'] AND id = ?", + [("var_qmark", "?"), ("var_qmark", "?")], + ), +] + + +# # --- Helper --- +# def _transform_regex_params_for_test(sql: str, params_info: Optional[list[RegexParamInfo]]) -> list[tuple[str, str]]: +# """ +# Transforms the RegexParamInfo list from SQLStatement into the format +# expected by the test cases: List[Tuple[param_type_group_name, param_value]]. +# """ +# if not params_info: +# return [] +# output = [] +# for p_info in params_info: +# style = p_info.style +# name = p_info.name +# val: str = "" +# var_group: str = "" +# if style == "colon": +# var_group = "var_colon_named" +# val = name or "" +# elif style == "colon_numeric": +# var_group = "var_colon_numeric" +# val = sql[p_info.start_pos + 1 : p_info.end_pos] +# elif style == "qmark": +# var_group = "var_qmark" +# val = sql[p_info.start_pos : p_info.end_pos] +# elif style == "dollar": +# var_group = "var_dollar" +# val = name or "" +# elif style == "numeric": +# var_group = "var_numeric" +# val = sql[p_info.start_pos + 1 : p_info.end_pos] +# elif style == "at": +# var_group = "var_at" +# val = name or "" +# elif style == "pyformat": +# var_group = "var_pyformat" +# val = name or "" +# elif style == "format": +# var_group = "var_format_type" +# val = sql[p_info.start_pos + 1 : p_info.end_pos] +# else: +# raise ValueError(f"Unknown RegexParamInfo style: {style}") +# output.append((var_group, val)) +# return output + + +# # --- Test Functions --- + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), BASIC_PARAMETER_CASES) +# def test_basic_parameter_types(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), COMMENTS_AND_STRINGS_CASES) +# def test_parameters_ignored_in_comments_and_strings( +# description: str, sql: str, expected_params: list[tuple[str, str]] +# ) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), MIXED_AND_MULTIPLE_CASES) +# def test_mixed_and_multiple_parameters(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), EDGE_CASES) +# def test_edge_cases(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), NAMING_VARIATIONS) +# def test_parameter_naming_variations(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), LOOKAROUND_SYNTAX_CASES) +# def test_lookaround_and_syntax_interaction(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), PERCENT_STYLE_EDGE_CASES) +# def test_percent_style_edge_cases(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), DOLLAR_AT_COLON_EDGE_CASES) +# def test_dollar_at_colon_edge_cases(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" + + +# @pytest.mark.parametrize(("description", "sql", "expected_params"), POSTGRES_JSON_OP_CASES) +# def test_postgres_json_operator_cases(description: str, sql: str, expected_params: list[tuple[str, str]]) -> None: +# stmt = SQLStatement(sql=sql) +# discovered_info = stmt._regex_discovered_params +# actual = _transform_regex_params_for_test(sql, discovered_info) +# assert actual == expected_params, f"{description}\nSQL: {sql}\nExpected: {expected_params}\nActual: {actual}" From c63debcdd1493ff14e492aa8e02a9e460b282e6c Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Sun, 11 May 2025 17:47:16 +0000 Subject: [PATCH 05/11] feat: sqlglot updates --- .pre-commit-config.yaml | 4 +- pyproject.toml | 2 + sqlspec/adapters/adbc/driver.py | 447 +++++++----------- sqlspec/adapters/aiosqlite/driver.py | 219 +++------ sqlspec/adapters/asyncmy/driver.py | 231 +++------ sqlspec/adapters/asyncpg/driver.py | 235 ++++----- sqlspec/adapters/bigquery/driver.py | 316 ++++--------- sqlspec/adapters/duckdb/driver.py | 179 +------ sqlspec/adapters/oracledb/driver.py | 226 ++------- sqlspec/adapters/psqlpy/driver.py | 211 ++++----- sqlspec/adapters/psycopg/driver.py | 258 ++++------ sqlspec/adapters/sqlite/driver.py | 170 ++----- sqlspec/base.py | 3 +- sqlspec/extensions/litestar/handlers.py | 23 +- sqlspec/filters.py | 206 +++++++- sqlspec/statement.py | 347 ++++++++------ sqlspec/typing.py | 19 +- .../test_adbc/test_driver_sqlite.py | 8 - .../test_adapters/test_asyncpg/test_driver.py | 120 +++++ .../test_adapters/test_psqlpy/test_driver.py | 132 +++++- tests/unit/test_statement.py | 2 +- uv.lock | 417 ++++++++-------- 22 files changed, 1652 insertions(+), 2123 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 50271d5..d8e2def 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ default_language_version: python: "3" repos: - repo: https://github.com/compilerla/conventional-pre-commit - rev: v4.1.0 + rev: v4.2.0 hooks: - id: conventional-pre-commit stages: [commit-msg] @@ -17,7 +17,7 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: "v0.11.8" + rev: "v0.11.9" hooks: - id: ruff args: ["--fix"] diff --git a/pyproject.toml b/pyproject.toml index 0d5cc9c..1a8b100 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -323,8 +323,10 @@ convention = "google" max-complexity = 25 [tool.ruff.lint.pylint] +max-bool-expr = 10 max-branches = 20 max-locals = 20 +max-returns = 15 [tool.ruff.lint.pep8-naming] classmethod-decorators = ["classmethod"] diff --git a/sqlspec/adapters/adbc/driver.py b/sqlspec/adapters/adbc/driver.py index d39f99e..8366bd6 100644 --- a/sqlspec/adapters/adbc/driver.py +++ b/sqlspec/adapters/adbc/driver.py @@ -1,18 +1,18 @@ -# ruff: noqa: PLR0915, C901, PLR0912, PLR0911 import contextlib import logging +import re from collections.abc import Generator, Sequence from contextlib import contextmanager from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union, cast, overload -import sqlglot from adbc_driver_manager.dbapi import Connection, Cursor from sqlglot import exp as sqlglot_exp from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin -from sqlspec.typing import ArrowTable, StatementParameterType +from sqlspec.statement import SQLStatement +from sqlspec.typing import ArrowTable, StatementParameterType, is_dict if TYPE_CHECKING: from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T @@ -23,6 +23,13 @@ AdbcConnection = Connection +# SQLite named parameter pattern - simple pattern to find parameter references +SQLITE_PARAM_PATTERN = re.compile(r"(?::|\$|@)([a-zA-Z0-9_]+)") + +# Patterns to identify comments and string literals +SQL_COMMENT_PATTERN = re.compile(r"--[^\n]*|/\*.*?\*/", re.DOTALL) +SQL_STRING_PATTERN = re.compile(r"'[^']*'|\"[^\"]*\"") + class AdbcDriver( SyncArrowBulkOperationsMixin["AdbcConnection"], @@ -78,317 +85,197 @@ def _with_cursor(self, connection: "AdbcConnection") -> Generator["Cursor", None with contextlib.suppress(Exception): cursor.close() # type: ignore[no-untyped-call] - def _process_sql_params( + def _process_sql_params( # noqa: C901, PLR0912, PLR0915 self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any, ) -> "tuple[str, Optional[tuple[Any, ...]]]": # Always returns tuple or None for params - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], Sequence[Any], Any]] = None # Allow Any for scalar + """Process SQL and parameters for ADBC. + + ADBC drivers generally use positional parameters with '?' placeholders. + This method processes the SQL statement and transforms parameters into the format + expected by ADBC drivers. + + Args: + sql: The SQL statement to process. + parameters: The parameters to bind to the statement. + **kwargs: Additional keyword arguments (including filters). + + Raises: + SQLParsingError: If the SQL statement cannot be parsed. + ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. + + Returns: + A tuple of (sql, parameters) ready for execution. + """ + # Special handling for SQLite with non-dict parameters and named placeholders + if self.dialect == "sqlite" and parameters is not None and not is_dict(parameters): + # First mask out comments and strings to avoid detecting parameters in those + comments = list(SQL_COMMENT_PATTERN.finditer(sql)) + strings = list(SQL_STRING_PATTERN.finditer(sql)) + + all_matches = [(m.start(), m.end(), "comment") for m in comments] + [ + (m.start(), m.end(), "string") for m in strings + ] + all_matches.sort(reverse=True) + + for start, end, _ in all_matches: + sql = sql[:start] + " " * (end - start) + sql[end:] + + # Find named parameters in clean SQL + named_params = list(SQLITE_PARAM_PATTERN.finditer(sql)) + + if named_params: + param_positions = [(m.start(), m.end()) for m in named_params] + param_positions.sort(reverse=True) + for start, end in param_positions: + sql = sql[:start] + "?" + sql[end:] + if not isinstance(parameters, (list, tuple)): + return sql, (parameters,) + return sql, tuple(parameters) + + # Standard processing for all other cases + merged_params = parameters if kwargs: - if isinstance(parameters, dict): + if is_dict(parameters): merged_params = {**parameters, **kwargs} elif parameters is not None: msg = "Cannot mix positional parameters with keyword arguments for adbc driver." raise ParameterStyleMismatchError(msg) else: merged_params = kwargs - elif parameters is not None: - merged_params = parameters - # else merged_params remains None - - # 2. SQLGlot Parsing - Use the determined dialect for reading if possible - # For ADBC, the input SQL style might be generic, so a neutral read dialect or auto-detection might be safer initially. - # However, self.dialect is set in __init__ based on the connection. - # If the input SQL is guaranteed to match self.dialect, this is fine. - # If SQL can be :name style while dialect is e.g. postgres, sqlglot needs to know. - # Defaulting to parsing with the target dialect; an explicit read_dialect can be added if needed. - try: - # The `read` dialect might need to be more flexible if input SQL doesn't match target ADBC driver dialect. - # For now, assume input SQL should be somewhat compatible or generic enough for sqlglot to parse with target dialect hints. - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"ADBC ({self.dialect}): Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - sql_named_param_nodes = [ - node for node in parsed_expression.find_all(sqlglot_exp.Parameter) if node.name and not node.name.isdigit() - ] - sql_placeholder_nodes = list( - parsed_expression.find_all(sqlglot_exp.Placeholder) - ) # Represents '?' and also ':name' for some dialects - - # More robust detection of numeric parameters (e.g., $1, :1) - sql_numeric_nodes = [] - for node in parsed_expression.find_all(sqlglot_exp.Parameter): - is_numeric = False - if node.name and isinstance(node.name, str) and node.name.isdigit(): # e.g. @1 - is_numeric = True - elif not node.name and node.this: - # Combined and corrected multi-line condition - is_identifier_numeric = ( - isinstance(node.this, sqlglot_exp.Identifier) - and node.this.this - and isinstance(node.this.this, str) - and node.this.this.isdigit() - ) - if ( - (isinstance(node.this, str) and node.this.isdigit()) - or is_identifier_numeric - or isinstance(node.this, sqlglot.exp.Number) - ): # Corrected: sqlglot.exp.Number - is_numeric = True - if is_numeric: - sql_numeric_nodes.append(node) - - # Numeric placeholders like :1, :2 (parsed as Placeholder(this="1")) - numeric_placeholder_nodes = [ - p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and p_node.this.isdigit() - ] - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or sql_placeholder_nodes or sql_numeric_nodes: - placeholder_types = set() - if sql_named_param_nodes: - placeholder_types.add("named (e.g., :name, @name, $name)") - if sql_placeholder_nodes: - placeholder_types.add("positional ('?')") - if sql_numeric_nodes: - placeholder_types.add("numeric (e.g., $1, :1)") - msg = ( - f"ADBC ({self.dialect}): SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - # ADBC execute often expects list/tuple for parameters argument, even if empty. - return sql, () - final_sql: str - final_params_seq: list[Any] = [] + # 2. Create SQLStatement with dialect and process + statement = SQLStatement(sql, merged_params, dialect=self.dialect) - target_dialect = self.dialect # Dialect determined from ADBC connection + # Apply any filters if present + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) - if isinstance(merged_params, dict): - has_qmark_placeholders = any( - p_node.this is None # Removed isinstance check as p_node is already known to be Placeholder - for p_node in sql_placeholder_nodes - ) + processed_sql, processed_params, parsed_expr = statement.process() - if has_qmark_placeholders or numeric_placeholder_nodes or sql_numeric_nodes: - msg = ( - f"ADBC ({target_dialect}): Dictionary parameters provided, but SQL uses positional " - f"placeholders ('?', $N, or :N). Use named placeholders (e.g. :name, @name, $name)." - ) - raise ParameterStyleMismatchError(msg) + # Special handling for SQLite dialect with dict parameters + if self.dialect == "sqlite" and is_dict(processed_params): + # First, mask out comments and string literals with placeholders + masked_sql = processed_sql + + # Replace comments and strings with placeholders + comments = list(SQL_COMMENT_PATTERN.finditer(masked_sql)) + strings = list(SQL_STRING_PATTERN.finditer(masked_sql)) - # Validate keys - colon_named_placeholder_nodes = [ - p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and not p_node.this.isdigit() + # Sort all matches by their start position (descending) + all_matches = [(m.start(), m.end(), "comment") for m in comments] + [ + (m.start(), m.end(), "string") for m in strings ] - all_ast_named_params = {node.name for node in sql_named_param_nodes if node.name} - all_ast_named_params.update( - node.this for node in colon_named_placeholder_nodes if isinstance(node.this, str) - ) - - provided_keys = set(merged_params.keys()) - missing_keys = all_ast_named_params - provided_keys - if missing_keys: - msg = f"ADBC ({target_dialect}): Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - extra_keys = provided_keys - all_ast_named_params - if extra_keys: - logger.warning( - f"ADBC ({target_dialect}): Parameters {extra_keys} provided but not found in SQL. Behavior depends on underlying driver. SQL: {sql}" + all_matches.sort(reverse=True) + + # Replace each match with spaces to preserve positions + for start, end, _ in all_matches: + masked_sql = masked_sql[:start] + " " * (end - start) + masked_sql[end:] + + # Now find parameters in the masked SQL + param_order = [] + param_spans = [] # Store (start, end) of each parameter + + for match in SQLITE_PARAM_PATTERN.finditer(masked_sql): + param_name = match.group(1) + if param_name in processed_params: + param_order.append(param_name) + param_spans.append((match.start(), match.end())) + + if param_order: + # Replace parameters with ? placeholders in reverse order to preserve positions + result_sql = processed_sql + for i, (start, end) in enumerate(reversed(param_spans)): # noqa: B007 + # Replace :param with ? + result_sql = result_sql[:start] + "?" + result_sql[start + 1 + len(param_order[-(i + 1)]) :] + + return result_sql, tuple(processed_params[name] for name in param_order) + + if processed_params is None: + return processed_sql, () + if ( + isinstance(processed_params, (tuple, list)) + or (processed_params is not None and not isinstance(processed_params, dict)) + ) and parsed_expr is not None: + # Find all named placeholders + named_param_nodes = [ + node + for node in parsed_expr.find_all(sqlglot_exp.Parameter, sqlglot_exp.Placeholder) + if (isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit()) + or ( + isinstance(node, sqlglot_exp.Placeholder) + and node.this + and not isinstance(node.this, (sqlglot_exp.Identifier, sqlglot_exp.Literal)) + and not str(node.this).isdigit() ) - - # Transformation logic: convert all named styles to '?' and populate final_params_seq - final_params_seq.clear() - - def _convert_any_named_to_qmark(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: - param_name_to_check = None - if isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit(): - param_name_to_check = node.name - elif ( - isinstance(node, sqlglot_exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit() - ): - param_name_to_check = node.this - - if param_name_to_check and param_name_to_check in merged_params: # merged_params is a dict here - final_params_seq.append(merged_params[param_name_to_check]) - return sqlglot_exp.Placeholder() # Anonymous placeholder '?' - return node - - transformed_expression = parsed_expression.transform(_convert_any_named_to_qmark, copy=True) - final_sql = transformed_expression.sql(dialect=target_dialect) - - elif isinstance(merged_params, (list, tuple)): - # Collect all types of placeholders from SQL - qmark_placeholders_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) - - # Named placeholders from sqlglot_exp.Parameter (e.g., @name, $name) - # sql_named_param_nodes is already defined - - # Named placeholders from sqlglot_exp.Placeholder (e.g., :name) - colon_named_placeholder_nodes = [ - p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and not p_node.this.isdigit() ] - # Numeric placeholders (e.g., $1, :1) - from both Parameter and Placeholder nodes - # numeric_placeholder_nodes and sql_numeric_nodes are already defined + # If we found named parameters, transform to question marks + if named_param_nodes: - # Get all named parameters in order of appearance in the AST - ordered_named_params_in_ast = [] - # We need to iterate through the AST to get them in order. find_all gives traversal order. - for node in parsed_expression.find_all(sqlglot_exp.Parameter, sqlglot_exp.Placeholder): - if isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit(): - ordered_named_params_in_ast.append(node.name) - elif ( - isinstance(node, sqlglot_exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit() - ): - ordered_named_params_in_ast.append(node.this) - - # Remove duplicates while preserving order for mapping if needed (though duplicates might be intended by user in some complex SQLs) - # For now, let's assume unique placeholders for mapping tuple to names. If SQL has duplicate named params, - # this logic might need adjustment or clarification on expected behavior. - # A simpler approach for now: just count unique types. - - has_any_named_placeholders = bool(sql_named_param_nodes or colon_named_placeholder_nodes) - has_any_positional_or_numeric = bool( - qmark_placeholders_count or numeric_placeholder_nodes or sql_numeric_nodes - ) - - if has_any_named_placeholders: - if has_any_positional_or_numeric: - msg = f"ADBC ({target_dialect}): Sequence parameters provided, but SQL mixes named and positional/numeric placeholders. This is not supported." - raise ParameterStyleMismatchError(msg) - - # SQL has only named placeholders. Try to map sequence params to them by order. - # Re-extract ordered unique named parameter *names* for mapping. - # find_all preserves order. To get unique names in order: - unique_ordered_named_param_names = list( - dict.fromkeys(ordered_named_params_in_ast) - ) # Python 3.7+ dict preserves insertion order - - if len(unique_ordered_named_param_names) != len(merged_params): - msg = ( - f"ADBC ({target_dialect}): Sequence parameters provided (count: {len(merged_params)}), " - f"but SQL has {len(unique_ordered_named_param_names)} unique named placeholders. Counts must match." - ) - raise SQLParsingError(msg) - - # Create a temporary dict from named params and sequence values - temp_dict_params = dict(zip(unique_ordered_named_param_names, merged_params)) - - # Now, use the same transformation as the dict instance block - final_params_seq.clear() - - def _convert_any_named_to_qmark_for_seq(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: - param_name_to_check = None - if isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit(): - param_name_to_check = node.name - elif ( + def convert_to_qmark(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: + if (isinstance(node, sqlglot_exp.Parameter) and node.name and not node.name.isdigit()) or ( isinstance(node, sqlglot_exp.Placeholder) - and isinstance(node.this, str) - and not node.this.isdigit() + and node.this + and not isinstance(node.this, (sqlglot_exp.Identifier, sqlglot_exp.Literal)) + and not str(node.this).isdigit() ): - param_name_to_check = node.this - - if param_name_to_check and param_name_to_check in temp_dict_params: - final_params_seq.append(temp_dict_params[param_name_to_check]) - return sqlglot_exp.Placeholder() # Anonymous placeholder '?' + return sqlglot_exp.Placeholder() return node - transformed_expression = parsed_expression.transform(_convert_any_named_to_qmark_for_seq, copy=True) - final_sql = transformed_expression.sql(dialect=target_dialect) - - elif has_any_positional_or_numeric: # SQL has only positional/numeric (or qmark) placeholders - final_sql = parsed_expression.sql( - dialect=target_dialect - ) # Ensure it's in target dialect form (e.g. ? -> $1) - expected_param_count = ( - qmark_placeholders_count + len(numeric_placeholder_nodes) + len(sql_numeric_nodes) - ) - if expected_param_count != len(merged_params): - msg = ( - f"ADBC ({target_dialect}): Parameter count mismatch. SQL expects {expected_param_count} " - f"positional parameters, but {len(merged_params)} were provided. SQL: {sql}, Processed SQL: {final_sql}" - ) - raise SQLParsingError(msg) - final_params_seq.extend(merged_params) - else: # No placeholders in SQL, but sequence params provided - if merged_params: # If params is not an empty tuple/list - msg = f"ADBC ({target_dialect}): Sequence parameters provided, but SQL has no placeholders." - raise SQLParsingError(msg) - # If merged_params is empty sequence and no placeholders, that's fine. - final_sql = sql # No transformation needed - # final_params_seq remains empty, which is correct - - elif merged_params is not None: # Scalar parameter - qmark_placeholders_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) - colon_named_placeholder_nodes = [ - p_node for p_node in sql_placeholder_nodes if isinstance(p_node.this, str) and not p_node.this.isdigit() - ] + # Transform the SQL + processed_sql = parsed_expr.transform(convert_to_qmark, copy=True).sql(dialect=self.dialect) - total_named_placeholders = len(sql_named_param_nodes) + len(colon_named_placeholder_nodes) - total_positional_or_numeric_placeholders = ( - qmark_placeholders_count + len(numeric_placeholder_nodes) + len(sql_numeric_nodes) - ) + # If it's a scalar parameter, ensure it's wrapped in a tuple + if not isinstance(processed_params, (tuple, list)): + processed_params = (processed_params,) # type: ignore[unreachable] - if total_named_placeholders > 0 and total_positional_or_numeric_placeholders > 0: - # SQL mixes named and positional/numeric types, not allowed with scalar param. - msg = ( - f"ADBC ({target_dialect}): Scalar parameter provided, but SQL mixes named and positional/numeric " - f"placeholders. Use a single placeholder of one type." - ) - raise ParameterStyleMismatchError(msg) + # 6. Handle dictionary parameters + if is_dict(processed_params): + # Skip conversion if there's no parsed expression to work with + if parsed_expr is None: + msg = f"ADBC ({self.dialect}): Failed to parse SQL with dictionary parameters. Cannot determine parameter order." + raise SQLParsingError(msg) - if total_named_placeholders == 1 and total_positional_or_numeric_placeholders == 0: - # Case: Scalar param with exactly one NAMED placeholder (e.g., :name, @name) - final_params_seq.clear() - single_named_param_name = None - if sql_named_param_nodes: # @name style - single_named_param_name = sql_named_param_nodes[0].name - elif colon_named_placeholder_nodes: # :name style - single_named_param_name = colon_named_placeholder_nodes[0].this - - def _convert_the_one_named_to_qmark(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: - # This function assumes single_named_param_name is correctly identified - if (isinstance(node, sqlglot_exp.Parameter) and node.name == single_named_param_name) or ( - isinstance(node, sqlglot_exp.Placeholder) and node.this == single_named_param_name + # Collect named parameters in the order they appear in the SQL + named_params = [] + for node in parsed_expr.find_all(sqlglot_exp.Parameter, sqlglot_exp.Placeholder): + if isinstance(node, sqlglot_exp.Parameter) and node.name and node.name in processed_params: + named_params.append(node.name) # type: ignore[arg-type] + elif ( + isinstance(node, sqlglot_exp.Placeholder) + and isinstance(node.this, str) + and node.this in processed_params + ): + named_params.append(node.this) # type: ignore[arg-type] + + # If we found named parameters, convert them to ? placeholders + if named_params: + # Transform SQL to use ? placeholders + def convert_to_qmark(node: sqlglot_exp.Expression) -> sqlglot_exp.Expression: + if isinstance(node, sqlglot_exp.Parameter) and node.name and node.name in processed_params: + return sqlglot_exp.Placeholder() # Anonymous ? placeholder + if ( + isinstance(node, sqlglot_exp.Placeholder) + and isinstance(node.this, str) + and node.this in processed_params ): - final_params_seq.append(merged_params) # Directly use scalar - return sqlglot_exp.Placeholder() # Anonymous placeholder '?' + return sqlglot_exp.Placeholder() # Anonymous ? placeholder return node - transformed_expression = parsed_expression.transform(_convert_the_one_named_to_qmark, copy=True) - final_sql = transformed_expression.sql(dialect=target_dialect) - - elif total_positional_or_numeric_placeholders == 1 and total_named_placeholders == 0: - # Case: Scalar param with exactly one POSITIONAL/NUMERIC placeholder (e.g., ?, $1) - final_sql = parsed_expression.sql(dialect=target_dialect) # Ensure correct dialect form (e.g. ? -> $1) - final_params_seq.append(merged_params) - - elif total_named_placeholders == 0 and total_positional_or_numeric_placeholders == 0: - # Case: Scalar param, but SQL has NO placeholders at all. - msg = f"ADBC ({target_dialect}): Scalar parameter provided, but SQL has no parameter placeholders." - raise SQLParsingError(msg) - - else: - # Any other scenario: e.g. multiple named, multiple positional, etc. - msg = ( - f"ADBC ({target_dialect}): Scalar parameter provided, but SQL placeholder configuration is invalid. " - f"Found {total_named_placeholders} named and {total_positional_or_numeric_placeholders} positional/numeric placeholders. " - f"Expected exactly one placeholder of a consistent type for a scalar parameter." + return parsed_expr.transform(convert_to_qmark, copy=True).sql(dialect=self.dialect), tuple( + processed_params[name] # type: ignore[index] + for name in named_params ) - raise ParameterStyleMismatchError(msg) - - else: - return sql, () - - return final_sql, tuple(final_params_seq) + return processed_sql, tuple(processed_params.values()) + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + return processed_sql, (processed_params,) @overload def select( diff --git a/sqlspec/adapters/aiosqlite/driver.py b/sqlspec/adapters/aiosqlite/driver.py index 62066f8..9fefda3 100644 --- a/sqlspec/adapters/aiosqlite/driver.py +++ b/sqlspec/adapters/aiosqlite/driver.py @@ -3,13 +3,12 @@ from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload import aiosqlite -import sqlglot from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin from sqlspec.statement import SQLStatement +from sqlspec.typing import is_dict if TYPE_CHECKING: from collections.abc import AsyncGenerator, Sequence @@ -53,169 +52,63 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # 1. Use SQLStatement for initial processing and validation - stmt = SQLStatement(sql, parameters, kwargs=kwargs) - original_sql, merged_params = stmt.process() # `process` returns original_sql and merged_params + """Process SQL and parameters for aiosqlite using SQLStatement. - if merged_params is None: - return original_sql, None + aiosqlite supports both named (:name) and positional (?) parameters. + This method processes the SQL with dialect-aware parsing and handles + parameters appropriately for aiosqlite. - try: - parsed_expression = sqlglot.parse_one(original_sql, read=self.dialect) - except Exception as e: - msg = f"aiosqlite: Failed to re-parse SQL with sqlglot after SQLStatement validation: {e}. SQL: {original_sql}" - raise SQLParsingError(msg) from e - - final_sql: str = original_sql - final_params_tuple: Optional[tuple[Any, ...]] = None - - if isinstance(merged_params, dict): - actual_named_placeholders_in_ast: dict[str, Union[exp.Parameter, exp.Placeholder]] = {} - has_true_qmark_placeholders = False - - for node in parsed_expression.find_all(exp.Placeholder, exp.Parameter): - if isinstance(node, exp.Parameter) and node.name and not node.name.isdigit(): - actual_named_placeholders_in_ast[node.name] = node - elif isinstance(node, exp.Placeholder) and node.this and not node.this.isdigit(): # :name - actual_named_placeholders_in_ast[node.this] = node - elif isinstance(node, exp.Placeholder) and node.this is None: # ? - has_true_qmark_placeholders = True - - if has_true_qmark_placeholders: - msg = "aiosqlite: Dictionary parameters provided, but SQL uses '?' placeholders. Use named placeholders (e.g., :name)." - raise ParameterStyleMismatchError(msg) - - if not actual_named_placeholders_in_ast and merged_params: - # If merged_params is not empty and no named placeholders found. - msg = "aiosqlite: Dictionary parameters provided, but no recognizable named placeholders found in SQL." - raise ParameterStyleMismatchError(msg) - if not actual_named_placeholders_in_ast and not merged_params: - # Empty dict params and no named placeholders, this is fine, but should have been caught by merged_params is None earlier if truly no params. - # If merged_params is an empty dict, it implies user intended named params but provided none. - # However, if SQL also has no named params, it could be a query without params. - # This path should be less common due to the `merged_params is None` check. - pass # Allowing empty dict with SQL that has no named params found by sqlglot. - - sql_param_names_in_ast = set(actual_named_placeholders_in_ast.keys()) - provided_keys = set(merged_params.keys()) - - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"aiosqlite: Named parameters {missing_keys} found in SQL but not provided. SQL: {original_sql}" - raise SQLParsingError(msg) - - extra_keys = provided_keys - sql_param_names_in_ast - if extra_keys: - logger.warning( - f"aiosqlite: Parameters {extra_keys} provided but not found in SQL. They will be ignored. SQL: {original_sql}" - ) - - ordered_param_values: list[Any] = [] - - def _convert_named_to_qmark(node_transform: exp.Expression) -> exp.Expression: - param_name = None - if ( - isinstance(node_transform, exp.Parameter) - and node_transform.name - and not node_transform.name.isdigit() - ): - param_name = node_transform.name - elif ( - isinstance(node_transform, exp.Placeholder) - and node_transform.this - and not node_transform.this.isdigit() - ): - param_name = node_transform.this - - if param_name and param_name in merged_params: - ordered_param_values.append(merged_params[param_name]) - return exp.Placeholder() # Represents '?' - return node_transform - - transformed_expression = parsed_expression.transform(_convert_named_to_qmark, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - final_params_tuple = tuple(ordered_param_values) - - elif isinstance(merged_params, (list, tuple)): - # Logic for sequence parameters (should be largely correct now thanks to SQLStatement updates) - # SQLStatement already validated that if sequence params are given, SQL doesn't have named placeholders. - # It also validated counts if it could parse qmarks. The main task here is to ensure dialect-specific SQL. - sql_placeholder_nodes = list( - parsed_expression.find_all(exp.Placeholder) - ) # Re-fetch for this block if needed - sql_numeric_param_nodes = [ # Simplified numeric detection for sqlite context, primarily expecting ? - node - for node in parsed_expression.find_all(exp.Parameter) - if (node.name and node.name.isdigit()) - or (not node.name and node.this and isinstance(node.this, str) and node.this.isdigit()) - ] - qmark_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) - numeric_count = len(sql_numeric_param_nodes) - # For aiosqlite (sqlite), we primarily expect '?' (qmark). $N is not native. - # SQLStatement should have validated this. If SQL had $N, it should be an error from SQLStatement if dialect is sqlite. - # Here, we just ensure final SQL is in '?' form if it wasn't already. - - # This check is somewhat redundant if SQLStatement.process() worked correctly. - # It should have raised ParameterStyleMismatchError if named params were in SQL with sequence input. - has_named_placeholders_in_ast = False - for node in parsed_expression.find_all(exp.Placeholder, exp.Parameter): - if (isinstance(node, exp.Parameter) and node.name and not node.name.isdigit()) or ( - isinstance(node, exp.Placeholder) and node.this and not node.this.isdigit() - ): - has_named_placeholders_in_ast = True - break - if has_named_placeholders_in_ast: - msg = f"aiosqlite: Sequence parameters provided, but SQL unexpectedly contains named placeholders after SQLStatement validation. SQL: {original_sql}" - raise ParameterStyleMismatchError(msg) - - expected_qmarks = qmark_count + numeric_count # Should primarily be qmark_count for sqlite - if expected_qmarks != len(merged_params): - # This might indicate SQLStatement's regex fallback was used and sqlglot count differs. - # Or, the SQL is malformed in a way that bypasses SQLStatement's initial validation for sequence params. - msg = ( - f"aiosqlite: Parameter count mismatch after SQLStatement validation. " - f"SQL (re-parsed) expects {expected_qmarks} positional placeholders, but {len(merged_params)} were provided. SQL: {original_sql}" - ) - # Check if SQLStatement validation should have caught this. This is more of an internal consistency check. - logger.warning(msg) # Log as warning, as SQLStatement might have allowed it based on regex. - # If we proceed, it might lead to runtime errors from aiosqlite. For now, we proceed with params as is. - - final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures '?' for sqlite - final_params_tuple = tuple(merged_params) - - elif merged_params is not None: # Scalar parameter - # Similar to sequence, SQLStatement should have validated this. - # Expecting one 'qmark' placeholder. - sql_placeholder_nodes = list(parsed_expression.find_all(exp.Placeholder)) # Re-fetch for this block - sql_numeric_param_nodes = [ # Simplified numeric detection for sqlite context - node - for node in parsed_expression.find_all(exp.Parameter) - if (node.name and node.name.isdigit()) - or (not node.name and node.this and isinstance(node.this, str) and node.this.isdigit()) - ] - qmark_count = sum(1 for p_node in sql_placeholder_nodes if p_node.this is None) - numeric_count = len(sql_numeric_param_nodes) - - has_named_placeholders_in_ast = False - for node in parsed_expression.find_all(exp.Placeholder, exp.Parameter): - if (isinstance(node, exp.Parameter) and node.name and not node.name.isdigit()) or ( - isinstance(node, exp.Placeholder) and node.this and not node.this.isdigit() - ): - has_named_placeholders_in_ast = True - break - if has_named_placeholders_in_ast: - msg = f"aiosqlite: Scalar parameter provided, but SQL unexpectedly contains named placeholders after SQLStatement validation. SQL: {original_sql}" - raise ParameterStyleMismatchError(msg) - - expected_qmarks = qmark_count + numeric_count - if expected_qmarks != 1: - msg = f"aiosqlite: Scalar parameter provided, but SQL (re-parsed) expects {expected_qmarks} positional placeholders (expected 1). SQL: {original_sql}" - raise SQLParsingError(msg) - - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params_tuple = (merged_params,) - - return final_sql, final_params_tuple + Args: + sql: SQL statement. + parameters: Query parameters. + **kwargs: Additional keyword arguments. + + Returns: + Tuple of processed SQL and parameters. + """ + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + processed_sql, processed_params, parsed_expr = statement.process() + if processed_params is None: + return processed_sql, None + + if is_dict(processed_params): + # For dict parameters, we need to use ordered ? placeholders + # but only if we have a parsed expression to work with + if parsed_expr: + # Collect named parameters in the order they appear in the SQL + named_params = [] + for node in parsed_expr.find_all(exp.Parameter, exp.Placeholder): + if isinstance(node, exp.Parameter) and node.name and node.name in processed_params: + named_params.append(node.name) + elif ( + isinstance(node, exp.Placeholder) + and isinstance(node.this, str) + and node.this in processed_params + ): + named_params.append(node.this) + + if named_params: + # Transform SQL to use ? placeholders + def _convert_to_qmark(node: exp.Expression) -> exp.Expression: + if (isinstance(node, exp.Parameter) and node.name and node.name in processed_params) or ( + isinstance(node, exp.Placeholder) + and isinstance(node.this, str) + and node.this in processed_params + ): + return exp.Placeholder() # ? placeholder + return node + + return parsed_expr.transform(_convert_to_qmark, copy=True).sql(dialect=self.dialect), tuple( + processed_params[name] for name in named_params + ) + return processed_sql, processed_params + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + return processed_sql, (processed_params,) # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/asyncmy/driver.py b/sqlspec/adapters/asyncmy/driver.py index 5df44c9..a8bb75b 100644 --- a/sqlspec/adapters/asyncmy/driver.py +++ b/sqlspec/adapters/asyncmy/driver.py @@ -1,16 +1,17 @@ # type: ignore import logging +import re from collections.abc import AsyncGenerator, Sequence from contextlib import asynccontextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot from asyncmy import Connection -from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError +from sqlspec.exceptions import ParameterStyleMismatchError from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.statement import SQLStatement +from sqlspec.typing import is_dict if TYPE_CHECKING: from asyncmy.cursors import Cursor @@ -23,6 +24,9 @@ logger = logging.getLogger("sqlspec") +# Pattern to identify MySQL-style placeholders (%s) for proper conversion +MYSQL_PLACEHOLDER_PATTERN = re.compile(r"(? "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for asyncmy driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters # type: ignore[assignment] - # else merged_params remains None - - # Check if the SQL contains MySQL format placeholders (%s) - # If so, we'll use a simpler approach rather than SQLGlot parsing - # as SQLGlot doesn't correctly handle %s parameters (treats them as modulo operations) - format_placeholders_count = sql.count("%s") - - if format_placeholders_count > 0: - # Simple MySQL format placeholder handling - if merged_params is None: - if format_placeholders_count > 0: - msg = f"asyncmy: SQL statement contains {format_placeholders_count} format placeholders ('%s'), but no parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - return sql, None + """Process SQL and parameters using SQLStatement with dialect support. + + Args: + sql: The SQL statement to process. + parameters: The parameters to bind to the statement. + **kwargs: Additional keyword arguments (including filters). - if isinstance(merged_params, (list, tuple)): - if len(merged_params) != format_placeholders_count: - msg = f"asyncmy: Parameter count mismatch. SQL expects {format_placeholders_count} '%s' placeholders, but {len(merged_params)} parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) - # MySQL/asyncmy uses %s for format placeholders, so we can just pass the SQL as-is - return sql, tuple(merged_params) + Raises: + ParameterStyleMismatchError: If the parameter style is not supported. - if isinstance(merged_params, dict): + Returns: + A tuple of (sql, parameters) ready for execution. + """ + # Handle MySQL-specific placeholders (%s) which SQLGlot doesn't parse well + # If %s placeholders are present, handle them directly + mysql_placeholders_count = len(MYSQL_PLACEHOLDER_PATTERN.findall(sql)) + + if mysql_placeholders_count > 0: + # For MySQL format placeholders, minimal processing is needed + if parameters is None: + if mysql_placeholders_count > 0: + msg = f"asyncmy: SQL statement contains {mysql_placeholders_count} format placeholders ('%s'), but no parameters were provided. SQL: {sql}" + raise ParameterStyleMismatchError(msg) + return sql, None + + # Convert dict to tuple if needed + if is_dict(parameters): + # MySQL's %s placeholders require positional params msg = "asyncmy: Dictionary parameters provided with '%s' placeholders. MySQL format placeholders require tuple/list parameters." raise ParameterStyleMismatchError(msg) - # Scalar parameter - if format_placeholders_count != 1: - msg = f"asyncmy: Scalar parameter provided, but SQL expects {format_placeholders_count} '%s' placeholders. Expected 1. SQL: {sql}" - raise SQLParsingError(msg) - return sql, (merged_params,) + # Convert to tuple (handles both scalar and sequence cases) + if not isinstance(parameters, (list, tuple)): + # Scalar parameter case + return sql, (parameters,) - # Continue with SQLGlot parsing for non-%s cases (like ? or named parameters) - try: - # self.dialect is "mysql" - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - # If parsing fails but we have %s placeholders, it might be due to SQLGlot not handling %s correctly - # In this case, use the simple approach for format placeholders - if format_placeholders_count > 0: - if merged_params is None: - return sql, None - - if isinstance(merged_params, (list, tuple)): - if len(merged_params) != format_placeholders_count: - msg = f"asyncmy: Parameter count mismatch. SQL expects {format_placeholders_count} '%s' placeholders, but {len(merged_params)} parameters were provided. SQL: {sql}" - raise SQLParsingError(msg) from e - return sql, tuple(merged_params) - - if isinstance(merged_params, dict): - msg = "asyncmy: Dictionary parameters provided with '%s' placeholders. MySQL format placeholders require tuple/list parameters." - raise ParameterStyleMismatchError(msg) from e - - # Scalar parameter - if format_placeholders_count != 1: - msg = f"asyncmy: Scalar parameter provided, but SQL expects {format_placeholders_count} '%s' placeholders. Expected 1. SQL: {sql}" - raise SQLParsingError(msg) from e - return sql, (merged_params,) - # If no %s placeholders, then it's a genuine SQLGlot parsing error - msg = f"asyncmy: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # From here, we're handling named parameters or ? placeholders only - # exp.Parameter with .name for :name, @name, etc. - # exp.Placeholder for '?'. - sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] - sql_placeholder_nodes = list(parsed_expression.find_all(exp.Placeholder)) - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or sql_placeholder_nodes: - placeholder_types = set() - if sql_named_param_nodes: - placeholder_types.add("named (e.g., :name)") - if sql_placeholder_nodes: - placeholder_types.add("positional ('?')") - msg = ( - f"asyncmy: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - return sql, None # asyncmy can take None - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - # asyncmy execute takes `args: Any | tuple[Any, ...] | list[Any] | dict[str, Any] | None` - # We will aim to return a tuple for sequence/scalar, or dict for named (if driver supports it natively and sql matches) - # However, for consistency and to ensure broad compatibility if asyncmy prefers one over other internally for qmark, let's convert named to qmark/tuple. - - if isinstance(merged_params, dict): - # Dictionary parameters. Convert to qmark style for asyncmy. - if sql_placeholder_nodes: - msg = "asyncmy: Dictionary parameters provided, but SQL uses positional placeholders ('?'). Use named placeholders (e.g., :name)." + # Sequence parameter case - ensure appropriate length + if len(parameters) != mysql_placeholders_count: + msg = f"asyncmy: Parameter count mismatch. SQL expects {mysql_placeholders_count} '%s' placeholders, but {len(parameters)} parameters were provided. SQL: {sql}" raise ParameterStyleMismatchError(msg) - if not sql_named_param_nodes: - msg = "asyncmy: Dictionary parameters provided, but no named placeholders (e.g., :name) found by sqlglot to convert to '?'." - raise ParameterStyleMismatchError(msg) + return sql, tuple(parameters) - ordered_param_values: list[Any] = [] - sql_param_names_in_ast = {node.name for node in sql_named_param_nodes if node.name} - provided_keys = set(merged_params.keys()) - - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"asyncmy: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - extra_keys = provided_keys - sql_param_names_in_ast - if extra_keys: - logger.warning( - f"asyncmy: Parameters {extra_keys} provided but not found in SQL. They will be ignored during qmark conversion. SQL: {sql}" - ) - - def _convert_named_to_qmark(node: exp.Expression) -> exp.Expression: - if isinstance(node, exp.Parameter) and node.name: - param_name = node.name - if param_name in merged_params: # type: ignore[operator] - ordered_param_values.append(merged_params[param_name]) # type: ignore[index] - return exp.Placeholder() # Represents '?' for MySQL dialect generation - return node - - transformed_expression = parsed_expression.transform(_convert_named_to_qmark, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) # MySQL dialect makes '?' - final_params = tuple(ordered_param_values) - - elif isinstance(merged_params, (list, tuple)): - # Sequence parameters. SQL should use '?' - if sql_named_param_nodes: - msg = "asyncmy: Sequence parameters provided, but SQL contains named placeholders. Use '?'." - raise ParameterStyleMismatchError(msg) + # Create a SQLStatement with MySQL dialect + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - expected_param_count = len(sql_placeholder_nodes) - if expected_param_count != len(merged_params): - msg = ( - f"asyncmy: Parameter count mismatch. SQL expects {expected_param_count} positional placeholders ('?'), " - f"but {len(merged_params)} were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) + # Apply any filters if present + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = tuple(merged_params) + # Process the statement for execution + processed_sql, processed_params, _ = statement.process() - elif merged_params is not None: # Scalar parameter - if sql_named_param_nodes: - msg = "asyncmy: Scalar parameter provided, but SQL uses named placeholders. Use a single '?'." - raise ParameterStyleMismatchError(msg) + # Convert parameters to the format expected by MySQL + if processed_params is None: + return processed_sql, None + + # For MySQL, ensure parameters are in the right format + if is_dict(processed_params): + # Dictionary parameters are not well supported by asyncmy + msg = "asyncmy: Dictionary parameters are not supported for MySQL placeholders. Use sequence parameters." + raise ParameterStyleMismatchError(msg) + + # For sequence parameters, ensure they're a tuple + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) - expected_param_count = len(sql_placeholder_nodes) - if expected_param_count != 1: - msg = ( - f"asyncmy: Scalar parameter provided, but SQL expects {expected_param_count} positional placeholders. " - f"Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = (merged_params,) - - else: # Should be caught by 'merged_params is None' earlier - final_sql = sql - final_params = None - - return final_sql, final_params + # For scalar parameter, wrap in a tuple + return processed_sql, (processed_params,) # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/asyncpg/driver.py b/sqlspec/adapters/asyncpg/driver.py index 0f5184b..055e7a9 100644 --- a/sqlspec/adapters/asyncpg/driver.py +++ b/sqlspec/adapters/asyncpg/driver.py @@ -1,14 +1,13 @@ import logging import re +from re import Match from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot from asyncpg import Connection from sqlglot import exp from typing_extensions import TypeAlias from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin from sqlspec.statement import SQLStatement @@ -29,6 +28,24 @@ # Compile the row count regex once for efficiency ROWCOUNT_REGEX = re.compile(r"^(?:INSERT|UPDATE|DELETE) \d+ (\d+)$") +# Improved regex to match question mark placeholders only when they are outside string literals and comments +# This pattern handles: +# 1. Single quoted strings with escaped quotes +# 2. Double quoted strings with escaped quotes +# 3. Single-line comments (-- to end of line) +# 4. Multi-line comments (/* to */) +# 5. Only question marks outside of these contexts are considered parameters +QUESTION_MARK_PATTERN = re.compile( + r""" + (?:'[^']*(?:''[^']*)*') | # Skip single-quoted strings (with '' escapes) + (?:"[^"]*(?:""[^"]*)*") | # Skip double-quoted strings (with "" escapes) + (?:--.*?(?:\n|$)) | # Skip single-line comments + (?:/\*(?:[^*]|\*(?!/))*\*/) | # Skip multi-line comments + (\?) # Capture only question marks outside of these contexts + """, + re.VERBOSE | re.DOTALL, +) + class AsyncpgDriver( SQLTranslatorMixin["AsyncpgConnection"], @@ -49,134 +66,92 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # First, use SQLStatement for parameter validation - statement = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs) - sql, validated_params = statement.process() - - if validated_params is None: - return sql, () # asyncpg expects an empty tuple for no params - - # Now use SQLGlot for PostgreSQL-specific parameter handling - try: - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"asyncpg: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Find different types of parameter nodes in the AST - # Traditional named parameters (e.g., @name, $name) - sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] - - # For PostgreSQL dialect, ':name' gets parsed as Placeholder with this='name' - colon_named_placeholder_nodes = [ - node - for node in parsed_expression.find_all(exp.Placeholder) - if isinstance(node.this, str) and not node.this.isdigit() - ] - - # Anonymous placeholders (?) - question_mark_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] - - # PostgreSQL-specific dollar-numeric parameters like $1, $2 - sql_numeric_dollar_nodes = [ - node - for node in parsed_expression.find_all(exp.Parameter) - if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() - ] - - final_params_seq = [] - - if isinstance(validated_params, dict): - # Dictionary parameters - convert named parameters to PostgreSQL style ($n) - if question_mark_nodes or sql_numeric_dollar_nodes: - msg = "asyncpg: Dictionary parameters provided, but SQL uses positional placeholders. Use named placeholders (e.g., :name)." - raise ParameterStyleMismatchError(msg) - - # With PostgreSQL dialect, :name is parsed as Placeholder, not Parameter - if not sql_named_param_nodes and not colon_named_placeholder_nodes: - msg = "asyncpg: Dictionary parameters provided, but no named placeholders found in SQL by sqlglot." - raise ParameterStyleMismatchError(msg) - - # Transform both types of named parameters to $n placeholders - def _convert_named_to_dollar(node: exp.Expression) -> exp.Expression: - param_name = None - if isinstance(node, exp.Parameter) and node.name: - param_name = node.name - elif isinstance(node, exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit(): - param_name = node.this - - if param_name and param_name in validated_params: - final_params_seq.append(validated_params[param_name]) - # Create a Parameter node that PostgreSQL will interpret as a positional parameter ($n) - # The position is determined by the order in final_params_seq - return exp.Parameter(this=str(len(final_params_seq))) - return node - - transformed_expression = parsed_expression.transform(_convert_named_to_dollar, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - - elif hasattr(validated_params, "__iter__") and not isinstance(validated_params, (str, bytes, dict)): - # Sequence parameters (list or tuple) - if sql_named_param_nodes or colon_named_placeholder_nodes: - msg = ( - "asyncpg: Sequence parameters provided, but SQL contains named placeholders. Use '?' placeholders." - ) - raise ParameterStyleMismatchError(msg) - - # Count placeholders for validation - total_placeholders = len(question_mark_nodes) + len(sql_numeric_dollar_nodes) - if total_placeholders != len(validated_params): - msg = ( - f"asyncpg: Parameter count mismatch. SQL expects {total_placeholders} placeholders, " - f"but {len(validated_params)} parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - - # For PostgreSQL, convert ? to $n - def _convert_qmark_to_dollar(node: exp.Expression) -> exp.Expression: - if isinstance(node, exp.Placeholder) and node.this is None: - position = len(final_params_seq) + 1 # PostgreSQL positions are 1-indexed - final_params_seq.append(validated_params[position - 1]) - return exp.Parameter(this=str(position)) - return node - - transformed_expression = parsed_expression.transform(_convert_qmark_to_dollar, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - - # If we didn't add any parameters via transformation (e.g., SQL already uses $n style), - # just add all parameters in order - if not final_params_seq and validated_params: - final_params_seq.extend(validated_params) - - else: # Scalar parameter - if sql_named_param_nodes or colon_named_placeholder_nodes: - msg = "asyncpg: Scalar parameter provided, but SQL contains named placeholders. Use a '?' placeholder." - raise ParameterStyleMismatchError(msg) - - total_placeholders = len(question_mark_nodes) + len(sql_numeric_dollar_nodes) - if total_placeholders != 1: - msg = ( - f"asyncpg: Scalar parameter provided, but SQL expects {total_placeholders} placeholders. " - f"Expected exactly 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - - # Convert single ? to $1 - def _convert_single_qmark_to_dollar(node: exp.Expression) -> exp.Expression: - if isinstance(node, exp.Placeholder) and node.this is None: - final_params_seq.append(validated_params) - return exp.Parameter(this="1") - return node - - transformed_expression = parsed_expression.transform(_convert_single_qmark_to_dollar, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - - # If we didn't add the parameter via transformation (e.g., SQL already uses $1), - # add it directly - if not final_params_seq: - final_params_seq.append(validated_params) - - return final_sql, tuple(final_params_seq) + """Process SQL and parameters for AsyncPG using SQLStatement. + + This method applies filters (if provided), processes the SQL through SQLStatement + with dialect support, and converts parameters to the format required by AsyncPG. + + Args: + sql: SQL statement. + parameters: Query parameters. + **kwargs: Additional keyword arguments. + + Returns: + Tuple of processed SQL and parameters. + """ + # Handle scalar parameter by converting to a single-item tuple + if parameters is not None and not isinstance(parameters, (list, tuple, dict)): + parameters = (parameters,) + + # Create a SQLStatement with PostgreSQL dialect + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + + # Apply any filters if present + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + + # Process the statement + processed_sql, processed_params, parsed_expr = statement.process() + + if processed_params is None: + return processed_sql, () + + # Convert question marks to PostgreSQL style $N parameters + if isinstance(processed_params, (list, tuple)) and "?" in processed_sql: + # Use a counter to generate $1, $2, etc. for each ? in the SQL that's outside strings/comments + param_index = 0 + + def replace_question_mark(match: Match[str]) -> str: + # Only process the match if it's not in a skipped context (string/comment) + if match.group(1): # This is a question mark outside string/comment + nonlocal param_index + param_index += 1 + return f"${param_index}" + # Return the entire matched text unchanged for strings/comments + return match.group(0) + + processed_sql = QUESTION_MARK_PATTERN.sub(replace_question_mark, processed_sql) + + # Now handle the asyncpg-specific parameter conversion - asyncpg requires positional parameters + if isinstance(processed_params, dict): + if parsed_expr is not None: + # Find named parameters + named_params = [] + for node in parsed_expr.find_all(exp.Parameter, exp.Placeholder): + if isinstance(node, exp.Parameter) and node.name and node.name in processed_params: + named_params.append(node.name) + elif ( + isinstance(node, exp.Placeholder) + and isinstance(node.this, str) + and node.this in processed_params + ): + named_params.append(node.this) + + # Convert named parameters to positional + if named_params: + # Transform the SQL to use $1, $2, etc. + def replace_named_with_positional(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Parameter) and node.name and node.name in processed_params: + idx = named_params.index(node.name) + 1 + return exp.Parameter(this=str(idx)) + if ( + isinstance(node, exp.Placeholder) + and isinstance(node.this, str) + and node.this in processed_params + ): + idx = named_params.index(node.this) + 1 + return exp.Parameter(this=str(idx)) + return node + + return parsed_expr.transform(replace_named_with_positional, copy=True).sql( + dialect=self.dialect + ), tuple(processed_params[name] for name in named_params) + return processed_sql, tuple(processed_params.values()) + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + return processed_sql, (processed_params,) # type: ignore[unreachable] @overload async def select( diff --git a/sqlspec/adapters/bigquery/driver.py b/sqlspec/adapters/bigquery/driver.py index 9e0df1a..0a813fc 100644 --- a/sqlspec/adapters/bigquery/driver.py +++ b/sqlspec/adapters/bigquery/driver.py @@ -13,20 +13,19 @@ overload, ) -import sqlglot from google.cloud import bigquery from google.cloud.bigquery import Client from google.cloud.bigquery.job import QueryJob, QueryJobConfig from google.cloud.exceptions import NotFound -from sqlglot import exp from sqlspec.base import SyncDriverAdapterProtocol -from sqlspec.exceptions import NotFoundError, ParameterStyleMismatchError, SQLParsingError, SQLSpecError +from sqlspec.exceptions import NotFoundError, ParameterStyleMismatchError, SQLSpecError from sqlspec.mixins import ( SQLTranslatorMixin, SyncArrowBulkOperationsMixin, SyncParquetExportMixin, ) +from sqlspec.statement import SQLStatement from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T if TYPE_CHECKING: @@ -59,7 +58,7 @@ def __init__(self, connection: "BigQueryConnection", **kwargs: Any) -> None: ) @staticmethod - def _get_bq_param_type(value: Any) -> "tuple[Optional[str], Optional[str]]": # noqa: PLR0911 + def _get_bq_param_type(value: Any) -> "tuple[Optional[str], Optional[str]]": if isinstance(value, bool): return "BOOL", None if isinstance(value, int): @@ -116,120 +115,42 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Process SQL and parameters for BigQuery using sqlglot for parsing and validation. + """Process SQL and parameters using SQLStatement with dialect support. - BigQuery uses named (@name) or positional (?) parameters. - This method merges input parameters, validates them against the parsed SQL structure, - and returns the SQL (potentially normalized by sqlglot) and merged parameters. - Actual creation of BigQuery QueryParameter objects is handled later. - """ - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for BigQuery driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters - # else merged_params remains None + Args: + sql: The SQL statement to process. + parameters: The parameters to bind to the statement. + **kwargs: Additional keyword arguments (including filters). - # 2. SQLGlot Parsing - try: - # self.dialect is "bigquery" - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"bigquery: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Identify parameter types from AST - # BigQuery's @name are exp.Parameter with a name. '?' are exp.Placeholder. - sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] - sql_placeholder_nodes = list(parsed_expression.find_all(exp.Placeholder)) - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or sql_placeholder_nodes: - placeholder_types = set() - if sql_named_param_nodes: - placeholder_types.add("named (e.g., @name)") - if sql_placeholder_nodes: - placeholder_types.add("positional ('?')") - msg = ( - f"bigquery: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - # Return original SQL if no params and no placeholders found by sqlglot - # _run_query_job may still transpile it if not a script. - return sql, None - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - - # Generate SQL using BigQuery dialect. This normalizes syntax if input was, e.g. :name. - # The actual BQ param objects are created in _run_query_job. - final_sql = parsed_expression.sql(dialect=self.dialect) - - if isinstance(merged_params, dict): - if sql_placeholder_nodes: - msg = "bigquery: Dictionary parameters provided, but SQL uses positional '?' placeholders. Use named @params." - raise ParameterStyleMismatchError(msg) - if not sql_named_param_nodes and not any(f"@{key}" in sql for key in merged_params): - # If sqlglot found no :name (common input) or @name (native BQ) - # and the raw SQL doesn't contain @key for the provided dict keys. - msg = "bigquery: Dictionary parameters provided, but no recognizable named placeholders (e.g., @name or :name) found." - raise ParameterStyleMismatchError(msg) + Raises: + ParameterStyleMismatchError: If pre-formatted BigQuery parameters are mixed with keyword arguments. - # Validate keys only if sqlglot identified specific named parameters from a known style like :name - if sql_named_param_nodes: - sql_param_names_in_ast = {node.name for node in sql_named_param_nodes if node.name} - provided_keys = set(merged_params.keys()) - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"bigquery: Named parameters {missing_keys} (from :name style) found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - extra_keys = provided_keys - sql_param_names_in_ast - if extra_keys: - msg = f"bigquery: Parameters {extra_keys} provided but not found as :name style in SQL. Ensure they match @name style if used. SQL: {sql}" - logger.warning(msg) - final_params = merged_params # Pass dict; _run_query_job will make BQ params - - elif isinstance(merged_params, (list, tuple)): - if sql_named_param_nodes: - msg = "bigquery: Sequence parameters provided, but SQL uses named placeholders. Use '?' placeholders." + Returns: + A tuple of (sql, parameters) ready for execution. + """ + # Special case: check for pre-formatted BQ parameters + if ( + isinstance(parameters, (list, tuple)) + and parameters + and all(isinstance(p, (bigquery.ScalarQueryParameter, bigquery.ArrayQueryParameter)) for p in parameters) + ): + if kwargs: + msg = "Cannot mix pre-formatted BigQuery parameters with keyword arguments." raise ParameterStyleMismatchError(msg) + return sql, parameters - if len(sql_placeholder_nodes) != len(merged_params): - msg = ( - f"bigquery: Parameter count mismatch. SQL expects {len(sql_placeholder_nodes)} '?' placeholders, " - f"but {len(merged_params)} were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - final_params = tuple(merged_params) - - elif merged_params is not None: # Scalar parameter - if sql_named_param_nodes: - msg = "bigquery: Scalar parameter provided, but SQL uses named placeholders. Use a single '?'." - raise ParameterStyleMismatchError(msg) - if len(sql_placeholder_nodes) != 1: - msg = ( - f"bigquery: Scalar parameter provided, but SQL expects {len(sql_placeholder_nodes)} '?' placeholders. " - f"Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - final_params = (merged_params,) + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) - else: # Should be caught by 'merged_params is None' earlier - final_params = None # Should align with the `return sql, None` path earlier + # Process the statement for execution + processed_sql, processed_params, _ = statement.process() - return final_sql, final_params + return processed_sql, processed_params - def _run_query_job( # noqa: PLR0912, PLR0915 (User change) + def _run_query_job( self, sql: str, parameters: "Optional[StatementParameterType]" = None, @@ -249,104 +170,44 @@ def _run_query_job( # noqa: PLR0912, PLR0915 (User change) else: final_job_config = QueryJobConfig() # Create a fresh config - # --- Parameter Handling Logic --- Start - params: Union[dict[str, Any], list[Any], None] = None - param_style: Optional[str] = None # 'named' (@), 'qmark' (?) - use_preformatted_params = False - final_sql = sql # Default to original SQL + # Process SQL and parameters + final_sql, processed_params = self._process_sql_params(sql, parameters, **kwargs) - # Check for pre-formatted BQ parameters first + # Handle pre-formatted parameters if ( - isinstance(parameters, (list, tuple)) - and parameters - and all(isinstance(p, (bigquery.ScalarQueryParameter, bigquery.ArrayQueryParameter)) for p in parameters) + isinstance(processed_params, (list, tuple)) + and processed_params + and all( + isinstance(p, (bigquery.ScalarQueryParameter, bigquery.ArrayQueryParameter)) for p in processed_params + ) ): - if kwargs: - msg = "Cannot mix pre-formatted BigQuery parameters with keyword arguments." - raise SQLSpecError(msg) - use_preformatted_params = True - final_job_config.query_parameters = list(parameters) - # Keep final_sql = sql, as it should match the pre-formatted named params - - # Determine parameter style and merge standard parameters ONLY if not preformatted - if not use_preformatted_params: - if isinstance(parameters, dict): - params = {**parameters, **kwargs} - param_style = "named" - elif isinstance(parameters, (list, tuple)): - if kwargs: - msg = "Cannot mix positional parameters with keyword arguments." - raise SQLSpecError(msg) - # Check if it's primitives for qmark style - if all( - not isinstance(p, (bigquery.ScalarQueryParameter, bigquery.ArrayQueryParameter)) for p in parameters - ): - params = list(parameters) - param_style = "qmark" - else: - # Mixed list or non-BQ parameter objects - msg = "Invalid mix of parameter types in list. Use only primitive values or only BigQuery QueryParameter objects." - raise SQLSpecError(msg) - - elif kwargs: - params = kwargs - param_style = "named" - elif parameters is not None and not isinstance( - parameters, (bigquery.ScalarQueryParameter, bigquery.ArrayQueryParameter) - ): - # Could be a single primitive value for positional - params = [parameters] - param_style = "qmark" - elif parameters is not None: # Single BQ parameter object - msg = "Single BigQuery QueryParameter objects should be passed within a list." - raise SQLSpecError(msg) - - # Use sqlglot to transpile ONLY if not a script and not preformatted - if not is_script and not use_preformatted_params: - try: - # Transpile for syntax normalization/dialect conversion if needed - # Use BigQuery dialect for both reading and writing - final_sql = sqlglot.transpile(sql, read=self.dialect, write=self.dialect)[0] - except Exception as e: - # Catch potential sqlglot errors - msg = f"SQL transpilation failed using sqlglot: {e!s}" # Adjusted message - raise SQLSpecError(msg) from e - # else: If preformatted_params, final_sql remains the original sql - - # --- Parameter Handling Logic --- (Moved outside the transpilation try/except) - # Prepare BQ parameters based on style, ONLY if not preformatted - if not use_preformatted_params: - if param_style == "named" and params: - # Convert dict params to BQ ScalarQueryParameter - if isinstance(params, dict): - final_job_config.query_parameters = [ - bigquery.ScalarQueryParameter(name, self._get_bq_param_type(value)[0], value) - for name, value in params.items() - ] - else: - # This path should ideally not be reached if param_style logic is correct - msg = f"Internal error: Parameter style is 'named' but parameters are not a dict: {type(params)}" - raise SQLSpecError(msg) - elif param_style == "qmark" and params: - # Convert list params to BQ ScalarQueryParameter - final_job_config.query_parameters = [ - bigquery.ScalarQueryParameter(None, self._get_bq_param_type(value)[0], value) for value in params - ] - - # --- Parameter Handling Logic --- End - - # Determine which kwargs to pass to the actual query method. - # We only want to pass kwargs that were *not* treated as SQL parameters. + final_job_config.query_parameters = list(processed_params) + # Convert regular parameters to BigQuery parameters + elif isinstance(processed_params, dict): + # Convert dict params to BQ ScalarQueryParameter + final_job_config.query_parameters = [ + bigquery.ScalarQueryParameter(name, self._get_bq_param_type(value)[0], value) + for name, value in processed_params.items() + ] + elif isinstance(processed_params, (list, tuple)): + # Convert list params to BQ ScalarQueryParameter + final_job_config.query_parameters = [ + bigquery.ScalarQueryParameter(None, self._get_bq_param_type(value)[0], value) + for value in processed_params + ] + + # Determine which kwargs to pass to the actual query method + # We only want to pass kwargs that were *not* treated as SQL parameters final_query_kwargs = {} if parameters is not None and kwargs: # Params came via arg, kwargs are separate final_query_kwargs = kwargs - # Else: If params came via kwargs, they are already handled, so don't pass them again. + # Else: If params came via kwargs, they are already handled, so don't pass them again # Execute query return conn.query( final_sql, job_config=final_job_config, - **final_query_kwargs, # Pass only relevant kwargs + **final_query_kwargs, ) @staticmethod @@ -715,41 +576,13 @@ def select_arrow( # pyright: ignore conn = self._connection(connection) final_job_config = job_config or self._default_query_job_config or QueryJobConfig() - # Determine parameter style and merge parameters (Similar to _run_query_job) - params: Union[dict[str, Any], list[Any], None] = None - param_style: Optional[str] = None # 'named' (@), 'qmark' (?) - - if isinstance(parameters, dict): - params = {**parameters, **kwargs} - param_style = "named" - elif isinstance(parameters, (list, tuple)): - if kwargs: - msg = "Cannot mix positional parameters with keyword arguments." - raise SQLSpecError(msg) - params = list(parameters) - param_style = "qmark" - elif kwargs: - params = kwargs - param_style = "named" - elif parameters is not None: - params = [parameters] - param_style = "qmark" - - # Use sqlglot to transpile and bind parameters - try: - transpiled_sql = sqlglot.transpile(sql, args=params or {}, read=None, write=self.dialect)[0] - except Exception as e: - msg = f"SQL transpilation/binding failed using sqlglot: {e!s}" - raise SQLSpecError(msg) from e + # Process SQL and parameters using SQLStatement + processed_sql, processed_params = self._process_sql_params(sql, parameters, **kwargs) - # Prepare BigQuery specific parameters if named style was used - if param_style == "named" and params: - if not isinstance(params, dict): - # This should be logically impossible due to how param_style is set - msg = "Internal error: named parameter style detected but params is not a dict." - raise SQLSpecError(msg) + # Convert parameters to BigQuery format + if isinstance(processed_params, dict): query_parameters = [] - for key, value in params.items(): + for key, value in processed_params.items(): param_type, array_element_type = self._get_bq_param_type(value) if param_type == "ARRAY" and array_element_type: @@ -760,15 +593,17 @@ def select_arrow( # pyright: ignore msg = f"Unsupported parameter type for BigQuery Arrow named parameter '{key}': {type(value)}" raise SQLSpecError(msg) final_job_config.query_parameters = query_parameters - elif param_style == "qmark" and params: - # Positional params handled by client library - pass + elif isinstance(processed_params, (list, tuple)): + # Convert sequence parameters + final_job_config.query_parameters = [ + bigquery.ScalarQueryParameter(None, self._get_bq_param_type(value)[0], value) + for value in processed_params + ] # Execute the query and get Arrow table try: - query_job = conn.query(transpiled_sql, job_config=final_job_config) + query_job = conn.query(processed_sql, job_config=final_job_config) arrow_table = query_job.to_arrow() # Waits for job completion - except Exception as e: msg = f"BigQuery Arrow query execution failed: {e!s}" raise SQLSpecError(msg) from e @@ -823,3 +658,14 @@ def select_to_parquet( if extract_job.errors: msg = f"BigQuery Parquet export failed: {extract_job.errors}" raise SQLSpecError(msg) + + def _connection(self, connection: "Optional[BigQueryConnection]" = None) -> "BigQueryConnection": + """Get the connection to use for the operation. + + Args: + connection: Optional connection to use. + + Returns: + The connection to use. + """ + return connection or self.connection diff --git a/sqlspec/adapters/duckdb/driver.py b/sqlspec/adapters/duckdb/driver.py index 61f9f64..d1438f6 100644 --- a/sqlspec/adapters/duckdb/driver.py +++ b/sqlspec/adapters/duckdb/driver.py @@ -2,13 +2,11 @@ from contextlib import contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot from duckdb import DuckDBPyConnection -from sqlglot import exp from sqlspec.base import SyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.statement import SQLStatement from sqlspec.typing import ArrowTable, StatementParameterType if TYPE_CHECKING: @@ -61,160 +59,33 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Process SQL and parameters for DuckDB. + """Process SQL and parameters for DuckDB using SQLStatement. DuckDB supports both named (:name, $name) and positional (?) parameters. - This method merges parameters, validates them, and ensures SQL is in a - consistent format for the duckdb driver using sqlglot. + This method processes the SQL with dialect-aware parsing and handles + parameters appropriately for DuckDB. + + Args: + sql: SQL statement. + parameters: Query parameters. + **kwargs: Additional keyword arguments. + + Returns: + Tuple of processed SQL and parameters. """ - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for DuckDB driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters - # else merged_params remains None - - # Special case: if merged_params is an empty dict, treat it as None for parameterless queries - if isinstance(merged_params, dict) and not merged_params: - merged_params = None - - # 2. SQLGlot Parsing - try: - # self.dialect is "duckdb" - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"duckdb: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Traditional named parameters (e.g., @name, $name) parsed as Parameter nodes - sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] - - # Named placeholders parsed as Placeholder nodes (e.g., :name, $name in some dialects) - named_placeholder_nodes = [ - node - for node in parsed_expression.find_all(exp.Placeholder) - if isinstance(node.this, str) and not node.this.isdigit() - ] - - # Anonymous placeholders (?) parsed as Placeholder nodes with this=None - qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] - - # DuckDB also uses $N for positional, sqlglot might parse these as exp.Parameter without name and numeric .this - sql_dollar_numeric_nodes = [ - node - for node in parsed_expression.find_all(exp.Parameter) - if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() - ] - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes or sql_dollar_numeric_nodes: - placeholder_types = set() - if sql_named_param_nodes or named_placeholder_nodes: - placeholder_types.add("named (e.g., :name, $name)") - if qmark_placeholder_nodes: - placeholder_types.add("qmark ('?')") - if sql_dollar_numeric_nodes: - placeholder_types.add("numeric ($N)") - msg = ( - f"duckdb: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - return sql, None # DuckDB can take None - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - - if isinstance(merged_params, dict): - # Dictionary parameters. DuckDB client handles :name and $name if SQL uses them. - # sqlglot's "duckdb" dialect should preserve/generate these. - if qmark_placeholder_nodes or sql_dollar_numeric_nodes: - msg = "duckdb: Dictionary parameters provided, but SQL uses positional placeholders ('?' or $N). Use named placeholders." - raise ParameterStyleMismatchError(msg) - - if not sql_named_param_nodes and not named_placeholder_nodes: - msg = "duckdb: Dictionary parameters provided, but no named placeholders (e.g., :name, $name) found by sqlglot." - raise ParameterStyleMismatchError(msg) - - # Collect parameter names from both types of nodes - sql_param_names_in_ast = set() - - # Get names from Parameter nodes - sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) - - # Get names from Placeholder nodes - sql_param_names_in_ast.update(node.this for node in named_placeholder_nodes if isinstance(node.this, str)) - - provided_keys = set(merged_params.keys()) - - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"duckdb: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - extra_keys = provided_keys - sql_param_names_in_ast - if extra_keys: - logger.warning( - f"duckdb: Parameters {extra_keys} provided but not found in SQL. DuckDB might ignore them. SQL: {sql}" - ) - - # Generate SQL with duckdb dialect to ensure consistent named param style if input was varied. - # e.g. if input was :name, output for duckdb might be $name or vice-versa, sqlglot handles this. - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = merged_params # Pass the dict directly to DuckDB - - elif isinstance(merged_params, (list, tuple)): - # Sequence parameters. DuckDB uses '?'. - # sqlglot's "duckdb" dialect should generate '?' from exp.Placeholder. - if sql_named_param_nodes or named_placeholder_nodes: - msg = ( - "duckdb: Sequence parameters provided, but SQL uses named placeholders. Use '?' or $N placeholders." - ) - raise ParameterStyleMismatchError(msg) - - # If SQL already has $N, it's a mismatch for unnamed sequence params - if sql_dollar_numeric_nodes: - msg = "duckdb: Sequence parameters provided, but SQL uses $N style. Use '?' placeholders for unnamed sequences." - raise ParameterStyleMismatchError(msg) - - if len(qmark_placeholder_nodes) != len(merged_params): - msg = ( - f"duckdb: Parameter count mismatch. SQL expects {len(qmark_placeholder_nodes)} '?' placeholders, " - f"but {len(merged_params)} were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - - final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures qmark style from placeholders - final_params = tuple(merged_params) - - elif merged_params is not None: # Scalar parameter - if sql_named_param_nodes or named_placeholder_nodes or sql_dollar_numeric_nodes: - msg = "duckdb: Scalar parameter provided, but SQL uses named or $N placeholders. Use a single '?'." - raise ParameterStyleMismatchError(msg) - - if len(qmark_placeholder_nodes) != 1: - msg = ( - f"duckdb: Scalar parameter provided, but SQL expects {len(qmark_placeholder_nodes)} '?' placeholders. " - f"Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = (merged_params,) - - else: # Should be caught by 'merged_params is None' earlier - final_sql = sql - final_params = None - - return final_sql, final_params + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + processed_sql, processed_params, _ = statement.process() + if processed_params is None: + return processed_sql, None + if isinstance(processed_params, dict): + return processed_sql, processed_params + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + return processed_sql, (processed_params,) # type: ignore[unreachable] # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/oracledb/driver.py b/sqlspec/adapters/oracledb/driver.py index 4716aea..44ff601 100644 --- a/sqlspec/adapters/oracledb/driver.py +++ b/sqlspec/adapters/oracledb/driver.py @@ -2,13 +2,11 @@ from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot from oracledb import AsyncConnection, AsyncCursor, Connection, Cursor -from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import AsyncArrowBulkOperationsMixin, SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.statement import SQLStatement from sqlspec.typing import ArrowTable, StatementParameterType, T if TYPE_CHECKING: @@ -36,180 +34,36 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], dict[str, Any]]]]": - """Process SQL and parameters for OracleDB. + """Process SQL and parameters using SQLStatement with dialect support. - OracleDB supports both named (:name) and positional (?, :1, etc.) parameters. - This method merges parameters, validates them, and ensures SQL is in a - consistent format for the OracleDB driver using sqlglot. + Args: + sql: The SQL statement to process. + parameters: The parameters to bind to the statement. + **kwargs: Additional keyword arguments (including filters). + + Returns: + A tuple of (sql, parameters) ready for execution. """ - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for OracleDB driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters - # else merged_params remains None - - # Special case: if merged_params is an empty dict, treat it as None for parameterless queries - if isinstance(merged_params, dict) and not merged_params: - merged_params = None - - # 2. SQLGlot Parsing - try: - # self.dialect is "oracle" - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"oracledb: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Traditional named parameters (e.g., :name as Parameter nodes) - sql_named_param_nodes = [ - node for node in parsed_expression.find_all(exp.Parameter) if node.name and not node.name.isdigit() - ] - - # Named placeholders parsed as Placeholder nodes (e.g., :name might be here in some dialects) - named_placeholder_nodes = [ - node - for node in parsed_expression.find_all(exp.Placeholder) - if isinstance(node.this, str) and not node.this.isdigit() - ] - - # Anonymous placeholders (?) - qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] - - # Oracle positional parameters (:1, :2, etc.) - numeric_param_nodes = [ - node for node in parsed_expression.find_all(exp.Parameter) if node.name and node.name.isdigit() - ] - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes or numeric_param_nodes: - placeholder_types = set() - if sql_named_param_nodes or named_placeholder_nodes: - placeholder_types.add("named (e.g., :name)") - if qmark_placeholder_nodes: - placeholder_types.add("qmark ('?')") - if numeric_param_nodes: - placeholder_types.add("positional (:n)") - msg = ( - f"oracledb: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - return sql, None # OracleDB can handle None - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - - if isinstance(merged_params, dict): - # Dictionary parameters. OracleDB can take dict for :name params. - if qmark_placeholder_nodes or numeric_param_nodes: - msg = "oracledb: Dictionary parameters provided, but SQL uses positional placeholders ('?' or :n). Use named placeholders (e.g., :name)." - raise ParameterStyleMismatchError(msg) - - if not sql_named_param_nodes and not named_placeholder_nodes: - msg = "oracledb: Dictionary parameters provided, but no named placeholders (e.g., :name) found by sqlglot." - raise ParameterStyleMismatchError(msg) - - # Collect parameter names from both types of nodes - sql_param_names_in_ast = set() - - # Get names from Parameter nodes - sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) - - # Get names from Placeholder nodes - sql_param_names_in_ast.update(node.this for node in named_placeholder_nodes if isinstance(node.this, str)) - - provided_keys = set(merged_params.keys()) - - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"oracledb: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - extra_keys = provided_keys - sql_param_names_in_ast - if extra_keys: - logger.warning( - f"oracledb: Parameters {extra_keys} provided but not found in SQL. They will be ignored. SQL: {sql}" - ) - - # Generate SQL with oracle dialect for named params - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = merged_params # OracleDB works with dict directly - - elif isinstance(merged_params, (list, tuple)): - # Sequence parameters. OracleDB can take tuple where SQL has ? or :n. - # Ideally transform all to :n style for consistency with oracle dialect. - if sql_named_param_nodes or named_placeholder_nodes: - msg = "oracledb: Sequence parameters provided, but SQL contains named placeholders. Use positional placeholders ('?' or ':n')." - raise ParameterStyleMismatchError(msg) - - total_positional = len(qmark_placeholder_nodes) + len(numeric_param_nodes) - if total_positional != len(merged_params): - msg = ( - f"oracledb: Parameter count mismatch. SQL expects {total_positional} " - f"positional placeholders, but {len(merged_params)} parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - - # Transform '?' to :n if needed for consistency - counter: list[int] = [0] # Use list to make counter mutable in nested function - - def _convert_qmark_to_param(node: exp.Expression) -> exp.Expression: - if isinstance(node, exp.Placeholder) and node.this is None: - counter[0] += 1 - return exp.Parameter(this=exp.Identifier(this=str(counter[0]))) - return node - - if qmark_placeholder_nodes: - # Transform and regenerate SQL - transformed_expression = parsed_expression.transform(_convert_qmark_to_param, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - else: - final_sql = parsed_expression.sql(dialect=self.dialect) - - final_params = tuple(merged_params) # OracleDB expects tuple for positional params - - elif merged_params is not None: # Scalar parameter - if sql_named_param_nodes or named_placeholder_nodes: - msg = "oracledb: Scalar parameter provided, but SQL contains named placeholders. Use a single positional placeholder ('?' or ':1')." - raise ParameterStyleMismatchError(msg) - - total_positional = len(qmark_placeholder_nodes) + len(numeric_param_nodes) - if total_positional != 1: - msg = ( - f"oracledb: Scalar parameter provided, but SQL expects {total_positional} " - f"positional placeholders. Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - - # Transform '?' to :1 if needed for consistency with oracle dialect - if qmark_placeholder_nodes: - transformed_expression = parsed_expression.transform( - lambda node: exp.Parameter(this=exp.Identifier(this="1")) - if isinstance(node, exp.Placeholder) and node.this is None - else node, - copy=True, - ) - final_sql = transformed_expression.sql(dialect=self.dialect) - else: - final_sql = parsed_expression.sql(dialect=self.dialect) - - final_params = (merged_params,) # OracleDB expects tuple for scalar - - else: # Should be caught by 'merged_params is None' earlier - final_sql = sql - final_params = None - - return final_sql, final_params + # Special case: Oracle treats empty dicts as None + if isinstance(parameters, dict) and not parameters and not kwargs: + return sql, None + + # Create a SQLStatement with appropriate dialect + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + + # Apply any filters if present + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + processed_sql, processed_params, _ = statement.process() + if processed_params is None: + return processed_sql, None + if isinstance(processed_params, dict): + return processed_sql, processed_params + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + return processed_sql, (processed_params,) # type: ignore[unreachable] class OracleSyncDriver( @@ -626,6 +480,17 @@ def select_arrow( # pyright: ignore[reportUnknownParameterType] results = connection.fetch_df_all(sql, parameters) return cast("ArrowTable", ArrowTable.from_arrays(arrays=results.column_arrays(), names=results.column_names())) # pyright: ignore + def _connection(self, connection: "Optional[OracleSyncConnection]" = None) -> "OracleSyncConnection": + """Get the connection to use for the operation. + + Args: + connection: Optional connection to use. + + Returns: + The connection to use. + """ + return connection or self.connection + class OracleAsyncDriver( OracleDriverBase, @@ -1032,3 +897,14 @@ async def select_arrow( # pyright: ignore[reportUnknownParameterType] sql, parameters = self._process_sql_params(sql, parameters, **kwargs) results = await connection.fetch_df_all(sql, parameters) return ArrowTable.from_arrays(arrays=results.column_arrays(), names=results.column_names()) # pyright: ignore + + def _connection(self, connection: "Optional[OracleAsyncConnection]" = None) -> "OracleAsyncConnection": + """Get the connection to use for the operation. + + Args: + connection: Optional connection to use. + + Returns: + The connection to use. + """ + return connection or self.connection diff --git a/sqlspec/adapters/psqlpy/driver.py b/sqlspec/adapters/psqlpy/driver.py index 208e0c6..0809d25 100644 --- a/sqlspec/adapters/psqlpy/driver.py +++ b/sqlspec/adapters/psqlpy/driver.py @@ -1,18 +1,19 @@ -# ruff: noqa: PLR0915 """Psqlpy Driver Implementation.""" import logging +import re +from re import Match from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot from psqlpy import Connection, QueryResult from psqlpy.exceptions import RustPSQLDriverPyBaseError from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError +from sqlspec.exceptions import SQLParsingError from sqlspec.mixins import SQLTranslatorMixin from sqlspec.statement import SQLStatement +from sqlspec.typing import is_dict if TYPE_CHECKING: from collections.abc import Sequence @@ -23,6 +24,23 @@ __all__ = ("PsqlpyConnection", "PsqlpyDriver") +# Improved regex to match question mark placeholders only when they are outside string literals and comments +# This pattern handles: +# 1. Single quoted strings with escaped quotes +# 2. Double quoted strings with escaped quotes +# 3. Single-line comments (-- to end of line) +# 4. Multi-line comments (/* to */) +# 5. Only question marks outside of these contexts are considered parameters +QUESTION_MARK_PATTERN = re.compile( + r""" + (?:'[^']*(?:''[^']*)*') | # Skip single-quoted strings (with '' escapes) + (?:"[^"]*(?:""[^"]*)*") | # Skip double-quoted strings (with "" escapes) + (?:--.*?(?:\n|$)) | # Skip single-line comments + (?:/\*(?:[^*]|\*(?!/))*\*/) | # Skip multi-line comments + (\?) # Capture only question marks outside of these contexts + """, + re.VERBOSE | re.DOTALL, +) PsqlpyConnection = Connection logger = logging.getLogger("sqlspec") @@ -58,140 +76,83 @@ def _process_sql_params( The SQL statement and parameters. Raises: - ParameterStyleMismatchError: If the parameter style doesn't match the SQL statement. SQLParsingError: If the SQL parsing fails. """ - # First, use SQLStatement for parameter validation - statement = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs) - sql, validated_params = statement.process() + # Handle scalar parameter by converting to a single-item tuple + if parameters is not None and not isinstance(parameters, (list, tuple, dict)): + parameters = (parameters,) - if validated_params is None: - return sql, None # psqlpy can handle None + # Create and process the statement + statement = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs, dialect=self.dialect) - # Now use SQLGlot for PostgreSQL-specific parameter handling - try: - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"psqlpy: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Traditional named parameters (e.g., @name, $name) - sql_named_param_nodes = [ - node for node in parsed_expression.find_all(exp.Parameter) if node.name and not node.name.isdigit() - ] - - # Named placeholders (e.g., :name which are parsed as Placeholder with this="name") - named_placeholder_nodes = [ - node - for node in parsed_expression.find_all(exp.Placeholder) - if isinstance(node.this, str) and not node.this.isdigit() - ] - - # Anonymous placeholders (?) - qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] - - # PostgreSQL-specific dollar-numeric parameters like $1, $2 - sql_numeric_dollar_nodes = [ - node - for node in parsed_expression.find_all(exp.Parameter) - if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() - ] - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - - if isinstance(validated_params, dict): - # Dictionary parameters - need to convert named parameters from :name to $n style - if qmark_placeholder_nodes or sql_numeric_dollar_nodes: - msg = "psqlpy: Dictionary parameters provided, but SQL uses positional placeholders. Use named placeholders (e.g., :name)." - raise ParameterStyleMismatchError(msg) - - if not sql_named_param_nodes and not named_placeholder_nodes: - msg = "psqlpy: Dictionary parameters provided, but no named placeholders found in SQL by sqlglot." - raise ParameterStyleMismatchError(msg) - - # Transform named parameters to $n placeholders for psqlpy - param_seq = [] - - def _convert_named_to_dollar(node: exp.Expression) -> exp.Expression: - param_name = None - if isinstance(node, exp.Parameter) and node.name: - param_name = node.name - elif isinstance(node, exp.Placeholder) and isinstance(node.this, str) and not node.this.isdigit(): - param_name = node.this - - if param_name and param_name in validated_params: - param_seq.append(validated_params[param_name]) - # Create a Parameter node that PostgreSQL will interpret as a positional parameter ($n) - return exp.Parameter(this=str(len(param_seq))) - return node - - transformed_expression = parsed_expression.transform(_convert_named_to_dollar, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - final_params = tuple(param_seq) - - elif hasattr(validated_params, "__iter__") and not isinstance(validated_params, (str, bytes, dict)): - # Sequence parameters (list or tuple) - if sql_named_param_nodes or named_placeholder_nodes: - msg = "psqlpy: Sequence parameters provided, but SQL contains named placeholders. Use positional placeholders ('?' or '$1')." - raise ParameterStyleMismatchError(msg) - - # Count placeholders for validation - total_positional_params = len(qmark_placeholder_nodes) + len(sql_numeric_dollar_nodes) - if total_positional_params != len(validated_params): - msg = ( - f"psqlpy: Parameter count mismatch. SQL expects {total_positional_params} " - f"positional placeholders, but {len(validated_params)} parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) + # Apply any filters if present + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) - param_seq = list(validated_params) + # Process the statement + sql, validated_params, parsed_expr = statement.process() - # Convert question marks to $n parameters - if qmark_placeholder_nodes: - counter = [0] # Make it mutable for the inner function + if validated_params is None: + return sql, None # psqlpy can handle None - def _convert_qmark_to_dollar(node: exp.Expression) -> exp.Expression: - if isinstance(node, exp.Placeholder) and node.this is None: - counter[0] += 1 - return exp.Parameter(this=str(counter[0])) + # Convert positional parameters from question mark style to PostgreSQL's $N style + if isinstance(validated_params, (list, tuple)): + # Use a counter to generate $1, $2, etc. for each ? in the SQL that's outside strings/comments + param_index = 0 + + def replace_question_mark(match: Match[str]) -> str: + # Only process the match if it's not in a skipped context (string/comment) + if match.group(1): # This is a question mark outside string/comment + nonlocal param_index + param_index += 1 + return f"${param_index}" + # Return the entire matched text unchanged for strings/comments + return match.group(0) + + return QUESTION_MARK_PATTERN.sub(replace_question_mark, sql), tuple(validated_params) + + # If no parsed expression is available, we can't safely transform dictionary parameters + if is_dict(validated_params) and parsed_expr is None: + msg = f"psqlpy: SQL parsing failed and dictionary parameters were provided. Cannot determine parameter order without successful parse. SQL: {sql}" + raise SQLParsingError(msg) + + # Convert dictionary parameters to the format expected by psqlpy + if is_dict(validated_params) and parsed_expr is not None: + # Find all named parameters in the SQL expression + named_params = [] + + for node in parsed_expr.find_all(exp.Parameter, exp.Placeholder): + if isinstance(node, exp.Parameter) and node.name and node.name in validated_params: + named_params.append(node.name) + elif isinstance(node, exp.Placeholder) and isinstance(node.this, str) and node.this in validated_params: + named_params.append(node.this) + + if named_params: + # Transform the SQL to use $1, $2, etc. + def convert_named_to_dollar(node: exp.Expression) -> exp.Expression: + if isinstance(node, exp.Parameter) and node.name and node.name in validated_params: + idx = named_params.index(node.name) + 1 + return exp.Parameter(this=str(idx)) + if ( + isinstance(node, exp.Placeholder) + and isinstance(node.this, str) + and node.this in validated_params + ): + idx = named_params.index(node.this) + 1 + return exp.Parameter(this=str(idx)) return node - transformed_expression = parsed_expression.transform(_convert_qmark_to_dollar, copy=True) - final_sql = transformed_expression.sql(dialect=self.dialect) - else: - final_sql = parsed_expression.sql(dialect=self.dialect) - - final_params = tuple(param_seq) - - else: # Scalar parameter (if validated_params is not None and not a sequence) - if sql_named_param_nodes or named_placeholder_nodes: - msg = "psqlpy: Scalar parameter provided, but SQL contains named placeholders. Use a single positional placeholder ('?' or '$1')." - raise ParameterStyleMismatchError(msg) - - total_positional_params = len(qmark_placeholder_nodes) + len(sql_numeric_dollar_nodes) - if total_positional_params != 1: - msg = ( - f"psqlpy: Scalar parameter provided, but SQL expects {total_positional_params} " - f"positional placeholders. Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - - # For scalar parameter with question mark, convert to $1 - if qmark_placeholder_nodes: - transformed_expression = parsed_expression.transform( - lambda node: exp.Parameter(this="1") - if isinstance(node, exp.Placeholder) and node.this is None - else node, - copy=True, + return parsed_expr.transform(convert_named_to_dollar, copy=True).sql(dialect=self.dialect), tuple( + validated_params[name] for name in named_params ) - final_sql = transformed_expression.sql(dialect=self.dialect) - else: - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = (validated_params,) # psqlpy expects a tuple for $1 + # If no named parameters were found in the SQL but dictionary was provided + return sql, tuple(validated_params.values()) - return final_sql, final_params + # For any other case, return validated params + return sql, (validated_params,) if not isinstance(validated_params, (list, tuple)) else tuple(validated_params) # type: ignore[unreachable] # --- Public API Methods --- # @overload diff --git a/sqlspec/adapters/psycopg/driver.py b/sqlspec/adapters/psycopg/driver.py index 312fc74..8d6cbcd 100644 --- a/sqlspec/adapters/psycopg/driver.py +++ b/sqlspec/adapters/psycopg/driver.py @@ -1,15 +1,16 @@ import logging +import re from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot from psycopg import AsyncConnection, Connection from psycopg.rows import dict_row -from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError +from sqlspec.exceptions import ParameterStyleMismatchError from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.statement import SQLStatement +from sqlspec.typing import is_dict if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence @@ -20,12 +21,17 @@ __all__ = ("PsycopgAsyncConnection", "PsycopgAsyncDriver", "PsycopgSyncConnection", "PsycopgSyncDriver") + +NAMED_PARAMS_PATTERN = re.compile(r"(? "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for psycopg driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters - # else merged_params remains None - - # Special case: if merged_params is an empty dict, treat it as None for parameterless queries - if isinstance(merged_params, dict) and not merged_params: - merged_params = None - - # 2. SQLGlot Parsing - try: - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"psycopg: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Traditional named parameters (e.g., @name, $name) - sql_named_param_nodes = [ - node for node in parsed_expression.find_all(exp.Parameter) if node.name and not node.name.isdigit() - ] - - # Named placeholders (e.g., :name which are parsed as Placeholder with this="name") - named_placeholder_nodes = [ - node - for node in parsed_expression.find_all(exp.Placeholder) - if isinstance(node.this, str) and not node.this.isdigit() - ] - - # Anonymous placeholders (?) - qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] - - # Numeric dollar params (e.g., $1, $2) - sql_numeric_dollar_nodes = [ - node - for node in parsed_expression.find_all(exp.Parameter) - if not node.name and node.this and isinstance(node.this, str) and node.this.isdigit() - ] - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes or sql_numeric_dollar_nodes: - placeholder_types = set() - if sql_named_param_nodes or named_placeholder_nodes: - placeholder_types.add("named (e.g., :name)") - if qmark_placeholder_nodes: - placeholder_types.add("qmark ('?')") - if sql_numeric_dollar_nodes: - placeholder_types.add("numeric ($n)") - msg = ( - f"psycopg: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - return sql, None # psycopg can take None for params - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - - if isinstance(merged_params, dict): - # Dictionary parameters. Aim for %(name)s style for psycopg. - if qmark_placeholder_nodes or sql_numeric_dollar_nodes: - msg = "psycopg: Dictionary parameters provided, but SQL uses positional placeholders ('?' or $n). Use named placeholders for dictionary params (e.g. :name, which will be converted to %(name)s)." - raise ParameterStyleMismatchError(msg) - - if not sql_named_param_nodes and not named_placeholder_nodes and "%(" not in sql: - msg = "psycopg: Dictionary parameters provided, but no standard named placeholders (e.g., :name) found to convert to %(name)s, and SQL does not appear to be pyformat already." - raise ParameterStyleMismatchError(msg) - - if sql_named_param_nodes or named_placeholder_nodes: - # Collect parameter names from both types of nodes - sql_param_names_in_ast = set() - - # Get names from Parameter nodes - sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) - - # Get names from Placeholder nodes - sql_param_names_in_ast.update( - node.this for node in named_placeholder_nodes if isinstance(node.this, str) - ) - - provided_keys = set(merged_params.keys()) - - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"psycopg: Named parameters {missing_keys} (from :name style) found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - try: - final_sql = parsed_expression.sql(dialect=self.dialect, pyformat=True) - except Exception as e: - logger.exception("psycopg: Failed to generate pyformat SQL with sqlglot: %s. SQL: %s", e, sql) - if "%(" in sql: - final_sql = sql - else: - msg = f"psycopg: Error generating pyformat SQL: {e}" - raise SQLParsingError(msg) from e - - final_params = merged_params - - elif isinstance(merged_params, (list, tuple)): - # Sequence parameters. Aim for %s style. - if sql_named_param_nodes or named_placeholder_nodes: - msg = "psycopg: Sequence parameters provided, but SQL contains named placeholders. Use '?' or '%s' for sequence parameters." - raise ParameterStyleMismatchError(msg) - if sql_numeric_dollar_nodes: - msg = "psycopg: Sequence parameters provided, but SQL uses $n style. Use '?' or '%s' for psycopg." - raise ParameterStyleMismatchError(msg) - - expected_param_count = len(qmark_placeholder_nodes) - if expected_param_count == 0 and "%s" in sql and not qmark_placeholder_nodes: - logger.debug( - "psycopg: No '?' found, but '%s' present with sequence params. Assuming intended for '%s' style. Count validation relies on psycopg." - ) - elif expected_param_count != len(merged_params) and not ("%s" in sql and expected_param_count == 0): - if not ("%s" in sql and len(merged_params) > 0 and expected_param_count == 0): - msg = ( - f"psycopg: Parameter count mismatch. SQL (based on '?' count) expects " - f"{expected_param_count} positional placeholders, but {len(merged_params)} were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = tuple(merged_params) - - elif merged_params is not None: # Scalar parameter - if sql_named_param_nodes or named_placeholder_nodes: - msg = "psycopg: Scalar parameter provided, but SQL uses named placeholders. Use a single '?' or '%s'." - raise ParameterStyleMismatchError(msg) - if sql_numeric_dollar_nodes: - msg = "psycopg: Scalar parameter provided, but SQL uses $n style. Use '?' or '%s' for psycopg." - raise ParameterStyleMismatchError(msg) - - expected_param_count = len(qmark_placeholder_nodes) - if expected_param_count == 0 and "%s" in sql and not qmark_placeholder_nodes: - logger.debug( - "psycopg: No '?' for scalar, but '%s' present. Assuming '%s' style. Count relies on psycopg." - ) - elif expected_param_count != 1 and not ("%s" in sql and expected_param_count == 0): - if not ("%s" in sql and expected_param_count == 0): # Avoid error if it might be a single %s - msg = ( - f"psycopg: Scalar parameter provided, but SQL expects {expected_param_count} " - f"positional placeholders ('?' or '%s'). Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = (merged_params,) - - else: # Should be caught by 'merged_params is None' earlier - final_sql = sql - final_params = None - - return final_sql, final_params + """Process SQL and parameters using SQLStatement with dialect support. + + Args: + sql: The SQL statement to process. + parameters: The parameters to bind to the statement. + **kwargs: Additional keyword arguments (including filters). + + Raises: + ParameterStyleMismatchError: If the parameter style is mismatched. + + Returns: + A tuple of (sql, parameters) ready for execution. + """ + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + + processed_sql, processed_params, _ = statement.process() + + if is_dict(processed_params): + named_params = NAMED_PARAMS_PATTERN.findall(processed_sql) + + if not named_params: + if PSYCOPG_PARAMS_PATTERN.search(processed_sql): + return processed_sql, processed_params + + if processed_params: + msg = "psycopg: Dictionary parameters provided, but no named placeholders found in SQL." + raise ParameterStyleMismatchError(msg) + return processed_sql, None + + # Convert named parameters to psycopg's preferred format + return NAMED_PARAMS_PATTERN.sub("%s", processed_sql), tuple(processed_params[name] for name in named_params) + + # For sequence parameters, ensure they're a tuple + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + + # For scalar parameter or None + if processed_params is not None: + return processed_sql, (processed_params,) + + return processed_sql, None class PsycopgSyncDriver( @@ -207,7 +95,6 @@ class PsycopgSyncDriver( """Psycopg Sync Driver Adapter.""" connection: "PsycopgSyncConnection" - dialect: str = "postgres" def __init__(self, connection: "PsycopgSyncConnection") -> None: self.connection = connection @@ -565,7 +452,6 @@ class PsycopgAsyncDriver( """Psycopg Async Driver Adapter.""" connection: "PsycopgAsyncConnection" - dialect: str = "postgres" def __init__(self, connection: "PsycopgAsyncConnection") -> None: self.connection = connection @@ -608,8 +494,8 @@ async def select( parameters: "Optional[StatementParameterType]" = None, /, *, - connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, + connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": """Fetch data from the database. @@ -619,15 +505,14 @@ async def select( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - results: list[Union[ModelDTOT, dict[str, Any]]] = [] - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) results = await cursor.fetchall() if not results: return [] + if schema_type is not None: - return [cast("ModelDTOT", schema_type(**cast("dict[str,Any]", row))) for row in results] # pyright: ignore[reportUnknownArgumentType] + return [cast("ModelDTOT", schema_type(**row)) for row in results] # pyright: ignore[reportUnknownArgumentType] return [cast("dict[str,Any]", row) for row in results] # pyright: ignore[reportUnknownArgumentType] @overload @@ -669,7 +554,6 @@ async def select_one( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() @@ -717,7 +601,6 @@ async def select_one_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() @@ -766,7 +649,6 @@ async def select_value( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() @@ -777,6 +659,28 @@ async def select_value( return schema_type(val) # type: ignore[call-arg] return val + @overload + async def select_value_or_none( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + *, + connection: "Optional[PsycopgAsyncConnection]" = None, + schema_type: None = None, + **kwargs: Any, + ) -> "Optional[Any]": ... + @overload + async def select_value_or_none( + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + *, + connection: "Optional[PsycopgAsyncConnection]" = None, + schema_type: "type[T]", + **kwargs: Any, + ) -> "Optional[T]": ... async def select_value_or_none( self, sql: str, @@ -794,7 +698,6 @@ async def select_value_or_none( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() @@ -891,7 +794,6 @@ async def execute_script( """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) - async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) return str(cursor.statusmessage) if cursor.statusmessage is not None else "DONE" diff --git a/sqlspec/adapters/sqlite/driver.py b/sqlspec/adapters/sqlite/driver.py index 1ddadb9..9343e72 100644 --- a/sqlspec/adapters/sqlite/driver.py +++ b/sqlspec/adapters/sqlite/driver.py @@ -4,12 +4,10 @@ from sqlite3 import Cursor from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload -import sqlglot -from sqlglot import exp - from sqlspec.base import SyncDriverAdapterProtocol -from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.statement import SQLStatement +from sqlspec.typing import is_dict if TYPE_CHECKING: from collections.abc import Generator, Sequence @@ -54,142 +52,40 @@ def _process_sql_params( /, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": - """Process SQL and parameters for SQLite. + """Process SQL and parameters for SQLite using SQLStatement. SQLite supports both named (:name) and positional (?) parameters. - This method merges parameters, validates them, and ensures SQL is in a consistent - format for the sqlite driver using sqlglot. + This method processes the SQL with dialect-aware parsing and handles + parameters appropriately for SQLite. + + Args: + sql: The SQL to process. + parameters: The parameters to process. + kwargs: Additional keyword arguments. + + Returns: + A tuple of (processed SQL, processed parameters). """ - # 1. Merge parameters and kwargs - merged_params: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...], Any]] = None # Allow Any for scalar - - if kwargs: - if isinstance(parameters, dict): - merged_params = {**parameters, **kwargs} - elif parameters is not None: - msg = "Cannot mix positional parameters with keyword arguments for SQLite driver." - raise ParameterStyleMismatchError(msg) - else: - merged_params = kwargs - elif parameters is not None: - merged_params = parameters - # else merged_params remains None - - # Special case: if merged_params is an empty dict, treat it as None for parameterless queries - if isinstance(merged_params, dict) and not merged_params: - merged_params = None - - # 2. SQLGlot Parsing - try: - # self.dialect is "sqlite" - parsed_expression = sqlglot.parse_one(sql, read=self.dialect) - except Exception as e: - msg = f"sqlite: Failed to parse SQL with sqlglot: {e}. SQL: {sql}" - raise SQLParsingError(msg) from e - - # Traditional named parameters (e.g., @name) - sql_named_param_nodes = [node for node in parsed_expression.find_all(exp.Parameter) if node.name] - - # Named placeholders parsed as Placeholder nodes (e.g., :name in some dialects) - named_placeholder_nodes = [ - node - for node in parsed_expression.find_all(exp.Placeholder) - if isinstance(node.this, str) and not node.this.isdigit() - ] - - # Anonymous placeholders (?) - qmark_placeholder_nodes = [node for node in parsed_expression.find_all(exp.Placeholder) if node.this is None] - - # 3. Handle No Parameters Case - if merged_params is None: - if sql_named_param_nodes or named_placeholder_nodes or qmark_placeholder_nodes: - placeholder_types = set() - if sql_named_param_nodes or named_placeholder_nodes: - placeholder_types.add("named (e.g., :name, @name)") - if qmark_placeholder_nodes: - placeholder_types.add("qmark ('?')") - msg = ( - f"sqlite: SQL statement contains {', '.join(placeholder_types) if placeholder_types else 'unknown'} " - f"parameter placeholders, but no parameters were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - return sql, None # SQLite can take None - - final_sql: str - final_params: Optional[Union[tuple[Any, ...], dict[str, Any]]] = None - - if isinstance(merged_params, dict): - # Dictionary parameters. SQLite client handles :name natively. - if qmark_placeholder_nodes: - msg = "sqlite: Dictionary parameters provided, but SQL uses positional placeholders ('?'). Use named placeholders (e.g., :name)." - raise ParameterStyleMismatchError(msg) - - if not sql_named_param_nodes and not named_placeholder_nodes: - msg = ( - "sqlite: Dictionary parameters provided, but no named placeholders (e.g., :name) found by sqlglot." - ) - raise ParameterStyleMismatchError(msg) - - # Collect parameter names from both types of nodes - sql_param_names_in_ast = set() - - # Get names from Parameter nodes - sql_param_names_in_ast.update(node.name for node in sql_named_param_nodes if node.name) - - # Get names from Placeholder nodes - sql_param_names_in_ast.update(node.this for node in named_placeholder_nodes if isinstance(node.this, str)) - - provided_keys = set(merged_params.keys()) - - missing_keys = sql_param_names_in_ast - provided_keys - if missing_keys: - msg = f"sqlite: Named parameters {missing_keys} found in SQL but not provided. SQL: {sql}" - raise SQLParsingError(msg) - - extra_keys = provided_keys - sql_param_names_in_ast - if extra_keys: - msg = f"sqlite: Parameters {extra_keys} provided but not found in SQL. SQLite might ignore them. SQL: {sql}" - logger.warning(msg) - - # Generate SQL with sqlite dialect for named params - final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures consistent named param style - final_params = merged_params # SQLite handles dict directly - - elif isinstance(merged_params, (list, tuple)): - # Sequence parameters. SQLite uses '?'. - if sql_named_param_nodes or named_placeholder_nodes: - msg = "sqlite: Sequence parameters provided, but SQL uses named placeholders. Use '?' for sequence parameters." - raise ParameterStyleMismatchError(msg) - - if len(qmark_placeholder_nodes) != len(merged_params): - msg = ( - f"sqlite: Parameter count mismatch. SQL expects {len(qmark_placeholder_nodes)} '?' placeholders, " - f"but {len(merged_params)} were provided. SQL: {sql}" - ) - raise SQLParsingError(msg) - - final_sql = parsed_expression.sql(dialect=self.dialect) # Ensures '?' style - final_params = tuple(merged_params) # SQLite can take a tuple - - elif merged_params is not None: # Scalar parameter - if sql_named_param_nodes or named_placeholder_nodes: - msg = "sqlite: Scalar parameter provided, but SQL uses named placeholders. Use a single '?'." - raise ParameterStyleMismatchError(msg) - - if len(qmark_placeholder_nodes) != 1: - msg = ( - f"sqlite: Scalar parameter provided, but SQL expects {len(qmark_placeholder_nodes)} '?' placeholders. " - f"Expected 1. SQL: {sql}" - ) - raise SQLParsingError(msg) - final_sql = parsed_expression.sql(dialect=self.dialect) - final_params = (merged_params,) # SQLite needs a tuple for a scalar - - else: # Should be caught by 'merged_params is None' earlier - final_sql = sql - final_params = None - - return final_sql, final_params + # Create a SQLStatement with SQLite dialect + statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) + + filters = kwargs.pop("filters", None) + if filters: + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + + processed_sql, processed_params, _ = statement.process() + + if processed_params is None: + return processed_sql, None + + if is_dict(processed_params): + return processed_sql, processed_params + + if isinstance(processed_params, (list, tuple)): + return processed_sql, tuple(processed_params) + + return processed_sql, (processed_params,) # --- Public API Methods --- # @overload diff --git a/sqlspec/base.py b/sqlspec/base.py index 2e88904..1c752ac 100644 --- a/sqlspec/base.py +++ b/sqlspec/base.py @@ -548,7 +548,8 @@ def _process_sql_params( # Instantiate SQLStatement with parameters and kwargs for internal merging stmt = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs or None) # Process uses the merged parameters internally - return stmt.process() + processed = stmt.process() + return processed[0], processed[1] # Return only the SQL and parameters, discard the third element class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]): diff --git a/sqlspec/extensions/litestar/handlers.py b/sqlspec/extensions/litestar/handlers.py index ef8fc6a..2de5652 100644 --- a/sqlspec/extensions/litestar/handlers.py +++ b/sqlspec/extensions/litestar/handlers.py @@ -1,6 +1,3 @@ -# sqlspec/extensions/litestar/handlers.py -"""ASGI Message handlers and dependency providers for the Litestar SQLSpec extension.""" - import contextlib from typing import TYPE_CHECKING, Any, Callable, Optional, cast @@ -238,16 +235,7 @@ async def provide_connection(state: "State", scope: "Scope") -> "ConnectionT": msg = f"Database pool with key '{pool_key}' not found in application state. Cannot create a connection." raise ImproperConfigurationError(msg) - # Acquire a new connection from the pool. - # This relies on the DatabaseConfigProtocol's `acquire_connection_from_pool` method. - if not hasattr(config, "acquire_connection_from_pool"): - msg = ( - f"The DatabaseConfigProtocol implementation for dialect '{config.dialect_name}' " # type: ignore[attr-defined] - "is missing the 'acquire_connection_from_pool' method, " - "which is required for pooled connection management." - ) - raise ImproperConfigurationError(msg) - connection = await ensure_async_(config.acquire_connection_from_pool(db_pool)) # type: ignore[attr-defined] + connection = await ensure_async_(config.provide_connection)(db_pool) set_sqlspec_scope_state(scope, connection_key, connection) return cast("ConnectionT", connection) @@ -295,14 +283,7 @@ async def provide_session(state: "State", scope: "Scope") -> "DriverT": if db_pool is None: msg = f"Database pool with key '{pool_key}' not found in application state while trying to create a session." raise ImproperConfigurationError(msg) - if not hasattr(config, "acquire_connection_from_pool"): - msg = ( - f"The DatabaseConfigProtocol implementation for dialect '{config.dialect_name}' " # type: ignore[attr-defined] - "is missing the 'acquire_connection_from_pool' method, " - "which is required for pooled connection management." - ) - raise ImproperConfigurationError(msg) - connection = await ensure_async_(config.acquire_connection_from_pool(db_pool)) # type: ignore[attr-defined] + connection = await ensure_async_(config.provide_session)(db_pool) set_sqlspec_scope_state(scope, connection_key, connection) # Create the driver/session instance with the (pooled) connection diff --git a/sqlspec/filters.py b/sqlspec/filters.py index 2525bb6..62d3c3f 100644 --- a/sqlspec/filters.py +++ b/sqlspec/filters.py @@ -1,13 +1,16 @@ """Collection filter datastructures.""" -from abc import ABC +from abc import ABC, abstractmethod from collections import abc from dataclasses import dataclass from datetime import datetime -from typing import Generic, Literal, Optional, Protocol, Union +from typing import Any, Generic, Literal, Optional, Protocol, Union, cast +from sqlglot import exp from typing_extensions import TypeVar +from sqlspec.statement import SQLStatement + __all__ = ( "BeforeAfter", "CollectionFilter", @@ -20,17 +23,24 @@ "PaginationFilter", "SearchFilter", "StatementFilter", + "apply_filter", ) T = TypeVar("T") -StatementT = TypeVar("StatementT", bound="str") class StatementFilter(Protocol): """Protocol for filters that can be appended to a statement.""" - def append_to_statement(self, statement: StatementT) -> StatementT: - """Append the filter to the statement.""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + """Append the filter to the statement. + + Args: + statement: The SQL statement to modify. + + Returns: + The modified statement. + """ return statement @@ -45,6 +55,27 @@ class BeforeAfter(StatementFilter): after: Optional[datetime] = None """Filter results where field later than this.""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + conditions = [] + params: dict[str, Any] = {} + col_expr = exp.column(self.field_name) + + if self.before: + param_name = statement.generate_param_name(f"{self.field_name}_before") + conditions.append(exp.LT(this=col_expr, expression=exp.Placeholder(this=param_name))) + params[param_name] = self.before + if self.after: + param_name = statement.generate_param_name(f"{self.field_name}_after") + conditions.append(exp.GT(this=col_expr, expression=exp.Placeholder(this=param_name))) # type: ignore[arg-type] + params[param_name] = self.after + + if conditions: + final_condition = conditions[0] + for cond in conditions[1:]: + final_condition = exp.And(this=final_condition, expression=cond) # type: ignore[assignment] + statement.add_condition(final_condition, params) + return statement + @dataclass class OnBeforeAfter(StatementFilter): @@ -57,13 +88,38 @@ class OnBeforeAfter(StatementFilter): on_or_after: Optional[datetime] = None """Filter results where field on or later than this.""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + conditions = [] + params: dict[str, Any] = {} + col_expr = exp.column(self.field_name) + + if self.on_or_before: + param_name = statement.generate_param_name(f"{self.field_name}_on_or_before") + conditions.append(exp.LTE(this=col_expr, expression=exp.Placeholder(this=param_name))) + params[param_name] = self.on_or_before + if self.on_or_after: + param_name = statement.generate_param_name(f"{self.field_name}_on_or_after") + conditions.append(exp.GTE(this=col_expr, expression=exp.Placeholder(this=param_name))) # type: ignore[arg-type] + params[param_name] = self.on_or_after + + if conditions: + final_condition = conditions[0] + for cond in conditions[1:]: + final_condition = exp.And(this=final_condition, expression=cond) # type: ignore[assignment] + statement.add_condition(final_condition, params) + return statement + -class InAnyFilter(StatementFilter, ABC): +class InAnyFilter(StatementFilter, ABC, Generic[T]): """Subclass for methods that have a `prefer_any` attribute.""" + @abstractmethod + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + raise NotImplementedError + @dataclass -class CollectionFilter(InAnyFilter, Generic[T]): +class CollectionFilter(InAnyFilter[T]): """Data required to construct a ``WHERE ... IN (...)`` clause.""" field_name: str @@ -73,9 +129,30 @@ class CollectionFilter(InAnyFilter, Generic[T]): An empty list will return an empty result set, however, if ``None``, the filter is not applied to the query, and all rows are returned. """ + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + if self.values is None: + return statement + + if not self.values: # Empty collection + # Add a condition that is always false + statement.add_condition(exp.false()) + return statement + + placeholder_expressions: list[exp.Placeholder] = [] + current_params: dict[str, Any] = {} + + for i, value_item in enumerate(self.values): + param_key = statement.generate_param_name(f"{self.field_name}_in_{i}") + placeholder_expressions.append(exp.Placeholder(this=param_key)) + current_params[param_key] = value_item + + in_condition = exp.In(this=exp.column(self.field_name), expressions=placeholder_expressions) + statement.add_condition(in_condition, current_params) + return statement + @dataclass -class NotInCollectionFilter(InAnyFilter, Generic[T]): +class NotInCollectionFilter(InAnyFilter[T]): """Data required to construct a ``WHERE ... NOT IN (...)`` clause.""" field_name: str @@ -85,10 +162,31 @@ class NotInCollectionFilter(InAnyFilter, Generic[T]): An empty list or ``None`` will return all rows.""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + if self.values is None or not self.values: # Empty list or None, no filter applied + return statement + + placeholder_expressions: list[exp.Placeholder] = [] + current_params: dict[str, Any] = {} + + for i, value_item in enumerate(self.values): + param_key = statement.generate_param_name(f"{self.field_name}_notin_{i}") + placeholder_expressions.append(exp.Placeholder(this=param_key)) + current_params[param_key] = value_item + + in_expr = exp.In(this=exp.column(self.field_name), expressions=placeholder_expressions) + not_in_condition = exp.Not(this=in_expr) + statement.add_condition(not_in_condition, current_params) + return statement + class PaginationFilter(StatementFilter, ABC): """Subclass for methods that function as a pagination type.""" + @abstractmethod + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + raise NotImplementedError + @dataclass class LimitOffset(PaginationFilter): @@ -99,6 +197,16 @@ class LimitOffset(PaginationFilter): offset: int """Value for ``OFFSET`` clause of query.""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + # Generate parameter names for limit and offset + limit_param_name = statement.generate_param_name("limit_val") + offset_param_name = statement.generate_param_name("offset_val") + + statement.add_limit(self.limit, param_name=limit_param_name) + statement.add_offset(self.offset, param_name=offset_param_name) + + return statement + @dataclass class OrderBy(StatementFilter): @@ -109,6 +217,16 @@ class OrderBy(StatementFilter): sort_order: Literal["asc", "desc"] = "asc" """Sort ascending or descending""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + # Basic validation for sort_order, though Literal helps at type checking time + normalized_sort_order = self.sort_order.lower() + if normalized_sort_order not in {"asc", "desc"}: + normalized_sort_order = "asc" + + statement.add_order_by(self.field_name, direction=cast("Literal['asc', 'desc']", normalized_sort_order)) + + return statement + @dataclass class SearchFilter(StatementFilter): @@ -121,7 +239,77 @@ class SearchFilter(StatementFilter): ignore_case: Optional[bool] = False """Should the search be case insensitive.""" + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + if not self.value: + return statement + + search_val_param_name = statement.generate_param_name("search_val") + + # The pattern %value% needs to be handled carefully. + params = {search_val_param_name: f"%{self.value}%"} + pattern_expr = exp.Placeholder(this=search_val_param_name) + + like_op = exp.ILike if self.ignore_case else exp.Like + + if isinstance(self.field_name, str): + condition = like_op(this=exp.column(self.field_name), expression=pattern_expr) + statement.add_condition(condition, params) + elif isinstance(self.field_name, set) and self.field_name: + field_conditions = [like_op(this=exp.column(field), expression=pattern_expr) for field in self.field_name] + if not field_conditions: + return statement + + final_condition = field_conditions[0] + for cond in field_conditions[1:]: + final_condition = exp.Or(this=final_condition, expression=cond) # type: ignore[assignment] + statement.add_condition(final_condition, params) + + return statement + @dataclass -class NotInSearchFilter(SearchFilter): +class NotInSearchFilter(SearchFilter): # Inherits field_name, value, ignore_case """Data required to construct a ``WHERE field_name NOT LIKE '%' || :value || '%'`` clause.""" + + def append_to_statement(self, statement: SQLStatement) -> SQLStatement: + if not self.value: + return statement + + search_val_param_name = statement.generate_param_name("not_search_val") + + params = {search_val_param_name: f"%{self.value}%"} + pattern_expr = exp.Placeholder(this=search_val_param_name) + + like_op = exp.ILike if self.ignore_case else exp.Like + + if isinstance(self.field_name, str): + condition = exp.Not(this=like_op(this=exp.column(self.field_name), expression=pattern_expr)) + statement.add_condition(condition, params) + elif isinstance(self.field_name, set) and self.field_name: + field_conditions = [ + exp.Not(this=like_op(this=exp.column(field), expression=pattern_expr)) for field in self.field_name + ] + if not field_conditions: + return statement + + # Combine with AND: (field1 NOT LIKE pattern) AND (field2 NOT LIKE pattern) ... + final_condition = field_conditions[0] + for cond in field_conditions[1:]: + final_condition = exp.And(this=final_condition, expression=cond) # type: ignore[assignment] + statement.add_condition(final_condition, params) + + return statement + + +# Function to be imported in SQLStatement module +def apply_filter(statement: SQLStatement, filter_obj: StatementFilter) -> SQLStatement: + """Apply a statement filter to a SQL statement. + + Args: + statement: The SQL statement to modify. + filter_obj: The filter to apply. + + Returns: + The modified statement. + """ + return filter_obj.append_to_statement(statement) diff --git a/sqlspec/statement.py b/sqlspec/statement.py index 25246a5..2ded555 100644 --- a/sqlspec/statement.py +++ b/sqlspec/statement.py @@ -1,8 +1,9 @@ # ruff: noqa: RUF100, PLR6301, PLR0912, PLR0915, C901, PLR0911, PLR0914, N806 import logging -import re -from dataclasses import dataclass +from collections.abc import Sequence +from dataclasses import dataclass, field from typing import ( + TYPE_CHECKING, Any, Optional, Union, @@ -14,64 +15,13 @@ from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError from sqlspec.typing import StatementParameterType +if TYPE_CHECKING: + from sqlspec.filters import StatementFilter + __all__ = ("SQLStatement",) logger = logging.getLogger("sqlspec") -CONSOLIDATED_PARAM_REGEX = re.compile( - r""" - # Fields to skip (matched first, then ignored in processing logic) - (?P"(?:[^"]|"")*") | # Double-quoted strings (SQL standard "" escaping) - (?P'(?:[^']|'')*') | # Single-quoted strings (SQL standard '' escaping) - (?P--.*?\n|\/\*.*?\*\/) | # SQL comments (single-line or multi-line) - - # Actual placeholders - attempt to match one of these - (?: # Non-capturing group for colon-numeric POSITIONAL parameter (e.g., :1, :23) - (?[1-9][0-9]*) # Captured number (1-9 followed by 0 or more digits) - ) | - (?: # Non-capturing group for colon-prefixed named parameter (e.g., :name) - (?[a-zA-Z_][a-zA-Z0-9_]*) # Captured variable name - ) | - (?: # Non-capturing group for question mark positional parameter (e.g., ?) - # Needs careful lookaround if we want to avoid matching e.g. JSON operators '?|' - # For now, keeping it simple as SQL '?' is usually well-spaced or at end of comparisons. - # A full context-aware parse (like sqlglot) is primary, this is a fallback. - (?P\?) # Captured question mark - ) | - (?: # Non-capturing group for dollar-prefixed NAMED parameter (e.g., $name) - PRIORITIZE THIS OVER $n - (?[a-zA-Z_][a-zA-Z0-9_]*) # Captured variable name (must start with letter/underscore) - ) | - (?: # Non-capturing group for at-symbol-prefixed named parameter (e.g., @name) - (?[a-zA-Z_][a-zA-Z0-9_]*) # Captured variable name - ) | - (?: # Non-capturing group for pyformat named parameter (e.g., %(name)s) - (?[a-zA-Z_][a-zA-Z0-9_]*)\) # Captured variable name inside parentheses - [a-zA-Z] # Type specifier (e.g., s, d, f) - simple match for any letter - ) | - (?: # Non-capturing group for format/printf POSITIONAL parameter (e.g., %s, %d) - AFTER pyformat - (?[a-zA-Z]) # Captured type specifier (s, d, f, etc.) - ) | - (?: # Non-capturing group for numeric dollar POSITIONAL parameter (e.g., $1, $2) - (?[1-9][0-9]*) # Captured number (1-9 followed by 0 or more digits) - ) - """, - re.VERBOSE | re.DOTALL, -) - @dataclass() class SQLStatement: @@ -87,8 +37,12 @@ class SQLStatement: """The parameters for the SQL statement.""" kwargs: Optional[dict[str, Any]] = None """Keyword arguments passed for parameter binding.""" + dialect: Optional[str] = None + """SQL dialect to use for parsing. If not provided, sqlglot will try to auto-detect.""" - _merged_parameters: Optional[Union[StatementParameterType, dict[str, Any]]] = None + _merged_parameters: Optional[Union[StatementParameterType, dict[str, Any]]] = field(default=None, init=False) + _parsed_expression: Optional[exp.Expression] = field(default=None, init=False) + _param_counter: int = field(default=0, init=False) def __post_init__(self) -> None: """Merge parameters and kwargs after initialization.""" @@ -107,17 +61,21 @@ def __post_init__(self) -> None: self._merged_parameters = merged_params - def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": + def process( + self, + ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]], Optional[exp.Expression]]": """Process the SQL statement and merged parameters for execution. This method validates the parameters against the SQL statement using sqlglot - parsing but returns the *original* SQL string and the merged parameters. + parsing but returns the *original* SQL string, the merged parameters, + and the parsed sqlglot expression if successful. The actual formatting of SQL placeholders and parameter structures for the DBAPI driver is delegated to the specific adapter. Returns: - A tuple containing the *original* SQL string and the merged/validated - parameters (dict, tuple, list, or None). + A tuple containing the *original* SQL string, the merged/validated + parameters (dict, tuple, list, or None), and the parsed sqlglot expression + (or None if parsing failed). Raises: SQLParsingError: If the SQL statement contains parameter placeholders @@ -133,7 +91,8 @@ def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict logger.debug( "SQL parsing failed during validation: %s. Returning original SQL and parameters for adapter.", e ) - return self.sql, self._merged_parameters + self._parsed_expression = None + return self.sql, self._merged_parameters, None if self._merged_parameters is None: # If no parameters were provided, but the parsed SQL expects them, raise an error. @@ -142,17 +101,21 @@ def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict for p_node in all_sqlglot_placeholders: if isinstance(p_node, exp.Parameter) and p_node.name: placeholder_types_desc.append(f"named (e.g., :{p_node.name}, @{p_node.name})") - elif isinstance(p_node, exp.Placeholder) and p_node.this and not p_node.this.isdigit(): + elif ( + isinstance(p_node, exp.Placeholder) + and p_node.this + and not isinstance(p_node.this, (exp.Identifier, exp.Literal)) + and not str(p_node.this).isdigit() + ): placeholder_types_desc.append(f"named (e.g., :{p_node.this})") + elif isinstance(p_node, exp.Parameter) and p_node.name and p_node.name.isdigit(): + placeholder_types_desc.append("positional (e.g., $1, :1)") elif isinstance(p_node, exp.Placeholder) and p_node.this is None: placeholder_types_desc.append("positional (?)") - # Add more descriptions for other types like numeric $1 if necessary - # Make unique descriptions desc_str = ", ".join(sorted(set(placeholder_types_desc))) or "unknown" msg = f"SQL statement contains {desc_str} parameter placeholders, but no parameters were provided. SQL: {self.sql}" raise SQLParsingError(msg) - # No parameters provided and none found in SQL - OK - return self.sql, None + return self.sql, None, self._parsed_expression # Validate provided parameters against parsed SQL parameters if isinstance(self._merged_parameters, dict): @@ -163,7 +126,7 @@ def process(self) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict self._validate_scalar_param(all_sqlglot_placeholders, self._merged_parameters) # Return the original SQL and the merged parameters for the adapter to process - return self.sql, self._merged_parameters + return self.sql, self._merged_parameters, self._parsed_expression def _parse_sql(self) -> exp.Expression: """Parse the SQL using sqlglot. @@ -174,22 +137,23 @@ def _parse_sql(self) -> exp.Expression: Returns: The parsed SQL expression. """ - # Use a generic dialect or try autodetection if specific dialect knowledge is removed. - # For validation purposes, 'postgres' is often a good lenient default. - # Alternatively, let the caller (adapter) provide the dialect if needed for parsing hints. - # For now, let's keep it simple and assume a generic parse works for validation. try: - # Removed read=self.dialect as self.dialect is removed. - # parse_one without 'read' uses the standard dialect by default. - return sqlglot.parse_one(self.sql) + if not self.sql.strip(): + self._parsed_expression = exp.Select() + return self._parsed_expression + # Use the provided dialect if available, otherwise sqlglot will try to auto-detect + self._parsed_expression = sqlglot.parse_one(self.sql, dialect=self.dialect) + if self._parsed_expression is None: + self._parsed_expression = exp.Select() # type: ignore[unreachable] except Exception as e: - error_detail = str(e) - # Removed dialect from error message - msg = f"Failed to parse SQL for validation: {error_detail}\nSQL: {self.sql}" + msg = f"Failed to parse SQL for validation: {e!s}\nSQL: {self.sql}" + self._parsed_expression = None raise SQLParsingError(msg) from e + else: + return self._parsed_expression def _validate_dict_params( - self, all_sqlglot_placeholders: list[Union[exp.Parameter, exp.Placeholder]], parameter_dict: dict[str, Any] + self, all_sqlglot_placeholders: Sequence[exp.Expression], parameter_dict: dict[str, Any] ) -> None: sqlglot_named_params: dict[str, Union[exp.Parameter, exp.Placeholder]] = {} has_positional_qmark = False @@ -199,8 +163,13 @@ def _validate_dict_params( isinstance(p_node, exp.Parameter) and p_node.name and not p_node.name.isdigit() ): # @name, $name (non-numeric) sqlglot_named_params[p_node.name] = p_node - elif isinstance(p_node, exp.Placeholder) and p_node.this and not p_node.this.isdigit(): # :name - sqlglot_named_params[p_node.this] = p_node + elif ( + isinstance(p_node, exp.Placeholder) + and p_node.this + and not isinstance(p_node.this, (exp.Identifier, exp.Literal)) + and not str(p_node.this).isdigit() + ): # :name + sqlglot_named_params[str(p_node.this)] = p_node elif isinstance(p_node, exp.Placeholder) and p_node.this is None: # ? has_positional_qmark = True # Ignores numeric placeholders like $1, :1 for dict validation for now @@ -209,33 +178,18 @@ def _validate_dict_params( msg = f"Dictionary parameters provided, but found unnamed placeholders ('?') in SQL: {self.sql}" raise ParameterStyleMismatchError(msg) - # Regex check as a fallback (can be simplified or removed if sqlglot is trusted) - regex_named_placeholders_found = False - for match in CONSOLIDATED_PARAM_REGEX.finditer(self.sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - if match.group("var_colon") or match.group("var_dollar") or match.group("var_at"): - regex_named_placeholders_found = True - if not sqlglot_named_params and parameter_dict: - if not regex_named_placeholders_found: - msg = f"Dictionary parameters provided, but no named placeholders (e.g., ':name', '$name', '@name') found by sqlglot or regex in SQL: {self.sql}" - raise ParameterStyleMismatchError(msg) - logger.warning( - "SQLglot found no named parameters, but regex did. Proceeding with validation. SQL: %s", self.sql - ) - - required_keys = set(sqlglot_named_params.keys()) - provided_keys = set(parameter_dict.keys()) + msg = f"Dictionary parameters provided, but no named placeholders (e.g., ':name', '$name', '@name') found by sqlglot in SQL: {self.sql}" + raise ParameterStyleMismatchError(msg) - missing_keys = required_keys - provided_keys + missing_keys = set(sqlglot_named_params.keys()) - set(parameter_dict.keys()) if missing_keys: msg = f"Named parameters found in SQL by sqlglot but not provided: {missing_keys}. SQL: {self.sql}" raise SQLParsingError(msg) def _validate_sequence_params( self, - all_sqlglot_placeholders: list[Union[exp.Parameter, exp.Placeholder]], + all_sqlglot_placeholders: Sequence[exp.Expression], params: Union[tuple[Any, ...], list[Any]], ) -> None: sqlglot_named_param_names = [] # For detecting named params @@ -244,8 +198,13 @@ def _validate_sequence_params( for p_node in all_sqlglot_placeholders: if isinstance(p_node, exp.Parameter) and p_node.name and not p_node.name.isdigit(): # @name, $name sqlglot_named_param_names.append(p_node.name) - elif isinstance(p_node, exp.Placeholder) and p_node.this and not p_node.this.isdigit(): # :name - sqlglot_named_param_names.append(p_node.this) + elif ( + isinstance(p_node, exp.Placeholder) + and p_node.this + and not isinstance(p_node.this, (exp.Identifier, exp.Literal)) + and not str(p_node.this).isdigit() + ): # :name + sqlglot_named_param_names.append(str(p_node.this)) elif isinstance(p_node, exp.Placeholder) and p_node.this is None: # ? sqlglot_positional_count += 1 elif isinstance(p_node, exp.Parameter) and ( # noqa: PLR0916 @@ -253,59 +212,167 @@ def _validate_sequence_params( or ( not p_node.name and p_node.this - and isinstance(p_node.this, (str, exp.Identifier, exp.Number)) + and isinstance(p_node.this, (str, exp.Identifier, exp.Literal)) and str(p_node.this).isdigit() ) ): - # $1, :1 style (parsed as Parameter with name="1" or this="1" or this=Identifier(this="1") or this=Number(this=1)) + # $1, :1 style (parsed as Parameter with name="1" or this="1" or this=Identifier(this="1") or this=Literal(this=1)) sqlglot_positional_count += 1 elif ( - isinstance(p_node, exp.Placeholder) and p_node.this and p_node.this.isdigit() + isinstance(p_node, exp.Placeholder) and p_node.this and str(p_node.this).isdigit() ): # :1 style (Placeholder with this="1") sqlglot_positional_count += 1 - # Regex check (can be simplified if sqlglot part is robust) - regex_named_placeholders_found = False - for match in CONSOLIDATED_PARAM_REGEX.finditer(self.sql): - if match.group("dquote") or match.group("squote") or match.group("comment"): - continue - if match.group("var_colon") or match.group("var_dollar") or match.group("var_at"): - regex_named_placeholders_found = True - - if sqlglot_named_param_names or regex_named_placeholders_found: - found_by = [] - if sqlglot_named_param_names: - found_by.append(f"sqlglot ({', '.join(sorted(set(sqlglot_named_param_names)))})") - if regex_named_placeholders_found and not sqlglot_named_param_names: - found_by.append("regex") - msg = ( - f"Sequence parameters provided, but found named placeholders " - f"by {', '.join(found_by)} in SQL: {self.sql}" - ) + if sqlglot_named_param_names: + msg = f"Sequence parameters provided, but found named placeholders ({', '.join(sorted(set(sqlglot_named_param_names)))}) in SQL: {self.sql}" raise ParameterStyleMismatchError(msg) - expected_count_sqlglot = sqlglot_positional_count actual_count_provided = len(params) - if expected_count_sqlglot != actual_count_provided: - if sqlglot_positional_count != actual_count_provided: - msg = ( - f"Parameter count mismatch. SQL expects {expected_count_sqlglot} (sqlglot) / {sqlglot_positional_count} (regex) positional '?' parameters, " - f"but {actual_count_provided} were provided. SQL: {self.sql}" - ) - raise SQLParsingError(msg) - logger.warning( - "Parameter count mismatch (sqlglot: %d, provided: %d), but regex count for '?' (%d) matches provided. Proceeding. SQL: %s", - expected_count_sqlglot, - actual_count_provided, - sqlglot_positional_count, - self.sql, + if sqlglot_positional_count != actual_count_provided: + msg = ( + f"Parameter count mismatch. SQL expects {sqlglot_positional_count} (sqlglot) positional " + f"parameters, but {actual_count_provided} were provided. SQL: {self.sql}" ) + raise SQLParsingError(msg) - def _validate_scalar_param( - self, all_sqlglot_placeholders: list[Union[exp.Parameter, exp.Placeholder]], param_value: Any - ) -> None: + def _validate_scalar_param(self, all_sqlglot_placeholders: Sequence[exp.Expression], param_value: Any) -> None: """Validates a single scalar parameter against parsed SQL parameters.""" self._validate_sequence_params( all_sqlglot_placeholders, (param_value,) ) # Treat scalar as a single-element sequence + + def get_expression(self) -> exp.Expression: + """Get the parsed SQLglot expression, parsing if necessary. + + Returns: + The SQLglot expression. + """ + if self._parsed_expression is None: + self._parse_sql() + if self._parsed_expression is None: # Still None after parsing attempt + return exp.Select() # Return an empty SELECT as fallback + return self._parsed_expression + + def generate_param_name(self, base_name: str) -> str: + """Generates a unique parameter name. + + Args: + base_name: The base name for the parameter. + + Returns: + The generated parameter name. + """ + self._param_counter += 1 + safe_base_name = "".join(c if c.isalnum() else "_" for c in base_name if c.isalnum() or c == "_") + return f"param_{safe_base_name}_{self._param_counter}" + + def add_condition(self, condition: exp.Condition, params: Optional[dict[str, Any]] = None) -> None: + """Adds a condition to the WHERE clause of the query. + + Args: + condition: The condition to add to the WHERE clause. + params: The parameters to add to the statement parameters. + """ + expression = self.get_expression() + if not isinstance(expression, (exp.Select, exp.Update, exp.Delete)): + return # Cannot add WHERE to some expressions + + # Update the expression + expression.where(condition, copy=False) + + # Update the parameters + if params: + if self._merged_parameters is None: + self._merged_parameters = params + elif isinstance(self._merged_parameters, dict): + self._merged_parameters.update(params) + else: + # Convert to dict if not already + self._merged_parameters = params + + # Update the SQL string + self.sql = expression.sql(dialect=self.dialect) + + def add_order_by(self, field_name: str, direction: str = "asc") -> None: + """Adds an ORDER BY clause. + + Args: + field_name: The name of the field to order by. + direction: The direction to order by ("asc" or "desc"). + """ + expression = self.get_expression() + if not isinstance(expression, exp.Select): + return + + expression.order_by(exp.Ordered(this=exp.column(field_name), desc=direction.lower() == "desc"), copy=False) + self.sql = expression.sql(dialect=self.dialect) + + def add_limit(self, limit_val: int, param_name: Optional[str] = None) -> None: + """Adds a LIMIT clause. + + Args: + limit_val: The value for the LIMIT clause. + param_name: Optional name for the parameter. + """ + expression = self.get_expression() + if not isinstance(expression, exp.Select): + return + + if param_name: + expression.limit(exp.Placeholder(this=param_name), copy=False) + if self._merged_parameters is None: + self._merged_parameters = {param_name: limit_val} + elif isinstance(self._merged_parameters, dict): + self._merged_parameters[param_name] = limit_val + else: + expression.limit(exp.Literal.number(limit_val), copy=False) + + self.sql = expression.sql(dialect=self.dialect) + + def add_offset(self, offset_val: int, param_name: Optional[str] = None) -> None: + """Adds an OFFSET clause. + + Args: + offset_val: The value for the OFFSET clause. + param_name: Optional name for the parameter. + """ + expression = self.get_expression() + if not isinstance(expression, exp.Select): + return + + if param_name: + expression.offset(exp.Placeholder(this=param_name), copy=False) + if self._merged_parameters is None: + self._merged_parameters = {param_name: offset_val} + elif isinstance(self._merged_parameters, dict): + self._merged_parameters[param_name] = offset_val + else: + expression.offset(exp.Literal.number(offset_val), copy=False) + + self.sql = expression.sql(dialect=self.dialect) + + def apply_filter(self, filter_obj: "StatementFilter") -> "SQLStatement": + """Apply a statement filter to this statement. + + Args: + filter_obj: The filter to apply. + + Returns: + The modified statement. + """ + from sqlspec.filters import apply_filter + + return apply_filter(self, filter_obj) + + def to_sql(self, dialect: Optional[str] = None) -> str: + """Generate SQL string using the specified dialect. + + Args: + dialect: SQL dialect to use for SQL generation. If None, uses the statement's dialect. + + Returns: + SQL string in the specified dialect. + """ + expression = self.get_expression() + return expression.sql(dialect=dialect or self.dialect) diff --git a/sqlspec/typing.py b/sqlspec/typing.py index 92de8f9..b170ea8 100644 --- a/sqlspec/typing.py +++ b/sqlspec/typing.py @@ -474,7 +474,7 @@ def dataclass_to_dict( return cast("dict[str, Any]", ret) -def schema_dump( # noqa: PLR0911 +def schema_dump( data: "Union[dict[str, Any], DataclassProtocol, Struct, BaseModel]", exclude_unset: bool = True, ) -> "dict[str, Any]": @@ -503,6 +503,18 @@ def schema_dump( # noqa: PLR0911 return cast("dict[str, Any]", data) +def is_dto_data(v: Any) -> TypeGuard[DTOData[Any]]: + """Check if a value is a Litestar DTOData object. + + Args: + v: Value to check. + + Returns: + bool + """ + return LITESTAR_INSTALLED and isinstance(v, DTOData) + + __all__ = ( "LITESTAR_INSTALLED", "MSGSPEC_INSTALLED", @@ -536,6 +548,7 @@ def schema_dump( # noqa: PLR0911 "is_dict", "is_dict_with_field", "is_dict_without_field", + "is_dto_data", "is_msgspec_struct", "is_msgspec_struct_with_field", "is_msgspec_struct_without_field", @@ -566,3 +579,7 @@ def schema_dump( # noqa: PLR0911 from sqlspec._typing import ArrowTable else: from pyarrow import Table as ArrowTable # noqa: TC004 + if not LITESTAR_INSTALLED: + from sqlspec._typing import DTOData + else: + from litestar.dto import DTOData # noqa: TC004 diff --git a/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py b/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py index 8e85381..635f936 100644 --- a/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py +++ b/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py @@ -67,7 +67,6 @@ def test_driver_insert_returning(adbc_session: AdbcConfig, params: Any, style: P @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_select(adbc_session: AdbcConfig) -> None: """Test select functionality with simple tuple parameters.""" params = ("test_name",) @@ -95,7 +94,6 @@ def test_driver_select(adbc_session: AdbcConfig) -> None: @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_select_value(adbc_session: AdbcConfig) -> None: """Test select_value functionality with simple tuple parameters.""" params = ("test_name",) @@ -122,7 +120,6 @@ def test_driver_select_value(adbc_session: AdbcConfig) -> None: @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_insert(adbc_session: AdbcConfig) -> None: """Test insert functionality.""" with adbc_session.provide_session() as driver: @@ -147,7 +144,6 @@ def test_driver_insert(adbc_session: AdbcConfig) -> None: @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_select_normal(adbc_session: AdbcConfig) -> None: """Test select functionality.""" with adbc_session.provide_session() as driver: @@ -185,7 +181,6 @@ def test_driver_select_normal(adbc_session: AdbcConfig) -> None: ], ) @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_param_styles(adbc_session: AdbcConfig, param_style: str) -> None: """Test different parameter styles.""" with adbc_session.provide_session() as driver: @@ -215,7 +210,6 @@ def test_param_styles(adbc_session: AdbcConfig, param_style: str) -> None: @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_select_arrow(adbc_session: AdbcConfig) -> None: """Test select_arrow functionality.""" with adbc_session.provide_session() as driver: @@ -253,7 +247,6 @@ def test_driver_select_arrow(adbc_session: AdbcConfig) -> None: @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_named_params_with_scalar(adbc_session: AdbcConfig) -> None: """Test that scalar parameters work with named parameters in SQL.""" with adbc_session.provide_session() as driver: @@ -281,7 +274,6 @@ def test_driver_named_params_with_scalar(adbc_session: AdbcConfig) -> None: @xfail_if_driver_missing -@pytest.mark.xdist_group("sqlite") def test_driver_named_params_with_tuple(adbc_session: AdbcConfig) -> None: """Test that tuple parameters work with named parameters in SQL.""" with adbc_session.provide_session() as driver: diff --git a/tests/integration/test_adapters/test_asyncpg/test_driver.py b/tests/integration/test_adapters/test_asyncpg/test_driver.py index 4e62ced..213615a 100644 --- a/tests/integration/test_adapters/test_asyncpg/test_driver.py +++ b/tests/integration/test_adapters/test_asyncpg/test_driver.py @@ -273,3 +273,123 @@ async def test_param_styles(asyncpg_config: AsyncpgConfig, param_style: str) -> assert results[0]["name"] == "test" finally: await driver.execute_script("DROP TABLE IF EXISTS test_table") + + +@pytest.mark.xdist_group("postgres") +@pytest.mark.asyncio +async def test_question_mark_in_edge_cases(asyncpg_config: AsyncpgConfig) -> None: + """Test that question marks in comments, strings, and other contexts aren't mistaken for parameters.""" + async with asyncpg_config.provide_session() as driver: + await driver.execute_script("DROP TABLE IF EXISTS test_table") # Ensure clean state + # Create test table + sql = """ + CREATE TABLE test_table ( + id SERIAL PRIMARY KEY, + name VARCHAR(50) + ) + """ + await driver.execute_script(sql) + + # Insert a record + await driver.insert_update_delete("INSERT INTO test_table (name) VALUES (?)", "edge_case_test") + + try: + # Test question mark in a string literal - should not be treated as a parameter + result = await driver.select_one("SELECT * FROM test_table WHERE name = ? AND '?' = '?'", "edge_case_test") + assert result["name"] == "edge_case_test" + + # Test question mark in a comment - should not be treated as a parameter + result = await driver.select_one( + "SELECT * FROM test_table WHERE name = ? -- Does this work with a ? in a comment?", "edge_case_test" + ) + assert result["name"] == "edge_case_test" + + # Test question mark in a block comment - should not be treated as a parameter + result = await driver.select_one( + "SELECT * FROM test_table WHERE name = ? /* Does this work with a ? in a block comment? */", + "edge_case_test", + ) + assert result["name"] == "edge_case_test" + + # Test with mixed parameter styles and multiple question marks + result = await driver.select_one( + "SELECT * FROM test_table WHERE name = ? AND '?' = '?' -- Another ? here", "edge_case_test" + ) + assert result["name"] == "edge_case_test" + + # Test a complex query with multiple question marks in different contexts + result = await driver.select_one( + """ + SELECT * FROM test_table + WHERE name = ? -- A ? in a comment + AND '?' = '?' -- Another ? here + AND 'String with a ? in it' = 'String with a ? in it' + AND /* Block comment with a ? */ id > 0 + """, + "edge_case_test", + ) + assert result["name"] == "edge_case_test" + finally: + await driver.execute_script("DROP TABLE IF EXISTS test_table") + + +@pytest.mark.xdist_group("postgres") +@pytest.mark.asyncio +async def test_regex_parameter_binding_complex_case(asyncpg_config: AsyncpgConfig) -> None: + """Test handling of complex SQL with question mark parameters in various positions.""" + async with asyncpg_config.provide_session() as driver: + await driver.execute_script("DROP TABLE IF EXISTS test_table") # Ensure clean state + # Create test table + sql = """ + CREATE TABLE test_table ( + id SERIAL PRIMARY KEY, + name VARCHAR(50) + ) + """ + await driver.execute_script(sql) + + try: + # Insert test records + await driver.insert_update_delete( + "INSERT INTO test_table (name) VALUES (?), (?), (?)", ("complex1", "complex2", "complex3") + ) + + # Complex query with parameters at various positions + results = await driver.select( + """ + SELECT t1.* + FROM test_table t1 + JOIN test_table t2 ON t2.id <> t1.id + WHERE + t1.name = ? OR + t1.name = ? OR + t1.name = ? + -- Let's add a comment with ? here + /* And a block comment with ? here */ + ORDER BY t1.id + """, + ("complex1", "complex2", "complex3"), + ) + + # With a self-join where id <> id, each of the 3 rows joins with the other 2, + # resulting in 6 total rows (3 names X 2 matches each) + assert len(results) == 6 + + # Verify that all three names are present in results + names = {row["name"] for row in results} + assert names == {"complex1", "complex2", "complex3"} + + # Verify that question marks escaped in strings don't count as parameters + # This passes 2 parameters and has one ? in a string literal + result = await driver.select_one( + """ + SELECT * FROM test_table + WHERE name = ? AND id IN ( + SELECT id FROM test_table WHERE name = ? AND '?' = '?' + ) + """, + ("complex1", "complex1"), + ) + assert result["name"] == "complex1" + finally: + await driver.execute_script("DROP TABLE IF EXISTS test_table") diff --git a/tests/integration/test_adapters/test_psqlpy/test_driver.py b/tests/integration/test_adapters/test_psqlpy/test_driver.py index 254f143..8941d29 100644 --- a/tests/integration/test_adapters/test_psqlpy/test_driver.py +++ b/tests/integration/test_adapters/test_psqlpy/test_driver.py @@ -79,7 +79,6 @@ async def test_insert_returning_param_styles(psqlpy_config: PsqlpyConfig, params pytest.param({"name": "test_name"}, "dict_binds", id="dict_binds"), ], ) -@pytest.mark.asyncio async def test_select_param_styles(psqlpy_config: PsqlpyConfig, params: Any, style: ParamStyle) -> None: """Test select with different parameter styles.""" # Insert test data first (using tuple style for simplicity here) @@ -101,7 +100,6 @@ async def test_select_param_styles(psqlpy_config: PsqlpyConfig, params: Any, sty # --- Test Core Driver Methods --- # -@pytest.mark.asyncio async def test_insert_update_delete(psqlpy_config: PsqlpyConfig) -> None: """Test basic insert, update, delete operations.""" async with psqlpy_config.provide_session() as driver: @@ -137,7 +135,6 @@ async def test_insert_update_delete(psqlpy_config: PsqlpyConfig) -> None: assert result_or_none is None -@pytest.mark.asyncio async def test_select_methods(psqlpy_config: PsqlpyConfig) -> None: """Test various select methods (select, select_one, select_one_or_none, select_value).""" async with psqlpy_config.provide_session() as driver: @@ -180,7 +177,6 @@ async def test_select_methods(psqlpy_config: PsqlpyConfig) -> None: assert value_or_none_missing is None -@pytest.mark.asyncio async def test_execute_script(psqlpy_config: PsqlpyConfig) -> None: """Test execute_script method for non-query operations.""" sql = "SELECT 1;" # Simple script @@ -189,3 +185,131 @@ async def test_execute_script(psqlpy_config: PsqlpyConfig) -> None: # psqlpy execute returns a status string, exact content might vary assert isinstance(status, str) # We don't assert exact status content as it might change, just that it runs + + +async def test_multiple_positional_parameters(psqlpy_config: PsqlpyConfig) -> None: + """Test handling multiple positional parameters in a single SQL statement.""" + async with psqlpy_config.provide_session() as driver: + # Insert multiple records + await driver.insert_update_delete("INSERT INTO test_table (name) VALUES (?), (?)", ("param1", "param2")) + + # Query with multiple parameters + results = await driver.select("SELECT * FROM test_table WHERE name = ? OR name = ?", ("param1", "param2")) + assert len(results) == 2 + + # Test with IN clause + results = await driver.select("SELECT * FROM test_table WHERE name IN (?, ?)", ("param1", "param2")) + assert len(results) == 2 + + # Test with a mixture of parameter styles + results = await driver.select("SELECT * FROM test_table WHERE name = ? AND id > ?", ("param1", 0)) + assert len(results) == 1 + + +async def test_scalar_parameter_handling(psqlpy_config: PsqlpyConfig) -> None: + """Test handling of scalar parameters in various contexts.""" + async with psqlpy_config.provide_session() as driver: + # Insert a record + await driver.insert_update_delete("INSERT INTO test_table (name) VALUES (?)", "single_param") + + # Verify the record exists with scalar parameter + result1 = await driver.select_one("SELECT * FROM test_table WHERE name = ?", "single_param") + assert result1["name"] == "single_param" + + # Test select_value with scalar parameter + value = await driver.select_value("SELECT id FROM test_table WHERE name = ?", "single_param") + assert isinstance(value, int) + + # Test select_one_or_none with scalar parameter that doesn't exist + result2 = await driver.select_one_or_none("SELECT * FROM test_table WHERE name = ?", "non_existent_param") # + assert result2 is None + + +async def test_question_mark_in_edge_cases(psqlpy_config: PsqlpyConfig) -> None: + """Test that question marks in comments, strings, and other contexts aren't mistaken for parameters.""" + async with psqlpy_config.provide_session() as driver: + # Insert a record + await driver.insert_update_delete("INSERT INTO test_table (name) VALUES (?)", "edge_case_test") + + # Test question mark in a string literal - should not be treated as a parameter + result = await driver.select_one("SELECT * FROM test_table WHERE name = ? AND '?' = '?'", "edge_case_test") + assert result["name"] == "edge_case_test" + + # Test question mark in a comment - should not be treated as a parameter + result = await driver.select_one( + "SELECT * FROM test_table WHERE name = ? -- Does this work with a ? in a comment?", "edge_case_test" + ) + assert result["name"] == "edge_case_test" + + # Test question mark in a block comment - should not be treated as a parameter + result = await driver.select_one( + "SELECT * FROM test_table WHERE name = ? /* Does this work with a ? in a block comment? */", + "edge_case_test", + ) + assert result["name"] == "edge_case_test" + + # Test with mixed parameter styles and multiple question marks + result = await driver.select_one( + "SELECT * FROM test_table WHERE name = ? AND '?' = '?' -- Another ? here", "edge_case_test" + ) + assert result["name"] == "edge_case_test" + + # Test a complex query with multiple question marks in different contexts + result = await driver.select_one( + """ + SELECT * FROM test_table + WHERE name = ? -- A ? in a comment + AND '?' = '?' -- Another ? here + AND 'String with a ? in it' = 'String with a ? in it' + AND /* Block comment with a ? */ id > 0 + """, + "edge_case_test", + ) + assert result["name"] == "edge_case_test" + + +async def test_regex_parameter_binding_complex_case(psqlpy_config: PsqlpyConfig) -> None: + """Test handling of complex SQL with question mark parameters in various positions.""" + async with psqlpy_config.provide_session() as driver: + # Insert test records + await driver.insert_update_delete( + "INSERT INTO test_table (name) VALUES (?), (?), (?)", ("complex1", "complex2", "complex3") + ) + + # Complex query with parameters at various positions + results = await driver.select( + """ + SELECT t1.* + FROM test_table t1 + JOIN test_table t2 ON t2.id <> t1.id + WHERE + t1.name = ? OR + t1.name = ? OR + t1.name = ? + -- Let's add a comment with ? here + /* And a block comment with ? here */ + ORDER BY t1.id + """, + ("complex1", "complex2", "complex3"), + ) + + # With a self-join where id <> id, each of the 3 rows joins with the other 2, + # resulting in 6 total rows (3 names * 2 matches each) + assert len(results) == 6 + + # Verify that all three names are present in results + names = {row["name"] for row in results} + assert names == {"complex1", "complex2", "complex3"} + + # Verify that question marks escaped in strings don't count as parameters + # This passes 2 parameters and has one ? in a string literal + result = await driver.select_one( + """ + SELECT * FROM test_table + WHERE name = ? AND id IN ( + SELECT id FROM test_table WHERE name = ? AND '?' = '?' + ) + """, + ("complex1", "complex1"), + ) + assert result["name"] == "complex1" diff --git a/tests/unit/test_statement.py b/tests/unit/test_statement.py index 798708a..482fd73 100644 --- a/tests/unit/test_statement.py +++ b/tests/unit/test_statement.py @@ -12,7 +12,7 @@ ("Format type", "SELECT name FROM users WHERE status = %s", [("var_format_type", "s")]), ] -COMMENTS_AND_STRINGS_CASES = [ +COMMENTS_AND_STRINGS_CASES: list[tuple[str, str, list[tuple[str, str]]]] = [ ("Inside single quotes", "SELECT * FROM users WHERE notes = 'param: :value, other: ?'", []), ("Inside double quotes", 'SELECT * FROM users WHERE description = "param: :value, other: ?"', []), ("Single quotes with escaped quote", "SELECT 'It''s value: :not_param' FROM test", []), diff --git a/uv.lock b/uv.lock index b5f0c20..39bf641 100644 --- a/uv.lock +++ b/uv.lock @@ -10,106 +10,106 @@ resolution-markers = [ [[package]] name = "adbc-driver-bigquery" -version = "1.5.0" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/35/cf/05c630f2c076db860a1c70a1c2edaa6345a2d86090c498f5ad89f99ce727/adbc_driver_bigquery-1.5.0.tar.gz", hash = "sha256:d396d5454739b61e0b988584c25d9c06f7a8ec01a6fa2be46c7086da7016231f", size = 19231, upload-time = "2025-03-07T00:55:00.94Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/e7/9b945131d65370b56d913d30370d3840da0fdbc2ca7b09c53f9af17193d7/adbc_driver_bigquery-1.6.0.tar.gz", hash = "sha256:4b3357ae3f6ad3a4b786bf62d50bce497a791e6060511abf4b15ba8abfaf8876", size = 19238, upload-time = "2025-05-06T00:43:11.618Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/33/1df7ad5f430d07a93f0126028ad0d151a33c80caccbf070e773128771de9/adbc_driver_bigquery-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:db0e666447c46e0d74948ef6a11ef2eff0457e8359d7b3c2be75452f92251cb5", size = 8683381, upload-time = "2025-03-07T00:53:36.707Z" }, - { url = "https://files.pythonhosted.org/packages/6f/47/5f857fba33cd70949d06757915387a021326955b73fe927d93115e277704/adbc_driver_bigquery-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:446aa7affc30825fd01b8f197f3512f18f04d7480c61188e5f118478f71a2e6e", size = 8211988, upload-time = "2025-03-07T00:53:38.761Z" }, - { url = "https://files.pythonhosted.org/packages/97/18/a1044bb04d0dac6599cf7b6669c394fbf136485a518230fd7a84389eb9e0/adbc_driver_bigquery-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d21365c0f4816e0f28605f05f88c365df82ab2d13cd7d3bd8d17449baf97770", size = 8079367, upload-time = "2025-03-07T00:53:40.49Z" }, - { url = "https://files.pythonhosted.org/packages/71/57/65e52fd0d460a85188f5afa96346aba8a6eab2c1a7a330c98efaf176f90c/adbc_driver_bigquery-1.5.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fff37309963e710ffbb65ddf038cd34eef9486c1e155fd2e1afc9f72b418b72", size = 8778798, upload-time = "2025-03-07T00:53:42.568Z" }, - { url = "https://files.pythonhosted.org/packages/a7/c6/e0f231ef145f30475f7b759ce2c74ed19db0a681295ea69fe55d572ee433/adbc_driver_bigquery-1.5.0-py3-none-win_amd64.whl", hash = "sha256:23652f2275eed25de1d55d4990bff36744544ec3034bb656489425cb197b8d6d", size = 16213586, upload-time = "2025-03-07T00:53:45.362Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e5/ed867239ffc7e879e376ddca26b347606d3b9b6a19fe5ab27f5873e5ff62/adbc_driver_bigquery-1.6.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:4367b7f0d48ae12d51207f68fc395f0bb428143e6879348289ce865044618d15", size = 9026815, upload-time = "2025-05-06T00:41:43.505Z" }, + { url = "https://files.pythonhosted.org/packages/c2/66/729a653064d727fefca93e4f571d74dddc22f7da27945adff7a6ebe3b25f/adbc_driver_bigquery-1.6.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a5851c9a4af8fed1aff419aaa8cd486376a4da2c16d35c054ff0677278079d48", size = 8508744, upload-time = "2025-05-06T00:41:46.013Z" }, + { url = "https://files.pythonhosted.org/packages/ed/5c/debd7f6d77ffc4a5db33027bd8c6288e41ed8cd7b53953ab2f0ad9d6d968/adbc_driver_bigquery-1.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46a114a9a5ea7dea983ec956824cc82a06940f8c1edc271ce5160ba405367b3e", size = 8369358, upload-time = "2025-05-06T00:41:48.335Z" }, + { url = "https://files.pythonhosted.org/packages/e7/24/a62e00e0d2348d6bbe644f873035ac678b528c131d4c0aa55e00abc0a6cc/adbc_driver_bigquery-1.6.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8a5b78155a35940bb98b7727d946c25acc8c221b3a343cb38b6c14398a16908", size = 9123463, upload-time = "2025-05-06T00:41:50.608Z" }, + { url = "https://files.pythonhosted.org/packages/74/f4/3a0cf6a68a11734648918035072a8a9036ba3339dd51f2cb25d401b7d35b/adbc_driver_bigquery-1.6.0-py3-none-win_amd64.whl", hash = "sha256:63bad2e95e5efd4aad40e98e10944df68f9d8b3ed09eaea1e846b624a2840039", size = 16963032, upload-time = "2025-05-06T00:41:55.338Z" }, ] [[package]] name = "adbc-driver-flightsql" -version = "1.5.0" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/b4/e7a308591f5a0982d77021e00094e8bd3c325c01310338b04cc9f73d59b5/adbc_driver_flightsql-1.5.0.tar.gz", hash = "sha256:5beef9ec4916bce3baa03d376926f62244562fb5b8e9dd424934869bfb4558c5", size = 19924, upload-time = "2025-03-07T00:55:01.751Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/e5/86a08c8a35479b7eca0ab7ee118355de7e86e6f2afefb827e41cc60fdc67/adbc_driver_flightsql-1.6.0.tar.gz", hash = "sha256:060fe6a566d485d933e8f3d597178486bcdc3379a411e0d94a3924f1a6f50707", size = 19933, upload-time = "2025-05-06T00:43:12.853Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/50/657710004d770c0d6c5aa51ba5bfc72f62a75bb64b57d857141ca4c9ad27/adbc_driver_flightsql-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:63df9621ee3fcfdf0d5c5c0d4aa8d8a3834e1b8ced50ccc6d27d25b01beaec57", size = 6560976, upload-time = "2025-03-07T00:53:47.434Z" }, - { url = "https://files.pythonhosted.org/packages/43/4e/509f18621ddccc22cbc4f58c05e5261b5eeea40bc6a65238fabfcc216485/adbc_driver_flightsql-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93b61b865b7824d1a3f637a8780ac6928f37b4a4987956ec205a0e28ba4ecf03", size = 6178498, upload-time = "2025-03-07T00:53:49.768Z" }, - { url = "https://files.pythonhosted.org/packages/bd/4d/480db656caad5b7225227c18ffabb76b9ed2b843d50477fb243c2e85293c/adbc_driver_flightsql-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b71399d108a1d0a621f412c86e433a4f7f7a66e8d82df434eaa419f65a2db0ff", size = 6055235, upload-time = "2025-03-07T00:53:51.272Z" }, - { url = "https://files.pythonhosted.org/packages/5a/7c/53b2eda95f126a0dd42fa899f9a549360a79c75a2f272eb1eac4c3acc740/adbc_driver_flightsql-1.5.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29d9cd05f73d97cf9d9f716dbc521f1057d5d30908e448769290ce6d331b7b2e", size = 6599901, upload-time = "2025-03-07T00:53:53.332Z" }, - { url = "https://files.pythonhosted.org/packages/5a/27/f48f748d3378866b8c33d4068102497650279a2b80bb8564e154d9fa2382/adbc_driver_flightsql-1.5.0-py3-none-win_amd64.whl", hash = "sha256:bf366ba3541c4c32d15cb899de73c57e0712569ac9ab3c765cdbdf1a5bbd8d96", size = 12257810, upload-time = "2025-03-07T00:53:55.429Z" }, + { url = "https://files.pythonhosted.org/packages/61/77/3dd8535743bb9206e898da49adc8b2faa195697bfde9a8e46a17651bd2b3/adbc_driver_flightsql-1.6.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:24872b650dd403776a6a5538706f7f2d0259f9804a618b14a8d3bde830a82030", size = 7080746, upload-time = "2025-05-06T00:41:57.816Z" }, + { url = "https://files.pythonhosted.org/packages/3f/26/08b96741c05ae130bd3667c5c6b90f64adf8c25be20ac6d7421bfe74adb8/adbc_driver_flightsql-1.6.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:153fdf7f266370f4e26caa158ae24b5f553fef236876605afc49d622d2b1e451", size = 6648742, upload-time = "2025-05-06T00:42:00.18Z" }, + { url = "https://files.pythonhosted.org/packages/20/ef/b39413ea761fe2b853aa2e4f1958bb86ccdfaf9e8b47711513338da395f0/adbc_driver_flightsql-1.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6597a78d676705a3fde0074d4df90dc3a5e27d7933445bad120c4fc3ccd70a8c", size = 6504306, upload-time = "2025-05-06T00:42:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/75/ae/8537dc1d5b9329df7e8cc59446ed6035890b4fa0358316d73fe162fdd82a/adbc_driver_flightsql-1.6.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a25d581e5d4deccdfabf2ff296f0172b2641c087f8cb95cd306dc65639470863", size = 7116989, upload-time = "2025-05-06T00:42:03.887Z" }, + { url = "https://files.pythonhosted.org/packages/54/f1/88068128c0d99e8e86b755277e986afca4c26694599fe996a1d53683912f/adbc_driver_flightsql-1.6.0-py3-none-win_amd64.whl", hash = "sha256:fcc61b91716af113627b3be1e5b35ac82c2612bc330211ffa20f1c43e4406d5c", size = 13286767, upload-time = "2025-05-06T00:42:06.266Z" }, ] [[package]] name = "adbc-driver-manager" -version = "1.5.0" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6b/e9/34d91055e13c86ff8a636ed9fd90752e21075541267774bf6ebc3cce7eae/adbc_driver_manager-1.5.0.tar.gz", hash = "sha256:db3f7a0e3f7d9c4df2e117b411407f8b1e0f202d9c2516f42cdf2d44415ac0d4", size = 107714, upload-time = "2025-03-07T00:55:02.587Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/d4/dc1574f810a78c08c045a97cb108a15d5c1e47885c6711775b5edce650de/adbc_driver_manager-1.5.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:872e27c35e209c60a1b151630801847642afaadbd2e45bb2a6a66834c276c210", size = 380840, upload-time = "2025-03-07T00:53:57.154Z" }, - { url = "https://files.pythonhosted.org/packages/50/3f/904d6324bcee5e9e51fb0e80b5c52fc062b1f2092c778101761e2aabe0b9/adbc_driver_manager-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9260a90bb87ead7634e2ddad6aa2cc90acdf6978450609a05ed0bc15cdbc4113", size = 368033, upload-time = "2025-03-07T00:53:58.797Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6e/a32e2982afd30edd2eb57b50e803a2daeaa9bef3c889fc867d155f6711e1/adbc_driver_manager-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65b5abe35349ceb3cdd9d30f24e5d757511aa50f28d1944d46e2d3064e88da25", size = 2038386, upload-time = "2025-03-07T00:54:00.27Z" }, - { url = "https://files.pythonhosted.org/packages/55/0f/6fb1bbfb399ed6b9515f608ba1de5069d5a87d4732869c8922863338f854/adbc_driver_manager-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:917b724181112ad0e7bfbd46f951dae2fb0163884e3fc7c0149fdf571fb5f1ac", size = 2060224, upload-time = "2025-03-07T00:54:01.689Z" }, - { url = "https://files.pythonhosted.org/packages/f3/50/e3c7c64836860dc8ce0b1b48c415e054a3c81ee584261ff2b6f418c7402a/adbc_driver_manager-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:339280a4314abaf1e5830a57cad1527425b7394e3ac92b3c81a01805f248ae9b", size = 535309, upload-time = "2025-03-07T00:54:02.868Z" }, - { url = "https://files.pythonhosted.org/packages/68/d0/ad57a4a03817719e9ee5f57878229b6e78b6d841d2a983ab5f7d42b5d2bc/adbc_driver_manager-1.5.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:9e8ae0620a136d1fcee9b10070318bf2bda8692184eecc83c8583fbf58c438c6", size = 381818, upload-time = "2025-03-07T00:54:04.421Z" }, - { url = "https://files.pythonhosted.org/packages/a2/6a/04286cd20fe5738d08e6b08524787d12a2c031420234903580cf6191807b/adbc_driver_manager-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f547e60a242daf4b9f7b7a9100573e33d86a6128f2248c7f4e958fec70d2413", size = 368715, upload-time = "2025-03-07T00:54:05.95Z" }, - { url = "https://files.pythonhosted.org/packages/b5/98/0846e39180107821a865079db94b34e65d9771fc6865ba82ba0763e4f96d/adbc_driver_manager-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17f3b3538e751d23a18b8e4aaffdcca4e2de0bff69954b920cebc173d176d5d4", size = 2150181, upload-time = "2025-03-07T00:54:09.034Z" }, - { url = "https://files.pythonhosted.org/packages/83/c3/91089e985f3436a6cbd52fc9f015af1a8028ca0e508472646c1f4c7daaa6/adbc_driver_manager-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c47a270711db680816378f93083a3a2153d1e3e5a82949ed4e15550a1cf46e2", size = 2164979, upload-time = "2025-03-07T00:54:10.46Z" }, - { url = "https://files.pythonhosted.org/packages/9f/fe/90909d17b04172aab20ef2da54fc32014219a62e184e10935df5e5a78087/adbc_driver_manager-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:4cef37ddd48c4a3460c53701706132d255511f21dd8f7524566c2654ca16c906", size = 536664, upload-time = "2025-03-07T00:54:11.688Z" }, - { url = "https://files.pythonhosted.org/packages/8b/02/093ef07a88ad304b07fcfbc8bd452ade6936d03fbe3bd1f1e6636b6340df/adbc_driver_manager-1.5.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:133cd63196d16b42e5b2ba5fe7b6e014848a656f5470819a9a0c75febfa47c0a", size = 381421, upload-time = "2025-03-07T00:54:12.851Z" }, - { url = "https://files.pythonhosted.org/packages/78/ea/24ffd0e67af5e8b41be6016dbc6ce5493e0c5adcafa310113637617cbf4b/adbc_driver_manager-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bc2b183f82ab46cae347c36ca4ab52c042f7b610c7f5db2f515e22c831c185e", size = 365697, upload-time = "2025-03-07T00:54:14.095Z" }, - { url = "https://files.pythonhosted.org/packages/bb/ef/6bc3014ad469deadb58a2460732d045aa1d3e55cbe03be03b89f382da90c/adbc_driver_manager-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab827d358756ca313db4351807b9f27afd938bcdbee87861f880a40e449b3216", size = 2129071, upload-time = "2025-03-07T00:54:15.189Z" }, - { url = "https://files.pythonhosted.org/packages/21/54/d6401e064894685a4fd07ca4b2ba094c4190b35384beedf4ece020f33a34/adbc_driver_manager-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0170739f3b1995ccd1cfa4e108e142c50d3b47a019c9aa1a251f43d497bc93d1", size = 2161129, upload-time = "2025-03-07T00:54:16.537Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f6/ca520d1a76c8d273b17a9068de14d7fc52d69e03cc3c2aeb807c00d07d9f/adbc_driver_manager-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d1ef71398bc8622ca49224a20f68bd4948e546efdfdfb043b0760dfbd30b6e2", size = 533566, upload-time = "2025-03-07T00:54:17.729Z" }, - { url = "https://files.pythonhosted.org/packages/51/4a/8c1303f0c6a42059390b8204cf6b9a26710b22db598ef8bee919f5f7097f/adbc_driver_manager-1.5.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:7c097a0dce36f651496e21a3e576857733a47f749de999d1a53901580d530484", size = 379609, upload-time = "2025-03-07T00:54:19.174Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b9/227cf6905af9fc406a2632fa96c4435a3d9cc3c40ecc09a513fcbf353fe7/adbc_driver_manager-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1efa9d8586020f785d22c3319eb14363df4e0de7a2666449af3f8c47876ecf2f", size = 363410, upload-time = "2025-03-07T00:54:20.653Z" }, - { url = "https://files.pythonhosted.org/packages/d2/6a/0247a28a1ca64e531d7eff0e229368439b5b86dd29fd6079449eb0380d66/adbc_driver_manager-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7623dd5505f6f7ac4d8948a5ef816aca34ba388730b8690bbe2e7b1de8e7385c", size = 2123347, upload-time = "2025-03-07T00:54:21.832Z" }, - { url = "https://files.pythonhosted.org/packages/52/66/36a57bda7858b3dfc303df2f0f5be840c778f0c3ea083680e6ae9c7795ff/adbc_driver_manager-1.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:826a4749806d68bc0ae2a490533093f7fb18c12ae353cc136e8f40974e11246d", size = 2156234, upload-time = "2025-03-07T00:54:23.318Z" }, - { url = "https://files.pythonhosted.org/packages/b6/ac/1fb234f5b5c47088bf8db114b0e64b10f99d287e41e80ebe703482f4b6fc/adbc_driver_manager-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:ce4e0b9805df82213f8130af97320a5544f7a873982104cb81a9474adaf42caf", size = 531676, upload-time = "2025-03-07T00:54:25.168Z" }, - { url = "https://files.pythonhosted.org/packages/76/84/bb12cc84c7e337e96acde5644cdd250eb9f97c39228aa32d45d02e8e33db/adbc_driver_manager-1.5.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:82c9aad221319d490ddf79ce841206d52fb102a2919a41a4dba5ff759bdf0e6e", size = 382176, upload-time = "2025-03-07T00:54:26.341Z" }, - { url = "https://files.pythonhosted.org/packages/68/63/d678bc2c3d96bfb4d120fcad6d3be4c0b05922095a0b1129a9e6835c46f7/adbc_driver_manager-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f6296f6a63fa23aecdc14ebbae8cf8491cd52c6299510b6ce0388d66bd4b3aad", size = 369132, upload-time = "2025-03-07T00:54:27.441Z" }, - { url = "https://files.pythonhosted.org/packages/1a/ee/2cd4a5254072d9cb6d25bf74615d5cf0c93e2cf22d2b96abf5bee5574c2b/adbc_driver_manager-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f81e38e28282edc532c69608c4c4e8de4bf3c5c17d8310863b42a4ed36535958", size = 2044587, upload-time = "2025-03-07T00:54:29.537Z" }, - { url = "https://files.pythonhosted.org/packages/d7/7d/e24e7fedb09bce131ca5918afc0b2e35806131a3155a3a41d76ceb3ecdc9/adbc_driver_manager-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dac3e7c3f4981839c6afd276bd4502252b29b87571cb8da86a902c959387dae", size = 2059148, upload-time = "2025-03-07T00:54:31.067Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e4/870a2e1ac08eeb3ae1656c92b64dac8478bd968a8c4f7bacfeff57355a78/adbc_driver_manager-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:81581c5301c65f18230f885dbf6ef8fd60c01787ab7ce7597b0f39f36b134ec4", size = 536826, upload-time = "2025-03-07T00:54:32.335Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/89/ed/e2b548e9ffe19a405ea4afb0679805b7da981bdc0366017cb6c826e1dae1/adbc_driver_manager-1.6.0.tar.gz", hash = "sha256:618659313a5c712f7938ab35e8f8bae1b80e9ed0c7a8582b2ec9174a88a442ba", size = 109319, upload-time = "2025-05-06T00:43:14.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/1a/e9e6d1814e7ffc9bfb75327ef1c15c66c74a2f41786cce7f685b9a1cc059/adbc_driver_manager-1.6.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:d4b84cb733494bbcc7246a795c8be84fdb36dad472ec95c0fbc5c24f5df493c0", size = 385775, upload-time = "2025-05-06T00:42:08.761Z" }, + { url = "https://files.pythonhosted.org/packages/6c/dc/5aacf26256b47406f5806163d90e0c7c5fd36da00396af93c719ccd1e7b0/adbc_driver_manager-1.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fcd5b89de4ff1c5ba313d789ac3905541bd8a897e42ca6684ca19a3f47ae53f3", size = 372816, upload-time = "2025-05-06T00:42:10.19Z" }, + { url = "https://files.pythonhosted.org/packages/64/50/8dbd1860699b6adf9f095fafe48375c7e7cbf4d6f2b1d069f8dacec1dd27/adbc_driver_manager-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f5c66c3824512faa63b70b1bc94d74aa1a573c3c49ab3c7b0226ba5655268e4", size = 2054041, upload-time = "2025-05-06T00:42:11.661Z" }, + { url = "https://files.pythonhosted.org/packages/1c/6a/c13691815c2619a2f5cdbd0cb310d35681e3cbb6dcbec7f39df143a84be7/adbc_driver_manager-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:359dafe2ccc0f0de3f10faa0e462cb2518b9ffb495f103f7ec2b437dcff600fc", size = 2076092, upload-time = "2025-05-06T00:42:12.896Z" }, + { url = "https://files.pythonhosted.org/packages/a7/a1/f8c2d1d1fbe4973833a9a6679bac060ece23303af3b3cfaf36bbfcddb93f/adbc_driver_manager-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6f05c0e53d556bd5ff9fa90cc4c37733bde8a7ed0ce7359cd2836ff3c3242a6", size = 538557, upload-time = "2025-05-06T00:42:14.48Z" }, + { url = "https://files.pythonhosted.org/packages/e7/99/0f1338830a6ff886b568a29f5eec874f599c8f7550b18876410fea753ca8/adbc_driver_manager-1.6.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:09f760c7ed2ec0cb2087800b16132ed433d628e6131bbf416eea2dca89294f09", size = 386991, upload-time = "2025-05-06T00:42:15.822Z" }, + { url = "https://files.pythonhosted.org/packages/70/85/da32d443e8b7bafbec0dd6d8d4560484a1ca318060154f2de0e6e60e14c2/adbc_driver_manager-1.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0386d29c8fae0bb78f2bf50939b37b22449fdd14ea6ea4e99c491fc85257c242", size = 373667, upload-time = "2025-05-06T00:42:16.884Z" }, + { url = "https://files.pythonhosted.org/packages/cd/2b/5416197f2043001196b773c101e15ab4432ff7abeb7a7fa326ea4042380d/adbc_driver_manager-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c37acc9b1e1430e4a0c5435eb2d5f4302443306835ad3dafd927aa134a98127", size = 2170777, upload-time = "2025-05-06T00:42:17.981Z" }, + { url = "https://files.pythonhosted.org/packages/7e/ec/16eefe1c58cec292ab47acd984de21ebe22bd74cc63e777aa61036efddba/adbc_driver_manager-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3ade5a5d1b94ab21a0e7f61f043aa4d04ace14e8dcf70c5abd1b5a623eaa18b", size = 2180866, upload-time = "2025-05-06T00:42:19.76Z" }, + { url = "https://files.pythonhosted.org/packages/ce/80/f1eb85e3f2bf6fa4efa1cd7f5c9728728bad02ef5009b6bc86baf9d5b495/adbc_driver_manager-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc99d4dabf4441be574cb8224ea367ec1e144894f9c6076b031db45c3244f72a", size = 539877, upload-time = "2025-05-06T00:42:21.354Z" }, + { url = "https://files.pythonhosted.org/packages/25/29/e2d6459d0f502b3042d16e8e30d79c3eb137eac64dd6db0a7b02ba662bfe/adbc_driver_manager-1.6.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:e572ed22d1615034e7e90499af74ed21d624cc54c1d5ec8aa3e0ec4ca4a654f7", size = 385342, upload-time = "2025-05-06T00:42:22.498Z" }, + { url = "https://files.pythonhosted.org/packages/40/b8/badb83c73cfa4dfff741ba2b338c5a25480c220afba9e592b153212bf47c/adbc_driver_manager-1.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1a251977656f574d3881b5964b0611c62f252214de255f6d88a494965f15eba2", size = 370867, upload-time = "2025-05-06T00:42:23.604Z" }, + { url = "https://files.pythonhosted.org/packages/7f/bb/eee9daffd175f30e301e5f9eb233564c0535b28c324b424bd24c13516059/adbc_driver_manager-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e6dd7b657029d9ef5d4fb5bc7b976be90b552c44442cd39e89eb410663db44", size = 2145818, upload-time = "2025-05-06T00:42:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/11/e4/ed90877f09d1c73ff47cc120bd82296dc9ec34299313f1ed661f79578d5f/adbc_driver_manager-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64306174f149c3ceeb081997aa46682424a000b00eb8c2e9e8df022ccdf6f1ec", size = 2173678, upload-time = "2025-05-06T00:42:27.105Z" }, + { url = "https://files.pythonhosted.org/packages/32/38/3038af0c48b166c58d8a038d23e3b6b49c386845400eed2334c6f2b0741a/adbc_driver_manager-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:31f1857413a2f9572aba8a0236af36cc3da46a1720ea8747c62948b626010b98", size = 537249, upload-time = "2025-05-06T00:42:28.324Z" }, + { url = "https://files.pythonhosted.org/packages/7b/0a/1bd66b56514f7412fb737cf9ec38a1e32576ab6b2ed5aab74e890fb10b50/adbc_driver_manager-1.6.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:f75a65f5fb4aeac33b8b08c054335ae5a7bc5de848d7b036398bff876119cc27", size = 383339, upload-time = "2025-05-06T00:42:29.487Z" }, + { url = "https://files.pythonhosted.org/packages/18/5a/c8ad32c5d0689aae1a9fbf4acfd5605664b3d077298dc27a6e216e601691/adbc_driver_manager-1.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0a9e2be3fca404e3b78b6fafb1e61d5a08565a7815debc53d049cc5fbe0c955d", size = 368543, upload-time = "2025-05-06T00:42:30.765Z" }, + { url = "https://files.pythonhosted.org/packages/33/bb/a9e1daa66b09b33852a4e592e951a29e6ee055d88e792b64eb5761a4f011/adbc_driver_manager-1.6.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83dfde4c8d2f130be23048800117a8f3166b797d1442d74135ce7611ab26e812", size = 2141507, upload-time = "2025-05-06T00:42:32.246Z" }, + { url = "https://files.pythonhosted.org/packages/d3/49/b5e260deff3d218a17fe23a1313bb3c033d846bf74505c297f74d2c8abfe/adbc_driver_manager-1.6.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41972465fa4db46bf151cc37000d0bd29c87c2eabbc81f502f0b6932c235f213", size = 2173133, upload-time = "2025-05-06T00:42:33.933Z" }, + { url = "https://files.pythonhosted.org/packages/bf/5f/a04791038cb659c8e1e7fb4a22d75a9fd3e3109a22822bd80beea0046dc4/adbc_driver_manager-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:0e8ffb182fafe1e6ae12964a833700daacc55f7abfdc2ada8b5214b18108d87b", size = 535018, upload-time = "2025-05-06T00:42:35.574Z" }, + { url = "https://files.pythonhosted.org/packages/da/b7/a19fb5920cc56893ca644d2a6b855386a18753205b2f2d5f604c3a323f79/adbc_driver_manager-1.6.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:ef82b3e7661420887c04f7cef04d76a465445b8d2c20bcd2d7da6aa1a23aa7ce", size = 387069, upload-time = "2025-05-06T00:42:36.766Z" }, + { url = "https://files.pythonhosted.org/packages/bb/b4/e9c6b18b899142f70086b3fbc92e99723e2b4070a72ae9475a37fa196c82/adbc_driver_manager-1.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc49efbdee89e98535b7692bebe79f9760b90482207812af84550878c0bf1059", size = 373833, upload-time = "2025-05-06T00:42:37.938Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f6/0fe0910b517d7ac2ee70d89d0858b147f1148b1495280dc514beeb1d128d/adbc_driver_manager-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0cd224e5a29af7c63a3a8d6502c0438a05820f4cda48be6d274fe39a1236bae", size = 2056528, upload-time = "2025-05-06T00:42:39.039Z" }, + { url = "https://files.pythonhosted.org/packages/b2/11/25dede4885fc2f4f605d4ce9c2353fd17c06a6c786bdc62cac4dc97ac39c/adbc_driver_manager-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab52976384586fa6ad991a9d1aff0a04871e72f300112ee80f240772498675a", size = 2075586, upload-time = "2025-05-06T00:42:40.342Z" }, + { url = "https://files.pythonhosted.org/packages/8a/7c/61de80a8f42ed511f05b6577c7082f1237fece73d55fbd7f1d9070b0d191/adbc_driver_manager-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb28324c0276df20477a527e291b37ed611a9fad5968ab252295002179ae9a6d", size = 540165, upload-time = "2025-05-06T00:42:41.604Z" }, ] [[package]] name = "adbc-driver-postgresql" -version = "1.5.0" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b5/61/7e6b9fc03fc294bcb9f18495a1f157bb6ee4f365a14d526dfc9977ecef72/adbc_driver_postgresql-1.5.0.tar.gz", hash = "sha256:3fc569ecd816838529e4778d5a5bd3678b6e35204d0b6428335e6bb3549312e8", size = 18400, upload-time = "2025-03-07T00:55:03.91Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/87/ee97f199ebf0367bb93bab50f7bb4a23f723956e5869871ec51c7530bc2c/adbc_driver_postgresql-1.6.0.tar.gz", hash = "sha256:531b34ee2eb7c17ad5b3a791f05742d5e7c24725671fc8348be2ff48c0bdaf29", size = 18882, upload-time = "2025-05-06T00:43:15.001Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/c4/8f239c5047640bf15971c34b74c56d190be20c2841c11a196ea63241d360/adbc_driver_postgresql-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:fb359d9a735090f8267b01f455c6ac4646e6595b4c9d4acea5764e77630c86c2", size = 2683354, upload-time = "2025-03-07T00:54:33.461Z" }, - { url = "https://files.pythonhosted.org/packages/a4/8a/6995f1746ea4db7456699e36c973ac9ddd87f7acbda939c0ca2b01189ded/adbc_driver_postgresql-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2f3e3a9b75c735eb79042e5f393f7b8aa699b3fe4c474b13871f85db7ad43eb3", size = 2997056, upload-time = "2025-03-07T00:54:34.956Z" }, - { url = "https://files.pythonhosted.org/packages/39/c9/add6659f0df14d001d2933dbbf94511ea507c6a94fd4ae09aed9ab1f1b78/adbc_driver_postgresql-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dfe69557d1af24d0d6c05085f91df825f02ac837f0861528ba5c7aa79e0cf0d", size = 3190202, upload-time = "2025-03-07T00:54:36.522Z" }, - { url = "https://files.pythonhosted.org/packages/22/dd/5335cee201c4f3e9cc3a101f306d1a09cf5956d44de8c80850bc958b7cd0/adbc_driver_postgresql-1.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b955dc6a53e3f01875659637d875b46bd04bf1ec361524c326c6963f5bc48a", size = 2846677, upload-time = "2025-03-07T00:54:37.849Z" }, - { url = "https://files.pythonhosted.org/packages/cd/9d/e34bafc8e99c93fd42227ec1bb15d80f5f661beefc30e98b4e3b54ce0792/adbc_driver_postgresql-1.5.0-py3-none-win_amd64.whl", hash = "sha256:251674ada39becb6ae86949c4d0987950d18c9b9ff6a941ff7a96f6eba2e4365", size = 2702604, upload-time = "2025-03-07T00:54:39.499Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/570d951dd918fdc7cbe57add0f68c9e76d71caf3f8d07d4f6b435735ba1e/adbc_driver_postgresql-1.6.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:a82803bcc7a73967bd08f2e70334b87706ef6dc7895606f7d5d7357df18789de", size = 2688571, upload-time = "2025-05-06T00:42:43.211Z" }, + { url = "https://files.pythonhosted.org/packages/7e/79/c3066a810938cf00a8566b4c89d6dcf6e0f7aaae230112eaf2dc71c643f3/adbc_driver_postgresql-1.6.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8d72dcf359b98c173e316e9e3761011bea7a67cb41a2d678b66c6834ccad809d", size = 3002077, upload-time = "2025-05-06T00:42:44.688Z" }, + { url = "https://files.pythonhosted.org/packages/16/c0/5967e0d47cf6e27474f630974b044c59e429103daf1a41031ec075013b02/adbc_driver_postgresql-1.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49a88d1d55c347c26e1de1199896b91f7bf581b6efd398e6c7241fa70a3fd20", size = 3192914, upload-time = "2025-05-06T00:42:46.511Z" }, + { url = "https://files.pythonhosted.org/packages/c1/45/2d3514fd2bf7ee7e1e28c45fdb70f2a27db2f8cc8af7e7c28f846dd7b99d/adbc_driver_postgresql-1.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3d09a688fb95bbe5431b488431145d77b3e20f8adbc413b1c2530b6623a9a2a", size = 2849841, upload-time = "2025-05-06T00:42:47.944Z" }, + { url = "https://files.pythonhosted.org/packages/51/26/b06d767a03fec4b0bd77aaaff6ea40de7c98d9e2b52aa646d125f0644298/adbc_driver_postgresql-1.6.0-py3-none-win_amd64.whl", hash = "sha256:23823cc70f8194c61e04b879c6ad6bae4871e1527b727b897cbc3039b6e4b892", size = 2858544, upload-time = "2025-05-06T00:42:49.804Z" }, ] [[package]] name = "adbc-driver-sqlite" -version = "1.5.0" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "adbc-driver-manager" }, { name = "importlib-resources" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/8f/41c7abe718e95dfbd443c5ca5de11b5c0b5be4f9e451dcb1367eca1f077e/adbc_driver_sqlite-1.5.0.tar.gz", hash = "sha256:bfb401e9bf3532977a4631d28bbff3114c056ef270acf9c038891af81e4d5295", size = 17011, upload-time = "2025-03-07T00:55:05.552Z" } +sdist = { url = "https://files.pythonhosted.org/packages/35/b1/c6e3c4e6740413c580b40085c21870a09ca9181bcfaa8a7aba98b93c2d7e/adbc_driver_sqlite-1.6.0.tar.gz", hash = "sha256:f3d6db788afde92b9cb1eecfc08fdcee301a7ee86c50e21357db0bb3e80b991b", size = 17038, upload-time = "2025-05-06T00:43:16.959Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/c4/29fd0540ff4fe0c685e03d032642d4d134c2d156a0b048037633fe80a0a8/adbc_driver_sqlite-1.5.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:4d58a5907903eb43fc6aa3d30da172b85670d1400af00a34e835071ecb8db320", size = 1040886, upload-time = "2025-03-07T00:54:54.515Z" }, - { url = "https://files.pythonhosted.org/packages/0f/8d/d8f7d5681309e18f6a7e964aa3c8d3012a84923b5a7e14175011f67cfb4c/adbc_driver_sqlite-1.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a09f4bbd8eeebc8793603ec8462defb0d85dcbacffbf036d94cd1357bcecaf68", size = 1011230, upload-time = "2025-03-07T00:54:55.931Z" }, - { url = "https://files.pythonhosted.org/packages/2d/90/3e4f4bbafaf67266e56a503bc4f706370ceb3ff0b3b1cb75dc7126f74d7f/adbc_driver_sqlite-1.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea30d29b402b259556045f61f9775fb75d86fbb74c8742ff7452545bc7fc1a6", size = 955040, upload-time = "2025-03-07T00:54:57.097Z" }, - { url = "https://files.pythonhosted.org/packages/83/e3/d26f2e9b02544b51d30f3d6217597a3c1ae0e93b47235bc1033f91ebd024/adbc_driver_sqlite-1.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d91359bdd27a198472374583bd7e0a76d9a1f3973fa6671168e43c80665bae2", size = 976400, upload-time = "2025-03-07T00:54:58.342Z" }, - { url = "https://files.pythonhosted.org/packages/bb/f1/4ca555bee7f80d8bd74bfeb61462e8c273931f588bf5fdc98ffffa025b6b/adbc_driver_sqlite-1.5.0-py3-none-win_amd64.whl", hash = "sha256:f6ef2e77e8221f243f86b490059c1c25ba1e5c875662287aba15a40f8297d323", size = 862790, upload-time = "2025-03-07T00:54:59.631Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a0/a635440c9521be7924ab1daf76d64b77c93042b1901026acb1c018ce789a/adbc_driver_sqlite-1.6.0-py3-none-macosx_10_15_x86_64.whl", hash = "sha256:b68dbe03c6a26ac1a3ec089ad6f067fe60a6eb4e26a0bffd230d8bf4a9f58f21", size = 1041104, upload-time = "2025-05-06T00:43:05.182Z" }, + { url = "https://files.pythonhosted.org/packages/72/25/52a079ddfde95d08c37bed59fcd5e2e1d0f180fc552885f925058ebc922f/adbc_driver_sqlite-1.6.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:55e163c08dbb7b068f692e359f3dadb9f3349a720d1b2cf39aec44925a1bed3a", size = 1011451, upload-time = "2025-05-06T00:43:06.521Z" }, + { url = "https://files.pythonhosted.org/packages/73/28/be596c01913a81fed3dda451764b216221ba074c2a690733eef7528c152a/adbc_driver_sqlite-1.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4bf7bd287d4dc76bc865d0c88ffd6c22a606965298febf714e6b9439a0ff5f3", size = 955262, upload-time = "2025-05-06T00:43:07.773Z" }, + { url = "https://files.pythonhosted.org/packages/92/ec/ce41f3c84b5b4f762e4de9072574714c623e959924bf1bbaf1548612cb6e/adbc_driver_sqlite-1.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:922a561c84c53f8fac42f1d636dfb915a265de3ebd39c35cf0d1cbe58d668616", size = 976623, upload-time = "2025-05-06T00:43:09.016Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6e/0231878df1e7b71607f6c71c08dd68ea168622496b000d9be79860c1e32d/adbc_driver_sqlite-1.6.0-py3-none-win_amd64.whl", hash = "sha256:1e28c378759915dd39eae02da98b189d33b9604c3c54e08caf256457f63727b2", size = 862809, upload-time = "2025-05-06T00:43:10.471Z" }, ] [[package]] @@ -415,7 +415,8 @@ name = "bump-my-version" version = "1.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "httpx" }, { name = "pydantic" }, { name = "pydantic-settings" }, @@ -622,14 +623,34 @@ wheels = [ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, ] +[[package]] +name = "click" +version = "8.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/0f/62ca20172d4f87d93cf89665fbaedcd560ac48b465bd1d92bfc7ea6b0a41/click-8.2.0.tar.gz", hash = "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d", size = 235857, upload-time = "2025-05-10T22:21:03.111Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/58/1f37bf81e3c689cc74ffa42102fa8915b59085f54a6e4a80bc6265c0f6bf/click-8.2.0-py3-none-any.whl", hash = "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c", size = 102156, upload-time = "2025-05-10T22:21:01.352Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -890,11 +911,14 @@ wheels = [ [[package]] name = "exceptiongroup" -version = "1.2.2" +version = "1.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883, upload-time = "2024-07-12T22:26:00.161Z" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453, upload-time = "2024-07-12T22:25:58.476Z" }, + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] [[package]] @@ -1029,7 +1053,8 @@ version = "3.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "blinker" }, - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "itsdangerous" }, { name = "jinja2" }, @@ -1064,16 +1089,16 @@ grpc = [ [[package]] name = "google-auth" -version = "2.39.0" +version = "2.40.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachetools" }, { name = "pyasn1-modules" }, { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cb/8e/8f45c9a32f73e786e954b8f9761c61422955d23c45d1e8c347f9b4b59e8e/google_auth-2.39.0.tar.gz", hash = "sha256:73222d43cdc35a3aeacbfdcaf73142a97839f10de930550d89ebfe1d0a00cde7", size = 274834, upload-time = "2025-04-14T17:44:49.402Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/a5/38c21d0e731bb716cffcf987bd9a3555cb95877ab4b616cfb96939933f20/google_auth-2.40.1.tar.gz", hash = "sha256:58f0e8416a9814c1d86c9b7f6acf6816b51aba167b2c76821965271bac275540", size = 280975, upload-time = "2025-05-07T01:04:55.3Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/12/ad37a1ef86006d0a0117fc06a4a00bd461c775356b534b425f00dde208ea/google_auth-2.39.0-py2.py3-none-any.whl", hash = "sha256:0150b6711e97fb9f52fe599f55648950cc4540015565d8fbb31be2ad6e1548a2", size = 212319, upload-time = "2025-04-14T17:44:47.699Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b1/1272c6e80847ba5349f5ccb7574596393d1e222543f5003cb810865c3575/google_auth-2.40.1-py2.py3-none-any.whl", hash = "sha256:ed4cae4f5c46b41bae1d19c036e06f6c371926e97b19e816fc854eff811974ee", size = 216101, upload-time = "2025-05-07T01:04:53.612Z" }, ] [[package]] @@ -1430,7 +1455,8 @@ version = "2.16.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "httpx" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, @@ -1854,6 +1880,7 @@ wheels = [ name = "mysql-connector-python" version = "9.3.0" source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/5e/55b265cb95938e271208e5692d7e615c53f2aeea894ab72a9f14ab198e9a/mysql-connector-python-9.3.0.tar.gz", hash = "sha256:8b16d51447e3603f18478fb5a19b333bfb73fb58f872eb055a105635f53d2345", size = 942579, upload-time = "2025-05-07T18:50:34.339Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/59/f8/b36f551601a4b942e2014f80a0bfa5f2f0da30ef2710182cc96d875a5852/mysql_connector_python-9.3.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:f979e712187796ad57cd0bef76666dd48ed4887104775833c9489ea837144ad8", size = 15148231, upload-time = "2025-04-15T11:21:33.974Z" }, { url = "https://files.pythonhosted.org/packages/41/ae/abd18c61277ec9e00c36de6a4f53f84003ae9fc34ca6077241a19e2c440f/mysql_connector_python-9.3.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:ee1a901c287471013570e29cdf5ca7159898af31cf3a582180eadd41c96b42c9", size = 15964353, upload-time = "2025-04-15T11:21:38.211Z" }, @@ -2070,11 +2097,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.3.7" +version = "4.3.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291, upload-time = "2025-03-19T20:36:10.989Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499, upload-time = "2025-03-19T20:36:09.038Z" }, + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, ] [[package]] @@ -2171,90 +2198,90 @@ wheels = [ [[package]] name = "psqlpy" -version = "0.9.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/39/bfa6bec547d9b197b72e547aee1440c300911895798fce00b0439ac8978b/psqlpy-0.9.3.tar.gz", hash = "sha256:f369528a4a1f5c8dea6efe0d469a07a735ab4d07e680faff4508699b183bcc37", size = 269627, upload-time = "2025-02-22T18:00:12.113Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/ca/85ed2d5a927b1c0336e1c5ffc22ec576a9e9edc35a09895d9aa01f165c9b/psqlpy-0.9.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c36efab33733d6fb9064a0c9fb59de4a529376837b080277e6825437bb1efa9", size = 4240144, upload-time = "2025-02-22T17:57:24.357Z" }, - { url = "https://files.pythonhosted.org/packages/93/72/45efb35a79ce717e282917610b3ff93fddd869d3e7702dfac8852c49b80f/psqlpy-0.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57d9b5054494daaa60a7337351c3f9fc36354bac5764dd868134f9e91cd11245", size = 4476802, upload-time = "2025-02-22T17:57:27.872Z" }, - { url = "https://files.pythonhosted.org/packages/83/2b/2b25af4cc385bede8e1ba29a0e17ec0e72e8c6318c1c551af536f5216c54/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a32b7f7b700180058ac7b5e7a02bac4c91de1ac94404e2a2a4eb67c91d2369a", size = 4936843, upload-time = "2025-02-22T17:57:30.235Z" }, - { url = "https://files.pythonhosted.org/packages/28/04/bff643f7bd711b41ccc15f7cadc041291350a3a5d989b07bc42b9515da20/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:40ce3f9b67c7cea8bff8ce7b2f435191f1f064168134c17ba457695278145cd1", size = 4207043, upload-time = "2025-02-22T17:57:31.668Z" }, - { url = "https://files.pythonhosted.org/packages/04/ba/0e5822e81a7205a4d9cd558f4b0b7d2fae3b2c5ad64b66e08c8ee6fb2404/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e6704cd34d1ed0f0873c448eb206565fdcd3eb0fc435428860aa529ce203bec", size = 4806688, upload-time = "2025-02-22T17:57:34.063Z" }, - { url = "https://files.pythonhosted.org/packages/c8/7a/e803e1c33ceb0c219c49db4767f1888294e08ddbf58e62bad81189e8f575/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3215cac58e8a6fb867a4cafaac3303d03ace5a623cb2ed7858ee797ab6b2bcd", size = 4651636, upload-time = "2025-02-22T17:57:37.354Z" }, - { url = "https://files.pythonhosted.org/packages/50/a5/b69d8da7aee1c6c5c40396d832e0d970a3c4fbbe3974296010d7397c207b/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a741e1694325c737f1917fa80ffcda27a3a533c03d033a059b39e5fb85eca6", size = 4775602, upload-time = "2025-02-22T17:57:39.796Z" }, - { url = "https://files.pythonhosted.org/packages/64/5f/27d3215bab4246d1978eecc74e649e4a12b7fbe895a24cc8ed1f0c6c5d09/psqlpy-0.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9013962aac0ca16d59e8b7a20856c0838fb09ddbf9a3e5bb2cde2add3c5a89", size = 4825250, upload-time = "2025-02-22T17:57:43.495Z" }, - { url = "https://files.pythonhosted.org/packages/31/9c/beb520f93f8f5fccb8d09bf9afb5b99b844e89e154de733eb3f54dbcdc82/psqlpy-0.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2bdf0afa1cae9e79553665a906315d7c6421ed587b012ec9c4397e91c200fd7b", size = 4857456, upload-time = "2025-02-22T17:57:45.861Z" }, - { url = "https://files.pythonhosted.org/packages/89/c4/5344648456b9184ef142baafd216396f2566e7025177070e26afbd52442c/psqlpy-0.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd2c3c3a5b0305d42430cc8af1d5c4130008b9a80cf5bb3fedfd414cd9b95181", size = 4977942, upload-time = "2025-02-22T17:57:47.462Z" }, - { url = "https://files.pythonhosted.org/packages/5a/52/b376c046d4f4da66d22aa6db62a33fca8ccecc41538beb6640cef0c081b3/psqlpy-0.9.3-cp310-cp310-win32.whl", hash = "sha256:79a0ec837dd314df5af74577f8b5b2fb752e74641a5cb66d58d779d88648d191", size = 3308783, upload-time = "2025-02-22T17:57:49.924Z" }, - { url = "https://files.pythonhosted.org/packages/08/24/f6552cdaf3e062966e6beac948c4f8daa28d32de9aae68011ebbeadd590b/psqlpy-0.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:ee0d53b33f7b841cd606a8dbbf8b36e809dddee526dc7e226a7d1b1fdb0e3e3b", size = 3721262, upload-time = "2025-02-22T17:57:52.295Z" }, - { url = "https://files.pythonhosted.org/packages/5e/1a/48bdacd23b7d2e2dd2c74bef7591e35a40795e9071faf672828f947bc9b5/psqlpy-0.9.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:66830960242bdec926ebb697284731f643176f4694419ecc4e48d064545c6e40", size = 4240197, upload-time = "2025-02-22T17:57:54.795Z" }, - { url = "https://files.pythonhosted.org/packages/4b/48/299439ba665aeafbd053150d77c451254a7ef797c143e9760cfbcfe240c2/psqlpy-0.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:45a12aead3ca4d2b18b114b541289bcb5894bd5746670ee9fe5d783f55a565d4", size = 4477221, upload-time = "2025-02-22T17:57:56.293Z" }, - { url = "https://files.pythonhosted.org/packages/09/cb/fbddd6c99f770a0fece65a3470d98dc0873a16a6c4e1adda246e5a5e6551/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fec5e579f519b98f5feb9e2148549c48391811e3153156deee7d2bc129f605", size = 4937618, upload-time = "2025-02-22T17:57:58.362Z" }, - { url = "https://files.pythonhosted.org/packages/6c/c0/4ace3aacbe3a7b9e87a282c3ca2313e25ef7970739e1f8392fa6da5781e7/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11a2b3574e9cf37f49dd5a8376823bb1c416222c133b59873ad2fdb91b0ba25f", size = 4206271, upload-time = "2025-02-22T17:58:00.753Z" }, - { url = "https://files.pythonhosted.org/packages/eb/1b/194462eddc3373af65c04ed2d6d710f57812937f5361fb8492659e43987f/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92afd8603006a18461d91167eff7ac100029b47034bbdd477f5e3805f9d23ff8", size = 4805586, upload-time = "2025-02-22T17:58:02.524Z" }, - { url = "https://files.pythonhosted.org/packages/b9/1f/fcdb60dda446b392f27243f9e5f633d4f8a95ab3e222c120d26b6b6ebf47/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71a912328513d6c89a8c3d1be615916ab360075c810ff0445e7c53030ff03186", size = 4653073, upload-time = "2025-02-22T17:58:05.133Z" }, - { url = "https://files.pythonhosted.org/packages/c9/a7/b82afd9f9950304468cecc9b027fc8248d846764f9f9a0251b3c77c9c0f4/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4861bb23574f2275bbd4f695bd4b2393fe6a5442f0a1bb603ebb6061f9926f9e", size = 4786884, upload-time = "2025-02-22T17:58:07.561Z" }, - { url = "https://files.pythonhosted.org/packages/29/49/11b42d762702be8624f6e1824a8743eb496951204389f1faaef1b31c60b7/psqlpy-0.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf151599e516d7b0bbe0f8e2c10d45b7a48a72be2716c9fe7a77ecf41b17e3b9", size = 4823808, upload-time = "2025-02-22T17:58:09.179Z" }, - { url = "https://files.pythonhosted.org/packages/f5/39/300dfdfa8780e7a1cf0dc5569a489a87f0061a264ce87ffd762351f53d7f/psqlpy-0.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b3fece2b78d568d74435b5ff0f05406bb3a43b1c571a66b7c1909efd52c31508", size = 4857527, upload-time = "2025-02-22T17:58:11.896Z" }, - { url = "https://files.pythonhosted.org/packages/c1/ec/178c575c45ad4884151d5f741e87ffe00712d491ad8c70413f2a4e95e173/psqlpy-0.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c49ea203ef3007b8dbd12a453dd6d45aa9ffd3e395181e837138d172e30c293", size = 4979751, upload-time = "2025-02-22T17:58:13.697Z" }, - { url = "https://files.pythonhosted.org/packages/8a/0c/e5ebe4c100ac134ef16ad95469cd38e9654ceca017561789680020149765/psqlpy-0.9.3-cp311-cp311-win32.whl", hash = "sha256:60833a0187dfdd859248bc424326d34b96b74c627e057a286632adbe4fb185a1", size = 3308639, upload-time = "2025-02-22T17:58:15.259Z" }, - { url = "https://files.pythonhosted.org/packages/90/e8/a0e1b19d7035e5b849ca57b1c201d0243268bd6a215781ebd197ccfdca81/psqlpy-0.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:185d508f9165ae51ed8e659ce8356986523ac14021233162e7b565a1b50e0486", size = 3721553, upload-time = "2025-02-22T17:58:16.927Z" }, - { url = "https://files.pythonhosted.org/packages/6b/73/f65c655c2c3d89f36a6eb160db86e8aecbe7a0258368d05111b08456a3d6/psqlpy-0.9.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6502545e46f9453a6103152e223f43461ca90e4d6d353b8567b40b45a01d43f8", size = 4226965, upload-time = "2025-02-22T17:58:18.397Z" }, - { url = "https://files.pythonhosted.org/packages/32/9b/e17f40ecf4c518d83ff4cd742869d769f2a26224531a6fe1dfee88bba210/psqlpy-0.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f447410df05b0b927a8cc995fa011477b291d57f1b8f8ca52ee4a3799b698c8b", size = 4440561, upload-time = "2025-02-22T17:58:20.166Z" }, - { url = "https://files.pythonhosted.org/packages/6c/62/6f9e6b409c6af33792386ba0e7a2beece6cf96fdffa8739144dfc1c897f4/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b825a3534d6a2810aed9c53873b8a58562bd28afc95506643ec4cc095bdda1a0", size = 4936741, upload-time = "2025-02-22T17:58:21.768Z" }, - { url = "https://files.pythonhosted.org/packages/ae/d3/9f5ed5a8703dd3b1349f4ff53b03eb4b2589cb0034186cdf8a562a97653c/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842a06192c4d6748aa63df3966b8685630ce1d2f1cdfbe54f95177c2db7436ad", size = 4219026, upload-time = "2025-02-22T17:58:23.999Z" }, - { url = "https://files.pythonhosted.org/packages/7b/ca/9788d4ad663f6841825f89013414ac28a483bb031417ccf6e5f087065139/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ece78105348c482bbcc1c7504c2067e8baf8ec64600aea40c293880995fb39c", size = 4805613, upload-time = "2025-02-22T17:58:25.732Z" }, - { url = "https://files.pythonhosted.org/packages/f8/a3/2702d69e47ef26a75c1f8fbf2cfe9e280da45945501998082644f98f1411/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c099c16aa3d224d3b0c6950eabbbf58154f04612522511c3d83a0e97cd689eed", size = 4645177, upload-time = "2025-02-22T17:58:27.448Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8a/c452f47cc9cabdcd694681ca2c8326ea3887cbf481678266e67de334d984/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb9746cdb5c8ddbbcf952bad67e07f4c46722de072cf6cfd69d8fb67d296156c", size = 4775536, upload-time = "2025-02-22T17:58:29.366Z" }, - { url = "https://files.pythonhosted.org/packages/c6/1d/fa6f86bf856019b0f48cdc92497afe632e1176d1d12773d5a77971de0096/psqlpy-0.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4beb0fc66c7924edcf6f842682554910d93376e31d527fa3d055ee24326bd84f", size = 4826617, upload-time = "2025-02-22T17:58:31.099Z" }, - { url = "https://files.pythonhosted.org/packages/6e/5c/8d85a5295ea236d85213aced33560ff93f8224dd7830d80e6bb37b5488d9/psqlpy-0.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:40e530d71441af61b791723bbf4a198b0da4e95f59d261e67074790564b629e5", size = 4826660, upload-time = "2025-02-22T17:58:32.861Z" }, - { url = "https://files.pythonhosted.org/packages/d3/dd/d6181320adb9271bb8559c1588cf6c956592dd19876bf09937f8b647e5c6/psqlpy-0.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a74926fa272acc2889f510317894307c2dda7702feb8195a159b564603d0c74c", size = 4946588, upload-time = "2025-02-22T17:58:34.363Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0c/9fa61aec2daf03e257fe314a2db0671828e1b397b028473b190fac921067/psqlpy-0.9.3-cp312-cp312-win32.whl", hash = "sha256:2b125d06a0c2718b5cf3b9c866ea9bf19764f51c2aa054919534e4767f43b1f8", size = 3293165, upload-time = "2025-02-22T17:58:36.726Z" }, - { url = "https://files.pythonhosted.org/packages/0a/7c/49717e45df23318bf1ebc6775ad4755e5b2ca7d920aaaeed514900a9fe65/psqlpy-0.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:613facca51bbf0682d863989e7368222e8040b3ce5f5b0ae3ce30d9df4e44d60", size = 3700904, upload-time = "2025-02-22T17:58:39.067Z" }, - { url = "https://files.pythonhosted.org/packages/4d/70/491f46e652492b22a8038082eae8821c3f74febba3d89eb72efbaa50e41c/psqlpy-0.9.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9c7b371f5bc3e4e60e7f0b34db5c8ec82c6aee3e967f6916251895fc0123015b", size = 4225496, upload-time = "2025-02-22T17:58:40.629Z" }, - { url = "https://files.pythonhosted.org/packages/2a/e2/83d29c062876383ad016897ecec2d8b67ca36fe3d37f5c25367e83c9a9db/psqlpy-0.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8546854232368d26eb2c7eba64df2765a4b4698d1465a9c20e6af0b61f495558", size = 4438780, upload-time = "2025-02-22T17:58:42.356Z" }, - { url = "https://files.pythonhosted.org/packages/19/6a/4f520027cf6474f20e45a9292c9e80e297763c82ffb47cc4f9176d286865/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5e83ede139b7c650b5be3019de769db5bab44e72c3365604719222ca9c0825d", size = 4935733, upload-time = "2025-02-22T17:58:43.861Z" }, - { url = "https://files.pythonhosted.org/packages/84/4d/44165581b4bc0eb7cda0b35da1a72681c38cb67506e18b244e5bd8373d9f/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5441f83b707f698c23b9c498845caabf523248adda1276be4efc58474991ba88", size = 4217304, upload-time = "2025-02-22T17:58:47.466Z" }, - { url = "https://files.pythonhosted.org/packages/51/0b/357b9f0e303f6378cb5a03b58c5d0be31d219b013f5a670c5fec82ca3fc5/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9070b7a767aa3ad6d16a6b4008b3590e576296d1ef810f11fbf7ad317ca902e", size = 4804254, upload-time = "2025-02-22T17:58:52.052Z" }, - { url = "https://files.pythonhosted.org/packages/e7/da/3721d5457d64584d521219328210a216790b7a911710864a9260bd2760c2/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2452e0c1b5fa1f4d4b0c73daf277de0785e2a4aaa7d75282b100b2d1758a7677", size = 4644033, upload-time = "2025-02-22T17:58:54.563Z" }, - { url = "https://files.pythonhosted.org/packages/44/fc/1170684ea74be268d2b27ae7e69517c29f6bd5bafb192bb7f76615d3fa79/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:231f57d6129358bdd828f1a24667c727ac9cd07ae374b76ab9d860bc9778be36", size = 4774739, upload-time = "2025-02-22T17:58:56.761Z" }, - { url = "https://files.pythonhosted.org/packages/4d/bb/cd369c0d7b9a022b07740167f1d7eae33ccac1a239e10b21306ca6ebc99e/psqlpy-0.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9d258b4af8593fafd02ec00dd594f0de7cb9c5a6d59bb30c0883bb314046bf4", size = 4826125, upload-time = "2025-02-22T17:58:58.824Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ff/6bba939bab5e6b7b42aa2b3f8eedb46f7c9d5e5c21e008c856986d594255/psqlpy-0.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a45f42936faa2839b72d8ba6f31c7f22490cf5211a5acfe507655b22110df6e", size = 4826300, upload-time = "2025-02-22T17:59:01.393Z" }, - { url = "https://files.pythonhosted.org/packages/94/2f/2702b621b8d68683b14d954f5ff2a7a65904a9ae8ea1b62278a1d81cdd84/psqlpy-0.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81f2c9f7f94388d5977e28ab00522ddccd1b880e9f382e350207a80a6c2b790f", size = 4944879, upload-time = "2025-02-22T17:59:02.903Z" }, - { url = "https://files.pythonhosted.org/packages/46/97/b6dacbe274cbf95419af1c8c6c5f06a0290a22a66b4202cbc493db97d127/psqlpy-0.9.3-cp313-cp313-win32.whl", hash = "sha256:9126f5e942c2a8ed1aefa8a662a2865f7aaf293a7610911fd4a07200c133a27a", size = 3292642, upload-time = "2025-02-22T17:59:04.528Z" }, - { url = "https://files.pythonhosted.org/packages/ea/55/aaadda7cbdfdbef9f880b57fb25d3cb641e01a71fbd20d76f59a5eddab78/psqlpy-0.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:e438732440dbba845b1f2fcec426cc8a70461d31e81b330efe5ab4e5a83ead52", size = 3700554, upload-time = "2025-02-22T17:59:06.16Z" }, - { url = "https://files.pythonhosted.org/packages/ae/4d/3395a1a83e4501f9928c83fbfdc88f643158a3224d76d06f6eca837c61a7/psqlpy-0.9.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:583f93e6dcdc5f0c6a9259ed7da686c5a888f10ac8546cdd7e4cacfac5826700", size = 4240939, upload-time = "2025-02-22T17:59:07.697Z" }, - { url = "https://files.pythonhosted.org/packages/d4/46/610c514db36e83e1f5f9e3f309d30795eff8ef7cba45bc223bea98811fa4/psqlpy-0.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fc690c4b56b5aa3242518309167c78820621fd6b3284951c65d7426218be3f6", size = 4479396, upload-time = "2025-02-22T17:59:10.265Z" }, - { url = "https://files.pythonhosted.org/packages/0d/36/fe06b173bee1bc09aac918c4759071773d433c04c943a7d161de1c93c87f/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1395fcfdb294d75ee9044b1da60fcaaca3d01c62cfa338f3c18ecd097e0bd738", size = 4937303, upload-time = "2025-02-22T17:59:11.964Z" }, - { url = "https://files.pythonhosted.org/packages/c8/91/a2187176a1799c2b5d409f6d4fc39c40c2abfd3dfb2d08435c2956a86539/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:033e41fecdfe3b4dee6050d4002c5d619b9325bef4167cc497d644c093ee87f4", size = 4210807, upload-time = "2025-02-22T17:59:13.691Z" }, - { url = "https://files.pythonhosted.org/packages/b7/d7/313638aee4d3f73c4c07bf37a232d83348c37c251f609881796ee6324267/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fadb57a391db8ac1b172a2f3882796e8f77ef2e01795db9fe96870b3d434116", size = 4807024, upload-time = "2025-02-22T17:59:15.269Z" }, - { url = "https://files.pythonhosted.org/packages/01/09/64469aa84e596d8c08210ff6e86d7aafb75eedb7ffae12daa75519eb9f97/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7cb7714554cf08e4eaea8fd547dddb65a32927db4c37afd0fbe9a941d839743", size = 4653704, upload-time = "2025-02-22T17:59:17.655Z" }, - { url = "https://files.pythonhosted.org/packages/e6/47/28eb3014eff4642be833abe1c5c745cd31efd63ef5706528901e9efad820/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ddbcd8438cc439862e05e03f4cf364f76dc51d918fe405878c1acfab1848112c", size = 4789815, upload-time = "2025-02-22T17:59:19.301Z" }, - { url = "https://files.pythonhosted.org/packages/17/7c/509f51dfae6b4fd4282d2589199ab9a895bb3984bf27244231566d5f8cad/psqlpy-0.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd086508cf11e3c390f5d6ed638a39e3d2b4186e53e33ffe6af9b37981ef615", size = 4826656, upload-time = "2025-02-22T17:59:20.865Z" }, - { url = "https://files.pythonhosted.org/packages/b5/79/bb9725575368f46570b646b45da22ef943e97b32e336a485ac169906c1d1/psqlpy-0.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:35aa277d6585ed14936e6c1e4de677564959e379485272906c88090cc5e635dd", size = 4860622, upload-time = "2025-02-22T17:59:22.595Z" }, - { url = "https://files.pythonhosted.org/packages/d3/69/3d80d7286b116734fa8c256b711a0a9554d31df82f7f33cd52e7772ba77b/psqlpy-0.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:81a25ef924322a15a53ee6c36dd38c3d609d05c96f3cf500af33cd929cbe30a1", size = 4980015, upload-time = "2025-02-22T17:59:25.203Z" }, - { url = "https://files.pythonhosted.org/packages/6c/09/b9c0f007c6686193a8f6362980c20c1b33e35cf7bac061071a2a84370e7c/psqlpy-0.9.3-cp39-cp39-win32.whl", hash = "sha256:fa1cbd09536576b22e7aa5e312cf802d4e7da2438c48064bf6886028e8977bec", size = 3311353, upload-time = "2025-02-22T17:59:26.953Z" }, - { url = "https://files.pythonhosted.org/packages/2a/78/181d4f7fbb9f77dce11513b50406ae65484fb5e933143a8c038d73f0a549/psqlpy-0.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:ca15a64cbd4de84c7b9a34f388c70dded46316fac8af851c2f1ba51a755f378f", size = 3722931, upload-time = "2025-02-22T17:59:28.527Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b0/e5e9c3006523bf9a32d1b3506bb2dfc109101d1d8e9d28badba64af9ff38/psqlpy-0.9.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:8c4a6035ebfba0744b15a5c9a3668b2166393619bfb882a189468966ec45f7f0", size = 4236200, upload-time = "2025-02-22T17:59:30.257Z" }, - { url = "https://files.pythonhosted.org/packages/97/23/af1bbbe53c04c029a45dd4c65bb19434c152f4c314d2362f5913ecf09c4d/psqlpy-0.9.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:681dee1d030873f08e55b154c8907a2062f0f6e4b10646411f5ce94028eb0642", size = 4474528, upload-time = "2025-02-22T17:59:31.858Z" }, - { url = "https://files.pythonhosted.org/packages/a3/2a/60cad4acd6be95d0df233f13ac810fb357347f2d224eb2d70471df6c7353/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e26ed13c864b21542eab15f1dfccf02e40fae046076d9c48b3ff062f8406053b", size = 4937463, upload-time = "2025-02-22T17:59:34.338Z" }, - { url = "https://files.pythonhosted.org/packages/fa/45/ba6e10effa92090ed508988dad48d776f466aa2cbc94c7a16b5f14d75e1e/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1baa0200bcdacc9f61efbd273074395bfc7f32b7f7a30fcebb260ae175545914", size = 4210011, upload-time = "2025-02-22T17:59:36.162Z" }, - { url = "https://files.pythonhosted.org/packages/bc/fe/cd176b3a342b45d2f10ad24b109db7a069b437f411302b27eaea77cf0b28/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:925677b1c2ea70addbcb28b86ddc826b77a8107ec489e2d191fb74074ea423b2", size = 4806658, upload-time = "2025-02-22T17:59:37.796Z" }, - { url = "https://files.pythonhosted.org/packages/59/8f/1898a03913f9b697d1b8ae02b3d435a5f05f60e81be5a91934e51044e310/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2c01d44e04f2e9fc7de1c3a8692f38fa22d0a354ce51888b91d8653cae4e0a3", size = 4656552, upload-time = "2025-02-22T17:59:39.666Z" }, - { url = "https://files.pythonhosted.org/packages/60/4d/b67e4b9ffd963850107befa435e8b38b8e7d4f393ee15964c73706c67b13/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b89fb5906bffa757f76c1ef46ec48e3ec3488d484d95d9bc57503b30107e3041", size = 4788063, upload-time = "2025-02-22T17:59:41.458Z" }, - { url = "https://files.pythonhosted.org/packages/25/36/ea1a770563db9105624d0ce73d1b16a80d82d9d278383f9b4633b97ea9ec/psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c193eeca5dbceb770332197cc77a6e5e6ead210c34c4fff1d8cb8675e42e1f6", size = 4827112, upload-time = "2025-02-22T17:59:43.265Z" }, - { url = "https://files.pythonhosted.org/packages/94/fe/248438003e8fcd3ba261da0de09b19a679f34c1b0d633222eef4c826729b/psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:eab75d64e3b27a52bcbee690e8651a3b0dbaeef3028a19afad3a848ccb1b2951", size = 4860284, upload-time = "2025-02-22T17:59:45.795Z" }, - { url = "https://files.pythonhosted.org/packages/7f/43/70111a42df62bf3d1b4053192cd0a3e55f18c2297f8c2732b6baae4b9703/psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:a4f77af73b77bd73285efc0576a3ac087ee0aca39821371ea16d8e2bf9a16c90", size = 4980559, upload-time = "2025-02-22T17:59:48.6Z" }, - { url = "https://files.pythonhosted.org/packages/c7/95/7089fd34c80e948d7f544c73f2ff1a0c20938024f61323e31a71bd85fe21/psqlpy-0.9.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d7d4c6fcc343e0c0238e767caccb534d08b42d234d96e35aa5ce55d195f81281", size = 4237481, upload-time = "2025-02-22T17:59:51.062Z" }, - { url = "https://files.pythonhosted.org/packages/5a/ce/5819a1f1e8f69639789b523d227ce07b989b1fc565fed2e3efb3efc67dc2/psqlpy-0.9.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d0220fa8127db04433c2be2a55da1042e4581531a36692c45668c3484bda437", size = 4474728, upload-time = "2025-02-22T17:59:52.753Z" }, - { url = "https://files.pythonhosted.org/packages/2c/55/daeab10685010204bfb18246fbdab892eeb0a0db94de5bfb3cabd524344b/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbdd68fa7f61e00d7f14f010cd4a7f242935cb9df560181bb947fde75c8c1af5", size = 4938916, upload-time = "2025-02-22T17:59:54.796Z" }, - { url = "https://files.pythonhosted.org/packages/1d/35/2feb538ee0fa6d3e248727501b911dd99f20c58e65fd03c22d0d047bf7a5/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c1e3c82aeec4c58328c723ef0755c2f02e2d30874ce850e0d7505db8bd90397", size = 4211573, upload-time = "2025-02-22T17:59:56.568Z" }, - { url = "https://files.pythonhosted.org/packages/dd/4e/588b6c548363dab19bb58d808760f785058cef0af7649c16c80ddaad2eea/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c936f35fa793b421b116aa37040291ff5a33fc54e7f636e7ae946ec987070a94", size = 4809847, upload-time = "2025-02-22T17:59:58.865Z" }, - { url = "https://files.pythonhosted.org/packages/d6/cc/2aef99aef78b0df24e43790786c0507bb63f4e6fa3e338fbdccb4e1b70e7/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28ee25f791ccbad04269e22a21a79d52609d65298fe9b5300b8fe00fef42bab6", size = 4658403, upload-time = "2025-02-22T18:00:01.167Z" }, - { url = "https://files.pythonhosted.org/packages/67/33/9d5094a57caddd9ffe2eb176e3e30a367312929323daa333bbc4dd11e3a4/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3a1d90bb1da48649852e636612bb12fa0e3ec07f230446836195054598f0de4", size = 4789341, upload-time = "2025-02-22T18:00:05.161Z" }, - { url = "https://files.pythonhosted.org/packages/52/5a/3506b0b6731b7e3f6a818fb3dcef7b2f8685254790a7a4bb0a1c9c2ac3cc/psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a764bf80ce4e9d284bc11e255aff836894ee55e540c1be20120e67f855d8b07c", size = 4829845, upload-time = "2025-02-22T18:00:06.958Z" }, - { url = "https://files.pythonhosted.org/packages/6b/fd/cd5e2929cfe3e357694118638fa227cd9dc6b4717b39590e731d0e3bd2ee/psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7939bfa80b649e650b9b4efe9064936837b14082851f1ad95c24548a105277cd", size = 4862164, upload-time = "2025-02-22T18:00:08.833Z" }, - { url = "https://files.pythonhosted.org/packages/b2/af/e4ca9ccaed96d27c1c753b6d4f16264f0f7a2c752249ea25074f636a6734/psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:23496ed36433c88308f7e85f36091b203bb6c8c655ded639ce1626a1c8319afe", size = 4981643, upload-time = "2025-02-22T18:00:10.595Z" }, +version = "0.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/c9/933b8d218bbc6b8d9e7917434930143a4a44e2d6e24a646d5e99e7360380/psqlpy-0.10.1.tar.gz", hash = "sha256:635727a60c7a966f9eff39ccf05d34acfdedee7b6a2c998e299e4de5cbed6e8c", size = 275987, upload-time = "2025-05-06T11:01:19.766Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/6f/79317f46bc64418c7a4365209687c393a1382733d9426ebfb49066110dcf/psqlpy-0.10.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1b1f3451f366b0c69a1659bde3aa726e0051b2ae3847821e847c44c9dc01bc9d", size = 4275675, upload-time = "2025-05-06T10:58:13.205Z" }, + { url = "https://files.pythonhosted.org/packages/ac/da/1ccd48835b8f1f45c70afa9fe7537cff6e2aa3bea1ca97c2379e30485d37/psqlpy-0.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51911d3d0d13ce90a008785f0b657a7bf104d93d5d19835968727a6f3b67effb", size = 4484742, upload-time = "2025-05-06T10:58:16.94Z" }, + { url = "https://files.pythonhosted.org/packages/29/f2/d1bef98fbc49b7ea69739dfb3b08a7b4c2c9b4b6754954a1c2876de079aa/psqlpy-0.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e71531ac364a0fa6c3bdf0ebf82f9b27db8b885867feda89b65f935717667bf6", size = 4997775, upload-time = "2025-05-06T10:58:18.921Z" }, + { url = "https://files.pythonhosted.org/packages/5d/68/d194ab05a5fc8ef909fa148e08facb562d91f6a21ed0ab928a9b1a90ac59/psqlpy-0.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e55c2675324c45d29f5de0aad88a4623cd3c71feeaaa30199ffcd3fc9b46578b", size = 4263921, upload-time = "2025-05-06T10:58:20.937Z" }, + { url = "https://files.pythonhosted.org/packages/a1/70/343e3ba8ddb6f1937f1c075ad94153d83b7821436510c75fa2b0733cee49/psqlpy-0.10.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd7c5a93650c58133ae6f9ad10c12efcca698f612937860d8d093cfa5bb28746", size = 4865894, upload-time = "2025-05-06T10:58:23.285Z" }, + { url = "https://files.pythonhosted.org/packages/12/7f/5f5724aee24ac9c35ee34c971eb3a3d4227389d003c6aeba85a32b93c3fd/psqlpy-0.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8085a0c53f025d609a6385da68badf58d57727b15c3dcb3e4c9b7d0f153dc113", size = 4721525, upload-time = "2025-05-06T10:58:25.406Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e1/538b4aae5bfc3ab913ace19ab926a943decc2eba4169c1e5b5269835b901/psqlpy-0.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbf6c07e49ab06243744a1262c211e0e741649511de3adac3ea21d3307e5d611", size = 4866257, upload-time = "2025-05-06T10:58:27.908Z" }, + { url = "https://files.pythonhosted.org/packages/a8/67/6c7ff1d262a34bf0935e50ca057a8081e20f6b0a670bb25013813f2683e9/psqlpy-0.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be41f70e7565305b2f1f89deb7ca16c832b2d6a719739c10c81324fc99702e45", size = 4883373, upload-time = "2025-05-06T10:58:30.707Z" }, + { url = "https://files.pythonhosted.org/packages/d8/8f/d9734d19bdd11e9d265393d3a899cbac6fe3f47fd5b7af961db75c879845/psqlpy-0.10.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dde3f1af071ca285bc2f035d87c2b826bb74e628777c8a8fbe1acbced12933d5", size = 4900850, upload-time = "2025-05-06T10:58:33.216Z" }, + { url = "https://files.pythonhosted.org/packages/d7/eb/218c02a9e9f7f034acaf3ba86ec52d98daa71456cb6448ac9419a9652fc4/psqlpy-0.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:48d0482d3f0c36c4a1a0d49c1e334174b28bdd407e4d3fc6f5ab67cbd5d52a9c", size = 5022316, upload-time = "2025-05-06T10:58:35.524Z" }, + { url = "https://files.pythonhosted.org/packages/ac/66/2d2eaa45c4c1171f890cdb07cf539b46fd927c74fee6cd6f5c202c81181b/psqlpy-0.10.1-cp310-cp310-win32.whl", hash = "sha256:5fcef6faa5cbe316f26f77f18e0fbe8f8d66664b3ca3460a3db43ddc6f3233e2", size = 3338695, upload-time = "2025-05-06T10:58:37.47Z" }, + { url = "https://files.pythonhosted.org/packages/79/dc/79b930a69e5f7a261331fd04f969958b05420180a7b5b44a5bdabaf72134/psqlpy-0.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:83646ab11a22199d5299b523e93c4645f465cb14249ecdfcc77b3752235f800e", size = 3753540, upload-time = "2025-05-06T10:58:39.504Z" }, + { url = "https://files.pythonhosted.org/packages/9a/35/647d1a2fcb43604ba6f6dfacd05567d55ce7555225c6c1256f78b66d87e3/psqlpy-0.10.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:11767ffbf8d4f8006ab93a4719893a62cfa368af10f314e015cb0027398028c7", size = 4272725, upload-time = "2025-05-06T10:58:41.396Z" }, + { url = "https://files.pythonhosted.org/packages/ed/c3/45761176a2638c4bb7f1c920de46a9bc461d114f08409ed4697c93dbf21f/psqlpy-0.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9d42591c950ca60628376f0572b5b5ce0178b2958b3938b19085be09d8032d1a", size = 4485202, upload-time = "2025-05-06T10:58:43.237Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d3/77c9ce3e2dae1e05a2e10703e9752af3b3e969151a2d37f1d2aaf4f1eb54/psqlpy-0.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaeb2a3329f919e4f39191d74225228dd1a504d7da09dd2d908cc3043da42e8d", size = 4996513, upload-time = "2025-05-06T10:58:46.755Z" }, + { url = "https://files.pythonhosted.org/packages/63/af/aeaf5b9e84c8d2f6390bdddf29c920f6d98544d2e82b038bbfaf40c22e73/psqlpy-0.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8496bed99ee2f41e10b92a044ac100843b0518d94ba292197d79957529228d64", size = 4267530, upload-time = "2025-05-06T10:58:49.164Z" }, + { url = "https://files.pythonhosted.org/packages/28/e4/d560ba30fedd3db1f74b194f1d90e24b634fa2dbca44d7d9ed86321b64dc/psqlpy-0.10.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f76ddf58293415b5f8754ac2f8b5ba1c6a7564c2699ac16914776916a7703bb2", size = 4865525, upload-time = "2025-05-06T10:58:51.686Z" }, + { url = "https://files.pythonhosted.org/packages/ff/37/d4af03da76d9fb9ee4a5af5ea590e9216a26dbeaa5326a821630a4fe265e/psqlpy-0.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bdce9e1179e9639b6139f5b0382088695c5a1eaa7fc923addce946bdd05e41c", size = 4721244, upload-time = "2025-05-06T10:58:53.687Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/4cadb911b380f25b9e1a9bc6074bab4e6b895dcdd91c28388920451091f0/psqlpy-0.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0bf6ce9bb3b2100a6641c475abc2f55f6d004ea403a5aa9c3168b8597a28e8c", size = 4871873, upload-time = "2025-05-06T10:58:56.142Z" }, + { url = "https://files.pythonhosted.org/packages/d5/be/207af3044dcb36a43beda7eefb4c355912febf45ab8648391bb9eca35196/psqlpy-0.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9cf35ebd610f0c2264fb8fe07103213fe29eeebc8689d737c98473637e17c71", size = 4887459, upload-time = "2025-05-06T10:58:59.582Z" }, + { url = "https://files.pythonhosted.org/packages/32/a6/1ee495f5a0d16853324eb66e8fd6f32e0b8908867ebc5a3744efb3055284/psqlpy-0.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:04f1b6dcda69d1adecb178bf7b81998b7ff5eafb1614bf6d65e8805c804191d6", size = 4900773, upload-time = "2025-05-06T10:59:01.963Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4c/e594171162aaf0ad0edf2b9ec2206ddf4b123225a72069c8d1be2d87fcd1/psqlpy-0.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8ce4266435c6cb61676279d2e53b42b2d60aa3d9f10d740c210348085afd8953", size = 5024936, upload-time = "2025-05-06T10:59:04.12Z" }, + { url = "https://files.pythonhosted.org/packages/24/a2/41708244fef8d1d96cdc44e48c017d0b79f6849326ce907f34907ab24fa4/psqlpy-0.10.1-cp311-cp311-win32.whl", hash = "sha256:69ce194b3154d458a8d2f98d0029cb0914b5766677d3d10504c566877633b908", size = 3339338, upload-time = "2025-05-06T10:59:06.06Z" }, + { url = "https://files.pythonhosted.org/packages/24/7a/e85afd62aa99801aa59004b8299d85ef03841fe983f998cb2c82c1372144/psqlpy-0.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:449ad88f9ec974abf1ed2c642c573fd486ec15f902e3c6f9f999f44063162404", size = 3753495, upload-time = "2025-05-06T10:59:08.051Z" }, + { url = "https://files.pythonhosted.org/packages/9d/88/9d131073c05d62e088cb0d7633e1542778be39b3d1adb546ddd8915ad750/psqlpy-0.10.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e4d08a9043c7c1185b0aa0b90c38c035aaf977a76d0a8def886c6341b8669597", size = 4245883, upload-time = "2025-05-06T10:59:10.026Z" }, + { url = "https://files.pythonhosted.org/packages/93/f1/47e112676b4f0c9d6e8d9509fd0379371ab63a4760993a1d91e5f12e3bea/psqlpy-0.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3d725aa0eae9777d273b884e87f124ad1aaa595731ad1d0d8d0082f2898699ea", size = 4477019, upload-time = "2025-05-06T10:59:12.031Z" }, + { url = "https://files.pythonhosted.org/packages/e1/39/018b653ffce3d6eee37bf095e38f51fa58f2cd5652d2d84038e3bee5bbdb/psqlpy-0.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88f33b946e78098febb3552e3d217795b3aca8921d09c8db7fac4b79c3e5f8eb", size = 5003880, upload-time = "2025-05-06T10:59:14.381Z" }, + { url = "https://files.pythonhosted.org/packages/93/6d/e96238aec65cf71f58c0b95fc7c996ba83eee303dd355f9066bf69afde24/psqlpy-0.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1351c405ec2018bd782a61d5dc9e270ae095e0728b96371c1c2ee6072b5ad3c4", size = 4272126, upload-time = "2025-05-06T10:59:16.454Z" }, + { url = "https://files.pythonhosted.org/packages/18/ec/b9a4ef483eb59d704af05b9e77595bf07030a165bd58868db8ad59ad4d48/psqlpy-0.10.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cbdaf4a0c97eff79dba7c25deaacb9031204c2102e832438ae9b152e80c5fba", size = 4874162, upload-time = "2025-05-06T10:59:18.547Z" }, + { url = "https://files.pythonhosted.org/packages/19/d7/636c62d04dd4597aed3529553a53f74b04da9fd4084d149fc07e8ea9c2a1/psqlpy-0.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8609f9164385d20febd8944635b0c47fb7994e05342168a6d8295628aa3728fe", size = 4715795, upload-time = "2025-05-06T10:59:20.754Z" }, + { url = "https://files.pythonhosted.org/packages/62/20/8b114d358bfa7ec3eaa15ba632a7049a8c9ef42d4a2fc8c65c12240340a7/psqlpy-0.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1e0e1828098e5fa8b96cdaa9923e92c605463bb30eb9f2ac81ac19cff37a544", size = 4854069, upload-time = "2025-05-06T10:59:22.902Z" }, + { url = "https://files.pythonhosted.org/packages/41/c6/05e2d4ad568dd9b1620671805c9a6567150f28f1bdc7d67e35ec6c4306da/psqlpy-0.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd8fe8c355a5e39f01c8ed5a0782b7611bce41f77aa481c50a1ebe39c2a56d6", size = 4889096, upload-time = "2025-05-06T10:59:24.879Z" }, + { url = "https://files.pythonhosted.org/packages/56/cd/2c6e2cd17fe2622adc570375f852b4cc866b166dc935b2293ce214d74da4/psqlpy-0.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:786cb804298e65364c99d421d9ceb67d6afdf365d312e27568afa41d7ff92f36", size = 4904682, upload-time = "2025-05-06T10:59:27.045Z" }, + { url = "https://files.pythonhosted.org/packages/ec/72/65171102dd2e4015a3a1dc86cb73e531156ec32abf33ceca52ecec9a0073/psqlpy-0.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bfff4d31184c2702cfe31b0f620242b34be0c2691ede75681a44dc8b5696c114", size = 5022991, upload-time = "2025-05-06T10:59:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/1dd64ee9f99ea9bd56c12c33c96e34112ef164bf4dd2dcbeacdca3b5c6e9/psqlpy-0.10.1-cp312-cp312-win32.whl", hash = "sha256:06ccf63429ce282bcdffd64f626d9a5cd8d4283a3a6dfe8f2e71322edb36fade", size = 3340168, upload-time = "2025-05-06T10:59:31.247Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6e/7dde32d8900899f94eab03ea530ebbf5d9f6bd31f53e07ec9d6d787e9f7c/psqlpy-0.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:d7eb3344ead1da9193a9d8822f6e1dce1abedd81db8812992ba3e66119e80f39", size = 3754429, upload-time = "2025-05-06T10:59:33.341Z" }, + { url = "https://files.pythonhosted.org/packages/bb/2e/ca98a66f13bbb14a43321b1bd7afda5804c6e8a2e1f3d501b4bd6bcdea6d/psqlpy-0.10.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d38003c939ffbcff99f36d7f19a405d52fdf9de493bbac33e33feb63720328ef", size = 4248884, upload-time = "2025-05-06T10:59:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/ba/98/0424624662e4ba16928757bec9554cd994929e74bdc89125339b46b69242/psqlpy-0.10.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e26b1c9daaf7f6e520e9ae0fa4df802c62b6ffd40281bef2b88e73af1471db", size = 4475666, upload-time = "2025-05-06T10:59:37.622Z" }, + { url = "https://files.pythonhosted.org/packages/43/d3/5b703c69616ced9a2ba7f829314238963cd12d88d5f08bf61d222018e109/psqlpy-0.10.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569647f04da16736a984f28b9d3bda400957377d8d8e933e89d4c961ff6ece15", size = 5003844, upload-time = "2025-05-06T10:59:39.788Z" }, + { url = "https://files.pythonhosted.org/packages/91/27/5aec11a38818b916ff972eab95b5ccb9347e44b65828085a464d5956d138/psqlpy-0.10.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86819b1550fa6253a581c5466297380e8163af9160931f16d5873d73ba1f8ac0", size = 4269699, upload-time = "2025-05-06T10:59:41.932Z" }, + { url = "https://files.pythonhosted.org/packages/c0/91/558ef70e5f889d4529e1ca7c0e73bf735473235244a5f3d73999d8eac5a1/psqlpy-0.10.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4689257eb530ea1f89e9f3e97c6425953829966de9b5ec627ebee1a88e52705", size = 4873779, upload-time = "2025-05-06T10:59:44.499Z" }, + { url = "https://files.pythonhosted.org/packages/a2/d6/bc75034d2ac8c4d895ec2bae4dbc8c7ddcc0312e88ae99a86d5c41d51c8a/psqlpy-0.10.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a48a7be5bcae7167ea1dcc031af9a71e24556cf3943d681fca2cbd402ea8c069", size = 4710884, upload-time = "2025-05-06T10:59:47.093Z" }, + { url = "https://files.pythonhosted.org/packages/e5/97/4b5c79182064528ad54b39f4316063f482c4e6cd9271b600d08ab50528fa/psqlpy-0.10.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:218adac109d31dfc73082ccd0483c2fb83c6ecaf3575d3b9fca80fa44dc01db3", size = 4843091, upload-time = "2025-05-06T10:59:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/f8/aa/c03d721dedab41f612f63257b7982f6ad0af521b5346afcfab29e6862370/psqlpy-0.10.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52f4f3bf5d530f0c62dd127c2154b06baaef31443d459e3c4566bb219e6dd1ca", size = 4888297, upload-time = "2025-05-06T10:59:51.332Z" }, + { url = "https://files.pythonhosted.org/packages/7e/08/f466ffc1ae86756a146abb3b7b4ba9a130efb7c2ef026058b27e6a8aad05/psqlpy-0.10.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:55738f1d23ca7d1a08fdf49759b9872541da9302b896eec0ee95deab62336fd1", size = 4904145, upload-time = "2025-05-06T10:59:53.276Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/52aa99319e9ce9c66d097e4c239c11df16237bc82ee056e82f0e63a44880/psqlpy-0.10.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dbe0625d7b8232150562de10105d7089c3f3321295ddf45b036d029595338f90", size = 5024109, upload-time = "2025-05-06T10:59:55.366Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9b/6dbb50c6874a93f6e0d9cd78b7b5fe458a5ccdddd8971695ef0be3d7bc5d/psqlpy-0.10.1-cp313-cp313-win32.whl", hash = "sha256:3f54110a29235936e59e210fd1176443bafdcec5d7dedf4e3671459a98ba3d4d", size = 3340240, upload-time = "2025-05-06T10:59:57.795Z" }, + { url = "https://files.pythonhosted.org/packages/05/ef/700124b76788a0025a00c91c11da6fecbfb70f9636190d2b96a4fc3c9490/psqlpy-0.10.1-cp313-cp313-win_amd64.whl", hash = "sha256:3ec2ddec67227297592d0a6c983d2f0ce7bb027cbf67629c304d1c1c3d9c8c08", size = 3753294, upload-time = "2025-05-06T10:59:59.904Z" }, + { url = "https://files.pythonhosted.org/packages/2c/5f/0ddede5ab03e3e0beeb358c8801ff7955b600c9f80162d8a6cfb0b3d6cdd/psqlpy-0.10.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:120eb1d16b54e3cc8795de2b0b60813422a7a44a2586495fa7618b5bd4bc5add", size = 4277427, upload-time = "2025-05-06T11:00:02.321Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3c/1d118e722d3b7cb16ab7b01cb78c8293faa3082e05579c69741312b048e3/psqlpy-0.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fa828c84c3f726906c9335c76a84b0963946bcbb508b34aee9865c67bdfa97d6", size = 4485859, upload-time = "2025-05-06T11:00:04.588Z" }, + { url = "https://files.pythonhosted.org/packages/b4/56/c69c7c81c93f2b8f2d4f2f7801182580b592870f32d610f3c9cfc37e7ea4/psqlpy-0.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd63db94c28dabfb823ba20292aec51958b5a358e110f80b7afbc2d36b6a046f", size = 5000031, upload-time = "2025-05-06T11:00:06.66Z" }, + { url = "https://files.pythonhosted.org/packages/d4/91/ddbf4750ce41a37352107bdb37326c687210877d143a8f71ed0d388e96b8/psqlpy-0.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cefaeb49fd15aa4aeb938c900c57a697ab84ccef11e110b0d56f9692378a5376", size = 4264776, upload-time = "2025-05-06T11:00:08.939Z" }, + { url = "https://files.pythonhosted.org/packages/c3/7a/a73c4e73796be5cc5a307d1a203d2929de4c1e98110f42ff7bc7278cac57/psqlpy-0.10.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ccd15e42a3304ed87ea1bbdba168f30844c37af4ea614e9c500f09f699e95a2", size = 4869824, upload-time = "2025-05-06T11:00:11.436Z" }, + { url = "https://files.pythonhosted.org/packages/c9/cb/2c8ac4ba36caf080e46ecc624321dbd73ff524a4e836b5b13110ace0a03f/psqlpy-0.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:90d991874b1d6aea110c98cc9c8517318231109a6e27a985188e5cfa6b57e661", size = 4723201, upload-time = "2025-05-06T11:00:14.037Z" }, + { url = "https://files.pythonhosted.org/packages/ff/35/ecbb4d602170fe625224b9f40885be0cc8e5fd5e0f68be278740c57ccd63/psqlpy-0.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73359152273aae4f49057cdd6cf35696897dde9b3a3da874edcb5e250ae5713d", size = 4853392, upload-time = "2025-05-06T11:00:16.137Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f4/e0a657881b91180445f9b9a3b265f66ff5c1c75c07859e064aaa1d54c7cf/psqlpy-0.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baee9e42d432ebd0b5e5c4af65de3df6fa4c1d7ea15384643fe0ba17c24b0126", size = 4885133, upload-time = "2025-05-06T11:00:18.188Z" }, + { url = "https://files.pythonhosted.org/packages/db/eb/6bb8d4c2e348e3919aac88d9e8578dde7b009944586cc4dd6c71d514cdf8/psqlpy-0.10.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:27936cd03acd544696b58250d7515dc68216da531fdb84be75276a4a68041d1d", size = 4902289, upload-time = "2025-05-06T11:00:20.469Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d3/fab6a4292f96bb8b1871dd9837f9d1d1a1c1b3ac5105c7d14271be333aa3/psqlpy-0.10.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c677c4afb8550c2961c8c255d0dbb2741e90a63bf17783794c22fe2a5f9aff", size = 5023630, upload-time = "2025-05-06T11:00:23.088Z" }, + { url = "https://files.pythonhosted.org/packages/fd/b3/f975ea0efa807e3afc73cecf34632aa540b9d84acce7bbaac7e8cae6848f/psqlpy-0.10.1-cp39-cp39-win32.whl", hash = "sha256:8c5af893dd1cfd4d5be75e50847ae71347c9b9deada5fa7ee152c5527de34ddb", size = 3338635, upload-time = "2025-05-06T11:00:25.453Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f4/a5ec76a3ac5a4066a97a138e09425a7fbb9628bbc7ca231708892f5e4649/psqlpy-0.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:5b8d7c61ba1c366264a4209813785060112751a1af6325a5e6fd3cb10e89f915", size = 3754812, upload-time = "2025-05-06T11:00:27.745Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e2/983b24c0d6df9490c54368dc6c54897ab58b98f0337ce91df53acb6c63f4/psqlpy-0.10.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f15a9fb455970346f973b496415fe701e931a536d97b1cd13e040385e4c0d0e3", size = 4273879, upload-time = "2025-05-06T11:00:29.982Z" }, + { url = "https://files.pythonhosted.org/packages/6e/3c/2b96c9c49964be02efb39fbbd47f635797e117a1e6b8b7967c6df7bd079b/psqlpy-0.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:474865370ccc61301af138a7d07ab85e459a53db2967ffaf248a93f9713c5ab5", size = 4488590, upload-time = "2025-05-06T11:00:32.37Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/eb3bed8a1d900b9815e3a81a5c45796cc7bfbf630fb108696dd01eb3c141/psqlpy-0.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:addaf4a954ea4cdf84270697fd2e2dfda643900d4afc584d71b8782d899cda46", size = 4995077, upload-time = "2025-05-06T11:00:34.881Z" }, + { url = "https://files.pythonhosted.org/packages/06/f4/86fb3836a0aee8e38541ddb71aa81b97f05031e4886ca178f51878ac1876/psqlpy-0.10.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b291886999da8d00054e489ee5cb8934f319cf75cc1b3806a543646ef582c35", size = 4265346, upload-time = "2025-05-06T11:00:37.078Z" }, + { url = "https://files.pythonhosted.org/packages/e7/0b/628b46e3e15c54219c0a0cf2c0094b273186b2fd4b1b44ae4fcd31b36c69/psqlpy-0.10.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8616ba5be0ab0c0c5401660e880b1ad63ca87a78463af49624da3da5682c7c18", size = 4874626, upload-time = "2025-05-06T11:00:39.79Z" }, + { url = "https://files.pythonhosted.org/packages/44/38/5fe44daca0ccec7011af8e0328f185c416ee1f08f39721300450c8ce4d57/psqlpy-0.10.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d71627bc1a827ab7cf60ff107e8a8927c0e703d9c72788fc1edb26f0cb196571", size = 4719972, upload-time = "2025-05-06T11:00:42.556Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7f/81f3f8c68e398e2a677e99397c795b06b3f3949bc4032b04edc1220f8dcb/psqlpy-0.10.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9aff916bce182b1c0ca697955b67e9e4bb709c07a4fb90550420c2088f2aaaa", size = 4852966, upload-time = "2025-05-06T11:00:45.335Z" }, + { url = "https://files.pythonhosted.org/packages/c3/af/1c1e3853c1c6655a2ec4aaef6f11a8adb44051dc5cd769781dee47af8667/psqlpy-0.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4de8b61a45960093b873eeb3156db9746480f78981335e3f48c616b05fd7b075", size = 4886746, upload-time = "2025-05-06T11:00:47.828Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/cfb43af957b50c45ac25097660a7d66f2dd725536fa212223ff82354eb7d/psqlpy-0.10.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:75e0908cf7b59d40b1dde684dd411354896356107fb89cc26844f740ceb94594", size = 4903163, upload-time = "2025-05-06T11:00:50.584Z" }, + { url = "https://files.pythonhosted.org/packages/ac/05/976c28b94afa87f024df69485d62ba6bde59db4a31fbd2f485e542ed9a6b/psqlpy-0.10.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:cd5447eeec512237ef35babf5e03a014f96c330bf6b0753bdcbcea25c3de1cd9", size = 5024245, upload-time = "2025-05-06T11:00:53.455Z" }, + { url = "https://files.pythonhosted.org/packages/15/a3/59f622f0ae327b500ebb1600cc4a9b535edd9c6f2ac85fb2e62419f5a72e/psqlpy-0.10.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1cd6549ecf6c6c26bcd9b5f5a0eab8b6e7d5eacfd18e4d4413dd11ffdf6f37aa", size = 4275394, upload-time = "2025-05-06T11:00:55.742Z" }, + { url = "https://files.pythonhosted.org/packages/36/06/e810ffe844e4fad6631d08fded01ff050ad476b1e28b0ba324d70c0bd4a0/psqlpy-0.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:66e61dc05d488aecbd0e54f41e7e763c2ba0b66a4298c584698dd11bd43505f8", size = 4490563, upload-time = "2025-05-06T11:00:57.987Z" }, + { url = "https://files.pythonhosted.org/packages/a9/da/bc0391524373557d8c6250850866a5fb0d3bb966b5e8af64ea21990120e0/psqlpy-0.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7be4f4e754b869c896c510a1708314c3a542869a208539a8376eb4e9ecd24dc", size = 4996595, upload-time = "2025-05-06T11:01:01.025Z" }, + { url = "https://files.pythonhosted.org/packages/42/19/3d8b01d14dfad1ccc498f7a5ac58be88adcb113ac6c6d2ba01d638971207/psqlpy-0.10.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f895cc894bb5ac4a1545120887c5c2b7b232bd45002553b8312880c6edad2c40", size = 4266649, upload-time = "2025-05-06T11:01:03.445Z" }, + { url = "https://files.pythonhosted.org/packages/eb/b5/bd97f22c5db681ab5dc88cbd906aa1eae96fa9977c62c47bd8369881b48f/psqlpy-0.10.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8dc5820b719e610df32bf895a4f544c1617e84bed3b67d9b2049094d41a7ef4", size = 4874413, upload-time = "2025-05-06T11:01:05.824Z" }, + { url = "https://files.pythonhosted.org/packages/76/51/8f69310f53c05af8c06d519de67e2f0b13c6399c55eb39712858e9534d06/psqlpy-0.10.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea580559b4c06c12f29a4543ca340609dd3518fae9f538f352f421abb3832ef6", size = 4721087, upload-time = "2025-05-06T11:01:08.184Z" }, + { url = "https://files.pythonhosted.org/packages/64/fc/84f2aa69368068ee624a407ee3b7788913750b159a873031c76349a3bf6e/psqlpy-0.10.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e01530b5e5c9e8b47029752c837ff34362ca95d2e8e09b581715b9691808d913", size = 4870168, upload-time = "2025-05-06T11:01:10.86Z" }, + { url = "https://files.pythonhosted.org/packages/86/87/4950f54861826258f6ae7038e3a7736cd07a82512b77de7830d42e80bb2a/psqlpy-0.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7642934d0c3f0a04a565f317917b4b77aee8d82fa8b8ca57e3bde05d4d69d2de", size = 4889819, upload-time = "2025-05-06T11:01:13.13Z" }, + { url = "https://files.pythonhosted.org/packages/05/47/10ef69b8ab656fdc6fc38ae0038b9f0155904ca2ac18d04855620c12dbd9/psqlpy-0.10.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:201e7d9afdf561d99a1accb04e5f59db86e1722affd2de5561432dbde280c0f8", size = 4904246, upload-time = "2025-05-06T11:01:15.515Z" }, + { url = "https://files.pythonhosted.org/packages/eb/68/bc2364ee255a4ad764b9324610b0bbd3742153804db96ca4e1fc233b472d/psqlpy-0.10.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:613a5e016ceb8e55875759610fcbdec62c16fedb19160ba985e3002d10d99586", size = 5026112, upload-time = "2025-05-06T11:01:17.735Z" }, ] [[package]] @@ -2979,7 +3006,8 @@ name = "rich-click" version = "1.8.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "rich" }, { name = "typing-extensions" }, ] @@ -3076,36 +3104,36 @@ wheels = [ [[package]] name = "ruff" -version = "0.11.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/f6/adcf73711f31c9f5393862b4281c875a462d9f639f4ccdf69dc368311c20/ruff-0.11.8.tar.gz", hash = "sha256:6d742d10626f9004b781f4558154bb226620a7242080e11caeffab1a40e99df8", size = 4086399, upload-time = "2025-05-01T14:53:24.459Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/60/c6aa9062fa518a9f86cb0b85248245cddcd892a125ca00441df77d79ef88/ruff-0.11.8-py3-none-linux_armv6l.whl", hash = "sha256:896a37516c594805e34020c4a7546c8f8a234b679a7716a3f08197f38913e1a3", size = 10272473, upload-time = "2025-05-01T14:52:37.252Z" }, - { url = "https://files.pythonhosted.org/packages/a0/e4/0325e50d106dc87c00695f7bcd5044c6d252ed5120ebf423773e00270f50/ruff-0.11.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab86d22d3d721a40dd3ecbb5e86ab03b2e053bc93c700dc68d1c3346b36ce835", size = 11040862, upload-time = "2025-05-01T14:52:41.022Z" }, - { url = "https://files.pythonhosted.org/packages/e6/27/b87ea1a7be37fef0adbc7fd987abbf90b6607d96aa3fc67e2c5b858e1e53/ruff-0.11.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:258f3585057508d317610e8a412788cf726efeefa2fec4dba4001d9e6f90d46c", size = 10385273, upload-time = "2025-05-01T14:52:43.551Z" }, - { url = "https://files.pythonhosted.org/packages/d3/f7/3346161570d789045ed47a86110183f6ac3af0e94e7fd682772d89f7f1a1/ruff-0.11.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:727d01702f7c30baed3fc3a34901a640001a2828c793525043c29f7614994a8c", size = 10578330, upload-time = "2025-05-01T14:52:45.48Z" }, - { url = "https://files.pythonhosted.org/packages/c6/c3/327fb950b4763c7b3784f91d3038ef10c13b2d42322d4ade5ce13a2f9edb/ruff-0.11.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3dca977cc4fc8f66e89900fa415ffe4dbc2e969da9d7a54bfca81a128c5ac219", size = 10122223, upload-time = "2025-05-01T14:52:47.675Z" }, - { url = "https://files.pythonhosted.org/packages/de/c7/ba686bce9adfeb6c61cb1bbadc17d58110fe1d602f199d79d4c880170f19/ruff-0.11.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c657fa987d60b104d2be8b052d66da0a2a88f9bd1d66b2254333e84ea2720c7f", size = 11697353, upload-time = "2025-05-01T14:52:50.264Z" }, - { url = "https://files.pythonhosted.org/packages/53/8e/a4fb4a1ddde3c59e73996bb3ac51844ff93384d533629434b1def7a336b0/ruff-0.11.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f2e74b021d0de5eceb8bd32919f6ff8a9b40ee62ed97becd44993ae5b9949474", size = 12375936, upload-time = "2025-05-01T14:52:52.394Z" }, - { url = "https://files.pythonhosted.org/packages/ad/a1/9529cb1e2936e2479a51aeb011307e7229225df9ac64ae064d91ead54571/ruff-0.11.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b5ef39820abc0f2c62111f7045009e46b275f5b99d5e59dda113c39b7f4f38", size = 11850083, upload-time = "2025-05-01T14:52:55.424Z" }, - { url = "https://files.pythonhosted.org/packages/3e/94/8f7eac4c612673ae15a4ad2bc0ee62e03c68a2d4f458daae3de0e47c67ba/ruff-0.11.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1dba3135ca503727aa4648152c0fa67c3b1385d3dc81c75cd8a229c4b2a1458", size = 14005834, upload-time = "2025-05-01T14:52:58.056Z" }, - { url = "https://files.pythonhosted.org/packages/1e/7c/6f63b46b2be870cbf3f54c9c4154d13fac4b8827f22fa05ac835c10835b2/ruff-0.11.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f024d32e62faad0f76b2d6afd141b8c171515e4fb91ce9fd6464335c81244e5", size = 11503713, upload-time = "2025-05-01T14:53:01.244Z" }, - { url = "https://files.pythonhosted.org/packages/3a/91/57de411b544b5fe072779678986a021d87c3ee5b89551f2ca41200c5d643/ruff-0.11.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d365618d3ad747432e1ae50d61775b78c055fee5936d77fb4d92c6f559741948", size = 10457182, upload-time = "2025-05-01T14:53:03.726Z" }, - { url = "https://files.pythonhosted.org/packages/01/49/cfe73e0ce5ecdd3e6f1137bf1f1be03dcc819d1bfe5cff33deb40c5926db/ruff-0.11.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4d9aaa91035bdf612c8ee7266153bcf16005c7c7e2f5878406911c92a31633cb", size = 10101027, upload-time = "2025-05-01T14:53:06.555Z" }, - { url = "https://files.pythonhosted.org/packages/56/21/a5cfe47c62b3531675795f38a0ef1c52ff8de62eaddf370d46634391a3fb/ruff-0.11.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0eba551324733efc76116d9f3a0d52946bc2751f0cd30661564117d6fd60897c", size = 11111298, upload-time = "2025-05-01T14:53:08.825Z" }, - { url = "https://files.pythonhosted.org/packages/36/98/f76225f87e88f7cb669ae92c062b11c0a1e91f32705f829bd426f8e48b7b/ruff-0.11.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:161eb4cff5cfefdb6c9b8b3671d09f7def2f960cee33481dd898caf2bcd02304", size = 11566884, upload-time = "2025-05-01T14:53:11.626Z" }, - { url = "https://files.pythonhosted.org/packages/de/7e/fff70b02e57852fda17bd43f99dda37b9bcf3e1af3d97c5834ff48d04715/ruff-0.11.8-py3-none-win32.whl", hash = "sha256:5b18caa297a786465cc511d7f8be19226acf9c0a1127e06e736cd4e1878c3ea2", size = 10451102, upload-time = "2025-05-01T14:53:14.303Z" }, - { url = "https://files.pythonhosted.org/packages/7b/a9/eaa571eb70648c9bde3120a1d5892597de57766e376b831b06e7c1e43945/ruff-0.11.8-py3-none-win_amd64.whl", hash = "sha256:6e70d11043bef637c5617297bdedec9632af15d53ac1e1ba29c448da9341b0c4", size = 11597410, upload-time = "2025-05-01T14:53:16.571Z" }, - { url = "https://files.pythonhosted.org/packages/cd/be/f6b790d6ae98f1f32c645f8540d5c96248b72343b0a56fab3a07f2941897/ruff-0.11.8-py3-none-win_arm64.whl", hash = "sha256:304432e4c4a792e3da85b7699feb3426a0908ab98bf29df22a31b0cdd098fac2", size = 10713129, upload-time = "2025-05-01T14:53:22.27Z" }, +version = "0.11.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/e7/e55dda1c92cdcf34b677ebef17486669800de01e887b7831a1b8fdf5cb08/ruff-0.11.9.tar.gz", hash = "sha256:ebd58d4f67a00afb3a30bf7d383e52d0e036e6195143c6db7019604a05335517", size = 4132134, upload-time = "2025-05-09T16:19:41.511Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/71/75dfb7194fe6502708e547941d41162574d1f579c4676a8eb645bf1a6842/ruff-0.11.9-py3-none-linux_armv6l.whl", hash = "sha256:a31a1d143a5e6f499d1fb480f8e1e780b4dfdd580f86e05e87b835d22c5c6f8c", size = 10335453, upload-time = "2025-05-09T16:18:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/74/fc/ad80c869b1732f53c4232bbf341f33c5075b2c0fb3e488983eb55964076a/ruff-0.11.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:66bc18ca783b97186a1f3100e91e492615767ae0a3be584e1266aa9051990722", size = 11072566, upload-time = "2025-05-09T16:19:01.432Z" }, + { url = "https://files.pythonhosted.org/packages/87/0d/0ccececef8a0671dae155cbf7a1f90ea2dd1dba61405da60228bbe731d35/ruff-0.11.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bd576cd06962825de8aece49f28707662ada6a1ff2db848d1348e12c580acbf1", size = 10435020, upload-time = "2025-05-09T16:19:03.897Z" }, + { url = "https://files.pythonhosted.org/packages/52/01/e249e1da6ad722278094e183cbf22379a9bbe5f21a3e46cef24ccab76e22/ruff-0.11.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b1d18b4be8182cc6fddf859ce432cc9631556e9f371ada52f3eaefc10d878de", size = 10593935, upload-time = "2025-05-09T16:19:06.455Z" }, + { url = "https://files.pythonhosted.org/packages/ed/9a/40cf91f61e3003fe7bd43f1761882740e954506c5a0f9097b1cff861f04c/ruff-0.11.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0f3f46f759ac623e94824b1e5a687a0df5cd7f5b00718ff9c24f0a894a683be7", size = 10172971, upload-time = "2025-05-09T16:19:10.261Z" }, + { url = "https://files.pythonhosted.org/packages/61/12/d395203de1e8717d7a2071b5a340422726d4736f44daf2290aad1085075f/ruff-0.11.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f34847eea11932d97b521450cf3e1d17863cfa5a94f21a056b93fb86f3f3dba2", size = 11748631, upload-time = "2025-05-09T16:19:12.307Z" }, + { url = "https://files.pythonhosted.org/packages/66/d6/ef4d5eba77677eab511644c37c55a3bb8dcac1cdeb331123fe342c9a16c9/ruff-0.11.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f33b15e00435773df97cddcd263578aa83af996b913721d86f47f4e0ee0ff271", size = 12409236, upload-time = "2025-05-09T16:19:15.006Z" }, + { url = "https://files.pythonhosted.org/packages/c5/8f/5a2c5fc6124dd925a5faf90e1089ee9036462118b619068e5b65f8ea03df/ruff-0.11.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b27613a683b086f2aca8996f63cb3dd7bc49e6eccf590563221f7b43ded3f65", size = 11881436, upload-time = "2025-05-09T16:19:17.063Z" }, + { url = "https://files.pythonhosted.org/packages/39/d1/9683f469ae0b99b95ef99a56cfe8c8373c14eba26bd5c622150959ce9f64/ruff-0.11.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e0d88756e63e8302e630cee3ce2ffb77859797cc84a830a24473939e6da3ca6", size = 13982759, upload-time = "2025-05-09T16:19:19.693Z" }, + { url = "https://files.pythonhosted.org/packages/4e/0b/c53a664f06e0faab596397867c6320c3816df479e888fe3af63bc3f89699/ruff-0.11.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:537c82c9829d7811e3aa680205f94c81a2958a122ac391c0eb60336ace741a70", size = 11541985, upload-time = "2025-05-09T16:19:21.831Z" }, + { url = "https://files.pythonhosted.org/packages/23/a0/156c4d7e685f6526a636a60986ee4a3c09c8c4e2a49b9a08c9913f46c139/ruff-0.11.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:440ac6a7029f3dee7d46ab7de6f54b19e34c2b090bb4f2480d0a2d635228f381", size = 10465775, upload-time = "2025-05-09T16:19:24.401Z" }, + { url = "https://files.pythonhosted.org/packages/43/d5/88b9a6534d9d4952c355e38eabc343df812f168a2c811dbce7d681aeb404/ruff-0.11.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:71c539bac63d0788a30227ed4d43b81353c89437d355fdc52e0cda4ce5651787", size = 10170957, upload-time = "2025-05-09T16:19:27.08Z" }, + { url = "https://files.pythonhosted.org/packages/f0/b8/2bd533bdaf469dc84b45815ab806784d561fab104d993a54e1852596d581/ruff-0.11.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c67117bc82457e4501473c5f5217d49d9222a360794bfb63968e09e70f340abd", size = 11143307, upload-time = "2025-05-09T16:19:29.462Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d9/43cfba291788459b9bfd4e09a0479aa94d05ab5021d381a502d61a807ec1/ruff-0.11.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e4b78454f97aa454586e8a5557facb40d683e74246c97372af3c2d76901d697b", size = 11603026, upload-time = "2025-05-09T16:19:31.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e6/7ed70048e89b01d728ccc950557a17ecf8df4127b08a56944b9d0bae61bc/ruff-0.11.9-py3-none-win32.whl", hash = "sha256:7fe1bc950e7d7b42caaee2a8a3bc27410547cc032c9558ee2e0f6d3b209e845a", size = 10548627, upload-time = "2025-05-09T16:19:33.657Z" }, + { url = "https://files.pythonhosted.org/packages/90/36/1da5d566271682ed10f436f732e5f75f926c17255c9c75cefb77d4bf8f10/ruff-0.11.9-py3-none-win_amd64.whl", hash = "sha256:52edaa4a6d70f8180343a5b7f030c7edd36ad180c9f4d224959c2d689962d964", size = 11634340, upload-time = "2025-05-09T16:19:35.815Z" }, + { url = "https://files.pythonhosted.org/packages/40/f7/70aad26e5877c8f7ee5b161c4c9fa0100e63fc4c944dc6d97b9c7e871417/ruff-0.11.9-py3-none-win_arm64.whl", hash = "sha256:bcf42689c22f2e240f496d0c183ef2c6f7b35e809f12c1db58f75d9aa8d630ca", size = 10741080, upload-time = "2025-05-09T16:19:39.605Z" }, ] [[package]] name = "setuptools" -version = "80.3.1" +version = "80.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/70/dc/3976b322de9d2e87ed0007cf04cc7553969b6c7b3f48a565d0333748fbcd/setuptools-80.3.1.tar.gz", hash = "sha256:31e2c58dbb67c99c289f51c16d899afedae292b978f8051efaf6262d8212f927", size = 1315082, upload-time = "2025-05-04T18:47:04.397Z" } +sdist = { url = "https://files.pythonhosted.org/packages/95/32/0cc40fe41fd2adb80a2f388987f4f8db3c866c69e33e0b4c8b093fdf700e/setuptools-80.4.0.tar.gz", hash = "sha256:5a78f61820bc088c8e4add52932ae6b8cf423da2aff268c23f813cfbb13b4006", size = 1315008, upload-time = "2025-05-09T20:42:27.972Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/7e/5d8af3317ddbf9519b687bd1c39d8737fde07d97f54df65553faca5cffb1/setuptools-80.3.1-py3-none-any.whl", hash = "sha256:ea8e00d7992054c4c592aeb892f6ad51fe1b4d90cc6947cc45c45717c40ec537", size = 1201172, upload-time = "2025-05-04T18:47:02.575Z" }, + { url = "https://files.pythonhosted.org/packages/b1/93/dba5ed08c2e31ec7cdc2ce75705a484ef0be1a2fecac8a58272489349de8/setuptools-80.4.0-py3-none-any.whl", hash = "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2", size = 1200812, upload-time = "2025-05-09T20:42:25.325Z" }, ] [[package]] @@ -3136,7 +3164,8 @@ name = "slotscheck" version = "0.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4b/57/6fcb8df11e7c76eb87b23bfa931408e47f051c6161749c531b4060a45516/slotscheck-0.19.1.tar.gz", hash = "sha256:6146b7747f8db335a00a66b782f86011b74b995f61746dc5b36a9e77d5326013", size = 16050, upload-time = "2024-10-19T13:30:53.369Z" } @@ -3155,11 +3184,11 @@ wheels = [ [[package]] name = "snowballstemmer" -version = "2.2.0" +version = "3.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699, upload-time = "2021-11-16T18:38:38.009Z" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002, upload-time = "2021-11-16T18:38:34.792Z" }, + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, ] [[package]] @@ -3336,7 +3365,8 @@ name = "sphinx-click" version = "6.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "docutils" }, { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, @@ -3476,7 +3506,7 @@ wheels = [ [[package]] name = "sphinx-toolbox" -version = "3.9.0" +version = "3.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "apeye" }, @@ -3502,9 +3532,9 @@ dependencies = [ { name = "tabulate" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/32/e10c272614a1f4d84b680007bd45f9b77db3262ee6c3c61a0e27932a55b7/sphinx_toolbox-3.9.0.tar.gz", hash = "sha256:9ee0603b090762d6eed4d0ec9fa91445e3ef95d40a584af125308541c1bf7b8d", size = 114497, upload-time = "2025-02-26T13:32:07.253Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/2d/d916dc5a70bc7b006af8a31bba1a2767e99cdb884f3dfa47aa79a60cc1e9/sphinx_toolbox-3.10.0.tar.gz", hash = "sha256:6afea9ac9afabe76bd5bd4d2b01edfdad81d653a1a34768e776e6a56d5a6f572", size = 113656, upload-time = "2025-05-06T17:36:50.926Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/7e/9811c8cf0df10c2b6c9c72667837d731dd4f0dc0d0e68980938c8eb6f7f8/sphinx_toolbox-3.9.0-py3-none-any.whl", hash = "sha256:49024961c7791ad6e9dd39c611f89b5162550afa26ccad087be38388c3dd3c1e", size = 195429, upload-time = "2025-02-26T13:32:04.4Z" }, + { url = "https://files.pythonhosted.org/packages/12/ec/d09521ae2059fe89d8b59b2b34f5a1713b82a14e70a9a018fca8d3d514be/sphinx_toolbox-3.10.0-py3-none-any.whl", hash = "sha256:675e5978eaee31adf21701054fa75bacf820459d56e93ac30ad01eaee047a6ef", size = 195622, upload-time = "2025-05-06T17:36:48.81Z" }, ] [[package]] @@ -3578,11 +3608,11 @@ wheels = [ [[package]] name = "sqlglot" -version = "26.16.4" +version = "26.17.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/38/90/e487ae7c3722896e9b6911ac95e472a0bf37069061fdd3f54181db00ec28/sqlglot-26.16.4.tar.gz", hash = "sha256:0de74266e4ab1286801c40640a8bd99f96c1ec0fc20681f3c55802f39ce4b3ec", size = 5355134, upload-time = "2025-05-02T01:28:55.707Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/86/461568bd63a43fd3c9d2dec42f9070905cd7b1a0a7e27cacfe91c2e386ff/sqlglot-26.17.1.tar.gz", hash = "sha256:518c649ff4ae9601e2f156758c21d3552db8a109872f1228e0f6e89d3712bf73", size = 5356122, upload-time = "2025-05-08T15:31:31.39Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/b3/f91be0e284bb221d5e52073e3ab73e788e9101d7f7e7561dd771daed7a81/sqlglot-26.16.4-py3-none-any.whl", hash = "sha256:dbff0ace2e21c9169182d6852b8f6eb56d86fc6477354abcb5bda7ab93292975", size = 460033, upload-time = "2025-05-02T01:28:52.589Z" }, + { url = "https://files.pythonhosted.org/packages/81/30/2b50dd8bc227cce28aa7cb4dfa8fc174d34d1b7fb65128055d308ab6af7a/sqlglot-26.17.1-py3-none-any.whl", hash = "sha256:8772f5c1d095a9600cfbe5bdd08bc345d84f875773735a6cbe6cd5abcfa43900", size = 460536, upload-time = "2025-05-08T15:31:28.33Z" }, ] [package.optional-dependencies] @@ -4157,7 +4187,8 @@ name = "uvicorn" version = "0.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -4168,16 +4199,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.30.0" +version = "20.31.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/e0/633e369b91bbc664df47dcb5454b6c7cf441e8f5b9d0c250ce9f0546401e/virtualenv-20.30.0.tar.gz", hash = "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8", size = 4346945, upload-time = "2025-03-31T16:33:29.185Z" } +sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/ed/3cfeb48175f0671ec430ede81f628f9fb2b1084c9064ca67ebe8c0ed6a05/virtualenv-20.30.0-py3-none-any.whl", hash = "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6", size = 4329461, upload-time = "2025-03-31T16:33:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" }, ] [[package]] From 203a283838e5df1e031186c620bd3f57a9182677 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Sun, 11 May 2025 19:46:27 +0000 Subject: [PATCH 06/11] remove old rules --- .rules | 84 ---------------------------------------------------------- 1 file changed, 84 deletions(-) delete mode 100644 .rules diff --git a/.rules b/.rules deleted file mode 100644 index d8533bb..0000000 --- a/.rules +++ /dev/null @@ -1,84 +0,0 @@ -# SQLSpec Development Guidelines - -## Naming Conventions - -- Private methods start with underscore: `_method_name` -- Configuration methods use "configure": `_configure_connection`, `_configure_pool` -- Connection callbacks use "on_connection_create" -- Configs follow the pattern `{DB}Config` (e.g. `DuckDBConfig`). If the database driver supports Sync and Async connections, use `{DB}SyncConfig` and `{DB}AsyncConfig` -- Each driver should export a type alias of that drivers Connection object (`DuckDBConnection: TypeAlias = DuckDBPyConnection`) -- Driver adapters follow pattern: `{DB}Driver` (e.g. `DuckDBDriver`). If the driver support Sync and Async connections, use `{DB}SyncDriver` and `{DB}AsyncDriver` -- Use Python 3.9+ type hints (this means `tuple` instead of `Tuple`, `dict` vs `Dict`, `list` vs `List`, etc) -- Never use `from __future__ import annotations`. Please stringify type quotes. -- Do not do needless variable assignments to make the linter satisfied. Simple cast or ignore instead of copying. - -## Base Protocol Structure - -- `DatabaseConfigProtocol` is the base for all configs -- Split connection creation into: - - `create_connection()` - public API - - `_create_connection()` - internal implementation - - `_configure_connection()` - post-creation setup - -## Connection Callback Pattern - -```python -on_connection_create: "Optional[Callable[[ConnectionT], Optional[ConnectionT]]]" = None -"""A callable to be called after the connection is created.""" - -def _configure_connection(self, connection: ConnectionT) -> ConnectionT: - """Configure a connection with the on_connection_create callback if set.""" - if self.on_connection_create is not None: - result = self.on_connection_create(connection) - if result is not None: - return result - return connection -``` - -## Config Class Structure - -- Sync/Async variants: - - `NoPoolSyncConfig` - - `NoPoolAsyncConfig` - - `SyncDatabaseConfig` - - `AsyncDatabaseConfig` -- All must implement: - - `create_connection()` - - `_create_connection()` - - `_configure_connection()` - -## Driver Adapter Structure - -- Inherit from appropriate base: - - `SyncDriverAdapterProtocol` - - `AsyncDriverAdapterProtocol` -- Common attributes: - - `connection: ConnectionT` - - `dialect: str` - - `__supports_arrow__: ClassVar[bool]` - -## Type Hints - -- Use `ConnectionT` for connection types -- Use `PoolT` for pool types -- Use `DriverT` for driver types -- Use `ModelDTOT` for model types -- Use `StatementParameterType` for query parameters - -## Error Handling - -- Use `NotFoundError` for missing results -- Use `check_not_found()` helper for result validation - -## SQL Processing - -- Use `_process_sql_params()` for SQL and parameter processing -- Use `SQLStatement` for SQL validation and formatting - -## Testing Requirements - -- Test both sync and async paths -- Test with and without connection pooling -- Test connection callbacks -- Test error cases -- Test type safety From df86b32b39aaefb6b228a917abb0f119956d2a1f Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Sun, 11 May 2025 22:38:34 +0000 Subject: [PATCH 07/11] feat: updates --- sqlspec/extensions/litestar/plugin.py | 30 +++-- sqlspec/filters.py | 3 +- sqlspec/mixins.py | 154 +++++++++++++++++++++++++- sqlspec/utils/sync_tools.py | 37 +++++++ 4 files changed, 209 insertions(+), 15 deletions(-) diff --git a/sqlspec/extensions/litestar/plugin.py b/sqlspec/extensions/litestar/plugin.py index 53e72a0..e408759 100644 --- a/sqlspec/extensions/litestar/plugin.py +++ b/sqlspec/extensions/litestar/plugin.py @@ -70,18 +70,24 @@ def on_app_init(self, app_config: "AppConfig") -> "AppConfig": The updated :class:`AppConfig <.config.app.AppConfig>` instance. """ self._validate_dependency_keys() - app_config.signature_types.extend( - [ - SQLSpec, - ConnectionT, - PoolT, - DriverT, - DatabaseConfig, - DatabaseConfigProtocol, - SyncConfigT, - AsyncConfigT, - ] - ) + + def store_sqlspec_in_state() -> None: + app_config.state.sqlspec = self + + app_config.on_startup.append(store_sqlspec_in_state) + + # Register types for injection + app_config.signature_types.extend([ + SQLSpec, + ConnectionT, + PoolT, + DriverT, + DatabaseConfig, + DatabaseConfigProtocol, + SyncConfigT, + AsyncConfigT, + ]) + for c in self._plugin_configs: c.annotation = self.add_config(c.config) app_config.signature_types.append(c.annotation) diff --git a/sqlspec/filters.py b/sqlspec/filters.py index 62d3c3f..ecc0843 100644 --- a/sqlspec/filters.py +++ b/sqlspec/filters.py @@ -32,6 +32,7 @@ class StatementFilter(Protocol): """Protocol for filters that can be appended to a statement.""" + @abstractmethod def append_to_statement(self, statement: SQLStatement) -> SQLStatement: """Append the filter to the statement. @@ -41,7 +42,7 @@ def append_to_statement(self, statement: SQLStatement) -> SQLStatement: Returns: The modified statement. """ - return statement + raise NotImplementedError @dataclass diff --git a/sqlspec/mixins.py b/sqlspec/mixins.py index 067bb5a..3823970 100644 --- a/sqlspec/mixins.py +++ b/sqlspec/mixins.py @@ -1,17 +1,37 @@ +import datetime from abc import abstractmethod +from collections.abc import Sequence +from enum import Enum +from functools import partial +from pathlib import Path, PurePath from typing import ( TYPE_CHECKING, Any, + Callable, ClassVar, Generic, Optional, + Union, + cast, + overload, ) +from uuid import UUID from sqlglot import parse_one from sqlglot.dialects.dialect import DialectType -from sqlspec.exceptions import SQLConversionError, SQLParsingError -from sqlspec.typing import ConnectionT, StatementParameterType +from sqlspec.exceptions import SQLConversionError, SQLParsingError, SQLSpecError +from sqlspec.typing import ( + ConnectionT, + ModelDTOT, + ModelT, + StatementParameterType, + convert, + get_type_adapter, + is_dataclass, + is_msgspec_struct, + is_pydantic_model, +) if TYPE_CHECKING: from sqlspec.typing import ArrowTable @@ -154,3 +174,133 @@ def convert_to_dialect( except Exception as e: error_msg = f"Failed to convert SQL to {to_dialect}: {e!s}" raise SQLConversionError(error_msg) from e + + +_DEFAULT_TYPE_DECODERS = [ # pyright: ignore[reportUnknownVariableType] + (lambda x: x is UUID, lambda t, v: t(v.hex)), # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType] + (lambda x: x is datetime.datetime, lambda t, v: t(v.isoformat())), # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType] + (lambda x: x is datetime.date, lambda t, v: t(v.isoformat())), # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType] + (lambda x: x is datetime.time, lambda t, v: t(v.isoformat())), # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType] + (lambda x: x is Enum, lambda t, v: t(v.value)), # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType] +] + + +def _default_msgspec_deserializer( + target_type: Any, + value: Any, + type_decoders: "Union[Sequence[tuple[Callable[[Any], bool], Callable[[Any, Any], Any]]], None]" = None, +) -> Any: # pragma: no cover + """Transform values non-natively supported by ``msgspec`` + + Args: + target_type: Encountered type + value: Value to coerce + type_decoders: Optional sequence of type decoders + + Raises: + TypeError: If the value cannot be coerced to the target type + + Returns: + A ``msgspec``-supported type + """ + + if isinstance(value, target_type): + return value + + if type_decoders: + for predicate, decoder in type_decoders: + if predicate(target_type): + return decoder(target_type, value) + + if issubclass(target_type, (Path, PurePath, UUID)): + return target_type(value) + + try: + return target_type(value) + except Exception as e: + msg = f"Unsupported type: {type(value)!r}" + raise TypeError(msg) from e + + +class ResultConverter: + """Simple mixin to help convert to dictionary or list of dictionaries to specified schema type. + + Single objects are transformed to the supplied schema type, and lists of objects are transformed into a list of the supplied schema type. + + Args: + data: A database model instance or row mapping. + Type: :class:`~sqlspec.typing.ModelDictT` + + Returns: + The converted schema object. + """ + + @overload + @staticmethod + def to_schema(data: "ModelT", *, schema_type: None = None) -> "ModelT": ... + @overload + @staticmethod + def to_schema(data: "dict[str, Any]", *, schema_type: "type[ModelDTOT]") -> "ModelDTOT": ... + @overload + @staticmethod + def to_schema(data: "Sequence[ModelT]", *, schema_type: None = None) -> "list[ModelT]": ... + @overload + @staticmethod + def to_schema(data: "Sequence[dict[str, Any]]", *, schema_type: "type[ModelDTOT]") -> "list[ModelDTOT]": ... + + @staticmethod + def to_schema( + data: "Union[ModelT, Sequence[ModelT], dict[str, Any], Sequence[dict[str, Any]], ModelDTOT, Sequence[ModelDTOT]]", + *, + schema_type: "Optional[type[ModelDTOT]]" = None, + ) -> "Union[ModelT, list[ModelT], ModelDTOT, list[ModelDTOT]]": + if schema_type is None: + if not isinstance(data, Sequence): + return cast("ModelT", data) + return cast("list[ModelT]", data) + if is_dataclass(schema_type): + if not isinstance(data, Sequence): + # data is assumed to be dict[str, Any] as per the method's overloads + return cast("ModelDTOT", schema_type(**data)) # type: ignore[operator] + # data is assumed to be Sequence[dict[str, Any]] + return cast("list[ModelDTOT]", [schema_type(**item) for item in data]) # type: ignore[operator] + if is_msgspec_struct(schema_type): + if not isinstance(data, Sequence): + return cast( + "ModelDTOT", + convert( + obj=data, + type=schema_type, + from_attributes=True, + dec_hook=partial( + _default_msgspec_deserializer, + type_decoders=_DEFAULT_TYPE_DECODERS, + ), + ), + ) + return cast( + "list[ModelDTOT]", + convert( + obj=data, + type=list[schema_type], # type: ignore[valid-type] + from_attributes=True, + dec_hook=partial( + _default_msgspec_deserializer, + type_decoders=_DEFAULT_TYPE_DECODERS, + ), + ), + ) + + if schema_type is not None and is_pydantic_model(schema_type): + if not isinstance(data, Sequence): + return cast( + "ModelDTOT", + get_type_adapter(schema_type).validate_python(data, from_attributes=True), # pyright: ignore + ) + return cast( + "list[ModelDTOT]", + get_type_adapter(list[schema_type]).validate_python(data, from_attributes=True), # type: ignore[valid-type] # pyright: ignore[reportUnknownArgumentType] + ) + + msg = "`schema_type` should be a valid Dataclass, Pydantic model or Msgspec struct" + raise SQLSpecError(msg) diff --git a/sqlspec/utils/sync_tools.py b/sqlspec/utils/sync_tools.py index a95132d..06dc570 100644 --- a/sqlspec/utils/sync_tools.py +++ b/sqlspec/utils/sync_tools.py @@ -235,3 +235,40 @@ def with_ensure_async_( if isinstance(obj, AbstractContextManager): return cast("AbstractAsyncContextManager[T]", _ContextManagerWrapper(obj)) return obj + + +class NoValue: + """A fake "Empty class""" + + +async def get_next(iterable: Any, default: Any = NoValue, *args: Any) -> Any: # pragma: no cover + """Return the next item from an async iterator. + + In Python <3.10, `anext` is not available. This function is a drop-in replacement. + + This function will return the next value form an async iterable. If the + iterable is empty the StopAsyncIteration will be propagated. However, if + a default value is given as a second argument the exception is silenced and + the default value is returned instead. + + Args: + iterable: An async iterable. + default: An optional default value to return if the iterable is empty. + *args: The remaining args + Return: + The next value of the iterable. + + Raises: + StopAsyncIteration: The iterable given is not async. + + + """ + has_default = bool(not isinstance(default, NoValue)) + try: + return await iterable.__anext__() + + except StopAsyncIteration as exc: + if has_default: + return default + + raise StopAsyncIteration from exc From 104915c37e4bb0de4a8ea3d4d697c576f1672bff Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Mon, 12 May 2025 01:18:11 +0000 Subject: [PATCH 08/11] feat: implement corrections to the litestar plugin --- pyproject.toml | 4 + sqlspec/adapters/psycopg/driver.py | 208 ++++----- sqlspec/base.py | 119 ++---- sqlspec/extensions/litestar/__init__.py | 15 +- sqlspec/extensions/litestar/config.py | 21 +- sqlspec/extensions/litestar/handlers.py | 159 +++---- sqlspec/extensions/litestar/plugin.py | 31 +- sqlspec/extensions/litestar/providers.py | 521 +++++++++++++++++++++++ sqlspec/filters.py | 16 +- sqlspec/utils/__init__.py | 4 +- sqlspec/utils/singleton.py | 32 ++ sqlspec/utils/text.py | 99 +++-- tests/unit/test_utils/test_text.py | 43 +- uv.lock | 122 +++--- 14 files changed, 961 insertions(+), 433 deletions(-) create mode 100644 sqlspec/extensions/litestar/providers.py create mode 100644 sqlspec/utils/singleton.py diff --git a/pyproject.toml b/pyproject.toml index 1a8b100..d7c2739 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -249,6 +249,10 @@ module = [ "pyarrow.*", ] +[[tool.mypy.overrides]] +disable_error_code = "ignore-without-code" +module = "sqlspec.extensions.litestar.providers" + [tool.pyright] disableBytesTypePromotions = true exclude = ["**/node_modules", "**/__pycache__", ".venv", "tools", "docs"] diff --git a/sqlspec/adapters/psycopg/driver.py b/sqlspec/adapters/psycopg/driver.py index 8d6cbcd..2d6d34e 100644 --- a/sqlspec/adapters/psycopg/driver.py +++ b/sqlspec/adapters/psycopg/driver.py @@ -1,14 +1,15 @@ import logging import re from contextlib import asynccontextmanager, contextmanager -from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +from typing import TYPE_CHECKING, Any, Optional, Union, overload from psycopg import AsyncConnection, Connection from psycopg.rows import dict_row from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError -from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.filters import StatementFilter +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement from sqlspec.typing import is_dict @@ -38,6 +39,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: StatementFilter, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters using SQLStatement with dialect support. @@ -45,7 +47,8 @@ def _process_sql_params( Args: sql: The SQL statement to process. parameters: The parameters to bind to the statement. - **kwargs: Additional keyword arguments (including filters). + *filters: Statement filters to apply. + **kwargs: Additional keyword arguments. Raises: ParameterStyleMismatchError: If the parameter style is mismatched. @@ -54,10 +57,10 @@ def _process_sql_params( A tuple of (sql, parameters) ready for execution. """ statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + + # Apply all statement filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) processed_sql, processed_params, _ = statement.process() @@ -112,10 +115,9 @@ def _with_cursor(connection: "PsycopgSyncConnection") -> "Generator[Any, None, N @overload def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -123,20 +125,18 @@ def select( @overload def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Sequence[ModelDTOT]": ... def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, schema_type: "Optional[type[ModelDTOT]]" = None, connection: "Optional[PsycopgSyncConnection]" = None, **kwargs: Any, @@ -147,24 +147,22 @@ def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) results = cursor.fetchall() if not results: return [] - if schema_type is not None: - return [cast("ModelDTOT", schema_type(**row)) for row in results] # pyright: ignore[reportUnknownArgumentType] - return [cast("dict[str,Any]", row) for row in results] # pyright: ignore[reportUnknownArgumentType] + # Use ResultConverter for batch conversion + return ResultConverter.to_schema(results, schema_type=schema_type) @overload def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -172,20 +170,18 @@ def select_one( @overload def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -196,22 +192,21 @@ def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) row = cursor.fetchone() row = self.check_not_found(row) - if schema_type is not None: - return cast("ModelDTOT", schema_type(**cast("dict[str,Any]", row))) - return cast("dict[str,Any]", row) + + # Use ResultConverter for single row conversion + return ResultConverter.to_schema(row, schema_type=schema_type) @overload def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -219,20 +214,18 @@ def select_one_or_none( @overload def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Optional[ModelDTOT]": ... def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -243,23 +236,22 @@ def select_one_or_none( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) row = cursor.fetchone() if row is None: return None - if schema_type is not None: - return cast("ModelDTOT", schema_type(**cast("dict[str,Any]", row))) - return cast("dict[str,Any]", row) + + # Use ResultConverter for single row conversion + return ResultConverter.to_schema(row, schema_type=schema_type) @overload def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -267,20 +259,18 @@ def select_value( @overload def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "T": ... def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -291,7 +281,7 @@ def select_value( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) row = cursor.fetchone() @@ -305,10 +295,9 @@ def select_value( @overload def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -316,20 +305,18 @@ def select_value_or_none( @overload def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "Optional[T]": ... def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -340,7 +327,7 @@ def select_value_or_none( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) row = cursor.fetchone() @@ -355,10 +342,9 @@ def select_value_or_none( def insert_update_delete( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, **kwargs: Any, ) -> int: @@ -368,7 +354,7 @@ def insert_update_delete( The number of rows affected by the operation. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) return getattr(cursor, "rowcount", -1) # pyright: ignore[reportUnknownMemberType] @@ -376,10 +362,9 @@ def insert_update_delete( @overload def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -387,20 +372,18 @@ def insert_update_delete_returning( @overload def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -411,7 +394,7 @@ def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) result = cursor.fetchone() @@ -419,16 +402,13 @@ def insert_update_delete_returning( if result is None: return None - if schema_type is not None: - return cast("ModelDTOT", schema_type(**result)) # pyright: ignore[reportUnknownArgumentType] - return cast("dict[str, Any]", result) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + # Use ResultConverter for single row conversion + return ResultConverter.to_schema(result, schema_type=schema_type) def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgSyncConnection]" = None, **kwargs: Any, ) -> str: @@ -469,10 +449,9 @@ async def _with_cursor(connection: "PsycopgAsyncConnection") -> "AsyncGenerator[ @overload async def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -480,20 +459,18 @@ async def select( @overload async def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Sequence[ModelDTOT]": ... async def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, schema_type: "Optional[type[ModelDTOT]]" = None, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, @@ -504,24 +481,22 @@ async def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) results = await cursor.fetchall() if not results: return [] - if schema_type is not None: - return [cast("ModelDTOT", schema_type(**row)) for row in results] # pyright: ignore[reportUnknownArgumentType] - return [cast("dict[str,Any]", row) for row in results] # pyright: ignore[reportUnknownArgumentType] + # Use ResultConverter for batch conversion + return ResultConverter.to_schema(results, schema_type=schema_type) @overload async def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -529,20 +504,18 @@ async def select_one( @overload async def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... async def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -553,22 +526,21 @@ async def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() row = self.check_not_found(row) - if schema_type is not None: - return cast("ModelDTOT", schema_type(**cast("dict[str,Any]", row))) - return cast("dict[str,Any]", row) + + # Use ResultConverter for single row conversion + return ResultConverter.to_schema(row, schema_type=schema_type) @overload async def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -576,20 +548,18 @@ async def select_one_or_none( @overload async def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Optional[ModelDTOT]": ... async def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, schema_type: "Optional[type[ModelDTOT]]" = None, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, @@ -600,23 +570,22 @@ async def select_one_or_none( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() if row is None: return None - if schema_type is not None: - return cast("ModelDTOT", schema_type(**cast("dict[str,Any]", row))) - return cast("dict[str,Any]", row) + + # Use ResultConverter for single row conversion + return ResultConverter.to_schema(row, schema_type=schema_type) @overload async def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -624,20 +593,18 @@ async def select_value( @overload async def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "T": ... async def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -648,7 +615,7 @@ async def select_value( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() @@ -662,10 +629,9 @@ async def select_value( @overload async def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -673,20 +639,18 @@ async def select_value_or_none( @overload async def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "Optional[T]": ... async def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -697,7 +661,7 @@ async def select_value_or_none( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) row = await cursor.fetchone() @@ -712,10 +676,9 @@ async def select_value_or_none( async def insert_update_delete( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, ) -> int: @@ -725,7 +688,7 @@ async def insert_update_delete( The number of rows affected by the operation. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) return getattr(cursor, "rowcount", -1) # pyright: ignore[reportUnknownMemberType] @@ -733,10 +696,9 @@ async def insert_update_delete( @overload async def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -744,20 +706,18 @@ async def insert_update_delete_returning( @overload async def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... async def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -768,22 +728,20 @@ async def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() if result is None: return None - if schema_type is not None: - return cast("ModelDTOT", schema_type(**result)) # pyright: ignore[reportUnknownArgumentType] - return cast("dict[str, Any]", result) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + + # Use ResultConverter for single row conversion + return ResultConverter.to_schema(result, schema_type=schema_type) async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, ) -> str: diff --git a/sqlspec/base.py b/sqlspec/base.py index 1c752ac..7abcd79 100644 --- a/sqlspec/base.py +++ b/sqlspec/base.py @@ -19,6 +19,7 @@ ) from sqlspec.exceptions import NotFoundError +from sqlspec.filters import StatementFilter from sqlspec.statement import SQLStatement from sqlspec.typing import ConnectionT, ModelDTOT, PoolT, StatementParameterType, T from sqlspec.utils.sync_tools import ensure_async_ @@ -562,10 +563,9 @@ def __init__(self, connection: "ConnectionT", **kwargs: Any) -> None: @abstractmethod def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -575,10 +575,9 @@ def select( @abstractmethod def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -587,10 +586,9 @@ def select( @abstractmethod def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -600,10 +598,9 @@ def select( @abstractmethod def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -613,10 +610,9 @@ def select_one( @abstractmethod def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -625,10 +621,9 @@ def select_one( @abstractmethod def select_one( self, + *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -638,10 +633,9 @@ def select_one( @abstractmethod def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -651,10 +645,9 @@ def select_one_or_none( @abstractmethod def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -663,10 +656,9 @@ def select_one_or_none( @abstractmethod def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -676,10 +668,9 @@ def select_one_or_none( @abstractmethod def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -689,10 +680,9 @@ def select_value( @abstractmethod def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -701,10 +691,9 @@ def select_value( @abstractmethod def select_value( self, + *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, schema_type: Optional[type[T]] = None, **kwargs: Any, @@ -714,10 +703,9 @@ def select_value( @abstractmethod def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -727,10 +715,9 @@ def select_value_or_none( @abstractmethod def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -739,10 +726,9 @@ def select_value_or_none( @abstractmethod def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, schema_type: Optional[type[T]] = None, **kwargs: Any, @@ -751,10 +737,9 @@ def select_value_or_none( @abstractmethod def insert_update_delete( self, + *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, **kwargs: Any, ) -> int: ... @@ -763,10 +748,9 @@ def insert_update_delete( @abstractmethod def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -776,10 +760,9 @@ def insert_update_delete_returning( @abstractmethod def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -788,10 +771,9 @@ def insert_update_delete_returning( @abstractmethod def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -802,8 +784,6 @@ def execute_script( self, sql: str, parameters: Optional[StatementParameterType] = None, - /, - *, connection: Optional[ConnectionT] = None, **kwargs: Any, ) -> str: ... @@ -819,10 +799,9 @@ def __init__(self, connection: "ConnectionT") -> None: @abstractmethod async def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -832,10 +811,9 @@ async def select( @abstractmethod async def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -844,10 +822,9 @@ async def select( @abstractmethod async def select( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -857,10 +834,9 @@ async def select( @abstractmethod async def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -870,10 +846,9 @@ async def select_one( @abstractmethod async def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -882,10 +857,9 @@ async def select_one( @abstractmethod async def select_one( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -895,10 +869,9 @@ async def select_one( @abstractmethod async def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -908,10 +881,9 @@ async def select_one_or_none( @abstractmethod async def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -920,10 +892,9 @@ async def select_one_or_none( @abstractmethod async def select_one_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -933,10 +904,9 @@ async def select_one_or_none( @abstractmethod async def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -946,10 +916,9 @@ async def select_value( @abstractmethod async def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -958,10 +927,9 @@ async def select_value( @abstractmethod async def select_value( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -971,10 +939,9 @@ async def select_value( @abstractmethod async def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -984,10 +951,9 @@ async def select_value_or_none( @abstractmethod async def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -996,10 +962,9 @@ async def select_value_or_none( @abstractmethod async def select_value_or_none( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -1008,10 +973,9 @@ async def select_value_or_none( @abstractmethod async def insert_update_delete( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, **kwargs: Any, ) -> int: ... @@ -1020,10 +984,9 @@ async def insert_update_delete( @abstractmethod async def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -1033,10 +996,9 @@ async def insert_update_delete_returning( @abstractmethod async def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -1045,10 +1007,9 @@ async def insert_update_delete_returning( @abstractmethod async def insert_update_delete_returning( self, + *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -1059,8 +1020,6 @@ async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[ConnectionT]" = None, **kwargs: Any, ) -> str: ... diff --git a/sqlspec/extensions/litestar/__init__.py b/sqlspec/extensions/litestar/__init__.py index 581d846..285a310 100644 --- a/sqlspec/extensions/litestar/__init__.py +++ b/sqlspec/extensions/litestar/__init__.py @@ -1,19 +1,10 @@ +from sqlspec.extensions.litestar import handlers, providers from sqlspec.extensions.litestar.config import DatabaseConfig -from sqlspec.extensions.litestar.handlers import ( - autocommit_handler_maker, - connection_provider_maker, - lifespan_handler_maker, - manual_handler_maker, - pool_provider_maker, -) from sqlspec.extensions.litestar.plugin import SQLSpec __all__ = ( "DatabaseConfig", "SQLSpec", - "autocommit_handler_maker", - "connection_provider_maker", - "lifespan_handler_maker", - "manual_handler_maker", - "pool_provider_maker", + "handlers", + "providers", ) diff --git a/sqlspec/extensions/litestar/config.py b/sqlspec/extensions/litestar/config.py index 85e6d4f..bb7e0da 100644 --- a/sqlspec/extensions/litestar/config.py +++ b/sqlspec/extensions/litestar/config.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Callable, Literal, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, Union from sqlspec.exceptions import ImproperConfigurationError from sqlspec.extensions.litestar.handlers import ( @@ -12,7 +12,7 @@ ) if TYPE_CHECKING: - from collections.abc import Awaitable + from collections.abc import AsyncGenerator, Awaitable from contextlib import AbstractAsyncContextManager from litestar import Litestar @@ -29,6 +29,15 @@ DEFAULT_POOL_KEY = "db_pool" DEFAULT_SESSION_KEY = "db_session" +__all__ = ( + "DEFAULT_COMMIT_MODE", + "DEFAULT_CONNECTION_KEY", + "DEFAULT_POOL_KEY", + "DEFAULT_SESSION_KEY", + "CommitMode", + "DatabaseConfig", +) + @dataclass class DatabaseConfig: @@ -39,9 +48,11 @@ class DatabaseConfig: commit_mode: "CommitMode" = field(default=DEFAULT_COMMIT_MODE) extra_commit_statuses: "Optional[set[int]]" = field(default=None) extra_rollback_statuses: "Optional[set[int]]" = field(default=None) - connection_provider: "Callable[[State,Scope], Awaitable[ConnectionT]]" = field(init=False, repr=False, hash=False) # pyright: ignore[reportGeneralTypeIssues] + connection_provider: "Callable[[State, Scope], AsyncGenerator[ConnectionT, None]]" = field( # pyright: ignore[reportGeneralTypeIssues] + init=False, repr=False, hash=False + ) pool_provider: "Callable[[State,Scope], Awaitable[PoolT]]" = field(init=False, repr=False, hash=False) # pyright: ignore[reportGeneralTypeIssues] - session_provider: "Callable[[State,Scope], Awaitable[DriverT]]" = field(init=False, repr=False, hash=False) # pyright: ignore[reportGeneralTypeIssues] + session_provider: "Callable[[Any], AsyncGenerator[DriverT, None]]" = field(init=False, repr=False, hash=False) # pyright: ignore[reportGeneralTypeIssues] before_send_handler: "BeforeMessageSendHookHandler" = field(init=False, repr=False, hash=False) lifespan_handler: "Callable[[Litestar], AbstractAsyncContextManager[None]]" = field( init=False, @@ -79,5 +90,5 @@ def __post_init__(self) -> None: ) self.pool_provider = pool_provider_maker(config=self.config, pool_key=self.pool_key) self.session_provider = session_provider_maker( - session_key=self.session_key, connection_key=self.connection_key, pool_key=self.pool_key, config=self.config + config=self.config, connection_dependency_key=self.connection_key ) diff --git a/sqlspec/extensions/litestar/handlers.py b/sqlspec/extensions/litestar/handlers.py index 2de5652..8526712 100644 --- a/sqlspec/extensions/litestar/handlers.py +++ b/sqlspec/extensions/litestar/handlers.py @@ -1,4 +1,8 @@ +# ruff: noqa: PLC2801 import contextlib +import inspect +from collections.abc import AsyncGenerator +from contextlib import AbstractAsyncContextManager from typing import TYPE_CHECKING, Any, Callable, Optional, cast from litestar.constants import HTTP_DISCONNECT, HTTP_RESPONSE_START, WEBSOCKET_CLOSE, WEBSOCKET_DISCONNECT @@ -12,8 +16,7 @@ from sqlspec.utils.sync_tools import ensure_async_ if TYPE_CHECKING: - from collections.abc import AsyncGenerator, Awaitable, Coroutine - from contextlib import AbstractAsyncContextManager + from collections.abc import Awaitable, Coroutine from litestar import Litestar from litestar.datastructures.state import State @@ -26,6 +29,16 @@ SESSION_TERMINUS_ASGI_EVENTS = {HTTP_RESPONSE_START, HTTP_DISCONNECT, WEBSOCKET_DISCONNECT, WEBSOCKET_CLOSE} """ASGI events that terminate a session scope.""" +__all__ = ( + "SESSION_TERMINUS_ASGI_EVENTS", + "autocommit_handler_maker", + "connection_provider_maker", + "lifespan_handler_maker", + "manual_handler_maker", + "pool_provider_maker", + "session_provider_maker", +) + def manual_handler_maker(connection_scope_key: str) -> "Callable[[Message, Scope], Coroutine[Any, Any, None]]": """Set up the handler to close the connection. @@ -46,7 +59,8 @@ async def handler(message: "Message", scope: "Scope") -> None: """ connection = get_sqlspec_scope_state(scope, connection_scope_key) if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: - await ensure_async_(connection.close)() + if hasattr(connection, "close") and callable(connection.close): + await ensure_async_(connection.close)() delete_sqlspec_scope_state(scope, connection_scope_key) return handler @@ -97,12 +111,14 @@ async def handler(message: "Message", scope: "Scope") -> None: if (message["status"] in commit_range or message["status"] in extra_commit_statuses) and message[ "status" ] not in extra_rollback_statuses: - await ensure_async_(connection.commit)() - else: + if hasattr(connection, "commit") and callable(connection.commit): + await ensure_async_(connection.commit)() + elif hasattr(connection, "rollback") and callable(connection.rollback): await ensure_async_(connection.rollback)() finally: if connection and message["type"] in SESSION_TERMINUS_ASGI_EVENTS: - await ensure_async_(connection.close)() + if hasattr(connection, "close") and callable(connection.close): + await ensure_async_(connection.close)() delete_sqlspec_scope_state(scope, connection_scope_key) return handler @@ -162,7 +178,7 @@ def pool_provider_maker( The generated pool provider. """ - async def provide_pool(state: "State", scope: "Scope") -> "PoolT": # pylint: disable=unused-argument + async def provide_pool(state: "State", scope: "Scope") -> "PoolT": """Provides the database pool from `app.state`. Args: @@ -192,103 +208,64 @@ async def provide_pool(state: "State", scope: "Scope") -> "PoolT": # pylint: di def connection_provider_maker( - connection_key: str, # Key for storing connection in request scope - pool_key: str, # Key for retrieving pool from app state - config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", # Needed for acquire_connection_from_pool -) -> "Callable[[State, Scope], Awaitable[ConnectionT]]": - """Build the connection provider to inject a database connection acquired from the pool. - - Args: - connection_key: The key to store the acquired connection in the ASGI scope for reuse - within the same request. - pool_key: The key used to retrieve the connection pool from `app.state`. - config: The database configuration object, expected to have a method - for acquiring connections from a pool instance. - - Returns: - The generated connection provider. - """ - - async def provide_connection(state: "State", scope: "Scope") -> "ConnectionT": - """Provides a database connection from the application pool. - - A connection is acquired from the pool and stored in the request scope - to be reused if the dependency is requested multiple times in the same request. - The `before_send` handler is responsible for closing this connection (returning it to the pool). + config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", + pool_key: str, + connection_key: str, +) -> "Callable[[State, Scope], AsyncGenerator[ConnectionT, None]]": + async def provide_connection(state: "State", scope: "Scope") -> "AsyncGenerator[ConnectionT, None]": + db_pool = state.get(pool_key) + if db_pool is None: + msg = f"Database pool with key '{pool_key}' not found. Cannot create a connection." + raise ImproperConfigurationError(msg) - Args: - state: The Litestar application State object. - scope: The ASGI scope. + connection_cm = config.provide_connection(db_pool) - Returns: - A database connection. + if not isinstance(connection_cm, AbstractAsyncContextManager): + conn_instance: ConnectionT + if hasattr(connection_cm, "__await__"): + conn_instance = await cast("Awaitable[ConnectionT]", connection_cm) + else: + conn_instance = cast("ConnectionT", connection_cm) + set_sqlspec_scope_state(scope, connection_key, conn_instance) + yield conn_instance + return - Raises: - ImproperConfigurationError: If the pool is not found or cannot provide a connection. - """ - # Check if a connection is already stored in the current request's scope - connection = get_sqlspec_scope_state(scope, connection_key) - if connection is None: - # Get the application-level pool from app.state - db_pool = state.get(pool_key) - if db_pool is None: - msg = f"Database pool with key '{pool_key}' not found in application state. Cannot create a connection." - raise ImproperConfigurationError(msg) - - connection = await ensure_async_(config.provide_connection)(db_pool) - set_sqlspec_scope_state(scope, connection_key, connection) - return cast("ConnectionT", connection) + entered_connection: Optional[ConnectionT] = None + try: + entered_connection = await connection_cm.__aenter__() + set_sqlspec_scope_state(scope, connection_key, entered_connection) + yield entered_connection + finally: + if entered_connection is not None: + await connection_cm.__aexit__(None, None, None) + delete_sqlspec_scope_state(scope, connection_key) # Optional: clear from scope return provide_connection def session_provider_maker( - config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", session_key: str, connection_key: str, pool_key: str -) -> "Callable[[State, Scope], Awaitable[DriverT]]": - """Build the session provider (DriverT instance) using a pooled connection. - - Args: - session_key: The key to store the DriverT instance in the ASGI scope. - connection_key: The key for the underlying ConnectionT in the ASGI scope. This - ensures the same connection instance is used and managed. - pool_key: The key to retrieve the connection pool from `app.state`. - config: The database configuration object. + config: "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]", connection_dependency_key: str +) -> "Callable[[Any], AsyncGenerator[DriverT, None]]": + async def provide_session(*args: Any, **kwargs: Any) -> "AsyncGenerator[DriverT, None]": + yield cast("DriverT", config.driver_type(connection=args[0] if args else kwargs.get(connection_dependency_key))) # pyright: ignore - Returns: - The generated session provider. - """ + conn_type_annotation = config.connection_type - async def provide_session(state: "State", scope: "Scope") -> "DriverT": - """Provides a DriverT instance (session) wrapping a pooled database connection. + db_conn_param = inspect.Parameter( + name=connection_dependency_key, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=conn_type_annotation + ) - The underlying connection is managed (acquired and stored in scope) similarly - to `provide_connection`. + provider_signature = inspect.Signature( + parameters=[db_conn_param], + return_annotation=AsyncGenerator[config.driver_type, None], # type: ignore[name-defined] + ) - Args: - state: The Litestar application State object. - scope: The ASGI scope. + provide_session.__signature__ = provider_signature # type: ignore[attr-defined] - Returns: - A DriverT instance. + if not hasattr(provide_session, "__annotations__") or provide_session.__annotations__ is None: + provide_session.__annotations__ = {} - Raises: - ImproperConfigurationError: If the pool is not found or cannot provide a connection. - """ - session = get_sqlspec_scope_state(scope, session_key) - if session is None: - # Get or create the underlying connection for this request scope - connection = get_sqlspec_scope_state(scope, connection_key) - if connection is None: - db_pool = state.get(pool_key) - if db_pool is None: - msg = f"Database pool with key '{pool_key}' not found in application state while trying to create a session." - raise ImproperConfigurationError(msg) - connection = await ensure_async_(config.provide_session)(db_pool) - set_sqlspec_scope_state(scope, connection_key, connection) - - # Create the driver/session instance with the (pooled) connection - session = config.driver_type(connection=connection) # pyright: ignore[reportCallIssue] - set_sqlspec_scope_state(scope, session_key, session) - return cast("DriverT", session) + provide_session.__annotations__[connection_dependency_key] = conn_type_annotation + provide_session.__annotations__["return"] = config.driver_type return provide_session diff --git a/sqlspec/extensions/litestar/plugin.py b/sqlspec/extensions/litestar/plugin.py index e408759..29be411 100644 --- a/sqlspec/extensions/litestar/plugin.py +++ b/sqlspec/extensions/litestar/plugin.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Any, Literal, Union +from typing import TYPE_CHECKING, Any, Union from litestar.di import Provide from litestar.plugins import InitPluginProtocol @@ -19,13 +19,6 @@ from litestar.config.app import AppConfig -CommitMode = Literal["manual", "autocommit", "autocommit_include_redirect"] -DEFAULT_COMMIT_MODE: CommitMode = "manual" -DEFAULT_CONNECTION_KEY = "db_connection" -DEFAULT_POOL_KEY = "db_pool" -DEFAULT_SESSION_KEY = "db_session" - - class SQLSpec(InitPluginProtocol, SQLSpecBase): """SQLSpec plugin.""" @@ -77,16 +70,18 @@ def store_sqlspec_in_state() -> None: app_config.on_startup.append(store_sqlspec_in_state) # Register types for injection - app_config.signature_types.extend([ - SQLSpec, - ConnectionT, - PoolT, - DriverT, - DatabaseConfig, - DatabaseConfigProtocol, - SyncConfigT, - AsyncConfigT, - ]) + app_config.signature_types.extend( + [ + SQLSpec, + ConnectionT, + PoolT, + DriverT, + DatabaseConfig, + DatabaseConfigProtocol, + SyncConfigT, + AsyncConfigT, + ] + ) for c in self._plugin_configs: c.annotation = self.add_config(c.config) diff --git a/sqlspec/extensions/litestar/providers.py b/sqlspec/extensions/litestar/providers.py new file mode 100644 index 0000000..bf99009 --- /dev/null +++ b/sqlspec/extensions/litestar/providers.py @@ -0,0 +1,521 @@ +# ruff: noqa: B008 +"""Application dependency providers generators. + +This module contains functions to create dependency providers for services and filters. + +You should not have modify this module very often and should only be invoked under normal usage. +""" + +import datetime +import inspect +from collections.abc import Callable +from typing import ( + Any, + Literal, + NamedTuple, + Optional, + TypedDict, + Union, + cast, +) +from uuid import UUID + +from litestar.di import Provide +from litestar.params import Dependency, Parameter +from typing_extensions import NotRequired + +from sqlspec.filters import ( + BeforeAfter, + CollectionFilter, + FilterTypes, + LimitOffset, + NotInCollectionFilter, + OrderBy, + SearchFilter, +) +from sqlspec.utils.singleton import SingletonMeta +from sqlspec.utils.text import camelize + +__all__ = ( + "DEPENDENCY_DEFAULTS", + "BooleanOrNone", + "DTorNone", + "DependencyDefaults", + "FieldNameType", + "FilterConfig", + "HashableType", + "HashableValue", + "IntOrNone", + "SortOrder", + "SortOrderOrNone", + "StringOrNone", + "UuidOrNone", + "create_filter_dependencies", + "dep_cache", +) + +DTorNone = Optional[datetime.datetime] +StringOrNone = Optional[str] +UuidOrNone = Optional[UUID] +IntOrNone = Optional[int] +BooleanOrNone = Optional[bool] +SortOrder = Literal["asc", "desc"] +SortOrderOrNone = Optional[SortOrder] +HashableValue = Union[str, int, float, bool, None] +HashableType = Union[HashableValue, tuple[Any, ...], tuple[tuple[str, Any], ...], tuple[HashableValue, ...]] + + +class DependencyDefaults: + FILTERS_DEPENDENCY_KEY: str = "filters" + """Key for the filters dependency.""" + CREATED_FILTER_DEPENDENCY_KEY: str = "created_filter" + """Key for the created filter dependency.""" + ID_FILTER_DEPENDENCY_KEY: str = "id_filter" + """Key for the id filter dependency.""" + LIMIT_OFFSET_FILTER_DEPENDENCY_KEY: str = "limit_offset_filter" + """Key for the limit offset dependency.""" + UPDATED_FILTER_DEPENDENCY_KEY: str = "updated_filter" + """Key for the updated filter dependency.""" + ORDER_BY_FILTER_DEPENDENCY_KEY: str = "order_by_filter" + """Key for the order by dependency.""" + SEARCH_FILTER_DEPENDENCY_KEY: str = "search_filter" + """Key for the search filter dependency.""" + DEFAULT_PAGINATION_SIZE: int = 20 + """Default pagination size.""" + + +DEPENDENCY_DEFAULTS = DependencyDefaults() + + +class FieldNameType(NamedTuple): + """Type for field name and associated type information. + + This allows for specifying both the field name and the expected type for filter values. + """ + + name: str + """Name of the field to filter on.""" + type_hint: type[Any] = str + """Type of the filter value. Defaults to str.""" + + +class FilterConfig(TypedDict): + """Configuration for generating dynamic filters.""" + + id_filter: NotRequired[type[Union[UUID, int, str]]] + """Indicates that the id filter should be enabled. When set, the type specified will be used for the :class:`CollectionFilter`.""" + id_field: NotRequired[str] + """The field on the model that stored the primary key or identifier.""" + sort_field: NotRequired[str] + """The default field to use for the sort filter.""" + sort_order: NotRequired[SortOrder] + """The default order to use for the sort filter.""" + pagination_type: NotRequired[Literal["limit_offset"]] + """When set, pagination is enabled based on the type specified.""" + pagination_size: NotRequired[int] + """The size of the pagination. Defaults to `DEFAULT_PAGINATION_SIZE`.""" + search: NotRequired[Union[str, set[str], list[str]]] + """Fields to enable search on. Can be a comma-separated string or a set of field names.""" + search_ignore_case: NotRequired[bool] + """When set, search is case insensitive by default.""" + created_at: NotRequired[bool] + """When set, created_at filter is enabled.""" + updated_at: NotRequired[bool] + """When set, updated_at filter is enabled.""" + not_in_fields: NotRequired[Union[FieldNameType, set[FieldNameType], list[Union[str, FieldNameType]]]] + """Fields that support not-in collection filters. Can be a single field or a set of fields with type information.""" + in_fields: NotRequired[Union[FieldNameType, set[FieldNameType], list[Union[str, FieldNameType]]]] + """Fields that support in-collection filters. Can be a single field or a set of fields with type information.""" + + +class DependencyCache(metaclass=SingletonMeta): + """Simple dependency cache for the application. This is used to help memoize dependencies that are generated dynamically.""" + + def __init__(self) -> None: + self.dependencies: dict[Union[int, str], dict[str, Provide]] = {} + + def add_dependencies(self, key: Union[int, str], dependencies: dict[str, Provide]) -> None: + self.dependencies[key] = dependencies + + def get_dependencies(self, key: Union[int, str]) -> Optional[dict[str, Provide]]: + return self.dependencies.get(key) + + +dep_cache = DependencyCache() + + +def create_filter_dependencies( + config: FilterConfig, dep_defaults: DependencyDefaults = DEPENDENCY_DEFAULTS +) -> dict[str, Provide]: + """Create a dependency provider for the combined filter function. + + Args: + config: FilterConfig instance with desired settings. + dep_defaults: Dependency defaults to use for the filter dependencies + + Returns: + A dependency provider function for the combined filter function. + """ + cache_key = hash(_make_hashable(config)) + deps = dep_cache.get_dependencies(cache_key) + if deps is not None: + return deps + deps = _create_statement_filters(config, dep_defaults) + dep_cache.add_dependencies(cache_key, deps) + return deps + + +def _make_hashable(value: Any) -> HashableType: + """Convert a value into a hashable type. + + This function converts any value into a hashable type by: + - Converting dictionaries to sorted tuples of (key, value) pairs + - Converting lists and sets to sorted tuples + - Preserving primitive types (str, int, float, bool, None) + - Converting any other type to its string representation + + Args: + value: Any value that needs to be made hashable. + + Returns: + A hashable version of the value. + """ + if isinstance(value, dict): + # Convert dict to tuple of tuples with sorted keys + items = [] + for k in sorted(value.keys()): # pyright: ignore + v = value[k] # pyright: ignore + items.append((str(k), _make_hashable(v))) # pyright: ignore + return tuple(items) # pyright: ignore + if isinstance(value, (list, set)): + hashable_items = [_make_hashable(item) for item in value] # pyright: ignore + filtered_items = [item for item in hashable_items if item is not None] # pyright: ignore + return tuple(sorted(filtered_items, key=str)) + if isinstance(value, (str, int, float, bool, type(None))): + return value + return str(value) + + +def _create_statement_filters( + config: FilterConfig, dep_defaults: DependencyDefaults = DEPENDENCY_DEFAULTS +) -> dict[str, Provide]: + """Create filter dependencies based on configuration. + + Args: + config (FilterConfig): Configuration dictionary specifying which filters to enable + dep_defaults (DependencyDefaults): Dependency defaults to use for the filter dependencies + + Returns: + dict[str, Provide]: Dictionary of filter provider functions + """ + filters: dict[str, Provide] = {} + + if config.get("id_filter", False): + + def provide_id_filter( # pyright: ignore[reportUnknownParameterType] + ids: Optional[list[str]] = Parameter(query="ids", default=None, required=False), + ) -> CollectionFilter: # pyright: ignore[reportMissingTypeArgument] + return CollectionFilter(field_name=config.get("id_field", "id"), values=ids) + + filters[dep_defaults.ID_FILTER_DEPENDENCY_KEY] = Provide(provide_id_filter, sync_to_thread=False) # pyright: ignore[reportUnknownArgumentType] + + if config.get("created_at", False): + + def provide_created_filter( + before: DTorNone = Parameter(query="createdBefore", default=None, required=False), + after: DTorNone = Parameter(query="createdAfter", default=None, required=False), + ) -> BeforeAfter: + return BeforeAfter("created_at", before, after) + + filters[dep_defaults.CREATED_FILTER_DEPENDENCY_KEY] = Provide(provide_created_filter, sync_to_thread=False) + + if config.get("updated_at", False): + + def provide_updated_filter( + before: DTorNone = Parameter(query="updatedBefore", default=None, required=False), + after: DTorNone = Parameter(query="updatedAfter", default=None, required=False), + ) -> BeforeAfter: + return BeforeAfter("updated_at", before, after) + + filters[dep_defaults.UPDATED_FILTER_DEPENDENCY_KEY] = Provide(provide_updated_filter, sync_to_thread=False) + + if config.get("pagination_type") == "limit_offset": + + def provide_limit_offset_pagination( + current_page: int = Parameter(ge=1, query="currentPage", default=1, required=False), + page_size: int = Parameter( + query="pageSize", + ge=1, + default=config.get("pagination_size", dep_defaults.DEFAULT_PAGINATION_SIZE), + required=False, + ), + ) -> LimitOffset: + return LimitOffset(page_size, page_size * (current_page - 1)) + + filters[dep_defaults.LIMIT_OFFSET_FILTER_DEPENDENCY_KEY] = Provide( + provide_limit_offset_pagination, sync_to_thread=False + ) + + if search_fields := config.get("search"): + + def provide_search_filter( + search_string: StringOrNone = Parameter( + title="Field to search", + query="searchString", + default=None, + required=False, + ), + ignore_case: BooleanOrNone = Parameter( + title="Search should be case sensitive", + query="searchIgnoreCase", + default=config.get("search_ignore_case", False), + required=False, + ), + ) -> SearchFilter: + # Handle both string and set input types for search fields + field_names = set(search_fields.split(",")) if isinstance(search_fields, str) else set(search_fields) + + return SearchFilter( + field_name=field_names, + value=search_string, # type: ignore[arg-type] + ignore_case=ignore_case or False, + ) + + filters[dep_defaults.SEARCH_FILTER_DEPENDENCY_KEY] = Provide(provide_search_filter, sync_to_thread=False) + + if sort_field := config.get("sort_field"): + + def provide_order_by( + field_name: StringOrNone = Parameter( + title="Order by field", + query="orderBy", + default=sort_field, + required=False, + ), + sort_order: SortOrderOrNone = Parameter( + title="Field to search", + query="sortOrder", + default=config.get("sort_order", "desc"), + required=False, + ), + ) -> OrderBy: + return OrderBy(field_name=field_name, sort_order=sort_order) # type: ignore[arg-type] + + filters[dep_defaults.ORDER_BY_FILTER_DEPENDENCY_KEY] = Provide(provide_order_by, sync_to_thread=False) + + # Add not_in filter providers + if not_in_fields := config.get("not_in_fields"): + # Get all field names, handling both strings and FieldNameType objects + not_in_fields = {not_in_fields} if isinstance(not_in_fields, (str, FieldNameType)) else not_in_fields + + for field_def in not_in_fields: + field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def + + def create_not_in_filter_provider( # pyright: ignore + field_name: FieldNameType, + ) -> Callable[..., Optional[NotInCollectionFilter[field_def.type_hint]]]: # type: ignore + def provide_not_in_filter( # pyright: ignore + values: Optional[list[field_name.type_hint]] = Parameter( # type: ignore + query=camelize(f"{field_name.name}_not_in"), default=None, required=False + ), + ) -> Optional[NotInCollectionFilter[field_name.type_hint]]: # type: ignore + return ( + NotInCollectionFilter[field_name.type_hint](field_name=field_name.name, values=values) # type: ignore + if values + else None + ) + + return provide_not_in_filter # pyright: ignore + + provider = create_not_in_filter_provider(field_def) # pyright: ignore + filters[f"{field_def.name}_not_in_filter"] = Provide(provider, sync_to_thread=False) # pyright: ignore + + # Add in filter providers + if in_fields := config.get("in_fields"): + # Get all field names, handling both strings and FieldNameType objects + in_fields = {in_fields} if isinstance(in_fields, (str, FieldNameType)) else in_fields + + for field_def in in_fields: + field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def + + def create_in_filter_provider( # pyright: ignore + field_name: FieldNameType, + ) -> Callable[..., Optional[CollectionFilter[field_def.type_hint]]]: # type: ignore # pyright: ignore + def provide_in_filter( # pyright: ignore + values: Optional[list[field_name.type_hint]] = Parameter( # type: ignore # pyright: ignore + query=camelize(f"{field_name.name}_in"), default=None, required=False + ), + ) -> Optional[CollectionFilter[field_name.type_hint]]: # type: ignore # pyright: ignore + return ( + CollectionFilter[field_name.type_hint](field_name=field_name.name, values=values) # type: ignore # pyright: ignore + if values + else None + ) + + return provide_in_filter # pyright: ignore + + provider = create_in_filter_provider(field_def) # type: ignore + filters[f"{field_def.name}_in_filter"] = Provide(provider, sync_to_thread=False) # pyright: ignore + + if filters: + filters[dep_defaults.FILTERS_DEPENDENCY_KEY] = Provide( + _create_filter_aggregate_function(config), sync_to_thread=False + ) + + return filters + + +def _create_filter_aggregate_function(config: FilterConfig) -> Callable[..., list[FilterTypes]]: # noqa: PLR0915 + """Create a filter function based on the provided configuration. + + Args: + config: The filter configuration. + + Returns: + A function that returns a list of filters based on the configuration. + """ + + parameters: dict[str, inspect.Parameter] = {} + annotations: dict[str, Any] = {} + + # Build parameters based on config + if cls := config.get("id_filter"): + parameters["id_filter"] = inspect.Parameter( + name="id_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=CollectionFilter[cls], # type: ignore[valid-type] + ) + annotations["id_filter"] = CollectionFilter[cls] # type: ignore[valid-type] + + if config.get("created_at"): + parameters["created_filter"] = inspect.Parameter( + name="created_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=BeforeAfter, + ) + annotations["created_filter"] = BeforeAfter + + if config.get("updated_at"): + parameters["updated_filter"] = inspect.Parameter( + name="updated_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=BeforeAfter, + ) + annotations["updated_filter"] = BeforeAfter + + if config.get("search"): + parameters["search_filter"] = inspect.Parameter( + name="search_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=SearchFilter, + ) + annotations["search_filter"] = SearchFilter + + if config.get("pagination_type") == "limit_offset": + parameters["limit_offset_filter"] = inspect.Parameter( + name="limit_offset_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=LimitOffset, + ) + annotations["limit_offset_filter"] = LimitOffset + + if config.get("sort_field"): + parameters["order_by_filter"] = inspect.Parameter( + name="order_by_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=OrderBy, + ) + annotations["order_by_filter"] = OrderBy + + # Add parameters for not_in filters + if not_in_fields := config.get("not_in_fields"): + for field_def in not_in_fields: + field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def + parameters[f"{field_def.name}_not_in_filter"] = inspect.Parameter( + name=f"{field_def.name}_not_in_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=NotInCollectionFilter[field_def.type_hint], # type: ignore + ) + annotations[f"{field_def.name}_not_in_filter"] = NotInCollectionFilter[field_def.type_hint] # type: ignore + + # Add parameters for in filters + if in_fields := config.get("in_fields"): + for field_def in in_fields: + field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def + parameters[f"{field_def.name}_in_filter"] = inspect.Parameter( + name=f"{field_def.name}_in_filter", + kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, + default=Dependency(skip_validation=True), + annotation=CollectionFilter[field_def.type_hint], # type: ignore + ) + annotations[f"{field_def.name}_in_filter"] = CollectionFilter[field_def.type_hint] # type: ignore + + def provide_filters(**kwargs: FilterTypes) -> list[FilterTypes]: + """Provide filter dependencies based on configuration. + + Args: + **kwargs: Filter parameters dynamically provided based on configuration. + + Returns: + list[FilterTypes]: List of configured filters. + """ + filters: list[FilterTypes] = [] + if id_filter := kwargs.get("id_filter"): + filters.append(id_filter) + if created_filter := kwargs.get("created_filter"): + filters.append(created_filter) + if limit_offset := kwargs.get("limit_offset_filter"): + filters.append(limit_offset) + if updated_filter := kwargs.get("updated_filter"): + filters.append(updated_filter) + if ( + (search_filter := cast("Optional[SearchFilter]", kwargs.get("search_filter"))) + and search_filter is not None # pyright: ignore[reportUnnecessaryComparison] + and search_filter.field_name is not None # pyright: ignore[reportUnnecessaryComparison] + and search_filter.value is not None # pyright: ignore[reportUnnecessaryComparison] + ): + filters.append(search_filter) + if ( + (order_by := cast("Optional[OrderBy]", kwargs.get("order_by_filter"))) + and order_by is not None # pyright: ignore[reportUnnecessaryComparison] + and order_by.field_name is not None # pyright: ignore[reportUnnecessaryComparison] + ): + filters.append(order_by) + + # Add not_in filters + if not_in_fields := config.get("not_in_fields"): + # Get all field names, handling both strings and FieldNameType objects + not_in_fields = {not_in_fields} if isinstance(not_in_fields, (str, FieldNameType)) else not_in_fields + for field_def in not_in_fields: + field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def + filter_ = kwargs.get(f"{field_def.name}_not_in_filter") + if filter_ is not None: + filters.append(filter_) + + # Add in filters + if in_fields := config.get("in_fields"): + # Get all field names, handling both strings and FieldNameType objects + in_fields = {in_fields} if isinstance(in_fields, (str, FieldNameType)) else in_fields + for field_def in in_fields: + field_def = FieldNameType(name=field_def, type_hint=str) if isinstance(field_def, str) else field_def + filter_ = kwargs.get(f"{field_def.name}_in_filter") + if filter_ is not None: + filters.append(filter_) + return filters + + # Set both signature and annotations + provide_filters.__signature__ = inspect.Signature( # type: ignore + parameters=list(parameters.values()), + return_annotation=list[FilterTypes], + ) + provide_filters.__annotations__ = annotations + provide_filters.__annotations__["return"] = list[FilterTypes] + + return provide_filters diff --git a/sqlspec/filters.py b/sqlspec/filters.py index ecc0843..3655f40 100644 --- a/sqlspec/filters.py +++ b/sqlspec/filters.py @@ -7,13 +7,14 @@ from typing import Any, Generic, Literal, Optional, Protocol, Union, cast from sqlglot import exp -from typing_extensions import TypeVar +from typing_extensions import TypeAlias, TypeVar from sqlspec.statement import SQLStatement __all__ = ( "BeforeAfter", "CollectionFilter", + "FilterTypes", "InAnyFilter", "LimitOffset", "NotInCollectionFilter", @@ -314,3 +315,16 @@ def apply_filter(statement: SQLStatement, filter_obj: StatementFilter) -> SQLSta The modified statement. """ return filter_obj.append_to_statement(statement) + + +FilterTypes: TypeAlias = Union[ + BeforeAfter, + OnBeforeAfter, + CollectionFilter[Any], + LimitOffset, + OrderBy, + SearchFilter, + NotInCollectionFilter[Any], + NotInSearchFilter, +] +"""Aggregate type alias of the types supported for collection filtering.""" diff --git a/sqlspec/utils/__init__.py b/sqlspec/utils/__init__.py index a8edc4e..623d721 100644 --- a/sqlspec/utils/__init__.py +++ b/sqlspec/utils/__init__.py @@ -1,3 +1,3 @@ -from sqlspec.utils import deprecation, fixtures, module_loader, sync_tools, text +from sqlspec.utils import deprecation, fixtures, module_loader, singleton, sync_tools, text -__all__ = ("deprecation", "fixtures", "module_loader", "sync_tools", "text") +__all__ = ("deprecation", "fixtures", "module_loader", "singleton", "sync_tools", "text") diff --git a/sqlspec/utils/singleton.py b/sqlspec/utils/singleton.py new file mode 100644 index 0000000..af33992 --- /dev/null +++ b/sqlspec/utils/singleton.py @@ -0,0 +1,32 @@ +from typing import Any, TypeVar + +_T = TypeVar("_T") + + +class SingletonMeta(type): + """Metaclass for singleton pattern.""" + + # We store instances keyed by the class type + _instances: dict[type, object] = {} + + def __call__(cls: type[_T], *args: Any, **kwargs: Any) -> _T: + """Call method for the singleton metaclass. + + Args: + cls: The class being instantiated. + *args: Positional arguments for the class constructor. + **kwargs: Keyword arguments for the class constructor. + + Returns: + The singleton instance of the class. + """ + # Use SingletonMeta._instances to access the class attribute + if cls not in SingletonMeta._instances: # pyright: ignore[reportUnnecessaryContains] + # Create the instance using super().__call__ which calls the class's __new__ and __init__ + instance = super().__call__(*args, **kwargs) # type: ignore[misc] + SingletonMeta._instances[cls] = instance + + # Return the cached instance. We cast here because the dictionary stores `object`, + # but we know it's of type _T for the given cls key. + # Mypy might need an ignore here depending on configuration, but pyright should handle it. + return SingletonMeta._instances[cls] # type: ignore[return-value] diff --git a/sqlspec/utils/text.py b/sqlspec/utils/text.py index e624d47..8676a52 100644 --- a/sqlspec/utils/text.py +++ b/sqlspec/utils/text.py @@ -1,30 +1,53 @@ """General utility functions.""" -import logging import re import unicodedata -from typing import Any, Optional, Union - -import sqlglot +from functools import lru_cache +from typing import Optional + +# Compiled regex for slugify +_SLUGIFY_REMOVE_INVALID_CHARS_RE = re.compile(r"[^\w\s-]") +_SLUGIFY_COLLAPSE_SEPARATORS_RE = re.compile(r"[-\s]+") + +# Compiled regex for snake_case +# Handles sequences like "HTTPRequest" -> "HTTP_Request" or "SSLError" -> "SSL_Error" +_SNAKE_CASE_RE_ACRONYM_SEQUENCE = re.compile(r"([A-Z\d]+)([A-Z][a-z])") +# Handles transitions like "camelCase" -> "camel_Case" or "PascalCase" -> "Pascal_Case" (partially) +_SNAKE_CASE_RE_LOWER_UPPER_TRANSITION = re.compile(r"([a-z\d])([A-Z])") +# Replaces hyphens, spaces, and dots with a single underscore +_SNAKE_CASE_RE_REPLACE_SEP = re.compile(r"[-\s.]+") +# Cleans up multiple consecutive underscores +_SNAKE_CASE_RE_CLEAN_MULTIPLE_UNDERSCORE = re.compile(r"__+") __all__ = ( - "bind_parameters", + "camelize", "check_email", "slugify", + "snake_case", ) -logger = logging.getLogger("sqlspec") - def check_email(email: str) -> str: - """Validate an email.""" + """Validate an email. + + Very simple email validation. + + Args: + email (str): The email to validate. + + Raises: + ValueError: If the email is invalid. + + Returns: + str: The validated email. + """ if "@" not in email: msg = "Invalid email!" raise ValueError(msg) return email.lower() -def slugify(value: str, allow_unicode: bool = False, separator: "Optional[str]" = None) -> str: +def slugify(value: str, allow_unicode: bool = False, separator: Optional[str] = None) -> str: """Slugify. Convert to ASCII if ``allow_unicode`` is ``False``. Convert spaces or repeated @@ -45,39 +68,41 @@ def slugify(value: str, allow_unicode: bool = False, separator: "Optional[str]" value = unicodedata.normalize("NFKC", value) else: value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii") - value = re.sub(r"[^\w\s-]", "", value.lower()) + value = _SLUGIFY_REMOVE_INVALID_CHARS_RE.sub("", value.lower()) if separator is not None: - return re.sub(r"[-\s]+", "-", value).strip("-_").replace("-", separator) - return re.sub(r"[-\s]+", "-", value).strip("-_") + return _SLUGIFY_COLLAPSE_SEPARATORS_RE.sub("-", value).strip("-_").replace("-", separator) + return _SLUGIFY_COLLAPSE_SEPARATORS_RE.sub("-", value).strip("-_") + + +@lru_cache(maxsize=100) +def camelize(string: str) -> str: + """Convert a string to camel case. + + Args: + string (str): The string to convert. + + Returns: + str: The converted string. + """ + return "".join(word if index == 0 else word.capitalize() for index, word in enumerate(string.split("_"))) + +@lru_cache(maxsize=100) +def snake_case(string: str) -> str: + """Convert a string to snake_case. -def bind_parameters( - sql: str, - parameters: Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]] = None, - dialect: str = "generic", -) -> tuple[str, Optional[Union[dict[str, Any], list[Any], tuple[Any, ...]]]]: - """Bind parameters to SQL using SQLGlot with fallback to original SQL/params. + Handles CamelCase, PascalCase, strings with spaces, hyphens, or dots + as separators, and ensures single underscores. It also correctly + handles acronyms (e.g., "HTTPRequest" becomes "http_request"). Args: - sql: The SQL query string. - parameters: The parameters to bind (dict, list, tuple, or None). - dialect: The SQL dialect for parameter substitution. + string: The string to convert. Returns: - A tuple of (possibly rewritten SQL, parameters for driver). + The snake_case version of the string. """ - if not parameters: - return sql, None - - try: - # For named parameters (dict) - if isinstance(parameters, dict): - bound_sql = sqlglot.transpile(sql, args=parameters, write=dialect)[0] - return bound_sql, parameters # Keep dict for drivers that need it - except Exception as e: # noqa: BLE001 - msg = f"SQLGlot parameter binding failed: {e}. Using original SQL and parameters." - logger.debug(msg) - return sql, parameters - # For positional parameters (list/tuple), just return as is for now - # (could extend to support ? -> $1, $2, etc. if needed) - return sql, parameters + s = _SNAKE_CASE_RE_ACRONYM_SEQUENCE.sub(r"\1_\2", string) + s = _SNAKE_CASE_RE_LOWER_UPPER_TRANSITION.sub(r"\1_\2", s) + s = _SNAKE_CASE_RE_REPLACE_SEP.sub("_", s).lower() + s = _SNAKE_CASE_RE_CLEAN_MULTIPLE_UNDERSCORE.sub("_", s) + return s.strip("_") diff --git a/tests/unit/test_utils/test_text.py b/tests/unit/test_utils/test_text.py index d79d0a5..0dcb211 100644 --- a/tests/unit/test_utils/test_text.py +++ b/tests/unit/test_utils/test_text.py @@ -1,4 +1,4 @@ -from sqlspec.utils.text import check_email, slugify +from sqlspec.utils.text import check_email, slugify, snake_case def test_check_email() -> None: @@ -14,3 +14,44 @@ def test_slugify() -> None: expected_slug = "this-is-a-test" assert slugify(string) == expected_slug assert slugify(string, separator="_") == "this_is_a_test" + + +def test_snake_case() -> None: + """Test the snake_case function.""" + test_cases = { + "simpleString": "simple_string", + "SimpleString": "simple_string", + "SimpleStringWithCAPS": "simple_string_with_caps", + "HTTPRequest": "http_request", + "anotherHTTPRequest": "another_http_request", + "endsWithHTTPRequest": "ends_with_http_request", + "SSLError": "ssl_error", + "HTMLParser": "html_parser", + "MyCoolAPI": "my_cool_api", + "My_Cool_API": "my_cool_api", + "my-cool-api": "my_cool_api", + "my cool api": "my_cool_api", + "my.cool.api": "my_cool_api", + " leading and trailing spaces ": "leading_and_trailing_spaces", + "__leading_and_trailing_underscores__": "leading_and_trailing_underscores", + "--leading-and-trailing-hyphens--": "leading_and_trailing_hyphens", + "with__multiple___underscores": "with_multiple_underscores", + "with--multiple---hyphens": "with_multiple_hyphens", + "with..multiple...dots": "with_multiple_dots", + "stringWith1Number": "string_with1_number", + "stringWith123Numbers": "string_with123_numbers", + "123startsWithNumber": "123starts_with_number", + "word": "word", + "WORD": "word", + "A": "a", + "a": "a", + "": "", + "ComplexHTTPRequestWithNumber123AndMore": "complex_http_request_with_number123_and_more", + "AnotherExample_ForYou-Sir.Yes": "another_example_for_you_sir_yes", + "_Already_Snake_Case_": "already_snake_case", # existing underscores should be handled gracefully + "Already_Snake_Case": "already_snake_case", + "already_snake_case": "already_snake_case", + } + + for input_str, expected_output in test_cases.items(): + assert snake_case(input_str) == expected_output, f"Input: '{input_str}'" diff --git a/uv.lock b/uv.lock index 39bf641..66f4a53 100644 --- a/uv.lock +++ b/uv.lock @@ -2286,15 +2286,15 @@ wheels = [ [[package]] name = "psycopg" -version = "3.2.7" +version = "3.2.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fe/16/ca27b38762a630b70243f51eb6a728f903a17cddc4961626fa540577aba6/psycopg-3.2.7.tar.gz", hash = "sha256:9afa609c7ebf139827a38c0bf61be9c024a3ed743f56443de9d38e1efc260bf3", size = 157238, upload-time = "2025-04-30T13:05:22.867Z" } +sdist = { url = "https://files.pythonhosted.org/packages/46/62/2d36820f3bef9e3737f5c899c8bba6c6de6af513ed977150607e8a86b26d/psycopg-3.2.8.tar.gz", hash = "sha256:cc995d836841e400c4f615d8dea351dc39697ad29df84d428f9c38c8040222f8", size = 158089, upload-time = "2025-05-11T17:20:56.47Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/eb/6e32d259437125a17b0bc2624e06c86149c618501da1dcbc8539b2684f6f/psycopg-3.2.7-py3-none-any.whl", hash = "sha256:d39747d2d5b9658b69fa462ad21d31f1ba4a5722ad1d0cb952552bc0b4125451", size = 200028, upload-time = "2025-04-30T12:59:32.435Z" }, + { url = "https://files.pythonhosted.org/packages/16/3f/eda96f7010c7d6bc4e10fdbcaa66d3d0d38f1619591fb1abe0f822dea2ec/psycopg-3.2.8-py3-none-any.whl", hash = "sha256:0e960f1977d77de7f1ace4b54590f686b52c2f9ab1f61fff4141887fc711d9e7", size = 202705, upload-time = "2025-05-11T17:15:45.071Z" }, ] [package.optional-dependencies] @@ -2307,64 +2307,64 @@ pool = [ [[package]] name = "psycopg-binary" -version = "3.2.7" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/48/54/e0f97118c57b4c7a94bf5564b22ae1c69bfb348d9a3f1424c1fec24d3ff3/psycopg_binary-3.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:17ab2b4c2722138b7a6eb42d139ad8e5fed792574c1069f27abf8f8ebb0d7f75", size = 3869223, upload-time = "2025-04-30T12:59:37.739Z" }, - { url = "https://files.pythonhosted.org/packages/b9/7c/d261cd9468c2ac2cdc9db5f78ea5768284180d1215b056325e0275237ebb/psycopg_binary-3.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:063f5a56ccab2b9eef58f55437cff78c59c5562ebb5f7453ecd480f038b045dc", size = 3938929, upload-time = "2025-04-30T12:59:43.491Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ce/1f2f6dd4c4e97d01d1029bc20a15e7a2eaf067ee853b17bc18f90c4a7415/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70632c9687731c8d0c9c72fbb73893e82ba4a2cdc8ffdd4c5bbcef51cc9c6b16", size = 4523155, upload-time = "2025-04-30T12:59:48.508Z" }, - { url = "https://files.pythonhosted.org/packages/b4/54/3b33dda4f56cb98ec8801a947372bb9e683e02cbc4f07d2ca06ce596408d/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebca1fd4b59523e3127eba7257bf764e80cddd9444b7f0d2870210ffc80ac688", size = 4329574, upload-time = "2025-04-30T12:59:54.468Z" }, - { url = "https://files.pythonhosted.org/packages/19/6b/57fa8324cfbc1760c568f4f41388ca5e0c9723d942186eb2ce65c2c84e07/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f2371822bc0b35ad735298964d531f95e59cfa2d31b87408f7d63ae78173279c", size = 4577282, upload-time = "2025-04-30T13:00:01.814Z" }, - { url = "https://files.pythonhosted.org/packages/30/54/2214b379b5de17efb79b11daabae5f7327699368447b955f349d0ecd0c00/psycopg_binary-3.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b1cd14d99d358483c665355eebb650f5e76f2d41c942fe6d0836b0fe76fbf0", size = 4287541, upload-time = "2025-04-30T13:00:07.623Z" }, - { url = "https://files.pythonhosted.org/packages/36/bb/a30e8733e6e11b22c2cd79c3b3978ee2efa0cf1d9873a46b2beaacbbf2dc/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:82369aa7cfbff19d65182698ee542af75d90c27284201d718f54f7b52480f730", size = 3777464, upload-time = "2025-04-30T13:00:12.947Z" }, - { url = "https://files.pythonhosted.org/packages/50/8c/ba1fe5bce097e8407f747c290f07cd75ecc13be1cd54f362678d8dd46ee3/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:00ba447b23daaacd9391c6a7ee0781e0860af72d0742c4d261df07940d601e29", size = 3336810, upload-time = "2025-04-30T13:00:16.96Z" }, - { url = "https://files.pythonhosted.org/packages/a9/90/18792d169c3daa7edebd7e88b09a6ca8781d766288581f344a3cecfff2b5/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0ccff5f988345dad22146f165e4395b37b9f4f3e3dd42eedad6627e791a8c8b4", size = 3438709, upload-time = "2025-04-30T13:00:21.124Z" }, - { url = "https://files.pythonhosted.org/packages/15/1c/0abde469359ba2129a7a1e4418f7665836ea7b11d8cb5b4b61c97768a473/psycopg_binary-3.2.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82e9ee9943da44a08f737d80c9b3878f9d4916a947cf182cd183f81e825cc41d", size = 3496758, upload-time = "2025-04-30T13:00:26.064Z" }, - { url = "https://files.pythonhosted.org/packages/2f/fe/8e3f19e477da87e29cd938f2ca6b95d24df56bec507c8bbc90493f1aba6b/psycopg_binary-3.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:26b1b7e39fa5139f99cb02a186dfa447c41f7e55c0aebb5f2da6ddf5b6ec5b32", size = 2936268, upload-time = "2025-04-30T13:00:32.129Z" }, - { url = "https://files.pythonhosted.org/packages/ac/ef/ff0578e07d696bc0465c6c97399af416563944ffdbafb23f033bc6f38359/psycopg_binary-3.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d001950bcabb725e003609073b83678962e9308e0b194a5227d6758ba8d46e0", size = 3876901, upload-time = "2025-04-30T13:00:38.307Z" }, - { url = "https://files.pythonhosted.org/packages/e7/66/6095832dcd76bcee4f442bcb862f56d6be2c200304ee67497d892b1a4874/psycopg_binary-3.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57acabe70587b65471b9f42593ec9bb17d317118e0dbe92d7173f0a75939150a", size = 3943982, upload-time = "2025-04-30T13:00:42.476Z" }, - { url = "https://files.pythonhosted.org/packages/7f/d0/c2aa1de7700661b5c4a0c698db42b6c34f69f2fa0c51afa44c053421c55c/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93f3937f293a30310501204bf0833704283675a8819a395bea8e352a5abaee84", size = 4520576, upload-time = "2025-04-30T13:00:47.063Z" }, - { url = "https://files.pythonhosted.org/packages/90/b5/976fcd95b03056812a53bdf58bcdd361eac71163619d51160ce82fc118ce/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72a3fb7cd7da15157bf63792db7346dfe2a07e3bc6ff702c7e8a76719e6efca0", size = 4325008, upload-time = "2025-04-30T13:00:54.407Z" }, - { url = "https://files.pythonhosted.org/packages/15/25/363bce348face3f08ef9515f0c0d39e53202b90c37c54367e6606d926957/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0350ba9a14295b266fba83d5a691511bf4ceb5df863973b525230fd15fd483f2", size = 4581129, upload-time = "2025-04-30T13:01:00.164Z" }, - { url = "https://files.pythonhosted.org/packages/cd/f8/72b081b9691f15d05a4edbc0707de8b9e698e3e0583a69dd0e471cf7ec4f/psycopg_binary-3.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de12375a49e70a6ac52431aa92b9c2e4ca01fea4fa872b4cd31e19028e3095d7", size = 4282727, upload-time = "2025-04-30T13:01:04.316Z" }, - { url = "https://files.pythonhosted.org/packages/97/ac/bbd215f0df248cb1f6bec1d580f4b699ec7a1fd82434d651a1a5283fa676/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33bb035e6f9b4911291472d6b5386b283fc835b97d2b1dc57f2ff82f777cb9f2", size = 3775842, upload-time = "2025-04-30T13:01:07.913Z" }, - { url = "https://files.pythonhosted.org/packages/9b/42/f51e420919611ddde52741b5489ab268876887e3577667fce681946681b4/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ed59c833678b55932f78aa60e85691b40fd7d2058ad60ca369fc4f908218c688", size = 3331510, upload-time = "2025-04-30T13:01:11.517Z" }, - { url = "https://files.pythonhosted.org/packages/13/a2/0a6f6b5e6a7cadd7789801f6f93460dd9ef44007205d6e2ffb24e758fb78/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b404c1a091dd034254694ae56111c69f07d54419c5436366c5b3af2aac9dce04", size = 3435475, upload-time = "2025-04-30T13:01:16.446Z" }, - { url = "https://files.pythonhosted.org/packages/4f/c2/115d546c3f570792433aadf248602b8ab3efa27c2cbc8173c15ffd1af1e2/psycopg_binary-3.2.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:25a3527a26b7589434a3eb52ad32b1f67e1af034cb17bd36a77344896d54b403", size = 3495896, upload-time = "2025-04-30T13:01:21.958Z" }, - { url = "https://files.pythonhosted.org/packages/da/b9/7a15a72a38f99054de1e517285ceb1cb3a62d5d404557961c6f8efa9065b/psycopg_binary-3.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:f5a2ebd0772c059e521b70a826a11b962fcba465b001fd655ca6aba10dc9432d", size = 2939079, upload-time = "2025-04-30T13:01:27.446Z" }, - { url = "https://files.pythonhosted.org/packages/c9/f6/00d303cbf258fd0053d8cacbd92c3f73dffe34ba2050cf4d25d677ec70fe/psycopg_binary-3.2.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:76e55ec30b3947b921f267795ffd2f433c65fc8a41adc4939fd9ccfb0f5b0322", size = 3858585, upload-time = "2025-04-30T13:01:34.348Z" }, - { url = "https://files.pythonhosted.org/packages/dc/01/56c5ec8ca159de1e4f6e2bb4663c3f985162ccdc810e29e19727c2849ddd/psycopg_binary-3.2.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff4c97a04eeb11d54d4c8ca22459e2cca9a423e7f397c29ae311c6e7c784d49", size = 3940735, upload-time = "2025-04-30T13:01:38.396Z" }, - { url = "https://files.pythonhosted.org/packages/0d/46/92855fbe7150cdc0e5949430d457d07b89d187f884a611858e2b46166e39/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d1c97a7c57e83b55172b585702744cd6bdad37c7a18cabdf55ba1e5a66ce476", size = 4499775, upload-time = "2025-04-30T13:01:43.129Z" }, - { url = "https://files.pythonhosted.org/packages/0b/5a/e0bd9e2fc450e972cfdb028d7e6bf1b2eaeb36b8110078e54040472927e7/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b394542a8b0706102a86c7006978848cf1748f4191e0e0e32b1f814b63ae7d68", size = 4308131, upload-time = "2025-04-30T13:01:49.44Z" }, - { url = "https://files.pythonhosted.org/packages/fe/45/14935e3b022cd31666a05861c72fc3ce1b2ccf622771dd9f5220fa2a5149/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6a10440bc02ed3a0ac1cb2d61e117273ce20e3d103061452acc7ed2c9a89e53", size = 4548217, upload-time = "2025-04-30T13:01:55.133Z" }, - { url = "https://files.pythonhosted.org/packages/d5/57/1bcabf46f45c88fe767b24e3a9a4d15f1bd78195e17179b85975c62f42dc/psycopg_binary-3.2.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8eee57667fdd8a1cd8c4c2dc7350914267baf4d699690d44e439df9ae9148e7a", size = 4260744, upload-time = "2025-04-30T13:02:03.076Z" }, - { url = "https://files.pythonhosted.org/packages/19/b0/c2edd72c05a8a4b73712f4705de137107042466f96ad054454e0b35cf5fe/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fd35ddbbfbe3cbe00a2b578defc7365e5e047e4fa9b803659bd4e8c3962069e7", size = 3752306, upload-time = "2025-04-30T13:02:08.378Z" }, - { url = "https://files.pythonhosted.org/packages/ff/ef/4303e6b5cb48f3802fe85c779af6feb34b8fac371396284118f894cc39d8/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e7f1d2dc575b00d951317b788a2244fdfcdd1503221ebc7e479220f6e3414aa4", size = 3316919, upload-time = "2025-04-30T13:02:15.345Z" }, - { url = "https://files.pythonhosted.org/packages/fe/71/91ae71a868861c93f9d2ab0e38f0f63dda8b0e1db913a739c04df932f658/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:359b2056e1203010c0044c12a3f933d522c613d7ee280d84be3643458f416796", size = 3405507, upload-time = "2025-04-30T13:02:22.115Z" }, - { url = "https://files.pythonhosted.org/packages/37/dd/dc44e86396939625a704d2fdfb2ed081d24034fed33e657ca1e01363e6cc/psycopg_binary-3.2.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:532b5c8a9ec70173812fbba26bbd5cf57c0f1c680907d637ddbb1be15dbf89d7", size = 3472779, upload-time = "2025-04-30T13:02:28.149Z" }, - { url = "https://files.pythonhosted.org/packages/4a/b0/d305977dfb5fbd9194d7a77b6edde8ff6054376b3d10595855de4269dfec/psycopg_binary-3.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:47e9d09b4f898eaf46cd2b7433f9e6faa935246a9d8983b4f88f0a46809abbd2", size = 2926878, upload-time = "2025-04-30T13:02:32.248Z" }, - { url = "https://files.pythonhosted.org/packages/3f/c8/590d8ca19e66810f7943a5c325f18bd29be472d2fa1bbee93905623a26fa/psycopg_binary-3.2.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3b280862c623616e0ced03602c98b44f51ab8cdaaad31f6b3523a2a68b2f92a4", size = 3853314, upload-time = "2025-04-30T13:02:37.469Z" }, - { url = "https://files.pythonhosted.org/packages/38/18/af7db2c61d50f86f38ba6d7e5b6aff4d138b9238f5cb9d6c57b49e80eb21/psycopg_binary-3.2.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:add318f12dc2be4d8a817e70c38cfd23a2af80ff6f871089e63012b62bf96f00", size = 3937308, upload-time = "2025-04-30T13:02:45.584Z" }, - { url = "https://files.pythonhosted.org/packages/c4/a4/d483311c22d4ae7a31dd643926309c480a54252ecb27a8fba654dba1753b/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03994806e62e795b1b286c60bb5d23e1cc3982b06192e87ec4dff0a0f7c528e2", size = 4500116, upload-time = "2025-04-30T13:02:51.525Z" }, - { url = "https://files.pythonhosted.org/packages/82/03/7047b4247a578fe296510e10c1ebcdf42009f4c022f924f697a6145a1062/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77709be5dc45828ca06d9d87fa7b065720fb87b1aa3e72d44177562f1df50ad2", size = 4312005, upload-time = "2025-04-30T13:02:55.806Z" }, - { url = "https://files.pythonhosted.org/packages/5b/a4/28dec7beddea4a93089dfa4692124a057914f0e6f5164712f9ae7ee97a8b/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d959a17ac2f1ff87a191786f66ae452791fbe73cee7375f2dafd2696e605a9", size = 4548230, upload-time = "2025-04-30T13:03:00.174Z" }, - { url = "https://files.pythonhosted.org/packages/51/ac/4b7e86fec44c428f27f28d742c13568419cc3d2a2b4dcc1be9b266ee9123/psycopg_binary-3.2.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:239e24fa33c6213320da0aee72d541e4780adb21753fc692337043c235118cf1", size = 4262584, upload-time = "2025-04-30T13:03:05.347Z" }, - { url = "https://files.pythonhosted.org/packages/05/b6/814805218644a0865c529221cc3413adba25b0d80a7db5f3e50e25c539ce/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d31c0523e0294e008d9031f2f2034a010f043ae8c7af0589d614b0bf6ed6e6aa", size = 3755762, upload-time = "2025-04-30T13:03:10.112Z" }, - { url = "https://files.pythonhosted.org/packages/58/b8/efa94ca4aff949324a52bdf62a9518939375af3048b7d025620d0e385ef8/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a15c88f1695c8dc8b90625931fe86909c74f7770bad7312999ee6babb0143dcc", size = 3319679, upload-time = "2025-04-30T13:03:15.068Z" }, - { url = "https://files.pythonhosted.org/packages/0e/3f/dd3a912abaa4ff2816e9a1e90c775f33315278f7d01621e874f5b5e83ada/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3c02790afcc6d82d1b9d886d9323f955c5c998693966c4c1e6d0ff9a96276a1e", size = 3409378, upload-time = "2025-04-30T13:03:20.422Z" }, - { url = "https://files.pythonhosted.org/packages/35/44/1ee04f0eae2dd9a75cf519792e95a00d5c7eb91b8ec341e2660fd0b4a033/psycopg_binary-3.2.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1d2288a7f1d0dec1ccce50b4470751acb563689048752fdbf7a4a804df3a0e0d", size = 3475892, upload-time = "2025-04-30T13:03:25.686Z" }, - { url = "https://files.pythonhosted.org/packages/11/1e/5133e346f0138f13d04e38f4b3976dc92ab4a1d72fc18f1199552c0bde3c/psycopg_binary-3.2.7-cp313-cp313-win_amd64.whl", hash = "sha256:c3781beaffb33fce17d8f137b003ebd930a7148eab2a1f60628e86c3d67884ea", size = 2927499, upload-time = "2025-04-30T13:03:31.398Z" }, - { url = "https://files.pythonhosted.org/packages/b3/a4/43ed70fc7ca36a17baac3d812b7c9b5b163708331235fa4b5ea7ab4bb1b4/psycopg_binary-3.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:519d7d8f35c5392599a5f5ceb9ebaa50881024fb6ecd32ea55436c8e3cda27cc", size = 3870416, upload-time = "2025-04-30T13:04:22.813Z" }, - { url = "https://files.pythonhosted.org/packages/09/7e/fd89b01a076f179987d0d6ec597e3c01d33736f9106b1345a7e1251d540e/psycopg_binary-3.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef399143d63bd67febe92b923dc6bd56bc8a9c3581a68bc8982eed75963ad169", size = 3939850, upload-time = "2025-04-30T13:04:27.137Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f9/2612cbf05c2865129db4873159c7d1ae9cc5735da146c7d4cb89a45e7df5/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a34757170706c67be94b248db458d3602269828a067a84bdc536869d35fed5", size = 4523348, upload-time = "2025-04-30T13:04:32.338Z" }, - { url = "https://files.pythonhosted.org/packages/09/4f/cabb879a3c7c4e719c16da757f7c3f1d0e01e08a7d965008ba24559bb358/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05a7265e80b362b93af2dbea0cd8828e6cbbb6daea97f2b0b4f29e61bd34b2e3", size = 4331305, upload-time = "2025-04-30T13:04:39.88Z" }, - { url = "https://files.pythonhosted.org/packages/73/fa/e34932141000129db0a19f385f175f6e471af66cdf92edaf3147fc3d63e2/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2a9aa6ddfd6a8fb5756498ccb7a3a4f9cd87906d9e8ac36b69e116b7104b891", size = 4579977, upload-time = "2025-04-30T13:04:47.795Z" }, - { url = "https://files.pythonhosted.org/packages/c1/11/8b6ec2ed9503334d6753034dca2c5f4c47bc0051309003b8ac5c65daff7a/psycopg_binary-3.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69310b8dc1277556711f6818b75a92581ae6c3cd2ca3c9c0798caf15976a8562", size = 4287106, upload-time = "2025-04-30T13:04:55.152Z" }, - { url = "https://files.pythonhosted.org/packages/b8/e6/60a67000de1245a7274033a58092266ab4cdca6c35b28f4a1742b703c6c2/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:73349f876b7288200c576c5c14b29c5f3266fb30598c3723dc57cfe05adf3121", size = 3777676, upload-time = "2025-04-30T13:05:00.871Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f7/1edf068549ba02efa8e2ca09722aa3426b4904fbed5a199344d4b357f749/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a8d3c8df6eb652e8140b24941b4da8bd07bfa7564101e9dee496a28683f7c2f8", size = 3337577, upload-time = "2025-04-30T13:05:07.828Z" }, - { url = "https://files.pythonhosted.org/packages/19/df/d16f79797d64cc6a0846add5ea85a56272a3e0c815ab444397a96494001c/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2321b6edfb4ca38a3446d5e88abe9ce78c04fc616d05a598ffe7cc5e2535c1fc", size = 3439812, upload-time = "2025-04-30T13:05:13.598Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a7/7cfb9f9cd23097354bd721569480cf05840f51bdf6840051f54aca901143/psycopg_binary-3.2.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2cf25feb92dceb5739dd029a047664a02f5df25a5e086d577cae810daf6a302a", size = 3498268, upload-time = "2025-04-30T13:05:17.47Z" }, - { url = "https://files.pythonhosted.org/packages/c3/1d/91b47bea94fbe66a6d69a53f2ede2dfa1c2daa90dd6a6fa9d39251b841f0/psycopg_binary-3.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:ac0b823a0b199d36e0570d5d2a1154ae767073907496a2e436a236e388fc0c97", size = 2938028, upload-time = "2025-04-30T13:05:20.976Z" }, +version = "3.2.8" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/4e/f753d7b5a8a63e5884adde8a45e5a99be5c219ff4484761af923a0619b47/psycopg_binary-3.2.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0694548e1633c2ea819406c5bfd297bf1b4f6f8638dec0d639ab9764fdebcb2a", size = 4033084, upload-time = "2025-05-11T17:15:49.386Z" }, + { url = "https://files.pythonhosted.org/packages/af/d3/94c9509011244a0b5518c77caab7ff4f8c36d0ee66a6125ce06692a32b62/psycopg_binary-3.2.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:85851cdc18b514f80790f711a25406515b42f6b64e9a5d3940ae399e3b0e2c23", size = 4082142, upload-time = "2025-05-11T17:15:55.043Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a0/6e1e21777c6eb65bc0152671db707ac73068079706a2e1375265529aa942/psycopg_binary-3.2.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:040c2a768bd9ae572421ee5695a6299e08147dd44bc8ac514961323dc5c31a62", size = 4678993, upload-time = "2025-05-11T17:16:02.8Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6e/fc78d0fcc620c983bd6fcd41ba504c6513640cb11c3cec5f29f788768603/psycopg_binary-3.2.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdb5567e81374734539f7b7deb9d547271585ec42a7866ea06bffa58fa5cd5a", size = 4500118, upload-time = "2025-05-11T17:16:09.636Z" }, + { url = "https://files.pythonhosted.org/packages/c8/1c/a2325279cf4e085e8f09f1c0a1a405802406140b6125d2c960987f5265a0/psycopg_binary-3.2.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289d2575edc00391c4bf586048701638126f396a76db83f36463d1c2b3495aae", size = 4766984, upload-time = "2025-05-11T17:16:14.237Z" }, + { url = "https://files.pythonhosted.org/packages/db/b0/4311b96362c0451ca037a363db1bb3769f03b8ea5a0459b69f924eb786a7/psycopg_binary-3.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c3a3b330c44e01ee29b3b76ddbb86890fbaf7e4b2f9abd43220d050642edee3", size = 4461989, upload-time = "2025-05-11T17:16:18.015Z" }, + { url = "https://files.pythonhosted.org/packages/84/cc/f8ba7eddfa61460713c88130843da65fa5ecbe85108a4a5b4261cef01a38/psycopg_binary-3.2.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:814d533e6a8359c2962e28a36fad2698c15639716459fe1100e859b6173c3b6d", size = 3777949, upload-time = "2025-05-11T17:16:22.003Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9c/7398af2ad041fe278e0b98edcb2ee5dd176500ff24a51fd3f0296f29886a/psycopg_binary-3.2.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b67f78f75b033d8833ec40432c28610c275455e0172762919912a5e6b9db6366", size = 3337502, upload-time = "2025-05-11T17:16:25.996Z" }, + { url = "https://files.pythonhosted.org/packages/94/a0/308b4720c0b8d63ce96253f288d0ad7a36508d7d457d61ebb3ffaf3c494a/psycopg_binary-3.2.8-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b98f7dc1ed83889803d0df2d327c94c95a487b9976215c3e9adb0dbb7a220d76", size = 3440809, upload-time = "2025-05-11T17:16:30.095Z" }, + { url = "https://files.pythonhosted.org/packages/51/3e/1f16b908a903ac5adb3af4d3b2643cda334928bd530b8618df262d89baf2/psycopg_binary-3.2.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a9c54bd5d91c6e1cc1e6f9127f175ce3162d8435cf8d4715149598c9baab4ff5", size = 3497231, upload-time = "2025-05-11T17:16:34.39Z" }, + { url = "https://files.pythonhosted.org/packages/1e/d1/4e09eda60266ef96f5c8f061d43b413040bfcb469b715078c7b55d6d53fd/psycopg_binary-3.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:2aba18f57da97b96ea9a6663c8982038a9d4a47b1f94f004ffa9491bd7d21160", size = 3782900, upload-time = "2025-05-11T17:16:38.937Z" }, + { url = "https://files.pythonhosted.org/packages/31/40/87bbdef58f347b54241a9df97f4870cde4083e8611b0e9404af9ed2fbeb3/psycopg_binary-3.2.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:076bd384a0d8bb7a59514b0d62bb75b48f83955a32ebec408b08db0e51bb06e5", size = 4040776, upload-time = "2025-05-11T17:16:43.159Z" }, + { url = "https://files.pythonhosted.org/packages/f9/2b/c7927dc71f570a8d7da0b0582c8c8a937aaa154a62bae5119377a9532ba8/psycopg_binary-3.2.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f162a44ed7e06ed075cbc9dfda23850a7f702c44af4b62061e9c83430130ff36", size = 4087603, upload-time = "2025-05-11T17:16:47.151Z" }, + { url = "https://files.pythonhosted.org/packages/99/a7/34c8eb1762ab4e27321992febff0589f994dd50ef0f457bc9fa42573ecbc/psycopg_binary-3.2.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e450989848bb63315e1768e6c6026cfdf6f72450c3752ce9f6e307c1d62b8d", size = 4676528, upload-time = "2025-05-11T17:16:52.587Z" }, + { url = "https://files.pythonhosted.org/packages/91/b0/54e4175b4113d46c172ac7423c0270cae4f947456b69ec7ceba966869c92/psycopg_binary-3.2.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90c0f2c88578db2bbeea98cd10fcb6f635c0b5bdd23ae90a931716589094ed08", size = 4495671, upload-time = "2025-05-11T17:16:57.58Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ab/1cb155dd800584547f0b282ecb0db16dd96e309b1d6e9fee28ecf18a7886/psycopg_binary-3.2.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75a929759a498b1b59481091da731f928e0cdbd3d7393b8a1022a1b57f01a91a", size = 4768129, upload-time = "2025-05-11T17:17:01.741Z" }, + { url = "https://files.pythonhosted.org/packages/5b/09/3ea950dea55a5e6aaba6b15baffd121e08ad3adfaa47308593301fd1f979/psycopg_binary-3.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d310d188bb349a5f66cc037f7416fd640ca9847d0083a63ba6c091fd45075482", size = 4458392, upload-time = "2025-05-11T17:17:10.136Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a4/c8ee70d5ca48d0f8447d986727a163c72b49f884d4206463e7711734943b/psycopg_binary-3.2.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f4965bc9d2ef8eed31ff411840e2ab0e1d0c1c59575e0154ced7b652ef0eaa33", size = 3776879, upload-time = "2025-05-11T17:17:16.614Z" }, + { url = "https://files.pythonhosted.org/packages/71/b9/e5a92b9dffe503f199018e784f2171dbf059136ea8be052eda1e0d81185e/psycopg_binary-3.2.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5f1c26c1213efba8102911099af2203db6859855f7ceba21fd941e6d2bc7e84e", size = 3333329, upload-time = "2025-05-11T17:17:20.998Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b1/61aefcc3b38fa970c0ed2530cd42440707550b273bbaf26f6f51a34872a4/psycopg_binary-3.2.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:58c5c7ef4daaaefb1e656a307ceb61aa3a101a5eb843004579d423428bef66e5", size = 3435684, upload-time = "2025-05-11T17:17:24.326Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/c3bf340054e999fafdba6b114c7f1cddeb71c53de1bba3ff1571ae9b96b9/psycopg_binary-3.2.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f501ee2b41a153aee59a3a5db238718f801ac39eec54ad3f28fbe657002e944", size = 3497123, upload-time = "2025-05-11T17:17:28.633Z" }, + { url = "https://files.pythonhosted.org/packages/9a/83/8b7131d778d9e57d332f7bc174411a5987da2e36e6fcac3838794e6152aa/psycopg_binary-3.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:fe51d8297bc8c178be1cc0ac6c060bfd706afb5cb04e794a44feae27c0afe6f4", size = 3785752, upload-time = "2025-05-11T17:17:32.838Z" }, + { url = "https://files.pythonhosted.org/packages/06/8e/d4ec28505cc1694bc3d9bbb329864fa9ca13f236bf78b16da092b9a99595/psycopg_binary-3.2.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1c330b86bc5ea67fee529d3c7b53c6394f8cacad77a3214c50fce0d5bdbc10cf", size = 4022230, upload-time = "2025-05-11T17:17:37.381Z" }, + { url = "https://files.pythonhosted.org/packages/d0/58/ee9bbecdf02f3f2c4beaef7764438fc2f468bb72fc6bfbe570ad6359f6e6/psycopg_binary-3.2.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce4e637ac339bfe583ac26e18232c33f9039c93cfc01adaec550cb5e8a03f87", size = 4083799, upload-time = "2025-05-11T17:17:41.519Z" }, + { url = "https://files.pythonhosted.org/packages/bc/da/3c52acf0e267d128bb066e53add32cbc71a2f82d523f1748e3ca530c913c/psycopg_binary-3.2.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:272ee7cd175996c7262f7ffb561593829b448032a52c545d844bc6a4fb77b078", size = 4655046, upload-time = "2025-05-11T17:17:46.134Z" }, + { url = "https://files.pythonhosted.org/packages/58/9b/b2ef57c791f098805299da38a0cb6929aff94e7056f5be2721d6739c6e60/psycopg_binary-3.2.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7237b1abcc36c04b45916c983a6c3d799104201f72475eab367874a5f37d3e7", size = 4477969, upload-time = "2025-05-11T17:17:50.661Z" }, + { url = "https://files.pythonhosted.org/packages/1f/d9/be82b51b12ea514573cd249eab01e59949a8f4db33a10e832cff0217eef1/psycopg_binary-3.2.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c9a30a1d8338823603cf064637aae5580c41ed95675c7aee6a47165784d0464", size = 4737511, upload-time = "2025-05-11T17:17:55.586Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/386413b8cf41d8bc921dd8e749a8e7cf9c5439e61849caa2511d265d699d/psycopg_binary-3.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f27d5ae05062f8ea0da6c11262ba8a1ab70864b1c18ea65d9e61636a8c72da4", size = 4436158, upload-time = "2025-05-11T17:18:00.181Z" }, + { url = "https://files.pythonhosted.org/packages/b9/a8/757a5d85a38e3c2bd9b580d2911d7af3eb3a97818a115a82c1854707f2e1/psycopg_binary-3.2.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:10fa234801b9b8b23799f869300c632a3298fb8daecd2d5734d08ab76e7a17cb", size = 3753518, upload-time = "2025-05-11T17:18:04.559Z" }, + { url = "https://files.pythonhosted.org/packages/0a/52/7b38e6a81d97aeacdb58cb73ca9cd29514071409ec7bd8b301bed97df199/psycopg_binary-3.2.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b055dba7df07c39f6a40a71862bf5525320350e3bd4c6d1809342fb7061d111f", size = 3313599, upload-time = "2025-05-11T17:18:10.247Z" }, + { url = "https://files.pythonhosted.org/packages/83/77/e74d3f5dcdd94858b5f6e255fd7cab5a7cdc5e9812b08faf3ae88a9b30ba/psycopg_binary-3.2.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8c36b8d3f76e2831f3b33f34226952ed39d1d6a79cb2ca2bf044f28df9c6b5f0", size = 3407291, upload-time = "2025-05-11T17:18:15.932Z" }, + { url = "https://files.pythonhosted.org/packages/fd/30/3d0a5931dacd5faeb94136d26a5cdbcd6bc4fa0005e71e6932b86f34db2e/psycopg_binary-3.2.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:764f9163ad9cfd32abd2d06f3000a52faf7a2b2411801d681ebe9158d72b46d5", size = 3472496, upload-time = "2025-05-11T17:18:20.318Z" }, + { url = "https://files.pythonhosted.org/packages/3f/2d/21663d776fdbb3f49b581d9be5137aef9fe5d7dee750ee8085d383449d3a/psycopg_binary-3.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:d8fa6fec9f7e225458d0031c43dd6d20673f55953eebe539d37e4b94b8831984", size = 3773878, upload-time = "2025-05-11T17:18:24.673Z" }, + { url = "https://files.pythonhosted.org/packages/e8/0c/6a29d13d947021e200b5933858a1399a45587bc2e698a2864622e454e84d/psycopg_binary-3.2.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84f03982598a6353cf70cafae34c16da28eac74ba9862cc740b6ba0dcf9721fc", size = 4017121, upload-time = "2025-05-11T17:18:29.089Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2d/49b881a66b8264ae8f9cb60db588838a97f12d2c8355bbbe6966539895d9/psycopg_binary-3.2.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d247f55b28afc4a87b77240e733419ad0c82be2ec122a0b93fbb227ee0e6608e", size = 4080326, upload-time = "2025-05-11T17:18:33.424Z" }, + { url = "https://files.pythonhosted.org/packages/44/bd/3752c86f6819797c722b48af3513837d1c31accc2216ebe5c02f857ff6aa/psycopg_binary-3.2.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89eb0c15c0eec1c81256e9df3c01d9bd1067f4365872f6f81da7521ab30e19de", size = 4655096, upload-time = "2025-05-11T17:18:37.883Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c8/ee544b8a73b52ab5b91ff36274f48628204b6f2edafdbe1f47a5473ee4c4/psycopg_binary-3.2.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aef90bdc201f2d375e5996d44124c588d3a7ce9f67c79f30531cdc5ead2c3d", size = 4482112, upload-time = "2025-05-11T17:18:42.75Z" }, + { url = "https://files.pythonhosted.org/packages/dc/f1/5d83d6069c0e69fd623088022f08bcaab3af39ca82be82846278f83ff6ea/psycopg_binary-3.2.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b60a17eca6a6906af8084c518be81bd71a3d50ddc69c0dc667d6ce9b8f4d8604", size = 4737683, upload-time = "2025-05-11T17:18:47.579Z" }, + { url = "https://files.pythonhosted.org/packages/84/19/2e1df0c4e30ec95d7c553507329661400f2deed7f54734196ce9fb6257aa/psycopg_binary-3.2.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8297d92f41e19b6794b04bdf7d53938a5ad8e68f7105b50048a078477b7ee4b8", size = 4437422, upload-time = "2025-05-11T17:18:52.811Z" }, + { url = "https://files.pythonhosted.org/packages/ad/8c/491827d42ebca49b3478b66ee160ba3055f3122eb27db33de8606d02e1e4/psycopg_binary-3.2.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a547d53e615776f8e79768aacd7a12c6f0131fa1d6820d2e3e848261b0ad3849", size = 3758667, upload-time = "2025-05-11T17:18:57.438Z" }, + { url = "https://files.pythonhosted.org/packages/09/55/617735f4110cc0d0e5e24a42e738f9d3ea73a00d9e88d57a657af0b7cb5f/psycopg_binary-3.2.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:058cfd606f1dc0be9b5a80d208fb9b487f7b4986a955322cbb45cee7e3e8056e", size = 3320577, upload-time = "2025-05-11T17:19:01.713Z" }, + { url = "https://files.pythonhosted.org/packages/88/97/69300bf1354c43bba633826ebd82a1c804541679e4ab53b96bb0eaafe4fb/psycopg_binary-3.2.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:15d21ed3292fb19b6ab096c3522d561d196eeef3903c31f1318df7478eb96fa5", size = 3411439, upload-time = "2025-05-11T17:19:06.088Z" }, + { url = "https://files.pythonhosted.org/packages/14/64/5a0aa4c3ddfbf6530b24aecff97e3eb9a0eedf67c61a0ff1dd95d847f5c7/psycopg_binary-3.2.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a6384f81c33a369144e4b98cbb4bf3ec4ac102ae11cfb84e70cf99aa43a44925", size = 3477479, upload-time = "2025-05-11T17:19:09.624Z" }, + { url = "https://files.pythonhosted.org/packages/50/33/f08b2d0b6608e51f013fa877bcc296baaac653b1658d7f1e35c6793fece4/psycopg_binary-3.2.8-cp313-cp313-win_amd64.whl", hash = "sha256:60db59a0f1676f70c027a8273b7b360af85ef87bf43cd49eb63727b72a170a9f", size = 3774539, upload-time = "2025-05-11T17:19:16.679Z" }, + { url = "https://files.pythonhosted.org/packages/f3/77/1323d65dfbba549b915b5e2a5e118a28c34575948657d523d9c58f60c5f1/psycopg_binary-3.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b1b5fd2e4ef6b28f0740fff4426e51d71390dbf970795f2e445536ce47da480", size = 4034291, upload-time = "2025-05-11T17:20:08.007Z" }, + { url = "https://files.pythonhosted.org/packages/54/58/de325ef607543796d68847af721a36e84032465afa820b59a09be38de253/psycopg_binary-3.2.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08ce4010185ee6d42287b37b6d2a18006fa9c053ecd2ed50d5bd428b99bdbee5", size = 4083020, upload-time = "2025-05-11T17:20:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/66/51/b25f6501c365e1ca10f8773ba83b2df60c379cf820453468d847d3b000fa/psycopg_binary-3.2.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4702427a3f6f240f888d78e36de37cc6d4298e95178e065fbc0c353fe692774", size = 4679368, upload-time = "2025-05-11T17:20:17.896Z" }, + { url = "https://files.pythonhosted.org/packages/78/86/0f798f1f2ab0ae61cdb9baceb91ff93b7b7aad4067b93346305c8408bec8/psycopg_binary-3.2.8-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42741f3fadfcef01252f4f6c67ab34a238c331c2504d976559236633618b1417", size = 4500889, upload-time = "2025-05-11T17:20:25.194Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a4/d4832031daada67d075bd15ec968a0992552fcb9888d7fdf343fea17e6f0/psycopg_binary-3.2.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53dfc4504a0e3b0f5efb1b94c9da68b917adc8a9c49c1b0061f6fa8125bd136c", size = 4769218, upload-time = "2025-05-11T17:20:30.082Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a5/b01190bc6deb10ca84159d8cb4e02236d3c96614d8bee6f36d46258cb347/psycopg_binary-3.2.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72f6269a64ee4f8b6b27116abf6536b31c1757973b0f0e612e19a1ad5376a73a", size = 4462834, upload-time = "2025-05-11T17:20:34.65Z" }, + { url = "https://files.pythonhosted.org/packages/1f/d5/7694b4637d4e81ff9e49ed0a129817a3faa85ca5e8d908691e52e2dd3bb1/psycopg_binary-3.2.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b72a737b88d1a14b2d9efea6819579ee8c4f335825f92f8d6e725f1e72ac519f", size = 3779529, upload-time = "2025-05-11T17:20:38.764Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/3c0528b038c0d72555236df60fb0a8834466083e13732bffc7d52cca28e7/psycopg_binary-3.2.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2705c34cba861699539619544078fe2a314b79c582874e813a6e512782b22638", size = 3337957, upload-time = "2025-05-11T17:20:42.536Z" }, + { url = "https://files.pythonhosted.org/packages/5f/20/8acd402b8b1c88459db2556fcdfcfcd6a7e19cbabef3e67f5bcf2b3fd94b/psycopg_binary-3.2.8-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b06a7cf2585bf6a3b4f9397af48427f558049a570d44b142eb9948c9b734c8ae", size = 3440569, upload-time = "2025-05-11T17:20:46.31Z" }, + { url = "https://files.pythonhosted.org/packages/4b/48/0a861b7f338e31d69dc6c2c77105a73ae4fad1cd7e487580f485af1ae552/psycopg_binary-3.2.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2f1be2d3160cdfb4732cd9f5777b0e9c78509ef0033dd6cff34ee0f16560e2fe", size = 3498637, upload-time = "2025-05-11T17:20:49.921Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a6/725406483100aa4b79fd01970114db7202aaaada2d1739b0331ecfc18251/psycopg_binary-3.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:6a45e2409352a99c8b4f733b86daf19c4df3dc7d9c1f2fb880adf7dfa225678a", size = 3784709, upload-time = "2025-05-11T17:20:54.303Z" }, ] [[package]] From 4664c91600d36c3b8923ae08c403a1348f9ec9e7 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Mon, 12 May 2025 02:32:17 +0000 Subject: [PATCH 09/11] feat: statement filter kwargs --- sqlspec/adapters/adbc/driver.py | 209 ++++++++++++++-------- sqlspec/adapters/aiosqlite/driver.py | 94 +++++----- sqlspec/adapters/asyncmy/driver.py | 100 ++++++----- sqlspec/adapters/asyncpg/config.py | 4 +- sqlspec/adapters/asyncpg/driver.py | 111 ++++++------ sqlspec/adapters/bigquery/driver.py | 131 +++++++++----- sqlspec/adapters/duckdb/driver.py | 113 +++++++----- sqlspec/adapters/oracledb/driver.py | 252 +++++++++++++++++---------- sqlspec/adapters/psqlpy/driver.py | 219 ++++++++++++++++------- sqlspec/adapters/psycopg/driver.py | 151 +++++++++------- sqlspec/adapters/sqlite/driver.py | 92 +++++----- sqlspec/base.py | 132 +++++++++----- sqlspec/mixins.py | 14 +- sqlspec/utils/singleton.py | 3 + 14 files changed, 1003 insertions(+), 622 deletions(-) diff --git a/sqlspec/adapters/adbc/driver.py b/sqlspec/adapters/adbc/driver.py index 8366bd6..584e964 100644 --- a/sqlspec/adapters/adbc/driver.py +++ b/sqlspec/adapters/adbc/driver.py @@ -10,7 +10,8 @@ from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError -from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.filters import StatementFilter +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin, SyncArrowBulkOperationsMixin from sqlspec.statement import SQLStatement from sqlspec.typing import ArrowTable, StatementParameterType, is_dict @@ -35,6 +36,7 @@ class AdbcDriver( SyncArrowBulkOperationsMixin["AdbcConnection"], SQLTranslatorMixin["AdbcConnection"], SyncDriverAdapterProtocol["AdbcConnection"], + ResultConverter, ): """ADBC Sync Driver Adapter.""" @@ -90,6 +92,7 @@ def _process_sql_params( # noqa: C901, PLR0912, PLR0915 sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[tuple[Any, ...]]]": # Always returns tuple or None for params """Process SQL and parameters for ADBC. @@ -101,11 +104,12 @@ def _process_sql_params( # noqa: C901, PLR0912, PLR0915 Args: sql: The SQL statement to process. parameters: The parameters to bind to the statement. - **kwargs: Additional keyword arguments (including filters). + *filters: Statement filters to apply. + **kwargs: Additional keyword arguments. Raises: - SQLParsingError: If the SQL statement cannot be parsed. ParameterStyleMismatchError: If positional parameters are mixed with keyword arguments. + SQLParsingError: If the SQL statement cannot be parsed. Returns: A tuple of (sql, parameters) ready for execution. @@ -150,11 +154,9 @@ def _process_sql_params( # noqa: C901, PLR0912, PLR0915 # 2. Create SQLStatement with dialect and process statement = SQLStatement(sql, merged_params, dialect=self.dialect) - # Apply any filters if present - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) processed_sql, processed_params, parsed_expr = statement.process() @@ -283,7 +285,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -294,7 +296,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -304,29 +306,35 @@ def select( sql: str, parameters: Optional["StatementParameterType"] = None, /, - *, + *filters: "StatementFilter", connection: Optional["AdbcConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": """Fetch data from the database. + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) + with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] results = cursor.fetchall() # pyright: ignore if not results: return [] + column_names = [column[0] for column in cursor.description or []] - column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - - if schema_type is not None: - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] - return [dict(zip(column_names, row)) for row in results] # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + return self.to_schema([dict(zip(column_names, row)) for row in results], schema_type=schema_type) @overload def select_one( @@ -334,7 +342,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -345,7 +353,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -355,26 +363,33 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[ModelDTOT, dict[str, Any]]": """Fetch one row from the database. + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) + with self._with_cursor(connection) as cursor: - cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - result = self.check_not_found(result) # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType,reportUnknownArgumentType] - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is None: - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] - return schema_type(**dict(zip(column_names, result))) # type: ignore[return-value] + cursor.execute(sql, parameters) + result = cursor.fetchone() + result = self.check_not_found(result) + column_names = [column[0] for column in cursor.description or []] + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) @overload def select_one_or_none( @@ -382,7 +397,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -393,7 +408,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -403,27 +418,34 @@ def select_one_or_none( sql: str, parameters: Optional["StatementParameterType"] = None, /, - *, + *filters: "StatementFilter", connection: Optional["AdbcConnection"] = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": - """Fetch one row from the database. + """Fetch one row from the database or return None if no rows found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - The first row of the query results. + The first row of the query results, or None if no results found. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) + with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] if result is None: return None - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is None: - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType] - return schema_type(**dict(zip(column_names, result))) # type: ignore[return-value] + column_names = [column[0] for column in cursor.description or []] + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) @overload def select_value( @@ -431,7 +453,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -442,7 +464,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -452,18 +474,27 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": """Fetch a single value from the database. + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: - The first value from the first row of results, or None if no results. + The first value of the first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) + with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] @@ -478,7 +509,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -489,7 +520,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -499,18 +530,27 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": - """Fetch a single value from the database. + """Fetch a single value or None if not found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - The first value from the first row of results, or None if no results. + The first value of the first row of the query results, or None if no results found. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) + with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] @@ -525,17 +565,24 @@ def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AdbcConnection]" = None, **kwargs: Any, ) -> int: - """Insert, update, or delete data from the database. + """Execute an insert, update, or delete statement. + + Args: + sql: The SQL statement to execute. + parameters: The parameters for the statement (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - Row count affected by the operation. + The number of rows affected by the statement. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -547,7 +594,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -558,7 +605,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -568,50 +615,57 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": """Insert, update, or delete data from the database and return result. + Args: + sql: The SQL statement to execute. + parameters: The parameters for the statement (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) + with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = cursor.fetchall() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] if not result: return None - - first_row = result[0] - column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - - result_dict = dict(zip(column_names, first_row)) - - if schema_type is None: - return result_dict - return cast("ModelDTOT", schema_type(**result_dict)) + return self.to_schema(dict(zip(column_names, result[0])), schema_type=schema_type) def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[AdbcConnection]" = None, **kwargs: Any, ) -> str: - """Execute a script. + """Execute a SQL script. + + Args: + sql: The SQL script to execute. + parameters: The parameters for the script (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - Status message for the operation. + A success message. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters) + sql, parameters = self._process_sql_params(sql, parameters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -624,17 +678,24 @@ def select_arrow( # pyright: ignore[reportUnknownParameterType] sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[AdbcConnection]" = None, **kwargs: Any, - ) -> "ArrowTable": + ) -> "ArrowTable": # pyright: ignore[reportUnknownVariableType] """Execute a SQL query and return results as an Apache Arrow Table. + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: - The results of the query as an Apache Arrow Table. + An Apache Arrow Table containing the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] diff --git a/sqlspec/adapters/aiosqlite/driver.py b/sqlspec/adapters/aiosqlite/driver.py index 9fefda3..41693ba 100644 --- a/sqlspec/adapters/aiosqlite/driver.py +++ b/sqlspec/adapters/aiosqlite/driver.py @@ -1,18 +1,19 @@ import logging from contextlib import asynccontextmanager -from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +from typing import TYPE_CHECKING, Any, Optional, Union, overload import aiosqlite from sqlglot import exp from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement from sqlspec.typing import is_dict if TYPE_CHECKING: from collections.abc import AsyncGenerator, Sequence + from sqlspec.filters import StatementFilter from sqlspec.typing import ModelDTOT, StatementParameterType, T __all__ = ("AiosqliteConnection", "AiosqliteDriver") @@ -24,6 +25,7 @@ class AiosqliteDriver( SQLTranslatorMixin["AiosqliteConnection"], AsyncDriverAdapterProtocol["AiosqliteConnection"], + ResultConverter, ): """SQLite Async Driver Adapter.""" @@ -50,6 +52,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters for aiosqlite using SQLStatement. @@ -61,16 +64,18 @@ def _process_sql_params( Args: sql: SQL statement. parameters: Query parameters. + *filters: Statement filters to apply. **kwargs: Additional keyword arguments. Returns: Tuple of processed SQL and parameters. """ statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + processed_sql, processed_params, parsed_expr = statement.process() if processed_params is None: return processed_sql, None @@ -117,7 +122,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -128,7 +133,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -138,7 +143,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -149,7 +154,7 @@ async def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -160,9 +165,9 @@ async def select( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return [dict(zip(column_names, row)) for row in results] - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] + # Convert to dicts first + dict_results = [dict(zip(column_names, row)) for row in results] + return self.to_schema(dict_results, schema_type=schema_type) @overload async def select_one( @@ -170,7 +175,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -181,7 +186,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -191,7 +196,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -202,7 +207,7 @@ async def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -212,9 +217,9 @@ async def select_one( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + # Convert to dict and then use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) @overload async def select_one_or_none( @@ -222,7 +227,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -233,7 +238,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -243,7 +248,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -254,7 +259,7 @@ async def select_one_or_none( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -265,9 +270,9 @@ async def select_one_or_none( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + # Convert to dict and then use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) @overload async def select_value( @@ -275,7 +280,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -286,7 +291,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -296,7 +301,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -307,7 +312,7 @@ async def select_value( The first value from the first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -326,7 +331,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -337,7 +342,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -347,7 +352,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -358,7 +363,7 @@ async def select_value_or_none( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -377,7 +382,7 @@ async def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, **kwargs: Any, ) -> int: @@ -387,7 +392,7 @@ async def insert_update_delete( Row count affected by the operation. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -400,7 +405,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -411,7 +416,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -421,7 +426,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AiosqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -432,7 +437,7 @@ async def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = await connection.execute(sql, parameters or ()) @@ -445,16 +450,15 @@ async def insert_update_delete_returning( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + # Convert to dict and then use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[AiosqliteConnection]" = None, **kwargs: Any, ) -> str: diff --git a/sqlspec/adapters/asyncmy/driver.py b/sqlspec/adapters/asyncmy/driver.py index a8bb75b..f6ea8b5 100644 --- a/sqlspec/adapters/asyncmy/driver.py +++ b/sqlspec/adapters/asyncmy/driver.py @@ -3,19 +3,20 @@ import re from collections.abc import AsyncGenerator, Sequence from contextlib import asynccontextmanager -from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +from typing import TYPE_CHECKING, Any, Optional, Union, overload from asyncmy import Connection from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError -from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement from sqlspec.typing import is_dict if TYPE_CHECKING: from asyncmy.cursors import Cursor + from sqlspec.filters import StatementFilter from sqlspec.typing import ModelDTOT, StatementParameterType, T __all__ = ("AsyncmyDriver",) @@ -31,6 +32,7 @@ class AsyncmyDriver( SQLTranslatorMixin["AsyncmyConnection"], AsyncDriverAdapterProtocol["AsyncmyConnection"], + ResultConverter, ): """Asyncmy MySQL/MariaDB Driver Adapter.""" @@ -54,6 +56,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters using SQLStatement with dialect support. @@ -61,7 +64,8 @@ def _process_sql_params( Args: sql: The SQL statement to process. parameters: The parameters to bind to the statement. - **kwargs: Additional keyword arguments (including filters). + *filters: Statement filters to apply. + **kwargs: Additional keyword arguments. Raises: ParameterStyleMismatchError: If the parameter style is not supported. @@ -102,11 +106,9 @@ def _process_sql_params( # Create a SQLStatement with MySQL dialect statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - # Apply any filters if present - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) # Process the statement for execution processed_sql, processed_params, _ = statement.process() @@ -135,7 +137,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -146,7 +148,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -156,7 +158,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -167,16 +169,17 @@ async def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) results = await cursor.fetchall() if not results: return [] column_names = [c[0] for c in cursor.description or []] - if schema_type is None: - return [dict(zip(column_names, row)) for row in results] - return [schema_type(**dict(zip(column_names, row))) for row in results] + + # Convert to dicts first + dict_results = [dict(zip(column_names, row)) for row in results] + return self.to_schema(dict_results, schema_type=schema_type) @overload async def select_one( @@ -184,7 +187,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -195,7 +198,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -205,7 +208,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -216,15 +219,16 @@ async def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() result = self.check_not_found(result) column_names = [c[0] for c in cursor.description or []] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + + # Convert to dict and use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) @overload async def select_one_or_none( @@ -232,7 +236,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -243,7 +247,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -253,7 +257,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -264,16 +268,17 @@ async def select_one_or_none( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() if result is None: return None column_names = [c[0] for c in cursor.description or []] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + + # Convert to dict and use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) @overload async def select_value( @@ -281,7 +286,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -292,7 +297,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -302,7 +307,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -313,7 +318,7 @@ async def select_value( The first value from the first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() @@ -329,7 +334,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -340,7 +345,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -350,7 +355,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -361,7 +366,7 @@ async def select_value_or_none( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) result = await cursor.fetchone() @@ -377,7 +382,7 @@ async def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, **kwargs: Any, ) -> int: @@ -387,7 +392,7 @@ async def insert_update_delete( Row count affected by the operation. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) return cursor.rowcount @@ -398,7 +403,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -409,7 +414,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -419,7 +424,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncmyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -430,7 +435,7 @@ async def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) @@ -438,16 +443,15 @@ async def insert_update_delete_returning( if result is None: return None column_names = [c[0] for c in cursor.description or []] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) - return dict(zip(column_names, result)) + + # Convert to dict and use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, - /, - *, connection: "Optional[AsyncmyConnection]" = None, **kwargs: Any, ) -> str: diff --git a/sqlspec/adapters/asyncpg/config.py b/sqlspec/adapters/asyncpg/config.py index 0acc9c5..b478e64 100644 --- a/sqlspec/adapters/asyncpg/config.py +++ b/sqlspec/adapters/asyncpg/config.py @@ -83,7 +83,9 @@ class AsyncpgConfig(AsyncDatabaseConfig["AsyncpgConnection", "Pool", "AsyncpgDri """For dialects that support the JSON datatype, this is a Python callable that will render a given object as JSON. By default, SQLSpec's :attr:`encode_json() ` is used.""" connection_type: "type[AsyncpgConnection]" = field( - hash=False, init=False, default_factory=lambda: PoolConnectionProxy + hash=False, + init=False, + default_factory=lambda: PoolConnectionProxy, # type: ignore[assignment] ) """Type of the connection object""" driver_type: "type[AsyncpgDriver]" = field(hash=False, init=False, default_factory=lambda: AsyncpgDriver) # type: ignore[type-abstract,unused-ignore] diff --git a/sqlspec/adapters/asyncpg/driver.py b/sqlspec/adapters/asyncpg/driver.py index 055e7a9..ff35810 100644 --- a/sqlspec/adapters/asyncpg/driver.py +++ b/sqlspec/adapters/asyncpg/driver.py @@ -1,29 +1,34 @@ import logging import re from re import Match -from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +from typing import TYPE_CHECKING, Any, Optional, Union, overload from asyncpg import Connection from sqlglot import exp from typing_extensions import TypeAlias from sqlspec.base import AsyncDriverAdapterProtocol -from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement if TYPE_CHECKING: from collections.abc import Sequence + from asyncpg import Record from asyncpg.connection import Connection from asyncpg.pool import PoolConnectionProxy + from sqlspec.filters import StatementFilter from sqlspec.typing import ModelDTOT, StatementParameterType, T __all__ = ("AsyncpgConnection", "AsyncpgDriver") logger = logging.getLogger("sqlspec") -AsyncpgConnection: TypeAlias = "Union[Connection[Any], PoolConnectionProxy[Any]]" +if TYPE_CHECKING: + AsyncpgConnection: TypeAlias = Union[Connection[Record], PoolConnectionProxy[Record]] +else: + AsyncpgConnection: TypeAlias = "Union[Connection, PoolConnectionProxy]" # Compile the row count regex once for efficiency ROWCOUNT_REGEX = re.compile(r"^(?:INSERT|UPDATE|DELETE) \d+ (\d+)$") @@ -50,6 +55,7 @@ class AsyncpgDriver( SQLTranslatorMixin["AsyncpgConnection"], AsyncDriverAdapterProtocol["AsyncpgConnection"], + ResultConverter, ): """AsyncPG Postgres Driver Adapter.""" @@ -64,6 +70,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters for AsyncPG using SQLStatement. @@ -74,6 +81,7 @@ def _process_sql_params( Args: sql: SQL statement. parameters: Query parameters. + *filters: Statement filters to apply. **kwargs: Additional keyword arguments. Returns: @@ -86,11 +94,9 @@ def _process_sql_params( # Create a SQLStatement with PostgreSQL dialect statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - # Apply any filters if present - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) # Process the statement processed_sql, processed_params, parsed_expr = statement.process() @@ -159,7 +165,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -170,7 +176,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -180,7 +186,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -188,6 +194,7 @@ async def select( """Fetch data from the database. Args: + *filters: Statement filters to apply. sql: SQL statement. parameters: Query parameters. connection: Optional connection to use. @@ -198,15 +205,13 @@ async def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () results = await connection.fetch(sql, *parameters) # pyright: ignore if not results: return [] - if schema_type is None: - return [dict(row.items()) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - return [cast("ModelDTOT", schema_type(**dict(row.items()))) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] + return self.to_schema([dict(row.items()) for row in results], schema_type=schema_type) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] @overload async def select_one( @@ -214,7 +219,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -225,7 +230,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -235,7 +240,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -243,6 +248,7 @@ async def select_one( """Fetch one row from the database. Args: + *filters: Statement filters to apply. sql: SQL statement. parameters: Query parameters. connection: Optional connection to use. @@ -253,15 +259,11 @@ async def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () result = await connection.fetchrow(sql, *parameters) # pyright: ignore result = self.check_not_found(result) - - if schema_type is None: - # Always return as dictionary - return dict(result.items()) # type: ignore[attr-defined] - return cast("ModelDTOT", schema_type(**dict(result.items()))) # type: ignore[attr-defined] + return self.to_schema(dict(result.items()), schema_type=schema_type) @overload async def select_one_or_none( @@ -269,7 +271,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -280,7 +282,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -290,7 +292,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -298,6 +300,7 @@ async def select_one_or_none( """Fetch one row from the database. Args: + *filters: Statement filters to apply. sql: SQL statement. parameters: Query parameters. connection: Optional connection to use. @@ -308,15 +311,12 @@ async def select_one_or_none( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () result = await connection.fetchrow(sql, *parameters) # pyright: ignore if result is None: return None - if schema_type is None: - # Always return as dictionary - return dict(result.items()) - return cast("ModelDTOT", schema_type(**dict(result.items()))) + return self.to_schema(dict(result.items()), schema_type=schema_type) @overload async def select_value( @@ -324,7 +324,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -335,7 +335,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -345,7 +345,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -353,6 +353,7 @@ async def select_value( """Fetch a single value from the database. Args: + *filters: Statement filters to apply. sql: SQL statement. parameters: Query parameters. connection: Optional connection to use. @@ -363,7 +364,7 @@ async def select_value( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () result = await connection.fetchval(sql, *parameters) # pyright: ignore result = self.check_not_found(result) @@ -377,7 +378,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -388,7 +389,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -398,18 +399,26 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": """Fetch a single value from the database. + Args: + *filters: Statement filters to apply. + sql: SQL statement. + parameters: Query parameters. + connection: Optional connection to use. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments. + Returns: The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () result = await connection.fetchval(sql, *parameters) # pyright: ignore if result is None: @@ -421,15 +430,16 @@ async def select_value_or_none( async def insert_update_delete( self, sql: str, - parameters: Optional["StatementParameterType"] = None, + parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: Optional["AsyncpgConnection"] = None, **kwargs: Any, ) -> int: """Insert, update, or delete data from the database. Args: + *filters: Statement filters to apply. sql: SQL statement. parameters: Query parameters. connection: Optional connection to use. @@ -439,7 +449,7 @@ async def insert_update_delete( Row count affected by the operation. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () result = await connection.execute(sql, *parameters) # pyright: ignore # asyncpg returns e.g. 'INSERT 0 1', 'UPDATE 0 2', etc. @@ -454,7 +464,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -465,7 +475,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -475,7 +485,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[AsyncpgConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -483,6 +493,7 @@ async def insert_update_delete_returning( """Insert, update, or delete data from the database and return the affected row. Args: + *filters: Statement filters to apply. sql: SQL statement. parameters: Query parameters. connection: Optional connection to use. @@ -493,21 +504,19 @@ async def insert_update_delete_returning( The affected row data as either a model instance or dictionary. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters if parameters is not None else () result = await connection.fetchrow(sql, *parameters) # pyright: ignore if result is None: return None - if schema_type is None: - return dict(result.items()) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - return cast("ModelDTOT", schema_type(**dict(result.items()))) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType, reportUnknownVariableType] + + return self.to_schema(dict(result.items()), schema_type=schema_type) async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[AsyncpgConnection]" = None, **kwargs: Any, ) -> str: diff --git a/sqlspec/adapters/bigquery/driver.py b/sqlspec/adapters/bigquery/driver.py index 0a813fc..ed9d8e6 100644 --- a/sqlspec/adapters/bigquery/driver.py +++ b/sqlspec/adapters/bigquery/driver.py @@ -20,7 +20,9 @@ from sqlspec.base import SyncDriverAdapterProtocol from sqlspec.exceptions import NotFoundError, ParameterStyleMismatchError, SQLSpecError +from sqlspec.filters import StatementFilter from sqlspec.mixins import ( + ResultConverter, SQLTranslatorMixin, SyncArrowBulkOperationsMixin, SyncParquetExportMixin, @@ -44,6 +46,7 @@ class BigQueryDriver( SyncArrowBulkOperationsMixin["BigQueryConnection"], SyncParquetExportMixin["BigQueryConnection"], SQLTranslatorMixin["BigQueryConnection"], + ResultConverter, ): """Synchronous BigQuery Driver Adapter.""" @@ -113,6 +116,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: StatementFilter, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters using SQLStatement with dialect support. @@ -120,7 +124,8 @@ def _process_sql_params( Args: sql: The SQL statement to process. parameters: The parameters to bind to the statement. - **kwargs: Additional keyword arguments (including filters). + *filters: Statement filters to apply. + **kwargs: Additional keyword arguments. Raises: ParameterStyleMismatchError: If pre-formatted BigQuery parameters are mixed with keyword arguments. @@ -140,10 +145,10 @@ def _process_sql_params( return sql, parameters statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) # Process the statement for execution processed_sql, processed_params, _ = statement.process() @@ -154,6 +159,8 @@ def _run_query_job( self, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, job_config: "Optional[QueryJobConfig]" = None, is_script: bool = False, @@ -171,7 +178,7 @@ def _run_query_job( final_job_config = QueryJobConfig() # Create a fresh config # Process SQL and parameters - final_sql, processed_params = self._process_sql_params(sql, parameters, **kwargs) + final_sql, processed_params = self._process_sql_params(sql, parameters, *filters, **kwargs) # Handle pre-formatted parameters if ( @@ -210,8 +217,22 @@ def _run_query_job( **final_query_kwargs, ) - @staticmethod + @overload + def _rows_to_results( + self, + rows: "Iterator[Row]", + schema: "Sequence[SchemaField]", + schema_type: "type[ModelDTOT]", + ) -> Sequence[ModelDTOT]: ... + @overload + def _rows_to_results( + self, + rows: "Iterator[Row]", + schema: "Sequence[SchemaField]", + schema_type: None = None, + ) -> Sequence[dict[str, Any]]: ... def _rows_to_results( + self, rows: "Iterator[Row]", schema: "Sequence[SchemaField]", schema_type: "Optional[type[ModelDTOT]]" = None, @@ -234,14 +255,8 @@ def _rows_to_results( row_dict[key] = value # type: ignore[assignment] else: row_dict[key] = value - # Use the processed dictionary for the final result - if schema_type: - processed_results.append(schema_type(**row_dict)) - else: - processed_results.append(row_dict) # type: ignore[arg-type] - if schema_type: - return cast("Sequence[ModelDTOT]", processed_results) - return cast("Sequence[dict[str, Any]]", processed_results) + processed_results.append(row_dict) + return self.to_schema(processed_results, schema_type=schema_type) @overload def select( @@ -249,7 +264,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -260,7 +275,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -270,13 +285,29 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": - query_job = self._run_query_job(sql, parameters, connection, job_config, **kwargs) + """Fetch data from the database. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + job_config: Optional job configuration. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + List of row data as either model instances or dictionaries. + """ + query_job = self._run_query_job( + sql, parameters, *filters, connection=connection, job_config=job_config, **kwargs + ) return self._rows_to_results(query_job.result(), query_job.result().schema, schema_type) @overload @@ -285,7 +316,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -296,7 +327,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -306,13 +337,15 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, ) -> "Union[ModelDTOT, dict[str, Any]]": - query_job = self._run_query_job(sql, parameters, connection, job_config, **kwargs) + query_job = self._run_query_job( + sql, parameters, *filters, connection=connection, job_config=job_config, **kwargs + ) rows_iterator = query_job.result() try: # Pass the iterator containing only the first row to _rows_to_results @@ -335,7 +368,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -346,7 +379,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -356,13 +389,15 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": - query_job = self._run_query_job(sql, parameters, connection, job_config, **kwargs) + query_job = self._run_query_job( + sql, parameters, *filters, connection=connection, job_config=job_config, **kwargs + ) rows_iterator = query_job.result() try: first_row = next(rows_iterator) @@ -380,7 +415,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[T]]" = None, job_config: "Optional[QueryJobConfig]" = None, @@ -392,7 +427,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -402,14 +437,14 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[T]]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, ) -> Union[T, Any]: query_job = self._run_query_job( - sql=sql, parameters=parameters, connection=connection, job_config=job_config, **kwargs + sql, parameters, *filters, connection=connection, job_config=job_config, **kwargs ) rows = query_job.result() try: @@ -432,7 +467,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -443,7 +478,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -453,14 +488,19 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[T]]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": query_job = self._run_query_job( - sql=sql, parameters=parameters, connection=connection, job_config=job_config, **kwargs + sql, + parameters, + *filters, + connection=connection, + job_config=job_config, + **kwargs, ) rows = query_job.result() try: @@ -481,7 +521,7 @@ def insert_update_delete( sql: str, parameters: Optional[StatementParameterType] = None, /, - *, + *filters: StatementFilter, connection: Optional["BigQueryConnection"] = None, job_config: Optional[QueryJobConfig] = None, **kwargs: Any, @@ -492,7 +532,7 @@ def insert_update_delete( int: The number of rows affected by the DML statement. """ query_job = self._run_query_job( - sql=sql, parameters=parameters, connection=connection, job_config=job_config, **kwargs + sql, parameters, *filters, connection=connection, job_config=job_config, **kwargs ) # DML statements might not return rows, check job properties # num_dml_affected_rows might be None initially, wait might be needed @@ -505,7 +545,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -516,7 +556,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -526,7 +566,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, job_config: "Optional[QueryJobConfig]" = None, @@ -541,7 +581,6 @@ def execute_script( sql: str, # Expecting a script here parameters: "Optional[StatementParameterType]" = None, # Parameters might be complex in scripts /, - *, connection: "Optional[BigQueryConnection]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, @@ -552,8 +591,8 @@ def execute_script( str: The job ID of the executed script. """ query_job = self._run_query_job( - sql=sql, - parameters=parameters, + sql, + parameters, connection=connection, job_config=job_config, is_script=True, @@ -568,7 +607,7 @@ def select_arrow( # pyright: ignore sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[BigQueryConnection]" = None, job_config: "Optional[QueryJobConfig]" = None, **kwargs: Any, @@ -577,7 +616,7 @@ def select_arrow( # pyright: ignore final_job_config = job_config or self._default_query_job_config or QueryJobConfig() # Process SQL and parameters using SQLStatement - processed_sql, processed_params = self._process_sql_params(sql, parameters, **kwargs) + processed_sql, processed_params = self._process_sql_params(sql, parameters, *filters, **kwargs) # Convert parameters to BigQuery format if isinstance(processed_params, dict): @@ -614,7 +653,7 @@ def select_to_parquet( sql: str, # Expects table ID: project.dataset.table parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, destination_uri: "Optional[str]" = None, connection: "Optional[BigQueryConnection]" = None, job_config: "Optional[bigquery.ExtractJobConfig]" = None, diff --git a/sqlspec/adapters/duckdb/driver.py b/sqlspec/adapters/duckdb/driver.py index d1438f6..9d210f3 100644 --- a/sqlspec/adapters/duckdb/driver.py +++ b/sqlspec/adapters/duckdb/driver.py @@ -5,13 +5,14 @@ from duckdb import DuckDBPyConnection from sqlspec.base import SyncDriverAdapterProtocol -from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin, SyncArrowBulkOperationsMixin from sqlspec.statement import SQLStatement from sqlspec.typing import ArrowTable, StatementParameterType if TYPE_CHECKING: from collections.abc import Generator, Sequence + from sqlspec.filters import StatementFilter from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T __all__ = ("DuckDBConnection", "DuckDBDriver") @@ -25,6 +26,7 @@ class DuckDBDriver( SyncArrowBulkOperationsMixin["DuckDBConnection"], SQLTranslatorMixin["DuckDBConnection"], SyncDriverAdapterProtocol["DuckDBConnection"], + ResultConverter, ): """DuckDB Sync Driver Adapter.""" @@ -57,6 +59,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters for DuckDB using SQLStatement. @@ -68,16 +71,18 @@ def _process_sql_params( Args: sql: SQL statement. parameters: Query parameters. + *filters: Statement filters to apply. **kwargs: Additional keyword arguments. Returns: Tuple of processed SQL and parameters. """ statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + processed_sql, processed_params, _ = statement.process() if processed_params is None: return processed_sql, None @@ -94,7 +99,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -105,7 +110,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -115,7 +120,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -126,16 +131,17 @@ def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, [] if parameters is None else parameters) results = cursor.fetchall() if not results: return [] column_names = [column[0] for column in cursor.description or []] - if schema_type is None: - return [dict(zip(column_names, row)) for row in results] - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] + + # Convert to dicts first + dict_results = [dict(zip(column_names, row)) for row in results] + return self.to_schema(dict_results, schema_type=schema_type) @overload def select_one( @@ -143,7 +149,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -154,7 +160,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -164,7 +170,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -175,15 +181,16 @@ def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, [] if parameters is None else parameters) result = cursor.fetchone() result = self.check_not_found(result) column_names = [column[0] for column in cursor.description or []] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + + # Convert to dict and use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) @overload def select_one_or_none( @@ -191,7 +198,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -202,7 +209,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -212,7 +219,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -223,16 +230,17 @@ def select_one_or_none( The first row of the query results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, [] if parameters is None else parameters) result = cursor.fetchone() if result is None: return None column_names = [column[0] for column in cursor.description or []] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + + # Convert to dict and use ResultConverter + dict_result = dict(zip(column_names, result)) + return self.to_schema(dict_result, schema_type=schema_type) @overload def select_value( @@ -240,7 +248,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -251,7 +259,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -261,7 +269,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -272,7 +280,7 @@ def select_value( The first value from the first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, [] if parameters is None else parameters) result = cursor.fetchone() @@ -288,7 +296,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -299,7 +307,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -309,13 +317,13 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, [] if parameters is None else parameters) result = cursor.fetchone() @@ -330,12 +338,12 @@ def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, **kwargs: Any, ) -> int: connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: params = [] if parameters is None else parameters cursor.execute(sql, params) @@ -347,7 +355,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -358,7 +366,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -368,29 +376,29 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[DuckDBConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[ModelDTOT, dict[str, Any]]": connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: params = [] if parameters is None else parameters cursor.execute(sql, params) result = cursor.fetchall() result = self.check_not_found(result) column_names = [col[0] for col in cursor.description or []] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result[0])))) - return dict(zip(column_names, result[0])) + + # Convert to dict and use ResultConverter + dict_result = dict(zip(column_names, result[0])) + return self.to_schema(dict_result, schema_type=schema_type) def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[DuckDBConnection]" = None, **kwargs: Any, ) -> str: @@ -412,8 +420,23 @@ def select_arrow( # pyright: ignore[reportUnknownParameterType] connection: "Optional[DuckDBConnection]" = None, **kwargs: Any, ) -> "ArrowTable": + """Execute a SQL query and return results as an Apache Arrow Table. + + Args: + sql: The SQL query string. + parameters: Parameters for the query. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + An Apache Arrow Table containing the query results. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + + # Extract filters from kwargs if present + filters = kwargs.pop("filters", []) + + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: params = [] if parameters is None else parameters cursor.execute(sql, params) diff --git a/sqlspec/adapters/oracledb/driver.py b/sqlspec/adapters/oracledb/driver.py index 44ff601..ca21752 100644 --- a/sqlspec/adapters/oracledb/driver.py +++ b/sqlspec/adapters/oracledb/driver.py @@ -5,13 +5,19 @@ from oracledb import AsyncConnection, AsyncCursor, Connection, Cursor from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol -from sqlspec.mixins import AsyncArrowBulkOperationsMixin, SQLTranslatorMixin, SyncArrowBulkOperationsMixin +from sqlspec.mixins import ( + AsyncArrowBulkOperationsMixin, + ResultConverter, + SQLTranslatorMixin, + SyncArrowBulkOperationsMixin, +) from sqlspec.statement import SQLStatement from sqlspec.typing import ArrowTable, StatementParameterType, T if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence + from sqlspec.filters import StatementFilter from sqlspec.typing import ModelDTOT __all__ = ("OracleAsyncConnection", "OracleAsyncDriver", "OracleSyncConnection", "OracleSyncDriver") @@ -32,6 +38,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], dict[str, Any]]]]": """Process SQL and parameters using SQLStatement with dialect support. @@ -39,7 +46,8 @@ def _process_sql_params( Args: sql: The SQL statement to process. parameters: The parameters to bind to the statement. - **kwargs: Additional keyword arguments (including filters). + *filters: Statement filters to apply. + **kwargs: Additional keyword arguments. Returns: A tuple of (sql, parameters) ready for execution. @@ -51,11 +59,10 @@ def _process_sql_params( # Create a SQLStatement with appropriate dialect statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - # Apply any filters if present - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) + processed_sql, processed_params, _ = statement.process() if processed_params is None: return processed_sql, None @@ -71,6 +78,7 @@ class OracleSyncDriver( SyncArrowBulkOperationsMixin["OracleSyncConnection"], SQLTranslatorMixin["OracleSyncConnection"], SyncDriverAdapterProtocol["OracleSyncConnection"], + ResultConverter, ): """Oracle Sync Driver Adapter.""" @@ -95,7 +103,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -106,7 +114,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -116,7 +124,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -126,6 +134,7 @@ def select( Args: sql: The SQL query string. parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. connection: Optional connection override. schema_type: Optional schema class for the result. **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. @@ -134,7 +143,7 @@ def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] results = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] @@ -143,10 +152,7 @@ def select( # Get column names column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type: - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore - - return [dict(zip(column_names, row)) for row in results] # pyright: ignore + return self.to_schema([dict(zip(column_names, row)) for row in results], schema_type=schema_type) @overload def select_one( @@ -154,7 +160,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -165,7 +171,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -175,7 +181,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -185,6 +191,7 @@ def select_one( Args: sql: The SQL query string. parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. connection: Optional connection override. schema_type: Optional schema class for the result. **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. @@ -193,7 +200,7 @@ def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -203,10 +210,7 @@ def select_one( # Get column names column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType] - # Always return dictionaries - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) @overload def select_one_or_none( @@ -214,7 +218,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -225,7 +229,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -235,33 +239,37 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": - """Fetch one row from the database. + """Fetch one row from the database or return None if no rows found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - The first row of the query results. + The first row of the query results, or None if no results found. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if result is None: return None # Get column names column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] - if schema_type is not None: - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType] - # Always return dictionaries - return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType] + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) @overload def select_value( @@ -269,7 +277,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -280,7 +288,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -290,18 +298,26 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": """Fetch a single value from the database. + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: - The first value from the first row of results, or None if no results. + The first value of the first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -318,7 +334,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -329,7 +345,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -339,23 +355,30 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": - """Fetch a single value from the database. + """Fetch a single value or None if not found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - The first value from the first row of results, or None if no results. + The first value of the first row of the query results, or None if no results found. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if result is None: return None @@ -368,21 +391,28 @@ def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, **kwargs: Any, ) -> int: - """Insert, update, or delete data from the database. + """Execute an insert, update, or delete statement. + + Args: + sql: The SQL statement to execute. + parameters: The parameters for the statement (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - Row count affected by the operation. + The number of rows affected by the statement. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] - return cursor.rowcount # pyright: ignore[reportUnknownMemberType] + return cursor.rowcount # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] @overload def insert_update_delete_returning( @@ -390,7 +420,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -401,7 +431,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -411,7 +441,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -422,7 +452,7 @@ def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -444,14 +474,20 @@ def execute_script( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[OracleSyncConnection]" = None, **kwargs: Any, ) -> str: - """Execute a script. + """Execute a SQL script. + + Args: + sql: The SQL script to execute. + parameters: The parameters for the script (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - Status message for the operation. + A success message. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) @@ -497,6 +533,7 @@ class OracleAsyncDriver( AsyncArrowBulkOperationsMixin["OracleAsyncConnection"], SQLTranslatorMixin["OracleAsyncConnection"], AsyncDriverAdapterProtocol["OracleAsyncConnection"], + ResultConverter, ): """Oracle Async Driver Adapter.""" @@ -521,7 +558,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -532,7 +569,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -542,7 +579,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -553,7 +590,7 @@ async def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -574,7 +611,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -585,7 +622,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -595,7 +632,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -606,7 +643,7 @@ async def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -626,7 +663,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -637,7 +674,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -647,7 +684,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -658,7 +695,7 @@ async def select_one_or_none( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -681,7 +718,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -692,7 +729,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -702,23 +739,31 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": """Fetch a single value from the database. + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + Returns: - The first value from the first row of results, or None if no results. + The first value of the first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - result = self.check_not_found(result) # pyright: ignore[reportUnknownArgumentType] + result = self.check_not_found(result) if schema_type is None: return result[0] # pyright: ignore[reportUnknownArgumentType] @@ -730,7 +775,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -741,7 +786,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -751,23 +796,30 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": - """Fetch a single value from the database. + """Fetch a single value or None if not found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - The first value from the first row of results, or None if no results. + The first value of the first row of the query results, or None if no results found. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType] - if result is None: return None @@ -780,17 +832,24 @@ async def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, **kwargs: Any, ) -> int: - """Insert, update, or delete data from the database. + """Execute an insert, update, or delete statement. + + Args: + sql: The SQL statement to execute. + parameters: The parameters for the statement (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - Row count affected by the operation. + The number of rows affected by the statement. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -802,7 +861,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -813,7 +872,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -823,7 +882,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[OracleAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -834,7 +893,7 @@ async def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) async with self._with_cursor(connection) as cursor: await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType] @@ -856,14 +915,19 @@ async def execute_script( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[OracleAsyncConnection]" = None, **kwargs: Any, ) -> str: - """Execute a script. + """Execute a SQL script. + + Args: + sql: The SQL script to execute. + parameters: The parameters for the script (dict, tuple, list, or None). + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: - Status message for the operation. + A success message. """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) diff --git a/sqlspec/adapters/psqlpy/driver.py b/sqlspec/adapters/psqlpy/driver.py index 0809d25..c01e300 100644 --- a/sqlspec/adapters/psqlpy/driver.py +++ b/sqlspec/adapters/psqlpy/driver.py @@ -3,7 +3,7 @@ import logging import re from re import Match -from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +from typing import TYPE_CHECKING, Any, Optional, Union, overload from psqlpy import Connection, QueryResult from psqlpy.exceptions import RustPSQLDriverPyBaseError @@ -11,7 +11,8 @@ from sqlspec.base import AsyncDriverAdapterProtocol from sqlspec.exceptions import SQLParsingError -from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.filters import StatementFilter +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement from sqlspec.typing import is_dict @@ -49,6 +50,7 @@ class PsqlpyDriver( SQLTranslatorMixin["PsqlpyConnection"], AsyncDriverAdapterProtocol["PsqlpyConnection"], + ResultConverter, ): """Psqlpy Postgres Driver Adapter.""" @@ -63,6 +65,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: StatementFilter, **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], dict[str, Any]]]]": """Process SQL and parameters for psqlpy. @@ -70,6 +73,7 @@ def _process_sql_params( Args: sql: SQL statement. parameters: Query parameters. + *filters: Statement filters to apply. **kwargs: Additional keyword arguments. Returns: @@ -85,11 +89,9 @@ def _process_sql_params( # Create and process the statement statement = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs, dialect=self.dialect) - # Apply any filters if present - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + # Apply any filters + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) # Process the statement sql, validated_params, parsed_expr = statement.process() @@ -161,7 +163,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -172,7 +174,7 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -182,20 +184,33 @@ async def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": + """Fetch data from the database. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + List of row data as either model instances or dictionaries. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] # psqlpy expects a list/tuple results: QueryResult = await connection.fetch(sql, parameters=parameters) - if schema_type is None: - return cast("list[dict[str, Any]]", results.result()) - return results.as_class(as_class=schema_type) + # Convert to dicts and use ResultConverter + dict_results = results.result() + return self.to_schema(dict_results, schema_type=schema_type) @overload async def select_one( @@ -203,7 +218,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -214,7 +229,7 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -224,21 +239,36 @@ async def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Union[ModelDTOT, dict[str, Any]]": + """Fetch one row from the database. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + The first row of the query results. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] result = await connection.fetch(sql, parameters=parameters) - if schema_type is None: - result = cast("list[dict[str, Any]]", result.result()) # type: ignore[assignment] - return cast("dict[str, Any]", result[0]) # type: ignore[index] - return result.as_class(as_class=schema_type)[0] + # Convert to dict and use ResultConverter + dict_results = result.result() + if not dict_results: + self.check_not_found(None) + + return self.to_schema(dict_results[0], schema_type=schema_type) @overload async def select_one_or_none( @@ -246,7 +276,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -257,7 +287,7 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -267,25 +297,35 @@ async def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": + """Fetch one row from the database or return None if no rows found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + The first row of the query results, or None if no results found. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] result = await connection.fetch(sql, parameters=parameters) - if schema_type is None: - result = cast("list[dict[str, Any]]", result.result()) # type: ignore[assignment] - if len(result) == 0: # type: ignore[arg-type] - return None - return cast("dict[str, Any]", result[0]) # type: ignore[index] - result = cast("list[ModelDTOT]", result.as_class(as_class=schema_type)) # type: ignore[assignment] - if len(result) == 0: # type: ignore[arg-type] + dict_results = result.result() + + if not dict_results: return None - return cast("ModelDTOT", result[0]) # type: ignore[index] + + return self.to_schema(dict_results[0], schema_type=schema_type) @overload async def select_value( @@ -293,7 +333,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -304,7 +344,7 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -314,16 +354,30 @@ async def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Union[T, Any]": + """Fetch a single value from the database. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + The first value of the first row of the query results. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] value = await connection.fetch_val(sql, parameters=parameters) + value = self.check_not_found(value) if schema_type is None: return value @@ -335,7 +389,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -346,7 +400,7 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -356,13 +410,26 @@ async def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, ) -> "Optional[Union[T, Any]]": + """Fetch a single value or None if not found. + + Args: + sql: The SQL query string. + parameters: The parameters for the query (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional type to convert the result to. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + The first value of the first row of the query results, or None if no results found. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] try: value = await connection.fetch_val(sql, parameters=parameters) @@ -380,12 +447,24 @@ async def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, **kwargs: Any, ) -> int: + """Execute an insert, update, or delete statement. + + Args: + sql: The SQL statement to execute. + parameters: The parameters for the statement (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + The number of rows affected by the statement. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] await connection.execute(sql, parameters=parameters) @@ -399,7 +478,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -410,7 +489,7 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -420,41 +499,61 @@ async def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: StatementFilter, connection: "Optional[PsqlpyConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, - ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": + ) -> "Union[ModelDTOT, dict[str, Any]]": + """Insert, update, or delete data from the database and return result. + + Args: + sql: The SQL statement to execute. + parameters: The parameters for the statement (dict, tuple, list, or None). + *filters: Statement filters to apply. + connection: Optional connection override. + schema_type: Optional schema class for the result. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + The first row of results. + """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) parameters = parameters or [] result = await connection.execute(sql, parameters=parameters) - if schema_type is None: - result = result.result() # type: ignore[assignment] - if len(result) == 0: # type: ignore[arg-type] - return None - return cast("dict[str, Any]", result[0]) # type: ignore[index] - result = result.as_class(as_class=schema_type) # type: ignore[assignment] - if len(result) == 0: # type: ignore[arg-type] - return None - return cast("ModelDTOT", result[0]) # type: ignore[index] + dict_results = result.result() + + if not dict_results: + self.check_not_found(None) + + return self.to_schema(dict_results[0], schema_type=schema_type) async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[PsqlpyConnection]" = None, **kwargs: Any, ) -> str: + """Execute a SQL script. + + Args: + sql: The SQL script to execute. + parameters: The parameters for the script (dict, tuple, list, or None). + connection: Optional connection override. + **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. + + Returns: + A success message. + """ connection = self._connection(connection) sql, parameters = self._process_sql_params(sql, parameters, **kwargs) parameters = parameters or [] await connection.execute(sql, parameters=parameters) - return sql + return "Script executed successfully" def _connection(self, connection: "Optional[PsqlpyConnection]" = None) -> "PsqlpyConnection": """Get the connection to use. diff --git a/sqlspec/adapters/psycopg/driver.py b/sqlspec/adapters/psycopg/driver.py index 2d6d34e..1fd00e8 100644 --- a/sqlspec/adapters/psycopg/driver.py +++ b/sqlspec/adapters/psycopg/driver.py @@ -1,14 +1,13 @@ import logging import re from contextlib import asynccontextmanager, contextmanager -from typing import TYPE_CHECKING, Any, Optional, Union, overload +from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload from psycopg import AsyncConnection, Connection from psycopg.rows import dict_row from sqlspec.base import AsyncDriverAdapterProtocol, SyncDriverAdapterProtocol from sqlspec.exceptions import ParameterStyleMismatchError -from sqlspec.filters import StatementFilter from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement from sqlspec.typing import is_dict @@ -16,6 +15,7 @@ if TYPE_CHECKING: from collections.abc import AsyncGenerator, Generator, Sequence + from sqlspec.filters import StatementFilter from sqlspec.typing import ModelDTOT, StatementParameterType, T logger = logging.getLogger("sqlspec") @@ -39,7 +39,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *filters: StatementFilter, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters using SQLStatement with dialect support. @@ -94,6 +94,7 @@ class PsycopgSyncDriver( PsycopgDriverBase, SQLTranslatorMixin["PsycopgSyncConnection"], SyncDriverAdapterProtocol["PsycopgSyncConnection"], + ResultConverter, ): """Psycopg Sync Driver Adapter.""" @@ -115,9 +116,10 @@ def _with_cursor(connection: "PsycopgSyncConnection") -> "Generator[Any, None, N @overload def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -125,18 +127,20 @@ def select( @overload def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Sequence[ModelDTOT]": ... def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", schema_type: "Optional[type[ModelDTOT]]" = None, connection: "Optional[PsycopgSyncConnection]" = None, **kwargs: Any, @@ -154,15 +158,15 @@ def select( if not results: return [] - # Use ResultConverter for batch conversion - return ResultConverter.to_schema(results, schema_type=schema_type) + return self.to_schema(cast("Sequence[dict[str, Any]]", results), schema_type=schema_type) @overload def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -170,18 +174,20 @@ def select_one( @overload def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -198,15 +204,15 @@ def select_one( row = cursor.fetchone() row = self.check_not_found(row) - # Use ResultConverter for single row conversion - return ResultConverter.to_schema(row, schema_type=schema_type) + return self.to_schema(cast("dict[str, Any]", row), schema_type=schema_type) @overload def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -214,18 +220,20 @@ def select_one_or_none( @overload def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Optional[ModelDTOT]": ... def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -242,16 +250,15 @@ def select_one_or_none( row = cursor.fetchone() if row is None: return None - - # Use ResultConverter for single row conversion - return ResultConverter.to_schema(row, schema_type=schema_type) + return self.to_schema(cast("dict[str, Any]", row), schema_type=schema_type) @overload def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -259,18 +266,20 @@ def select_value( @overload def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "T": ... def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -295,9 +304,10 @@ def select_value( @overload def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -305,18 +315,20 @@ def select_value_or_none( @overload def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "Optional[T]": ... def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -342,9 +354,10 @@ def select_value_or_none( def insert_update_delete( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, **kwargs: Any, ) -> int: @@ -362,9 +375,10 @@ def insert_update_delete( @overload def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -372,18 +386,20 @@ def insert_update_delete_returning( @overload def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgSyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -402,13 +418,13 @@ def insert_update_delete_returning( if result is None: return None - # Use ResultConverter for single row conversion - return ResultConverter.to_schema(result, schema_type=schema_type) + return self.to_schema(cast("dict[str, Any]", result), schema_type=schema_type) def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, connection: "Optional[PsycopgSyncConnection]" = None, **kwargs: Any, ) -> str: @@ -428,6 +444,7 @@ class PsycopgAsyncDriver( PsycopgDriverBase, SQLTranslatorMixin["PsycopgAsyncConnection"], AsyncDriverAdapterProtocol["PsycopgAsyncConnection"], + ResultConverter, ): """Psycopg Async Driver Adapter.""" @@ -449,9 +466,10 @@ async def _with_cursor(connection: "PsycopgAsyncConnection") -> "AsyncGenerator[ @overload async def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -459,18 +477,20 @@ async def select( @overload async def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Sequence[ModelDTOT]": ... async def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", schema_type: "Optional[type[ModelDTOT]]" = None, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, @@ -487,16 +507,15 @@ async def select( results = await cursor.fetchall() if not results: return [] - - # Use ResultConverter for batch conversion - return ResultConverter.to_schema(results, schema_type=schema_type) + return self.to_schema(cast("Sequence[dict[str, Any]]", results), schema_type=schema_type) @overload async def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -504,18 +523,20 @@ async def select_one( @overload async def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... async def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -532,15 +553,15 @@ async def select_one( row = await cursor.fetchone() row = self.check_not_found(row) - # Use ResultConverter for single row conversion - return ResultConverter.to_schema(row, schema_type=schema_type) + return self.to_schema(cast("dict[str, Any]", row), schema_type=schema_type) @overload async def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -548,18 +569,20 @@ async def select_one_or_none( @overload async def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "Optional[ModelDTOT]": ... async def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", schema_type: "Optional[type[ModelDTOT]]" = None, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, @@ -577,15 +600,16 @@ async def select_one_or_none( if row is None: return None - # Use ResultConverter for single row conversion - return ResultConverter.to_schema(row, schema_type=schema_type) + # Use self.to_schema from ResultConverter mixin + return self.to_schema(cast("dict[str, Any]", row), schema_type=schema_type) @overload async def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -593,18 +617,20 @@ async def select_value( @overload async def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "T": ... async def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -629,9 +655,10 @@ async def select_value( @overload async def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -639,18 +666,20 @@ async def select_value_or_none( @overload async def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[T]", **kwargs: Any, ) -> "Optional[T]": ... async def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -676,9 +705,10 @@ async def select_value_or_none( async def insert_update_delete( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, ) -> int: @@ -696,9 +726,10 @@ async def insert_update_delete( @overload async def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -706,18 +737,20 @@ async def insert_update_delete_returning( @overload async def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, ) -> "ModelDTOT": ... async def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[PsycopgAsyncConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -735,13 +768,13 @@ async def insert_update_delete_returning( if result is None: return None - # Use ResultConverter for single row conversion - return ResultConverter.to_schema(result, schema_type=schema_type) + return self.to_schema(cast("dict[str, Any]", result), schema_type=schema_type) async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, connection: "Optional[PsycopgAsyncConnection]" = None, **kwargs: Any, ) -> str: diff --git a/sqlspec/adapters/sqlite/driver.py b/sqlspec/adapters/sqlite/driver.py index 9343e72..d4b8975 100644 --- a/sqlspec/adapters/sqlite/driver.py +++ b/sqlspec/adapters/sqlite/driver.py @@ -2,16 +2,17 @@ import sqlite3 from contextlib import contextmanager from sqlite3 import Cursor -from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload +from typing import TYPE_CHECKING, Any, Optional, Union, overload from sqlspec.base import SyncDriverAdapterProtocol -from sqlspec.mixins import SQLTranslatorMixin +from sqlspec.mixins import ResultConverter, SQLTranslatorMixin from sqlspec.statement import SQLStatement from sqlspec.typing import is_dict if TYPE_CHECKING: from collections.abc import Generator, Sequence + from sqlspec.filters import StatementFilter from sqlspec.typing import ModelDTOT, StatementParameterType, T __all__ = ("SqliteConnection", "SqliteDriver") @@ -24,6 +25,7 @@ class SqliteDriver( SQLTranslatorMixin["SqliteConnection"], SyncDriverAdapterProtocol["SqliteConnection"], + ResultConverter, ): """SQLite Sync Driver Adapter.""" @@ -50,6 +52,7 @@ def _process_sql_params( sql: str, parameters: "Optional[StatementParameterType]" = None, /, + *filters: "StatementFilter", **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL and parameters for SQLite using SQLStatement. @@ -61,7 +64,8 @@ def _process_sql_params( Args: sql: The SQL to process. parameters: The parameters to process. - kwargs: Additional keyword arguments. + *filters: Statement filters to apply. + **kwargs: Additional keyword arguments. Returns: A tuple of (processed SQL, processed parameters). @@ -69,10 +73,8 @@ def _process_sql_params( # Create a SQLStatement with SQLite dialect statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect) - filters = kwargs.pop("filters", None) - if filters: - for filter_obj in filters: - statement = statement.apply_filter(filter_obj) + for filter_obj in filters: + statement = statement.apply_filter(filter_obj) processed_sql, processed_params, _ = statement.process() @@ -94,7 +96,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -105,7 +107,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -115,7 +117,7 @@ def select( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -126,7 +128,7 @@ def select( List of row data as either model instances or dictionaries. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters or []) @@ -137,9 +139,7 @@ def select( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return [dict(zip(column_names, row)) for row in results] - return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] + return self.to_schema([dict(zip(column_names, row)) for row in results], schema_type=schema_type) @overload def select_one( @@ -147,7 +147,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -158,7 +158,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -168,7 +168,7 @@ def select_one( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -179,7 +179,7 @@ def select_one( The first row of the query results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) # Execute the query cursor = connection.cursor() @@ -190,9 +190,7 @@ def select_one( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) @overload def select_one_or_none( @@ -200,7 +198,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -211,7 +209,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -221,7 +219,7 @@ def select_one_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -232,7 +230,7 @@ def select_one_or_none( The first row of the query results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters or []) @@ -243,9 +241,7 @@ def select_one_or_none( # Get column names column_names = [column[0] for column in cursor.description] - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) @overload def select_value( @@ -253,7 +249,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -264,7 +260,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -274,7 +270,7 @@ def select_value( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -285,7 +281,7 @@ def select_value( The first value from the first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters or []) @@ -304,7 +300,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -315,7 +311,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "type[T]", **kwargs: Any, @@ -325,7 +321,7 @@ def select_value_or_none( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -336,7 +332,7 @@ def select_value_or_none( The first value from the first row of results, or None if no results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters or []) @@ -355,7 +351,7 @@ def insert_update_delete( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, **kwargs: Any, ) -> int: @@ -365,11 +361,10 @@ def insert_update_delete( Row count affected by the operation. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters or []) - connection.commit() return cursor.rowcount @overload @@ -378,7 +373,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: None = None, **kwargs: Any, @@ -389,7 +384,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -399,7 +394,7 @@ def insert_update_delete_returning( sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, + *filters: "StatementFilter", connection: "Optional[SqliteConnection]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -410,26 +405,20 @@ def insert_update_delete_returning( The first row of results. """ connection = self._connection(connection) - sql, parameters = self._process_sql_params(sql, parameters, **kwargs) + sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs) with self._with_cursor(connection) as cursor: cursor.execute(sql, parameters or []) result = cursor.fetchone() result = self.check_not_found(result) - connection.commit() - # Get column names column_names = [column[0] for column in cursor.description] - - if schema_type is None: - return dict(zip(column_names, result)) - return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) + return self.to_schema(dict(zip(column_names, result)), schema_type=schema_type) def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, - *, connection: "Optional[SqliteConnection]" = None, **kwargs: Any, ) -> str: @@ -443,8 +432,7 @@ def execute_script( with self._with_cursor(connection) as cursor: cursor.executescript(sql) - connection.commit() - return "Script executed successfully." + return "DONE" def _connection(self, connection: "Optional[SqliteConnection]" = None) -> "SqliteConnection": """Get the connection to use for the operation. diff --git a/sqlspec/base.py b/sqlspec/base.py index 7abcd79..656c3f7 100644 --- a/sqlspec/base.py +++ b/sqlspec/base.py @@ -19,7 +19,6 @@ ) from sqlspec.exceptions import NotFoundError -from sqlspec.filters import StatementFilter from sqlspec.statement import SQLStatement from sqlspec.typing import ConnectionT, ModelDTOT, PoolT, StatementParameterType, T from sqlspec.utils.sync_tools import ensure_async_ @@ -27,6 +26,8 @@ if TYPE_CHECKING: from contextlib import AbstractAsyncContextManager, AbstractContextManager + from sqlspec.filters import StatementFilter + __all__ = ( "AsyncDatabaseConfig", @@ -534,13 +535,19 @@ def check_not_found(item_or_none: Optional[T] = None) -> T: return item_or_none def _process_sql_params( - self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any + self, + sql: str, + parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", + **kwargs: Any, ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]": """Process SQL query and parameters using SQLStatement for validation and formatting. Args: sql: The SQL query string. parameters: Parameters for the query. + *filters: Statement filters to apply. **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict. Returns: @@ -548,6 +555,11 @@ def _process_sql_params( """ # Instantiate SQLStatement with parameters and kwargs for internal merging stmt = SQLStatement(sql=sql, parameters=parameters, kwargs=kwargs or None) + + # Apply all statement filters + for filter_obj in filters: + stmt = stmt.apply_filter(filter_obj) + # Process uses the merged parameters internally processed = stmt.process() return processed[0], processed[1] # Return only the SQL and parameters, discard the third element @@ -563,9 +575,10 @@ def __init__(self, connection: "ConnectionT", **kwargs: Any) -> None: @abstractmethod def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -575,9 +588,10 @@ def select( @abstractmethod def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -586,9 +600,10 @@ def select( @abstractmethod def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -598,9 +613,10 @@ def select( @abstractmethod def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -610,9 +626,10 @@ def select_one( @abstractmethod def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -621,9 +638,10 @@ def select_one( @abstractmethod def select_one( self, - *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, + /, + *filters: "StatementFilter", connection: Optional[ConnectionT] = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -633,9 +651,10 @@ def select_one( @abstractmethod def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -645,9 +664,10 @@ def select_one_or_none( @abstractmethod def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -656,9 +676,10 @@ def select_one_or_none( @abstractmethod def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, + /, + *filters: "StatementFilter", connection: Optional[ConnectionT] = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -668,9 +689,10 @@ def select_one_or_none( @abstractmethod def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -680,9 +702,10 @@ def select_value( @abstractmethod def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -691,9 +714,10 @@ def select_value( @abstractmethod def select_value( self, - *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, + /, + *filters: "StatementFilter", connection: Optional[ConnectionT] = None, schema_type: Optional[type[T]] = None, **kwargs: Any, @@ -703,9 +727,10 @@ def select_value( @abstractmethod def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -715,9 +740,10 @@ def select_value_or_none( @abstractmethod def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -726,9 +752,10 @@ def select_value_or_none( @abstractmethod def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, + /, + *filters: "StatementFilter", connection: Optional[ConnectionT] = None, schema_type: Optional[type[T]] = None, **kwargs: Any, @@ -737,9 +764,10 @@ def select_value_or_none( @abstractmethod def insert_update_delete( self, - *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, + /, + *filters: "StatementFilter", connection: Optional[ConnectionT] = None, **kwargs: Any, ) -> int: ... @@ -748,9 +776,10 @@ def insert_update_delete( @abstractmethod def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -760,9 +789,10 @@ def insert_update_delete_returning( @abstractmethod def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -771,9 +801,10 @@ def insert_update_delete_returning( @abstractmethod def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: Optional[StatementParameterType] = None, + /, + *filters: "StatementFilter", connection: Optional[ConnectionT] = None, schema_type: Optional[type[ModelDTOT]] = None, **kwargs: Any, @@ -784,6 +815,7 @@ def execute_script( self, sql: str, parameters: Optional[StatementParameterType] = None, + /, connection: Optional[ConnectionT] = None, **kwargs: Any, ) -> str: ... @@ -799,9 +831,10 @@ def __init__(self, connection: "ConnectionT") -> None: @abstractmethod async def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -811,9 +844,10 @@ async def select( @abstractmethod async def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -822,9 +856,10 @@ async def select( @abstractmethod async def select( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -834,9 +869,10 @@ async def select( @abstractmethod async def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -846,9 +882,10 @@ async def select_one( @abstractmethod async def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -857,9 +894,10 @@ async def select_one( @abstractmethod async def select_one( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -869,9 +907,10 @@ async def select_one( @abstractmethod async def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -881,9 +920,10 @@ async def select_one_or_none( @abstractmethod async def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -892,9 +932,10 @@ async def select_one_or_none( @abstractmethod async def select_one_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -904,9 +945,10 @@ async def select_one_or_none( @abstractmethod async def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -916,9 +958,10 @@ async def select_value( @abstractmethod async def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -927,9 +970,10 @@ async def select_value( @abstractmethod async def select_value( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -939,9 +983,10 @@ async def select_value( @abstractmethod async def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -951,9 +996,10 @@ async def select_value_or_none( @abstractmethod async def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[T]", **kwargs: Any, @@ -962,9 +1008,10 @@ async def select_value_or_none( @abstractmethod async def select_value_or_none( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[T]]" = None, **kwargs: Any, @@ -973,9 +1020,10 @@ async def select_value_or_none( @abstractmethod async def insert_update_delete( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, **kwargs: Any, ) -> int: ... @@ -984,9 +1032,10 @@ async def insert_update_delete( @abstractmethod async def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: None = None, **kwargs: Any, @@ -996,9 +1045,10 @@ async def insert_update_delete_returning( @abstractmethod async def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "type[ModelDTOT]", **kwargs: Any, @@ -1007,9 +1057,10 @@ async def insert_update_delete_returning( @abstractmethod async def insert_update_delete_returning( self, - *filters: StatementFilter, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, + *filters: "StatementFilter", connection: "Optional[ConnectionT]" = None, schema_type: "Optional[type[ModelDTOT]]" = None, **kwargs: Any, @@ -1020,6 +1071,7 @@ async def execute_script( self, sql: str, parameters: "Optional[StatementParameterType]" = None, + /, connection: "Optional[ConnectionT]" = None, **kwargs: Any, ) -> str: ... diff --git a/sqlspec/mixins.py b/sqlspec/mixins.py index 3823970..c59fa80 100644 --- a/sqlspec/mixins.py +++ b/sqlspec/mixins.py @@ -243,27 +243,27 @@ def to_schema(data: "ModelT", *, schema_type: None = None) -> "ModelT": ... def to_schema(data: "dict[str, Any]", *, schema_type: "type[ModelDTOT]") -> "ModelDTOT": ... @overload @staticmethod - def to_schema(data: "Sequence[ModelT]", *, schema_type: None = None) -> "list[ModelT]": ... + def to_schema(data: "Sequence[ModelT]", *, schema_type: None = None) -> "Sequence[ModelT]": ... @overload @staticmethod - def to_schema(data: "Sequence[dict[str, Any]]", *, schema_type: "type[ModelDTOT]") -> "list[ModelDTOT]": ... + def to_schema(data: "Sequence[dict[str, Any]]", *, schema_type: "type[ModelDTOT]") -> "Sequence[ModelDTOT]": ... @staticmethod def to_schema( data: "Union[ModelT, Sequence[ModelT], dict[str, Any], Sequence[dict[str, Any]], ModelDTOT, Sequence[ModelDTOT]]", *, schema_type: "Optional[type[ModelDTOT]]" = None, - ) -> "Union[ModelT, list[ModelT], ModelDTOT, list[ModelDTOT]]": + ) -> "Union[ModelT, Sequence[ModelT], ModelDTOT, Sequence[ModelDTOT]]": if schema_type is None: if not isinstance(data, Sequence): return cast("ModelT", data) - return cast("list[ModelT]", data) + return cast("Sequence[ModelT]", data) if is_dataclass(schema_type): if not isinstance(data, Sequence): # data is assumed to be dict[str, Any] as per the method's overloads return cast("ModelDTOT", schema_type(**data)) # type: ignore[operator] # data is assumed to be Sequence[dict[str, Any]] - return cast("list[ModelDTOT]", [schema_type(**item) for item in data]) # type: ignore[operator] + return cast("Sequence[ModelDTOT]", [schema_type(**item) for item in data]) # type: ignore[operator] if is_msgspec_struct(schema_type): if not isinstance(data, Sequence): return cast( @@ -279,7 +279,7 @@ def to_schema( ), ) return cast( - "list[ModelDTOT]", + "Sequence[ModelDTOT]", convert( obj=data, type=list[schema_type], # type: ignore[valid-type] @@ -298,7 +298,7 @@ def to_schema( get_type_adapter(schema_type).validate_python(data, from_attributes=True), # pyright: ignore ) return cast( - "list[ModelDTOT]", + "Sequence[ModelDTOT]", get_type_adapter(list[schema_type]).validate_python(data, from_attributes=True), # type: ignore[valid-type] # pyright: ignore[reportUnknownArgumentType] ) diff --git a/sqlspec/utils/singleton.py b/sqlspec/utils/singleton.py index af33992..1468a77 100644 --- a/sqlspec/utils/singleton.py +++ b/sqlspec/utils/singleton.py @@ -1,5 +1,8 @@ from typing import Any, TypeVar +__all__ = ("SingletonMeta",) + + _T = TypeVar("_T") From 208bd5df2759d9a841916513a41054a06abfa446 Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Mon, 12 May 2025 02:36:46 +0000 Subject: [PATCH 10/11] feat: add `asyncmy` to the table --- README.md | 1 + docs/PYPI_README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 9b81af8..12b63e9 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,7 @@ This list is not final. If you have a driver you'd like to see added, please ope | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ | | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ | | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ | +| [`asyncmy`](https://github.com/long2ice/asyncmy) | MySQL | Async | ✅ | | [`snowflake`](https://docs.snowflake.com) | Snowflake | Sync | 🗓️ | ## Proposed Project Structure diff --git a/docs/PYPI_README.md b/docs/PYPI_README.md index 9b81af8..12b63e9 100644 --- a/docs/PYPI_README.md +++ b/docs/PYPI_README.md @@ -196,6 +196,7 @@ This list is not final. If you have a driver you'd like to see added, please ope | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ | | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ | | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ | +| [`asyncmy`](https://github.com/long2ice/asyncmy) | MySQL | Async | ✅ | | [`snowflake`](https://docs.snowflake.com) | Snowflake | Sync | 🗓️ | ## Proposed Project Structure From 1ac7902c37afb8be83d7d605b5ccaa373b0967ff Mon Sep 17 00:00:00 2001 From: Cody Fincher Date: Mon, 12 May 2025 02:39:57 +0000 Subject: [PATCH 11/11] fix: project links --- pyproject.toml | 7 ++++++- uv.lock | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d7c2739..f45bdbf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,12 @@ maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }] name = "sqlspec" readme = "README.md" requires-python = ">=3.9, <4.0" -version = "0.10.1" +version = "0.11.0" + +[project.urls] +Discord = "https://discord.gg/litestar" +Issue = "https://github.com/litestar-org/sqlspec/issues/" +Source = "https://github.com/litestar-org/sqlspec" [project.optional-dependencies] adbc = ["adbc_driver_manager", "pyarrow"] diff --git a/uv.lock b/uv.lock index 66f4a53..88c7df7 100644 --- a/uv.lock +++ b/uv.lock @@ -914,7 +914,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -3689,7 +3689,7 @@ wheels = [ [[package]] name = "sqlspec" -version = "0.10.1" +version = "0.11.0" source = { editable = "." } dependencies = [ { name = "eval-type-backport", marker = "python_full_version < '3.10'" },