sqlspec 0.3.0__tar.gz → 0.5.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 (73) hide show
  1. {sqlspec-0.3.0 → sqlspec-0.5.0}/.pre-commit-config.yaml +2 -2
  2. {sqlspec-0.3.0 → sqlspec-0.5.0}/CONTRIBUTING.rst +4 -4
  3. {sqlspec-0.3.0 → sqlspec-0.5.0}/Makefile +9 -18
  4. sqlspec-0.5.0/PKG-INFO +126 -0
  5. sqlspec-0.5.0/README.md +75 -0
  6. {sqlspec-0.3.0 → sqlspec-0.5.0}/pyproject.toml +21 -9
  7. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/_serialization.py +1 -1
  8. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/_typing.py +58 -2
  9. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/adbc/config.py +8 -10
  10. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/aiosqlite/config.py +4 -21
  11. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/asyncmy/config.py +12 -25
  12. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/asyncpg/config.py +15 -21
  13. sqlspec-0.5.0/sqlspec/adapters/duckdb/__init__.py +3 -0
  14. sqlspec-0.5.0/sqlspec/adapters/duckdb/config.py +202 -0
  15. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/oracledb/__init__.py +1 -1
  16. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/oracledb/config/_asyncio.py +14 -14
  17. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/oracledb/config/_common.py +9 -9
  18. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/oracledb/config/_sync.py +9 -13
  19. sqlspec-0.5.0/sqlspec/adapters/psycopg/config/__init__.py +9 -0
  20. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/psycopg/config/_async.py +8 -14
  21. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/psycopg/config/_common.py +6 -5
  22. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/psycopg/config/_sync.py +8 -14
  23. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/sqlite/config.py +6 -23
  24. sqlspec-0.5.0/sqlspec/base.py +87 -0
  25. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/filters.py +8 -5
  26. sqlspec-0.5.0/sqlspec/typing.py +503 -0
  27. sqlspec-0.5.0/sqlspec/utils/deprecation.py +111 -0
  28. sqlspec-0.5.0/sqlspec/utils/fixtures.py +66 -0
  29. sqlspec-0.5.0/sqlspec/utils/module_loader.py +94 -0
  30. sqlspec-0.5.0/sqlspec/utils/text.py +46 -0
  31. sqlspec-0.5.0/tests/unit/test_adapters/test_duckdb/__init__.py +0 -0
  32. sqlspec-0.5.0/tests/unit/test_adapters/test_duckdb/test_config.py +254 -0
  33. sqlspec-0.5.0/tests/unit/test_typing.py +276 -0
  34. sqlspec-0.5.0/tests/unit/test_utils/__init__.py +0 -0
  35. sqlspec-0.5.0/tests/unit/test_utils/test_module_loader.py +47 -0
  36. sqlspec-0.5.0/tests/unit/test_utils/test_text.py +16 -0
  37. sqlspec-0.5.0/tools/__init__.py +0 -0
  38. {sqlspec-0.3.0 → sqlspec-0.5.0}/uv.lock +638 -639
  39. sqlspec-0.3.0/PKG-INFO +0 -84
  40. sqlspec-0.3.0/README.md +0 -33
  41. sqlspec-0.3.0/sqlspec/adapters/duckdb/config.py +0 -101
  42. sqlspec-0.3.0/sqlspec/adapters/psycopg/config/__init__.py +0 -9
  43. sqlspec-0.3.0/sqlspec/config.py +0 -16
  44. sqlspec-0.3.0/sqlspec/typing.py +0 -287
  45. sqlspec-0.3.0/sqlspec/utils/dataclass.py +0 -138
  46. sqlspec-0.3.0/sqlspec/utils/empty.py +0 -18
  47. {sqlspec-0.3.0 → sqlspec-0.5.0}/.gitignore +0 -0
  48. {sqlspec-0.3.0 → sqlspec-0.5.0}/NOTICE +0 -0
  49. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/__init__.py +0 -0
  50. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/__metadata__.py +0 -0
  51. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/__init__.py +0 -0
  52. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/adbc/__init__.py +0 -0
  53. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/aiosqlite/__init__.py +0 -0
  54. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/asyncmy/__init__.py +0 -0
  55. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/asyncpg/__init__.py +0 -0
  56. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/adapters/oracledb/config/__init__.py +0 -0
  57. {sqlspec-0.3.0/sqlspec/adapters/duckdb → sqlspec-0.5.0/sqlspec/adapters/psycopg}/__init__.py +0 -0
  58. {sqlspec-0.3.0/sqlspec/adapters/psycopg → sqlspec-0.5.0/sqlspec/adapters/sqlite}/__init__.py +0 -0
  59. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/exceptions.py +0 -0
  60. {sqlspec-0.3.0/sqlspec/adapters/sqlite → sqlspec-0.5.0/sqlspec/extensions}/__init__.py +0 -0
  61. {sqlspec-0.3.0/sqlspec/extensions → sqlspec-0.5.0/sqlspec/extensions/litestar}/__init__.py +0 -0
  62. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/extensions/litestar/plugin.py +0 -0
  63. {sqlspec-0.3.0 → sqlspec-0.5.0}/sqlspec/py.typed +0 -0
  64. {sqlspec-0.3.0/sqlspec/extensions/litestar → sqlspec-0.5.0/sqlspec/utils}/__init__.py +0 -0
  65. {sqlspec-0.3.0/sqlspec/utils → sqlspec-0.5.0/tests}/__init__.py +0 -0
  66. {sqlspec-0.3.0 → sqlspec-0.5.0}/tests/conftest.py +0 -0
  67. {sqlspec-0.3.0/tests → sqlspec-0.5.0/tests/unit}/__init__.py +0 -0
  68. {sqlspec-0.3.0/tools → sqlspec-0.5.0/tests/unit/test_adapters}/__init__.py +0 -0
  69. {sqlspec-0.3.0 → sqlspec-0.5.0}/tools/build_docs.py +0 -0
  70. {sqlspec-0.3.0 → sqlspec-0.5.0}/tools/pypi_readme.py +0 -0
  71. {sqlspec-0.3.0 → sqlspec-0.5.0}/tools/sphinx_ext/__init__.py +0 -0
  72. {sqlspec-0.3.0 → sqlspec-0.5.0}/tools/sphinx_ext/changelog.py +0 -0
  73. {sqlspec-0.3.0 → sqlspec-0.5.0}/tools/sphinx_ext/missing_references.py +0 -0
