sqlspec 0.16.1__cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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 (148) hide show
  1. 51ff5a9eadfdefd49f98__mypyc.cpython-312-aarch64-linux-gnu.so +0 -0
  2. sqlspec/__init__.py +92 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_serialization.py +77 -0
  6. sqlspec/_sql.py +1780 -0
  7. sqlspec/_typing.py +680 -0
  8. sqlspec/adapters/__init__.py +0 -0
  9. sqlspec/adapters/adbc/__init__.py +5 -0
  10. sqlspec/adapters/adbc/_types.py +12 -0
  11. sqlspec/adapters/adbc/config.py +361 -0
  12. sqlspec/adapters/adbc/driver.py +512 -0
  13. sqlspec/adapters/aiosqlite/__init__.py +19 -0
  14. sqlspec/adapters/aiosqlite/_types.py +13 -0
  15. sqlspec/adapters/aiosqlite/config.py +253 -0
  16. sqlspec/adapters/aiosqlite/driver.py +248 -0
  17. sqlspec/adapters/asyncmy/__init__.py +19 -0
  18. sqlspec/adapters/asyncmy/_types.py +12 -0
  19. sqlspec/adapters/asyncmy/config.py +180 -0
  20. sqlspec/adapters/asyncmy/driver.py +274 -0
  21. sqlspec/adapters/asyncpg/__init__.py +21 -0
  22. sqlspec/adapters/asyncpg/_types.py +17 -0
  23. sqlspec/adapters/asyncpg/config.py +229 -0
  24. sqlspec/adapters/asyncpg/driver.py +344 -0
  25. sqlspec/adapters/bigquery/__init__.py +18 -0
  26. sqlspec/adapters/bigquery/_types.py +12 -0
  27. sqlspec/adapters/bigquery/config.py +298 -0
  28. sqlspec/adapters/bigquery/driver.py +558 -0
  29. sqlspec/adapters/duckdb/__init__.py +22 -0
  30. sqlspec/adapters/duckdb/_types.py +12 -0
  31. sqlspec/adapters/duckdb/config.py +504 -0
  32. sqlspec/adapters/duckdb/driver.py +368 -0
  33. sqlspec/adapters/oracledb/__init__.py +32 -0
  34. sqlspec/adapters/oracledb/_types.py +14 -0
  35. sqlspec/adapters/oracledb/config.py +317 -0
  36. sqlspec/adapters/oracledb/driver.py +538 -0
  37. sqlspec/adapters/psqlpy/__init__.py +16 -0
  38. sqlspec/adapters/psqlpy/_types.py +11 -0
  39. sqlspec/adapters/psqlpy/config.py +214 -0
  40. sqlspec/adapters/psqlpy/driver.py +530 -0
  41. sqlspec/adapters/psycopg/__init__.py +32 -0
  42. sqlspec/adapters/psycopg/_types.py +17 -0
  43. sqlspec/adapters/psycopg/config.py +426 -0
  44. sqlspec/adapters/psycopg/driver.py +796 -0
  45. sqlspec/adapters/sqlite/__init__.py +15 -0
  46. sqlspec/adapters/sqlite/_types.py +11 -0
  47. sqlspec/adapters/sqlite/config.py +240 -0
  48. sqlspec/adapters/sqlite/driver.py +294 -0
  49. sqlspec/base.py +571 -0
  50. sqlspec/builder/__init__.py +62 -0
  51. sqlspec/builder/_base.py +473 -0
  52. sqlspec/builder/_column.py +320 -0
  53. sqlspec/builder/_ddl.py +1346 -0
  54. sqlspec/builder/_ddl_utils.py +103 -0
  55. sqlspec/builder/_delete.py +76 -0
  56. sqlspec/builder/_insert.py +256 -0
  57. sqlspec/builder/_merge.py +71 -0
  58. sqlspec/builder/_parsing_utils.py +140 -0
  59. sqlspec/builder/_select.py +170 -0
  60. sqlspec/builder/_update.py +188 -0
  61. sqlspec/builder/mixins/__init__.py +55 -0
  62. sqlspec/builder/mixins/_cte_and_set_ops.py +222 -0
  63. sqlspec/builder/mixins/_delete_operations.py +41 -0
  64. sqlspec/builder/mixins/_insert_operations.py +244 -0
  65. sqlspec/builder/mixins/_join_operations.py +122 -0
  66. sqlspec/builder/mixins/_merge_operations.py +476 -0
  67. sqlspec/builder/mixins/_order_limit_operations.py +135 -0
  68. sqlspec/builder/mixins/_pivot_operations.py +153 -0
  69. sqlspec/builder/mixins/_select_operations.py +603 -0
  70. sqlspec/builder/mixins/_update_operations.py +187 -0
  71. sqlspec/builder/mixins/_where_clause.py +621 -0
  72. sqlspec/cli.py +247 -0
  73. sqlspec/config.py +395 -0
  74. sqlspec/core/__init__.py +63 -0
  75. sqlspec/core/cache.cpython-312-aarch64-linux-gnu.so +0 -0
  76. sqlspec/core/cache.py +871 -0
  77. sqlspec/core/compiler.cpython-312-aarch64-linux-gnu.so +0 -0
  78. sqlspec/core/compiler.py +417 -0
  79. sqlspec/core/filters.cpython-312-aarch64-linux-gnu.so +0 -0
  80. sqlspec/core/filters.py +830 -0
  81. sqlspec/core/hashing.cpython-312-aarch64-linux-gnu.so +0 -0
  82. sqlspec/core/hashing.py +310 -0
  83. sqlspec/core/parameters.cpython-312-aarch64-linux-gnu.so +0 -0
  84. sqlspec/core/parameters.py +1237 -0
  85. sqlspec/core/result.cpython-312-aarch64-linux-gnu.so +0 -0
  86. sqlspec/core/result.py +677 -0
  87. sqlspec/core/splitter.cpython-312-aarch64-linux-gnu.so +0 -0
  88. sqlspec/core/splitter.py +819 -0
  89. sqlspec/core/statement.cpython-312-aarch64-linux-gnu.so +0 -0
  90. sqlspec/core/statement.py +676 -0
  91. sqlspec/driver/__init__.py +19 -0
  92. sqlspec/driver/_async.py +502 -0
  93. sqlspec/driver/_common.py +631 -0
  94. sqlspec/driver/_sync.py +503 -0
  95. sqlspec/driver/mixins/__init__.py +6 -0
  96. sqlspec/driver/mixins/_result_tools.py +193 -0
  97. sqlspec/driver/mixins/_sql_translator.py +86 -0
  98. sqlspec/exceptions.py +193 -0
  99. sqlspec/extensions/__init__.py +0 -0
  100. sqlspec/extensions/aiosql/__init__.py +10 -0
  101. sqlspec/extensions/aiosql/adapter.py +461 -0
  102. sqlspec/extensions/litestar/__init__.py +6 -0
  103. sqlspec/extensions/litestar/_utils.py +52 -0
  104. sqlspec/extensions/litestar/cli.py +48 -0
  105. sqlspec/extensions/litestar/config.py +92 -0
  106. sqlspec/extensions/litestar/handlers.py +260 -0
  107. sqlspec/extensions/litestar/plugin.py +145 -0
  108. sqlspec/extensions/litestar/providers.py +454 -0
  109. sqlspec/loader.cpython-312-aarch64-linux-gnu.so +0 -0
  110. sqlspec/loader.py +760 -0
  111. sqlspec/migrations/__init__.py +35 -0
  112. sqlspec/migrations/base.py +414 -0
  113. sqlspec/migrations/commands.py +443 -0
  114. sqlspec/migrations/loaders.py +402 -0
  115. sqlspec/migrations/runner.py +213 -0
  116. sqlspec/migrations/tracker.py +140 -0
  117. sqlspec/migrations/utils.py +129 -0
  118. sqlspec/protocols.py +407 -0
  119. sqlspec/py.typed +0 -0
  120. sqlspec/storage/__init__.py +23 -0
  121. sqlspec/storage/backends/__init__.py +0 -0
  122. sqlspec/storage/backends/base.py +163 -0
  123. sqlspec/storage/backends/fsspec.py +386 -0
  124. sqlspec/storage/backends/obstore.py +459 -0
  125. sqlspec/storage/capabilities.py +102 -0
  126. sqlspec/storage/registry.py +239 -0
  127. sqlspec/typing.py +299 -0
  128. sqlspec/utils/__init__.py +3 -0
  129. sqlspec/utils/correlation.py +150 -0
  130. sqlspec/utils/deprecation.py +106 -0
  131. sqlspec/utils/fixtures.cpython-312-aarch64-linux-gnu.so +0 -0
  132. sqlspec/utils/fixtures.py +58 -0
  133. sqlspec/utils/logging.py +127 -0
  134. sqlspec/utils/module_loader.py +89 -0
  135. sqlspec/utils/serializers.py +4 -0
  136. sqlspec/utils/singleton.py +32 -0
  137. sqlspec/utils/sync_tools.cpython-312-aarch64-linux-gnu.so +0 -0
  138. sqlspec/utils/sync_tools.py +237 -0
  139. sqlspec/utils/text.cpython-312-aarch64-linux-gnu.so +0 -0
  140. sqlspec/utils/text.py +96 -0
  141. sqlspec/utils/type_guards.cpython-312-aarch64-linux-gnu.so +0 -0
  142. sqlspec/utils/type_guards.py +1139 -0
  143. sqlspec-0.16.1.dist-info/METADATA +365 -0
  144. sqlspec-0.16.1.dist-info/RECORD +148 -0
  145. sqlspec-0.16.1.dist-info/WHEEL +7 -0
  146. sqlspec-0.16.1.dist-info/entry_points.txt +2 -0
  147. sqlspec-0.16.1.dist-info/licenses/LICENSE +21 -0
  148. sqlspec-0.16.1.dist-info/licenses/NOTICE +29 -0
