oxyde 0.1.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.
Files changed (58) hide show
  1. oxyde-0.1.0/PKG-INFO +192 -0
  2. oxyde-0.1.0/README.md +155 -0
  3. oxyde-0.1.0/oxyde/__init__.py +123 -0
  4. oxyde-0.1.0/oxyde/codegen/__init__.py +15 -0
  5. oxyde-0.1.0/oxyde/codegen/stub_generator.py +639 -0
  6. oxyde-0.1.0/oxyde/core/__init__.py +82 -0
  7. oxyde-0.1.0/oxyde/core/ir.py +327 -0
  8. oxyde-0.1.0/oxyde/core/wrapper.py +198 -0
  9. oxyde-0.1.0/oxyde/db/__init__.py +221 -0
  10. oxyde-0.1.0/oxyde/db/pool.py +287 -0
  11. oxyde-0.1.0/oxyde/db/registry.py +113 -0
  12. oxyde-0.1.0/oxyde/db/transaction.py +341 -0
  13. oxyde-0.1.0/oxyde/exceptions.py +65 -0
  14. oxyde-0.1.0/oxyde/migrations/__init__.py +55 -0
  15. oxyde-0.1.0/oxyde/migrations/cli.py +457 -0
  16. oxyde-0.1.0/oxyde/migrations/context.py +480 -0
  17. oxyde-0.1.0/oxyde/migrations/executor.py +456 -0
  18. oxyde-0.1.0/oxyde/migrations/extract.py +284 -0
  19. oxyde-0.1.0/oxyde/migrations/generator.py +415 -0
  20. oxyde-0.1.0/oxyde/migrations/replay.py +296 -0
  21. oxyde-0.1.0/oxyde/migrations/tracker.py +176 -0
  22. oxyde-0.1.0/oxyde/migrations/types.py +376 -0
  23. oxyde-0.1.0/oxyde/models/__init__.py +69 -0
  24. oxyde-0.1.0/oxyde/models/base.py +796 -0
  25. oxyde-0.1.0/oxyde/models/decorators.py +109 -0
  26. oxyde-0.1.0/oxyde/models/field.py +193 -0
  27. oxyde-0.1.0/oxyde/models/lookups.py +389 -0
  28. oxyde-0.1.0/oxyde/models/metadata.py +133 -0
  29. oxyde-0.1.0/oxyde/models/registry.py +101 -0
  30. oxyde-0.1.0/oxyde/models/serializers.py +128 -0
  31. oxyde-0.1.0/oxyde/models/utils.py +113 -0
  32. oxyde-0.1.0/oxyde/py.typed +0 -0
  33. oxyde-0.1.0/oxyde/queries/__init__.py +72 -0
  34. oxyde-0.1.0/oxyde/queries/aggregates.py +153 -0
  35. oxyde-0.1.0/oxyde/queries/base.py +199 -0
  36. oxyde-0.1.0/oxyde/queries/conditions.py +71 -0
  37. oxyde-0.1.0/oxyde/queries/expressions.py +158 -0
  38. oxyde-0.1.0/oxyde/queries/insert.py +117 -0
  39. oxyde-0.1.0/oxyde/queries/joins.py +66 -0
  40. oxyde-0.1.0/oxyde/queries/manager.py +550 -0
  41. oxyde-0.1.0/oxyde/queries/mixins/__init__.py +65 -0
  42. oxyde-0.1.0/oxyde/queries/mixins/aggregation.py +225 -0
  43. oxyde-0.1.0/oxyde/queries/mixins/debug.py +159 -0
  44. oxyde-0.1.0/oxyde/queries/mixins/execution.py +378 -0
  45. oxyde-0.1.0/oxyde/queries/mixins/filtering.py +139 -0
  46. oxyde-0.1.0/oxyde/queries/mixins/joining.py +158 -0
  47. oxyde-0.1.0/oxyde/queries/mixins/mutation.py +132 -0
  48. oxyde-0.1.0/oxyde/queries/mixins/pagination.py +91 -0
  49. oxyde-0.1.0/oxyde/queries/q.py +229 -0
  50. oxyde-0.1.0/oxyde/queries/select.py +283 -0
  51. oxyde-0.1.0/oxyde.egg-info/PKG-INFO +192 -0
  52. oxyde-0.1.0/oxyde.egg-info/SOURCES.txt +56 -0
  53. oxyde-0.1.0/oxyde.egg-info/dependency_links.txt +1 -0
  54. oxyde-0.1.0/oxyde.egg-info/entry_points.txt +2 -0
  55. oxyde-0.1.0/oxyde.egg-info/requires.txt +11 -0
  56. oxyde-0.1.0/oxyde.egg-info/top_level.txt +1 -0
  57. oxyde-0.1.0/pyproject.toml +125 -0
  58. oxyde-0.1.0/setup.cfg +4 -0