@@ -2,7 +2,7 @@ default_language_version:
2
2
  python: "3"
3
3
  repos:
4
4
  - repo: https://github.com/compilerla/conventional-pre-commit
5
- rev: v3.6.0
5
+ rev: v4.0.0
6
6
  hooks:
7
7
  - id: conventional-pre-commit
8
8
  stages: [commit-msg]
@@ -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.8.3"
20
+ rev: "v0.9.1"
21
21
  hooks:
22
22
  - id: ruff
23
23
  args: ["--fix"]
@@ -14,7 +14,7 @@ Code contributions
14
14
  Workflow
15
15
  ++++++++
16
16
 
17
- 1. `Fork <https://github.com/litestar-org/litestar-htmx/fork>`_ the `litestar-htmx repository <https://github.com/litestar-org/litestar-htmx>`_
17
+ 1. `Fork <https://github.com/litestar-org/sqlspec/fork>`_ the `sqlspec repository <https://github.com/litestar-org/sqlspec>`_
18
18
  2. Clone your fork locally with git
19
19
  3. `Set up the environment <#setting-up-the-environment>`_
20
20
  4. Make your changes
@@ -59,13 +59,13 @@ You can serve the documentation with ``make docs-serve``, or build them with ``m
59
59
  Creating a new release
60
60
  ----------------------
61
61
 
62
- 1. Increment the version in `pyproject.toml <https://github.com/litestar-org/litestar-htmx/blob/main/pyproject.toml>`_.
62
+ 1. Increment the version in `pyproject.toml <https://github.com/litestar-org/sqlspec/blob/main/pyproject.toml>`_.
63
63
  .. note:: The version should follow `semantic versioning <https://semver.org/>`_ and `PEP 440 <https://www.python.org/dev/peps/pep-0440/>`_.
64
- 2. `Draft a new release <https://github.com/litestar-org/litestar-htmx/releases/new>`_ on GitHub
64
+ 2. `Draft a new release <https://github.com/litestar-org/sqlspec/releases/new>`_ on GitHub
65
65
 
66
66
  * Use ``vMAJOR.MINOR.PATCH`` (e.g. ``v1.2.3``) as both the tag and release title
67
67
  * Fill in the release description. You can use the "Generate release notes" function to get a draft for this
68
68
  3. Commit your changes and push to ``main``
69
69
  4. Publish the release
70
- 5. Go to `Actions <https://github.com/litestar-org/litestar-htmx/actions>`_ and approve the release workflow
70
+ 5. Go to `Actions <https://github.com/litestar-org/sqlspec/actions>`_ and approve the release workflow
71
71
  6. Check that the workflow runs successfully
@@ -121,45 +121,36 @@ test: ## Run the tests
121
121
  @uv run pytest tests
122
122
  @echo "${OK} Tests complete ✨"
123
123
 
