sqlspec 0.5.0__tar.gz → 0.7.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.
- {sqlspec-0.5.0 → sqlspec-0.7.0}/.pre-commit-config.yaml +2 -2
- sqlspec-0.7.0/LICENSE +21 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/PKG-INFO +24 -15
- {sqlspec-0.5.0 → sqlspec-0.7.0}/README.md +14 -13
- sqlspec-0.7.0/base.py +9 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/pyproject.toml +87 -113
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/__metadata__.py +1 -3
- sqlspec-0.7.0/sqlspec/_serialization.py +71 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/_typing.py +69 -20
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/adbc/config.py +8 -13
- sqlspec-0.7.0/sqlspec/adapters/aiosqlite/__init__.py +3 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/aiosqlite/config.py +15 -24
- sqlspec-0.7.0/sqlspec/adapters/asyncmy/__init__.py +3 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/asyncmy/config.py +46 -46
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/asyncpg/config.py +28 -33
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/duckdb/config.py +75 -79
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/oracledb/config/_asyncio.py +23 -18
- sqlspec-0.7.0/sqlspec/adapters/oracledb/config/_common.py +131 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/oracledb/config/_sync.py +21 -16
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/psycopg/config/_async.py +17 -17
- sqlspec-0.7.0/sqlspec/adapters/psycopg/config/_common.py +56 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/psycopg/config/_sync.py +16 -17
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/sqlite/config.py +13 -15
- sqlspec-0.7.0/sqlspec/base.py +227 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/exceptions.py +4 -6
- sqlspec-0.7.0/sqlspec/extensions/litestar/plugin.py +43 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/filters.py +11 -13
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/typing.py +110 -127
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/utils/deprecation.py +8 -10
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/utils/fixtures.py +3 -5
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/utils/module_loader.py +4 -6
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/utils/text.py +2 -3
- sqlspec-0.7.0/tests/unit/test_adapters/test_aiosqlite/test_config.py +108 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_asyncpg/__init__.py +1 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_asyncpg/test_config.py +159 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_duckdb/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tests/unit/test_adapters/test_duckdb/test_config.py +72 -71
- sqlspec-0.7.0/tests/unit/test_adapters/test_oracledb/__init__.py +1 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_oracledb/test_config.py +336 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_psycopg/test_async_config.py +167 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_psycopg/test_sync_config.py +152 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_sqlite/__init__.py +1 -0
- sqlspec-0.7.0/tests/unit/test_adapters/test_sqlite/test_config.py +87 -0
- sqlspec-0.7.0/tests/unit/test_base.py +229 -0
- sqlspec-0.7.0/tests/unit/test_utils/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tests/unit/test_utils/test_module_loader.py +4 -4
- sqlspec-0.7.0/tools/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tools/sphinx_ext/__init__.py +1 -1
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tools/sphinx_ext/missing_references.py +29 -21
- {sqlspec-0.5.0 → sqlspec-0.7.0}/uv.lock +1227 -775
- sqlspec-0.5.0/sqlspec/__init__.py +0 -1
- sqlspec-0.5.0/sqlspec/_serialization.py +0 -24
- sqlspec-0.5.0/sqlspec/adapters/aiosqlite/__init__.py +0 -3
- sqlspec-0.5.0/sqlspec/adapters/asyncmy/__init__.py +0 -3
- sqlspec-0.5.0/sqlspec/adapters/oracledb/config/_common.py +0 -151
- sqlspec-0.5.0/sqlspec/adapters/psycopg/config/_common.py +0 -73
- sqlspec-0.5.0/sqlspec/base.py +0 -87
- sqlspec-0.5.0/sqlspec/extensions/litestar/plugin.py +0 -34
- {sqlspec-0.5.0 → sqlspec-0.7.0}/.gitignore +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/CONTRIBUTING.rst +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/Makefile +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/NOTICE +0 -0
- {sqlspec-0.5.0/sqlspec/adapters → sqlspec-0.7.0/sqlspec}/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/adapters/adbc → sqlspec-0.7.0/sqlspec/adapters}/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/adapters/asyncpg → sqlspec-0.7.0/sqlspec/adapters/adbc}/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/adapters/psycopg → sqlspec-0.7.0/sqlspec/adapters/asyncpg}/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/duckdb/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/oracledb/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/oracledb/config/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/adapters/sqlite → sqlspec-0.7.0/sqlspec/adapters/psycopg}/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/sqlspec/adapters/psycopg/config/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/extensions → sqlspec-0.7.0/sqlspec/adapters/sqlite}/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/extensions/litestar → sqlspec-0.7.0/sqlspec/extensions}/__init__.py +0 -0
- {sqlspec-0.5.0/sqlspec/utils → sqlspec-0.7.0/sqlspec/extensions/litestar}/__init__.py +0 -0
- /sqlspec-0.5.0/sqlspec/py.typed → /sqlspec-0.7.0/sqlspec/extensions/litestar/config.py +0 -0
- /sqlspec-0.5.0/tests/__init__.py → /sqlspec-0.7.0/sqlspec/py.typed +0 -0
- {sqlspec-0.5.0/tests/unit → sqlspec-0.7.0/sqlspec/utils}/__init__.py +0 -0
- {sqlspec-0.5.0/tests/unit/test_adapters → sqlspec-0.7.0/tests}/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tests/conftest.py +0 -0
- {sqlspec-0.5.0/tests/unit/test_adapters/test_duckdb → sqlspec-0.7.0/tests/integration}/__init__.py +0 -0
- {sqlspec-0.5.0/tests/unit/test_utils → sqlspec-0.7.0/tests/unit}/__init__.py +0 -0
- {sqlspec-0.5.0/tools → sqlspec-0.7.0/tests/unit/test_adapters}/__init__.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tests/unit/test_typing.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tests/unit/test_utils/test_text.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tools/build_docs.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tools/pypi_readme.py +0 -0
- {sqlspec-0.5.0 → sqlspec-0.7.0}/tools/sphinx_ext/changelog.py +0 -0
|
@@ -17,13 +17,13 @@ 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.
|
|
20
|
+
rev: "v0.9.10"
|
|
21
21
|
hooks:
|
|
22
22
|
- id: ruff
|
|
23
23
|
args: ["--fix"]
|
|
24
24
|
- id: ruff-format
|
|
25
25
|
- repo: https://github.com/codespell-project/codespell
|
|
26
|
-
rev: v2.
|
|
26
|
+
rev: v2.4.1
|
|
27
27
|
hooks:
|
|
28
28
|
- id: codespell
|
|
29
29
|
additional_dependencies:
|
sqlspec-0.7.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Litestar Organization
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlspec
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.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
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
7
9
|
License-File: NOTICE
|
|
8
10
|
Requires-Python: <4.0,>=3.9
|
|
9
11
|
Requires-Dist: eval-type-backport; python_version < '3.10'
|
|
@@ -32,21 +34,27 @@ Provides-Extra: litestar
|
|
|
32
34
|
Requires-Dist: litestar; extra == 'litestar'
|
|
33
35
|
Provides-Extra: msgspec
|
|
34
36
|
Requires-Dist: msgspec; extra == 'msgspec'
|
|
37
|
+
Provides-Extra: nanoid
|
|
38
|
+
Requires-Dist: fastnanoid>=0.4.1; extra == 'nanoid'
|
|
35
39
|
Provides-Extra: oracledb
|
|
36
40
|
Requires-Dist: oracledb; extra == 'oracledb'
|
|
41
|
+
Provides-Extra: orjson
|
|
42
|
+
Requires-Dist: orjson; extra == 'orjson'
|
|
37
43
|
Provides-Extra: performance
|
|
38
|
-
Requires-Dist: google-re2; (sys_platform == 'linux') and extra == 'performance'
|
|
39
44
|
Requires-Dist: sqlglot[rs]; extra == 'performance'
|
|
40
45
|
Provides-Extra: psycopg
|
|
41
46
|
Requires-Dist: psycopg[binary,pool]; extra == 'psycopg'
|
|
42
47
|
Provides-Extra: pydantic
|
|
43
48
|
Requires-Dist: pydantic; extra == 'pydantic'
|
|
49
|
+
Requires-Dist: pydantic-extra-types; extra == 'pydantic'
|
|
44
50
|
Provides-Extra: pymssql
|
|
45
51
|
Requires-Dist: pymssql; extra == 'pymssql'
|
|
46
52
|
Provides-Extra: pymysql
|
|
47
53
|
Requires-Dist: pymysql; extra == 'pymysql'
|
|
48
54
|
Provides-Extra: spanner
|
|
49
55
|
Requires-Dist: google-cloud-spanner; extra == 'spanner'
|
|
56
|
+
Provides-Extra: uuid
|
|
57
|
+
Requires-Dist: uuid-utils>=0.6.1; extra == 'uuid'
|
|
50
58
|
Description-Content-Type: text/markdown
|
|
51
59
|
|
|
52
60
|
# SQLSpec
|
|
@@ -57,30 +65,31 @@ SQLSpec is an experimental Python library designed to streamline and modernize y
|
|
|
57
65
|
|
|
58
66
|
**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
67
|
|
|
60
|
-
|
|
68
|
+
## Core Features (Planned but subject to change, removal or redesign)
|
|
61
69
|
|
|
62
70
|
- **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
71
|
- **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,
|
|
72
|
+
- **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msgspec, Attrs, etc.
|
|
65
73
|
- **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
74
|
- **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
75
|
- **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
76
|
- **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
|
|
69
77
|
- **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.
|
|
78
|
+
- **Basic Migration Management**: A mechanism to generate empty migration files where you can add your own SQL and intelligently track which migrations have been applied.
|
|
70
79
|
|
|
71
|
-
|
|
80
|
+
## What SQLSpec Is Not (Yet)
|
|
72
81
|
|
|
73
82
|
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
83
|
|
|
75
|
-
|
|
84
|
+
## Inspiration and Future Direction
|
|
76
85
|
|
|
77
86
|
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
87
|
|
|
79
|
-
|
|
88
|
+
## Current Focus: Universal Connectivity
|
|
80
89
|
|
|
81
90
|
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
91
|
|
|
83
|
-
|
|
92
|
+
## Adapters: Completed, In Progress, and Planned
|
|
84
93
|
|
|
85
94
|
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
95
|
|
|
@@ -98,13 +107,13 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
98
107
|
| [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
|
|
99
108
|
| [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Sync | ✅ |
|
|
100
109
|
| [`duckdb`](https://duckdb.org/) | DuckDB | Sync | ✅ |
|
|
101
|
-
| [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️
|
|
102
|
-
| [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️
|
|
103
|
-
| [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️
|
|
104
|
-
| [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️
|
|
105
|
-
| [`snowflake`](https://docs.snowflake.com)
|
|
110
|
+
| [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️ |
|
|
111
|
+
| [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ |
|
|
112
|
+
| [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ |
|
|
113
|
+
| [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ |
|
|
114
|
+
| [`snowflake`](https://docs.snowflake.com) | Snowflake | Sync | 🗓️ |
|
|
106
115
|
|
|
107
|
-
|
|
116
|
+
## Proposed Project Structure
|
|
108
117
|
|
|
109
118
|
- `sqlspec/`:
|
|
110
119
|
- `adapters/`: Contains all database drivers and associated configuration.
|
|
@@ -119,7 +128,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
119
128
|
- `exceptions.py`: Contains custom exceptions for SQLSpec.
|
|
120
129
|
- `typing.py`: Contains type hints, type guards and several facades for optional libraries that are not required for the core functionality of SQLSpec.
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
## Get Involved
|
|
123
132
|
|
|
124
133
|
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
134
|
|
|
@@ -6,30 +6,31 @@ SQLSpec is an experimental Python library designed to streamline and modernize y
|
|
|
6
6
|
|
|
7
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
8
|
|
|
9
|
-
|
|
9
|
+
## Core Features (Planned but subject to change, removal or redesign)
|
|
10
10
|
|
|
11
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
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,
|
|
13
|
+
- **Type-Safe Queries**: Quickly map SQL queries to typed objects using libraries such as Pydantic, Msgspec, Attrs, etc.
|
|
14
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
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
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
17
|
- **Dialect Validation and Conversion**: Use `sqlglot` to validate your SQL against specific dialects and seamlessly convert between them.
|
|
18
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
|
+
- **Basic Migration Management**: A mechanism to generate empty migration files where you can add your own SQL and intelligently track which migrations have been applied.
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
## What SQLSpec Is Not (Yet)
|
|
21
22
|
|
|
22
23
|
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
|
|
|
24
|
-
|
|
25
|
+
## Inspiration and Future Direction
|
|
25
26
|
|
|
26
27
|
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
|
|
|
28
|
-
|
|
29
|
+
## Current Focus: Universal Connectivity
|
|
29
30
|
|
|
30
31
|
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
|
|
|
32
|
-
|
|
33
|
+
## Adapters: Completed, In Progress, and Planned
|
|
33
34
|
|
|
34
35
|
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
|
|
|
@@ -47,13 +48,13 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
47
48
|
| [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
|
|
48
49
|
| [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Sync | ✅ |
|
|
49
50
|
| [`duckdb`](https://duckdb.org/) | DuckDB | Sync | ✅ |
|
|
50
|
-
| [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️
|
|
51
|
-
| [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️
|
|
52
|
-
| [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️
|
|
53
|
-
| [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️
|
|
54
|
-
| [`snowflake`](https://docs.snowflake.com)
|
|
51
|
+
| [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️ |
|
|
52
|
+
| [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ |
|
|
53
|
+
| [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ |
|
|
54
|
+
| [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ |
|
|
55
|
+
| [`snowflake`](https://docs.snowflake.com) | Snowflake | Sync | 🗓️ |
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
## Proposed Project Structure
|
|
57
58
|
|
|
58
59
|
- `sqlspec/`:
|
|
59
60
|
- `adapters/`: Contains all database drivers and associated configuration.
|
|
@@ -68,7 +69,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
68
69
|
- `exceptions.py`: Contains custom exceptions for SQLSpec.
|
|
69
70
|
- `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
|
|
|
71
|
-
|
|
72
|
+
## Get Involved
|
|
72
73
|
|
|
73
74
|
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
|
|
sqlspec-0.7.0/base.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from sqlspec.adapters.duckdb.config import DuckDBConfig
|
|
2
|
+
from sqlspec.base import ConfigManager
|
|
3
|
+
|
|
4
|
+
dbs = ConfigManager()
|
|
5
|
+
|
|
6
|
+
config = DuckDBConfig(database="test.duckdb", extensions=[{"name": "vss"}])
|
|
7
|
+
etl_db = dbs.add_config(config)
|
|
8
|
+
|
|
9
|
+
connection = dbs.get_connection(etl_db)
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
authors = [{ name = "Cody Fincher", email = "cody@litestar.dev" }]
|
|
3
3
|
dependencies = ["typing-extensions", "sqlglot", "eval_type_backport; python_version < \"3.10\""]
|
|
4
4
|
description = "SQL Experiments in Python"
|
|
5
|
+
license = "MIT"
|
|
5
6
|
maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }]
|
|
6
7
|
name = "sqlspec"
|
|
7
8
|
readme = "README.md"
|
|
8
9
|
requires-python = ">=3.9, <4.0"
|
|
9
|
-
version = "0.
|
|
10
|
+
version = "0.7.0"
|
|
10
11
|
|
|
11
12
|
[project.optional-dependencies]
|
|
12
13
|
adbc = ["adbc-driver-manager", "pyarrow"]
|
|
@@ -20,15 +21,19 @@ fastapi = ["fastapi"]
|
|
|
20
21
|
flask = ["flask"]
|
|
21
22
|
litestar = ["litestar"]
|
|
22
23
|
msgspec = ["msgspec"]
|
|
24
|
+
nanoid = ["fastnanoid>=0.4.1"]
|
|
23
25
|
oracledb = ["oracledb"]
|
|
24
|
-
|
|
26
|
+
orjson = ["orjson"]
|
|
27
|
+
performance = ["sqlglot[rs]"]
|
|
25
28
|
psycopg = ["psycopg[binary,pool]"]
|
|
26
|
-
pydantic = ["pydantic"]
|
|
29
|
+
pydantic = ["pydantic", "pydantic-extra-types"]
|
|
27
30
|
pymssql = ["pymssql"]
|
|
28
31
|
pymysql = ["pymysql"]
|
|
29
32
|
spanner = ["google-cloud-spanner"]
|
|
33
|
+
uuid = ["uuid-utils>=0.6.1"]
|
|
30
34
|
|
|
31
35
|
[dependency-groups]
|
|
36
|
+
build = ["bump-my-version"]
|
|
32
37
|
dev = [
|
|
33
38
|
"adbc-driver-sqlite",
|
|
34
39
|
"adbc-driver-postgresql",
|
|
@@ -36,11 +41,11 @@ dev = [
|
|
|
36
41
|
{ include-group = "lint" },
|
|
37
42
|
{ include-group = "doc" },
|
|
38
43
|
{ include-group = "test" },
|
|
44
|
+
{ include-group = "build" },
|
|
39
45
|
]
|
|
40
46
|
doc = [
|
|
41
47
|
"auto-pytabs[sphinx]>=0.5.0",
|
|
42
|
-
"
|
|
43
|
-
"litestar-sphinx-theme @ git+https://github.com/litestar-org/litestar-sphinx-theme.git@v3",
|
|
48
|
+
"shibuya",
|
|
44
49
|
"sphinx>=7.0.0; python_version <= \"3.9\"",
|
|
45
50
|
"sphinx>=8.0.0; python_version >= \"3.10\"",
|
|
46
51
|
"sphinx-autobuild>=2021.3.14",
|
|
@@ -51,6 +56,8 @@ doc = [
|
|
|
51
56
|
"sphinx-paramlinks>=0.6.0",
|
|
52
57
|
"sphinx-togglebutton>=0.3.2",
|
|
53
58
|
"sphinx-toolbox>=3.8.1",
|
|
59
|
+
"myst-parser",
|
|
60
|
+
"sphinx-autodoc-typehints",
|
|
54
61
|
]
|
|
55
62
|
lint = [
|
|
56
63
|
"mypy>=1.13.0",
|
|
@@ -74,7 +81,6 @@ test = [
|
|
|
74
81
|
"pytest-xdist>=3.6.1",
|
|
75
82
|
]
|
|
76
83
|
|
|
77
|
-
|
|
78
84
|
[build-system]
|
|
79
85
|
build-backend = "hatchling.build"
|
|
80
86
|
requires = ["hatchling"]
|
|
@@ -91,6 +97,40 @@ include = ["NOTICE"]
|
|
|
91
97
|
packages = ["sqlspec"]
|
|
92
98
|
|
|
93
99
|
|
|
100
|
+
[tool.bumpversion]
|
|
101
|
+
allow_dirty = true
|
|
102
|
+
commit = false
|
|
103
|
+
commit_args = "--no-verify"
|
|
104
|
+
current_version = "0.33.1"
|
|
105
|
+
ignore_missing_files = false
|
|
106
|
+
ignore_missing_version = false
|
|
107
|
+
message = "chore(release): bump to v{new_version}"
|
|
108
|
+
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
109
|
+
regex = false
|
|
110
|
+
replace = "{new_version}"
|
|
111
|
+
search = "{current_version}"
|
|
112
|
+
serialize = ["{major}.{minor}.{patch}"]
|
|
113
|
+
sign_tags = false
|
|
114
|
+
tag = false
|
|
115
|
+
tag_message = "chore(release): v{new_version}"
|
|
116
|
+
tag_name = "v{new_version}"
|
|
117
|
+
|
|
118
|
+
[[tool.bumpversion.files]]
|
|
119
|
+
filename = "pyproject.toml"
|
|
120
|
+
replace = 'version = "{new_version}"'
|
|
121
|
+
search = 'version = "{current_version}"'
|
|
122
|
+
|
|
123
|
+
[[tool.bumpversion.files]]
|
|
124
|
+
filename = "uv.lock"
|
|
125
|
+
replace = """
|
|
126
|
+
name = "advanced-alchemy"
|
|
127
|
+
version = "{new_version}"
|
|
128
|
+
"""
|
|
129
|
+
search = """
|
|
130
|
+
name = "advanced-alchemy"
|
|
131
|
+
version = "{current_version}"
|
|
132
|
+
"""
|
|
133
|
+
|
|
94
134
|
[tool.codespell]
|
|
95
135
|
ignore-words-list = "te"
|
|
96
136
|
skip = 'uv.lock'
|
|
@@ -102,6 +142,7 @@ disable_warnings = ["no-data-collected", "module-not-measured", "module-not-impo
|
|
|
102
142
|
omit = ["*/tests/*"]
|
|
103
143
|
parallel = true
|
|
104
144
|
plugins = ["covdefaults"]
|
|
145
|
+
relative_files = true
|
|
105
146
|
source = ["sqlspec"]
|
|
106
147
|
|
|
107
148
|
[tool.coverage.report]
|
|
@@ -130,6 +171,17 @@ exclude_lines = [
|
|
|
130
171
|
addopts = "-ra -q --doctest-glob='*.md' --strict-markers --strict-config"
|
|
131
172
|
asyncio_default_fixture_loop_scope = "function"
|
|
132
173
|
asyncio_mode = "auto"
|
|
174
|
+
filterwarnings = [
|
|
175
|
+
"ignore::DeprecationWarning:pkg_resources.*",
|
|
176
|
+
"ignore:pkg_resources is deprecated as an API:DeprecationWarning",
|
|
177
|
+
"ignore::DeprecationWarning:pkg_resources",
|
|
178
|
+
"ignore::DeprecationWarning:google.rpc",
|
|
179
|
+
"ignore::DeprecationWarning:google.gcloud",
|
|
180
|
+
"ignore::DeprecationWarning:google.iam",
|
|
181
|
+
"ignore::DeprecationWarning:google",
|
|
182
|
+
"ignore::DeprecationWarning:websockets.connection",
|
|
183
|
+
"ignore::DeprecationWarning:websockets.legacy",
|
|
184
|
+
]
|
|
133
185
|
testpaths = ["tests"]
|
|
134
186
|
xfail_strict = true
|
|
135
187
|
|
|
@@ -175,45 +227,19 @@ reportUnnecessaryTypeIgnoreComments = true
|
|
|
175
227
|
strict-imports = false
|
|
176
228
|
|
|
177
229
|
[tool.ruff]
|
|
178
|
-
|
|
179
|
-
"A", # flake8-builtins
|
|
180
|
-
"B", # flake8-bugbear
|
|
181
|
-
"BLE", # flake8-blind-except
|
|
182
|
-
"C4", # flake8-comprehensions
|
|
183
|
-
"C90", # mccabe
|
|
184
|
-
"D", # pydocstyle
|
|
185
|
-
"DJ", # flake8-django
|
|
186
|
-
"DTZ", # flake8-datetimez
|
|
187
|
-
"E", # pycodestyle errors
|
|
188
|
-
"ERA", # eradicate
|
|
189
|
-
"EXE", # flake8-executable
|
|
190
|
-
"F", # pyflakes
|
|
191
|
-
"G", # flake8-logging-format
|
|
192
|
-
"I", # isort
|
|
193
|
-
"ICN", # flake8-import-conventions
|
|
194
|
-
"ISC", # flake8-implicit-str-concat
|
|
195
|
-
"N", # pep8-naming
|
|
196
|
-
"PIE", # flake8-pie
|
|
197
|
-
"PLC", # pylint - convention
|
|
198
|
-
"PLE", # pylint - error
|
|
199
|
-
"PLW", # pylint - warning
|
|
200
|
-
"PTH", # flake8-use-pathlib
|
|
201
|
-
"Q", # flake8-quotes
|
|
202
|
-
"RET", # flake8-return
|
|
203
|
-
"RUF", # Ruff-specific rules
|
|
204
|
-
"S", # flake8-bandit
|
|
205
|
-
"SIM", # flake8-simplify
|
|
206
|
-
"T10", # flake8-debugger
|
|
207
|
-
"T20", # flake8-print
|
|
208
|
-
"TC", # flake8-type-checking
|
|
209
|
-
"TID", # flake8-tidy-imports
|
|
210
|
-
"UP", # pyupgrade
|
|
211
|
-
"W", # pycodestyle - warning
|
|
212
|
-
"YTT", # flake8-2020
|
|
213
|
-
]
|
|
214
|
-
|
|
230
|
+
exclude = [".venv", "node_modules"]
|
|
215
231
|
line-length = 120
|
|
216
|
-
|
|
232
|
+
src = ["sqlspec", "tests", "docs/examples", "tools"]
|
|
233
|
+
target-version = "py39"
|
|
234
|
+
|
|
235
|
+
[tool.ruff.format]
|
|
236
|
+
docstring-code-format = true
|
|
237
|
+
docstring-code-line-length = 60
|
|
238
|
+
|
|
239
|
+
[tool.ruff.lint]
|
|
240
|
+
extend-safe-fixes = ["TC"]
|
|
241
|
+
fixable = ["ALL"]
|
|
242
|
+
ignore = [
|
|
217
243
|
"A003", # flake8-builtins - class attribute {name} is shadowing a python builtin
|
|
218
244
|
"B010", # flake8-bugbear - do not call setattr with a constant attribute value
|
|
219
245
|
"D100", # pydocstyle - missing docstring in public module
|
|
@@ -231,9 +257,18 @@ lint.ignore = [
|
|
|
231
257
|
"PLW2901", # pylint - for loop variable overwritten by assignment target
|
|
232
258
|
"RUF012", # Ruff-specific rule - annotated with classvar
|
|
233
259
|
"ISC001", # Ruff formatter incompatible
|
|
260
|
+
"A005", # flake8 - Module `x` shadows a Python standard-library module
|
|
261
|
+
"PLC0415", # pylint - `import` should be at the top of the file
|
|
262
|
+
"FA100", # Add `from __future__ import annotations` to simplify
|
|
263
|
+
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed
|
|
264
|
+
"FBT001", # Boolean-typed positional argument in function definition
|
|
265
|
+
"FBT002", # Boolean default positional argument in function definition
|
|
266
|
+
"PLR0913", # pylint - Too many arguments in function definition
|
|
267
|
+
"ARG002", # Unused method argument
|
|
268
|
+
"ARG001", # Unused function argument
|
|
269
|
+
"CPY001", # pycodestyle - Missing Copywrite notice at the top of the file
|
|
234
270
|
]
|
|
235
|
-
|
|
236
|
-
target-version = "py39"
|
|
271
|
+
select = ["ALL"]
|
|
237
272
|
|
|
238
273
|
[tool.ruff.lint.pydocstyle]
|
|
239
274
|
convention = "google"
|
|
@@ -273,73 +308,12 @@ known-first-party = ["sqlspec", "tests"]
|
|
|
273
308
|
"SIM",
|
|
274
309
|
"TC",
|
|
275
310
|
"TRY",
|
|
311
|
+
"PT012",
|
|
312
|
+
"INP001",
|
|
276
313
|
]
|
|
277
|
-
"tools/**/*.*" = ["D", "ARG", "EM", "TRY", "G", "FBT", "S603", "F811", "PLW0127"]
|
|
314
|
+
"tools/**/*.*" = ["D", "ARG", "EM", "TRY", "G", "FBT", "S603", "F811", "PLW0127", "PLR0911"]
|
|
278
315
|
"tools/prepare_release.py" = ["S603", "S607"]
|
|
279
316
|
|
|
280
|
-
[tool.ruff.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
[tool.git-cliff.changelog]
|
|
285
|
-
body = """
|
|
286
|
-
{% if version %}\
|
|
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") }}>`_
|
|
288
|
-
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
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") }}>`_
|
|
290
|
-
{% else %}\
|
|
291
|
-
[unreleased]
|
|
292
|
-
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
293
|
-
{% endif %}\
|
|
294
|
-
{% if previous %}\
|
|
295
|
-
{% if previous.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 }}>`_
|
|
299
|
-
{% endif %}\
|
|
300
|
-
{% endif %}\
|
|
301
|
-
{% for group, commits in commits | group_by(attribute="group") %}
|
|
302
|
-
{{ group | upper_first }}
|
|
303
|
-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
304
|
-
{% for commit in commits %}
|
|
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 }})\
|
|
306
|
-
{% for footer in commit.footers -%}
|
|
307
|
-
, {{ footer.token }}{{ footer.separator }}{{ footer.value }}\
|
|
308
|
-
{% endfor %}\
|
|
309
|
-
{% endfor %}
|
|
310
|
-
{% endfor %}\n
|
|
311
|
-
"""
|
|
312
|
-
footer = """
|
|
313
|
-
Type Lens Changelog
|
|
314
|
-
"""
|
|
315
|
-
header = """
|
|
316
|
-
=========
|
|
317
|
-
Changelog
|
|
318
|
-
=========\n
|
|
319
|
-
All commits to this project will be documented in this file.\n
|
|
320
|
-
"""
|
|
321
|
-
trim = true
|
|
322
|
-
|
|
323
|
-
[tool.git-cliff.git]
|
|
324
|
-
commit_parsers = [
|
|
325
|
-
{ message = "^feat", group = "Features" },
|
|
326
|
-
{ message = "^fix", group = "Bug Fixes" },
|
|
327
|
-
{ message = "^doc", group = "Documentation" },
|
|
328
|
-
{ message = "^perf", group = "Performance" },
|
|
329
|
-
{ message = "^refactor", group = "Refactor" },
|
|
330
|
-
{ message = "^style", group = "Styling" },
|
|
331
|
-
{ message = "^test", group = "Testing" },
|
|
332
|
-
{ message = "^chore\\(release\\): prepare for", skip = true },
|
|
333
|
-
{ message = "^chore", group = "Miscellaneous Tasks" },
|
|
334
|
-
{ body = ".*security", group = "Security" },
|
|
335
|
-
]
|
|
336
|
-
conventional_commits = true
|
|
337
|
-
filter_commits = false
|
|
338
|
-
filter_unconventional = true
|
|
339
|
-
ignore_tags = ""
|
|
340
|
-
protect_breaking_commits = false
|
|
341
|
-
skip_tags = "v0.1.0-beta.1"
|
|
342
|
-
sort_commits = "oldest"
|
|
343
|
-
split_commits = false
|
|
344
|
-
tag_pattern = "v[0-9]*"
|
|
345
|
-
topo_order = false
|
|
317
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
318
|
+
# Disallow all relative imports.
|
|
319
|
+
ban-relative-imports = "all"
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
"""Metadata for the Project."""
|
|
2
2
|
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
3
|
from importlib.metadata import PackageNotFoundError, metadata, version
|
|
6
4
|
|
|
7
|
-
__all__ =
|
|
5
|
+
__all__ = ("__project__", "__version__")
|
|
8
6
|
|
|
9
7
|
try:
|
|
10
8
|
__version__ = version("sqlspec")
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import enum
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from sqlspec._typing import PYDANTIC_INSTALLED, BaseModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _type_to_string(value: Any) -> str: # pragma: no cover
|
|
9
|
+
if isinstance(value, datetime.datetime):
|
|
10
|
+
return convert_datetime_to_gmt_iso(value)
|
|
11
|
+
if isinstance(value, datetime.date):
|
|
12
|
+
return convert_date_to_iso(value)
|
|
13
|
+
if isinstance(value, enum.Enum):
|
|
14
|
+
return str(value.value)
|
|
15
|
+
if PYDANTIC_INSTALLED and isinstance(value, BaseModel):
|
|
16
|
+
return value.model_dump_json()
|
|
17
|
+
try:
|
|
18
|
+
val = str(value)
|
|
19
|
+
except Exception as exc:
|
|
20
|
+
raise TypeError from exc
|
|
21
|
+
return val
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
from msgspec.json import Decoder, Encoder
|
|
26
|
+
|
|
27
|
+
encoder, decoder = Encoder(enc_hook=_type_to_string), Decoder()
|
|
28
|
+
decode_json = decoder.decode
|
|
29
|
+
|
|
30
|
+
def encode_json(data: Any) -> str: # pragma: no cover
|
|
31
|
+
return encoder.encode(data).decode("utf-8")
|
|
32
|
+
|
|
33
|
+
except ImportError:
|
|
34
|
+
try:
|
|
35
|
+
from orjson import ( # pyright: ignore[reportMissingImports]
|
|
36
|
+
OPT_NAIVE_UTC, # pyright: ignore[reportUnknownVariableType]
|
|
37
|
+
OPT_SERIALIZE_NUMPY, # pyright: ignore[reportUnknownVariableType]
|
|
38
|
+
OPT_SERIALIZE_UUID, # pyright: ignore[reportUnknownVariableType]
|
|
39
|
+
)
|
|
40
|
+
from orjson import dumps as _encode_json # pyright: ignore[reportUnknownVariableType,reportMissingImports]
|
|
41
|
+
from orjson import loads as decode_json # type: ignore[no-redef,assignment,unused-ignore]
|
|
42
|
+
|
|
43
|
+
def encode_json(data: Any) -> str: # pragma: no cover
|
|
44
|
+
return _encode_json(
|
|
45
|
+
data,
|
|
46
|
+
default=_type_to_string,
|
|
47
|
+
option=OPT_SERIALIZE_NUMPY | OPT_NAIVE_UTC | OPT_SERIALIZE_UUID,
|
|
48
|
+
).decode("utf-8")
|
|
49
|
+
|
|
50
|
+
except ImportError:
|
|
51
|
+
from json import dumps as encode_json # type: ignore[assignment]
|
|
52
|
+
from json import loads as decode_json # type: ignore[assignment]
|
|
53
|
+
|
|
54
|
+
__all__ = (
|
|
55
|
+
"convert_date_to_iso",
|
|
56
|
+
"convert_datetime_to_gmt_iso",
|
|
57
|
+
"decode_json",
|
|
58
|
+
"encode_json",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def convert_datetime_to_gmt_iso(dt: datetime.datetime) -> str: # pragma: no cover
|
|
63
|
+
"""Handle datetime serialization for nested timestamps."""
|
|
64
|
+
if not dt.tzinfo:
|
|
65
|
+
dt = dt.replace(tzinfo=datetime.timezone.utc)
|
|
66
|
+
return dt.isoformat().replace("+00:00", "Z")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def convert_date_to_iso(dt: datetime.date) -> str: # pragma: no cover
|
|
70
|
+
"""Handle datetime serialization for nested timestamps."""
|
|
71
|
+
return dt.isoformat()
|