sqlmodel-crud-utilities 0.0.1b0__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.
- sqlmodel_crud_utilities-0.0.1b0/LICENSE +21 -0
- sqlmodel_crud_utilities-0.0.1b0/PKG-INFO +331 -0
- sqlmodel_crud_utilities-0.0.1b0/README.md +304 -0
- sqlmodel_crud_utilities-0.0.1b0/pyproject.toml +107 -0
- sqlmodel_crud_utilities-0.0.1b0/setup.cfg +4 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utilities.egg-info/PKG-INFO +331 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utilities.egg-info/SOURCES.txt +14 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utilities.egg-info/dependency_links.txt +1 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utilities.egg-info/requires.txt +14 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utilities.egg-info/top_level.txt +1 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utils/__init__.py +0 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utils/a_sync.py +554 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utils/sync.py +555 -0
- sqlmodel_crud_utilities-0.0.1b0/sqlmodel_crud_utils/utils.py +45 -0
- sqlmodel_crud_utilities-0.0.1b0/tests/test_async_utils.py +1001 -0
- sqlmodel_crud_utilities-0.0.1b0/tests/test_sync_utils.py +815 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Francis Secada
|
|
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.
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sqlmodel_crud_utilities
|
|
3
|
+
Version: 0.0.1b0
|
|
4
|
+
Summary: A set of CRUD utilities to expedite operations with SQLModel
|
|
5
|
+
Author-email: Francis Secada <francis.secada@gmail.com>
|
|
6
|
+
License-Expression: MIT AND (Apache-2.0 OR BSD-2-Clause)
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: annotated-types==0.7.0
|
|
13
|
+
Requires-Dist: colorama==0.4.6
|
|
14
|
+
Requires-Dist: greenlet==3.1.1
|
|
15
|
+
Requires-Dist: loguru==0.7.3
|
|
16
|
+
Requires-Dist: pydantic-core==2.33.1
|
|
17
|
+
Requires-Dist: pydantic==2.11.3
|
|
18
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
|
19
|
+
Requires-Dist: python-dotenv==1.1.0
|
|
20
|
+
Requires-Dist: six==1.17.0
|
|
21
|
+
Requires-Dist: sqlalchemy==2.0.40
|
|
22
|
+
Requires-Dist: sqlmodel==0.0.24
|
|
23
|
+
Requires-Dist: typing-extensions==4.13.1
|
|
24
|
+
Requires-Dist: typing-inspection==0.4.0
|
|
25
|
+
Requires-Dist: win32-setctime==1.2.0
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
<div align="left" style="position: relative;">
|
|
29
|
+
<img src="https://raw.githubusercontent.com/PKief/vscode-material-icon-theme/ec559a9f6bfd399b82bb44393651661b08aaf7ba/icons/folder-markdown-open.svg" align="right" width="30%" style="margin: -20px 0 0 20px;">
|
|
30
|
+
<h1>SQLMODEL_CRUD_UTILS</h1>
|
|
31
|
+
<p align="left">
|
|
32
|
+
<em>A set of CRUD (Create, Read, Update, Delete) utilities designed to
|
|
33
|
+
streamline and expedite common database operations when using SQLModel, offering both synchronous and asynchronous support.</em>
|
|
34
|
+
</p>
|
|
35
|
+
<p align="left">
|
|
36
|
+
<!-- Add relevant badges here if/when hosted publicly, e.g., PyPI version, build status, coverage -->
|
|
37
|
+
<!-- Example:
|
|
38
|
+
<a href="https://pypi.org/project/sqlmodel-crud-utils/"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/sqlmodel-crud-utils"></a>
|
|
39
|
+
<a href="https://github.com/YOUR_USERNAME/sqlmodel-crud-utils/actions/workflows/release.yml"><img alt="CI Status" src="https://github.com/YOUR_USERNAME/sqlmodel-crud-utils/actions/workflows/release.yml/badge.svg"></a>
|
|
40
|
+
<a href="https://codecov.io/gh/YOUR_USERNAME/sqlmodel-crud-utils"><img src="https://codecov.io/gh/YOUR_USERNAME/sqlmodel-crud-utils/branch/main/graph/badge.svg"/></a>
|
|
41
|
+
-->
|
|
42
|
+
</p>
|
|
43
|
+
<p align="left">Built with the tools and technologies:</p>
|
|
44
|
+
<p align="left">
|
|
45
|
+
<img src="https://img.shields.io/badge/Python-3776AB.svg?style=default&logo=Python&logoColor=white" alt="Python">
|
|
46
|
+
<img src="https://img.shields.io/badge/SQLModel-488efc.svg?style=default&logo=Python&logoColor=white" alt="SQLModel">
|
|
47
|
+
<img src="https://img.shields.io/badge/SQLAlchemy-D71F00.svg?style=default&logo=Python&logoColor=white" alt="SQLAlchemy">
|
|
48
|
+
<img src="https://img.shields.io/badge/pytest-0A9EDC.svg?style=default&logo=pytest&logoColor=white" alt="pytest">
|
|
49
|
+
<img src="https://img.shields.io/badge/uv-43ccAC.svg?style=default&logo=Python&logoColor=white" alt="uv">
|
|
50
|
+
</p>
|
|
51
|
+
</div>
|
|
52
|
+
<br clear="right">
|
|
53
|
+
|
|
54
|
+
## Table of Contents
|
|
55
|
+
|
|
56
|
+
- [ Overview](#-overview)
|
|
57
|
+
- [Features](#-features)
|
|
58
|
+
- [ Project Structure](#-project-structure)
|
|
59
|
+
- [ Project Index](#-project-index)
|
|
60
|
+
- [ Getting Started](#-getting-started)
|
|
61
|
+
- [ Prerequisites](#-prerequisites)
|
|
62
|
+
- [ Configuration](#-configuration)
|
|
63
|
+
- [ Installation](#-installation)
|
|
64
|
+
- [ Usage](#-usage)
|
|
65
|
+
- [ Testing](#-testing)
|
|
66
|
+
- [ Project Roadmap](#-project-roadmap)
|
|
67
|
+
- [ Contributing](#-contributing)
|
|
68
|
+
- [ License](#-license)
|
|
69
|
+
- [ Acknowledgments](#-acknowledgments)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Overview
|
|
74
|
+
`sqlmodel-crud-utils` provides a convenient layer on top of SQLModel and SQLAlchemy to simplify common database interactions. It offers both synchronous and asynchronous functions for creating, reading, updating, and deleting data, along with helpers for bulk operations, filtering, pagination, and relationship loading. The goal is to reduce boilerplate code in
|
|
75
|
+
projects using SQLModel.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Features
|
|
80
|
+
|
|
81
|
+
- **Sync & Async Support:** Provides parallel functions in `sqlmodel_crud_utils.sync` and `sqlmodel_crud_utils.a_sync`.
|
|
82
|
+
- **Simplified CRUD:** Offers high-level functions:
|
|
83
|
+
- `get_one_or_create`:
|
|
84
|
+
Retrieves an existing record or creates a new one.
|
|
85
|
+
- `get_row`: Fetches a single row by primary key.
|
|
86
|
+
- `get_rows`: Fetches multiple rows with flexible filtering, sorting, and pagination.
|
|
87
|
+
- `get_rows_within_id_list`: Fetches rows matching a list of primary keys.
|
|
88
|
+
- `update_row`: Updates fields of an existing row.
|
|
89
|
+
- `delete_row`: Deletes a row by primary key.
|
|
90
|
+
- `write_row`: Inserts a single new row.
|
|
91
|
+
- `insert_data_rows`: Inserts multiple new rows with fallback for individual insertion on bulk failure.
|
|
92
|
+
- `bulk_upsert_mappings`: Performs bulk insert-or-update operations (dialect-aware).
|
|
93
|
+
- **Relationship Loading:** Supports eager loading (`selectinload`) and lazy loading (`lazyload`) via parameters in `get_row` and `get_rows`.
|
|
94
|
+
- **Flexible Filtering:** `get_rows` supports filtering by exact matches (`filter_by`) and common comparisons (`__like`, `__gte`, `__lte`, `__gt`, `__lt`, `__in`) using keyword arguments.
|
|
95
|
+
- **Pagination:** Built-in pagination for `get_rows`.
|
|
96
|
+
- **Dialect-Specific Upsert:** Automatically uses the correct `upsert` syntax (e.g., `ON CONFLICT DO UPDATE` for PostgreSQL/SQLite) based on the `SQL_DIALECT` environment variable.
|
|
97
|
+
- **Error Handling:** Includes basic error logging via `loguru` and session rollback on exceptions.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Project Structure
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
└── sqlmodel_crud_utils/
|
|
106
|
+
├── __init__.py
|
|
107
|
+
├── __pycache__
|
|
108
|
+
│ ├── __init__.cpython-313.pyc
|
|
109
|
+
│ ├── a_sync.cpython-313.pyc
|
|
110
|
+
│ ├── sync.cpython-313.pyc
|
|
111
|
+
│ └── utils.cpython-313.pyc
|
|
112
|
+
├── a_sync.py
|
|
113
|
+
├── sync.py
|
|
114
|
+
└── utils.py
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### Project Index
|
|
119
|
+
<details open>
|
|
120
|
+
<summary><b><code>sqlmodel_crud_utils/</code></b></summary>
|
|
121
|
+
<details> <!-- __root__ Submodule -->
|
|
122
|
+
<summary><b>__root__</b></summary>
|
|
123
|
+
<blockquote>
|
|
124
|
+
<table>
|
|
125
|
+
<tr>
|
|
126
|
+
<td><b><a href='sqlmodel_crud_utils/blob/master/a_sync.py'>a_sync.py</a></b></td>
|
|
127
|
+
<td>Contains asynchronous versions of the CRUD utility functions, designed for use with `asyncio` and async database drivers (e.g., `aiosqlite`, `asyncpg`).</td>
|
|
128
|
+
</tr>
|
|
129
|
+
<tr>
|
|
130
|
+
<td><b><a href='sqlmodel_crud_utils/blob/master/sync.py'>sync.py</a></b></td>
|
|
131
|
+
<td>Contains synchronous versions of the CRUD utility functions for standard execution environments.</td>
|
|
132
|
+
</tr>
|
|
133
|
+
<tr>
|
|
134
|
+
<td><b><a href='sqlmodel_crud_utils/blob/master/utils.py'>utils.py</a></b></td>
|
|
135
|
+
<td>Provides shared helper functions used by both `sync.py` and `a_sync.py`, such as environment variable retrieval and dynamic dialect-specific import logic for upsert statements.</td>
|
|
136
|
+
</tr>
|
|
137
|
+
</table>
|
|
138
|
+
</blockquote>
|
|
139
|
+
</details>
|
|
140
|
+
</details>
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
## Getting Started
|
|
147
|
+
|
|
148
|
+
### Prerequisites
|
|
149
|
+
|
|
150
|
+
- **Python:** Version 3.8+ recommended.
|
|
151
|
+
- **Database:** A SQLAlchemy-compatible database (e.g., PostgreSQL, SQLite, MySQL).
|
|
152
|
+
- **SQLModel:** Your project should be using SQLModel for ORM definitions.
|
|
153
|
+
|
|
154
|
+
### Configuration
|
|
155
|
+
|
|
156
|
+
This package requires the `SQL_DIALECT` environment variable to be set for the `upsert` functionality to work correctly across different database backends.
|
|
157
|
+
|
|
158
|
+
Set it in your environment:
|
|
159
|
+
```bash
|
|
160
|
+
export SQL_DIALECT=postgresql # or sqlite, mysql, etc
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Or add it to a `.env` file in your project root (will be loaded automatically via `python-dotenv`):
|
|
164
|
+
|
|
165
|
+
```.env
|
|
166
|
+
SQL_DIALECT=postgresql
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Refer to SQLAlchemy Dialects for a list of supported dialect names.
|
|
170
|
+
|
|
171
|
+
### Installation
|
|
172
|
+
|
|
173
|
+
**Install from PyPI (Recommended):**
|
|
174
|
+
```bash
|
|
175
|
+
pip install sqlmodel-crud-utils
|
|
176
|
+
# Or using uv:
|
|
177
|
+
uv pip install sqlmodel-crud-utils
|
|
178
|
+
```
|
|
179
|
+
**Build from source:**
|
|
180
|
+
|
|
181
|
+
1. Clone the sqlmodel_crud_utils repository:
|
|
182
|
+
```sh
|
|
183
|
+
git clone https://github.com/fsecada01/SQLModel-CRUD-Utilities.git
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
2. Navigate to the project directory:
|
|
187
|
+
```sh
|
|
188
|
+
cd sqlmodel_crud_utils
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
3. Install the project dependencies:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
uv pip install -r core_requirements.txt
|
|
195
|
+
# For testing/development
|
|
196
|
+
uv pip install -r dev_requirements.txt
|
|
197
|
+
```
|
|
198
|
+
*(Alternatively, use `pip install -r requirements.txt && pip install .`)*
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
### Usage
|
|
202
|
+
|
|
203
|
+
Import the desired functions from either the `sync` or `a_sync` module and use them with your SQLModel session and models.
|
|
204
|
+
|
|
205
|
+
**Example (Synchronous):**
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
|
|
209
|
+
from sqlmodel import Session, SQLModel, create_engine, Field
|
|
210
|
+
from sqlmodel_crud_utils.sync import get_one_or_create, get_rows
|
|
211
|
+
|
|
212
|
+
# Assume MyModel is defined and engine is created
|
|
213
|
+
|
|
214
|
+
class MyModel(SQLModel, table=True):
|
|
215
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
216
|
+
name: str = Field(index=True)
|
|
217
|
+
value: int | None = None
|
|
218
|
+
|
|
219
|
+
DATABASE_URL = "sqlite:///./mydatabase.db"
|
|
220
|
+
engine = create_engine(DATABASE_URL)
|
|
221
|
+
|
|
222
|
+
SQLModel.metadata.create_all(engine)
|
|
223
|
+
|
|
224
|
+
with Session(engine) as session:
|
|
225
|
+
# Get or create an instance
|
|
226
|
+
instance, created = get_one_or_create(
|
|
227
|
+
session_inst=session, model=MyModel,
|
|
228
|
+
name="Test Item", create_method_kwargs={"value": 123}
|
|
229
|
+
)
|
|
230
|
+
print(f"Instance ID: {instance.id}, Was created: {not created}")
|
|
231
|
+
|
|
232
|
+
# Get rows matching criteria
|
|
233
|
+
success, rows = get_rows(
|
|
234
|
+
session_inst=session,
|
|
235
|
+
model=MyModel,
|
|
236
|
+
value__gte=100,
|
|
237
|
+
sort_field="name"
|
|
238
|
+
)
|
|
239
|
+
if success:
|
|
240
|
+
print(f"Found {len(rows)} rows with value >= 100:")
|
|
241
|
+
for row in rows:
|
|
242
|
+
print(f"- {row.name} (ID: {row.id})")
|
|
243
|
+
```
|
|
244
|
+
*(See `sync.py` and `a_sync.py` docstrings or the full README examples from previous interactions for more detailed usage)*
|
|
245
|
+
|
|
246
|
+
### Testing
|
|
247
|
+
Ensure development dependencies are installed (`uv pip install -r dev_requirements.txt` or `pip install -r dev_requirements.txt`).
|
|
248
|
+
|
|
249
|
+
Run the test suite using pytest:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
python -m pytest
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
This will execute all tests in the `tests/` directory and provide coverage information based on the `pytest.ini` or `pyproject.toml` configuration.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Project Roadmap
|
|
260
|
+
|
|
261
|
+
- [x] **Alpha Release**: Initial working version with core CRUD functions.
|
|
262
|
+
- [x] **Testing**: Achieve 100% test coverage via Pytest.
|
|
263
|
+
- [x] **CI/CD**: Implement GitHub Actions for automated testing, build, and release.
|
|
264
|
+
- [x] **Beta Release**: Refine features based on initial testing and usage.
|
|
265
|
+
- [ ] **Community Feedback**: Solicit feedback from users.
|
|
266
|
+
- [ ] **360 Development Review**: Comprehensive internal review of code, docs, and tests.
|
|
267
|
+
- [ ] **Official 1.0 Release**: Stable release suitable for production use.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Contributing
|
|
272
|
+
|
|
273
|
+
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
|
|
274
|
+
|
|
275
|
+
- **💬 [Join the Discussions](https://github.com/fsecada01/SQLModel-CRUD-Utilities/discussions)**: Share your insights, provide feedback, or ask questions.
|
|
276
|
+
- **🐛 [Report Issues](https://github.com/fsecada01/SQLModel-CRUD-Utilities/issues)**: Submit bugs found or log feature requests for the `sqlmodel_crud_utils` project.
|
|
277
|
+
- **💡 [Submit Pull Requests](https://github.com/fsecada01/SQLModel-CRUD-Utilities/blob/main/CONTRIBUTING.md)**: Review open PRs, and submit your own PRs.
|
|
278
|
+
<details closed>
|
|
279
|
+
<summary>Contributing Guidelines</summary>
|
|
280
|
+
|
|
281
|
+
1. **Fork the Repository**: Start by forking the project repository to your GitHub account.
|
|
282
|
+
2. **Clone Locally**: Clone the forked repository to your local machine.
|
|
283
|
+
```bash
|
|
284
|
+
git clone https://github.com/fsecada01/SQLModel-CRUD-Utilities.git
|
|
285
|
+
```
|
|
286
|
+
3. **Create a New Branch**: Always work on a new branch for your changes.
|
|
287
|
+
```bash
|
|
288
|
+
git checkout -b feature/your-new-feature
|
|
289
|
+
```
|
|
290
|
+
4. **Make Your Changes**: Implement your feature or bug fix. Add tests!
|
|
291
|
+
5. **Test Your Changes**: Run `pytest` to ensure all tests pass.
|
|
292
|
+
6. **Format and Lint**: Ensure code follows project standards (e.g., using `black`, `ruff`, `pre-commit`).
|
|
293
|
+
7. **Commit Your Changes**: Commit with a clear and concise message.
|
|
294
|
+
```bash
|
|
295
|
+
git commit -m "feat: Implement the new feature."
|
|
296
|
+
```
|
|
297
|
+
8. **Push to GitHub**: Push the changes to your forked repository.
|
|
298
|
+
```bash
|
|
299
|
+
git push origin feature/your-new-feature
|
|
300
|
+
```
|
|
301
|
+
9. **Submit a Pull Request**: Create a PR against the main branch of the original repository. Clearly describe your changes.
|
|
302
|
+
10. **Review**: Wait for code review and address any feedback.
|
|
303
|
+
|
|
304
|
+
</details>
|
|
305
|
+
|
|
306
|
+
<details closed>
|
|
307
|
+
<summary>Contributor Graph</summary>
|
|
308
|
+
<br>
|
|
309
|
+
<p align="left">
|
|
310
|
+
<a href="https://github.com/fsecada01/sqlmodel-crud-utils/graphs/contributors">
|
|
311
|
+
<img src="https://contrib.rocks/image?repo=fsecada01/sqlmodel-crud-utils">
|
|
312
|
+
</a>
|
|
313
|
+
</p>
|
|
314
|
+
</details>
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
This project is protected under the **MIT License**. For more details, refer to
|
|
321
|
+
the [LICENSE file](LICENSE).
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Acknowledgments
|
|
326
|
+
|
|
327
|
+
- inspiration drawn from the need to streamline CRUD operations across multiple projects utilizing SQLModel.
|
|
328
|
+
- Built upon the excellent foundations provided by SQLModel and SQLAlchemy.
|
|
329
|
+
- Utilizes Loguru for logging and Factory Boy for test data generation.
|
|
330
|
+
|
|
331
|
+
---
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
<div align="left" style="position: relative;">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/PKief/vscode-material-icon-theme/ec559a9f6bfd399b82bb44393651661b08aaf7ba/icons/folder-markdown-open.svg" align="right" width="30%" style="margin: -20px 0 0 20px;">
|
|
3
|
+
<h1>SQLMODEL_CRUD_UTILS</h1>
|
|
4
|
+
<p align="left">
|
|
5
|
+
<em>A set of CRUD (Create, Read, Update, Delete) utilities designed to
|
|
6
|
+
streamline and expedite common database operations when using SQLModel, offering both synchronous and asynchronous support.</em>
|
|
7
|
+
</p>
|
|
8
|
+
<p align="left">
|
|
9
|
+
<!-- Add relevant badges here if/when hosted publicly, e.g., PyPI version, build status, coverage -->
|
|
10
|
+
<!-- Example:
|
|
11
|
+
<a href="https://pypi.org/project/sqlmodel-crud-utils/"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/sqlmodel-crud-utils"></a>
|
|
12
|
+
<a href="https://github.com/YOUR_USERNAME/sqlmodel-crud-utils/actions/workflows/release.yml"><img alt="CI Status" src="https://github.com/YOUR_USERNAME/sqlmodel-crud-utils/actions/workflows/release.yml/badge.svg"></a>
|
|
13
|
+
<a href="https://codecov.io/gh/YOUR_USERNAME/sqlmodel-crud-utils"><img src="https://codecov.io/gh/YOUR_USERNAME/sqlmodel-crud-utils/branch/main/graph/badge.svg"/></a>
|
|
14
|
+
-->
|
|
15
|
+
</p>
|
|
16
|
+
<p align="left">Built with the tools and technologies:</p>
|
|
17
|
+
<p align="left">
|
|
18
|
+
<img src="https://img.shields.io/badge/Python-3776AB.svg?style=default&logo=Python&logoColor=white" alt="Python">
|
|
19
|
+
<img src="https://img.shields.io/badge/SQLModel-488efc.svg?style=default&logo=Python&logoColor=white" alt="SQLModel">
|
|
20
|
+
<img src="https://img.shields.io/badge/SQLAlchemy-D71F00.svg?style=default&logo=Python&logoColor=white" alt="SQLAlchemy">
|
|
21
|
+
<img src="https://img.shields.io/badge/pytest-0A9EDC.svg?style=default&logo=pytest&logoColor=white" alt="pytest">
|
|
22
|
+
<img src="https://img.shields.io/badge/uv-43ccAC.svg?style=default&logo=Python&logoColor=white" alt="uv">
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
<br clear="right">
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [ Overview](#-overview)
|
|
30
|
+
- [Features](#-features)
|
|
31
|
+
- [ Project Structure](#-project-structure)
|
|
32
|
+
- [ Project Index](#-project-index)
|
|
33
|
+
- [ Getting Started](#-getting-started)
|
|
34
|
+
- [ Prerequisites](#-prerequisites)
|
|
35
|
+
- [ Configuration](#-configuration)
|
|
36
|
+
- [ Installation](#-installation)
|
|
37
|
+
- [ Usage](#-usage)
|
|
38
|
+
- [ Testing](#-testing)
|
|
39
|
+
- [ Project Roadmap](#-project-roadmap)
|
|
40
|
+
- [ Contributing](#-contributing)
|
|
41
|
+
- [ License](#-license)
|
|
42
|
+
- [ Acknowledgments](#-acknowledgments)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Overview
|
|
47
|
+
`sqlmodel-crud-utils` provides a convenient layer on top of SQLModel and SQLAlchemy to simplify common database interactions. It offers both synchronous and asynchronous functions for creating, reading, updating, and deleting data, along with helpers for bulk operations, filtering, pagination, and relationship loading. The goal is to reduce boilerplate code in
|
|
48
|
+
projects using SQLModel.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- **Sync & Async Support:** Provides parallel functions in `sqlmodel_crud_utils.sync` and `sqlmodel_crud_utils.a_sync`.
|
|
55
|
+
- **Simplified CRUD:** Offers high-level functions:
|
|
56
|
+
- `get_one_or_create`:
|
|
57
|
+
Retrieves an existing record or creates a new one.
|
|
58
|
+
- `get_row`: Fetches a single row by primary key.
|
|
59
|
+
- `get_rows`: Fetches multiple rows with flexible filtering, sorting, and pagination.
|
|
60
|
+
- `get_rows_within_id_list`: Fetches rows matching a list of primary keys.
|
|
61
|
+
- `update_row`: Updates fields of an existing row.
|
|
62
|
+
- `delete_row`: Deletes a row by primary key.
|
|
63
|
+
- `write_row`: Inserts a single new row.
|
|
64
|
+
- `insert_data_rows`: Inserts multiple new rows with fallback for individual insertion on bulk failure.
|
|
65
|
+
- `bulk_upsert_mappings`: Performs bulk insert-or-update operations (dialect-aware).
|
|
66
|
+
- **Relationship Loading:** Supports eager loading (`selectinload`) and lazy loading (`lazyload`) via parameters in `get_row` and `get_rows`.
|
|
67
|
+
- **Flexible Filtering:** `get_rows` supports filtering by exact matches (`filter_by`) and common comparisons (`__like`, `__gte`, `__lte`, `__gt`, `__lt`, `__in`) using keyword arguments.
|
|
68
|
+
- **Pagination:** Built-in pagination for `get_rows`.
|
|
69
|
+
- **Dialect-Specific Upsert:** Automatically uses the correct `upsert` syntax (e.g., `ON CONFLICT DO UPDATE` for PostgreSQL/SQLite) based on the `SQL_DIALECT` environment variable.
|
|
70
|
+
- **Error Handling:** Includes basic error logging via `loguru` and session rollback on exceptions.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Project Structure
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
└── sqlmodel_crud_utils/
|
|
79
|
+
├── __init__.py
|
|
80
|
+
├── __pycache__
|
|
81
|
+
│ ├── __init__.cpython-313.pyc
|
|
82
|
+
│ ├── a_sync.cpython-313.pyc
|
|
83
|
+
│ ├── sync.cpython-313.pyc
|
|
84
|
+
│ └── utils.cpython-313.pyc
|
|
85
|
+
├── a_sync.py
|
|
86
|
+
├── sync.py
|
|
87
|
+
└── utils.py
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### Project Index
|
|
92
|
+
<details open>
|
|
93
|
+
<summary><b><code>sqlmodel_crud_utils/</code></b></summary>
|
|
94
|
+
<details> <!-- __root__ Submodule -->
|
|
95
|
+
<summary><b>__root__</b></summary>
|
|
96
|
+
<blockquote>
|
|
97
|
+
<table>
|
|
98
|
+
<tr>
|
|
99
|
+
<td><b><a href='sqlmodel_crud_utils/blob/master/a_sync.py'>a_sync.py</a></b></td>
|
|
100
|
+
<td>Contains asynchronous versions of the CRUD utility functions, designed for use with `asyncio` and async database drivers (e.g., `aiosqlite`, `asyncpg`).</td>
|
|
101
|
+
</tr>
|
|
102
|
+
<tr>
|
|
103
|
+
<td><b><a href='sqlmodel_crud_utils/blob/master/sync.py'>sync.py</a></b></td>
|
|
104
|
+
<td>Contains synchronous versions of the CRUD utility functions for standard execution environments.</td>
|
|
105
|
+
</tr>
|
|
106
|
+
<tr>
|
|
107
|
+
<td><b><a href='sqlmodel_crud_utils/blob/master/utils.py'>utils.py</a></b></td>
|
|
108
|
+
<td>Provides shared helper functions used by both `sync.py` and `a_sync.py`, such as environment variable retrieval and dynamic dialect-specific import logic for upsert statements.</td>
|
|
109
|
+
</tr>
|
|
110
|
+
</table>
|
|
111
|
+
</blockquote>
|
|
112
|
+
</details>
|
|
113
|
+
</details>
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
## Getting Started
|
|
120
|
+
|
|
121
|
+
### Prerequisites
|
|
122
|
+
|
|
123
|
+
- **Python:** Version 3.8+ recommended.
|
|
124
|
+
- **Database:** A SQLAlchemy-compatible database (e.g., PostgreSQL, SQLite, MySQL).
|
|
125
|
+
- **SQLModel:** Your project should be using SQLModel for ORM definitions.
|
|
126
|
+
|
|
127
|
+
### Configuration
|
|
128
|
+
|
|
129
|
+
This package requires the `SQL_DIALECT` environment variable to be set for the `upsert` functionality to work correctly across different database backends.
|
|
130
|
+
|
|
131
|
+
Set it in your environment:
|
|
132
|
+
```bash
|
|
133
|
+
export SQL_DIALECT=postgresql # or sqlite, mysql, etc
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Or add it to a `.env` file in your project root (will be loaded automatically via `python-dotenv`):
|
|
137
|
+
|
|
138
|
+
```.env
|
|
139
|
+
SQL_DIALECT=postgresql
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Refer to SQLAlchemy Dialects for a list of supported dialect names.
|
|
143
|
+
|
|
144
|
+
### Installation
|
|
145
|
+
|
|
146
|
+
**Install from PyPI (Recommended):**
|
|
147
|
+
```bash
|
|
148
|
+
pip install sqlmodel-crud-utils
|
|
149
|
+
# Or using uv:
|
|
150
|
+
uv pip install sqlmodel-crud-utils
|
|
151
|
+
```
|
|
152
|
+
**Build from source:**
|
|
153
|
+
|
|
154
|
+
1. Clone the sqlmodel_crud_utils repository:
|
|
155
|
+
```sh
|
|
156
|
+
git clone https://github.com/fsecada01/SQLModel-CRUD-Utilities.git
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
2. Navigate to the project directory:
|
|
160
|
+
```sh
|
|
161
|
+
cd sqlmodel_crud_utils
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
3. Install the project dependencies:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
uv pip install -r core_requirements.txt
|
|
168
|
+
# For testing/development
|
|
169
|
+
uv pip install -r dev_requirements.txt
|
|
170
|
+
```
|
|
171
|
+
*(Alternatively, use `pip install -r requirements.txt && pip install .`)*
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
### Usage
|
|
175
|
+
|
|
176
|
+
Import the desired functions from either the `sync` or `a_sync` module and use them with your SQLModel session and models.
|
|
177
|
+
|
|
178
|
+
**Example (Synchronous):**
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
|
|
182
|
+
from sqlmodel import Session, SQLModel, create_engine, Field
|
|
183
|
+
from sqlmodel_crud_utils.sync import get_one_or_create, get_rows
|
|
184
|
+
|
|
185
|
+
# Assume MyModel is defined and engine is created
|
|
186
|
+
|
|
187
|
+
class MyModel(SQLModel, table=True):
|
|
188
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
189
|
+
name: str = Field(index=True)
|
|
190
|
+
value: int | None = None
|
|
191
|
+
|
|
192
|
+
DATABASE_URL = "sqlite:///./mydatabase.db"
|
|
193
|
+
engine = create_engine(DATABASE_URL)
|
|
194
|
+
|
|
195
|
+
SQLModel.metadata.create_all(engine)
|
|
196
|
+
|
|
197
|
+
with Session(engine) as session:
|
|
198
|
+
# Get or create an instance
|
|
199
|
+
instance, created = get_one_or_create(
|
|
200
|
+
session_inst=session, model=MyModel,
|
|
201
|
+
name="Test Item", create_method_kwargs={"value": 123}
|
|
202
|
+
)
|
|
203
|
+
print(f"Instance ID: {instance.id}, Was created: {not created}")
|
|
204
|
+
|
|
205
|
+
# Get rows matching criteria
|
|
206
|
+
success, rows = get_rows(
|
|
207
|
+
session_inst=session,
|
|
208
|
+
model=MyModel,
|
|
209
|
+
value__gte=100,
|
|
210
|
+
sort_field="name"
|
|
211
|
+
)
|
|
212
|
+
if success:
|
|
213
|
+
print(f"Found {len(rows)} rows with value >= 100:")
|
|
214
|
+
for row in rows:
|
|
215
|
+
print(f"- {row.name} (ID: {row.id})")
|
|
216
|
+
```
|
|
217
|
+
*(See `sync.py` and `a_sync.py` docstrings or the full README examples from previous interactions for more detailed usage)*
|
|
218
|
+
|
|
219
|
+
### Testing
|
|
220
|
+
Ensure development dependencies are installed (`uv pip install -r dev_requirements.txt` or `pip install -r dev_requirements.txt`).
|
|
221
|
+
|
|
222
|
+
Run the test suite using pytest:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
python -m pytest
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
This will execute all tests in the `tests/` directory and provide coverage information based on the `pytest.ini` or `pyproject.toml` configuration.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Project Roadmap
|
|
233
|
+
|
|
234
|
+
- [x] **Alpha Release**: Initial working version with core CRUD functions.
|
|
235
|
+
- [x] **Testing**: Achieve 100% test coverage via Pytest.
|
|
236
|
+
- [x] **CI/CD**: Implement GitHub Actions for automated testing, build, and release.
|
|
237
|
+
- [x] **Beta Release**: Refine features based on initial testing and usage.
|
|
238
|
+
- [ ] **Community Feedback**: Solicit feedback from users.
|
|
239
|
+
- [ ] **360 Development Review**: Comprehensive internal review of code, docs, and tests.
|
|
240
|
+
- [ ] **Official 1.0 Release**: Stable release suitable for production use.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Contributing
|
|
245
|
+
|
|
246
|
+
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
|
|
247
|
+
|
|
248
|
+
- **💬 [Join the Discussions](https://github.com/fsecada01/SQLModel-CRUD-Utilities/discussions)**: Share your insights, provide feedback, or ask questions.
|
|
249
|
+
- **🐛 [Report Issues](https://github.com/fsecada01/SQLModel-CRUD-Utilities/issues)**: Submit bugs found or log feature requests for the `sqlmodel_crud_utils` project.
|
|
250
|
+
- **💡 [Submit Pull Requests](https://github.com/fsecada01/SQLModel-CRUD-Utilities/blob/main/CONTRIBUTING.md)**: Review open PRs, and submit your own PRs.
|
|
251
|
+
<details closed>
|
|
252
|
+
<summary>Contributing Guidelines</summary>
|
|
253
|
+
|
|
254
|
+
1. **Fork the Repository**: Start by forking the project repository to your GitHub account.
|
|
255
|
+
2. **Clone Locally**: Clone the forked repository to your local machine.
|
|
256
|
+
```bash
|
|
257
|
+
git clone https://github.com/fsecada01/SQLModel-CRUD-Utilities.git
|
|
258
|
+
```
|
|
259
|
+
3. **Create a New Branch**: Always work on a new branch for your changes.
|
|
260
|
+
```bash
|
|
261
|
+
git checkout -b feature/your-new-feature
|
|
262
|
+
```
|
|
263
|
+
4. **Make Your Changes**: Implement your feature or bug fix. Add tests!
|
|
264
|
+
5. **Test Your Changes**: Run `pytest` to ensure all tests pass.
|
|
265
|
+
6. **Format and Lint**: Ensure code follows project standards (e.g., using `black`, `ruff`, `pre-commit`).
|
|
266
|
+
7. **Commit Your Changes**: Commit with a clear and concise message.
|
|
267
|
+
```bash
|
|
268
|
+
git commit -m "feat: Implement the new feature."
|
|
269
|
+
```
|
|
270
|
+
8. **Push to GitHub**: Push the changes to your forked repository.
|
|
271
|
+
```bash
|
|
272
|
+
git push origin feature/your-new-feature
|
|
273
|
+
```
|
|
274
|
+
9. **Submit a Pull Request**: Create a PR against the main branch of the original repository. Clearly describe your changes.
|
|
275
|
+
10. **Review**: Wait for code review and address any feedback.
|
|
276
|
+
|
|
277
|
+
</details>
|
|
278
|
+
|
|
279
|
+
<details closed>
|
|
280
|
+
<summary>Contributor Graph</summary>
|
|
281
|
+
<br>
|
|
282
|
+
<p align="left">
|
|
283
|
+
<a href="https://github.com/fsecada01/sqlmodel-crud-utils/graphs/contributors">
|
|
284
|
+
<img src="https://contrib.rocks/image?repo=fsecada01/sqlmodel-crud-utils">
|
|
285
|
+
</a>
|
|
286
|
+
</p>
|
|
287
|
+
</details>
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## License
|
|
292
|
+
|
|
293
|
+
This project is protected under the **MIT License**. For more details, refer to
|
|
294
|
+
the [LICENSE file](LICENSE).
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Acknowledgments
|
|
299
|
+
|
|
300
|
+
- inspiration drawn from the need to streamline CRUD operations across multiple projects utilizing SQLModel.
|
|
301
|
+
- Built upon the excellent foundations provided by SQLModel and SQLAlchemy.
|
|
302
|
+
- Utilizes Loguru for logging and Factory Boy for test data generation.
|
|
303
|
+
|
|
304
|
+
---
|