124
- .PHONY: test-examples
125
- test-examples: ## Run the examples tests
126
- @echo "${INFO} Running example tests... 🧪"
127
- @uv run pytest docs/examples
128
- @echo "${OK} Example tests complete ✨"
129
-
130
124
  .PHONY: test-all
131
- test-all: test test-examples ## Run all tests
125
+ test-all: tests ## Run all tests
132
126
  @echo "${INFO} All tests executed successfully ✨"
133
127
 
134
128
  .PHONY: coverage
135
- coverage: ## Run tests with coverage report
129
+ coverage: ## Run tests with coverage report
136
130
  @echo "${INFO} Running tests with coverage... 📊"
137
- @uv run pytest tests --cov -n auto --quiet
131
+ @uv run pytest --cov -n auto --quiet
138
132
  @uv run coverage html >/dev/null 2>&1
139
133
  @uv run coverage xml >/dev/null 2>&1
140
134
  @echo "${OK} Coverage report generated ✨"
141
135
 
136
+ # -----------------------------------------------------------------------------
137
+ # Type Checking
138
+ # -----------------------------------------------------------------------------
139
+
142
140
  .PHONY: mypy
143
141
  mypy: ## Run mypy
144
142
  @echo "${INFO} Running mypy... 🔍"
145
143
  @uv run dmypy run
146
- @echo "${OK} mypy complete ✨"
147
-
148
- .PHONY: mypy-nocache
149
- mypy-nocache: ## Run Mypy without cache
150
- @echo "${INFO} Running mypy without cache... 🔍"
151
- @uv run mypy
152
- @echo "${OK} mypy complete ✨"
144
+ @echo "${OK} Mypy checks passed ✨"
153
145
 
154
146
  .PHONY: pyright
155
147
  pyright: ## Run pyright
156
148
  @echo "${INFO} Running pyright... 🔍"
157
149
  @uv run pyright
158
- @echo "${OK} pyright complete ✨"
150
+ @echo "${OK} Pyright checks passed ✨"
159
151
 
160
152
  .PHONY: type-check
161
153
  type-check: mypy pyright ## Run all type checking
162
- @echo "${OK} All type checks passed ✨"
163
154
 
164
155
  # -----------------------------------------------------------------------------
165
156
  # Linting and Formatting
