diff --git a/docs/examples/adbc_example.py b/docs/examples/adbc_example.py index 1ce83b76c..2662d26fc 100644 --- a/docs/examples/adbc_example.py +++ b/docs/examples/adbc_example.py @@ -16,10 +16,10 @@ def adbc_example() -> None: # Create SQLSpec instance with ADBC (connects to dev PostgreSQL container) spec = SQLSpec() config = AdbcConfig(connection_config={"uri": "postgresql://postgres:postgres@localhost:5433/postgres"}) - spec.add_config(config) + db = spec.add_config(config) # Get a driver directly (drivers now have built-in query methods) - with spec.provide_session(config) as driver: + with spec.provide_session(db) as driver: # Create a table driver.execute(""" CREATE TABLE IF NOT EXISTS analytics_data ( diff --git a/pyproject.toml b/pyproject.toml index 746ff6bf3..c14a1e587 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }] name = "sqlspec" readme = "README.md" requires-python = ">=3.9, <4.0" -version = "0.17.0" +version = "0.17.1" [project.urls] Discord = "https://discord.gg/litestar" diff --git a/sqlspec/_sql.py b/sqlspec/_sql.py index 27b642534..0a393f3fb 100644 --- a/sqlspec/_sql.py +++ b/sqlspec/_sql.py @@ -33,13 +33,22 @@ Truncate, Update, ) +from sqlspec.builder._expression_wrappers import ( + AggregateExpression, + ConversionExpression, + FunctionExpression, + MathExpression, + StringExpression, +) from sqlspec.builder.mixins._join_operations import JoinBuilder from sqlspec.builder.mixins._select_operations import Case, SubqueryBuilder, WindowFunctionBuilder from sqlspec.exceptions import SQLBuilderError if TYPE_CHECKING: + from sqlspec.builder._expression_wrappers import ExpressionWrapper from sqlspec.core.statement import SQL + __all__ = ( "AlterTable", "Case", @@ -746,7 +755,9 @@ def raw(sql_fragment: str, **parameters: Any) -> "Union[exp.Expression, SQL]": # =================== @staticmethod - def count(column: Union[str, exp.Expression] = "*", distinct: bool = False) -> exp.Expression: + def count( + column: Union[str, exp.Expression, "ExpressionWrapper", "Case", "Column"] = "*", distinct: bool = False + ) -> AggregateExpression: """Create a COUNT expression. Args: @@ -756,12 +767,14 @@ def count(column: Union[str, exp.Expression] = "*", distinct: bool = False) -> e Returns: COUNT expression. """ - if column == "*": - return exp.Count(this=exp.Star(), distinct=distinct) - col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Count(this=col_expr, distinct=distinct) - - def count_distinct(self, column: Union[str, exp.Expression]) -> exp.Expression: + if isinstance(column, str) and column == "*": + expr = exp.Count(this=exp.Star(), distinct=distinct) + else: + col_expr = SQLFactory._extract_expression(column) + expr = exp.Count(this=col_expr, distinct=distinct) + return AggregateExpression(expr) + + def count_distinct(self, column: Union[str, exp.Expression, "ExpressionWrapper", "Case"]) -> AggregateExpression: """Create a COUNT(DISTINCT column) expression. Args: @@ -773,7 +786,9 @@ def count_distinct(self, column: Union[str, exp.Expression]) -> exp.Expression: return self.count(column, distinct=True) @staticmethod - def sum(column: Union[str, exp.Expression], distinct: bool = False) -> exp.Expression: + def sum( + column: Union[str, exp.Expression, "ExpressionWrapper", "Case"], distinct: bool = False + ) -> AggregateExpression: """Create a SUM expression. Args: @@ -783,11 +798,11 @@ def sum(column: Union[str, exp.Expression], distinct: bool = False) -> exp.Expre Returns: SUM expression. """ - col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Sum(this=col_expr, distinct=distinct) + col_expr = SQLFactory._extract_expression(column) + return AggregateExpression(exp.Sum(this=col_expr, distinct=distinct)) @staticmethod - def avg(column: Union[str, exp.Expression]) -> exp.Expression: + def avg(column: Union[str, exp.Expression, "ExpressionWrapper", "Case"]) -> AggregateExpression: """Create an AVG expression. Args: @@ -796,11 +811,11 @@ def avg(column: Union[str, exp.Expression]) -> exp.Expression: Returns: AVG expression. """ - col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Avg(this=col_expr) + col_expr = SQLFactory._extract_expression(column) + return AggregateExpression(exp.Avg(this=col_expr)) @staticmethod - def max(column: Union[str, exp.Expression]) -> exp.Expression: + def max(column: Union[str, exp.Expression, "ExpressionWrapper", "Case"]) -> AggregateExpression: """Create a MAX expression. Args: @@ -809,11 +824,11 @@ def max(column: Union[str, exp.Expression]) -> exp.Expression: Returns: MAX expression. """ - col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Max(this=col_expr) + col_expr = SQLFactory._extract_expression(column) + return AggregateExpression(exp.Max(this=col_expr)) @staticmethod - def min(column: Union[str, exp.Expression]) -> exp.Expression: + def min(column: Union[str, exp.Expression, "ExpressionWrapper", "Case"]) -> AggregateExpression: """Create a MIN expression. Args: @@ -822,15 +837,15 @@ def min(column: Union[str, exp.Expression]) -> exp.Expression: Returns: MIN expression. """ - col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Min(this=col_expr) + col_expr = SQLFactory._extract_expression(column) + return AggregateExpression(exp.Min(this=col_expr)) # =================== # Advanced SQL Operations # =================== @staticmethod - def rollup(*columns: Union[str, exp.Expression]) -> exp.Expression: + def rollup(*columns: Union[str, exp.Expression]) -> FunctionExpression: """Create a ROLLUP expression for GROUP BY clauses. Args: @@ -850,10 +865,10 @@ def rollup(*columns: Union[str, exp.Expression]) -> exp.Expression: ``` """ column_exprs = [exp.column(col) if isinstance(col, str) else col for col in columns] - return exp.Rollup(expressions=column_exprs) + return FunctionExpression(exp.Rollup(expressions=column_exprs)) @staticmethod - def cube(*columns: Union[str, exp.Expression]) -> exp.Expression: + def cube(*columns: Union[str, exp.Expression]) -> FunctionExpression: """Create a CUBE expression for GROUP BY clauses. Args: @@ -873,10 +888,10 @@ def cube(*columns: Union[str, exp.Expression]) -> exp.Expression: ``` """ column_exprs = [exp.column(col) if isinstance(col, str) else col for col in columns] - return exp.Cube(expressions=column_exprs) + return FunctionExpression(exp.Cube(expressions=column_exprs)) @staticmethod - def grouping_sets(*column_sets: Union[tuple[str, ...], list[str]]) -> exp.Expression: + def grouping_sets(*column_sets: Union[tuple[str, ...], list[str]]) -> FunctionExpression: """Create a GROUPING SETS expression for GROUP BY clauses. Args: @@ -908,10 +923,10 @@ def grouping_sets(*column_sets: Union[tuple[str, ...], list[str]]) -> exp.Expres else: set_expressions.append(exp.column(column_set)) - return exp.GroupingSets(expressions=set_expressions) + return FunctionExpression(exp.GroupingSets(expressions=set_expressions)) @staticmethod - def any(values: Union[list[Any], exp.Expression, str]) -> exp.Expression: + def any(values: Union[list[Any], exp.Expression, str]) -> FunctionExpression: """Create an ANY expression for use with comparison operators. Args: @@ -932,18 +947,18 @@ def any(values: Union[list[Any], exp.Expression, str]) -> exp.Expression: ``` """ if isinstance(values, list): - literals = [SQLFactory._to_literal(v) for v in values] - return exp.Any(this=exp.Array(expressions=literals)) + literals = [SQLFactory.to_literal(v) for v in values] + return FunctionExpression(exp.Any(this=exp.Array(expressions=literals))) if isinstance(values, str): # Parse as SQL parsed = exp.maybe_parse(values) # type: ignore[var-annotated] if parsed: - return exp.Any(this=parsed) - return exp.Any(this=exp.Literal.string(values)) - return exp.Any(this=values) + return FunctionExpression(exp.Any(this=parsed)) + return FunctionExpression(exp.Any(this=exp.Literal.string(values))) + return FunctionExpression(exp.Any(this=values)) @staticmethod - def not_any_(values: Union[list[Any], exp.Expression, str]) -> exp.Expression: + def not_any_(values: Union[list[Any], exp.Expression, str]) -> FunctionExpression: """Create a NOT ANY expression for use with comparison operators. Args: @@ -963,14 +978,14 @@ def not_any_(values: Union[list[Any], exp.Expression, str]) -> exp.Expression: ) ``` """ - return SQLFactory.any(values) # NOT ANY is handled by the comparison operator + return SQLFactory.any(values) # =================== # String Functions # =================== @staticmethod - def concat(*expressions: Union[str, exp.Expression]) -> exp.Expression: + def concat(*expressions: Union[str, exp.Expression]) -> StringExpression: """Create a CONCAT expression. Args: @@ -980,10 +995,10 @@ def concat(*expressions: Union[str, exp.Expression]) -> exp.Expression: CONCAT expression. """ exprs = [exp.column(expr) if isinstance(expr, str) else expr for expr in expressions] - return exp.Concat(expressions=exprs) + return StringExpression(exp.Concat(expressions=exprs)) @staticmethod - def upper(column: Union[str, exp.Expression]) -> exp.Expression: + def upper(column: Union[str, exp.Expression]) -> StringExpression: """Create an UPPER expression. Args: @@ -993,10 +1008,10 @@ def upper(column: Union[str, exp.Expression]) -> exp.Expression: UPPER expression. """ col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Upper(this=col_expr) + return StringExpression(exp.Upper(this=col_expr)) @staticmethod - def lower(column: Union[str, exp.Expression]) -> exp.Expression: + def lower(column: Union[str, exp.Expression]) -> StringExpression: """Create a LOWER expression. Args: @@ -1006,10 +1021,10 @@ def lower(column: Union[str, exp.Expression]) -> exp.Expression: LOWER expression. """ col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Lower(this=col_expr) + return StringExpression(exp.Lower(this=col_expr)) @staticmethod - def length(column: Union[str, exp.Expression]) -> exp.Expression: + def length(column: Union[str, exp.Expression]) -> StringExpression: """Create a LENGTH expression. Args: @@ -1019,14 +1034,14 @@ def length(column: Union[str, exp.Expression]) -> exp.Expression: LENGTH expression. """ col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Length(this=col_expr) + return StringExpression(exp.Length(this=col_expr)) # =================== # Math Functions # =================== @staticmethod - def round(column: Union[str, exp.Expression], decimals: int = 0) -> exp.Expression: + def round(column: Union[str, exp.Expression], decimals: int = 0) -> MathExpression: """Create a ROUND expression. Args: @@ -1038,15 +1053,15 @@ def round(column: Union[str, exp.Expression], decimals: int = 0) -> exp.Expressi """ col_expr = exp.column(column) if isinstance(column, str) else column if decimals == 0: - return exp.Round(this=col_expr) - return exp.Round(this=col_expr, expression=exp.Literal.number(decimals)) + return MathExpression(exp.Round(this=col_expr)) + return MathExpression(exp.Round(this=col_expr, expression=exp.Literal.number(decimals))) # =================== # Conversion Functions # =================== @staticmethod - def _to_literal(value: Any) -> exp.Expression: + def to_literal(value: Any) -> FunctionExpression: """Convert a Python value to a SQLGlot literal expression. Uses SQLGlot's built-in exp.convert() function for optimal dialect-agnostic @@ -1063,12 +1078,52 @@ def _to_literal(value: Any) -> exp.Expression: Returns: SQLGlot expression representing the literal value. """ + if isinstance(value, exp.Expression): + return FunctionExpression(value) + return FunctionExpression(exp.convert(value)) + + @staticmethod + def _to_expression(value: Any) -> exp.Expression: + """Convert a Python value to a raw SQLGlot expression. + + Args: + value: Python value or SQLGlot expression to convert. + + Returns: + Raw SQLGlot expression. + """ + if isinstance(value, exp.Expression): + return value + return exp.convert(value) + + @staticmethod + def _extract_expression(value: Any) -> exp.Expression: + """Extract SQLGlot expression from value, handling our wrapper types. + + Args: + value: String, SQLGlot expression, or our wrapper type. + + Returns: + Raw SQLGlot expression. + """ + from sqlspec.builder._expression_wrappers import ExpressionWrapper + from sqlspec.builder.mixins._select_operations import Case + + if isinstance(value, str): + return exp.column(value) + if isinstance(value, Column): + return value._expression + if isinstance(value, ExpressionWrapper): + return value.expression + if isinstance(value, Case): + # Case has _expression property via trait + return exp.Case(ifs=value._conditions, default=value._default) if isinstance(value, exp.Expression): return value return exp.convert(value) @staticmethod - def decode(column: Union[str, exp.Expression], *args: Union[str, exp.Expression, Any]) -> exp.Expression: + def decode(column: Union[str, exp.Expression], *args: Union[str, exp.Expression, Any]) -> FunctionExpression: """Create a DECODE expression (Oracle-style conditional logic). DECODE compares column to each search value and returns the corresponding result. @@ -1105,22 +1160,22 @@ def decode(column: Union[str, exp.Expression], *args: Union[str, exp.Expression, for i in range(0, len(args) - 1, 2): if i + 1 >= len(args): # Odd number of args means last one is default - default = SQLFactory._to_literal(args[i]) + default = SQLFactory._to_expression(args[i]) break search_val = args[i] result_val = args[i + 1] - search_expr = SQLFactory._to_literal(search_val) - result_expr = SQLFactory._to_literal(result_val) + search_expr = SQLFactory._to_expression(search_val) + result_expr = SQLFactory._to_expression(result_val) condition = exp.EQ(this=col_expr, expression=search_expr) - conditions.append(exp.When(this=condition, then=result_expr)) + conditions.append(exp.If(this=condition, true=result_expr)) - return exp.Case(ifs=conditions, default=default) + return FunctionExpression(exp.Case(ifs=conditions, default=default)) @staticmethod - def cast(column: Union[str, exp.Expression], data_type: str) -> exp.Expression: + def cast(column: Union[str, exp.Expression], data_type: str) -> ConversionExpression: """Create a CAST expression for type conversion. Args: @@ -1131,10 +1186,10 @@ def cast(column: Union[str, exp.Expression], data_type: str) -> exp.Expression: CAST expression. """ col_expr = exp.column(column) if isinstance(column, str) else column - return exp.Cast(this=col_expr, to=exp.DataType.build(data_type)) + return ConversionExpression(exp.Cast(this=col_expr, to=exp.DataType.build(data_type))) @staticmethod - def coalesce(*expressions: Union[str, exp.Expression]) -> exp.Expression: + def coalesce(*expressions: Union[str, exp.Expression]) -> ConversionExpression: """Create a COALESCE expression. Args: @@ -1144,10 +1199,12 @@ def coalesce(*expressions: Union[str, exp.Expression]) -> exp.Expression: COALESCE expression. """ exprs = [exp.column(expr) if isinstance(expr, str) else expr for expr in expressions] - return exp.Coalesce(expressions=exprs) + return ConversionExpression(exp.Coalesce(expressions=exprs)) @staticmethod - def nvl(column: Union[str, exp.Expression], substitute_value: Union[str, exp.Expression, Any]) -> exp.Expression: + def nvl( + column: Union[str, exp.Expression], substitute_value: Union[str, exp.Expression, Any] + ) -> ConversionExpression: """Create an NVL (Oracle-style) expression using COALESCE. Args: @@ -1158,15 +1215,15 @@ def nvl(column: Union[str, exp.Expression], substitute_value: Union[str, exp.Exp COALESCE expression equivalent to NVL. """ col_expr = exp.column(column) if isinstance(column, str) else column - sub_expr = SQLFactory._to_literal(substitute_value) - return exp.Coalesce(expressions=[col_expr, sub_expr]) + sub_expr = SQLFactory._to_expression(substitute_value) + return ConversionExpression(exp.Coalesce(expressions=[col_expr, sub_expr])) @staticmethod def nvl2( column: Union[str, exp.Expression], value_if_not_null: Union[str, exp.Expression, Any], value_if_null: Union[str, exp.Expression, Any], - ) -> exp.Expression: + ) -> ConversionExpression: """Create an NVL2 (Oracle-style) expression using CASE. NVL2 returns value_if_not_null if column is not NULL, @@ -1187,22 +1244,22 @@ def nvl2( ``` """ col_expr = exp.column(column) if isinstance(column, str) else column - not_null_expr = SQLFactory._to_literal(value_if_not_null) - null_expr = SQLFactory._to_literal(value_if_null) + not_null_expr = SQLFactory._to_expression(value_if_not_null) + null_expr = SQLFactory._to_expression(value_if_null) # Create CASE WHEN column IS NOT NULL THEN value_if_not_null ELSE value_if_null END is_null = exp.Is(this=col_expr, expression=exp.Null()) condition = exp.Not(this=is_null) when_clause = exp.If(this=condition, true=not_null_expr) - return exp.Case(ifs=[when_clause], default=null_expr) + return ConversionExpression(exp.Case(ifs=[when_clause], default=null_expr)) # =================== # Bulk Operations # =================== @staticmethod - def bulk_insert(table_name: str, column_count: int, placeholder_style: str = "?") -> exp.Expression: + def bulk_insert(table_name: str, column_count: int, placeholder_style: str = "?") -> FunctionExpression: """Create bulk INSERT expression for executemany operations. This is specifically for bulk loading operations like CSV ingestion where @@ -1237,13 +1294,15 @@ def bulk_insert(table_name: str, column_count: int, placeholder_style: str = "?" # Creates: INSERT INTO "my_table" VALUES (:1, :2, :3) ``` """ - return exp.Insert( - this=exp.Table(this=exp.to_identifier(table_name)), - expression=exp.Values( - expressions=[ - exp.Tuple(expressions=[exp.Placeholder(this=placeholder_style) for _ in range(column_count)]) - ] - ), + return FunctionExpression( + exp.Insert( + this=exp.Table(this=exp.to_identifier(table_name)), + expression=exp.Values( + expressions=[ + exp.Tuple(expressions=[exp.Placeholder(this=placeholder_style) for _ in range(column_count)]) + ] + ), + ) ) def truncate(self, table_name: str) -> "Truncate": @@ -1297,7 +1356,7 @@ def row_number( self, partition_by: Optional[Union[str, list[str], exp.Expression]] = None, order_by: Optional[Union[str, list[str], exp.Expression]] = None, - ) -> exp.Expression: + ) -> FunctionExpression: """Create a ROW_NUMBER() window function. Args: @@ -1313,7 +1372,7 @@ def rank( self, partition_by: Optional[Union[str, list[str], exp.Expression]] = None, order_by: Optional[Union[str, list[str], exp.Expression]] = None, - ) -> exp.Expression: + ) -> FunctionExpression: """Create a RANK() window function. Args: @@ -1329,7 +1388,7 @@ def dense_rank( self, partition_by: Optional[Union[str, list[str], exp.Expression]] = None, order_by: Optional[Union[str, list[str], exp.Expression]] = None, - ) -> exp.Expression: + ) -> FunctionExpression: """Create a DENSE_RANK() window function. Args: @@ -1347,7 +1406,7 @@ def _create_window_function( func_args: list[exp.Expression], partition_by: Optional[Union[str, list[str], exp.Expression]] = None, order_by: Optional[Union[str, list[str], exp.Expression]] = None, - ) -> exp.Expression: + ) -> FunctionExpression: """Helper to create window function expressions. Args: @@ -1373,13 +1432,13 @@ def _create_window_function( if order_by: if isinstance(order_by, str): - over_args["order"] = [exp.column(order_by).asc()] + over_args["order"] = exp.Order(expressions=[exp.column(order_by).asc()]) elif isinstance(order_by, list): - over_args["order"] = [exp.column(col).asc() for col in order_by] + over_args["order"] = exp.Order(expressions=[exp.column(col).asc() for col in order_by]) elif isinstance(order_by, exp.Expression): - over_args["order"] = [order_by] + over_args["order"] = exp.Order(expressions=[order_by]) - return exp.Window(this=func_expr, **over_args) + return FunctionExpression(exp.Window(this=func_expr, **over_args)) # Create a default SQL factory instance diff --git a/sqlspec/builder/_column.py b/sqlspec/builder/_column.py index 3b399d116..40a786cf7 100644 --- a/sqlspec/builder/_column.py +++ b/sqlspec/builder/_column.py @@ -5,7 +5,7 @@ """ from collections.abc import Iterable -from typing import Any, Optional +from typing import Any, Optional, cast from sqlglot import exp @@ -241,6 +241,10 @@ def desc(self) -> exp.Ordered: """Create a DESC ordering expression.""" return exp.Ordered(this=self._expression, desc=True) + def as_(self, alias: str) -> exp.Alias: + """Create an aliased expression.""" + return cast("exp.Alias", exp.alias_(self._expression, alias)) + def __repr__(self) -> str: if self.table: return f"Column<{self.table}.{self.name}>" diff --git a/sqlspec/builder/_expression_wrappers.py b/sqlspec/builder/_expression_wrappers.py new file mode 100644 index 000000000..6f1379bf2 --- /dev/null +++ b/sqlspec/builder/_expression_wrappers.py @@ -0,0 +1,46 @@ +"""Expression wrapper classes for proper type annotations.""" + +from typing import cast + +from sqlglot import exp + +__all__ = ("AggregateExpression", "ConversionExpression", "FunctionExpression", "MathExpression", "StringExpression") + + +class ExpressionWrapper: + """Base wrapper for SQLGlot expressions.""" + + def __init__(self, expression: exp.Expression) -> None: + self._expression = expression + + def as_(self, alias: str) -> exp.Alias: + """Create an aliased expression.""" + return cast("exp.Alias", exp.alias_(self._expression, alias)) + + @property + def expression(self) -> exp.Expression: + """Get the underlying SQLGlot expression.""" + return self._expression + + def __str__(self) -> str: + return str(self._expression) + + +class AggregateExpression(ExpressionWrapper): + """Aggregate functions like COUNT, SUM, AVG.""" + + +class FunctionExpression(ExpressionWrapper): + """General SQL functions.""" + + +class MathExpression(ExpressionWrapper): + """Mathematical functions like ROUND.""" + + +class StringExpression(ExpressionWrapper): + """String functions like UPPER, LOWER, LENGTH.""" + + +class ConversionExpression(ExpressionWrapper): + """Conversion functions like CAST, COALESCE.""" diff --git a/sqlspec/builder/_insert.py b/sqlspec/builder/_insert.py index 3d88940ba..0fa8e4315 100644 --- a/sqlspec/builder/_insert.py +++ b/sqlspec/builder/_insert.py @@ -412,9 +412,7 @@ def do_update(self, **kwargs: Any) -> "Insert": # Create ON CONFLICT with proper structure conflict_keys = [exp.to_identifier(col) for col in self._columns] if self._columns else None on_conflict = exp.OnConflict( - conflict_keys=conflict_keys, - action=exp.var("DO UPDATE"), - expressions=set_expressions if set_expressions else None, + conflict_keys=conflict_keys, action=exp.var("DO UPDATE"), expressions=set_expressions or None ) insert_expr.set("conflict", on_conflict) diff --git a/sqlspec/builder/_update.py b/sqlspec/builder/_update.py index 3a4337802..90f5c5b14 100644 --- a/sqlspec/builder/_update.py +++ b/sqlspec/builder/_update.py @@ -44,26 +44,26 @@ class Update( update_query = ( Update() .table("users") - .set(name="John Doe") - .set(email="john@example.com") + .set_(name="John Doe") + .set_(email="john@example.com") .where("id = 1") ) update_query = ( - Update("users").set(name="John Doe").where("id = 1") + Update("users").set_(name="John Doe").where("id = 1") ) update_query = ( Update() .table("users") - .set(status="active") + .set_(status="active") .where_eq("id", 123) ) update_query = ( Update() .table("users", "u") - .set(name="Updated Name") + .set_(name="Updated Name") .from_("profiles", "p") .where("u.id = p.user_id AND p.is_verified = true") ) diff --git a/sqlspec/builder/mixins/_order_limit_operations.py b/sqlspec/builder/mixins/_order_limit_operations.py index a521f2b2f..93c40e0e9 100644 --- a/sqlspec/builder/mixins/_order_limit_operations.py +++ b/sqlspec/builder/mixins/_order_limit_operations.py @@ -10,6 +10,9 @@ from sqlspec.exceptions import SQLBuilderError if TYPE_CHECKING: + from sqlspec.builder._column import Column + from sqlspec.builder._expression_wrappers import ExpressionWrapper + from sqlspec.builder.mixins._select_operations import Case from sqlspec.protocols import SQLBuilderProtocol __all__ = ("LimitOffsetClauseMixin", "OrderByClauseMixin", "ReturningClauseMixin") @@ -24,7 +27,7 @@ class OrderByClauseMixin: # Type annotation for PyRight - this will be provided by the base class _expression: Optional[exp.Expression] - def order_by(self, *items: Union[str, exp.Ordered], desc: bool = False) -> Self: + def order_by(self, *items: Union[str, exp.Ordered, "Column"], desc: bool = False) -> Self: """Add ORDER BY clause. Args: @@ -49,7 +52,13 @@ def order_by(self, *items: Union[str, exp.Ordered], desc: bool = False) -> Self: if desc: order_item = order_item.desc() else: - order_item = item + # Extract expression from Column objects or use as-is for sqlglot expressions + from sqlspec._sql import SQLFactory + + extracted_item = SQLFactory._extract_expression(item) + order_item = extracted_item + if desc and not isinstance(item, exp.Ordered): + order_item = order_item.desc() current_expr = current_expr.order_by(order_item, copy=False) builder._expression = current_expr return cast("Self", builder) @@ -111,7 +120,7 @@ class ReturningClauseMixin: # Type annotation for PyRight - this will be provided by the base class _expression: Optional[exp.Expression] - def returning(self, *columns: Union[str, exp.Expression]) -> Self: + def returning(self, *columns: Union[str, exp.Expression, "Column", "ExpressionWrapper", "Case"]) -> Self: """Add RETURNING clause to the statement. Args: @@ -130,6 +139,9 @@ def returning(self, *columns: Union[str, exp.Expression]) -> Self: if not isinstance(self._expression, valid_types): msg = "RETURNING is only supported for INSERT, UPDATE, and DELETE statements." raise SQLBuilderError(msg) - returning_exprs = [exp.column(c) if isinstance(c, str) else c for c in columns] + # Extract expressions from various wrapper types + from sqlspec._sql import SQLFactory + + returning_exprs = [SQLFactory._extract_expression(c) for c in columns] self._expression.set("returning", exp.Returning(expressions=returning_exprs)) return self diff --git a/sqlspec/builder/mixins/_select_operations.py b/sqlspec/builder/mixins/_select_operations.py index aa463dc81..ba9c2f0ae 100644 --- a/sqlspec/builder/mixins/_select_operations.py +++ b/sqlspec/builder/mixins/_select_operations.py @@ -858,7 +858,7 @@ def when(self, condition: Union[str, exp.Expression], value: Union[str, exp.Expr from sqlspec._sql import SQLFactory cond_expr = exp.maybe_parse(condition) or exp.column(condition) if isinstance(condition, str) else condition - val_expr = SQLFactory._to_literal(value) + val_expr = SQLFactory._to_expression(value) # SQLGlot uses exp.If for CASE WHEN clauses, not exp.When when_clause = exp.If(this=cond_expr, true=val_expr) @@ -876,7 +876,7 @@ def else_(self, value: Union[str, exp.Expression, Any]) -> Self: """ from sqlspec._sql import SQLFactory - self._default = SQLFactory._to_literal(value) + self._default = SQLFactory._to_expression(value) return self def end(self) -> Self: diff --git a/sqlspec/builder/mixins/_update_operations.py b/sqlspec/builder/mixins/_update_operations.py index 8fe8e47d1..b6bf530b8 100644 --- a/sqlspec/builder/mixins/_update_operations.py +++ b/sqlspec/builder/mixins/_update_operations.py @@ -111,10 +111,10 @@ def set(self, *args: Any, **kwargs: Any) -> Self: """Set columns and values for the UPDATE statement. Supports: - - set(column, value) - - set(mapping) - - set(**kwargs) - - set(mapping, **kwargs) + - set_(column, value) + - set_(mapping) + - set_(**kwargs) + - set_(mapping, **kwargs) Args: *args: Either (column, value) or a mapping. diff --git a/sqlspec/protocols.py b/sqlspec/protocols.py index 217ce7228..bb6001a98 100644 --- a/sqlspec/protocols.py +++ b/sqlspec/protocols.py @@ -20,6 +20,7 @@ __all__ = ( "BytesConvertibleProtocol", "DictProtocol", + "ExpressionWithAliasProtocol", "FilterAppenderProtocol", "FilterParameterProtocol", "HasExpressionProtocol", @@ -172,6 +173,15 @@ def __bytes__(self) -> bytes: ... +@runtime_checkable +class ExpressionWithAliasProtocol(Protocol): + """Protocol for SQL expressions that support aliasing with as_() method.""" + + def as_(self, alias: str, **kwargs: Any) -> "exp.Alias": + """Create an aliased expression.""" + ... + + @runtime_checkable class ObjectStoreItemProtocol(Protocol): """Protocol for object store items with path/key attributes.""" diff --git a/tests/unit/test_builder/test_parameter_naming.py b/tests/unit/test_builder/test_parameter_naming.py index 3c5bd30ca..7ebca5334 100644 --- a/tests/unit/test_builder/test_parameter_naming.py +++ b/tests/unit/test_builder/test_parameter_naming.py @@ -13,6 +13,8 @@ - Edge cases and error conditions """ +import string + from sqlspec import sql @@ -329,7 +331,7 @@ def test_parameter_names_are_sql_safe() -> None: assert "--" not in param_name # Should be valid identifier-like - assert param_name.replace("_", "").replace("0123456789", "").isalpha() or "_" in param_name + assert param_name.replace("_", "").replace(string.digits, "").isalpha() or "_" in param_name def test_empty_and_null_values_preserve_column_names() -> None: diff --git a/tests/unit/test_sql_factory.py b/tests/unit/test_sql_factory.py index 04988a56a..8c081ea1c 100644 --- a/tests/unit/test_sql_factory.py +++ b/tests/unit/test_sql_factory.py @@ -416,35 +416,63 @@ def test_all_ddl_methods_exist() -> None: def test_count_function() -> None: """Test sql.count() function.""" + from sqlspec.builder._expression_wrappers import AggregateExpression + expr = sql.count() - assert isinstance(expr, exp.Expression) + assert isinstance(expr, AggregateExpression) + assert hasattr(expr, "as_") + assert hasattr(expr, "expression") + assert isinstance(expr.expression, exp.Expression) count_column = sql.count("user_id") - assert isinstance(count_column, exp.Expression) + assert isinstance(count_column, AggregateExpression) + assert hasattr(count_column, "as_") + assert hasattr(count_column, "expression") + assert isinstance(count_column.expression, exp.Expression) def test_sum_function() -> None: """Test sql.sum() function.""" + from sqlspec.builder._expression_wrappers import AggregateExpression + expr = sql.sum("amount") - assert isinstance(expr, exp.Expression) + assert isinstance(expr, AggregateExpression) + assert hasattr(expr, "as_") + assert hasattr(expr, "expression") + assert isinstance(expr.expression, exp.Expression) def test_avg_function() -> None: """Test sql.avg() function.""" + from sqlspec.builder._expression_wrappers import AggregateExpression + expr = sql.avg("score") - assert isinstance(expr, exp.Expression) + assert isinstance(expr, AggregateExpression) + assert hasattr(expr, "as_") + assert hasattr(expr, "expression") + assert isinstance(expr.expression, exp.Expression) def test_max_function() -> None: """Test sql.max() function.""" + from sqlspec.builder._expression_wrappers import AggregateExpression + expr = sql.max("created_at") - assert isinstance(expr, exp.Expression) + assert isinstance(expr, AggregateExpression) + assert hasattr(expr, "as_") + assert hasattr(expr, "expression") + assert isinstance(expr.expression, exp.Expression) def test_min_function() -> None: """Test sql.min() function.""" + from sqlspec.builder._expression_wrappers import AggregateExpression + expr = sql.min("price") - assert isinstance(expr, exp.Expression) + assert isinstance(expr, AggregateExpression) + assert hasattr(expr, "as_") + assert hasattr(expr, "expression") + assert isinstance(expr.expression, exp.Expression) def test_column_method() -> None: @@ -1074,7 +1102,7 @@ def test_type_compatibility_across_all_operations() -> None: def test_update_set_method_with_sql_objects() -> None: - """Test that UPDATE.set() method properly handles SQL objects with kwargs.""" + """Test that UPDATE.set_() method properly handles SQL objects with kwargs.""" raw_timestamp = sql.raw("NOW()") raw_computed = sql.raw("UPPER(:value)", value="test") @@ -1097,7 +1125,7 @@ def test_update_set_method_with_sql_objects() -> None: def test_update_set_method_backward_compatibility() -> None: - """Test that UPDATE.set() method maintains backward compatibility with dict.""" + """Test that UPDATE.set_() method maintains backward compatibility with dict.""" raw_timestamp = sql.raw("NOW()") # Test using dict (original API) diff --git a/uv.lock b/uv.lock index aa64a2bb5..113cfe1dd 100644 --- a/uv.lock +++ b/uv.lock @@ -1562,7 +1562,7 @@ wheels = [ [[package]] name = "google-cloud-spanner" -version = "3.56.0" +version = "3.57.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core", extra = ["grpc"] }, @@ -1573,9 +1573,9 @@ dependencies = [ { name = "protobuf" }, { name = "sqlparse" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/67/33c120f21462173846b202c84bb9979f12ff8227cc6de4e0957c37fd9a60/google_cloud_spanner-3.56.0.tar.gz", hash = "sha256:bf7e4359d2f2148eda18a11f909813d07e794347a02f56dfbbd544418d30e5b2", size = 701321, upload-time = "2025-07-24T11:12:56.461Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/e8/e008f9ffa2dcf596718d2533d96924735110378853c55f730d2527a19e04/google_cloud_spanner-3.57.0.tar.gz", hash = "sha256:73f52f58617449fcff7073274a7f7a798f4f7b2788eda26de3b7f98ad857ab99", size = 701574, upload-time = "2025-08-14T15:24:59.18Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/e9/60ac93f633e3ed78d399d3f0e2117c4e4e751a2ac8c87ae994d86cae7a2b/google_cloud_spanner-3.56.0-py3-none-any.whl", hash = "sha256:64f732a44f6a2892b5cc3be88e6e2cc92b5e52db883d1e946e1e3ff93c9745f0", size = 501309, upload-time = "2025-07-24T11:12:54.892Z" }, + { url = "https://files.pythonhosted.org/packages/3a/9f/66fe9118bc0e593b65ade612775e397f596b0bcd75daa3ea63dbe1020f95/google_cloud_spanner-3.57.0-py3-none-any.whl", hash = "sha256:5b10b40bc646091f1b4cbb2e7e2e82ec66bcce52c7105f86b65070d34d6df86f", size = 501380, upload-time = "2025-08-14T15:24:57.683Z" }, ] [[package]] @@ -3311,100 +3311,100 @@ wheels = [ [[package]] name = "psqlpy" -version = "0.11.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/68/1e7ad83c3377beac8a204ca60b588efc1eb6f85e1aafddf0429b6416e502/psqlpy-0.11.3.tar.gz", hash = "sha256:0c432b38fa869aa4c1e2783c5314d5f3c76dec73bcc44f9287d13d9d8547d7ad", size = 291099, upload-time = "2025-07-16T21:42:29.003Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/48/06da35f80ecc1614e40f00de52e5f2e6ab1bf54aad73f464ec3adcc31145/psqlpy-0.11.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c55f25e6029126ae2617271e9e3b691458c13ba9e3f4b932ebb99e3fa6367e41", size = 4306284, upload-time = "2025-07-16T21:39:26.68Z" }, - { url = "https://files.pythonhosted.org/packages/0e/f8/59c3684b069e8887b10d3872f5246d50cf48c414219aeffd95d9f1bc4e81/psqlpy-0.11.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16b86a013e6d651470e3fc39cd64395146998c5c9fc1b9d24987d86d6a19a713", size = 4514285, upload-time = "2025-07-16T21:39:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/70/b1/5663173d263af06a73c68bc8184f36258c18a82b374d3b135c62d3e6d289/psqlpy-0.11.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd8ab8619f5c8884a14c1de94521eaa3da3a1d74cec7642027ecaf316b71472", size = 5024409, upload-time = "2025-07-16T21:39:33.169Z" }, - { url = "https://files.pythonhosted.org/packages/71/b3/42be675aabc38f4a5aa63621b2cee65aab8546778958902c18a430303da1/psqlpy-0.11.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d0cb2c596c85c3e30e83a395e433a15e90018719d51aed242121a1895917be1a", size = 4303932, upload-time = "2025-07-16T21:39:35.234Z" }, - { url = "https://files.pythonhosted.org/packages/51/e9/de6754110357875be6350d1bf14787ea1dc15213331691241dc9a7c623e1/psqlpy-0.11.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ad747d7bd1ef833bf46e10b55105a11a0ee619d023c6bb3a097b1119f7e241d", size = 4906446, upload-time = "2025-07-16T21:39:37.012Z" }, - { url = "https://files.pythonhosted.org/packages/64/21/e93377dae6273b4eb114f0332dd39b073910f3080bb41759afa6d610bd72/psqlpy-0.11.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2648bd8a431bc9ac878ddb987d15c9ada6ed66c266d26a1e85439e2ea76fa656", size = 5017799, upload-time = "2025-07-16T21:39:38.984Z" }, - { url = "https://files.pythonhosted.org/packages/50/ae/fb3baa02900deebe71895910b8c809eda658fb91420a7b6b32d338d78928/psqlpy-0.11.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2b0740b687d363b5e8a8fad3b8e1c806887a71dee036eccedb45943649980d4", size = 4671190, upload-time = "2025-07-16T21:39:40.724Z" }, - { url = "https://files.pythonhosted.org/packages/a7/51/d564be565a5aedd369faae988563c9ed94e537e16771fce925c27640f5f2/psqlpy-0.11.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:186cf1c5dc63a70197d12b6656daf44b937e7a7f1cc552e535df35fbdafd7833", size = 4912774, upload-time = "2025-07-16T21:39:42.841Z" }, - { url = "https://files.pythonhosted.org/packages/e3/61/a2a0a58057f2d6a19443c8beeb796a969fed99ef6c3c5be23fd48872aa6b/psqlpy-0.11.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1ec6125b1cafc157f540b185b323e7988e7c778f43de18e87bc26cafa70196d6", size = 4939079, upload-time = "2025-07-16T21:39:44.728Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c2/784ca302ddbcf9b94eb3cefa5d4585f35abfbd9339a0258c9dc6a7152b42/psqlpy-0.11.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e9bc75e93209d3f0519bba72e1db46f96a9c1022614830e1547c2c6699d2024c", size = 5057943, upload-time = "2025-07-16T21:39:46.49Z" }, - { url = "https://files.pythonhosted.org/packages/8b/76/1cab00dd8c4036abaa9e32e977263a77032059bc4fdab31c8bac9cb7fd54/psqlpy-0.11.3-cp310-cp310-win32.whl", hash = "sha256:6f783e0319bb677bf605edda9df7303ebb2642000237fb1f68c1212e191e80d4", size = 3356429, upload-time = "2025-07-16T21:39:48.168Z" }, - { url = "https://files.pythonhosted.org/packages/59/74/1cddb5c4fea1d9904bc2a2f57a5f0c202f98e8ce4ac627203882f22ac8e6/psqlpy-0.11.3-cp310-cp310-win_amd64.whl", hash = "sha256:cd08132ca91fd7383a3df4259bc45544a794f55708b17d788323a8fdbc676c5e", size = 3763418, upload-time = "2025-07-16T21:39:49.892Z" }, - { url = "https://files.pythonhosted.org/packages/f3/9b/44069b3c741763af8aa4c71111aa90ad60c9ba9a466b8b860a46a1aeb013/psqlpy-0.11.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0ce62c9a9092d6e0cfc4930c6438274748564172f0afa71afe0b7ff1b32f1f75", size = 4305668, upload-time = "2025-07-16T21:39:51.694Z" }, - { url = "https://files.pythonhosted.org/packages/50/53/289a3f82615098ba3edac5002ddf75cdd9275cc7770435b8ac16c80fab25/psqlpy-0.11.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0364e7c5a7023c3ab4207a8ab6ab97b1657cec631db22d6d9c73972750fe2b0a", size = 4514050, upload-time = "2025-07-16T21:39:53.894Z" }, - { url = "https://files.pythonhosted.org/packages/5c/ba/b3c5f28a74d70cc740575f3e505591461bc380c5b6317e70b42dbc254472/psqlpy-0.11.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66e40eceb45eeb6f2a5b570aa836ac830fcf0122c3690ecce05c72d039d8f9ec", size = 5024951, upload-time = "2025-07-16T21:39:56.15Z" }, - { url = "https://files.pythonhosted.org/packages/12/ab/711563b1b68c2c7811433636f3282834560c5a07631a29a2fca35100e8bb/psqlpy-0.11.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1a8fa3c36c16fbe11b848b5850ccdb9286389df8999d463a6f06f6774d84c2d9", size = 4303733, upload-time = "2025-07-16T21:39:58.146Z" }, - { url = "https://files.pythonhosted.org/packages/5d/e2/1eae6aa1e48b7db81cc66c675580b7b732365229b12212168133160890d8/psqlpy-0.11.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8db109dab943fb16e9f944db494f7d781ed0b37e2628d4e26d3c86b06b46d26", size = 4906672, upload-time = "2025-07-16T21:40:01.157Z" }, - { url = "https://files.pythonhosted.org/packages/3a/e8/d4fc0434f958d2e171efcf793a2e6e93298336b4267df5ce1542193e722b/psqlpy-0.11.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7cbf5f860b3da8694999d29ff8f72c5086a2e1826e263efc8a7ad11d0e789d9", size = 5017456, upload-time = "2025-07-16T21:40:02.959Z" }, - { url = "https://files.pythonhosted.org/packages/3b/f8/45e09f45d50635a18759a0b333133d9b1bec044a41765b642ed7a436bfd1/psqlpy-0.11.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3685ce63b280f7a0273bc491891d731f6137c9ca40348c45359fc4b76d3c923f", size = 4685966, upload-time = "2025-07-16T21:40:05.275Z" }, - { url = "https://files.pythonhosted.org/packages/d5/a9/140aa40c2abf70a93de2cc7780a3d93397c593de2f0feee47d9c8243f87f/psqlpy-0.11.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a7454dcce0ed71ca742e8d4258b7a7cdee5bb6df12760fb74867a8e189209ed", size = 4911338, upload-time = "2025-07-16T21:40:07.446Z" }, - { url = "https://files.pythonhosted.org/packages/5e/92/bd0622c4e5709a3a18a86e5c3e05f8a7b9ce0538e405dbb6155a926c9c64/psqlpy-0.11.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9f3b771d5c68d6dff63fd3ebd587708d0f479775bef77bcfafe0aa941d86329e", size = 4939545, upload-time = "2025-07-16T21:40:09.263Z" }, - { url = "https://files.pythonhosted.org/packages/04/f6/c6f20306ce38c79c0ac0689a6349777084a1b27ea12b55feea818e617800/psqlpy-0.11.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96ed55c5dec7ceb02f6db67b9a7a7ea635df27c7fbc13be1c66d74695ef0c259", size = 5058982, upload-time = "2025-07-16T21:40:11.151Z" }, - { url = "https://files.pythonhosted.org/packages/08/19/cf5c0f3f461fe95bfa557624a88a925d24a58343a7962eff111d7e0cf70c/psqlpy-0.11.3-cp311-cp311-win32.whl", hash = "sha256:5a7a6c5faaa578f95533700f76b28b2e4264904a1e328ca446bfa893eeefc030", size = 3354854, upload-time = "2025-07-16T21:40:13.081Z" }, - { url = "https://files.pythonhosted.org/packages/a6/bc/f81cb9074cad038694c4e5b8bb8205096a583052913f1074915484b4cd15/psqlpy-0.11.3-cp311-cp311-win_amd64.whl", hash = "sha256:51f3e751f2f45a1e215d18111528340ecd5bdfb86ccde59f7d514f9e47d95027", size = 3763042, upload-time = "2025-07-16T21:40:14.834Z" }, - { url = "https://files.pythonhosted.org/packages/1f/6e/5a7cc68a4c399401ff49c29517fca7ac632a448d5e13b3abee7ed4e7642e/psqlpy-0.11.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:104c92ba3da60c0d13fb341d674c43593e2d2fc11b273515d5728f5d8ed5082d", size = 4291408, upload-time = "2025-07-16T21:40:16.626Z" }, - { url = "https://files.pythonhosted.org/packages/e4/99/99d73dd41e51d19f97d70906097a9616fcd1bfc29a3c8bc3c81edd94acf1/psqlpy-0.11.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c396e9d5a641e1d642b2b324262653429528454ef393bdee56800e0eac05e1", size = 4496394, upload-time = "2025-07-16T21:40:18.754Z" }, - { url = "https://files.pythonhosted.org/packages/d8/8c/787af160394e696eb161305dac57a0f4a693a3755ef4085d9b5136abdf60/psqlpy-0.11.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbe7e7f595f68cafdea27ab172dfa4840a5eb26616616a7c0d103671b7545fb", size = 5026443, upload-time = "2025-07-16T21:40:20.765Z" }, - { url = "https://files.pythonhosted.org/packages/bc/bf/5bfac94b8ada3901ada1c3deab37244cdff78d4c1b8a8bfdf907aede162f/psqlpy-0.11.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d32222318c80aea3cda4111cd8f860ea9711c657a67f494546c36dc38c172d03", size = 4303057, upload-time = "2025-07-16T21:40:22.543Z" }, - { url = "https://files.pythonhosted.org/packages/fc/6a/a6e3ecb02d0d8838ccb4fc6717f9d11a3f683c1b417cddd05ae297d5958b/psqlpy-0.11.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:787cfbd40c22d9a101fdee8bbbb641f6c60588a808ef72bf5f03b5776088898b", size = 4904929, upload-time = "2025-07-16T21:40:24.345Z" }, - { url = "https://files.pythonhosted.org/packages/f2/b1/4223375808cb13ff1bbe5575c057c5f13238dd0ca71be19b1d28650ce610/psqlpy-0.11.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a19df6b85ed83aa7d4be1b4ffd26a7e36544a78e14c89d156270bc65d1512316", size = 5009551, upload-time = "2025-07-16T21:40:26.156Z" }, - { url = "https://files.pythonhosted.org/packages/20/11/0737e3a4d39394a715ef4e7647147960c76e985a1ee1603eab1d4c28bef8/psqlpy-0.11.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2bb3450b4a7fe0bebf41f5b8e2b40e48470e1305d59a393302d7e9a10132f8a", size = 4694538, upload-time = "2025-07-16T21:40:27.975Z" }, - { url = "https://files.pythonhosted.org/packages/8e/40/7e2f340eaf53d06047b50ca9e07de2d40e2c70ef83defcc7e33f2cb62af9/psqlpy-0.11.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a7ac444267ac764ac8503cfef03acc7ec5d1122ef35bb2b2e164169a99706be", size = 4921555, upload-time = "2025-07-16T21:40:30.268Z" }, - { url = "https://files.pythonhosted.org/packages/7e/af/71c8e50b1e677975d991f03c80791a07377741584e9277b0bd3b3879062d/psqlpy-0.11.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d3114508ec98965300a6f576c149cb72c9c90da6f72cc4df04daecf891d4b2f0", size = 4934177, upload-time = "2025-07-16T21:40:32.146Z" }, - { url = "https://files.pythonhosted.org/packages/4d/7d/844702e5f6b711818d64f28de431200a6a180bd5092c3dd2af636ae61e2a/psqlpy-0.11.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:296b3fd5891a64697db5de9778ef9c0e87db3a237e456865a575ed038ed6401f", size = 5064407, upload-time = "2025-07-16T21:40:33.906Z" }, - { url = "https://files.pythonhosted.org/packages/76/0f/57c0ca8fda6c9d63203ed96330189ce72437ed39e688359e77fe55cc9c09/psqlpy-0.11.3-cp312-cp312-win32.whl", hash = "sha256:2389e0d4dca07413929ab5e4d214b9b2e3686f48c8e48f855c3e892eb8783d87", size = 3356512, upload-time = "2025-07-16T21:40:35.652Z" }, - { url = "https://files.pythonhosted.org/packages/04/79/79e329bd1b8fe75dc4c07af309053199f131e7c072b6f699c571d1463807/psqlpy-0.11.3-cp312-cp312-win_amd64.whl", hash = "sha256:4dba78a02586669cba487ea6d1a76c7dccea012a1f868f11a187d5fed9fb245e", size = 3767846, upload-time = "2025-07-16T21:40:37.753Z" }, - { url = "https://files.pythonhosted.org/packages/81/66/42490700a6d6d8709146a37f2ca3c1a30fc3d4c6aec8e5d602ab4f87d756/psqlpy-0.11.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b48dc0f2e7e6df1985df9db94c260c7bc340909d426ab5fcf94f1b3139d6e8", size = 4284035, upload-time = "2025-07-16T21:40:39.601Z" }, - { url = "https://files.pythonhosted.org/packages/74/89/2852bb855d649136f024c10cb7b2d7d2821bd3604a69f45b7be183e2e6d7/psqlpy-0.11.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d99a31d7e2d57c9a4e841fc33a287d2b97db8eb26273264d67158ed64b66de2d", size = 4497120, upload-time = "2025-07-16T21:40:41.604Z" }, - { url = "https://files.pythonhosted.org/packages/ab/b1/24d85916055489c87b445909ac64d661693af99891d6304ab8f93aaa74cc/psqlpy-0.11.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd3c97238b44beb0d150652e88f5b0b73c19c2df54bea64c4b13fd2adc6ed52b", size = 5025080, upload-time = "2025-07-16T21:40:43.689Z" }, - { url = "https://files.pythonhosted.org/packages/2c/2f/b6783d2aa6be2c7fd38c054c82895f0e8aa1b53c48d0d2779ac5c3ce51ff/psqlpy-0.11.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816de822ce77f3dc5cc660340c527e84e31c9c601b0426aa90d5d9702c6e92da", size = 4300899, upload-time = "2025-07-16T21:40:45.716Z" }, - { url = "https://files.pythonhosted.org/packages/a4/e0/7dea9df60a53765ac476dd4f9957ab1f20973c36641c94c07be22962a45e/psqlpy-0.11.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4fea804d21fa2531eaa3fdf7c1efc5f1daafc8dc2d6b4f84c0551a1881e891a7", size = 4905725, upload-time = "2025-07-16T21:40:47.745Z" }, - { url = "https://files.pythonhosted.org/packages/bf/4c/bfb4a135072b6436cd6a411a103e46f0fd5093f14551dc4d41c53ec5bda1/psqlpy-0.11.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4ee4672a0557eeefd0709b3255758f57c4005166bc1f1367153e258a6d9dd55", size = 5013516, upload-time = "2025-07-16T21:40:50.188Z" }, - { url = "https://files.pythonhosted.org/packages/41/fa/809bcae860e95e3d65624810b9f6211fef951ca18c513f5a7c99b2d4abc8/psqlpy-0.11.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7afe87a0b9fae297e15f1c249c62e5879fa95328eaf780e24734f536f72a654e", size = 4693319, upload-time = "2025-07-16T21:40:52.36Z" }, - { url = "https://files.pythonhosted.org/packages/0d/3b/a94ad4df5e365909139013dc3875ae6ebb51ff4366c8133b5f0b740326f7/psqlpy-0.11.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb6f39d5bfa24675a7425f2f1f68cb75c7f2fc6648c1de046e00c3acdddf1810", size = 4919072, upload-time = "2025-07-16T21:40:54.254Z" }, - { url = "https://files.pythonhosted.org/packages/d9/1d/6b47d2a1efdd3a13c572ccb7529d34f2cf61c426c12854674ccaea727791/psqlpy-0.11.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:89ce90107895c43676b133e1f281bdfbea62180c71610f353ad34fe79c3cae67", size = 4935241, upload-time = "2025-07-16T21:40:56.242Z" }, - { url = "https://files.pythonhosted.org/packages/62/f7/ae9c20532f1b06c07fb50769ad34d1a86ca571b2d2c4c78c573d2de7cb12/psqlpy-0.11.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:91fca7d319f78ad7e32f0cd6626b40e483ece9bc4b09b4ae39a8e2efc69f6459", size = 5061102, upload-time = "2025-07-16T21:40:58.373Z" }, - { url = "https://files.pythonhosted.org/packages/51/ff/45a6d08a8dbbe9b830350b3137b44f5461df7f40bc1794965f6702f8adc7/psqlpy-0.11.3-cp313-cp313-win32.whl", hash = "sha256:5e7e0728fc228b574d06b333e9fc10180a8a9b3577fb6712d123ec87c4e7d98e", size = 3357972, upload-time = "2025-07-16T21:41:00.363Z" }, - { url = "https://files.pythonhosted.org/packages/c3/6b/260b2196741f959513fac8c31d6ae491100abe46a96decb43ec3e228cdcf/psqlpy-0.11.3-cp313-cp313-win_amd64.whl", hash = "sha256:cb0e7b15c0783eb629cc11345ec778eda80cedf732dee6c6de9312e7e02f243c", size = 3767607, upload-time = "2025-07-16T21:41:02.19Z" }, - { url = "https://files.pythonhosted.org/packages/15/2c/4b66a8fb94e02fe8bb7c59afb63795f79203079022f88a2a5ea4708057ad/psqlpy-0.11.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5cc61367338d4b08d859f4dcc1fa1857457fc97fc0010940b517e53867263991", size = 4307501, upload-time = "2025-07-16T21:41:04.013Z" }, - { url = "https://files.pythonhosted.org/packages/e8/04/232a42a998199c3f5e9323e399a60f76dc8151f7cde4ba43f2052191d6f1/psqlpy-0.11.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df6b78c05433b4f9b47203c0322b2957214e4fe6a515cd9e6ad32c981153e620", size = 4515476, upload-time = "2025-07-16T21:41:05.825Z" }, - { url = "https://files.pythonhosted.org/packages/64/71/3da557814eab5675d68c165b7cfd52fa4bfeceffddb4d28bcb4af986b8a6/psqlpy-0.11.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c94e1ac34bc9a4ae033f9285f7a88816df2b514d32cfd760de9a15b1207fae08", size = 5025680, upload-time = "2025-07-16T21:41:07.704Z" }, - { url = "https://files.pythonhosted.org/packages/a6/bd/f5c93659a2d56c5121e060c8a830565981c76f357c7c69e82b46ba80b957/psqlpy-0.11.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2acac9978b6d125d24fa6e7039545ddf8caa6b59b78aef741f24e95146efcd4", size = 4304804, upload-time = "2025-07-16T21:41:09.58Z" }, - { url = "https://files.pythonhosted.org/packages/ab/52/80b14cfbdf40bfa2e54ac66433d0eed34737c92ebe4fe836b681d3a6afe6/psqlpy-0.11.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea762bd4abf8f87dbb270736a71318bc4b020a767087e85d7c67341c367b3de1", size = 4908176, upload-time = "2025-07-16T21:41:11.421Z" }, - { url = "https://files.pythonhosted.org/packages/3a/bb/5028ef2c7ed35ca660a8249cc54036a8e92ecd687948822c347749906282/psqlpy-0.11.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08c046ca6aec05f027cd9884d29cbb9a05a2b8057213eb99e271b1307a67afe4", size = 5019810, upload-time = "2025-07-16T21:41:13.336Z" }, - { url = "https://files.pythonhosted.org/packages/a3/10/7262faeb51c34af6a8ba14734dac46d55670a99a1ec195e41a9cb5d80efc/psqlpy-0.11.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25545f1479b32a19d6d2c6316cb8c287d528586b48ba7d5151aaaffe9b81543d", size = 4687626, upload-time = "2025-07-16T21:41:15.648Z" }, - { url = "https://files.pythonhosted.org/packages/5e/b1/b3a3421bd461d468447174633d657202065d49cfe3b2175631e5f8ae2582/psqlpy-0.11.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f434f942d7363fc596fb6998c2827f9b200766fa1552a45d8d2a803eea16a6", size = 4912546, upload-time = "2025-07-16T21:41:17.498Z" }, - { url = "https://files.pythonhosted.org/packages/38/f2/a56df153c725be77be5b324927ee52ae9d1a761a6ae9b80dbc37770add9f/psqlpy-0.11.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0fbcd0dd0956aff698c6ecfa5f8b936890792c79a90956ac1351b22ba3817468", size = 4940887, upload-time = "2025-07-16T21:41:19.693Z" }, - { url = "https://files.pythonhosted.org/packages/91/e4/ee83df1bbfaaee5925fb6aa49c506485379b5287e0456f74e08094120862/psqlpy-0.11.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:70b3e9183a0416f339dc9ba585dc5bae02eca83d5d115b398178756c0a45e3fd", size = 5058545, upload-time = "2025-07-16T21:41:21.664Z" }, - { url = "https://files.pythonhosted.org/packages/1c/74/7c6475b717ec252520db69ef07523dc80d654b8417a4add63d17a67692d0/psqlpy-0.11.3-cp39-cp39-win32.whl", hash = "sha256:0d8d94e9873a24c57911b0dfa59fef36f65c25a6d6f30e5a09e775271f46d805", size = 3357626, upload-time = "2025-07-16T21:41:23.57Z" }, - { url = "https://files.pythonhosted.org/packages/99/03/219755d5c147c8dd77baa5fe1bb7a94b05ee35a66b55d6ff03af1b0db857/psqlpy-0.11.3-cp39-cp39-win_amd64.whl", hash = "sha256:8765f455c5540c0b21b863ad2d4335074926a483119b11e5c94b1add916a50ab", size = 3764148, upload-time = "2025-07-16T21:41:25.391Z" }, - { url = "https://files.pythonhosted.org/packages/18/39/4cd0915c5759298c5ecdf48c9bd02756d684dc0ffdb6c657852ff032027c/psqlpy-0.11.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:46ad0e3fc9961e8a265b9017ed08a5389941e2b0a30912ce07981d52d5221bc5", size = 4307816, upload-time = "2025-07-16T21:41:27.195Z" }, - { url = "https://files.pythonhosted.org/packages/92/34/da7dbf64e103a2a16b32d5e5077af21bac2e7ce7dc024d2069d3160bd40a/psqlpy-0.11.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1784d26da21a4ae29372c692425e08ce33a72c0f0b3505dde72f2adee8d49128", size = 4514015, upload-time = "2025-07-16T21:41:29.146Z" }, - { url = "https://files.pythonhosted.org/packages/98/6a/f32dbce8f3c32cc039f6b20d74cce8c8c6f8a5a1da9b4a26a5fff2f86a25/psqlpy-0.11.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45d91f9e9259e4f6c02dae34947a7e80898b9795bda70d913f000aa2caed9664", size = 5027311, upload-time = "2025-07-16T21:41:31.044Z" }, - { url = "https://files.pythonhosted.org/packages/33/8d/1ca095a9f78f19178fbb838c228b2eb9de9fdd917b9edc2b8d8169a8c9f8/psqlpy-0.11.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a4dd4023b22436bdc8cc52cb9efd81dccbb6737d9d393d1a8c51f55107c8393", size = 4305811, upload-time = "2025-07-16T21:41:32.95Z" }, - { url = "https://files.pythonhosted.org/packages/b0/a3/3c2576aa36aeb93972e15b4227d95c87d8fac05057a39340583885805fc6/psqlpy-0.11.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fcb8f2068dfb7540bbeaf85f136a7ba6b265f1712621ab3b8f05f17d0bb6e59", size = 4907423, upload-time = "2025-07-16T21:41:34.841Z" }, - { url = "https://files.pythonhosted.org/packages/6f/28/bbc2284495351489d1634c3232ab7aa5a6dfb51770f30a7bddd1d2d8b7e4/psqlpy-0.11.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63068dd6e61f745ade9cba52ae3c1ea5689135bffd035094df3f7aa03753ccb7", size = 5016112, upload-time = "2025-07-16T21:41:36.98Z" }, - { url = "https://files.pythonhosted.org/packages/66/77/c96b66b8974e115c2d86cf1885a4cfdbe064f3b039de687062064852fd43/psqlpy-0.11.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ef9c6d8c66959c22c2c161a48186f8afdfd915bb2a5aef427b54c068b805b28", size = 4690441, upload-time = "2025-07-16T21:41:39.02Z" }, - { url = "https://files.pythonhosted.org/packages/8c/34/e7a162671ed54c5094a6b99a56b7fa7d416891286caa8d1cd15075a50474/psqlpy-0.11.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e60737698df1668b66598fbdd6fbc1a74cccaad1030ac3d7c8b29c0751a95374", size = 4914541, upload-time = "2025-07-16T21:41:40.972Z" }, - { url = "https://files.pythonhosted.org/packages/26/32/e1eb992419b850ceded1f4cf1804420da881aad212e4fef32f3b987eec1c/psqlpy-0.11.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:458e4df26916c024ae0bb4a6dbab8921cff4b8a4f3698347c484f7feaffc4c76", size = 4935158, upload-time = "2025-07-16T21:41:42.914Z" }, - { url = "https://files.pythonhosted.org/packages/15/08/4e7e2945523a9fbb93d2d29de77cbb10cd5a5e0f3bed8c4256a78fa87023/psqlpy-0.11.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3246c9f2d0f20dfaae3d24e1a0e1f877fd49c7e2f75c1f61920230f124c30ac4", size = 5059966, upload-time = "2025-07-16T21:41:45.219Z" }, - { url = "https://files.pythonhosted.org/packages/4a/83/46d996c05ebfd43100b8be6b20b78d37d76c2ffbe093ce463a48ee84e354/psqlpy-0.11.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e3051d66a5ce9ac214b5485c76ec7506fa58eea1799306503ddfa35cf69a0a39", size = 4307680, upload-time = "2025-07-16T21:41:47.171Z" }, - { url = "https://files.pythonhosted.org/packages/3f/1a/989b44317f20b66ef691612fee436379c870f1fe6a583db7a3176b585aab/psqlpy-0.11.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:c3bb1d99fa0e51bc30f75c3fae71845800e6a7d91f03cb58b766e4baa6c002c0", size = 4514330, upload-time = "2025-07-16T21:41:49.184Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ef/4e50611445b63673c0760cb4f24e4212753544e77d19a5f9ee2e7b2e3c0d/psqlpy-0.11.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63f343f633ace071f894e981221a5885b442c3f5da3afb55a1b4c6bd8bdbae6", size = 5027398, upload-time = "2025-07-16T21:41:51.089Z" }, - { url = "https://files.pythonhosted.org/packages/d3/5b/4f1b1b0c20b08e19f7613d84edeffadf980a6a8d4a943852503a1444120a/psqlpy-0.11.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08eefa0a62835a124a1788e7c5a12af963f31c8ab06a7ab91ce0aa3d22c7e17d", size = 4306162, upload-time = "2025-07-16T21:41:53.106Z" }, - { url = "https://files.pythonhosted.org/packages/72/48/88131d3d91aee81c96638d2558cc335d0b77b9770d4f0bce674730cc7b28/psqlpy-0.11.3-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e4dd7edf2f7567697db4a046520c38153f1b29ec4f60e973b4d4c13ae931fc4", size = 4907778, upload-time = "2025-07-16T21:41:54.974Z" }, - { url = "https://files.pythonhosted.org/packages/5f/58/cd2a1c24619f2ae298ca243888a71e330cda29cbb48628864a72244a0578/psqlpy-0.11.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a9f867ddbb36bd73a79f1b6cf20162e9f6a3c50ba90bd9086c1f5306d1f2d9b", size = 5016508, upload-time = "2025-07-16T21:41:56.92Z" }, - { url = "https://files.pythonhosted.org/packages/b1/3a/7ffb7e10b0d8e0929ca2be0d8f67f4f804bdc0de2b06bebd01cd1f25d477/psqlpy-0.11.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b7802665ab26163a75fbc60857e0ef01a0e5be0eaf1ca2e6475b5e0afbeb91", size = 4685098, upload-time = "2025-07-16T21:41:58.858Z" }, - { url = "https://files.pythonhosted.org/packages/df/d3/2b3f777a2a243b1eadb35fc430acad2b1fc2f6026d8cf71f353548cd2a74/psqlpy-0.11.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29a73982ac45401ac5f6a856bb21f579e45a6dc1d81610296510252d042b7e49", size = 4915103, upload-time = "2025-07-16T21:42:00.79Z" }, - { url = "https://files.pythonhosted.org/packages/13/a0/a2228c51be51a98e0116994d78040bf6db6d158fb7cf0d6bb624adad6233/psqlpy-0.11.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:6028d5790c4acfc22e6f5e54bffd8ede4de48d440ee2592ff4ba794ece84ea57", size = 4934827, upload-time = "2025-07-16T21:42:02.661Z" }, - { url = "https://files.pythonhosted.org/packages/61/d9/a2665b049ee91372ab7389f001a0c5a193d0a6e86a917cc9dfc9b319dfab/psqlpy-0.11.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d19f7382730e0fbf57d574be284194e56a080425a528dc7818eb64e58eff1b58", size = 5060062, upload-time = "2025-07-16T21:42:04.521Z" }, - { url = "https://files.pythonhosted.org/packages/f2/33/6508b81998f372d7b62d48abb9cec2fc196eac3c75cec7a757c2f53b0080/psqlpy-0.11.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bae63456857ba0fe3bb1c4a4b121625c0720adeca0977d37c3f122e5d79c5586", size = 4308204, upload-time = "2025-07-16T21:42:06.358Z" }, - { url = "https://files.pythonhosted.org/packages/ab/20/96d8cc192187d87fbb798e8c7fce1042cc5a12457578f640bee5148d5994/psqlpy-0.11.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:64e53e138208a687187c1aef9f9890a1fca297ba6b4a94cb56dc3df09469505d", size = 4514875, upload-time = "2025-07-16T21:42:08.249Z" }, - { url = "https://files.pythonhosted.org/packages/a4/81/be60eaf51a16c17893c2ed389c28865869243c68411657486fe9ddefed0f/psqlpy-0.11.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04ccc930e5d76e1bb29616c3d85fcde52a681e307bc2fdbdded00788bce17c6e", size = 5028556, upload-time = "2025-07-16T21:42:10.129Z" }, - { url = "https://files.pythonhosted.org/packages/0d/72/70da2698e7e6cd015925ac273b6a58f5815e4079a4395177e7d53c627d1f/psqlpy-0.11.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76efecab17369d4f9fd534481d2f45b9eecc650a982f2541d594362565ee888c", size = 4306361, upload-time = "2025-07-16T21:42:12.087Z" }, - { url = "https://files.pythonhosted.org/packages/19/85/39b6521c65797cf7a9acaa477baa00f2f2331a45c5bffc7cac58aefceeba/psqlpy-0.11.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e85f191f0d317cb174088c763ddf00d0a41229d93c226586ea043e02f90483f", size = 4907157, upload-time = "2025-07-16T21:42:13.912Z" }, - { url = "https://files.pythonhosted.org/packages/8f/56/37b72cf9eaa6ba73a15b96c0714c22f0c9b37f68702b32e152b7b0579c39/psqlpy-0.11.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb1d75ce58f97fac5e7affb1b30aedcb17cdb264f32a3bf9345cf46c7ec4971f", size = 5017209, upload-time = "2025-07-16T21:42:18.432Z" }, - { url = "https://files.pythonhosted.org/packages/f2/46/9b3499eb402dbc3584818c4f7abafd832bb5568a5fc8ad3d13e0b028c5e6/psqlpy-0.11.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ffca622362eee3b02c9c532001443e153715eb593802a1a061405cf275e7e5b", size = 4673916, upload-time = "2025-07-16T21:42:20.796Z" }, - { url = "https://files.pythonhosted.org/packages/c4/c5/facbe0af55f2389a4efe8390614b0600083a3a5880699baf956af8876f4c/psqlpy-0.11.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd9ea3b1b90faa66e5621ca8d8de636098919d957bd1f45f0ba2f709278bafec", size = 4915913, upload-time = "2025-07-16T21:42:22.755Z" }, - { url = "https://files.pythonhosted.org/packages/3e/4f/801ab636f090db3d12d02132699400d9195a2b199cd6d41948e28725e6b0/psqlpy-0.11.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2032767bb84c185de312f9315ca82415009b37cdaaed0437960599cccbf5953c", size = 4936121, upload-time = "2025-07-16T21:42:24.771Z" }, - { url = "https://files.pythonhosted.org/packages/7f/07/a02bcabddc1d07c7fc6cdc5a09e5f25ae4d8f21c81543f7926f34c3eb514/psqlpy-0.11.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4521f33a0997256d5acddc20e8123bd086bf3b470e0c28ef6a8cccf2a9373147", size = 5061900, upload-time = "2025-07-16T21:42:26.928Z" }, +version = "0.11.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/8e/40babfa88d73591286182d9eda5511589994233adda9ffb5bd4c3c7652b6/psqlpy-0.11.4.tar.gz", hash = "sha256:5165e8b69f640dbbeeefaea58585b6d7b462bc9e90de0828c04a0521082a18a9", size = 290188, upload-time = "2025-08-14T09:12:10.675Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/96/7982dff18b953c1b27fd1092d1eba035dbc6ef4ab1eb759943db6c5edde9/psqlpy-0.11.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f0009aed360ba3b5c70b93ab264d12ae2f7f46e77cb977ac83741680bd175e3c", size = 4309718, upload-time = "2025-08-14T08:41:29.949Z" }, + { url = "https://files.pythonhosted.org/packages/06/c4/5bd280b4a1f54c72c5f699f5b5d64b94f63481ca71a7ca75e22c885fc304/psqlpy-0.11.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:676664b65e78754b3a72013079a25898631e5fb66bb3eb912eb79ddc27a50eb6", size = 4512969, upload-time = "2025-08-14T08:41:33.906Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b3/bbd91284cd74156cc5773f2befe20ad767700d0d1e063438a205368944fe/psqlpy-0.11.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9584bbcb768e5ae9fcec4f8ef819cd163126e6d0b90a5036e8dbad573a33ba3", size = 5044023, upload-time = "2025-08-14T08:41:36.506Z" }, + { url = "https://files.pythonhosted.org/packages/0f/d6/b3f401f24655e3eaccf1fe980c3f8bc76443a9d6e680cf815ed4f7cb9fb1/psqlpy-0.11.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e12d53ec40d9f1e1363edee5b1e467d3d5646f041afd6747eaa438e6bdb95131", size = 4298505, upload-time = "2025-08-14T08:41:39.027Z" }, + { url = "https://files.pythonhosted.org/packages/36/55/d5c39f0b4774d1dc63f9054a63198fa03a24a443b371fdc31d3be5c5eeb0/psqlpy-0.11.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe0755559bebd62d77321bd7496c1be72911d8a8077116763b909ca18aebb1f9", size = 4926981, upload-time = "2025-08-14T08:41:41.621Z" }, + { url = "https://files.pythonhosted.org/packages/dd/e2/8dc80be09255223343916d3d57e71ebcdd2838c38bdc3ae48b14d96e46dc/psqlpy-0.11.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e472c967f750e61351f6fb643a9f19183d9f3e0ffff8a53fc0cd33845a04569", size = 5034500, upload-time = "2025-08-14T08:41:44.069Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2f/22b5a5f36f5ea1c49fd862d2a3936e1c52ebc33cb5e6510bf8345a322c42/psqlpy-0.11.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d457b3c6a50e86e797baef7b97f4ecb3e884db82f5ce202bcf56d4d88b29e6c5", size = 4699619, upload-time = "2025-08-14T08:41:46.69Z" }, + { url = "https://files.pythonhosted.org/packages/d1/af/aa9e8f70f901c85203e2c04be21e65b00d3910441d686734be7ce1c54842/psqlpy-0.11.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73ea116c31d641de3ecad803df13b24cd1eff060d7bbc93e2cfe0477458bc040", size = 4927790, upload-time = "2025-08-14T08:41:48.773Z" }, + { url = "https://files.pythonhosted.org/packages/fc/23/80864d2ec1ad0e3f6be988e45e5083edd20f6e299e9db80a2df3428b2b94/psqlpy-0.11.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:19bd4e686b2e9536d65d821429509261eb9a43ce56785fd51d5be1e14cd9f3e2", size = 4955661, upload-time = "2025-08-14T08:41:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/64/e0/c5b05464e0eb914161d384695202bfda133f388d93059439d585dbf945a6/psqlpy-0.11.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d0bc4a0f813622fa6bb3e0ea687e67c746db1abccfa5620c644180e456dc5e2a", size = 5066954, upload-time = "2025-08-14T08:41:54.096Z" }, + { url = "https://files.pythonhosted.org/packages/65/9c/24d76002256ac33b340f89dbbeb91f8a8ac766a7f0836133922a53a56044/psqlpy-0.11.4-cp310-cp310-win32.whl", hash = "sha256:3fa567fe209aaf157047552170bab5a73c94d7f6377113b6dc3bc143e3e02d39", size = 3356380, upload-time = "2025-08-14T08:41:56.055Z" }, + { url = "https://files.pythonhosted.org/packages/72/a9/327bd74604ab69eff5e5a9b2a72143f00700b0491d42f16e7cecfeaa8c3f/psqlpy-0.11.4-cp310-cp310-win_amd64.whl", hash = "sha256:41090e01af00a3931c1ab352dc3e47b488c7987160ec9b19d90dde70b511a20c", size = 3760670, upload-time = "2025-08-14T08:41:58.125Z" }, + { url = "https://files.pythonhosted.org/packages/f7/29/2833de8e1b823cd6710a7235cbf668c76e0245f93277b9a2ad984174c3f9/psqlpy-0.11.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6543270b65201fbc61d4bcb7e14ae8d50b279e134b7c983d01337bd9666ad08c", size = 4309147, upload-time = "2025-08-14T08:42:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/44/62/93fb5fa393a24c3998b1a571ec3a073bcc7050afffc481cdc9e27a62a44a/psqlpy-0.11.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7630bcc949dbf5603f13f49a20d5d817c3fe6404f9930a3113fbae597b1db4c3", size = 4510920, upload-time = "2025-08-14T08:42:02.837Z" }, + { url = "https://files.pythonhosted.org/packages/10/6b/9a583a73e7480198421471d3827d6c0e98629f83dfc82d409d8f952764e9/psqlpy-0.11.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6130442eca0bc43a5e22ccc7158d8675e17e46797ef0195cd7c5c96d653d3b9e", size = 5042446, upload-time = "2025-08-14T08:42:04.897Z" }, + { url = "https://files.pythonhosted.org/packages/06/b7/96e73807ab5045ab66fdf683e887def781be8718252e9529b2004c11a63b/psqlpy-0.11.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82caf18bfe218540e2f7c2ba1dae9c5d9855ad60de91d863009b663d4b5122c9", size = 4298490, upload-time = "2025-08-14T08:42:07.206Z" }, + { url = "https://files.pythonhosted.org/packages/76/5f/62468c362b8fc7b8f7cd53ea5d67fc3b755e49212540821f8cd73890c1ef/psqlpy-0.11.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0c52c2af7e8908731c5b81c984bdb095c40b44d866687977944cad707eee194", size = 4926630, upload-time = "2025-08-14T08:42:10Z" }, + { url = "https://files.pythonhosted.org/packages/9a/41/9edd3cc9b334c9cb655a12820fed901648e44d0ec855604a6157eb4a614f/psqlpy-0.11.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce52c351b85c57708959bf3f2fe0ac9d0d2b21b8f46ea9c9d3e94ab61c3da9b7", size = 5034246, upload-time = "2025-08-14T08:42:12.165Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/6185d3a2fa2e5ad086b763ca17934f14e0770a7b9a76b63fdc33d1b5c3fc/psqlpy-0.11.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5482c529471ffdcdee62af1e06747b8b6845004764bd300ea4496bda99da182", size = 4699816, upload-time = "2025-08-14T08:42:14.071Z" }, + { url = "https://files.pythonhosted.org/packages/52/7e/b10a4f5f9c1d4a5c33b78090ca3c033c6d01eb96f7e7a546b0ddd0a6f3c9/psqlpy-0.11.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e6e115a4e9d14bceddcf350d92c9e67ed4b40ef34eee4fc66be1663faec61e", size = 4928103, upload-time = "2025-08-14T08:42:16.226Z" }, + { url = "https://files.pythonhosted.org/packages/93/65/ae6400bcd2e47fc413bc17c4dcb059ee946013e2ef5a3104295c53ab59ca/psqlpy-0.11.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:826f2c0df29d0d9696513aa2944aa1d7d9b1ee6f9aa6d2bcbbbdd852784f01fa", size = 4955367, upload-time = "2025-08-14T08:42:18.911Z" }, + { url = "https://files.pythonhosted.org/packages/82/0a/0c99b62b7d3a90cd4dfcb5e6459cb1d6fe55392c0d7967784ac8c3295fff/psqlpy-0.11.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3321a971a90df8f5806d7ba5513b87b47ee114fcfbbb98bc1449db0da55d29ab", size = 5067086, upload-time = "2025-08-14T08:42:21.823Z" }, + { url = "https://files.pythonhosted.org/packages/39/75/d088bb1eb29acfac4e3823597adf67dc66282e50e30c4f39bdf4847e459c/psqlpy-0.11.4-cp311-cp311-win32.whl", hash = "sha256:d6225b1447037e60f0eec065d24f7433cb77c2b5cbccf5d6ea8607b4abc6809e", size = 3354073, upload-time = "2025-08-14T08:42:24.433Z" }, + { url = "https://files.pythonhosted.org/packages/99/49/cd0bca36d7b7f17e0253ae73c38c9c4ec68923c030ba6a92f4e11b178323/psqlpy-0.11.4-cp311-cp311-win_amd64.whl", hash = "sha256:5214f251a7d5315ebc01e0c7ca6b9103d3a321e3d89b0e9f520420a4a5c99c85", size = 3759893, upload-time = "2025-08-14T08:42:27.76Z" }, + { url = "https://files.pythonhosted.org/packages/a2/76/a2cb3af82db0f4f05a999f1eb77a7d63ebf51b8c90cebebf045d551f9cd9/psqlpy-0.11.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4452ec42b07ef63169a4427f53cfe8021c2d2181992969ae627af3af005db3a5", size = 4286702, upload-time = "2025-08-14T08:42:30.065Z" }, + { url = "https://files.pythonhosted.org/packages/b7/32/486da263017e74147bcae96901a7c43dd895b9732ed40a9a276a00c71c56/psqlpy-0.11.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:29aea5bb164302284852b46cc4be8ab4e4df3f5e4cbdb744c2c8811d87a859ea", size = 4489824, upload-time = "2025-08-14T08:42:32.568Z" }, + { url = "https://files.pythonhosted.org/packages/a2/76/be44108b26651eacddb8460bd2cd584b5a5e16834f433b20ec7426421eef/psqlpy-0.11.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71694d170db4cff7efb25e1ad0507ba6ba1dbb131213fa12c476621009aa651e", size = 5029062, upload-time = "2025-08-14T08:42:35.008Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d0/4d019d8213a853247e2d3bb28d6d3e74ac73ffde5db0a346631892b6b9a6/psqlpy-0.11.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7b6ee237d4387df389245e20e09370bab95f12e5d57325b48bc326fa348f68d", size = 4289114, upload-time = "2025-08-14T08:42:37.354Z" }, + { url = "https://files.pythonhosted.org/packages/9a/0f/38ba3fdb03bd4114038f6238bf85eab7882a0d53ae576624c8f7589b4357/psqlpy-0.11.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27798b066e7413ecc3ae7a0ded458f6267b4a169ddf9dc077f6c7b105d710d9f", size = 4899028, upload-time = "2025-08-14T08:42:39.473Z" }, + { url = "https://files.pythonhosted.org/packages/82/d6/ad5f51e04200fa3e8b1b5b26af3eb3abbe3039400d8d784d9674a90d9ee0/psqlpy-0.11.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f97919461d1d537c7eafe32d6611b496447bc2f484e94c92b7614d6e1e836ce4", size = 5019343, upload-time = "2025-08-14T08:42:41.881Z" }, + { url = "https://files.pythonhosted.org/packages/9d/19/2c06d9133979fbcb68ff8ea9e3489f11d97fc402524f7399df6bee0324d8/psqlpy-0.11.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c369d8a52335acefffd617ffe0e2f77ee6586da4fdfc1f8cb939a5dc7d302fa", size = 4677079, upload-time = "2025-08-14T08:42:43.974Z" }, + { url = "https://files.pythonhosted.org/packages/90/04/c36c34ff5138f8b767b20305e44319fb8d97bac40c263b0f206101a4466c/psqlpy-0.11.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44b746f44e15ae06ffbac957a4975491bd2024c2ff9d2b743b911e4c92cc2b06", size = 4925320, upload-time = "2025-08-14T08:42:46.528Z" }, + { url = "https://files.pythonhosted.org/packages/6d/08/33d9d032d2a4ce90244ba2c4152b40688f2bb8f6637b7f88f0c36037813b/psqlpy-0.11.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:13e6eeeb8002baf34a0f49f638d73a3f68bb6470865f9ca9a115272f962e12b6", size = 4930091, upload-time = "2025-08-14T08:42:48.836Z" }, + { url = "https://files.pythonhosted.org/packages/50/eb/53bec2233414f5d50b7c3f8a73ed45ed35995f34166336f374726ac707c9/psqlpy-0.11.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:444ddf597a4edafe90e4a568c031d4698fb221e3b58de7307a5608c524091781", size = 5063064, upload-time = "2025-08-14T08:42:51.409Z" }, + { url = "https://files.pythonhosted.org/packages/88/21/34d4095c059f64e387263869070308fa136eaf63b2778e5825c733534998/psqlpy-0.11.4-cp312-cp312-win32.whl", hash = "sha256:1660247e393abb61b81214af7a9bf4787e2ae9de8fec7645ce9df4cf1268086d", size = 3356744, upload-time = "2025-08-14T08:42:53.209Z" }, + { url = "https://files.pythonhosted.org/packages/20/b8/b16150d738bbc83043c5a0f759ef6c73efa50ec439e94c995ef5733d8dc7/psqlpy-0.11.4-cp312-cp312-win_amd64.whl", hash = "sha256:5bb66a7978fc0f0c02d167c8a084e8c7a43c7628dcf69416940b63ba8aeac9ec", size = 3765608, upload-time = "2025-08-14T08:42:56.111Z" }, + { url = "https://files.pythonhosted.org/packages/f1/0a/a70017f622c50d51f7fe202cea35698d3d007e53d2a31d712a2e643df657/psqlpy-0.11.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:55e1ca321461f1675f9041bf4c3257051ea324320313435b06493cf55f32c155", size = 4284840, upload-time = "2025-08-14T08:42:58.417Z" }, + { url = "https://files.pythonhosted.org/packages/74/77/8cb0fb9c4095c4afdc19b939d3cfce17c7f145f184c723f74076e61154b9/psqlpy-0.11.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5081d67c1115ac302dc31dd5d62b2cb5d8365abc324cbe3f18110b8147450e9f", size = 4490518, upload-time = "2025-08-14T08:43:00.807Z" }, + { url = "https://files.pythonhosted.org/packages/91/3c/8f3325ee8865af4be496caa23b4a5f9a08e4d06abe634de781b720b103dc/psqlpy-0.11.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29099623fe339d3d396be05d73f7b9144f850550b87aeed47e51130e5329f205", size = 5031400, upload-time = "2025-08-14T08:43:03.699Z" }, + { url = "https://files.pythonhosted.org/packages/e5/73/4f7f40548e194c7d7a615e894162e2731176c9018a9d888dde1a46579365/psqlpy-0.11.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e95c38b2617825265c41e2ecaedee5beaf531d2f42a7cf368b18270c6dcdd24d", size = 4289769, upload-time = "2025-08-14T08:43:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/3f/3e/c4ee89d3a18e2bdddb77e6f48c586424d16720f03fd125d655370ed1f5a2/psqlpy-0.11.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd715d8185eccd2c77216bfcdc962e5ed5b146c9b78b5df92222ab902781519f", size = 4911483, upload-time = "2025-08-14T08:43:08.235Z" }, + { url = "https://files.pythonhosted.org/packages/89/c7/db79fe484299c277e05d2434b0e7f6f1d80ff11c0e5f53fd607e1448e588/psqlpy-0.11.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08a331a6634edfc6285e328011d177bc190ff62167ef98403ba7096dded72d46", size = 5018283, upload-time = "2025-08-14T08:43:10.392Z" }, + { url = "https://files.pythonhosted.org/packages/b1/0c/e50bc06d73af42b84bdc79b9a055bf855e38518fdeabaa32d19a28792c0d/psqlpy-0.11.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53032983a1ee48e9af6cfa2ca40b6b6ea6da863c0b207b991cc5c0eda2fea79b", size = 4694187, upload-time = "2025-08-14T08:43:12.84Z" }, + { url = "https://files.pythonhosted.org/packages/59/05/20b35f56bdd9b2e8c1b5837b45067b9b7bc99f4af31914e083ef0e1ec18e/psqlpy-0.11.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47e17b6575387c8f2cb5d3b9b90089914a0d62bc837ca38a4d6abcfb2cf61a8", size = 4922955, upload-time = "2025-08-14T08:43:14.832Z" }, + { url = "https://files.pythonhosted.org/packages/8b/de/220695bf6c801a7ec6ce9a828cc67e5a5576323fe0b9b8959825c05db892/psqlpy-0.11.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c84cd445581499d7982d1162b82ca39a59ede2556b15490bf65466aa88a248c0", size = 4942011, upload-time = "2025-08-14T08:43:17.023Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a2/cfb3b44d1cb8dbc2af43b4aa2606cf288de048ca2c6f5321b23323f64cd5/psqlpy-0.11.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94a12830982725686f8040d3b216f0743ad3909153e5bdcf9c497dec254998e9", size = 5060338, upload-time = "2025-08-14T08:43:19.505Z" }, + { url = "https://files.pythonhosted.org/packages/71/07/e98b021c71337fa17044f7190427a3e9aa53c8bdaa19dc92d4b505d5f5f5/psqlpy-0.11.4-cp313-cp313-win32.whl", hash = "sha256:546f4589014813ed06ada386052b50f045958d71289375230678755c1ce20199", size = 3357017, upload-time = "2025-08-14T08:43:21.377Z" }, + { url = "https://files.pythonhosted.org/packages/38/c8/5abf0e2cf58bc57e8ea313fcfb170c77bd768e1b7abe161fd637ba0f7e7e/psqlpy-0.11.4-cp313-cp313-win_amd64.whl", hash = "sha256:0134d01637aeceb496723e32634faef00a0320f520f1e404a0ff04875eedb3d8", size = 3765210, upload-time = "2025-08-14T08:43:24.24Z" }, + { url = "https://files.pythonhosted.org/packages/36/19/91e1a52be9668ab1c7196c682166e492d056d9b0a209f513c2c4e962cb6f/psqlpy-0.11.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:7d73c7e8c71caaf7e595f077c921ea0ea1226c9907dc48c7b339c38cfc519cfa", size = 4309965, upload-time = "2025-08-14T08:43:26.783Z" }, + { url = "https://files.pythonhosted.org/packages/c2/55/87c74143d8d4548fd699c60a51b1aebb6dbb18d7e10034ea123bd32e8a4a/psqlpy-0.11.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:504237a577595c04712a07f84fefa008b31f966a6a80c75467a3ccf5524f6868", size = 4513889, upload-time = "2025-08-14T08:43:29.728Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/7c77bd145fe88e83a555bd0c319ce8c3a16a0594b7210b654a8753a09c3e/psqlpy-0.11.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2c7a35776b5cbc0e65ef12b9ff44c63250a36c5d81d1a36db6daa32acd7258d", size = 5044923, upload-time = "2025-08-14T08:43:31.678Z" }, + { url = "https://files.pythonhosted.org/packages/62/0f/b600e06f57b72d5eb217cdf3720f8978e1d18bfa9593ecdb2ac89d4310eb/psqlpy-0.11.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81017357d30df8baa64f90899683cf92ba84891d3f53b85bbbf728af3fd64745", size = 4299450, upload-time = "2025-08-14T08:43:33.985Z" }, + { url = "https://files.pythonhosted.org/packages/03/e3/e03c3b97932752b037146099ed5a03064f433aa4cd9875934c110b6285ff/psqlpy-0.11.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c83f7d6a2e8c7d8e3a0499e970686dfe93ce5e34f83db05ef7da0a17a030aeb4", size = 4928217, upload-time = "2025-08-14T08:43:36.888Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a0/dcd2191d5e43a8761f9933229567de1cca8be6daea35b0305ee9757038eb/psqlpy-0.11.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7be5e090837c55ed07963abbdd039a2b2b02fadea9c9ba6ea7894c25dcaf17bf", size = 5037082, upload-time = "2025-08-14T08:43:39.355Z" }, + { url = "https://files.pythonhosted.org/packages/6e/1c/7c794ca5e4ce3e6f5920b9cf9a770016cc348ee3955d0d7daaf2abe3079c/psqlpy-0.11.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bdf8e40c02b302d149be0ad8d469154659b70c9a9fccd8f98bb4913ba9d981d", size = 4698835, upload-time = "2025-08-14T08:43:41.36Z" }, + { url = "https://files.pythonhosted.org/packages/6f/b2/0894ca29d94ca3d76a488d47d2cd18b47f4de65482651d932d81056db59f/psqlpy-0.11.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c425ba3185616770edf6cc4a3200e9f25b992d22fd594919cb3c7efc0249631b", size = 4929131, upload-time = "2025-08-14T08:43:43.465Z" }, + { url = "https://files.pythonhosted.org/packages/b6/0f/f88c6f510a2220788ea7e1a06b0f8d562706d8e388f36a5aebb5a404d765/psqlpy-0.11.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9bbe5c697b5a494f47ee3aed586ba5d15954eae9edbbb5e2911e056332ab38f0", size = 4955968, upload-time = "2025-08-14T08:43:45.825Z" }, + { url = "https://files.pythonhosted.org/packages/52/04/2c026361ec7f13f2a90bb1a48e54d5132a73f3b6643d76e38c5b434644bb/psqlpy-0.11.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5f706d6f2bc4a08e0cb94c221dda7234901859cb4537d59764ebfe795027de64", size = 5067871, upload-time = "2025-08-14T08:43:47.847Z" }, + { url = "https://files.pythonhosted.org/packages/80/58/bf8c49750f2d0a5bfd1fe5b37aea35b03eef3173a9e5abc7ea8c688ca56f/psqlpy-0.11.4-cp39-cp39-win32.whl", hash = "sha256:6f6e803191c582ae85c3e2a8a5f29e2ceb59e81bf4bc9d3baeccebfcd73eaecb", size = 3356927, upload-time = "2025-08-14T08:43:50.086Z" }, + { url = "https://files.pythonhosted.org/packages/a1/17/b47a665a83181ac5213117f6e69e74da12dad0614eae3d2e3d6024048f87/psqlpy-0.11.4-cp39-cp39-win_amd64.whl", hash = "sha256:b157ff7d73fa6f19f617412391291e26d2bc75dfd5d7a27826e57145d04f9415", size = 3761352, upload-time = "2025-08-14T08:43:51.981Z" }, + { url = "https://files.pythonhosted.org/packages/72/09/f168b54afcdf8c36115c3125cc60a45694d287c6c7727cc24f85767f1bd3/psqlpy-0.11.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e4e1ab9a7c98769d09a9557af59e8cfd2b5c307d36133a7f2013d558151e8d37", size = 4305382, upload-time = "2025-08-14T08:43:54.636Z" }, + { url = "https://files.pythonhosted.org/packages/11/d4/6b969e6147c9b4493e9fab52303606493a33a6eea0fda1251fab9d54811c/psqlpy-0.11.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c3f813f7f7b7095a1f56ba351013ddd85a03a77c3ae38170d183f64742e63fd5", size = 4505679, upload-time = "2025-08-14T08:43:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/5e/90/44950361fc484e01fca7e5044940bf80d6993c89b8dee401be59a20d25d7/psqlpy-0.11.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ade55257c70b1929be3e1d731b1389466ea2a02f74bed1cf40417a4f6fbb68c", size = 5042759, upload-time = "2025-08-14T08:43:59.038Z" }, + { url = "https://files.pythonhosted.org/packages/7e/4f/20a929782106276e6720e6944001a928ed771ae2d92b9bf81ff1c86eccb3/psqlpy-0.11.4-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3b0aaae7426339e183e268a60fc40fe2e3a1a7c620518b28c2d83348ca5f4b54", size = 4295894, upload-time = "2025-08-14T08:44:00.97Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ca/bab6c1f9a67e32d5393ec84a48487631fce53c42d6ff35b6631937642d43/psqlpy-0.11.4-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:804e5a124d0a2c0a777649d746b36e5cee1e807f6ae742ea320d51cd117f5bc2", size = 4920311, upload-time = "2025-08-14T09:11:29.42Z" }, + { url = "https://files.pythonhosted.org/packages/c5/ae/ebb97a4a9db56bb9a09b41ac5c17ff484a557bb363051d8613bba32557ef/psqlpy-0.11.4-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afba6e6206d8ba47ecf7837f3552685e2cff692ba9c65febeacf59a6ae07019b", size = 5028796, upload-time = "2025-08-14T09:11:30.881Z" }, + { url = "https://files.pythonhosted.org/packages/1a/51/4ed6be9e2350dd7c0814770996959ed4754163f2ea63b8b2fb92ccdb1954/psqlpy-0.11.4-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f72ef1cd0f6270da3f597638ab1e1b340bc75a2b9e33b85d26547d72057fe23f", size = 4681905, upload-time = "2025-08-14T09:11:32.479Z" }, + { url = "https://files.pythonhosted.org/packages/01/1a/0004d2ae122d83653b1fafc542a7ca3b6cadf9631bc3d526bb9473945279/psqlpy-0.11.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bbb3f610c917114641ad0132ba07015b4c882d00459ed19979ac45a00428b32", size = 4933794, upload-time = "2025-08-14T09:11:34.233Z" }, + { url = "https://files.pythonhosted.org/packages/3d/9f/0a984d4dad209ccb68a112033229498532ba6d0bd2b1f0fedddadac10c4a/psqlpy-0.11.4-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3653d4e7363d50e5f9d5ac76a15fc462b5111a80111354141d784930b20dacf", size = 4951140, upload-time = "2025-08-14T09:11:35.721Z" }, + { url = "https://files.pythonhosted.org/packages/89/e1/707f136f1bf9a1455d459706bf9b19a96946918e05aebc630ccdd99307ad/psqlpy-0.11.4-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:46384aa8d9a1e300a730436c6ca3551a0eb59863a26ca5c7475337f8e0481eac", size = 5071764, upload-time = "2025-08-14T09:11:37.343Z" }, + { url = "https://files.pythonhosted.org/packages/27/a3/cc729b211dc3c2d872510ce8a6759fafafe5fd14f83038f4f41e97754e8a/psqlpy-0.11.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:43de0d4c167bca48831653e8ccb2631d4af0d6e6210ab0649fc5126bf5376e33", size = 4303103, upload-time = "2025-08-14T09:11:38.762Z" }, + { url = "https://files.pythonhosted.org/packages/b3/75/abeae3ac76545cdf4b8054b042b325ea7e2e4aab62c4d3821d60f3d4e99e/psqlpy-0.11.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9fe3ab8b0dc4d74eea5579e43fbc2500e5dff1ea00653cc46f8a51dcca8c57b1", size = 4506333, upload-time = "2025-08-14T09:11:40.477Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2a/38ed70fc148e0ec980041f341e79a06ccf989ad2d9fb76ea53d150c343a2/psqlpy-0.11.4-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264b3e9d3bed0e7bc19557d9ffb9275c0701d91c9375807b81db562a47b1202", size = 5043283, upload-time = "2025-08-14T09:11:42.142Z" }, + { url = "https://files.pythonhosted.org/packages/de/09/819c40619222432aa2871b554fe5564cba00e4fdbf22914d6ed55280a13b/psqlpy-0.11.4-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8612d436dd6ee0b2ecf622362870f271217f241b89de92434dc4fcf59ca3dd04", size = 4296471, upload-time = "2025-08-14T09:11:43.556Z" }, + { url = "https://files.pythonhosted.org/packages/14/52/0063fab3f4ff180a70c1c892db08f4d2df81c4f4a6cfdefd9a146e767ed3/psqlpy-0.11.4-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:725bfc04afc0cf48f408483e6d03134acdc3b3d53c847dbccf486262a287d5c1", size = 4923692, upload-time = "2025-08-14T09:11:44.99Z" }, + { url = "https://files.pythonhosted.org/packages/db/9a/fdd745dc0f9aaa80d2454cd0caac2a2e70d656b2f708a948aa2b65b7d788/psqlpy-0.11.4-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5877bcd74e9cc129080b9e721ccaae84a49b88dbadabcca13b11193f6268880e", size = 5029846, upload-time = "2025-08-14T09:11:47.084Z" }, + { url = "https://files.pythonhosted.org/packages/b3/6f/099489ab96429856f1ac05d18efd6ef70460f3171bac24cf3f24cef59672/psqlpy-0.11.4-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be6ecb02e588bed4510e61a1c1be5b68597d04e55de03a462935347fbb14cba4", size = 4699035, upload-time = "2025-08-14T09:11:48.758Z" }, + { url = "https://files.pythonhosted.org/packages/2b/56/52e581005e16ae40f924695148ebe1d42583c298eb23272bead50fd11422/psqlpy-0.11.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:faa704f395506eb8ca68d652a893ef6fce258d016e9fb1ab62602e15a67d016a", size = 4933932, upload-time = "2025-08-14T09:11:50.189Z" }, + { url = "https://files.pythonhosted.org/packages/d7/c0/d969ad7a5d4fb36b44b1a2fd83ec091abb880d05ea2fce86d903f3c9a9b1/psqlpy-0.11.4-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:3c00db96ac60199d9756e4fa67ac9051ab62b50852ea74d0a8f8acb268f3011f", size = 4952333, upload-time = "2025-08-14T09:11:51.613Z" }, + { url = "https://files.pythonhosted.org/packages/75/78/acfc4fa9f3ceda9a7bdfb21063423c302cc0f3369e6e6bba79fd6c57b440/psqlpy-0.11.4-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d9991a76daee1d153124b93ec2e4a65fba71a5273ec0f6738b0e8b84d2945630", size = 5072043, upload-time = "2025-08-14T09:11:53.1Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/732d475f5e1f253ae2f1b10ad0c50f98c248be6bd3ad373606f3ea771cfc/psqlpy-0.11.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:07051ac8f2705e90f700273371a6b5f61812676ed2da3c3a049a64870a486b8d", size = 4305282, upload-time = "2025-08-14T09:11:54.579Z" }, + { url = "https://files.pythonhosted.org/packages/98/c9/c9188c11543a76bff09c4317e7972a3a02d43b02248426ce35a92ed707ed/psqlpy-0.11.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ca237aa2eb130e460ebf8c32c9925fc6b5d7f63c915981048acebb51a51ad7a8", size = 4505381, upload-time = "2025-08-14T09:11:56.074Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b8/9bbbc5dafc240bc59a37b0fa549d59c455ed45d42c47f8be0206ff3f2fef/psqlpy-0.11.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:783f81c466240c28f78e3dd8a0f95763f3f7b2d99086b82158078712d4736d12", size = 5044313, upload-time = "2025-08-14T09:11:57.74Z" }, + { url = "https://files.pythonhosted.org/packages/d0/be/adb1ca30d47b84d1472e08abfe6dcc1e57392167e749c95334af94027bf9/psqlpy-0.11.4-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7824fbff64c9b6adc9ca5605b45cfc50c806e40f84e536df7651f7bc44463a7a", size = 4297820, upload-time = "2025-08-14T09:11:59.369Z" }, + { url = "https://files.pythonhosted.org/packages/4f/df/5283839d7f5602825efbf1dd76f7a72a6ab4701bbb0f524674dacd0b39b9/psqlpy-0.11.4-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e78b2e41fc4bbf65372bb889c13f7dd61a4199ae5e52f36834fec4bcf3bc85f4", size = 4920650, upload-time = "2025-08-14T09:12:00.912Z" }, + { url = "https://files.pythonhosted.org/packages/bd/b6/979f6de4893d1899a24ed59a84a8c57adadaafa7df4c5414d22edaf987b1/psqlpy-0.11.4-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ae342ff1637ead3f263419211b93ff7423864c2d1f4340ee70d0c7747ef125d", size = 5030537, upload-time = "2025-08-14T09:12:02.383Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d7/8adfdb5670c4bb777498ed6234660b24b133cf4847c39dff4b1c3b12b414/psqlpy-0.11.4-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c54478ae6ccc8763bed1e573f3decc7125292a3a3e6f6e68575bdaca42dffb71", size = 4682027, upload-time = "2025-08-14T09:12:03.952Z" }, + { url = "https://files.pythonhosted.org/packages/3f/44/587471fc8c00d4917e9f150edb7283e6f850d75548f6c926ddbe03c4faba/psqlpy-0.11.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e53380a3344c794daa5040f173d389849662eaeb6a600eea1ad34232319334c", size = 4933704, upload-time = "2025-08-14T09:12:05.456Z" }, + { url = "https://files.pythonhosted.org/packages/bb/e0/ca5ef98995053eee7df563dd7389912106b72ca88c04ff68d7a55df69bc2/psqlpy-0.11.4-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:b570403b143689755165d0d908c40259fe66d4cec15f5aba06b00fda95dc994a", size = 4952292, upload-time = "2025-08-14T09:12:07.197Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4f/f7b979c6012cbfe666d24090a4f06d2250578402fed38453bc4d22a972c8/psqlpy-0.11.4-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:12352c214f44fddb69ce1f4f299027e25cc56c322fd63a5d6377bf76dd49ef34", size = 5071934, upload-time = "2025-08-14T09:12:09.057Z" }, ] [[package]] @@ -4957,7 +4957,7 @@ wheels = [ [[package]] name = "sqlspec" -version = "0.17.0" +version = "0.17.1" source = { editable = "." } dependencies = [ { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, @@ -5487,11 +5487,11 @@ wheels = [ [[package]] name = "types-docutils" -version = "0.21.0.20250809" +version = "0.22.0.20250814" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/be/9b/f92917b004e0a30068e024e8925c7d9b10440687b96d91f26d8762f4b68c/types_docutils-0.21.0.20250809.tar.gz", hash = "sha256:cc2453c87dc729b5aae499597496e4f69b44aa5fccb27051ed8bb55b0bd5e31b", size = 54770, upload-time = "2025-08-09T03:15:42.752Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/d4/12d7f102fb76207f9003c46f69b91d009f75c64a6db73dd6fcdcc3bd51b2/types_docutils-0.22.0.20250814.tar.gz", hash = "sha256:84c645863419b38f949a93e77d31420fe4b5cacf95757b3104278318a95fc158", size = 56376, upload-time = "2025-08-14T03:13:55.63Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/a9/46bc12e4c918c4109b67401bf87fd450babdffbebd5dbd7833f5096f42a5/types_docutils-0.21.0.20250809-py3-none-any.whl", hash = "sha256:af02c82327e8ded85f57dd85c8ebf93b6a0b643d85a44c32d471e3395604ea50", size = 89598, upload-time = "2025-08-09T03:15:41.503Z" }, + { url = "https://files.pythonhosted.org/packages/27/3e/61a5354f8a1b7e2815cf17efa9c6cf6be6f66a12df248313bdff57765c79/types_docutils-0.22.0.20250814-py3-none-any.whl", hash = "sha256:22ff141b85be203cb57999ca5fc94d7cf574a7065e19446920e3f11c7181700a", size = 91736, upload-time = "2025-08-14T03:13:53.614Z" }, ] [[package]]