sqlcrucible 0.2.1__tar.gz → 0.2.2__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.
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/.github/workflows/docs.yml +17 -6
- sqlcrucible-0.2.2/PKG-INFO +81 -0
- sqlcrucible-0.2.2/README.md +63 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/_version.py +2 -2
- sqlcrucible-0.2.1/PKG-INFO +0 -673
- sqlcrucible-0.2.1/README.md +0 -655
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/.github/workflows/ci.yml +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/.gitignore +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/.python-version +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/LICENSE +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/comparison.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/getting-started.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/guide/advanced.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/guide/defining-entities.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/guide/field-mapping.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/guide/inheritance.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/guide/relationships.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/guide/type-conversion.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/index.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/docs/reference/api.md +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/mkdocs.yml +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/noxfile.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/pyproject.toml +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/dicts.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/exceptions.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/function.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/literals.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/noop.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/registry.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/sequences.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/conversion/unions.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/annotations.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/automodel.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/core.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/field_metadata.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/field_resolution.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/fields.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/sa_conversion.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/entity/sa_type.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/stubs/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/stubs/__main__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/collections.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/properties.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/sa_fields.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/annotations.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/equivalence.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/forward_refs.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/match.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/params.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/src/sqlcrucible/utils/types/transformer.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/conftest.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/test_dicts.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/test_literals.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/test_noop.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/test_registry.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/test_sequences.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/conversion/test_unions.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_attrs_entity.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_concrete_table_inheritance.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_custom_sa_model.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_dataclass_entity.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_joined_table_inheritance.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_pydantic_entity.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_back_populates.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_cycles.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_eager.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_many_to_many.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_one_to_many_child.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_one_to_many_parent.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_one_to_one.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_relationships_self_referential.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_sa_type.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/entity/test_single_table_inheritance.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/stubs/__init__.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/stubs/sample_models.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/stubs/test_stub_typecheck.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/utils/types/test_annotations.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/utils/types/test_forward_refs.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/tests/utils/types/test_params.py +0 -0
- {sqlcrucible-0.2.1 → sqlcrucible-0.2.2}/uv.lock +0 -0
|
@@ -5,13 +5,20 @@ on:
|
|
|
5
5
|
tags: ["*"]
|
|
6
6
|
workflow_dispatch:
|
|
7
7
|
inputs:
|
|
8
|
+
action:
|
|
9
|
+
description: "Action to perform"
|
|
10
|
+
type: choice
|
|
11
|
+
options:
|
|
12
|
+
- deploy
|
|
13
|
+
- delete
|
|
14
|
+
default: deploy
|
|
8
15
|
version:
|
|
9
|
-
description: "Version to deploy (e.g., 0.1.0)"
|
|
16
|
+
description: "Version to deploy or delete (e.g., 0.1.0, pr-123)"
|
|
10
17
|
required: true
|
|
11
18
|
latest:
|
|
12
|
-
description: "Update 'latest' alias"
|
|
19
|
+
description: "Update 'latest' alias (deploy only)"
|
|
13
20
|
type: boolean
|
|
14
|
-
default:
|
|
21
|
+
default: false
|
|
15
22
|
|
|
16
23
|
permissions:
|
|
17
24
|
contents: write
|
|
@@ -21,7 +28,7 @@ concurrency:
|
|
|
21
28
|
cancel-in-progress: false
|
|
22
29
|
|
|
23
30
|
jobs:
|
|
24
|
-
|
|
31
|
+
docs:
|
|
25
32
|
runs-on: ubuntu-latest
|
|
26
33
|
steps:
|
|
27
34
|
- uses: actions/checkout@v4
|
|
@@ -36,16 +43,20 @@ jobs:
|
|
|
36
43
|
git config user.name "github-actions[bot]"
|
|
37
44
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
38
45
|
|
|
39
|
-
- name: Deploy docs
|
|
46
|
+
- name: Deploy or delete docs
|
|
40
47
|
run: |
|
|
41
48
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
42
49
|
VERSION="${{ github.event.inputs.version }}"
|
|
43
|
-
if [ "${{ github.event.inputs.
|
|
50
|
+
if [ "${{ github.event.inputs.action }}" = "delete" ]; then
|
|
51
|
+
uv run --group docs mike delete --push "$VERSION"
|
|
52
|
+
elif [ "${{ github.event.inputs.latest }}" = "true" ]; then
|
|
44
53
|
uv run --group docs mike deploy --push --update-aliases "$VERSION" latest
|
|
54
|
+
uv run --group docs mike set-default --push latest
|
|
45
55
|
else
|
|
46
56
|
uv run --group docs mike deploy --push "$VERSION"
|
|
47
57
|
fi
|
|
48
58
|
else
|
|
49
59
|
VERSION="${GITHUB_REF#refs/tags/}"
|
|
50
60
|
uv run --group docs mike deploy --push --update-aliases "$VERSION" latest
|
|
61
|
+
uv run --group docs mike set-default --push latest
|
|
51
62
|
fi
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sqlcrucible
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author-email: Richard Rae-Jones <sqlcrucible@richard.rdrj.uk>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Requires-Dist: pydantic~=2.10
|
|
15
|
+
Requires-Dist: sqlalchemy~=2.0
|
|
16
|
+
Requires-Dist: typing-extensions~=4.15
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# SQLCrucible
|
|
20
|
+
|
|
21
|
+
Get the full power of Pydantic for your API and the full power of SQLAlchemy for your database, without compromising on either.
|
|
22
|
+
|
|
23
|
+
SQLCrucible lets you define a single model class that works as both a Pydantic model and a SQLAlchemy table, with explicit conversion between the two. Your Pydantic models stay pure Pydantic (working with FastAPI, validation, serialization), your SQLAlchemy models stay pure SQLAlchemy (supporting relationships, inheritance, Alembic), and conversion only happens when you ask for it.
|
|
24
|
+
|
|
25
|
+
## Key Features
|
|
26
|
+
|
|
27
|
+
- **Explicit conversion** — `to_sa_model()` and `from_sa_model()` make it clear when you're crossing the boundary between Pydantic and SQLAlchemy
|
|
28
|
+
- **Native SQLAlchemy** — use `mapped_column()`, `relationship()`, and `__mapper_args__` directly; if SQLAlchemy supports it, so does SQLCrucible
|
|
29
|
+
- **Escape hatches everywhere** — mix with plain SQLAlchemy models, attach entities to existing tables, customize generated models, or drop down to raw queries
|
|
30
|
+
- **Full inheritance support** — single table, joined table, and concrete table inheritance all work out of the box
|
|
31
|
+
- **Type stub generation** — generate `.pyi` stubs for IDE autocompletion and type checking of SQLAlchemy columns
|
|
32
|
+
- **Multiple frameworks** — works with Pydantic, dataclasses, and attrs
|
|
33
|
+
|
|
34
|
+
## Example
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from typing import Annotated
|
|
38
|
+
from uuid import UUID, uuid4
|
|
39
|
+
|
|
40
|
+
from pydantic import Field
|
|
41
|
+
from sqlalchemy import create_engine, select
|
|
42
|
+
from sqlalchemy.orm import Session, mapped_column
|
|
43
|
+
|
|
44
|
+
from sqlcrucible import SAType, SQLCrucibleBaseModel
|
|
45
|
+
|
|
46
|
+
class Artist(SQLCrucibleBaseModel):
|
|
47
|
+
__sqlalchemy_params__ = {"__tablename__": "artist"}
|
|
48
|
+
|
|
49
|
+
id: Annotated[UUID, mapped_column(primary_key=True)] = Field(default_factory=uuid4)
|
|
50
|
+
name: str
|
|
51
|
+
|
|
52
|
+
engine = create_engine("sqlite:///:memory:")
|
|
53
|
+
SAType[Artist].__table__.metadata.create_all(engine)
|
|
54
|
+
|
|
55
|
+
artist = Artist(name="Bob Dylan")
|
|
56
|
+
with Session(engine) as session:
|
|
57
|
+
session.add(artist.to_sa_model())
|
|
58
|
+
session.commit()
|
|
59
|
+
|
|
60
|
+
with Session(engine) as session:
|
|
61
|
+
sa_artist = session.scalar(
|
|
62
|
+
select(SAType[Artist]).where(SAType[Artist].name == "Bob Dylan")
|
|
63
|
+
)
|
|
64
|
+
artist = Artist.from_sa_model(sa_artist)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install sqlcrucible
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Documentation
|
|
74
|
+
|
|
75
|
+
Full documentation is available at [sqlcrucible.rdrj.uk](https://sqlcrucible.rdrj.uk/).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
<p align="center">
|
|
80
|
+
🏴 Made with haggis
|
|
81
|
+
</p>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# SQLCrucible
|
|
2
|
+
|
|
3
|
+
Get the full power of Pydantic for your API and the full power of SQLAlchemy for your database, without compromising on either.
|
|
4
|
+
|
|
5
|
+
SQLCrucible lets you define a single model class that works as both a Pydantic model and a SQLAlchemy table, with explicit conversion between the two. Your Pydantic models stay pure Pydantic (working with FastAPI, validation, serialization), your SQLAlchemy models stay pure SQLAlchemy (supporting relationships, inheritance, Alembic), and conversion only happens when you ask for it.
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- **Explicit conversion** — `to_sa_model()` and `from_sa_model()` make it clear when you're crossing the boundary between Pydantic and SQLAlchemy
|
|
10
|
+
- **Native SQLAlchemy** — use `mapped_column()`, `relationship()`, and `__mapper_args__` directly; if SQLAlchemy supports it, so does SQLCrucible
|
|
11
|
+
- **Escape hatches everywhere** — mix with plain SQLAlchemy models, attach entities to existing tables, customize generated models, or drop down to raw queries
|
|
12
|
+
- **Full inheritance support** — single table, joined table, and concrete table inheritance all work out of the box
|
|
13
|
+
- **Type stub generation** — generate `.pyi` stubs for IDE autocompletion and type checking of SQLAlchemy columns
|
|
14
|
+
- **Multiple frameworks** — works with Pydantic, dataclasses, and attrs
|
|
15
|
+
|
|
16
|
+
## Example
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from typing import Annotated
|
|
20
|
+
from uuid import UUID, uuid4
|
|
21
|
+
|
|
22
|
+
from pydantic import Field
|
|
23
|
+
from sqlalchemy import create_engine, select
|
|
24
|
+
from sqlalchemy.orm import Session, mapped_column
|
|
25
|
+
|
|
26
|
+
from sqlcrucible import SAType, SQLCrucibleBaseModel
|
|
27
|
+
|
|
28
|
+
class Artist(SQLCrucibleBaseModel):
|
|
29
|
+
__sqlalchemy_params__ = {"__tablename__": "artist"}
|
|
30
|
+
|
|
31
|
+
id: Annotated[UUID, mapped_column(primary_key=True)] = Field(default_factory=uuid4)
|
|
32
|
+
name: str
|
|
33
|
+
|
|
34
|
+
engine = create_engine("sqlite:///:memory:")
|
|
35
|
+
SAType[Artist].__table__.metadata.create_all(engine)
|
|
36
|
+
|
|
37
|
+
artist = Artist(name="Bob Dylan")
|
|
38
|
+
with Session(engine) as session:
|
|
39
|
+
session.add(artist.to_sa_model())
|
|
40
|
+
session.commit()
|
|
41
|
+
|
|
42
|
+
with Session(engine) as session:
|
|
43
|
+
sa_artist = session.scalar(
|
|
44
|
+
select(SAType[Artist]).where(SAType[Artist].name == "Bob Dylan")
|
|
45
|
+
)
|
|
46
|
+
artist = Artist.from_sa_model(sa_artist)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install sqlcrucible
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Documentation
|
|
56
|
+
|
|
57
|
+
Full documentation is available at [sqlcrucible.rdrj.uk](https://sqlcrucible.rdrj.uk/).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
<p align="center">
|
|
62
|
+
🏴 Made with haggis
|
|
63
|
+
</p>
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
31
|
+
__version__ = version = '0.2.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 2)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|