sqlspec 0.7.0__tar.gz → 0.8.0__tar.gz

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 (160) hide show
  1. {sqlspec-0.7.0 → sqlspec-0.8.0}/.pre-commit-config.yaml +1 -1
  2. {sqlspec-0.7.0 → sqlspec-0.8.0}/PKG-INFO +1 -1
  3. {sqlspec-0.7.0 → sqlspec-0.8.0}/pyproject.toml +29 -10
  4. sqlspec-0.8.0/sqlspec/__init__.py +15 -0
  5. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/_serialization.py +16 -2
  6. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/_typing.py +1 -1
  7. sqlspec-0.8.0/sqlspec/adapters/adbc/__init__.py +7 -0
  8. sqlspec-0.8.0/sqlspec/adapters/adbc/config.py +190 -0
  9. sqlspec-0.8.0/sqlspec/adapters/adbc/driver.py +333 -0
  10. sqlspec-0.8.0/sqlspec/adapters/aiosqlite/__init__.py +7 -0
  11. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/adapters/aiosqlite/config.py +25 -7
  12. sqlspec-0.8.0/sqlspec/adapters/aiosqlite/driver.py +275 -0
  13. sqlspec-0.8.0/sqlspec/adapters/asyncmy/__init__.py +8 -0
  14. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/adapters/asyncmy/config.py +75 -14
  15. sqlspec-0.8.0/sqlspec/adapters/asyncmy/driver.py +255 -0
  16. sqlspec-0.8.0/sqlspec/adapters/asyncpg/__init__.py +9 -0
  17. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/adapters/asyncpg/config.py +99 -20
  18. sqlspec-0.8.0/sqlspec/adapters/asyncpg/driver.py +288 -0
  19. sqlspec-0.8.0/sqlspec/adapters/duckdb/__init__.py +7 -0
  20. sqlspec-0.8.0/sqlspec/adapters/duckdb/config.py +380 -0
  21. sqlspec-0.8.0/sqlspec/adapters/duckdb/driver.py +225 -0
  22. sqlspec-0.8.0/sqlspec/adapters/oracledb/__init__.py +16 -0
  23. sqlspec-0.8.0/sqlspec/adapters/oracledb/config/__init__.py +9 -0
  24. sqlspec-0.8.0/sqlspec/adapters/oracledb/config/_asyncio.py +188 -0
  25. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/adapters/oracledb/config/_common.py +1 -1
  26. sqlspec-0.8.0/sqlspec/adapters/oracledb/config/_sync.py +188 -0
  27. sqlspec-0.8.0/sqlspec/adapters/oracledb/driver.py +498 -0
  28. sqlspec-0.8.0/sqlspec/adapters/psycopg/__init__.py +11 -0
  29. sqlspec-0.8.0/sqlspec/adapters/psycopg/config/__init__.py +9 -0
  30. sqlspec-0.8.0/sqlspec/adapters/psycopg/config/_async.py +170 -0
  31. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/adapters/psycopg/config/_common.py +2 -2
  32. sqlspec-0.8.0/sqlspec/adapters/psycopg/config/_sync.py +169 -0
  33. sqlspec-0.8.0/sqlspec/adapters/psycopg/driver.py +616 -0
  34. sqlspec-0.8.0/sqlspec/adapters/sqlite/__init__.py +7 -0
  35. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/adapters/sqlite/config.py +25 -7
  36. sqlspec-0.8.0/sqlspec/adapters/sqlite/driver.py +303 -0
  37. sqlspec-0.8.0/sqlspec/base.py +607 -0
  38. sqlspec-0.8.0/sqlspec/extensions/litestar/__init__.py +19 -0
  39. sqlspec-0.8.0/sqlspec/extensions/litestar/_utils.py +56 -0
  40. sqlspec-0.8.0/sqlspec/extensions/litestar/config.py +81 -0
  41. sqlspec-0.8.0/sqlspec/extensions/litestar/handlers.py +188 -0
  42. sqlspec-0.8.0/sqlspec/extensions/litestar/plugin.py +135 -0
  43. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/typing.py +72 -17
  44. sqlspec-0.8.0/sqlspec/utils/__init__.py +3 -0
  45. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/utils/deprecation.py +1 -1
  46. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/utils/fixtures.py +4 -5
  47. sqlspec-0.8.0/sqlspec/utils/sync_tools.py +335 -0
  48. {sqlspec-0.7.0 → sqlspec-0.8.0}/tests/conftest.py +8 -0
  49. sqlspec-0.8.0/tests/fixtures/__init__.py +1 -0
  50. sqlspec-0.8.0/tests/fixtures/example_usage.py +82 -0
  51. sqlspec-0.8.0/tests/fixtures/sql_utils.py +90 -0
  52. sqlspec-0.8.0/tests/integration/test_adapters/__init__.py +1 -0
  53. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/__init__.py +1 -0
  54. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/conftest.py +35 -0
  55. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/test_connection.py +29 -0
  56. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/test_driver_bigquery.py +190 -0
  57. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/test_driver_duckdb.py +228 -0
  58. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/test_driver_postgres.py +167 -0
  59. sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py +202 -0
  60. sqlspec-0.8.0/tests/integration/test_adapters/test_aiosqlite/__init__.py +1 -0
  61. sqlspec-0.8.0/tests/integration/test_adapters/test_aiosqlite/conftest.py +16 -0
  62. sqlspec-0.8.0/tests/integration/test_adapters/test_aiosqlite/test_connection.py +27 -0
  63. sqlspec-0.8.0/tests/integration/test_adapters/test_aiosqlite/test_driver.py +181 -0
  64. sqlspec-0.8.0/tests/integration/test_adapters/test_asyncmy/test_connection.py +53 -0
  65. sqlspec-0.8.0/tests/integration/test_adapters/test_asyncmy/test_driver.py +213 -0
  66. sqlspec-0.8.0/tests/integration/test_adapters/test_duckdb/__init__.py +1 -0
  67. sqlspec-0.8.0/tests/integration/test_adapters/test_duckdb/test_connection.py +25 -0
  68. sqlspec-0.8.0/tests/integration/test_adapters/test_duckdb/test_driver.py +135 -0
  69. sqlspec-0.8.0/tests/integration/test_adapters/test_oracledb/__init__.py +1 -0
  70. sqlspec-0.8.0/tests/integration/test_adapters/test_oracledb/test_connection.py +106 -0
  71. sqlspec-0.8.0/tests/integration/test_adapters/test_oracledb/test_driver_async.py +166 -0
  72. sqlspec-0.8.0/tests/integration/test_adapters/test_oracledb/test_driver_sync.py +151 -0
  73. sqlspec-0.8.0/tests/integration/test_adapters/test_psycopg/__init__.py +1 -0
  74. sqlspec-0.8.0/tests/integration/test_adapters/test_psycopg/test_connection.py +82 -0
  75. sqlspec-0.8.0/tests/integration/test_adapters/test_psycopg/test_driver.py +401 -0
  76. sqlspec-0.8.0/tests/integration/test_adapters/test_sqlite/__init__.py +1 -0
  77. sqlspec-0.8.0/tests/integration/test_adapters/test_sqlite/test_connection.py +24 -0
  78. sqlspec-0.8.0/tests/integration/test_adapters/test_sqlite/test_driver.py +174 -0
  79. sqlspec-0.8.0/tests/unit/test_adapters/test_adbc/__init__.py +1 -0
  80. sqlspec-0.8.0/tests/unit/test_adapters/test_adbc/test_config.py +93 -0
  81. sqlspec-0.8.0/tests/unit/test_adapters/test_aiosqlite/test_config.py +110 -0
  82. sqlspec-0.8.0/tests/unit/test_adapters/test_asyncmy/__init__.py +1 -0
  83. sqlspec-0.8.0/tests/unit/test_adapters/test_asyncmy/test_config.py +152 -0
  84. sqlspec-0.8.0/tests/unit/test_adapters/test_asyncpg/test_config.py +153 -0
  85. sqlspec-0.8.0/tests/unit/test_adapters/test_duckdb/test_config.py +137 -0
  86. sqlspec-0.8.0/tests/unit/test_adapters/test_oracledb/__init__.py +1 -0
  87. sqlspec-0.8.0/tests/unit/test_adapters/test_oracledb/test_async_config.py +135 -0
  88. sqlspec-0.8.0/tests/unit/test_adapters/test_oracledb/test_sync_config.py +129 -0
  89. sqlspec-0.8.0/tests/unit/test_adapters/test_psycopg/__init__.py +1 -0
  90. sqlspec-0.8.0/tests/unit/test_adapters/test_psycopg/test_async_config.py +179 -0
  91. sqlspec-0.8.0/tests/unit/test_adapters/test_psycopg/test_sync_config.py +160 -0
  92. sqlspec-0.8.0/tests/unit/test_adapters/test_sqlite/test_config.py +89 -0
  93. sqlspec-0.8.0/tests/unit/test_base.py +276 -0
  94. sqlspec-0.8.0/tests/unit/test_typing.py +280 -0
  95. {sqlspec-0.7.0 → sqlspec-0.8.0}/tests/unit/test_utils/test_module_loader.py +2 -3
  96. sqlspec-0.8.0/tests/unit/test_utils/test_sync_tools.py +109 -0
  97. sqlspec-0.8.0/tools/sphinx_ext/__init__.py +16 -0
  98. {sqlspec-0.7.0 → sqlspec-0.8.0}/tools/sphinx_ext/missing_references.py +2 -2
  99. {sqlspec-0.7.0 → sqlspec-0.8.0}/uv.lock +1001 -831
  100. sqlspec-0.7.0/base.py +0 -9
  101. sqlspec-0.7.0/sqlspec/adapters/adbc/config.py +0 -47
  102. sqlspec-0.7.0/sqlspec/adapters/aiosqlite/__init__.py +0 -3
  103. sqlspec-0.7.0/sqlspec/adapters/asyncmy/__init__.py +0 -3
  104. sqlspec-0.7.0/sqlspec/adapters/duckdb/__init__.py +0 -3
  105. sqlspec-0.7.0/sqlspec/adapters/duckdb/config.py +0 -198
  106. sqlspec-0.7.0/sqlspec/adapters/oracledb/__init__.py +0 -13
  107. sqlspec-0.7.0/sqlspec/adapters/oracledb/config/__init__.py +0 -9
  108. sqlspec-0.7.0/sqlspec/adapters/oracledb/config/_asyncio.py +0 -103
  109. sqlspec-0.7.0/sqlspec/adapters/oracledb/config/_sync.py +0 -103
  110. sqlspec-0.7.0/sqlspec/adapters/psycopg/config/__init__.py +0 -9
  111. sqlspec-0.7.0/sqlspec/adapters/psycopg/config/_async.py +0 -78
  112. sqlspec-0.7.0/sqlspec/adapters/psycopg/config/_sync.py +0 -77
  113. sqlspec-0.7.0/sqlspec/base.py +0 -227
  114. sqlspec-0.7.0/sqlspec/extensions/litestar/config.py +0 -0
  115. sqlspec-0.7.0/sqlspec/extensions/litestar/plugin.py +0 -43
  116. sqlspec-0.7.0/tests/unit/__init__.py +0 -0
  117. sqlspec-0.7.0/tests/unit/test_adapters/__init__.py +0 -0
  118. sqlspec-0.7.0/tests/unit/test_adapters/test_aiosqlite/test_config.py +0 -108
  119. sqlspec-0.7.0/tests/unit/test_adapters/test_asyncpg/test_config.py +0 -159
  120. sqlspec-0.7.0/tests/unit/test_adapters/test_duckdb/__init__.py +0 -0
  121. sqlspec-0.7.0/tests/unit/test_adapters/test_duckdb/test_config.py +0 -255
  122. sqlspec-0.7.0/tests/unit/test_adapters/test_oracledb/test_config.py +0 -336
  123. sqlspec-0.7.0/tests/unit/test_adapters/test_psycopg/test_async_config.py +0 -167
  124. sqlspec-0.7.0/tests/unit/test_adapters/test_psycopg/test_sync_config.py +0 -152
  125. sqlspec-0.7.0/tests/unit/test_adapters/test_sqlite/test_config.py +0 -87
  126. sqlspec-0.7.0/tests/unit/test_base.py +0 -229
  127. sqlspec-0.7.0/tests/unit/test_typing.py +0 -276
  128. sqlspec-0.7.0/tests/unit/test_utils/__init__.py +0 -0
  129. sqlspec-0.7.0/tools/__init__.py +0 -0
  130. sqlspec-0.7.0/tools/sphinx_ext/__init__.py +0 -16
  131. {sqlspec-0.7.0 → sqlspec-0.8.0}/.gitignore +0 -0
  132. {sqlspec-0.7.0 → sqlspec-0.8.0}/CONTRIBUTING.rst +0 -0
  133. {sqlspec-0.7.0 → sqlspec-0.8.0}/LICENSE +0 -0
  134. {sqlspec-0.7.0 → sqlspec-0.8.0}/Makefile +0 -0
  135. {sqlspec-0.7.0 → sqlspec-0.8.0}/NOTICE +0 -0
  136. {sqlspec-0.7.0 → sqlspec-0.8.0}/README.md +0 -0
  137. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/__metadata__.py +0 -0
  138. {sqlspec-0.7.0/sqlspec → sqlspec-0.8.0/sqlspec/adapters}/__init__.py +0 -0
  139. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/exceptions.py +0 -0
  140. {sqlspec-0.7.0/sqlspec/adapters → sqlspec-0.8.0/sqlspec/extensions}/__init__.py +0 -0
  141. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/filters.py +0 -0
  142. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/py.typed +0 -0
  143. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/utils/module_loader.py +0 -0
  144. {sqlspec-0.7.0 → sqlspec-0.8.0}/sqlspec/utils/text.py +0 -0
  145. {sqlspec-0.7.0/sqlspec/adapters/adbc → sqlspec-0.8.0/tests}/__init__.py +0 -0
  146. {sqlspec-0.7.0/sqlspec/adapters/asyncpg → sqlspec-0.8.0/tests/integration}/__init__.py +0 -0
  147. {sqlspec-0.7.0/sqlspec/adapters/psycopg → sqlspec-0.8.0/tests/integration/test_adapters/test_asyncmy}/__init__.py +0 -0
  148. /sqlspec-0.7.0/sqlspec/adapters/sqlite/__init__.py → /sqlspec-0.8.0/tests/integration/test_adapters/test_psycopg/conftest.py +0 -0
  149. {sqlspec-0.7.0/sqlspec/extensions → sqlspec-0.8.0/tests/unit}/__init__.py +0 -0
  150. {sqlspec-0.7.0/sqlspec/extensions/litestar → sqlspec-0.8.0/tests/unit/test_adapters}/__init__.py +0 -0
  151. {sqlspec-0.7.0/tests/unit/test_adapters/test_oracledb → sqlspec-0.8.0/tests/unit/test_adapters/test_aiosqlite}/__init__.py +0 -0
  152. {sqlspec-0.7.0 → sqlspec-0.8.0}/tests/unit/test_adapters/test_asyncpg/__init__.py +0 -0
  153. {sqlspec-0.7.0/sqlspec/utils → sqlspec-0.8.0/tests/unit/test_adapters/test_duckdb}/__init__.py +0 -0
  154. {sqlspec-0.7.0 → sqlspec-0.8.0}/tests/unit/test_adapters/test_sqlite/__init__.py +0 -0
  155. {sqlspec-0.7.0/tests → sqlspec-0.8.0/tests/unit/test_utils}/__init__.py +0 -0
  156. {sqlspec-0.7.0 → sqlspec-0.8.0}/tests/unit/test_utils/test_text.py +0 -0
  157. {sqlspec-0.7.0/tests/integration → sqlspec-0.8.0/tools}/__init__.py +0 -0
  158. {sqlspec-0.7.0 → sqlspec-0.8.0}/tools/build_docs.py +0 -0
  159. {sqlspec-0.7.0 → sqlspec-0.8.0}/tools/pypi_readme.py +0 -0
  160. {sqlspec-0.7.0 → sqlspec-0.8.0}/tools/sphinx_ext/changelog.py +0 -0