sqlspec-0.5.0/PKG-INFO ADDED
@@ -0,0 +1,126 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlspec
3
+ Version: 0.5.0
4
+ Summary: SQL Experiments in Python
5
+ Author-email: Cody Fincher <cody@litestar.dev>
6
+ Maintainer-email: Litestar Developers <hello@litestar.dev>
7
+ License-File: NOTICE
8
+ Requires-Python: <4.0,>=3.9
9
+ Requires-Dist: eval-type-backport; python_version < '3.10'
10
+ Requires-Dist: sqlglot
11
+ Requires-Dist: typing-extensions
12
+ Provides-Extra: adbc
13
+ Requires-Dist: adbc-driver-manager; extra == 'adbc'
14
+ Requires-Dist: pyarrow; extra == 'adbc'
15
+ Provides-Extra: aioodbc
16
+ Requires-Dist: aioodbc; extra == 'aioodbc'
17
+ Provides-Extra: aiosqlite
18
+ Requires-Dist: aiosqlite; extra == 'aiosqlite'
19
+ Provides-Extra: asyncmy
20
+ Requires-Dist: asyncmy; extra == 'asyncmy'
21
+ Provides-Extra: asyncpg
22
+ Requires-Dist: asyncpg; extra == 'asyncpg'
23
+ Provides-Extra: bigquery
24
+ Requires-Dist: google-cloud-bigquery; extra == 'bigquery'
25
+ Provides-Extra: duckdb
26
+ Requires-Dist: duckdb; extra == 'duckdb'
27
+ Provides-Extra: fastapi
28
+ Requires-Dist: fastapi; extra == 'fastapi'
29
+ Provides-Extra: flask
30
+ Requires-Dist: flask; extra == 'flask'
31
+ Provides-Extra: litestar
32
+ Requires-Dist: litestar; extra == 'litestar'
33
+ Provides-Extra: msgspec
34
+ Requires-Dist: msgspec; extra == 'msgspec'
35
+ Provides-Extra: oracledb
36
+ Requires-Dist: oracledb; extra == 'oracledb'
37
+ Provides-Extra: performance
38
+ Requires-Dist: google-re2; (sys_platform == 'linux') and extra == 'performance'
39
+ Requires-Dist: sqlglot[rs]; extra == 'performance'
40
+ Provides-Extra: psycopg
41
+ Requires-Dist: psycopg[binary,pool]; extra == 'psycopg'
42
+ Provides-Extra: pydantic
43
+ Requires-Dist: pydantic; extra == 'pydantic'
44
+ Provides-Extra: pymssql
45
+ Requires-Dist: pymssql; extra == 'pymssql'
46
+ Provides-Extra: pymysql
47
+ Requires-Dist: pymysql; extra == 'pymysql'
48
+ Provides-Extra: spanner
49
+ Requires-Dist: google-cloud-spanner; extra == 'spanner'
50
+ Description-Content-Type: text/markdown
51
+
52
+ # SQLSpec
53
+
54
+ ## A Query Mapper for Python
55
+
56
+ SQLSpec is an experimental Python library designed to streamline and modernize your SQL interactions across a variety of database systems. While still in its early stages, SQLSpec aims to provide a flexible, typed, and extensible interface for working with SQL in Python.
57
+
58
+ **Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
59
+
60
+ ### Core Features (Planned but subject to change, removal or redesign)
61
+
62
+ - **Consistent Database Session Interface**: Provides a consistent connectivity interface for interacting with one or more database systems, including SQLite, Postgres, DuckDB, MySQL, Oracle, SQL Server, Spanner, BigQuery, and more.
63
+ - **Emphasis on RAW SQL and Minimal Abstractions and Performance**: SQLSpec is a library for working with SQL in Python. It's goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
64
+ - **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msqgspec, Attrs, etc.
65
+ - **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
66
+ - **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on it's own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
67
+ - **Dynamic Query Manipulation**: Easily apply filters to pre-defined queries with a fluent, Pythonic API. Safely manipulate queries without the risk of SQL injection.
68
+ - **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
69
+ - **Support for Async and Sync Database Drivers**: SQLSpec supports both async and sync database drivers, allowing you to choose the style that best fits your application.
70
+
71
+ ### What SQLSpec Is Not (Yet)
72
+
73
+ SQLSpec is a work in progress. While it offers a solid foundation for modern SQL interactions, it does not yet include every feature you might find in a mature ORM or database toolkit. The focus is on building a robust, flexible core that can be extended over time.
74
+
75
+ ### Inspiration and Future Direction
76
+
77
+ SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
78
+
79
+ ### Current Focus: Universal Connectivity
80
+
81
+ The primary goal at this stage is to establish a **native connectivity interface** that works seamlessly across all supported database environments. This means you can connect to any of the supported databases using a consistent API, regardless of the underlying driver or dialect.
82
+
83
+ ### Adapters: Completed, In Progress, and Planned
84
+
85
+ This list is not final. If you have a driver you'd like to see added, please open an issue or submit a PR!
86
+
87
+ | Driver | Database | Mode | Status |
88
+ | :----------------------------------------------------------------------------------------------------------- | :--------- | :------ | :--------- |
89
+ | [`adbc`](https://arrow.apache.org/adbc/) | Postgres | Sync | ✅ |
90
+ | [`adbc`](https://arrow.apache.org/adbc/) | SQLite | Sync | ✅ |
91
+ | [`adbc`](https://arrow.apache.org/adbc/) | Snowflake | Sync | ✅ |
92
+ | [`adbc`](https://arrow.apache.org/adbc/) | DuckDB | Sync | ✅ |
93
+ | [`asyncpg`](https://magicstack.github.io/asyncpg/current/) | PostgreSQL | Async | ✅ |
94
+ | [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Sync | ✅ |
95
+ | [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Async | ✅ |
96
+ | [`aiosqlite`](https://github.com/omnilib/aiosqlite) | SQLite | Async | ✅ |
97
+ | `sqlite3` | SQLite | Sync | ✅ |
98
+ | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
99
+ | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Sync | ✅ |
100
+ | [`duckdb`](https://duckdb.org/) | DuckDB | Sync | ✅ |
101
+ | [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️ Planned |
102
+ | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ Planned |
103
+ | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ Planned |
104
+ | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ Planned |
105
+ | [`snowflake`](https://docs.snowflake.com)
106
+
107
+ ### Proposed Project Structure
108
+
109
+ - `sqlspec/`:
110
+ - `adapters/`: Contains all database drivers and associated configuration.
111
+ - `extensions/`:
112
+ - `litestar/`: Future home of `litestar` integration.
113
+ - `fastapi/`: Future home of `fastapi` integration.
114
+ - `flask/`: Future home of `flask` integration.
115
+ - `*/`: Future home of your favorite framework integration 🔌 ✨
116
+ - `base.py`: Contains base protocols for database configurations.
117
+ - `filters.py`: Contains the `Filter` class which is used to apply filters to pre-defined SQL queries.
118
+ - `utils/`: Contains utility functions used throughout the project.
119
+ - `exceptions.py`: Contains custom exceptions for SQLSpec.
120
+ - `typing.py`: Contains type hints, type guards and several facades for optional libraries that are not required for the core functionality of SQLSpec.
121
+
122
+ ### Get Involved
123
+
124
+ SQLSpec is an open-source project, and contributions are welcome! Whether you're interested in adding support for new databases, improving the query interface, or simply providing feedback, your input is valuable.
125
+
126
+ **Disclaimer**: SQLSpec is under active development. Expect changes and improvements as the project evolves.
@@ -0,0 +1,75 @@
1
+ # SQLSpec
2
+
3
+ ## A Query Mapper for Python
4
+
5
+ SQLSpec is an experimental Python library designed to streamline and modernize your SQL interactions across a variety of database systems. While still in its early stages, SQLSpec aims to provide a flexible, typed, and extensible interface for working with SQL in Python.
6
+
7
+ **Note**: SQLSpec is currently under active development and the API is subject to change. It is not yet ready for production use. Contributions are welcome!
8
+
9
+ ### Core Features (Planned but subject to change, removal or redesign)
10
+
11
+ - **Consistent Database Session Interface**: Provides a consistent connectivity interface for interacting with one or more database systems, including SQLite, Postgres, DuckDB, MySQL, Oracle, SQL Server, Spanner, BigQuery, and more.
12
+ - **Emphasis on RAW SQL and Minimal Abstractions and Performance**: SQLSpec is a library for working with SQL in Python. It's goals are to offer minimal abstractions between the user and the database. It does not aim to be an ORM library.
13
+ - **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msqgspec, Attrs, etc.
14
+ - **Extensible Design**: Easily add support for new database dialects or extend existing functionality to meet your specific needs. Easily add support for async and sync database drivers.
15
+ - **Minimal Dependencies**: SQLSpec is designed to be lightweight and can run on it's own or with other libraries such as `litestar`, `fastapi`, `flask` and more. (Contributions welcome!)
16
+ - **Dynamic Query Manipulation**: Easily apply filters to pre-defined queries with a fluent, Pythonic API. Safely manipulate queries without the risk of SQL injection.
17
+ - **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
18
+ - **Support for Async and Sync Database Drivers**: SQLSpec supports both async and sync database drivers, allowing you to choose the style that best fits your application.
19
+
20
+ ### What SQLSpec Is Not (Yet)
21
+
22
+ SQLSpec is a work in progress. While it offers a solid foundation for modern SQL interactions, it does not yet include every feature you might find in a mature ORM or database toolkit. The focus is on building a robust, flexible core that can be extended over time.
23
+
24
+ ### Inspiration and Future Direction
25
+
26
+ SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
27
+
28
+ ### Current Focus: Universal Connectivity
29
+
30
+ The primary goal at this stage is to establish a **native connectivity interface** that works seamlessly across all supported database environments. This means you can connect to any of the supported databases using a consistent API, regardless of the underlying driver or dialect.
31
+
32
+ ### Adapters: Completed, In Progress, and Planned
33
+
34
+ This list is not final. If you have a driver you'd like to see added, please open an issue or submit a PR!
35
+
36
+ | Driver | Database | Mode | Status |
37
+ | :----------------------------------------------------------------------------------------------------------- | :--------- | :------ | :--------- |
38
+ | [`adbc`](https://arrow.apache.org/adbc/) | Postgres | Sync | ✅ |
39
+ | [`adbc`](https://arrow.apache.org/adbc/) | SQLite | Sync | ✅ |
40
+ | [`adbc`](https://arrow.apache.org/adbc/) | Snowflake | Sync | ✅ |
41
+ | [`adbc`](https://arrow.apache.org/adbc/) | DuckDB | Sync | ✅ |
42
+ | [`asyncpg`](https://magicstack.github.io/asyncpg/current/) | PostgreSQL | Async | ✅ |
43
+ | [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Sync | ✅ |
44
+ | [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Async | ✅ |
45
+ | [`aiosqlite`](https://github.com/omnilib/aiosqlite) | SQLite | Async | ✅ |
46
+ | `sqlite3` | SQLite | Sync | ✅ |
47
+ | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
48
+ | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Sync | ✅ |
49
+ | [`duckdb`](https://duckdb.org/) | DuckDB | Sync | ✅ |
50
+ | [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️ Planned |
51
+ | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ Planned |
52
+ | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ Planned |
53
+ | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ Planned |
54
+ | [`snowflake`](https://docs.snowflake.com)
55
+
56
+ ### Proposed Project Structure
57
+
58
+ - `sqlspec/`:
59
+ - `adapters/`: Contains all database drivers and associated configuration.
60
+ - `extensions/`:
61
+ - `litestar/`: Future home of `litestar` integration.
62
+ - `fastapi/`: Future home of `fastapi` integration.
63
+ - `flask/`: Future home of `flask` integration.
64
+ - `*/`: Future home of your favorite framework integration 🔌 ✨
65
+ - `base.py`: Contains base protocols for database configurations.
66
+ - `filters.py`: Contains the `Filter` class which is used to apply filters to pre-defined SQL queries.
67
+ - `utils/`: Contains utility functions used throughout the project.
68
+ - `exceptions.py`: Contains custom exceptions for SQLSpec.
69
+ - `typing.py`: Contains type hints, type guards and several facades for optional libraries that are not required for the core functionality of SQLSpec.
70
+
71
+ ### Get Involved
72
+
73
+ SQLSpec is an open-source project, and contributions are welcome! Whether you're interested in adding support for new databases, improving the query interface, or simply providing feedback, your input is valuable.
74
+
75
+ **Disclaimer**: SQLSpec is under active development. Expect changes and improvements as the project evolves.
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  authors = [{ name = "Cody Fincher", email = "cody@litestar.dev" }]
3
- dependencies = ["typing-extensions>=4.0.0", "eval_type_backport; python_version <= \"3.9\"", "sqlglot"]
3
+ dependencies = ["typing-extensions", "sqlglot", "eval_type_backport; python_version < \"3.10\""]
4
4
  description = "SQL Experiments in Python"
5
5
  maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }]
6
6
  name = "sqlspec"
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.9, <4.0"
9
- version = "0.3.0"
9
+ version = "0.5.0"
10
10
 
11
11
  [project.optional-dependencies]
12
12
  adbc = ["adbc-driver-manager", "pyarrow"]
@@ -128,6 +128,8 @@ exclude_lines = [
128
128
 
129
129
  [tool.pytest.ini_options]
130
130
  addopts = "-ra -q --doctest-glob='*.md' --strict-markers --strict-config"
131
+ asyncio_default_fixture_loop_scope = "function"
132
+ asyncio_mode = "auto"
131
133
  testpaths = ["tests"]
132
134
  xfail_strict = true
133
135
 
@@ -149,7 +151,17 @@ warn_unused_ignores = true
149
151
 
150
152
  [[tool.mypy.overrides]]
151
153
  ignore_missing_imports = true
152
- module = ["orjson", "re2", "re2.*", "uvicorn.*", "googleapiclient", "googleapiclient.*", "uvloop.*","asyncmy", "asyncmy.*"]
154
+ module = [
155
+ "orjson",
156
+ "re2",
157
+ "re2.*",
158
+ "uvicorn.*",
159
+ "googleapiclient",
160
+ "googleapiclient.*",
161
+ "uvloop.*",
162
+ "asyncmy",
163
+ "asyncmy.*",
164
+ ]
153
165
 
154
166
  [tool.pyright]
155
167
  disableBytesTypePromotions = true
@@ -272,25 +284,25 @@ docstring-code-line-length = 88
272
284
  [tool.git-cliff.changelog]
273
285
  body = """
274
286
  {% if version %}\
275
- `Release [v{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} <https://github.com/litestar-org/litestar-htmx/releases/tag/v{{ version | trim_start_matches(pat="v") }}>`_
287
+ `Release [v{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} <https://github.com/litestar-org/sqlspec/releases/tag/v{{ version | trim_start_matches(pat="v") }}>`_
276
288
  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
277
- * `See All commits in v{{ version | trim_start_matches(pat="v") }} <https://github.com/litestar-org/litestar-htmx/commits/v{{ version | trim_start_matches(pat="v") }}>`_
289
+ * `See All commits in v{{ version | trim_start_matches(pat="v") }} <https://github.com/litestar-org/sqlspec/commits/v{{ version | trim_start_matches(pat="v") }}>`_
278
290
  {% else %}\
279
291
  [unreleased]
280
292
  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
281
293
  {% endif %}\
282
294
  {% if previous %}\
283
295
  {% if previous.commit_id %}
284
- `{{ previous.commit_id | truncate(length=7, end="") }} <https://github.com/litestar-org/litestar-htmx/commit/{{ previous.commit_id }}>`_ ... \
285
- `{{ commit_id | truncate(length=7, end="") }} <https://github.com/litestar-org/litestar-htmx/commit/{{ commit_id }}>`_ \
286
- | `See diff for {{ version | trim_start_matches(pat="v") }} <https://github.com/litestar-org/litestar-htmx/compare/{{ previous.commit_id }}...{{ commit_id }}>`_
296
+ `{{ previous.commit_id | truncate(length=7, end="") }} <https://github.com/litestar-org/sqlspec/commit/{{ previous.commit_id }}>`_ ... \
297
+ `{{ commit_id | truncate(length=7, end="") }} <https://github.com/litestar-org/sqlspec/commit/{{ commit_id }}>`_ \
298
+ | `See diff for {{ version | trim_start_matches(pat="v") }} <https://github.com/litestar-org/sqlspec/compare/{{ previous.commit_id }}...{{ commit_id }}>`_
287
299
  {% endif %}\
288
300
  {% endif %}\
289
301
  {% for group, commits in commits | group_by(attribute="group") %}
290
302
  {{ group | upper_first }}
291
303
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
292
304
  {% for commit in commits %}
293
- * (`{{ commit.id | truncate(length=7, end="") }} <https://github.com/litestar-org/litestar-htmx/commit/{{ commit.id }}>`_) {% if commit.breaking %}[**breaking**] {% endif %} - {{ commit.message | upper_first }} ({{ commit.author.name }})\
305
+ * (`{{ commit.id | truncate(length=7, end="") }} <https://github.com/litestar-org/sqlspec/commit/{{ commit.id }}>`_) {% if commit.breaking %}[**breaking**] {% endif %} - {{ commit.message | upper_first }} ({{ commit.author.name }})\
294
306
  {% for footer in commit.footers -%}
295
307
  , {{ footer.token }}{{ footer.separator }}{{ footer.value }}\
296
308
  {% endfor %}\
@@ -13,7 +13,7 @@ try:
13
13
 
14
14
  except ImportError:
15
15
  try:
16
- from orjson import dumps as _encode_json # pyright: ignore[reportMissingImports]
16
+ from orjson import dumps as _encode_json # pyright: ignore[reportMissingImports,reportUnknownVariableType]
17
17
  from orjson import loads as decode_json # type: ignore[no-redef]
18
18
 
19
19
  def encode_json(data: Any) -> str:
@@ -5,20 +5,30 @@ This is used to ensure compatibility when one or more of the libraries are insta
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
+ from enum import Enum
8
9
  from typing import (
9
10
  Any,
10
11
  ClassVar,
12
+ Final,
11
13
  Protocol,
14
+ Union,
12
15
  cast,
13
16
  runtime_checkable,
14
17
  )
15
18
 
16
- from typing_extensions import TypeVar, dataclass_transform
19
+ from typing_extensions import Literal, TypeVar, dataclass_transform
20
+
21
+
22
+ @runtime_checkable
23
+ class DataclassProtocol(Protocol):
24
+ """Protocol for instance checking dataclasses."""
25
+
26
+ __dataclass_fields__: ClassVar[dict[str, Any]]
27
+
17
28
 
18
29
  T = TypeVar("T")
19
30
  T_co = TypeVar("T_co", covariant=True)
20
31
 
21
-
22
32
  try:
23
33
  from pydantic import BaseModel, FailFast, TypeAdapter
24
34
 
@@ -99,11 +109,57 @@ except ImportError:
99
109
  UNSET = UnsetType.UNSET # pyright: ignore[reportConstantRedefinition]
100
110
  MSGSPEC_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
101
111
 
112
+ try:
113
+ from litestar.dto.data_structures import DTOData # pyright: ignore[reportUnknownVariableType]
114
+
115
+ LITESTAR_INSTALLED = True
116
+ except ImportError:
117
+
118
+ @runtime_checkable
119
+ class DTOData(Protocol[T]): # type: ignore[no-redef]
120
+ """Placeholder implementation"""
121
+
122
+ __slots__ = ("_backend", "_data_as_builtins")
123
+
124
+ def __init__(self, backend: Any, data_as_builtins: Any) -> None:
125
+ """Placeholder init"""
126
+
127
+ def create_instance(self, **kwargs: Any) -> T:
128
+ """Placeholder implementation"""
129
+ return cast("T", kwargs)
130
+
131
+ def update_instance(self, instance: T, **kwargs: Any) -> T:
132
+ """Placeholder implementation"""
133
+ return cast("T", kwargs)
134
+
135
+ def as_builtins(self) -> Any:
136
+ """Placeholder implementation"""
137
+ return {}
138
+
139
+ LITESTAR_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
140
+
141
+
142
+ class EmptyEnum(Enum):
143
+ """A sentinel enum used as placeholder."""
144
+
145
+ EMPTY = 0
146
+
147
+
148
+ EmptyType = Union[Literal[EmptyEnum.EMPTY], UnsetType]
149
+ Empty: Final = EmptyEnum.EMPTY
150
+
151
+
102
152
  __all__ = (
153
+ "LITESTAR_INSTALLED",
103
154
  "MSGSPEC_INSTALLED",
104
155
  "PYDANTIC_INSTALLED",
105
156
  "UNSET",
106
157
  "BaseModel",
158
+ "DTOData",
159
+ "DataclassProtocol",
160
+ "Empty",
161
+ "EmptyEnum",
162
+ "EmptyType",
107
163
  "FailFast",
108
164
  "Struct",
109
165
  "TypeAdapter",
@@ -2,33 +2,31 @@ from __future__ import annotations
2
2
 
3
3
  from contextlib import contextmanager
4
4
  from dataclasses import dataclass
5
- from typing import TYPE_CHECKING, TypeVar
5
+ from typing import TYPE_CHECKING
6
6
 
7
- from sqlspec.config import GenericDatabaseConfig
8
- from sqlspec.utils.empty import Empty
7
+ from sqlspec.base import GenericDatabaseConfig, NoPoolConfig
8
+ from sqlspec.typing import Empty, EmptyType
9
9
 
10
10
  if TYPE_CHECKING:
11
11
  from collections.abc import Generator
12
12
  from typing import Any
13
13
 
14
- from adbc_driver_manager.dbapi import Connection, Cursor
15
-
16
- from sqlspec.utils.empty import EmptyType
14
+ from adbc_driver_manager.dbapi import Connection
17
15
 
18
16
  __all__ = ("AdbcDatabaseConfig",)
19
17
 
20
- ConnectionT = TypeVar("ConnectionT", bound="Connection")
21
- CursorT = TypeVar("CursorT", bound="Cursor")
22
-
23
18
 
24
19
  @dataclass
25
- class AdbcDatabaseConfig(GenericDatabaseConfig):
20
+ class AdbcDatabaseConfig(NoPoolConfig["Connection"], GenericDatabaseConfig):
26
21
  """Configuration for ADBC connections.
27
22
 
28
23
  This class provides configuration options for ADBC database connections using the
29
24
  ADBC Driver Manager.([1](https://arrow.apache.org/adbc/current/python/api/adbc_driver_manager.html))
30
25
  """
31
26
 
27
+ __supports_connection_pooling = False
28
+ __is_async = False
29
+
32
30
  uri: str | EmptyType = Empty
33
31
  """Database URI"""
34
32
  driver_name: str | EmptyType = Empty
@@ -4,10 +4,9 @@ from contextlib import asynccontextmanager
4
4
  from dataclasses import dataclass
5
5
  from typing import TYPE_CHECKING, Any
6
6
 
7
- from sqlspec.config import GenericDatabaseConfig
7
+ from sqlspec.base import GenericDatabaseConfig, NoPoolConfig
8
8
  from sqlspec.exceptions import ImproperConfigurationError
9
- from sqlspec.utils.dataclass import simple_asdict
10
- from sqlspec.utils.empty import Empty, EmptyType
9
+ from sqlspec.typing import Empty, EmptyType, dataclass_to_dict
11
10
 
12
11
  if TYPE_CHECKING:
13
12
  from collections.abc import AsyncGenerator
@@ -20,7 +19,7 @@ __all__ = ("AiosqliteConfig",)
20
19
 
21
20
 
22
21
  @dataclass
23
- class AiosqliteConfig(GenericDatabaseConfig):
22
+ class AiosqliteConfig(NoPoolConfig["Connection"], GenericDatabaseConfig):
24
23
  """Configuration for Aiosqlite database connections.
25
24
 
26
25
  This class provides configuration options for Aiosqlite database connections, wrapping all parameters
@@ -60,7 +59,7 @@ class AiosqliteConfig(GenericDatabaseConfig):
60
59
  Returns:
61
60
  A string keyed dict of config kwargs for the aiosqlite.connect() function.
62
61
  """
63
- return simple_asdict(self, exclude_empty=True, convert_nested=False)
62
+ return dataclass_to_dict(self, exclude_empty=True, convert_nested=False)
64
63
 
65
64
  async def create_connection(self) -> Connection:
66
65
  """Create and return a new database connection.
@@ -79,22 +78,6 @@ class AiosqliteConfig(GenericDatabaseConfig):
79
78
  msg = f"Could not configure the Aiosqlite connection. Error: {e!s}"
80
79
  raise ImproperConfigurationError(msg) from e
81
80
 
82
- @asynccontextmanager
83
- async def lifespan(self, *args: Any, **kwargs: Any) -> AsyncGenerator[None, None]:
84
- """Manage the lifecycle of a database connection.
85
-
86
- Yields:
87
- None
88
-
89
- Raises:
90
- ImproperConfigurationError: If the connection could not be established.
91
- """
92
- connection = await self.create_connection()
93
- try:
94
- yield
95
- finally:
96
- await connection.close()
97
-
98
81
  @asynccontextmanager
99
82
  async def provide_connection(self, *args: Any, **kwargs: Any) -> AsyncGenerator[Connection, None]:
100
83
  """Create and provide a database connection.