sqlspec 0.13.1__py3-none-any.whl → 0.14.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sqlspec might be problematic. Click here for more details.

Files changed (112) hide show
  1. sqlspec/__init__.py +39 -1
  2. sqlspec/__main__.py +12 -0
  3. sqlspec/adapters/adbc/config.py +16 -40
  4. sqlspec/adapters/adbc/driver.py +43 -16
  5. sqlspec/adapters/adbc/transformers.py +108 -0
  6. sqlspec/adapters/aiosqlite/config.py +2 -20
  7. sqlspec/adapters/aiosqlite/driver.py +36 -18
  8. sqlspec/adapters/asyncmy/config.py +2 -33
  9. sqlspec/adapters/asyncmy/driver.py +23 -16
  10. sqlspec/adapters/asyncpg/config.py +5 -39
  11. sqlspec/adapters/asyncpg/driver.py +41 -18
  12. sqlspec/adapters/bigquery/config.py +2 -43
  13. sqlspec/adapters/bigquery/driver.py +26 -14
  14. sqlspec/adapters/duckdb/config.py +2 -49
  15. sqlspec/adapters/duckdb/driver.py +35 -16
  16. sqlspec/adapters/oracledb/config.py +4 -83
  17. sqlspec/adapters/oracledb/driver.py +54 -27
  18. sqlspec/adapters/psqlpy/config.py +2 -55
  19. sqlspec/adapters/psqlpy/driver.py +28 -8
  20. sqlspec/adapters/psycopg/config.py +4 -73
  21. sqlspec/adapters/psycopg/driver.py +69 -24
  22. sqlspec/adapters/sqlite/config.py +3 -21
  23. sqlspec/adapters/sqlite/driver.py +50 -26
  24. sqlspec/cli.py +248 -0
  25. sqlspec/config.py +18 -20
  26. sqlspec/driver/_async.py +28 -10
  27. sqlspec/driver/_common.py +5 -4
  28. sqlspec/driver/_sync.py +28 -10
  29. sqlspec/driver/mixins/__init__.py +6 -0
  30. sqlspec/driver/mixins/_cache.py +114 -0
  31. sqlspec/driver/mixins/_pipeline.py +0 -4
  32. sqlspec/{service/base.py → driver/mixins/_query_tools.py} +86 -421
  33. sqlspec/driver/mixins/_result_utils.py +0 -2
  34. sqlspec/driver/mixins/_sql_translator.py +0 -2
  35. sqlspec/driver/mixins/_storage.py +4 -18
  36. sqlspec/driver/mixins/_type_coercion.py +0 -2
  37. sqlspec/driver/parameters.py +4 -4
  38. sqlspec/extensions/aiosql/adapter.py +4 -4
  39. sqlspec/extensions/litestar/__init__.py +2 -1
  40. sqlspec/extensions/litestar/cli.py +48 -0
  41. sqlspec/extensions/litestar/plugin.py +3 -0
  42. sqlspec/loader.py +1 -1
  43. sqlspec/migrations/__init__.py +23 -0
  44. sqlspec/migrations/base.py +390 -0
  45. sqlspec/migrations/commands.py +525 -0
  46. sqlspec/migrations/runner.py +215 -0
  47. sqlspec/migrations/tracker.py +153 -0
  48. sqlspec/migrations/utils.py +89 -0
  49. sqlspec/protocols.py +37 -3
  50. sqlspec/statement/builder/__init__.py +8 -8
  51. sqlspec/statement/builder/{column.py → _column.py} +82 -52
  52. sqlspec/statement/builder/{ddl.py → _ddl.py} +5 -5
  53. sqlspec/statement/builder/_ddl_utils.py +1 -1
  54. sqlspec/statement/builder/{delete.py → _delete.py} +1 -1
  55. sqlspec/statement/builder/{insert.py → _insert.py} +1 -1
  56. sqlspec/statement/builder/{merge.py → _merge.py} +1 -1
  57. sqlspec/statement/builder/_parsing_utils.py +5 -3
  58. sqlspec/statement/builder/{select.py → _select.py} +59 -61
  59. sqlspec/statement/builder/{update.py → _update.py} +2 -2
  60. sqlspec/statement/builder/mixins/__init__.py +24 -30
  61. sqlspec/statement/builder/mixins/{_set_ops.py → _cte_and_set_ops.py} +86 -2
  62. sqlspec/statement/builder/mixins/{_delete_from.py → _delete_operations.py} +2 -0
  63. sqlspec/statement/builder/mixins/{_insert_values.py → _insert_operations.py} +70 -1
  64. sqlspec/statement/builder/mixins/{_merge_clauses.py → _merge_operations.py} +2 -0
  65. sqlspec/statement/builder/mixins/_order_limit_operations.py +123 -0
  66. sqlspec/statement/builder/mixins/{_pivot.py → _pivot_operations.py} +71 -2
  67. sqlspec/statement/builder/mixins/_select_operations.py +612 -0
  68. sqlspec/statement/builder/mixins/{_update_set.py → _update_operations.py} +73 -2
  69. sqlspec/statement/builder/mixins/_where_clause.py +536 -0
  70. sqlspec/statement/cache.py +50 -0
  71. sqlspec/statement/filters.py +37 -8
  72. sqlspec/statement/parameters.py +143 -54
  73. sqlspec/statement/pipelines/__init__.py +1 -1
  74. sqlspec/statement/pipelines/context.py +4 -10
  75. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +3 -3
  76. sqlspec/statement/pipelines/validators/_parameter_style.py +22 -22
  77. sqlspec/statement/pipelines/validators/_performance.py +1 -5
  78. sqlspec/statement/sql.py +246 -176
  79. sqlspec/utils/__init__.py +2 -1
  80. sqlspec/utils/statement_hashing.py +203 -0
  81. sqlspec/utils/type_guards.py +32 -0
  82. {sqlspec-0.13.1.dist-info → sqlspec-0.14.1.dist-info}/METADATA +1 -1
  83. sqlspec-0.14.1.dist-info/RECORD +145 -0
  84. sqlspec-0.14.1.dist-info/entry_points.txt +2 -0
  85. sqlspec/service/__init__.py +0 -4
  86. sqlspec/service/_util.py +0 -147
  87. sqlspec/service/pagination.py +0 -26
  88. sqlspec/statement/builder/mixins/_aggregate_functions.py +0 -250
  89. sqlspec/statement/builder/mixins/_case_builder.py +0 -91
  90. sqlspec/statement/builder/mixins/_common_table_expr.py +0 -90
  91. sqlspec/statement/builder/mixins/_from.py +0 -63
  92. sqlspec/statement/builder/mixins/_group_by.py +0 -118
  93. sqlspec/statement/builder/mixins/_having.py +0 -35
  94. sqlspec/statement/builder/mixins/_insert_from_select.py +0 -47
  95. sqlspec/statement/builder/mixins/_insert_into.py +0 -36
  96. sqlspec/statement/builder/mixins/_limit_offset.py +0 -53
  97. sqlspec/statement/builder/mixins/_order_by.py +0 -46
  98. sqlspec/statement/builder/mixins/_returning.py +0 -37
  99. sqlspec/statement/builder/mixins/_select_columns.py +0 -61
  100. sqlspec/statement/builder/mixins/_unpivot.py +0 -77
  101. sqlspec/statement/builder/mixins/_update_from.py +0 -55
  102. sqlspec/statement/builder/mixins/_update_table.py +0 -29
  103. sqlspec/statement/builder/mixins/_where.py +0 -401
  104. sqlspec/statement/builder/mixins/_window_functions.py +0 -86
  105. sqlspec/statement/parameter_manager.py +0 -220
  106. sqlspec/statement/sql_compiler.py +0 -140
  107. sqlspec-0.13.1.dist-info/RECORD +0 -150
  108. /sqlspec/statement/builder/{base.py → _base.py} +0 -0
  109. /sqlspec/statement/builder/mixins/{_join.py → _join_operations.py} +0 -0
  110. {sqlspec-0.13.1.dist-info → sqlspec-0.14.1.dist-info}/WHEEL +0 -0
  111. {sqlspec-0.13.1.dist-info → sqlspec-0.14.1.dist-info}/licenses/LICENSE +0 -0
  112. {sqlspec-0.13.1.dist-info → sqlspec-0.14.1.dist-info}/licenses/NOTICE +0 -0