@@ -17,7 +17,7 @@ repos:
17
17
  - id: mixed-line-ending
18
18
  - id: trailing-whitespace
19
19
  - repo: https://github.com/charliermarsh/ruff-pre-commit
20
- rev: "v0.9.10"
20
+ rev: "v0.11.6"
21
21
  hooks:
22
22
  - id: ruff
23
23
  args: ["--fix"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlspec
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: SQL Experiments in Python
5
5
  Author-email: Cody Fincher <cody@litestar.dev>
6
6
  Maintainer-email: Litestar Developers <hello@litestar.dev>
@@ -7,10 +7,10 @@ maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }]
7
7
  name = "sqlspec"
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.9, <4.0"
10
- version = "0.7.0"
10
+ version = "0.8.0"
11
11
 
12
12
  [project.optional-dependencies]
13
- adbc = ["adbc-driver-manager", "pyarrow"]
13
+ adbc = ["adbc_driver_manager", "pyarrow"]
14
14
  aioodbc = ["aioodbc"]
15
15
  aiosqlite = ["aiosqlite"]
16
16
  asyncmy = ["asyncmy"]
@@ -35,9 +35,7 @@ uuid = ["uuid-utils>=0.6.1"]
35
35
  [dependency-groups]
36
36
  build = ["bump-my-version"]
