Skip to content

Commit 1af5dd1

Browse files
committed
Merge branch 'develop'
2 parents 2c4b16b + 4d23a5c commit 1af5dd1

16 files changed

Lines changed: 171 additions & 224 deletions

CONTRIBUTING.md

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ a smooth collaboration process.
2020
- Adhere to **clean code principles**, such as **SOLID**, **DRY**, and
2121
**KISS**. Avoid unnecessary complexity.
2222
- Use **Active Record** patterns for database interactions where applicable.
23-
- Limit the use of classes unless strictly necessary; prefer functions when
24-
simpler and sufficient.
2523
- Keep contributions small and focused. One feature or fix per pull request.
2624
- Discuss significant changes or enhancements transparently by opening an
2725
issue first.
@@ -33,16 +31,8 @@ a smooth collaboration process.
3331
- Use **Ruff** as the linter and formatter (**Black** could be an alternative).
3432
- Write **NumPy-style docstrings** for all public functions, classes, attributes,
3533
and properties.
36-
- Commit messages and pull requests must follow specific prefixes:
37-
- `ci:` for CI/CD changes.
38-
- `test:` Update tests/* files.
39-
- `dist:` Changes to dependencies, e.g. `requirements.txt`.
40-
- `minor:` Small changes.
41-
- `docs:` Updates to documentation. `doc` is also a valid prefix.
42-
- `fix:` Bug fixes.
43-
- `refactor:` Refactor of existing code.
44-
- `nit:` Small code review changes mainly around style or syntax.
45-
- `feat:` New features.
34+
- Commit messages and pull requests must follow specific prefixes described
35+
[here](#commit-message-format).
4636

4737
## Your First Pull Request
4838

@@ -185,4 +175,5 @@ Before submitting a pull request:
185175
5. Provide a clear and descriptive pull request title and description.
186176
187177
Pull requests titles should be short and descriptive, and should not exceed
188-
72 characters. Also, must follow the specified commit message format.
178+
72 characters. Also, must follow the specified
179+
[commit message format](#commit-message-format).

README.md

Lines changed: 17 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
<!-- omit in toc -->
2727
# SQLActive
2828

29-
SQLActive is a lightweight and asynchronous ActiveRecord-style wrapper for
30-
SQLAlchemy. Bring Django-like queries, automatic timestamps, nested eager
31-
loading, and serialization/deserialization for SQLAlchemy models.
29+
A lightweight and asynchronous ActiveRecord-style wrapper for SQLAlchemy.
30+
Brings Django-like queries, automatic timestamps, nested eager loading, and
31+
serialization/deserialization for SQLAlchemy models.
3232

3333
Heavily inspired by
3434
[sqlalchemy-mixins](https://github.com/absent1706/sqlalchemy-mixins/).
@@ -40,18 +40,14 @@ Visit the [documentation website](https://daireto.github.io/sqlactive/).
4040
- [Features](#features)
4141
- [Requirements](#requirements)
4242
- [Installation](#installation)
43-
- [Usage](#usage)
44-
- [1. Define the Models](#1-define-the-models)
45-
- [2. Initialize the Database](#2-initialize-the-database)
46-
- [3. Perform CRUD Operations](#3-perform-crud-operations)
47-
- [4. Perform Bulk Operations](#4-perform-bulk-operations)
48-
- [5. Perform Queries](#5-perform-queries)
49-
- [6. Manage Timestamps](#6-manage-timestamps)
50-
- [7. Serialization and Deserialization](#7-serialization-and-deserialization)
51-
- [Testing and Linting](#testing-and-linting)
52-
- [Unit Tests](#unit-tests)
53-
- [Coverage](#coverage)
54-
- [Linting](#linting)
43+
- [Quick Start](#quick-start)
44+
- [1. Define the Models](#1-define-the-models)
45+
- [2. Initialize the Database](#2-initialize-the-database)
46+
- [3. Perform CRUD Operations](#3-perform-crud-operations)
47+
- [4. Perform Bulk Operations](#4-perform-bulk-operations)
48+
- [5. Perform Queries](#5-perform-queries)
49+
- [6. Manage Timestamps](#6-manage-timestamps)
50+
- [7. Serialization and Deserialization](#7-serialization-and-deserialization)
5551
- [Documentation](#documentation)
5652
- [Contributing](#contributing)
5753
- [License](#license)
@@ -71,8 +67,9 @@ Visit the [documentation website](https://daireto.github.io/sqlactive/).
7167

7268
## Requirements
7369

74-
- Python 3.10+
75-
- sqlalchemy 2.0+
70+
- `Python>=3.10`
71+
- `SQLAlchemy>=2.0.0`
72+
- `typing_extensions>=4.5.0 (for Python<3.11)`
7673

7774
## Installation
7875

@@ -83,7 +80,7 @@ You can simply install sqlactive from
8380
pip install sqlactive
8481
```
8582

86-
## Usage
83+
## Quick Start
8784

8885
### 1. Define the Models
8986

@@ -447,71 +444,6 @@ user = User.from_json(user_json)
447444
user.name # John Doe
448445
```
449446
450-
## Testing and Linting
451-
452-
### Unit Tests
453-
454-
To run the tests, simply run the following command from the root directory:
455-
456-
```bash
457-
python -m unittest discover -s tests -t .
458-
```
459-
460-
To run a specific test, use the following command:
461-
462-
```bash
463-
python -m unittest tests.<test_name>
464-
```
465-
466-
**Available tests**
467-
- `test_active_record.py`
468-
- `test_async_query.py`
469-
- `test_db_connection.py`
470-
- `test_execute.py`
471-
- `test_inspection.py`
472-
- `test_serialization.py`
473-
- `test_smart_query.py`
474-
475-
### Coverage
476-
477-
First, install the `coverage` package:
478-
479-
```bash
480-
pip install coverage
481-
```
482-
483-
To check the coverage, run the following command:
484-
485-
```bash
486-
python -m coverage run -m unittest discover -s tests -t .
487-
```
488-
489-
To generate the coverage report, run the following command:
490-
491-
```bash
492-
python -m coverage report -m
493-
```
494-
495-
To generate the HTML report, run the following command:
496-
497-
```bash
498-
python -m coverage html -d htmlcov
499-
```
500-
501-
### Linting
502-
503-
First, install the `ruff` package:
504-
505-
```bash
506-
pip install ruff
507-
```
508-
509-
To check the code style, run the following command:
510-
511-
```bash
512-
python -m ruff check .
513-
```
514-
515447
## Documentation
516448
517449
Find the complete documentation [here](https://daireto.github.io/sqlactive/).
@@ -522,7 +454,8 @@ Please read the [contribution guidelines](CONTRIBUTING.md).
522454
523455
## License
524456
525-
This project is licensed under the [MIT License](LICENSE).
457+
This project is licensed under the MIT License - see the [LICENSE](LICENSE)
458+
file for details.
526459
527460
## Support
528461

docs/about/contributing.md

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ a smooth collaboration process.
2020
- Adhere to **clean code principles**, such as **SOLID**, **DRY**, and
2121
**KISS**. Avoid unnecessary complexity.
2222
- Use **Active Record** patterns for database interactions where applicable.
23-
- Limit the use of classes unless strictly necessary; prefer functions when
24-
simpler and sufficient.
2523
- Keep contributions small and focused. One feature or fix per pull request.
2624
- Discuss significant changes or enhancements transparently by opening an
2725
issue first.
@@ -33,16 +31,8 @@ a smooth collaboration process.
3331
- Use **Ruff** as the linter and formatter (**Black** could be an alternative).
3432
- Write **NumPy-style docstrings** for all public functions, classes, attributes,
3533
and properties.
36-
- Commit messages and pull requests must follow specific prefixes:
37-
- `ci:` for CI/CD changes.
38-
- `test:` Update tests/* files.
39-
- `dist:` Changes to dependencies, e.g. `requirements.txt`.
40-
- `minor:` Small changes.
41-
- `docs:` Updates to documentation. `doc` is also a valid prefix.
42-
- `fix:` Bug fixes.
43-
- `refactor:` Refactor of existing code.
44-
- `nit:` Small code review changes mainly around style or syntax.
45-
- `feat:` New features.
34+
- Commit messages and pull requests must follow specific prefixes described
35+
[here](#commit-message-format).
4636

4737
## Your First Pull Request
4838

@@ -185,4 +175,5 @@ Before submitting a pull request:
185175
5. Provide a clear and descriptive pull request title and description.
186176
187177
Pull requests titles should be short and descriptive, and should not exceed
188-
72 characters. Also, must follow the specified commit message format.
178+
72 characters. Also, must follow the specified
179+
[commit message format](#commit-message-format).

docs/api/async-query.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,14 @@ async def execute() -> Result[Any]
226226
#### scalars
227227

228228
```python
229-
async def scalars() -> ScalarResult[_T]
229+
async def scalars() -> ScalarResult[T]
230230
```
231231

232232
> Returns a `sqlalchemy.engine.ScalarResult` instance containing all rows.
233233

234234
> **Returns**
235235

236-
> - `sqlalchemy.engine.ScalarResult[_T]`: Result instance containing
236+
> - `sqlalchemy.engine.ScalarResult[T]`: Result instance containing
237237
> all scalars.
238238

239239
> **Examples**
@@ -256,7 +256,7 @@ async def scalars() -> ScalarResult[_T]
256256
#### first
257257

258258
```python
259-
async def first(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
259+
async def first(scalar: bool = True) -> T | Row[tuple[Any, ...]] | None
260260
```
261261

262262
> Fetches the first row or `None` if no results are found.
@@ -265,12 +265,12 @@ async def first(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
265265

266266
> **Parameters**
267267

268-
> - `scalar`: If `True`, returns a scalar value (`_T`),
268+
> - `scalar`: If `True`, returns a scalar value (`T`),
269269
> otherwise returns a row (default: `True`).
270270

271271
> **Returns**
272272

273-
> - `_T`: Instance for method chaining (scalar).
273+
> - `T`: Instance for method chaining (scalar).
274274
> - `sqlalchemy.engine.Row[tuple[Any, ...]]`: Row.
275275
> - `None`: If no result is found.
276276

@@ -302,7 +302,7 @@ async def first(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
302302
#### one
303303

304304
```python
305-
async def one(scalar: bool = True) -> _T | Row[tuple[Any, ...]]
305+
async def one(scalar: bool = True) -> T | Row[tuple[Any, ...]]
306306
```
307307

308308
> Fetches one row or raises a `sqlalchemy.exc.NoResultFound` exception
@@ -315,12 +315,12 @@ async def one(scalar: bool = True) -> _T | Row[tuple[Any, ...]]
315315

316316
> **Parameters**
317317

318-
> - `scalar`: If `True`, returns a scalar value (`_T`),
318+
> - `scalar`: If `True`, returns a scalar value (`T`),
319319
> otherwise returns a row (default: `True`).
320320

321321
> **Returns**
322322

323-
> - `_T`: Instance for method chaining (scalar).
323+
> - `T`: Instance for method chaining (scalar).
324324
> - `sqlalchemy.engine.Row[tuple[Any, ...]]`: Row.
325325

326326
> **Raises**
@@ -368,7 +368,7 @@ async def one(scalar: bool = True) -> _T | Row[tuple[Any, ...]]
368368
#### one_or_none
369369

370370
```python
371-
async def one_or_none(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
371+
async def one_or_none(scalar: bool = True) -> T | Row[tuple[Any, ...]] | None
372372
```
373373

374374
> Fetches one row or `None` if no results are found.
@@ -380,12 +380,12 @@ async def one_or_none(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
380380

381381
> **Parameters**
382382

383-
> - `scalar`: If `True`, returns a scalar value (`_T`),
383+
> - `scalar`: If `True`, returns a scalar value (`T`),
384384
> otherwise returns a row (default: `True`).
385385

386386
> **Returns**
387387

388-
> - `_T`: Instance for method chaining (scalar).
388+
> - `T`: Instance for method chaining (scalar).
389389
> - `sqlalchemy.engine.Row[tuple[Any, ...]]`: Row.
390390
> - `None`: If no result is found.
391391

@@ -434,7 +434,7 @@ async def one_or_none(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
434434
#### all
435435

436436
```python
437-
async def all(scalars: bool = True) -> Sequence[_T] | Sequence[Row[tuple[Any, ...]]]
437+
async def all(scalars: bool = True) -> Sequence[T] | Sequence[Row[tuple[Any, ...]]]
438438
```
439439

440440
> Fetches all rows.
@@ -443,12 +443,12 @@ async def all(scalars: bool = True) -> Sequence[_T] | Sequence[Row[tuple[Any, ..
443443

444444
> **Parameters**
445445

446-
> - `scalars`: If `True`, returns scalar values (`Sequence[_T]`),
446+
> - `scalars`: If `True`, returns scalar values (`Sequence[T]`),
447447
> otherwise returns rows (default: `True`).
448448

449449
> **Returns**
450450

451-
> - `Sequence[_T]`: Instances (scalars).
451+
> - `Sequence[T]`: Instances (scalars).
452452
> - `Sequence[sqlalchemy.engine.Row[tuple[Any, ...]]]`: Rows.
453453

454454
> **Examples**
@@ -501,7 +501,7 @@ async def count() -> int
501501
#### unique
502502

503503
```python
504-
async def unique(scalars: bool = True) -> ScalarResult[_T] | Result[tuple[Any, ...]]
504+
async def unique(scalars: bool = True) -> ScalarResult[T] | Result[tuple[Any, ...]]
505505
```
506506

507507
> Similar to [`scalars()`](#scalars) but applies unique filtering to
@@ -525,7 +525,7 @@ async def unique(scalars: bool = True) -> ScalarResult[_T] | Result[tuple[Any, .
525525

526526
> **Returns**
527527

528-
> - `sqlalchemy.engine.ScalarResult[_T]`: Result instance containing
528+
> - `sqlalchemy.engine.ScalarResult[T]`: Result instance containing
529529
> all scalars.
530530
> - `sqlalchemy.engine.Result[tuple[Any, ...]]`: Result instance containing
531531
> all rows.
@@ -546,7 +546,7 @@ async def unique(scalars: bool = True) -> ScalarResult[_T] | Result[tuple[Any, .
546546
#### unique_first
547547

548548
```python
549-
async def unique_first(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
549+
async def unique_first(scalar: bool = True) -> T | Row[tuple[Any, ...]] | None
550550
```
551551

552552
> Similar to [`first()`](#first) but applies unique filtering to
@@ -565,7 +565,7 @@ async def unique_first(scalar: bool = True) -> _T | Row[tuple[Any, ...]] | None
565565
#### unique_one
566566

567567
```python
568-
async def unique_one(scalar: bool) -> _T | Row[tuple[Any, ...]]
568+
async def unique_one(scalar: bool) -> T | Row[tuple[Any, ...]]
569569
```
570570

571571
> Similar to [`one()`](#one) but applies unique filtering to
@@ -584,7 +584,7 @@ async def unique_one(scalar: bool) -> _T | Row[tuple[Any, ...]]
584584
#### unique_one_or_none
585585

586586
```python
587-
async def unique_one_or_none(scalar: bool) -> _T | Row[tuple[Any, ...]] | None
587+
async def unique_one_or_none(scalar: bool) -> T | Row[tuple[Any, ...]] | None
588588
```
589589

590590
> Similar to [`one_or_none()`](#one_or_none) but applies unique filtering to
@@ -604,7 +604,7 @@ async def unique_one_or_none(scalar: bool) -> _T | Row[tuple[Any, ...]] | None
604604
#### unique_all
605605

606606
```python
607-
async def unique_all(scalars: bool) -> Sequence[_T] | Sequence[Row[tuple[Any, ...]]]
607+
async def unique_all(scalars: bool) -> Sequence[T] | Sequence[Row[tuple[Any, ...]]]
608608
```
609609

610610
> Similar to [`all()`](#all) but applies unique filtering to
@@ -1116,7 +1116,7 @@ def top(top: int) -> Self
11161116

11171117
```python
11181118
def join(
1119-
*paths: EagerLoadPath, model: type[_T] | None = None
1119+
*paths: EagerLoadPath, model: type[T] | None = None
11201120
) -> Self
11211121
```
11221122

@@ -1170,7 +1170,7 @@ def join(
11701170

11711171
```python
11721172
def with_subquery(
1173-
*paths: EagerLoadPath, model: type[_T] | None = None
1173+
*paths: EagerLoadPath, model: type[T] | None = None
11741174
) -> Self
11751175
```
11761176

0 commit comments

Comments
 (0)