@@ -0,0 +1,140 @@
1
+ """Migration version tracking for SQLSpec.
2
+
3
+ This module provides functionality to track applied migrations in the database.
4
+ """
5
+
6
+ import os
7
+ from typing import TYPE_CHECKING, Any, Optional
8
+
9
+ from sqlspec.migrations.base import BaseMigrationTracker
10
+
11
+ if TYPE_CHECKING:
12
+ from sqlspec.driver import AsyncDriverAdapterBase, SyncDriverAdapterBase
13
+
14
+ __all__ = ("AsyncMigrationTracker", "SyncMigrationTracker")
15
+
16
+
17
+ class SyncMigrationTracker(BaseMigrationTracker["SyncDriverAdapterBase"]):
18
+ """Tracks applied migrations in the database."""
19
+
20
+ def ensure_tracking_table(self, driver: "SyncDriverAdapterBase") -> None:
21
+ """Create the migration tracking table if it doesn't exist.
22
+
23
+ Args:
24
+ driver: The database driver to use.
25
+ """
26
+ driver.execute(self._get_create_table_sql())
27
+
28
+ def get_current_version(self, driver: "SyncDriverAdapterBase") -> Optional[str]:
29
+ """Get the latest applied migration version.
30
+
31
+ Args:
32
+ driver: The database driver to use.
33
+
34
+ Returns:
35
+ The current version number or None if no migrations applied.
36
+ """
37
+ result = driver.execute(self._get_current_version_sql())
38
+ return result.data[0]["version_num"] if result.data else None
39
+
40
+ def get_applied_migrations(self, driver: "SyncDriverAdapterBase") -> "list[dict[str, Any]]":
41
+ """Get all applied migrations in order.
42
+
43
+ Args:
44
+ driver: The database driver to use.
45
+
46
+ Returns:
47
+ List of migration records.
48
+ """
49
+ result = driver.execute(self._get_applied_migrations_sql())
50
+ return result.data or []
51
+
52
+ def record_migration(
53
+ self, driver: "SyncDriverAdapterBase", version: str, description: str, execution_time_ms: int, checksum: str
54
+ ) -> None:
55
+ """Record a successfully applied migration.
56
+
57
+ Args:
58
+ driver: The database driver to use.
59
+ version: Version number of the migration.
60
+ description: Description of the migration.
61
+ execution_time_ms: Execution time in milliseconds.
62
+ checksum: MD5 checksum of the migration content.
63
+ """
64
+ driver.execute(
65
+ self._get_record_migration_sql(
66
+ version, description, execution_time_ms, checksum, os.environ.get("USER", "unknown")
67
+ )
68
+ )
69
+
70
+ def remove_migration(self, driver: "SyncDriverAdapterBase", version: str) -> None:
71
+ """Remove a migration record (used during downgrade).
72
+
73
+ Args:
74
+ driver: The database driver to use.
75
+ version: Version number to remove.
76
+ """
77
+ driver.execute(self._get_remove_migration_sql(version))
78
+
79
+
80
+ class AsyncMigrationTracker(BaseMigrationTracker["AsyncDriverAdapterBase"]):
81
+ """Tracks applied migrations in the database."""
82
+
83
+ async def ensure_tracking_table(self, driver: "AsyncDriverAdapterBase") -> None:
84
+ """Create the migration tracking table if it doesn't exist.
85
+
86
+ Args:
87
+ driver: The database driver to use.
88
+ """
89
+ await driver.execute(self._get_create_table_sql())
90
+
91
+ async def get_current_version(self, driver: "AsyncDriverAdapterBase") -> Optional[str]:
92
+ """Get the latest applied migration version.
93
+
94
+ Args:
95
+ driver: The database driver to use.
96
+
97
+ Returns:
98
+ The current version number or None if no migrations applied.
99
+ """
100
+ result = await driver.execute(self._get_current_version_sql())
101
+ return result.data[0]["version_num"] if result.data else None
102
+
103
+ async def get_applied_migrations(self, driver: "AsyncDriverAdapterBase") -> "list[dict[str, Any]]":
104
+ """Get all applied migrations in order.
105
+
106
+ Args:
107
+ driver: The database driver to use.
108
+
109
+ Returns:
110
+ List of migration records.
111
+ """
112
+ result = await driver.execute(self._get_applied_migrations_sql())
113
+ return result.data or []
114
+
115
+ async def record_migration(
116
+ self, driver: "AsyncDriverAdapterBase", version: str, description: str, execution_time_ms: int, checksum: str
117
+ ) -> None:
118
+ """Record a successfully applied migration.
119
+
120
+ Args:
121
+ driver: The database driver to use.
122
+ version: Version number of the migration.
123
+ description: Description of the migration.
124
+ execution_time_ms: Execution time in milliseconds.
125
+ checksum: MD5 checksum of the migration content.
126
+ """
127
+ await driver.execute(
128
+ self._get_record_migration_sql(
129
+ version, description, execution_time_ms, checksum, os.environ.get("USER", "unknown")
130
+ )
131
+ )
132
+
133
+ async def remove_migration(self, driver: "AsyncDriverAdapterBase", version: str) -> None:
134
+ """Remove a migration record (used during downgrade).
135
+
136
+ Args:
137
+ driver: The database driver to use.
138
+ version: Version number to remove.
139
+ """
140
+ await driver.execute(self._get_remove_migration_sql(version))
@@ -0,0 +1,129 @@
1
+ """Utility functions for SQLSpec migrations.
2
+
3
+ This module provides helper functions for migration operations.
4
+ """
5
+
6
+ import os
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+ from typing import TYPE_CHECKING, Any, Optional
10
+
11
+ if TYPE_CHECKING:
12
+ from sqlspec.driver import AsyncDriverAdapterBase
13
+
14
+ __all__ = ("create_migration_file", "drop_all", "get_author")
15
+
16
+
17
+ def create_migration_file(migrations_dir: Path, version: str, message: str, file_type: str = "sql") -> Path:
18
+ """Create a new migration file from template.
19
+
20
+ Args:
21
+ migrations_dir: Directory to create the migration in.
22
+ version: Version number for the migration.
23
+ message: Description message for the migration.
24
+ file_type: Type of migration file to create ('sql' or 'py').
25
+
26
+ Returns:
27
+ Path to the created migration file.
28
+ """
29
+ safe_message = message.lower()
30
+ safe_message = "".join(c if c.isalnum() or c in " -" else "" for c in safe_message)
31
+ safe_message = safe_message.replace(" ", "_").replace("-", "_")
32
+ safe_message = "_".join(filter(None, safe_message.split("_")))[:50]
33
+
34
+ if file_type == "py":
35
+ filename = f"{version}_{safe_message}.py"
36
+ file_path = migrations_dir / filename
37
+ template = f'''"""SQLSpec Migration - {message}
38
+
39
+ Version: {version}
40
+ Created: {datetime.now(timezone.utc).isoformat()}
41
+ Author: {get_author()}
42
+
43
+ Migration functions can use either naming convention:
44
+ - Preferred: up()/down()
45
+ - Legacy: migrate_up()/migrate_down()
46
+
47
+ Both can be synchronous or asynchronous:
48
+ - def up(): ...
49
+ - async def up(): ...
50
+ """
51
+
52
+ from typing import List, Union
53
+
54
+
55
+ def up() -> Union[str, List[str]]:
56
+ """Apply the migration (upgrade).
57
+
58
+ Returns:
59
+ SQL statement(s) to execute for upgrade.
60
+ Can return a single string or list of strings.
61
+
62
+ Note: You can use either 'up()' or 'migrate_up()' for function names.
63
+ Both support async versions: 'async def up()' or 'async def migrate_up()'
64
+ """
65
+ return """
66
+ CREATE TABLE example (
67
+ id INTEGER PRIMARY KEY,
68
+ name TEXT NOT NULL
69
+ );
70
+ """
71
+
72
+
73
+ def down() -> Union[str, List[str]]:
74
+ """Reverse the migration (downgrade).
75
+
76
+ Returns:
77
+ SQL statement(s) to execute for downgrade.
78
+ Can return a single string or list of strings.
79
+ Return empty string or empty list if downgrade is not supported.
80
+
81
+ Note: You can use either 'down()' or 'migrate_down()' for function names.
82
+ Both support async versions: 'async def down()' or 'async def migrate_down()'
83
+ """
84
+ return "DROP TABLE example;"
85
+ '''
86
+ else:
87
+ filename = f"{version}_{safe_message}.sql"
88
+ file_path = migrations_dir / filename
89
+ template = f"""-- SQLSpec Migration
90
+ -- Version: {version}
91
+ -- Description: {message}
92
+ -- Created: {datetime.now(timezone.utc).isoformat()}
93
+ -- Author: {get_author()}
94
+
95
+ -- name: migrate-{version}-up
96
+ CREATE TABLE placeholder (
97
+ id INTEGER PRIMARY KEY
98
+ );
99
+
100
+ -- name: migrate-{version}-down
101
+ DROP TABLE placeholder;
102
+ """
103
+
104
+ file_path.write_text(template)
105
+ return file_path
106
+
107
+
108
+ def get_author() -> str:
109
+ """Get current user for migration metadata.
110
+
111
+ Returns:
112
+ Username from environment or 'unknown'.
113
+ """
114
+ return os.environ.get("USER", "unknown")
115
+
116
+
117
+ async def drop_all(engine: "AsyncDriverAdapterBase", version_table_name: str, metadata: Optional[Any] = None) -> None:
118
+ """Drop all tables from the database.
119
+
120
+ Args:
121
+ engine: The database engine/driver.
122
+ version_table_name: Name of the version tracking table.
123
+ metadata: Optional metadata object.
124
+
125
+ Raises:
126
+ NotImplementedError: Always raised.
127
+ """
128
+ msg = "drop_all functionality requires database-specific implementation"
129
+ raise NotImplementedError(msg)
sqlspec/protocols.py ADDED
@@ -0,0 +1,407 @@
1
+ """Runtime-checkable protocols for SQLSpec to replace duck typing.
2
+
3
+ This module provides protocols that can be used for static type checking
4
+ and runtime isinstance() checks, replacing defensive hasattr() patterns.
5
+ """
6
+
7
+ from typing import TYPE_CHECKING, Any, ClassVar, Optional, Protocol, Union, runtime_checkable
8
+
9
+ from typing_extensions import Self
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import AsyncIterator, Iterator
13
+ from pathlib import Path
14
+
15
+ from sqlglot import exp
16
+
17
+ from sqlspec.storage.capabilities import StorageCapabilities
18
+ from sqlspec.typing import ArrowRecordBatch, ArrowTable
19
+
20
+ __all__ = (
21
+ "BytesConvertibleProtocol",
22
+ "DictProtocol",
23
+ "FilterAppenderProtocol",
24
+ "FilterParameterProtocol",
25
+ "HasExpressionProtocol",
26
+ "HasExpressionsProtocol",
27
+ "HasLimitProtocol",
28
+ "HasOffsetProtocol",
29
+ "HasOrderByProtocol",
30
+ "HasParameterBuilderProtocol",
31
+ "HasSQLGlotExpressionProtocol",
32
+ "HasSQLMethodProtocol",
33
+ "HasToStatementProtocol",
34
+ "HasWhereProtocol",
35
+ "IndexableRow",
36
+ "IterableParameters",
37
+ "ObjectStoreItemProtocol",
38
+ "ObjectStoreProtocol",
39
+ "ParameterValueProtocol",
40
+ "SQLBuilderProtocol",
41
+ "SelectBuilderProtocol",
42
+ "WithMethodProtocol",
43
+ )
44
+
45
+
46
+ @runtime_checkable
47
+ class IndexableRow(Protocol):
48
+ """Protocol for row types that support index access."""
49
+
50
+ def __getitem__(self, index: int) -> Any:
51
+ """Get item by index."""
52
+ ...
53
+
54
+ def __len__(self) -> int:
55
+ """Get length of the row."""
56
+ ...
57
+
58
+
59
+ @runtime_checkable
60
+ class IterableParameters(Protocol):
61
+ """Protocol for parameter sequences."""
62
+
63
+ def __iter__(self) -> Any:
64
+ """Iterate over parameters."""
65
+ ...
66
+
67
+ def __len__(self) -> int:
68
+ """Get number of parameters."""
69
+ ...
70
+
71
+
72
+ @runtime_checkable
73
+ class WithMethodProtocol(Protocol):
74
+ """Protocol for objects with a with_ method (SQLGlot expressions)."""
75
+
76
+ def with_(self, *args: Any, **kwargs: Any) -> Any:
77
+ """Add WITH clause to expression."""
78
+ ...
79
+
80
+
81
+ @runtime_checkable
82
+ class HasWhereProtocol(Protocol):
83
+ """Protocol for SQL expressions that support WHERE clauses."""
84
+
85
+ def where(self, *args: Any, **kwargs: Any) -> Any:
86
+ """Add WHERE clause to expression."""
87
+ ...
88
+
89
+
90
+ @runtime_checkable
91
+ class HasLimitProtocol(Protocol):
92
+ """Protocol for SQL expressions that support LIMIT clauses."""
93
+
94
+ def limit(self, *args: Any, **kwargs: Any) -> Any:
95
+ """Add LIMIT clause to expression."""
96
+ ...
97
+
98
+
99
+ @runtime_checkable
100
+ class HasOffsetProtocol(Protocol):
101
+ """Protocol for SQL expressions that support OFFSET clauses."""
102
+
103
+ def offset(self, *args: Any, **kwargs: Any) -> Any:
104
+ """Add OFFSET clause to expression."""
105
+ ...
106
+
107
+
108
+ @runtime_checkable
109
+ class HasOrderByProtocol(Protocol):
110
+ """Protocol for SQL expressions that support ORDER BY clauses."""
111
+
112
+ def order_by(self, *args: Any, **kwargs: Any) -> Any:
113
+ """Add ORDER BY clause to expression."""
114
+ ...
115
+
116
+
117
+ @runtime_checkable
118
+ class HasExpressionsProtocol(Protocol):
119
+ """Protocol for SQL expressions that have an expressions attribute."""
120
+
121
+ expressions: Any
122
+
123
+
124
+ @runtime_checkable
125
+ class HasSQLMethodProtocol(Protocol):
126
+ """Protocol for objects that have a sql() method for rendering SQL."""
127
+
128
+ def sql(self, *args: Any, **kwargs: Any) -> str:
129
+ """Render object to SQL string."""
130
+ ...
131
+
132
+
133
+ @runtime_checkable
134
+ class FilterParameterProtocol(Protocol):
135
+ """Protocol for filter objects that can extract parameters."""
136
+
137
+ def extract_parameters(self) -> tuple[list[Any], dict[str, Any]]:
138
+ """Extract parameters from the filter."""
139
+ ...
140
+
141
+
142
+ @runtime_checkable
143
+ class FilterAppenderProtocol(Protocol):
144
+ """Protocol for filter objects that can append to SQL statements."""
145
+
146
+ def append_to_statement(self, sql: Any) -> Any:
147
+ """Append this filter to a SQL statement."""
148
+ ...
149
+
150
+
151
+ @runtime_checkable
152
+ class ParameterValueProtocol(Protocol):
153
+ """Protocol for parameter objects with value and type_hint attributes."""
154
+
155
+ value: Any
156
+ type_hint: str
157
+
158
+
159
+ @runtime_checkable
160
+ class DictProtocol(Protocol):
161
+ """Protocol for objects with a __dict__ attribute."""
162
+
163
+ __dict__: dict[str, Any]
164
+
165
+
166
+ @runtime_checkable
167
+ class BytesConvertibleProtocol(Protocol):
168
+ """Protocol for objects that can be converted to bytes."""
169
+
170
+ def __bytes__(self) -> bytes:
171
+ """Convert object to bytes."""
172
+ ...
173
+
174
+
175
+ @runtime_checkable
176
+ class ObjectStoreItemProtocol(Protocol):
177
+ """Protocol for object store items with path/key attributes."""
178
+
179
+ path: str
180
+ key: "Optional[str]"
181
+
182
+
183
+ @runtime_checkable
184
+ class ObjectStoreProtocol(Protocol):
185
+ """Protocol for object storage operations.
186
+
187
+ Defines the interface for storage backends with both sync and async operations.
188
+ """
189
+
190
+ capabilities: ClassVar["StorageCapabilities"]
191
+
192
+ protocol: str
193
+
194
+ def __init__(self, uri: str, **kwargs: Any) -> None:
195
+ return
196
+
197
+ def read_bytes(self, path: "Union[str, Path]", **kwargs: Any) -> bytes:
198
+ """Read bytes from an object."""
199
+ return b""
200
+
201
+ def write_bytes(self, path: "Union[str, Path]", data: bytes, **kwargs: Any) -> None:
202
+ """Write bytes to an object."""
203
+ return
204
+
205
+ def read_text(self, path: "Union[str, Path]", encoding: str = "utf-8", **kwargs: Any) -> str:
206
+ """Read text from an object."""
207
+ return ""
208
+
209
+ def write_text(self, path: "Union[str, Path]", data: str, encoding: str = "utf-8", **kwargs: Any) -> None:
210
+ """Write text to an object."""
211
+ return
212
+
213
+ def exists(self, path: "Union[str, Path]", **kwargs: Any) -> bool:
214
+ """Check if an object exists."""
215
+ return False
216
+
217
+ def delete(self, path: "Union[str, Path]", **kwargs: Any) -> None:
218
+ """Delete an object."""
219
+ return
220
+
221
+ def copy(self, source: "Union[str, Path]", destination: "Union[str, Path]", **kwargs: Any) -> None:
222
+ """Copy an object."""
223
+ return
224
+
225
+ def move(self, source: "Union[str, Path]", destination: "Union[str, Path]", **kwargs: Any) -> None:
226
+ """Move an object."""
227
+ return
228
+
229
+ def list_objects(self, prefix: str = "", recursive: bool = True, **kwargs: Any) -> list[str]:
230
+ """List objects with optional prefix."""
231
+ return []
232
+
233
+ def glob(self, pattern: str, **kwargs: Any) -> list[str]:
234
+ """Find objects matching a glob pattern."""
235
+ return []
236
+
237
+ def is_object(self, path: "Union[str, Path]") -> bool:
238
+ """Check if path points to an object."""
239
+ return False
240
+
241
+ def is_path(self, path: "Union[str, Path]") -> bool:
242
+ """Check if path points to a prefix (directory-like)."""
243
+ return False
244
+
245
+ def get_metadata(self, path: "Union[str, Path]", **kwargs: Any) -> dict[str, Any]:
246
+ """Get object metadata."""
247
+ return {}
248
+
249
+ def read_arrow(self, path: "Union[str, Path]", **kwargs: Any) -> "ArrowTable":
250
+ """Read an Arrow table from storage."""
251
+ msg = "Arrow reading not implemented"
252
+ raise NotImplementedError(msg)
253
+
254
+ def write_arrow(self, path: "Union[str, Path]", table: "ArrowTable", **kwargs: Any) -> None:
255
+ """Write an Arrow table to storage."""
256
+ msg = "Arrow writing not implemented"
257
+ raise NotImplementedError(msg)
258
+
259
+ def stream_arrow(self, pattern: str, **kwargs: Any) -> "Iterator[ArrowRecordBatch]":
260
+ """Stream Arrow record batches from matching objects."""
261
+ msg = "Arrow streaming not implemented"
262
+ raise NotImplementedError(msg)
263
+
264
+ async def read_bytes_async(self, path: "Union[str, Path]", **kwargs: Any) -> bytes:
265
+ """Async read bytes from an object."""
266
+ msg = "Async operations not implemented"
267
+ raise NotImplementedError(msg)
268
+
269
+ async def write_bytes_async(self, path: "Union[str, Path]", data: bytes, **kwargs: Any) -> None:
270
+ """Async write bytes to an object."""
271
+ msg = "Async operations not implemented"
272
+ raise NotImplementedError(msg)
273
+
274
+ async def read_text_async(self, path: "Union[str, Path]", encoding: str = "utf-8", **kwargs: Any) -> str:
275
+ """Async read text from an object."""
276
+ msg = "Async operations not implemented"
277
+ raise NotImplementedError(msg)
278
+
279
+ async def write_text_async(
280
+ self, path: "Union[str, Path]", data: str, encoding: str = "utf-8", **kwargs: Any
281
+ ) -> None:
282
+ """Async write text to an object."""
283
+ msg = "Async operations not implemented"
284
+ raise NotImplementedError(msg)
285
+
286
+ async def exists_async(self, path: "Union[str, Path]", **kwargs: Any) -> bool:
287
+ """Async check if an object exists."""
288
+ msg = "Async operations not implemented"
289
+ raise NotImplementedError(msg)
290
+
291
+ async def delete_async(self, path: "Union[str, Path]", **kwargs: Any) -> None:
292
+ """Async delete an object."""
293
+ msg = "Async operations not implemented"
294
+ raise NotImplementedError(msg)
295
+
296
+ async def list_objects_async(self, prefix: str = "", recursive: bool = True, **kwargs: Any) -> list[str]:
297
+ """Async list objects with optional prefix."""
298
+ msg = "Async operations not implemented"
299
+ raise NotImplementedError(msg)
300
+
301
+ async def copy_async(self, source: "Union[str, Path]", destination: "Union[str, Path]", **kwargs: Any) -> None:
302
+ """Async copy an object."""
303
+ msg = "Async operations not implemented"
304
+ raise NotImplementedError(msg)
305
+
306
+ async def move_async(self, source: "Union[str, Path]", destination: "Union[str, Path]", **kwargs: Any) -> None:
307
+ """Async move an object."""
308
+ msg = "Async operations not implemented"
309
+ raise NotImplementedError(msg)
310
+
311
+ async def get_metadata_async(self, path: "Union[str, Path]", **kwargs: Any) -> dict[str, Any]:
312
+ """Async get object metadata."""
313
+ msg = "Async operations not implemented"
314
+ raise NotImplementedError(msg)
315
+
316
+ async def read_arrow_async(self, path: "Union[str, Path]", **kwargs: Any) -> "ArrowTable":
317
+ """Async read an Arrow table from storage."""
318
+ msg = "Async arrow reading not implemented"
319
+ raise NotImplementedError(msg)
320
+
321
+ async def write_arrow_async(self, path: "Union[str, Path]", table: "ArrowTable", **kwargs: Any) -> None:
322
+ """Async write an Arrow table to storage."""
323
+ msg = "Async arrow writing not implemented"
324
+ raise NotImplementedError(msg)
325
+
326
+ async def stream_arrow_async(self, pattern: str, **kwargs: Any) -> "AsyncIterator[ArrowRecordBatch]":
327
+ """Async stream Arrow record batches from matching objects."""
328
+ msg = "Async arrow streaming not implemented"
329
+ raise NotImplementedError(msg)
330
+
331
+
332
+ @runtime_checkable
333
+ class HasSQLGlotExpressionProtocol(Protocol):
334
+ """Protocol for objects with a sqlglot_expression property."""
335
+
336
+ @property
337
+ def sqlglot_expression(self) -> "Optional[exp.Expression]":
338
+ """Return the SQLGlot expression for this object."""
339
+ ...
340
+
341
+
342
+ @runtime_checkable
343
+ class HasParameterBuilderProtocol(Protocol):
344
+ """Protocol for objects that can add parameters."""
345
+
346
+ def add_parameter(self, value: Any, name: "Optional[str]" = None) -> tuple[Any, str]:
347
+ """Add a parameter to the builder."""
348
+ ...
349
+
350
+
351
+ @runtime_checkable
352
+ class HasExpressionProtocol(Protocol):
353
+ """Protocol for objects with an _expression attribute."""
354
+
355
+ _expression: "Optional[exp.Expression]"
356
+
357
+
358
+ @runtime_checkable
359
+ class HasToStatementProtocol(Protocol):
360
+ """Protocol for objects with a to_statement method."""
361
+
362
+ def to_statement(self) -> Any:
363
+ """Convert to SQL statement."""
364
+ ...
365
+
366
+
367
+ @runtime_checkable
368
+ class SQLBuilderProtocol(Protocol):
369
+ """Protocol for SQL query builders."""
370
+
371
+ _expression: "Optional[exp.Expression]"
372
+ _parameters: dict[str, Any]
373
+ _parameter_counter: int
374
+ _columns: Any # Optional attribute for some builders
375
+ _table: Any # Optional attribute for some builders
376
+ _with_ctes: Any # Optional attribute for some builders
377
+ dialect: Any
378
+ dialect_name: "Optional[str]"
379
+
380
+ @property
381
+ def parameters(self) -> dict[str, Any]:
382
+ """Public access to query parameters."""
383
+ ...
384
+
385
+ def add_parameter(self, value: Any, name: "Optional[str]" = None) -> tuple[Any, str]:
386
+ """Add a parameter to the builder."""
387
+ ...
388
+
389
+ def _generate_unique_parameter_name(self, base_name: str) -> str:
390
+ """Generate a unique parameter name."""
391
+ ...
392
+
393
+ def _parameterize_expression(self, expression: "exp.Expression") -> "exp.Expression":
394
+ """Replace literal values in an expression with bound parameters."""
395
+ ...
396
+
397
+ def build(self) -> "Union[exp.Expression, Any]":
398
+ """Build and return the final expression."""
399
+ ...
400
+
401
+
402
+ class SelectBuilderProtocol(SQLBuilderProtocol, Protocol):
403
+ """Protocol for SELECT query builders."""
404
+
405
+ def select(self, *columns: "Union[str, exp.Expression]") -> Self:
406
+ """Add SELECT columns to the query."""
407
+ ...
sqlspec/py.typed ADDED
File without changes
@@ -0,0 +1,23 @@
1
+ """Storage abstraction layer for SQLSpec.
2
+
3
+ Provides a flexible storage system with:
4
+ - Multiple backend support (local, fsspec, obstore)
5
+ - Lazy loading and configuration-based registration
6
+ - URI scheme-based automatic backend resolution
7
+ - Key-based named storage configurations
8
+ - Capability-based backend selection
9
+ """
10
+
11
+ from sqlspec.protocols import ObjectStoreProtocol
12
+ from sqlspec.storage.capabilities import HasStorageCapabilities, StorageCapabilities
13
+ from sqlspec.storage.registry import StorageRegistry
14
+
15
+ storage_registry = StorageRegistry()
16
+
17
+ __all__ = (
18
+ "HasStorageCapabilities",
19
+ "ObjectStoreProtocol",
20
+ "StorageCapabilities",
21
+ "StorageRegistry",
22
+ "storage_registry",
23
+ )