37
37
  dev = [
38
- "adbc-driver-sqlite",
39
- "adbc-driver-postgresql",
40
- "adbc-driver-flightsql",
38
+ { include-group = "extras" },
41
39
  { include-group = "lint" },
42
40
  { include-group = "doc" },
43
41
  { include-group = "test" },
@@ -59,6 +57,15 @@ doc = [
59
57
  "myst-parser",
60
58
  "sphinx-autodoc-typehints",
61
59
  ]
60
+ extras = [
61
+ "adbc_driver_manager",
62
+ "pyarrow",
63
+ "polars",
64
+ "adbc_driver_sqlite",
65
+ "adbc_driver_postgresql",
66
+ "adbc_driver_flightsql",
67
+ "adbc_driver_bigquery",
68
+ ]
62
69
  lint = [
63
70
  "mypy>=1.13.0",
64
71
  "pre-commit>=3.5.0",
@@ -75,7 +82,7 @@ test = [
75
82
  "pytest>=8.0.0",
76
83
  "pytest-asyncio>=0.23.8",
77
84
  "pytest-cov>=5.0.0",
78
- "pytest-databases>=0.10.0",
85
+ "pytest-databases[postgres,oracle,mysql,bigquery,spanner]>=0.12.2",
79
86
  "pytest-mock>=3.14.0",
80
87
  "pytest-sugar>=1.0.0",
81
88
  "pytest-xdist>=3.6.1",
@@ -101,7 +108,7 @@ packages = ["sqlspec"]
101
108
  allow_dirty = true
102
109
  commit = false
103
110
  commit_args = "--no-verify"
104
- current_version = "0.33.1"
111
+ current_version = "0.8.0"
105
112
  ignore_missing_files = false
106
113
  ignore_missing_version = false
107
114
  message = "chore(release): bump to v{new_version}"
@@ -123,11 +130,11 @@ search = 'version = "{current_version}"'
123
130
  [[tool.bumpversion.files]]
124
131
  filename = "uv.lock"
125
132
  replace = """
126
- name = "advanced-alchemy"
133
+ name = "sqlspec"
127
134
  version = "{new_version}"
128
135
  """
129
136
  search = """
130
- name = "advanced-alchemy"
137
+ name = "sqlspec"
131
138
  version = "{current_version}"
132
139
  """
133
140
 
@@ -217,10 +224,17 @@ module = [
217
224
 
218
225
  [tool.pyright]
219
226
  disableBytesTypePromotions = true
220
- exclude = ["tools", "docs"]
227
+ exclude = ["**/node_modules", "**/__pycache__", ".venv", "tools", "docs"]
221
228
  include = ["sqlspec", "tests"]
222
229
  pythonVersion = "3.9"
230
+ reportMissingTypeStubs = false
231
+ reportPrivateImportUsage = false
232
+ reportPrivateUsage = false
233
+ reportUnknownArgumentType = false
234
+ reportUnknownMemberType = false
235
+ reportUnknownVariableType = false
223
236
  reportUnnecessaryTypeIgnoreComments = true
237
+ root = "."
224
238
 
225
239
 
226
240
  [tool.slotscheck]
@@ -267,6 +281,9 @@ ignore = [
267
281
  "ARG002", # Unused method argument
268
282
  "ARG001", # Unused function argument
269
283
  "CPY001", # pycodestyle - Missing Copywrite notice at the top of the file
284
+ "RUF029", # Ruff - function is declared as async but has no awaitable calls
285
+ "COM812", # flake8-comma - Missing trailing comma
286
+ "PGH003", # Use Specific ignore for pyright
270
287
  ]
271
288
  select = ["ALL"]
272
289
 
@@ -310,6 +327,8 @@ known-first-party = ["sqlspec", "tests"]
310
327
  "TRY",
311
328
  "PT012",
312
329
  "INP001",
330
+ "DOC",
331
+ "PLC",
313
332
  ]
314
333
  "tools/**/*.*" = ["D", "ARG", "EM", "TRY", "G", "FBT", "S603", "F811", "PLW0127", "PLR0911"]
315
334
  "tools/prepare_release.py" = ["S603", "S607"]
@@ -0,0 +1,15 @@
1
+ from sqlspec import adapters, base, exceptions, extensions, filters, typing, utils
2
+ from sqlspec.__metadata__ import __version__
3
+ from sqlspec.base import SQLSpec
4
+
5
+ __all__ = (
6
+ "SQLSpec",
7
+ "__version__",
8
+ "adapters",
9
+ "base",
10
+ "exceptions",
11
+ "extensions",
12
+ "filters",
13
+ "typing",
14
+ "utils",
15
+ )
@@ -60,12 +60,26 @@ __all__ = (
60
60
 
61
61
 
62
62
  def convert_datetime_to_gmt_iso(dt: datetime.datetime) -> str: # pragma: no cover
63
- """Handle datetime serialization for nested timestamps."""
63
+ """Handle datetime serialization for nested timestamps.
64
+
65
+ Args:
66
+ dt: The datetime to convert.
67
+
68
+ Returns:
69
+ The ISO formatted datetime string.
70
+ """
64
71
  if not dt.tzinfo:
65
72
  dt = dt.replace(tzinfo=datetime.timezone.utc)
66
73
  return dt.isoformat().replace("+00:00", "Z")
67
74
 
68
75
 
69
76
  def convert_date_to_iso(dt: datetime.date) -> str: # pragma: no cover
70
- """Handle datetime serialization for nested timestamps."""
77
+ """Handle datetime serialization for nested timestamps.
78
+
79
+ Args:
80
+ dt: The date to convert.
81
+
82
+ Returns:
83
+ The ISO formatted date string.
84
+ """
71
85
  return dt.isoformat()
@@ -29,7 +29,7 @@ T_co = TypeVar("T_co", covariant=True)
29
29
 
30
30
  try:
31
31
  from pydantic import (
32
- BaseModel,
32
+ BaseModel, # pyright: ignore[reportAssignmentType]
33
33
  FailFast, # pyright: ignore[reportGeneralTypeIssues,reportAssignmentType]
34
34
  TypeAdapter,
35
35
  )
@@ -0,0 +1,7 @@
1
+ from sqlspec.adapters.adbc.config import Adbc
2
+ from sqlspec.adapters.adbc.driver import AdbcDriver
3
+
4
+ __all__ = (
5
+ "Adbc",
6
+ "AdbcDriver",
7
+ )
@@ -0,0 +1,190 @@
1
+ from contextlib import contextmanager
2
+ from dataclasses import dataclass, field
3
+ from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast
4
+
5
+ from adbc_driver_manager.dbapi import Connection
6
+
7
+ from sqlspec.adapters.adbc.driver import AdbcDriver
8
+ from sqlspec.base import NoPoolSyncConfig
9
+ from sqlspec.exceptions import ImproperConfigurationError
10
+ from sqlspec.typing import Empty, EmptyType
11
+ from sqlspec.utils.module_loader import import_string
12
+
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Generator
15
+
16
+
17
+ __all__ = ("Adbc",)
18
+
19
+
20
+ @dataclass
21
+ class Adbc(NoPoolSyncConfig["Connection", "AdbcDriver"]):
22
+ """Configuration for ADBC connections.
23
+
24
+ This class provides configuration options for ADBC database connections using the
25
+ ADBC Driver Manager.([1](https://arrow.apache.org/adbc/current/python/api/adbc_driver_manager.html))
26
+ """
27
+
28
+ uri: "Union[str, EmptyType]" = Empty
29
+ """Database URI"""
30
+ driver_name: "Union[str, EmptyType]" = Empty
31
+ """Full dotted path to the ADBC driver's connect function (e.g., 'adbc_driver_sqlite.dbapi.connect')"""
32
+ db_kwargs: "Optional[dict[str, Any]]" = None
33
+ """Additional database-specific connection parameters"""
34
+ conn_kwargs: "Optional[dict[str, Any]]" = None
35
+ """Additional database-specific connection parameters"""
36
+ connection_type: "type[Connection]" = field(init=False, default_factory=lambda: Connection)
37
+ """Type of the connection object"""
38
+ driver_type: "type[AdbcDriver]" = field(init=False, default_factory=lambda: AdbcDriver) # type: ignore[type-abstract,unused-ignore]
39
+ """Type of the driver object"""
40
+ pool_instance: None = field(init=False, default=None)
41
+ """No connection pool is used for ADBC connections"""
42
+ _is_in_memory: bool = field(init=False, default=False)
43
+ """Flag indicating if the connection is for an in-memory database"""
44
+
45
+ def _set_adbc(self) -> str: # noqa: PLR0912
46
+ """Identify the driver type based on the URI (if provided) or preset driver name.
47
+
48
+ Also sets the `_is_in_memory` flag for specific in-memory URIs.
49
+
50
+ Raises:
51
+ ImproperConfigurationError: If the driver name is not recognized or supported.
52
+
53
+ Returns:
54
+ str: The driver name to be used for the connection.
55
+ """
56
+
57
+ if isinstance(self.driver_name, str):
58
+ if self.driver_name != "adbc_driver_sqlite.dbapi.connect" and "sqlite" in self.driver_name:
59
+ self.driver_name = "adbc_driver_sqlite.dbapi.connect"
60
+ elif self.driver_name != "adbc_driver_duckdb.dbapi.connect" and "duckdb" in self.driver_name:
61
+ self.driver_name = "adbc_driver_duckdb.dbapi.connect"
62
+ elif self.driver_name != "adbc_driver_postgresql.dbapi.connect" and "postgres" in self.driver_name:
63
+ self.driver_name = "adbc_driver_postgresql.dbapi.connect"
64
+ elif self.driver_name != "adbc_driver_snowflake.dbapi.connect" and "snowflake" in self.driver_name:
65
+ self.driver_name = "adbc_driver_snowflake.dbapi.connect"
66
+ elif self.driver_name != "adbc_driver_bigquery.dbapi.connect" and "bigquery" in self.driver_name:
67
+ self.driver_name = "adbc_driver_bigquery.dbapi.connect"
68
+ elif self.driver_name != "adbc_driver_flightsql.dbapi.connect" and "flightsql" in self.driver_name:
69
+ self.driver_name = "adbc_driver_flightsql.dbapi.connect"
70
+ return self.driver_name
71
+
72
+ # If driver_name wasn't explicit, try to determine from URI
73
+ if isinstance(self.uri, str) and self.uri.startswith("postgresql://"):
74
+ self.driver_name = "adbc_driver_postgresql.dbapi.connect"
75
+ elif isinstance(self.uri, str) and self.uri.startswith("sqlite://"):
76
+ self.driver_name = "adbc_driver_sqlite.dbapi.connect"
77
+ elif isinstance(self.uri, str) and self.uri.startswith("grpc://"):
78
+ self.driver_name = "adbc_driver_flightsql.dbapi.connect"
79
+ elif isinstance(self.uri, str) and self.uri.startswith("snowflake://"):
80
+ self.driver_name = "adbc_driver_snowflake.dbapi.connect"
81
+ elif isinstance(self.uri, str) and self.uri.startswith("bigquery://"):
82
+ self.driver_name = "adbc_driver_bigquery.dbapi.connect"
83
+ elif isinstance(self.uri, str) and self.uri.startswith("duckdb://"):
84
+ self.driver_name = "adbc_driver_duckdb.dbapi.connect"
85
+
86
+ # Check if we successfully determined a driver name
87
+ if self.driver_name is Empty or not isinstance(self.driver_name, str):
88
+ msg = (
89
+ "Could not determine ADBC driver connect path. Please specify 'driver_name' "
90
+ "(e.g., 'adbc_driver_sqlite.dbapi.connect') or provide a supported 'uri'. "
91
+ f"URI: {self.uri}, Driver Name: {self.driver_name}"
92
+ )
93
+ raise ImproperConfigurationError(msg)
94
+ return self.driver_name
95
+
96
+ @property
97
+ def connection_config_dict(self) -> "dict[str, Any]":
98
+ """Return the connection configuration as a dict.
99
+
100
+ Omits the 'uri' key for known in-memory database types.
101
+
102
+ Returns:
103
+ A string keyed dict of config kwargs for the adbc_driver_manager.dbapi.connect function.
104
+ """
105
+ config = {}
106
+ db_kwargs = self.db_kwargs or {}
107
+ conn_kwargs = self.conn_kwargs or {}
108
+ if isinstance(self.uri, str) and self.uri.startswith("sqlite://"):
109
+ db_kwargs["uri"] = self.uri.replace("sqlite://", "")
110
+ elif isinstance(self.uri, str) and self.uri.startswith("duckdb://"):
111
+ db_kwargs["path"] = self.uri.replace("duckdb://", "")
112
+ elif isinstance(self.uri, str):
113
+ db_kwargs["uri"] = self.uri
114
+ if isinstance(self.driver_name, str) and self.driver_name.startswith("adbc_driver_bigquery"):
115
+ config["db_kwargs"] = db_kwargs
116
+ else:
117
+ config = db_kwargs
118
+ if conn_kwargs:
119
+ config["conn_kwargs"] = conn_kwargs
120
+ return config
121
+
122
+ def _get_connect_func(self) -> "Callable[..., Connection]":
123
+ self._set_adbc()
124
+ driver_path = cast("str", self.driver_name)
125
+ try:
126
+ connect_func = import_string(driver_path)
127
+ except ImportError as e:
128
+ # Check if the error is likely due to missing suffix and try again
129
+ if ".dbapi.connect" not in driver_path:
130
+ try:
131
+ driver_path += ".dbapi.connect"
132
+ connect_func = import_string(driver_path)
133
+ except ImportError as e2:
134
+ msg = f"Failed to import ADBC connect function from '{self.driver_name}' or '{driver_path}'. Is the driver installed and the path correct? Original error: {e} / {e2}"
135
+ raise ImproperConfigurationError(msg) from e2
136
+ else:
137
+ # Original import failed, and suffix was already present or added
138
+ msg = f"Failed to import ADBC connect function from '{driver_path}'. Is the driver installed and the path correct? Original error: {e}"
139
+ raise ImproperConfigurationError(msg) from e
140
+ if not callable(connect_func):
141
+ msg = f"The path '{driver_path}' did not resolve to a callable function."
142
+ raise ImproperConfigurationError(msg)
143
+ return connect_func # type: ignore[no-any-return]
144
+
145
+ def create_connection(self) -> "Connection":
146
+ """Create and return a new database connection using the specific driver.
147
+
148
+ Returns:
149
+ A new ADBC connection instance.
150
+
151
+ Raises:
152
+ ImproperConfigurationError: If the connection could not be established.
153
+ """
154
+ try:
155
+ connect_func = self._get_connect_func()
156
+ _config = self.connection_config_dict
157
+ return connect_func(**_config)
158
+ except Exception as e:
159
+ # Include driver name in error message for better context
160
+ driver_name = self.driver_name if isinstance(self.driver_name, str) else "Unknown/Derived"
161
+ # Use the potentially modified driver_path from _get_connect_func if available,
162
+ # otherwise fallback to self.driver_name for the error message.
163
+ # This requires _get_connect_func to potentially return the used path or store it.
164
+ # For simplicity now, we stick to self.driver_name in the message.
165
+ msg = f"Could not configure the ADBC connection using driver path '{driver_name}'. Error: {e!s}"
166
+ raise ImproperConfigurationError(msg) from e
167
+
168
+ @contextmanager
169
+ def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[Connection, None, None]":
170
+ """Create and provide a database connection using the specific driver.
171
+
172
+ Yields:
173
+ Connection: A database connection instance.
174
+ """
175
+
176
+ connection = self.create_connection()
177
+ try:
178
+ yield connection
179
+ finally:
180
+ connection.close()
181
+
182
+ @contextmanager
183
+ def provide_session(self, *args: Any, **kwargs: Any) -> "Generator[AdbcDriver, None, None]":
184
+ """Create and provide a database session.
185
+
186
+ Yields:
187
+ An ADBC driver instance with an active connection.
188
+ """
189
+ with self.provide_connection(*args, **kwargs) as connection:
190
+ yield self.driver_type(connection)