oxyde-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: oxyde
3
+ Version: 0.1.0
4
+ Summary: High-performance async Python ORM with Rust core
5
+ Author-email: Nikita Ryzhenkov <nikita.ryzhenkoff@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/mr-fatalyst/oxyde
8
+ Project-URL: Documentation, https://github.com/mr-fatalyst/oxyde#readme
9
+ Project-URL: Repository, https://github.com/mr-fatalyst/oxyde
10
+ Project-URL: Issues, https://github.com/mr-fatalyst/oxyde/issues
11
+ Keywords: orm,async,database,postgresql,sqlite,mysql,pydantic
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Rust
22
+ Classifier: Framework :: AsyncIO
23
+ Classifier: Topic :: Database
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ Requires-Dist: pydantic>=2.0
28
+ Requires-Dist: msgpack>=1.0
29
+ Requires-Dist: typer>=0.9
30
+ Requires-Dist: oxyde-core<0.2.0,>=0.1.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=9.0; extra == "dev"
33
+ Requires-Dist: pytest-asyncio>=1.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=7.0; extra == "dev"
35
+ Requires-Dist: ruff>=0.14.7; extra == "dev"
36
+ Requires-Dist: pre-commit>=4.5.0; extra == "dev"
37
+
38
+ # Oxyde ORM
39
+
40
+ High-performance async Python ORM with Rust core.
41
+
42
+ Oxyde combines Python's expressiveness with Rust's performance. Models defined with Pydantic v2, queries executed in native Rust.
43
+
44
+ ```python
45
+ from oxyde import OxydeModel, Field, db
46
+
47
+ class User(OxydeModel):
48
+ class Meta:
49
+ is_table = True
50
+
51
+ id: int | None = Field(default=None, db_pk=True)
52
+ email: str = Field(db_unique=True)
53
+ age: int = Field(ge=0, le=150)
54
+
55
+ async def main():
56
+ async with db.connect("postgresql://localhost/mydb"):
57
+ # Create
58
+ user = await User.objects.create(email="alice@example.com", age=30)
59
+
60
+ # Read
61
+ users = await User.objects.filter(age__gte=18).limit(10).all()
62
+
63
+ # Update
64
+ await User.objects.filter(id=user.id).update(age=31)
65
+
66
+ # Delete
67
+ await User.objects.filter(id=user.id).delete()
68
+ ```
69
+
70
+ ## Features
71
+
72
+ - **Django-style API** — Familiar `Model.objects.filter()` syntax
73
+ - **Pydantic v2 models** — Full validation, type hints, serialization
74
+ - **Async-first** — Built for modern async Python with `asyncio`
75
+ - **Rust performance** — SQL generation and execution in native Rust
76
+ - **Multi-database** — PostgreSQL, SQLite, MySQL support
77
+ - **Transactions** — `atomic()` context manager with savepoints
78
+ - **Migrations** — Django-style `makemigrations` and `migrate` CLI
79
+
80
+ ## Installation
81
+
82
+ ```bash
83
+ pip install oxyde
84
+ ```
85
+
86
+ ## Quick Start
87
+
88
+ ### Define a Model
89
+
90
+ ```python
91
+ from oxyde import OxydeModel, Field
92
+
93
+ class User(OxydeModel):
94
+ class Meta:
95
+ is_table = True
96
+
97
+ id: int | None = Field(default=None, db_pk=True)
98
+ name: str
99
+ email: str = Field(db_unique=True)
100
+ age: int | None = Field(default=None)
101
+ ```
102
+
103
+ ### Connect and Query
104
+
105
+ ```python
106
+ from oxyde import db
107
+
108
+ async with db.connect("sqlite:///app.db"):
109
+ # Create
110
+ user = await User.objects.create(name="Alice", email="alice@example.com", age=30)
111
+
112
+ # Query
113
+ adults = await User.objects.filter(age__gte=18).all()
114
+
115
+ # Get single object
116
+ user = await User.objects.get(id=1)
117
+
118
+ # Update
119
+ user.age = 31
120
+ await user.save()
121
+
122
+ # Delete
123
+ await user.delete()
124
+ ```
125
+
126
+ ### Transactions
127
+
128
+ ```python
129
+ from oxyde.db import transaction
130
+
131
+ async with transaction.atomic():
132
+ user = await User.objects.create(name="Alice", email="alice@example.com")
133
+ await Profile.objects.create(user_id=user.id)
134
+ # Auto-commits on success, rolls back on exception
135
+ ```
136
+
137
+ ### FastAPI Integration
138
+
139
+ ```python
140
+ from fastapi import FastAPI
141
+ from oxyde import db
142
+
143
+ app = FastAPI(
144
+ lifespan=db.lifespan(
145
+ default="postgresql://localhost/mydb",
146
+ )
147
+ )
148
+
149
+ @app.get("/users")
150
+ async def get_users():
151
+ return await User.objects.filter(is_active=True).all()
152
+ ```
153
+
154
+ ## Database Support
155
+
156
+ | Database | Min Version | Status | Notes |
157
+ |------------|-------------|--------|-------|
158
+ | PostgreSQL | 12+ | Full | RETURNING, UPSERT, FOR UPDATE/SHARE, JSON, Arrays |
159
+ | SQLite | 3.35+ | Full | RETURNING, UPSERT, WAL mode by default |
160
+ | MySQL | 8.0+ | Full | UPSERT via ON DUPLICATE KEY, FOR UPDATE/SHARE |
161
+
162
+ **Recommendation**: PostgreSQL for production, SQLite for development/testing.
163
+
164
+ > **SQLite < 3.35**: Falls back to `last_insert_rowid()` which may return incorrect IDs with concurrent inserts.
165
+ >
166
+ > **MySQL**: No RETURNING clause — uses `last_insert_id()`. Bulk INSERT returns calculated ID range which may be incorrect with concurrent inserts.
167
+
168
+ **Connection URLs:**
169
+
170
+ ```python
171
+ "postgresql://user:password@localhost:5432/database"
172
+ "sqlite:///path/to/database.db"
173
+ "sqlite:///:memory:"
174
+ "mysql://user:password@localhost:3306/database"
175
+ ```
176
+
177
+ ## Documentation
178
+
179
+ Full documentation: **[https://oxyde.fatalyst.dev/](https://oxyde.fatalyst.dev/)**
180
+
181
+ - [Getting Started](https://oxyde.fatalyst.dev/getting-started/quickstart/) — First steps with Oxyde
182
+ - [User Guide](https://oxyde.fatalyst.dev/guide/models/) — Models, queries, relations, transactions
183
+ - [Cheatsheet](https://oxyde.fatalyst.dev/cheatsheet/) — Quick reference for all methods
184
+ - [FAQ](https://oxyde.fatalyst.dev/faq/) — Common questions and answers
185
+
186
+ ## Contributing
187
+
188
+ If you have suggestions or find a bug, please open an issue or create a pull request on GitHub.
189
+
190
+ ## License
191
+
192
+ This project is licensed under the terms of the MIT license.
oxyde-0.1.0/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # Oxyde ORM
2
+
3
+ High-performance async Python ORM with Rust core.
4
+
5
+ Oxyde combines Python's expressiveness with Rust's performance. Models defined with Pydantic v2, queries executed in native Rust.
6
+
7
+ ```python
8
+ from oxyde import OxydeModel, Field, db
9
+
10
+ class User(OxydeModel):
11
+ class Meta:
12
+ is_table = True
13
+
14
+ id: int | None = Field(default=None, db_pk=True)
15
+ email: str = Field(db_unique=True)
16
+ age: int = Field(ge=0, le=150)
17
+
18
+ async def main():
19
+ async with db.connect("postgresql://localhost/mydb"):
20
+ # Create
21
+ user = await User.objects.create(email="alice@example.com", age=30)
22
+
23
+ # Read
24
+ users = await User.objects.filter(age__gte=18).limit(10).all()
25
+
26
+ # Update
27
+ await User.objects.filter(id=user.id).update(age=31)
28
+
29
+ # Delete
30
+ await User.objects.filter(id=user.id).delete()
31
+ ```
32
+
33
+ ## Features
34
+
35
+ - **Django-style API** — Familiar `Model.objects.filter()` syntax
36
+ - **Pydantic v2 models** — Full validation, type hints, serialization
37
+ - **Async-first** — Built for modern async Python with `asyncio`
38
+ - **Rust performance** — SQL generation and execution in native Rust
39
+ - **Multi-database** — PostgreSQL, SQLite, MySQL support
40
+ - **Transactions** — `atomic()` context manager with savepoints
41
+ - **Migrations** — Django-style `makemigrations` and `migrate` CLI
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install oxyde
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ### Define a Model
52
+
53
+ ```python
54
+ from oxyde import OxydeModel, Field
55
+
56
+ class User(OxydeModel):
57
+ class Meta:
58
+ is_table = True
59
+
60
+ id: int | None = Field(default=None, db_pk=True)
61
+ name: str
62
+ email: str = Field(db_unique=True)
63
+ age: int | None = Field(default=None)
64
+ ```
65
+
66
+ ### Connect and Query
67
+
68
+ ```python
69
+ from oxyde import db
70
+
71
+ async with db.connect("sqlite:///app.db"):
72
+ # Create
73
+ user = await User.objects.create(name="Alice", email="alice@example.com", age=30)
74
+
75
+ # Query
76
+ adults = await User.objects.filter(age__gte=18).all()
77
+
78
+ # Get single object
79
+ user = await User.objects.get(id=1)
80
+
81
+ # Update
82
+ user.age = 31
83
+ await user.save()
84
+
85
+ # Delete
86
+ await user.delete()
87
+ ```
88
+
89
+ ### Transactions
90
+
91
+ ```python
92
+ from oxyde.db import transaction
93
+
94
+ async with transaction.atomic():
95
+ user = await User.objects.create(name="Alice", email="alice@example.com")
96
+ await Profile.objects.create(user_id=user.id)
97
+ # Auto-commits on success, rolls back on exception
98
+ ```
99
+
100
+ ### FastAPI Integration
101
+
102
+ ```python
103
+ from fastapi import FastAPI
104
+ from oxyde import db
105
+
106
+ app = FastAPI(
107
+ lifespan=db.lifespan(
108
+ default="postgresql://localhost/mydb",
109
+ )
110
+ )
111
+
112
+ @app.get("/users")
113
+ async def get_users():
114
+ return await User.objects.filter(is_active=True).all()
115
+ ```
116
+
117
+ ## Database Support
118
+
119
+ | Database | Min Version | Status | Notes |
120
+ |------------|-------------|--------|-------|
121
+ | PostgreSQL | 12+ | Full | RETURNING, UPSERT, FOR UPDATE/SHARE, JSON, Arrays |
122
+ | SQLite | 3.35+ | Full | RETURNING, UPSERT, WAL mode by default |
123
+ | MySQL | 8.0+ | Full | UPSERT via ON DUPLICATE KEY, FOR UPDATE/SHARE |
124
+
125
+ **Recommendation**: PostgreSQL for production, SQLite for development/testing.
126
+
127
+ > **SQLite < 3.35**: Falls back to `last_insert_rowid()` which may return incorrect IDs with concurrent inserts.
128
+ >
129
+ > **MySQL**: No RETURNING clause — uses `last_insert_id()`. Bulk INSERT returns calculated ID range which may be incorrect with concurrent inserts.
130
+
131
+ **Connection URLs:**
132
+
133
+ ```python
134
+ "postgresql://user:password@localhost:5432/database"
135
+ "sqlite:///path/to/database.db"
136
+ "sqlite:///:memory:"
137
+ "mysql://user:password@localhost:3306/database"
138
+ ```
139
+
140
+ ## Documentation
141
+
142
+ Full documentation: **[https://oxyde.fatalyst.dev/](https://oxyde.fatalyst.dev/)**
143
+
144
+ - [Getting Started](https://oxyde.fatalyst.dev/getting-started/quickstart/) — First steps with Oxyde
145
+ - [User Guide](https://oxyde.fatalyst.dev/guide/models/) — Models, queries, relations, transactions
146
+ - [Cheatsheet](https://oxyde.fatalyst.dev/cheatsheet/) — Quick reference for all methods
147
+ - [FAQ](https://oxyde.fatalyst.dev/faq/) — Common questions and answers
148
+
149
+ ## Contributing
150
+
151
+ If you have suggestions or find a bug, please open an issue or create a pull request on GitHub.
152
+
153
+ ## License
154
+
155
+ This project is licensed under the terms of the MIT license.
@@ -0,0 +1,123 @@
1
+ """Oxyde ORM - High-performance async Python ORM with Rust core.
2
+
3
+ This is the main entry point for the Oxyde ORM library. It re-exports
4
+ all public APIs from submodules for convenient access.
5
+
6
+ Public API:
7
+ Models:
8
+ OxydeModel: Base class for all ORM models (Pydantic v2 based).
9
+ Field: Field configuration with db_pk, db_index, db_default, etc.
10
+ Index: Composite index decorator for models.
11
+ Check: CHECK constraint decorator for models.
12
+
13
+ Queries:
14
+ Query: SELECT query builder with Django-like filter syntax.
15
+ QueryManager: Model.objects manager for CRUD operations.
16
+ Q: Boolean expressions for complex filters (AND/OR/NOT).
17
+ F: Database-side field references for expressions.
18
+
19
+ Aggregates:
20
+ Count, Sum, Avg, Max, Min: SQL aggregate functions.
21
+ Concat, Coalesce: SQL scalar functions.
22
+ RawSQL: Raw SQL expression wrapper.
23
+
24
+ Database:
25
+ db: Database module with init(), close(), connect(), lifespan().
26
+ AsyncDatabase: Connection pool wrapper.
27
+ PoolSettings: Pool configuration (max_connections, timeouts).
28
+ atomic: Transaction context manager (decorator or async with).
29
+
30
+ Exceptions:
31
+ OxydeError: Base exception for all Oxyde errors.
32
+ NotFoundError: Raised when get() finds no results.
33
+ MultipleObjectsReturned: Raised when get() finds multiple results.
34
+ IntegrityError: Raised on constraint violations.
35
+ FieldError, LookupError, ManagerError: Validation errors.
36
+
37
+ Example:
38
+ from oxyde import OxydeModel, Field, db
39
+
40
+ class User(OxydeModel):
41
+ id: int | None = Field(default=None, db_pk=True)
42
+ name: str
43
+
44
+ class Meta:
45
+ is_table = True
46
+
47
+ async with db.connect("sqlite://app.db"):
48
+ user = await User.objects.create(name="Alice")
49
+ users = await User.objects.filter(name__startswith="A").all()
50
+ """
51
+
52
+ from oxyde import db
53
+ from oxyde.db import (
54
+ AsyncDatabase,
55
+ PoolSettings,
56
+ TransactionTimeoutError,
57
+ atomic,
58
+ disconnect_all,
59
+ get_connection,
60
+ register_connection,
61
+ )
62
+ from oxyde.exceptions import (
63
+ FieldError,
64
+ IntegrityError,
65
+ LookupError,
66
+ LookupValueError,
67
+ ManagerError,
68
+ MultipleObjectsReturned,
69
+ NotFoundError,
70
+ OxydeError,
71
+ )
72
+ from oxyde.models import Check, Field, Index, OxydeModel
73
+ from oxyde.queries import (
74
+ Avg,
75
+ Coalesce,
76
+ Concat,
77
+ Count,
78
+ F,
79
+ Max,
80
+ Min,
81
+ Q,
82
+ Query,
83
+ QueryManager,
84
+ RawSQL,
85
+ Sum,
86
+ )
87
+
88
+ __version__ = "0.1.0"
89
+
90
+ __all__ = [
91
+ "OxydeModel",
92
+ "db",
93
+ "AsyncDatabase",
94
+ "PoolSettings",
95
+ "TransactionTimeoutError",
96
+ "register_connection",
97
+ "get_connection",
98
+ "disconnect_all",
99
+ "Field",
100
+ "Index",
101
+ "Check",
102
+ "Query",
103
+ "QueryManager",
104
+ "OxydeError",
105
+ "FieldError",
106
+ "LookupError",
107
+ "LookupValueError",
108
+ "ManagerError",
109
+ "NotFoundError",
110
+ "MultipleObjectsReturned",
111
+ "IntegrityError",
112
+ "atomic",
113
+ "F",
114
+ "Q",
115
+ "Count",
116
+ "Sum",
117
+ "Avg",
118
+ "Max",
119
+ "Min",
120
+ "Concat",
121
+ "Coalesce",
122
+ "RawSQL",
123
+ ]
@@ -0,0 +1,15 @@
1
+ """Code generation utilities for Oxyde ORM."""
2
+
3
+ from oxyde.codegen.stub_generator import (
4
+ generate_model_stub,
5
+ generate_stub_for_file,
6
+ generate_stubs_for_models,
7
+ write_stubs,
8
+ )
9
+
10
+ __all__ = [
11
+ "generate_model_stub",
12
+ "generate_stub_for_file",
13
+ "generate_stubs_for_models",
14
+ "write_stubs",
15
+ ]