sqlspec/utils/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
1
  from sqlspec.utils import deprecation, fixtures, module_loader, singleton, sync_tools, text
2
+ from sqlspec.utils.statement_hashing import hash_expression
2
3
 
3
- __all__ = ("deprecation", "fixtures", "module_loader", "singleton", "sync_tools", "text")
4
+ __all__ = ("deprecation", "fixtures", "hash_expression", "module_loader", "singleton", "sync_tools", "text")
@@ -0,0 +1,203 @@
1
+ """Statement hashing utilities for cache key generation.
2
+
3
+ This module provides centralized hashing logic for SQL statements,
4
+ including expressions, parameters, filters, and complete SQL objects.
5
+ """
6
+
7
+ from typing import TYPE_CHECKING, Any, Optional
8
+
9
+ from sqlglot import exp
10
+
11
+ if TYPE_CHECKING:
12
+ from sqlspec.statement.filters import StatementFilter
13
+ from sqlspec.statement.sql import SQL
14
+
15
+ __all__ = ("hash_expression", "hash_parameters", "hash_sql_statement")
16
+
17
+
18
+ def hash_expression(expr: Optional[exp.Expression], _seen: Optional[set[int]] = None) -> int:
19
+ """Generate deterministic hash from AST structure.
20
+
21
+ Args:
22
+ expr: SQLGlot Expression to hash
23
+ _seen: Set of seen object IDs to handle circular references
24
+
25
+ Returns:
26
+ Deterministic hash of the AST structure
27
+ """
28
+ if expr is None:
29
+ return hash(None)
30
+
31
+ if _seen is None:
32
+ _seen = set()
33
+
34
+ expr_id = id(expr)
35
+ if expr_id in _seen:
36
+ return hash(expr_id)
37
+
38
+ _seen.add(expr_id)
39
+
40
+ # Build hash from type and args
41
+ components: list[Any] = [type(expr).__name__]
42
+
43
+ for key, value in sorted(expr.args.items()):
44
+ components.extend((key, _hash_value(value, _seen)))
45
+
46
+ return hash(tuple(components))
47
+
48
+
49
+ def _hash_value(value: Any, _seen: set[int]) -> int:
50
+ """Hash different value types consistently.
51
+
52
+ Args:
53
+ value: Value to hash (can be Expression, list, dict, or primitive)
54
+ _seen: Set of seen object IDs to handle circular references
55
+
56
+ Returns:
57
+ Deterministic hash of the value
58
+ """
59
+ if isinstance(value, exp.Expression):
60
+ return hash_expression(value, _seen)
61
+ if isinstance(value, list):
62
+ return hash(tuple(_hash_value(v, _seen) for v in value))
63
+ if isinstance(value, dict):
64
+ items = sorted((k, _hash_value(v, _seen)) for k, v in value.items())
65
+ return hash(tuple(items))
66
+ if isinstance(value, tuple):
67
+ return hash(tuple(_hash_value(v, _seen) for v in value))
68
+ # Primitives: str, int, bool, None, etc.
69
+ return hash(value)
70
+
71
+
72
+ def hash_parameters(
73
+ positional_params: Optional[list[Any]] = None,
74
+ named_params: Optional[dict[str, Any]] = None,
75
+ original_parameters: Optional[Any] = None,
76
+ ) -> int:
77
+ """Generate hash for SQL parameters.
78
+
79
+ Args:
80
+ positional_params: List of positional parameters
81
+ named_params: Dictionary of named parameters
82
+ original_parameters: Original parameters (for execute_many)
83
+
84
+ Returns:
85
+ Combined hash of all parameters
86
+ """
87
+ param_hash = 0
88
+
89
+ # Hash positional parameters
90
+ if positional_params:
91
+ # Handle unhashable types like lists
92
+ hashable_params = []
93
+ for param in positional_params:
94
+ if isinstance(param, (list, dict)):
95
+ # Convert unhashable types to hashable representations
96
+ hashable_params.append(repr(param))
97
+ else:
98
+ hashable_params.append(param)
99
+ param_hash ^= hash(tuple(hashable_params))
100
+
101
+ # Hash named parameters
102
+ if named_params:
103
+ # Handle unhashable types in named params
104
+ hashable_items = []
105
+ for key, value in sorted(named_params.items()):
106
+ if isinstance(value, (list, dict)):
107
+ hashable_items.append((key, repr(value)))
108
+ else:
109
+ hashable_items.append((key, value))
110
+ param_hash ^= hash(tuple(hashable_items))
111
+
112
+ # Hash original parameters (important for execute_many)
113
+ if original_parameters is not None:
114
+ if isinstance(original_parameters, list):
115
+ # For execute_many, hash the count and first few items to avoid
116
+ # performance issues with large parameter sets
117
+ param_hash ^= hash(("original_count", len(original_parameters)))
118
+ if original_parameters:
119
+ # Hash first 3 items as representatives
120
+ sample_size = min(3, len(original_parameters))
121
+ sample_hash = hash(repr(original_parameters[:sample_size]))
122
+ param_hash ^= hash(("original_sample", sample_hash))
123
+ else:
124
+ param_hash ^= hash(("original", repr(original_parameters)))
125
+
126
+ return param_hash
127
+
128
+
129
+ def hash_filters(filters: Optional[list["StatementFilter"]] = None) -> int:
130
+ """Generate hash for statement filters.
131
+
132
+ Args:
133
+ filters: List of statement filters
134
+
135
+ Returns:
136
+ Hash of the filters
137
+ """
138
+ if not filters:
139
+ return 0
140
+
141
+ # Use class names and any hashable attributes
142
+ filter_components = []
143
+ for f in filters:
144
+ # Use class name as primary identifier
145
+ components: list[Any] = [f.__class__.__name__]
146
+
147
+ # Add any hashable attributes if available
148
+ if hasattr(f, "__dict__"):
149
+ for key, value in sorted(f.__dict__.items()):
150
+ try:
151
+ # Try to hash the value
152
+ hash(value)
153
+ components.append((key, value))
154
+ except TypeError: # noqa: PERF203
155
+ # If not hashable, use repr
156
+ components.append((key, repr(value)))
157
+
158
+ filter_components.append(tuple(components))
159
+
160
+ return hash(tuple(filter_components))
161
+
162
+
163
+ def hash_sql_statement(statement: "SQL") -> str:
164
+ """Generate a complete cache key for a SQL statement.
165
+
166
+ This centralizes all the complex hashing logic that was previously
167
+ scattered across different parts of the codebase.
168
+
169
+ Args:
170
+ statement: SQL statement object
171
+
172
+ Returns:
173
+ Cache key string
174
+ """
175
+ from sqlspec.utils.type_guards import is_expression
176
+
177
+ # Hash the expression or raw SQL
178
+ if is_expression(statement._statement):
179
+ expr_hash = hash_expression(statement._statement)
180
+ else:
181
+ expr_hash = hash(statement._raw_sql)
182
+
183
+ # Hash all parameters
184
+ param_hash = hash_parameters(
185
+ positional_params=statement._positional_params,
186
+ named_params=statement._named_params,
187
+ original_parameters=statement._original_parameters,
188
+ )
189
+
190
+ # Hash filters
191
+ filter_hash = hash_filters(statement._filters)
192
+
193
+ # Combine with other state
194
+ state_components = [
195
+ expr_hash,
196
+ param_hash,
197
+ filter_hash,
198
+ hash(statement._dialect), # Use _dialect instead of _config.dialect
199
+ hash(statement._is_many),
200
+ hash(statement._is_script),
201
+ ]
202
+
203
+ return f"sql:{hash(tuple(state_components))}"
@@ -69,11 +69,15 @@ __all__ = (
69
69
  "extract_dataclass_items",
70
70
  "has_bytes_conversion",
71
71
  "has_dict_attribute",
72
+ "has_expression_attr",
72
73
  "has_expressions",
74
+ "has_parameter_builder",
73
75
  "has_parameter_value",
74
76
  "has_query_builder_parameters",
75
77
  "has_risk_level",
76
78
  "has_sql_method",
79
+ "has_sqlglot_expression",
80
+ "has_to_statement",
77
81
  "has_with_method",
78
82
  "is_async_closeable_connection",
79
83
  "is_async_copy_capable",
@@ -890,3 +894,31 @@ def is_object_store_item(obj: Any) -> "TypeGuard[ObjectStoreItemProtocol]":
890
894
  from sqlspec.protocols import ObjectStoreItemProtocol
891
895
 
892
896
  return isinstance(obj, ObjectStoreItemProtocol)
897
+
898
+
899
+ def has_sqlglot_expression(obj: Any) -> "TypeGuard[Any]":
900
+ """Check if an object has a sqlglot_expression property."""
901
+ from sqlspec.protocols import HasSQLGlotExpressionProtocol
902
+
903
+ return isinstance(obj, HasSQLGlotExpressionProtocol)
904
+
905
+
906
+ def has_parameter_builder(obj: Any) -> "TypeGuard[Any]":
907
+ """Check if an object has an add_parameter method."""
908
+ from sqlspec.protocols import HasParameterBuilderProtocol
909
+
910
+ return isinstance(obj, HasParameterBuilderProtocol)
911
+
912
+
913
+ def has_expression_attr(obj: Any) -> "TypeGuard[Any]":
914
+ """Check if an object has an _expression attribute."""
915
+ from sqlspec.protocols import HasExpressionProtocol
916
+
917
+ return isinstance(obj, HasExpressionProtocol)
918
+
919
+
920
+ def has_to_statement(obj: Any) -> "TypeGuard[Any]":
921
+ """Check if an object has a to_statement method."""
922
+ from sqlspec.protocols import HasToStatementProtocol
923
+
924
+ return isinstance(obj, HasToStatementProtocol)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlspec
3
- Version: 0.13.1
3
+ Version: 0.14.1
4
4
  Summary: SQL Experiments in Python
5
5
  Project-URL: Discord, https://discord.gg/litestar
6
6
  Project-URL: Issue, https://github.com/litestar-org/sqlspec/issues/
@@ -0,0 +1,145 @@
1
+ sqlspec/__init__.py,sha256=SEPpbVPjSiF9kS4FpowO7S0jm8YNMD9FiX-5lrrCbY0,1676
2
+ sqlspec/__main__.py,sha256=tdu1ldelPAReNMbglVkTg7SVTEMTtxW1Ik3kLKdUonw,252
3
+ sqlspec/__metadata__.py,sha256=hNP3wXvtk8fQVPKGjRLpZ9mP-gaPJqzrmgm3UqpDIXQ,460
4
+ sqlspec/_serialization.py,sha256=7zox4G9zIps-DCdIEwYs4gwALfEOy1g_sWS4r5kpzO8,2604
5
+ sqlspec/_sql.py,sha256=zqMtVWBZzbnNErB8VyJkjDCPq0RNkhGUPA2ZCOtzmGo,35759
6
+ sqlspec/_typing.py,sha256=Vn1CTCfedAHZV3pKZP-l_mPw9pTxesCzRKVRypzNY_k,17903
7
+ sqlspec/base.py,sha256=a7adbCUzohf1MU-iP0TxazGsk9fsJhJmxuFKNWkgC6o,18355
8
+ sqlspec/cli.py,sha256=V8dYi286yXsrZg-w8vsh9OWKngViYCQJejujLjoV5co,9980
9
+ sqlspec/config.py,sha256=IfjXcHFXmGseUcMsf4eEHgeh7oOc2EEIg34R7BC62UI,13144
10
+ sqlspec/exceptions.py,sha256=T2h-tCN05sRKSpXDjPtYXvNgwInNVzTpha1PIkSUROQ,14168
11
+ sqlspec/loader.py,sha256=sR8hSbxbuo3QFC0YoIaT9Xf05QNqtG_WX912IG56kas,15353
12
+ sqlspec/protocols.py,sha256=Uum9tliNG6MOcXBK6KRBmkWGikhEAzH2qIAgZITXd1U,18094
13
+ sqlspec/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ sqlspec/typing.py,sha256=qkUcvruNzRUUfpv4AkbQezpy9SokhVHXlMbfFNwQlnU,8721
15
+ sqlspec/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ sqlspec/adapters/adbc/__init__.py,sha256=v9bs7501PgEyzR1XIsEpE2Wdrj9DOYkZ4grysw72UXk,218
17
+ sqlspec/adapters/adbc/config.py,sha256=LjcVqN3DUOxxz7u2j6o3DhIq4srS7TJrcUqQ86FFBGs,19898
18
+ sqlspec/adapters/adbc/driver.py,sha256=xHjeDukF8P9y491037kF7pt3mleb4jBHh8yIeiDG36c,17940
19
+ sqlspec/adapters/adbc/transformers.py,sha256=97L-5z278TSkjkK0fucDYb5i5G4WZheMkU8hlF53_Fk,4880
20
+ sqlspec/adapters/aiosqlite/__init__.py,sha256=7wPmhXQeu4jRi-LZzPxAPTdgRmgmyqCn9U-4wnCWoLM,258
21
+ sqlspec/adapters/aiosqlite/config.py,sha256=Rg2RduE5wLM7JkEITtQg6kJQ2n6YVgKsl0S-io-18n0,7246
22
+ sqlspec/adapters/aiosqlite/driver.py,sha256=40c3YVO9UcnUDSlqwEpuI2CNMzsufR4WVGeUKBMcnMY,12176
23
+ sqlspec/adapters/asyncmy/__init__.py,sha256=zYpebEt_PrNCifLcqXiCcWVm0Zl-LvWbFDromWwSTw8,270
24
+ sqlspec/adapters/asyncmy/config.py,sha256=jYeF80DKdd5arS4kSPz4hcpLnzv1WgQa5s9DmEy02OU,10155
25
+ sqlspec/adapters/asyncmy/driver.py,sha256=-rZcBj-gbJ6r3qZQzltqfOHyA70iSg9r4XtieuLliGg,10571
26
+ sqlspec/adapters/asyncpg/__init__.py,sha256=svnbKlOin8jRL88AdAqflBEU-WEAzp0Thc2y50QsxIo,310
27
+ sqlspec/adapters/asyncpg/config.py,sha256=8fKZ55YynepP7eC6A0Z3jpXcGVoSuLW9yGUH04O2a4A,11857
28
+ sqlspec/adapters/asyncpg/driver.py,sha256=sfoxCkHzJvRuE5kNRUH--zCecf2kcqNnDz9OIYsLv54,18629
29
+ sqlspec/adapters/bigquery/__init__.py,sha256=fWRH-BoCNX4rYwhU2DK64cXWpfkYpWIExddJAti0bxM,250
30
+ sqlspec/adapters/bigquery/config.py,sha256=z6FFWUvk3AdXcPRmOYf1lg-UlBqCq8EEDcxDz8-lI0Y,15773
31
+ sqlspec/adapters/bigquery/driver.py,sha256=zUZGGOuzQ4M4Ekt0H59UUQvX8AT4i-YUalkp2Ql6lKo,30956
32
+ sqlspec/adapters/duckdb/__init__.py,sha256=I1f6szfpKKrq6WhyDoUXD3i3NN4yjsh94_fhP1URI5M,351
33
+ sqlspec/adapters/duckdb/config.py,sha256=5k2fgJN1yTZuq4I0VRyIaiMno507sd6R_sl5G8sgpsI,18974
34
+ sqlspec/adapters/duckdb/driver.py,sha256=499tJ9xLj_09MDmnhuGHPiknzT7OFhCmorxB1yHXvXs,19051
35
+ sqlspec/adapters/oracledb/__init__.py,sha256=nn3whn0UyBThoXnE1-5_byVuc9PJjvB2P896p7LpNZI,474
36
+ sqlspec/adapters/oracledb/config.py,sha256=IRIwiWOo0BWoilGxtkrGNZEzVc8o8JqBQXSWdQoKgK8,22017
37
+ sqlspec/adapters/oracledb/driver.py,sha256=S7AyrOk1YbtGsdwrRJJi9-iI2hsBBE8rE67Tlw2kXMY,25790
38
+ sqlspec/adapters/psqlpy/__init__.py,sha256=dp0-96V4SAbNEvOqlJ8PWEyJMYzZGElVoyneZqJ-fbQ,297
39
+ sqlspec/adapters/psqlpy/config.py,sha256=7sM-RGEVpkJLHrX7DemlreL7spJdcrVZ0dDQSMDyt4k,15309
40
+ sqlspec/adapters/psqlpy/driver.py,sha256=GifEdVZKgqKaN0pajWCpZVvW0bKNRXeMZUhcNu-tetQ,10839
41
+ sqlspec/adapters/psycopg/__init__.py,sha256=ukkCUPrJPyAG78v4rOqcK4WZDs26PeB9Ra9qkFrGJ3E,484
42
+ sqlspec/adapters/psycopg/config.py,sha256=PAKtLZHQjGI3oCzoUL5jd0pNrOEdFTtRPsr9-kRmiqo,26300
43
+ sqlspec/adapters/psycopg/driver.py,sha256=lFoqYgG19lAA32_zjkx2yzYosBoINdnWG20KLDz2a3Q,42123
44
+ sqlspec/adapters/sqlite/__init__.py,sha256=1lYrJ-DojUAOvXMoZRUJNEVyMmYhO41hMJnDWCEeXlw,234
45
+ sqlspec/adapters/sqlite/config.py,sha256=ab9gYZvisBMO-lcB93ufmNn8lajs0-ZnFSrCtghWXPY,5757
46
+ sqlspec/adapters/sqlite/driver.py,sha256=Joov0hv709BrkNFFEyBC8saa3MgAM8uW0Du-kQxXedk,13343
47
+ sqlspec/driver/__init__.py,sha256=0udRS5IlJ17HzOCvzapG8c_88yAwTQri1XLD_3fZxZU,671
48
+ sqlspec/driver/_async.py,sha256=UYNjJ70kcIeRWfMBfXqBeVhtqGP9QhmANT2bR2VkRH8,10594
49
+ sqlspec/driver/_common.py,sha256=ohRsk4RmwHO0qLuDbjUpbXB9URC5CWrUOE-lSkFW5JI,15831
50
+ sqlspec/driver/_sync.py,sha256=yivXeRRIFpWkS62Kbi-pRDYidhh3epdJTbjqhLxwFNo,10434
51
+ sqlspec/driver/connection.py,sha256=zKP2p-VLxN07IPfOIBKMRELHN7ZMjmRVUKBgSW-6RQg,6610
52
+ sqlspec/driver/parameters.py,sha256=hxS3K6oICM8mtvRI3429jHPlJJL524b26wU3XFiFlKA,3995
53
+ sqlspec/driver/mixins/__init__.py,sha256=fvzM9gVjjnfUUTZ1TaDv-tEnxS1X-lxYiH7kZvBptzk,922
54
+ sqlspec/driver/mixins/_cache.py,sha256=GmQZLId_RdJX9BpEnVgWYWVmii3yjqGdnA6p1yawo08,3990
55
+ sqlspec/driver/mixins/_csv_writer.py,sha256=-uRe7QZRWtdZTFG3Fiej4Ia8EyQcjYr7oPT6wb0qTOc,2716
56
+ sqlspec/driver/mixins/_pipeline.py,sha256=71OyeDxAQc7KNGFqObMYUU_4LBCMvsm0qCZDiHEDwOI,19548
57
+ sqlspec/driver/mixins/_query_tools.py,sha256=c12s9gmOhAmgvIbK301SllOz89svgOXau5PwwnNu_TY,29186
58
+ sqlspec/driver/mixins/_result_utils.py,sha256=JzMpBXLxn9POMUnqaShhU1qc8TlHwCEy8H5vqnpNnXE,5672
59
+ sqlspec/driver/mixins/_sql_translator.py,sha256=wMv8FtGmulewCTFMdiQhlkiTz8hf7PKy_8VKP55aTuU,1499
60
+ sqlspec/driver/mixins/_storage.py,sha256=YNpkp_ZLXCIwJjosaUJXEFHhi8QGtgP1lKKop_YSWPc,38120
61
+ sqlspec/driver/mixins/_type_coercion.py,sha256=Al5IhsYzCnauOYW9o-STZ9DbIi9u8qYHJDeNDppN5q4,4558
62
+ sqlspec/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ sqlspec/extensions/aiosql/__init__.py,sha256=-9cefc9pYPf9vCgALoB-y1DtmcgRjKe2azfl6RIarAA,414
64
+ sqlspec/extensions/aiosql/adapter.py,sha256=jLOMftHnUR42khs63aYFS2TYa6udUPf4WrYbgHoUajg,16522
65
+ sqlspec/extensions/litestar/__init__.py,sha256=tOmQ7RHSWOot7p30gk0efxxuP0OCq1opyyZqNmQY7FE,320
66
+ sqlspec/extensions/litestar/_utils.py,sha256=o-FuUj1_WkDrLxQxiP6hXDak66XfyRP3QLyEVKrIRjI,1954
67
+ sqlspec/extensions/litestar/cli.py,sha256=NYjPIWe0jESBgS0AG-3bdpcC5YM4RmZeeeTeFQK5Yqo,1362
68
+ sqlspec/extensions/litestar/config.py,sha256=vLXM425tCV3IbJiNO1ZG90ctjBTb9oQCuLsqCaUYmo8,4685
69
+ sqlspec/extensions/litestar/handlers.py,sha256=bVoWmHhCsHZkXZXYHE23yDaJlRoydfvU-boJjA3BSLE,10478
70
+ sqlspec/extensions/litestar/plugin.py,sha256=SCkO6_dq6fiISXzNWqQTinbNayCMqzQ33EU9QhMWyAg,5539
71
+ sqlspec/extensions/litestar/providers.py,sha256=wUGqPeNV58rPqL1iwDQg439C4y-Zg-eXEogjeFsv0iQ,21021
72
+ sqlspec/migrations/__init__.py,sha256=-Shsli3g2C7e8adYVrOwBskTb7iESiAy4NChvcueZkY,776
73
+ sqlspec/migrations/base.py,sha256=kvv_Vi4-ZV4_HY0Ug2cZdL3V7bkMSCKyzqus3kOyKyo,11894
74
+ sqlspec/migrations/commands.py,sha256=1Q_rO21uruurAdAxtw81PkH28iUSmay1Zi87kSYwRRY,19672
75
+ sqlspec/migrations/runner.py,sha256=CH9zh-BurgkgmSXU-dHdzl0Y1JqWfWJuYJ7SUtW89_0,6893
76
+ sqlspec/migrations/tracker.py,sha256=CLsqb6dy34WMvkhvKVBkj8s07FhAnWsgQ77k16bz_s4,5412
77
+ sqlspec/migrations/utils.py,sha256=NKyJbfHlcCMfzJzuQc9pItvoYPt4lG-mG8u4oBmLo6o,2614
78
+ sqlspec/statement/__init__.py,sha256=NDvdrpr1EqAZXp4HmhTVaRnWVscahPSHpmSO8DHSoMY,536
79
+ sqlspec/statement/cache.py,sha256=eS0vi5icd2TWOF1bFL2XKemF0NBW2dKMHNqSCCtwiF0,1387
80
+ sqlspec/statement/filters.py,sha256=CmgGtQ7W5gJHnskpWXXJ7jdVmtoEGioHRTPntAEil2E,23478
81
+ sqlspec/statement/parameters.py,sha256=SOXN7tT5KzOHFj4mlMMJMx_HanoBvzOd7ywBmMYPQAc,39236
82
+ sqlspec/statement/result.py,sha256=-yARFxg7Wsm8nAeHMpnJ58OLd2VujFiZx29wfo7eFVs,14514
83
+ sqlspec/statement/splitter.py,sha256=mCzJsNEtJFk4A0FdTELkG_qOggRFCQC_ZEJisVo9orY,24111
84
+ sqlspec/statement/sql.py,sha256=j85wR8EsgPjNkG5BokFr5RyYd06DpkDX6gSc8u7S0oA,75745
85
+ sqlspec/statement/builder/__init__.py,sha256=sDC8HQ-LnfqzF-XmTT0YErp8wTaJiIu5YP3pdhb2MgY,1618
86
+ sqlspec/statement/builder/_base.py,sha256=DArCuNwDXslt73Jk5Io3WqUP1ZXA0e4cUXtzFjvQ5g4,14738
87
+ sqlspec/statement/builder/_column.py,sha256=0yTC00IMRVVuOXYXdz2Uy7BmtLe48apIY1N6oSUbp0s,12918
88
+ sqlspec/statement/builder/_ddl.py,sha256=6VfhavHfS4vONRPXvQl2TohizhJNGUTwWGnN9XWqT1o,51521
89
+ sqlspec/statement/builder/_ddl_utils.py,sha256=6BEcVuSAt0mHPuT8QZQJapWorPxgMzaEX0PxKeYxMQg,4327
90
+ sqlspec/statement/builder/_delete.py,sha256=fDuLaQIcYAJEZrQ0tdnuSmo2DcbHPiOej_YceOBKI1c,2882
91
+ sqlspec/statement/builder/_insert.py,sha256=6LARJr81LAR418DNlzsy8qPErER14a-Dy0Cs9UZK20w,10130
92
+ sqlspec/statement/builder/_merge.py,sha256=xjyKDqU7ABb0gA6vMoQXJGTPsUkk1j6Siohj9wHWGaE,2784
93
+ sqlspec/statement/builder/_parsing_utils.py,sha256=dxvbSkYMAHbHJx3nMU_4S2baEJ6Vp1TIJpl7BehAlpY,5841
94
+ sqlspec/statement/builder/_select.py,sha256=RSVTloFC7v0KYcc-zrToLiZTmO8D18hCZQ1UCs4e4NU,8527
95
+ sqlspec/statement/builder/_update.py,sha256=d-epAsZn3HKU_QNWIP6X6dlXZTokSwLRMbN86pFyN_8,6247
96
+ sqlspec/statement/builder/mixins/__init__.py,sha256=W5xXHE315-vAg76gbRBsQmYu72XY7wZ2vTbXM1xR_tk,2002
97
+ sqlspec/statement/builder/mixins/_cte_and_set_ops.py,sha256=VH7a6rZ29C7z30z_z-joRu2XVP4jsNqtQzHpYyfQ2w0,8911
98
+ sqlspec/statement/builder/mixins/_delete_operations.py,sha256=0f8ZZMFx5b53EUx1oF264owLb6aWP45naeB6g-BZQys,1068
99
+ sqlspec/statement/builder/mixins/_insert_operations.py,sha256=93kVOOCZBxMAN0uILNejFYIDrBg04NsPIvz-cTTGKzA,5415
100
+ sqlspec/statement/builder/mixins/_join_operations.py,sha256=lSGFtq_KJ985SCmUKmIx-4NwniIwQIVmLJYryF5mtc4,5658
101
+ sqlspec/statement/builder/mixins/_merge_operations.py,sha256=RrjyueCzxOhqyJSrJQlL89LkJyKES2-kMsfKy-w89XQ,16846
102
+ sqlspec/statement/builder/mixins/_order_limit_operations.py,sha256=7UOvQrRwTnOpBAXTGV509aqNj63J5UhuMIHYBjLh8vE,4538
103
+ sqlspec/statement/builder/mixins/_pivot_operations.py,sha256=yyKxBHaw9ApO4mwALo3ulohT08Z3kh07Mtst4DMULk4,6181
104
+ sqlspec/statement/builder/mixins/_select_operations.py,sha256=WM_wZPdKy8m-kAlfrMECFX1c2U5sZk-qRH_pTAMlUW4,25433
105
+ sqlspec/statement/builder/mixins/_update_operations.py,sha256=h9yMqIfLJvZlv8uJBZktqT3pJyu62DxPKffSedS0NuI,7508
106
+ sqlspec/statement/builder/mixins/_where_clause.py,sha256=yBRXq0pPMJKvpbaGI0FLZQNE2gw9ND_wofXTnsSXtZw,27018
107
+ sqlspec/statement/pipelines/__init__.py,sha256=aN8GtpqtjTKALANNm8KH5Adq9ijP1_Kq_I9s0S7t0QI,7343
108
+ sqlspec/statement/pipelines/context.py,sha256=ZL_1XvkPxadUtRijOh-pJ7jOkkikpNt8lymc20Jnmv8,3915
109
+ sqlspec/statement/pipelines/analyzers/__init__.py,sha256=RY7W0AiWG-8qdrTmRSGlEofjrPPJCJUnNK-LRukKt5Q,330
110
+ sqlspec/statement/pipelines/analyzers/_analyzer.py,sha256=0_FDty6H_4JvQwee_NrzmptX9-VdhyAePXUstuq4MU4,27474
111
+ sqlspec/statement/pipelines/transformers/__init__.py,sha256=Kh4CE_izdwEsSF7Is6_6NXqtNmbLm5x5OWdnlUGp9ok,480
112
+ sqlspec/statement/pipelines/transformers/_expression_simplifier.py,sha256=-imYcKeYcE66Uj04k-QywCcjvuZmvha_2H6rTy7wdSo,3376
113
+ sqlspec/statement/pipelines/transformers/_literal_parameterizer.py,sha256=N6a2lMGBHXcoHuSySY_9JhObNkPWabUBpR_25ZCnv0w,57183
114
+ sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py,sha256=-gM6VnlhNtQzSbQq44hQ5mhaPqNsjzeCaTgXTycgkOk,3008
115
+ sqlspec/statement/pipelines/validators/__init__.py,sha256=cdlwdLhOT2OwTbueIsA7bfRG2b6y-j7dw9pMzl5AP0M,747
116
+ sqlspec/statement/pipelines/validators/_dml_safety.py,sha256=s7Eee60u6w0K35vz4GVAwsB5Xy8zUqWhiIx_pRVfERo,10585
117
+ sqlspec/statement/pipelines/validators/_parameter_style.py,sha256=Dj85rkH1GyO4dRDgix-4CR9i3sTN_dO4pfmnIe8ORmg,17810
118
+ sqlspec/statement/pipelines/validators/_performance.py,sha256=HjXi24xh5jAHoP-tRZisu21E6ZnE1il4nQOMgRc80qo,26275
119
+ sqlspec/statement/pipelines/validators/_security.py,sha256=3WuH9n4j-VKOgmQnZvFIoI4MieRBVShtOZvXl2SJsyk,42103
120
+ sqlspec/storage/__init__.py,sha256=ZS8rmhN8e_h_df-Oab64Jh4EbddElBbmrtHkuO-KqOE,703
121
+ sqlspec/storage/capabilities.py,sha256=fsnQ9jbjHBFvd3P9yWAzfjPpVYUGcsTtR6fm5iOCvXY,3054
122
+ sqlspec/storage/registry.py,sha256=lv9pGt6vt0tDNAlao9qA7rSsFsCZtaOr48aG15IoMFA,10976
123
+ sqlspec/storage/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
+ sqlspec/storage/backends/base.py,sha256=34XYQuz1tQ-q_ZZwOz-Kimgvl088SR3VUYJoA-STslc,6350
125
+ sqlspec/storage/backends/fsspec.py,sha256=wo40MwtEjNTc73ZNTCmNC2-Img0zldUCaFGh9H3BZuE,14715
126
+ sqlspec/storage/backends/obstore.py,sha256=FnoVzTzzNn5NRXR8GgETqD3Rq9C5EWAmfWmY4JDFVJE,21214
127
+ sqlspec/utils/__init__.py,sha256=3nF4cd2RQX5SoCILETafwj-Vn6FVu7PCXtZhp6CbpL0,262
128
+ sqlspec/utils/cached_property.py,sha256=Sw_JZxfChSJu72gvYBJPF-89FyyIJAPf-1ETlDq-F2E,648
129
+ sqlspec/utils/correlation.py,sha256=4jqpjMivxI1tQ13Ed-P0hLdFHUKUQ9GlvIM69_HOlS4,4370
130
+ sqlspec/utils/deprecation.py,sha256=zrmb_eKRlLWVA6dWrjUbN3Vz6D3_-Z_15Ixk4H-sDRk,3850
131
+ sqlspec/utils/fixtures.py,sha256=q_Pghpmw2VgJ9P0TfkyjSF5PvdaD5Y2Laha0Bj4IDrA,1838
132
+ sqlspec/utils/logging.py,sha256=56a5tqx4jfTqm20WDyj5c7Dy-h_O0KambIKOMr1-Oms,3780
133
+ sqlspec/utils/module_loader.py,sha256=9LcmEhy4T0jgkCaDVkxX47PSgJOMeJ8IV67yXEWBp-U,3074
134
+ sqlspec/utils/serializers.py,sha256=TKsRryRcYMnb8Z8MGkYGClIxcYvC8CW7MsrPQTJqEcY,154
135
+ sqlspec/utils/singleton.py,sha256=KZ7481tlDAxq6gcAlpULVqPLNc9P0XkHOEp7hfWIHcI,1096
136
+ sqlspec/utils/statement_hashing.py,sha256=Y5OKJNucINCqXeRL9d2nGRzGuIlkK5RgK40QRZfedKU,6396
137
+ sqlspec/utils/sync_tools.py,sha256=ckP1_uLh40C2pDvdc4FsR4NkmZVa1zEB8jhUxPLIuAI,8726
138
+ sqlspec/utils/text.py,sha256=DpEnRuSDv3acp4VQQGEOQixlJnLGZsN5YBws4rkI6t0,4756
139
+ sqlspec/utils/type_guards.py,sha256=0sDlkB4HVl0uVA4asDNQgbGTu9Q7YaUrGllhneOi0LY,26755
140
+ sqlspec-0.14.1.dist-info/METADATA,sha256=-AljfX5325tdemtqBiV88XvctU2KTuBPlia6TFem-dI,16663
141
+ sqlspec-0.14.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
142
+ sqlspec-0.14.1.dist-info/entry_points.txt,sha256=G-ZqY1Nuuw3Iys7nXw23f6ILenk_Lt47VdK2mhJCWHg,53
143
+ sqlspec-0.14.1.dist-info/licenses/LICENSE,sha256=MdujfZ6l5HuLz4mElxlu049itenOR3gnhN1_Nd3nVcM,1078
144
+ sqlspec-0.14.1.dist-info/licenses/NOTICE,sha256=Lyir8ozXWov7CyYS4huVaOCNrtgL17P-bNV-5daLntQ,1634
145
+ sqlspec-0.14.1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ sqlspec = sqlspec.__main__:run_cli
@@ -1,4 +0,0 @@
1
- from sqlspec.service.base import SQLSpecAsyncService, SQLSpecSyncService
2
- from sqlspec.service.pagination import OffsetPagination
3
-
4
- __all__ = ("OffsetPagination", "SQLSpecAsyncService", "SQLSpecSyncService")
sqlspec/service/_util.py DELETED
@@ -1,147 +0,0 @@
1
- from collections.abc import Sequence
2
- from functools import partial
3
- from typing import Any, Optional, TypeVar, Union, cast, overload
4
-
5
- from sqlspec.driver.mixins._result_utils import _DEFAULT_TYPE_DECODERS, _default_msgspec_deserializer
6
- from sqlspec.exceptions import SQLSpecError
7
- from sqlspec.service.pagination import OffsetPagination
8
- from sqlspec.statement.filters import FilterTypeT, LimitOffsetFilter, StatementFilter
9
- from sqlspec.typing import BaseModel, DataclassProtocol, ModelDTOT, ModelT, Struct, convert, get_type_adapter
10
- from sqlspec.utils.type_guards import is_dataclass, is_msgspec_struct, is_pydantic_model
11
-
12
- __all__ = ("ResultConverter", "find_filter")
13
-
14
-
15
- T = TypeVar("T")
16
-
17
-
18
- def find_filter(
19
- filter_type: "type[FilterTypeT]", filters: "Optional[Sequence[StatementFilter]]" = None
20
- ) -> "Optional[FilterTypeT]":
21
- """Get the filter specified by filter type from the filters.
22
-
23
- Args:
24
- filter_type: The type of filter to find.
25
- filters: filter types to apply to the query
26
-
27
- Returns:
28
- The match filter instance or None
29
- """
30
- if filters is None:
31
- return None
32
- return next(
33
- (cast("Optional[FilterTypeT]", filter_) for filter_ in filters if isinstance(filter_, filter_type)), None
34
- )
35
-
36
-
37
- # TODO: add overloads for each type of pagination in the future
38
- class ResultConverter:
39
- """Simple mixin to help convert to dictionary or list of dictionaries to specified schema type.
40
-
41
- Single objects are transformed to the supplied schema type, and lists of objects are transformed into a list of the supplied schema type.
42
-
43
- Args:
44
- data: A database model instance or row mapping.
45
- Type: :class:`~sqlspec.typing.ModelDictT`
46
-
47
- Returns:
48
- The converted schema object.
49
- """
50
-
51
- @overload
52
- def to_schema(
53
- self,
54
- data: "ModelT",
55
- total: "int | None" = None,
56
- filters: "Sequence[StatementFilter] | None" = None,
57
- *,
58
- schema_type: None = None,
59
- ) -> "ModelT": ...
60
- @overload
61
- def to_schema(
62
- self,
63
- data: "dict[str, Any] | Struct | BaseModel | DataclassProtocol",
64
- total: "int | None" = None,
65
- filters: "Sequence[StatementFilter] | None" = None,
66
- *,
67
- schema_type: "type[ModelDTOT]",
68
- ) -> "ModelDTOT": ...
69
- @overload
70
- def to_schema(
71
- self,
72
- data: "Sequence[ModelT]",
73
- total: "int | None" = None,
74
- filters: "Sequence[StatementFilter] | None" = None,
75
- *,
76
- schema_type: None = None,
77
- ) -> "OffsetPagination[ModelT]": ...
78
- @overload
79
- def to_schema(
80
- self,
81
- data: "Sequence[dict[str, Any] | Struct | BaseModel | DataclassProtocol]",
82
- total: "int | None" = None,
83
- filters: "Sequence[StatementFilter] | None" = None,
84
- *,
85
- schema_type: "type[ModelDTOT]",
86
- ) -> "OffsetPagination[ModelDTOT]": ...
87
- def to_schema(
88
- self,
89
- data: "ModelT | Sequence[ModelT] | dict[str, Any] | Struct | BaseModel | DataclassProtocol | Sequence[dict[str, Any] | Struct | BaseModel | DataclassProtocol]",
90
- total: "int | None" = None,
91
- filters: "Sequence[StatementFilter] | None" = None,
92
- *,
93
- schema_type: "type[ModelDTOT] | None" = None,
94
- ) -> "Union[ModelT, ModelDTOT , OffsetPagination[ModelT] , OffsetPagination[ModelDTOT]]":
95
- if not isinstance(data, Sequence):
96
- if schema_type is None:
97
- return cast("ModelT", data)
98
- if is_dataclass(schema_type):
99
- return cast("ModelDTOT", schema_type(**data)) # type: ignore[operator]
100
- if is_msgspec_struct(schema_type):
101
- return cast(
102
- "ModelDTOT",
103
- convert(
104
- obj=data,
105
- type=schema_type,
106
- from_attributes=True,
107
- dec_hook=partial(_default_msgspec_deserializer, type_decoders=_DEFAULT_TYPE_DECODERS),
108
- ),
109
- )
110
- if is_pydantic_model(schema_type): # pyright: ignore
111
- return cast(
112
- "ModelDTOT",
113
- get_type_adapter(schema_type).validate_python(data, from_attributes=True), # pyright: ignore
114
- )
115
- assert isinstance(data, Sequence)
116
- limit_offset = find_filter(LimitOffsetFilter, filters=filters)
117
- if schema_type is None:
118
- return OffsetPagination[ModelT](
119
- items=cast("list[ModelT]", data),
120
- limit=limit_offset.limit if limit_offset else len(data),
121
- offset=limit_offset.offset if limit_offset else 0,
122
- total=total if total is not None else len(data),
123
- )
124
- converted_items: Sequence[ModelDTOT]
125
- if is_dataclass(schema_type):
126
- converted_items = [schema_type(**item) for item in data] # type: ignore[operator]
127
- elif is_msgspec_struct(schema_type):
128
- converted_items = convert(
129
- obj=data,
130
- type=list[schema_type], # type: ignore[valid-type]
131
- from_attributes=True,
132
- dec_hook=partial(_default_msgspec_deserializer, type_decoders=_DEFAULT_TYPE_DECODERS),
133
- )
134
- elif is_pydantic_model(schema_type): # pyright: ignore
135
- converted_items = get_type_adapter(list[schema_type]).validate_python(data, from_attributes=True) # type: ignore[valid-type] # pyright: ignore[reportUnknownArgumentType]
136
- else:
137
- # This will also catch the case where a single item had an unrecognized schema_type
138
- # if it somehow bypassed the initial single-item checks.
139
- msg = "`schema_type` should be a valid Dataclass, Pydantic model or Msgspec struct"
140
- raise SQLSpecError(msg)
141
-
142
- return OffsetPagination[ModelDTOT](
143
- items=cast("list[ModelDTOT]", converted_items),
144
- limit=limit_offset.limit if limit_offset else len(data),
145
- offset=limit_offset.offset if limit_offset else 0,
146
- total=total if total is not None else len(data),
147
- )
@@ -1,26 +0,0 @@
1
- from collections.abc import Sequence
2
- from dataclasses import dataclass
3
- from typing import Generic, TypeVar
4
-
5
- T = TypeVar("T")
6
-
7
- __all__ = ("OffsetPagination",)
8
-
9
-
10
- @dataclass
11
- class OffsetPagination(Generic[T]):
12
- """Container for data returned using limit/offset pagination."""
13
-
14
- __slots__ = ("items", "limit", "offset", "total")
15
-
16
- items: Sequence[T]
17
- """List of data being sent as part of the response."""
18
- limit: int
19
- """Maximal number of items to send."""
20
- offset: int
21
- """Offset from the beginning of the query.
22
-
23
- Identical to an index.
24
- """
25
- total: int
26
- """Total number of items."""