async-easy-model 0.2.1__tar.gz → 0.2.3__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.
@@ -0,0 +1,362 @@
1
+ Metadata-Version: 2.2
2
+ Name: async-easy-model
3
+ Version: 0.2.3
4
+ Summary: A simplified SQLModel-based ORM for async database operations
5
+ Home-page: https://github.com/puntorigen/easy-model
6
+ Author: Pablo Schaffner
7
+ Author-email: pablo@puntorigen.com
8
+ Keywords: orm,sqlmodel,database,async,postgresql,sqlite
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.7
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Requires-Python: >=3.7
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: sqlmodel>=0.0.8
23
+ Requires-Dist: sqlalchemy>=2.0.0
24
+ Requires-Dist: asyncpg>=0.25.0
25
+ Requires-Dist: aiosqlite>=0.19.0
26
+ Requires-Dist: greenlet>=3.1.1
27
+ Requires-Dist: inflection>=0.5.1
28
+ Dynamic: author
29
+ Dynamic: author-email
30
+ Dynamic: classifier
31
+ Dynamic: description
32
+ Dynamic: description-content-type
33
+ Dynamic: home-page
34
+ Dynamic: keywords
35
+ Dynamic: requires-dist
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # async-easy-model
40
+
41
+ A simplified SQLModel-based ORM for async database operations in Python. async-easy-model provides a clean, intuitive interface for common database operations while leveraging the power of SQLModel and SQLAlchemy.
42
+
43
+ <p align="center">
44
+ <img src="https://img.shields.io/pypi/v/async-easy-model" alt="PyPI Version">
45
+ <img src="https://img.shields.io/pypi/pyversions/async-easy-model" alt="Python Versions">
46
+ <img src="https://img.shields.io/github/license/puntorigen/easy_model" alt="License">
47
+ </p>
48
+
49
+ ## Features
50
+
51
+ - 🚀 Easy-to-use async database operations with standardized methods
52
+ - 🔄 Intuitive APIs with sensible defaults for rapid development
53
+ - 📊 Dictionary-based CRUD operations (select, insert, update, delete)
54
+ - 🔗 Enhanced relationship handling with eager loading and nested operations
55
+ - 🔍 Powerful query methods with flexible ordering support
56
+ - ⚙️ Automatic relationship detection and bidirectional setup
57
+ - 📱 Support for both PostgreSQL and SQLite databases
58
+ - 🛠️ Built on top of SQLModel and SQLAlchemy for robust performance
59
+ - 📝 Type hints for better IDE support
60
+ - 🕒 Automatic `id`, `created_at` and `updated_at` fields provided by default
61
+ - 🔄 Automatic schema migrations for evolving database models
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ pip install async-easy-model
67
+ ```
68
+
69
+ ## Basic Usage
70
+
71
+ ```python
72
+ from async_easy_model import EasyModel, init_db, db_config, Field
73
+ from typing import Optional
74
+ from datetime import datetime
75
+
76
+ # Configure your database
77
+ db_config.configure_sqlite("database.db")
78
+
79
+ # Define your model
80
+ class User(EasyModel, table=True):
81
+ #no need to specify id, created_at or updated_at since EasyModel provides them by default
82
+ username: str = Field(unique=True)
83
+ email: str
84
+
85
+ # Initialize your database
86
+ async def setup():
87
+ await init_db()
88
+
89
+ # Use it in your async code
90
+ async def main():
91
+ await setup()
92
+ # Create a new user
93
+ user = await User.insert({
94
+ "username": "john_doe",
95
+ "email": "john@example.com"
96
+ })
97
+
98
+ # Get user ID
99
+ print(f"New user id: {user.id}")
100
+ ```
101
+
102
+ ## CRUD Operations
103
+
104
+ First, let's define some models that we'll use throughout the examples:
105
+
106
+ ```python
107
+ from async_easy_model import EasyModel, Field
108
+ from typing import Optional, List
109
+ from datetime import datetime
110
+
111
+ class User(EasyModel, table=True):
112
+ username: str = Field(unique=True)
113
+ email: str
114
+ is_active: bool = Field(default=True)
115
+
116
+ class Post(EasyModel, table=True):
117
+ title: str
118
+ content: str
119
+ user_id: Optional[int] = Field(default=None, foreign_key="user.id")
120
+
121
+ class Comment(EasyModel, table=True):
122
+ text: str
123
+ post_id: Optional[int] = Field(default=None, foreign_key="post.id")
124
+ user_id: Optional[int] = Field(default=None, foreign_key="user.id")
125
+
126
+ class Department(EasyModel, table=True):
127
+ name: str = Field(unique=True)
128
+
129
+ class Product(EasyModel, table=True):
130
+ name: str
131
+ price: float
132
+ sales: int = Field(default=0)
133
+
134
+ class Book(EasyModel, table=True):
135
+ title: str
136
+ author_id: Optional[int] = Field(default=None, foreign_key="author.id")
137
+
138
+ class Author(EasyModel, table=True):
139
+ name: str
140
+ ```
141
+
142
+ ### Create (Insert)
143
+
144
+ ```python
145
+ # Insert a single record
146
+ user = await User.insert({
147
+ "username": "john_doe",
148
+ "email": "john@example.com"
149
+ })
150
+
151
+ # Insert multiple records
152
+ users = await User.insert([
153
+ {"username": "user1", "email": "user1@example.com"},
154
+ {"username": "user2", "email": "user2@example.com"}
155
+ ])
156
+
157
+ # Insert with nested relationships
158
+ new_post = await Post.insert({
159
+ "title": "My Post",
160
+ "content": "Content here",
161
+ "user": {"username": "jane_doe"}, # Will automatically link to existing user
162
+ "comments": [ # Create multiple comments in a single transaction
163
+ {"text": "Great post!", "user": {"username": "reader1"}},
164
+ {"text": "Thanks for sharing", "user": {"username": "reader2"}}
165
+ ]
166
+ })
167
+ # Access nested data without requerying
168
+ print(f"Post by {new_post.user.username} with {len(new_post.comments)} comments")
169
+
170
+ # Insert with nested one-to-many relationships
171
+ publisher = await Publisher.insert({
172
+ "name": "Example Publisher",
173
+ "books": [ # List of nested objects
174
+ {
175
+ "title": "Python Mastery",
176
+ "genres": [
177
+ {"name": "Programming"},
178
+ {"name": "Education"}
179
+ ]
180
+ },
181
+ {"title": "Data Science Handbook"}
182
+ ]
183
+ })
184
+ # Access nested relationships immediately
185
+ print(f"Publisher: {publisher.name} with {len(publisher.books)} books")
186
+ print(f"First book genres: {[g.name for g in publisher.books[0].genres]}")
187
+ ```
188
+
189
+ ### Read (Retrieve)
190
+
191
+ ```python
192
+ # Select by ID
193
+ user = await User.select({"id": 1})
194
+
195
+ # Select with criteria
196
+ users = await User.select({"is_active": True}, all=True)
197
+
198
+ # Select first matching record
199
+ first_user = await User.select({"is_active": True}, first=True)
200
+
201
+ # Select all records
202
+ all_users = await User.select({}, all=True)
203
+
204
+ # Select with wildcard pattern matching
205
+ gmail_users = await User.select({"email": "*@gmail.com"}, all=True)
206
+
207
+ # Select with ordering
208
+ recent_users = await User.select({}, order_by="-created_at", all=True)
209
+
210
+ # Select with limit
211
+ latest_posts = await Post.select({}, order_by="-created_at", limit=5)
212
+ # Note: limit > 1 automatically sets all=True
213
+
214
+ # Select with multiple ordering fields
215
+ sorted_users = await User.select({}, order_by=["last_name", "first_name"], all=True)
216
+
217
+ # Select with relationship ordering
218
+ posts_by_author = await Post.select({}, order_by="user.username", all=True)
219
+ ```
220
+
221
+ ### Update
222
+
223
+ ```python
224
+ # Update by ID
225
+ user = await User.update({"is_active": False}, 1)
226
+
227
+ # Update by criteria
228
+ count = await User.update(
229
+ {"is_active": False},
230
+ {"last_login": None} # Set all users without login to inactive
231
+ )
232
+
233
+ # Update with relationships
234
+ await User.update(
235
+ {"department": {"name": "Sales"}}, # Update department relationship
236
+ {"username": "john_doe"}
237
+ )
238
+ ```
239
+
240
+ ### Delete
241
+
242
+ ```python
243
+ # Delete by ID
244
+ success = await User.delete(1)
245
+
246
+ # Delete by criteria
247
+ deleted_count = await User.delete({"is_active": False})
248
+
249
+ # Delete with compound criteria
250
+ await Post.delete({"user": {"username": "john_doe"}, "is_published": False})
251
+ ```
252
+
253
+ ## Convenient Query Methods
254
+
255
+ async-easy-model provides simplified methods for common query patterns:
256
+
257
+ ```python
258
+ # Get all records with relationships loaded (default)
259
+ users = await User.all()
260
+
261
+ # Get all records ordered by a field (ascending)
262
+ users = await User.all(order_by="username")
263
+
264
+ # Get all records ordered by a field (descending)
265
+ newest_users = await User.all(order_by="-created_at")
266
+
267
+ # Get all records ordered by multiple fields
268
+ sorted_users = await User.all(order_by=["last_name", "first_name"])
269
+
270
+ # Get all records ordered by relationship fields
271
+ books = await Book.all(order_by="author.name")
272
+
273
+ # Get the first record
274
+ user = await User.first()
275
+
276
+ # Get the most recently created user
277
+ newest_user = await User.first(order_by="-created_at")
278
+
279
+ # Get a limited number of records
280
+ recent_users = await User.limit(10)
281
+
282
+ # Get a limited number of records with ordering
283
+ top_products = await Product.limit(5, order_by="-sales")
284
+ ```
285
+
286
+ ## Enhanced Relationship Handling
287
+
288
+ Using the models defined earlier, here's how to work with relationships:
289
+
290
+ ```python
291
+ # Load all relationships automatically
292
+ post = await Post.select({"id": 1})
293
+ print(post.user.username) # Access related objects directly
294
+
295
+ # Load specific relationships
296
+ post = await Post.get_with_related(1, ["user", "comments"])
297
+
298
+ # Load relationships after fetching
299
+ post = await Post.select({"id": 1}, include_relationships=False)
300
+ await post.load_related(["user", "comments"])
301
+
302
+ # Insert with nested relationships
303
+ new_post = await Post.insert({
304
+ "title": "My Post",
305
+ "content": "Content here",
306
+ "user": {"username": "jane_doe"}, # Will automatically link to existing user
307
+ "comments": [ # Create multiple comments in a single transaction
308
+ {"text": "Great post!", "user": {"username": "reader1"}},
309
+ {"text": "Thanks for sharing", "user": {"username": "reader2"}}
310
+ ]
311
+ })
312
+ # Access nested data without requerying
313
+ print(f"Post by {new_post.user.username} with {len(new_post.comments)} comments")
314
+
315
+ # Convert to dictionary with nested relationships
316
+ post_dict = post.to_dict(include_relationships=True, max_depth=2)
317
+ ```
318
+
319
+ ## Automatic Relationship Detection
320
+
321
+ The package can automatically detect and set up bidirectional relationships between models:
322
+
323
+ ```python
324
+ class User(EasyModel, table=True):
325
+ username: str
326
+
327
+ class Post(EasyModel, table=True):
328
+ title: str
329
+ user_id: int = Field(foreign_key="user.id")
330
+
331
+ # After init_db():
332
+ # - post.user relationship is automatically available
333
+ # - user.posts relationship is automatically available
334
+ ```
335
+
336
+ ## Database Configuration
337
+
338
+ ```python
339
+ # SQLite Configuration
340
+ db_config.configure_sqlite("database.db")
341
+ db_config.configure_sqlite(":memory:") # In-memory database
342
+
343
+ # PostgreSQL Configuration
344
+ db_config.configure_postgres(
345
+ user="your_user",
346
+ password="your_password",
347
+ host="localhost",
348
+ port="5432",
349
+ database="your_database"
350
+ )
351
+
352
+ # Custom Connection URL
353
+ db_config.set_connection_url("postgresql+asyncpg://user:password@localhost:5432/database")
354
+ ```
355
+
356
+ ## Documentation
357
+
358
+ For more detailed documentation, please visit the [GitHub repository](https://github.com/puntorigen/easy-model) or refer to the [DOCS.md](https://github.com/puntorigen/easy-model/blob/master/DOCS.md) file.
359
+
360
+ ## License
361
+
362
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,324 @@
1
+ # async-easy-model
2
+
3
+ A simplified SQLModel-based ORM for async database operations in Python. async-easy-model provides a clean, intuitive interface for common database operations while leveraging the power of SQLModel and SQLAlchemy.
4
+
5
+ <p align="center">
6
+ <img src="https://img.shields.io/pypi/v/async-easy-model" alt="PyPI Version">
7
+ <img src="https://img.shields.io/pypi/pyversions/async-easy-model" alt="Python Versions">
8
+ <img src="https://img.shields.io/github/license/puntorigen/easy_model" alt="License">
9
+ </p>
10
+
11
+ ## Features
12
+
13
+ - 🚀 Easy-to-use async database operations with standardized methods
14
+ - 🔄 Intuitive APIs with sensible defaults for rapid development
15
+ - 📊 Dictionary-based CRUD operations (select, insert, update, delete)
16
+ - 🔗 Enhanced relationship handling with eager loading and nested operations
17
+ - 🔍 Powerful query methods with flexible ordering support
18
+ - ⚙️ Automatic relationship detection and bidirectional setup
19
+ - 📱 Support for both PostgreSQL and SQLite databases
20
+ - 🛠️ Built on top of SQLModel and SQLAlchemy for robust performance
21
+ - 📝 Type hints for better IDE support
22
+ - 🕒 Automatic `id`, `created_at` and `updated_at` fields provided by default
23
+ - 🔄 Automatic schema migrations for evolving database models
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install async-easy-model
29
+ ```
30
+
31
+ ## Basic Usage
32
+
33
+ ```python
34
+ from async_easy_model import EasyModel, init_db, db_config, Field
35
+ from typing import Optional
36
+ from datetime import datetime
37
+
38
+ # Configure your database
39
+ db_config.configure_sqlite("database.db")
40
+
41
+ # Define your model
42
+ class User(EasyModel, table=True):
43
+ #no need to specify id, created_at or updated_at since EasyModel provides them by default
44
+ username: str = Field(unique=True)
45
+ email: str
46
+
47
+ # Initialize your database
48
+ async def setup():
49
+ await init_db()
50
+
51
+ # Use it in your async code
52
+ async def main():
53
+ await setup()
54
+ # Create a new user
55
+ user = await User.insert({
56
+ "username": "john_doe",
57
+ "email": "john@example.com"
58
+ })
59
+
60
+ # Get user ID
61
+ print(f"New user id: {user.id}")
62
+ ```
63
+
64
+ ## CRUD Operations
65
+
66
+ First, let's define some models that we'll use throughout the examples:
67
+
68
+ ```python
69
+ from async_easy_model import EasyModel, Field
70
+ from typing import Optional, List
71
+ from datetime import datetime
72
+
73
+ class User(EasyModel, table=True):
74
+ username: str = Field(unique=True)
75
+ email: str
76
+ is_active: bool = Field(default=True)
77
+
78
+ class Post(EasyModel, table=True):
79
+ title: str
80
+ content: str
81
+ user_id: Optional[int] = Field(default=None, foreign_key="user.id")
82
+
83
+ class Comment(EasyModel, table=True):
84
+ text: str
85
+ post_id: Optional[int] = Field(default=None, foreign_key="post.id")
86
+ user_id: Optional[int] = Field(default=None, foreign_key="user.id")
87
+
88
+ class Department(EasyModel, table=True):
89
+ name: str = Field(unique=True)
90
+
91
+ class Product(EasyModel, table=True):
92
+ name: str
93
+ price: float
94
+ sales: int = Field(default=0)
95
+
96
+ class Book(EasyModel, table=True):
97
+ title: str
98
+ author_id: Optional[int] = Field(default=None, foreign_key="author.id")
99
+
100
+ class Author(EasyModel, table=True):
101
+ name: str
102
+ ```
103
+
104
+ ### Create (Insert)
105
+
106
+ ```python
107
+ # Insert a single record
108
+ user = await User.insert({
109
+ "username": "john_doe",
110
+ "email": "john@example.com"
111
+ })
112
+
113
+ # Insert multiple records
114
+ users = await User.insert([
115
+ {"username": "user1", "email": "user1@example.com"},
116
+ {"username": "user2", "email": "user2@example.com"}
117
+ ])
118
+
119
+ # Insert with nested relationships
120
+ new_post = await Post.insert({
121
+ "title": "My Post",
122
+ "content": "Content here",
123
+ "user": {"username": "jane_doe"}, # Will automatically link to existing user
124
+ "comments": [ # Create multiple comments in a single transaction
125
+ {"text": "Great post!", "user": {"username": "reader1"}},
126
+ {"text": "Thanks for sharing", "user": {"username": "reader2"}}
127
+ ]
128
+ })
129
+ # Access nested data without requerying
130
+ print(f"Post by {new_post.user.username} with {len(new_post.comments)} comments")
131
+
132
+ # Insert with nested one-to-many relationships
133
+ publisher = await Publisher.insert({
134
+ "name": "Example Publisher",
135
+ "books": [ # List of nested objects
136
+ {
137
+ "title": "Python Mastery",
138
+ "genres": [
139
+ {"name": "Programming"},
140
+ {"name": "Education"}
141
+ ]
142
+ },
143
+ {"title": "Data Science Handbook"}
144
+ ]
145
+ })
146
+ # Access nested relationships immediately
147
+ print(f"Publisher: {publisher.name} with {len(publisher.books)} books")
148
+ print(f"First book genres: {[g.name for g in publisher.books[0].genres]}")
149
+ ```
150
+
151
+ ### Read (Retrieve)
152
+
153
+ ```python
154
+ # Select by ID
155
+ user = await User.select({"id": 1})
156
+
157
+ # Select with criteria
158
+ users = await User.select({"is_active": True}, all=True)
159
+
160
+ # Select first matching record
161
+ first_user = await User.select({"is_active": True}, first=True)
162
+
163
+ # Select all records
164
+ all_users = await User.select({}, all=True)
165
+
166
+ # Select with wildcard pattern matching
167
+ gmail_users = await User.select({"email": "*@gmail.com"}, all=True)
168
+
169
+ # Select with ordering
170
+ recent_users = await User.select({}, order_by="-created_at", all=True)
171
+
172
+ # Select with limit
173
+ latest_posts = await Post.select({}, order_by="-created_at", limit=5)
174
+ # Note: limit > 1 automatically sets all=True
175
+
176
+ # Select with multiple ordering fields
177
+ sorted_users = await User.select({}, order_by=["last_name", "first_name"], all=True)
178
+
179
+ # Select with relationship ordering
180
+ posts_by_author = await Post.select({}, order_by="user.username", all=True)
181
+ ```
182
+
183
+ ### Update
184
+
185
+ ```python
186
+ # Update by ID
187
+ user = await User.update({"is_active": False}, 1)
188
+
189
+ # Update by criteria
190
+ count = await User.update(
191
+ {"is_active": False},
192
+ {"last_login": None} # Set all users without login to inactive
193
+ )
194
+
195
+ # Update with relationships
196
+ await User.update(
197
+ {"department": {"name": "Sales"}}, # Update department relationship
198
+ {"username": "john_doe"}
199
+ )
200
+ ```
201
+
202
+ ### Delete
203
+
204
+ ```python
205
+ # Delete by ID
206
+ success = await User.delete(1)
207
+
208
+ # Delete by criteria
209
+ deleted_count = await User.delete({"is_active": False})
210
+
211
+ # Delete with compound criteria
212
+ await Post.delete({"user": {"username": "john_doe"}, "is_published": False})
213
+ ```
214
+
215
+ ## Convenient Query Methods
216
+
217
+ async-easy-model provides simplified methods for common query patterns:
218
+
219
+ ```python
220
+ # Get all records with relationships loaded (default)
221
+ users = await User.all()
222
+
223
+ # Get all records ordered by a field (ascending)
224
+ users = await User.all(order_by="username")
225
+
226
+ # Get all records ordered by a field (descending)
227
+ newest_users = await User.all(order_by="-created_at")
228
+
229
+ # Get all records ordered by multiple fields
230
+ sorted_users = await User.all(order_by=["last_name", "first_name"])
231
+
232
+ # Get all records ordered by relationship fields
233
+ books = await Book.all(order_by="author.name")
234
+
235
+ # Get the first record
236
+ user = await User.first()
237
+
238
+ # Get the most recently created user
239
+ newest_user = await User.first(order_by="-created_at")
240
+
241
+ # Get a limited number of records
242
+ recent_users = await User.limit(10)
243
+
244
+ # Get a limited number of records with ordering
245
+ top_products = await Product.limit(5, order_by="-sales")
246
+ ```
247
+
248
+ ## Enhanced Relationship Handling
249
+
250
+ Using the models defined earlier, here's how to work with relationships:
251
+
252
+ ```python
253
+ # Load all relationships automatically
254
+ post = await Post.select({"id": 1})
255
+ print(post.user.username) # Access related objects directly
256
+
257
+ # Load specific relationships
258
+ post = await Post.get_with_related(1, ["user", "comments"])
259
+
260
+ # Load relationships after fetching
261
+ post = await Post.select({"id": 1}, include_relationships=False)
262
+ await post.load_related(["user", "comments"])
263
+
264
+ # Insert with nested relationships
265
+ new_post = await Post.insert({
266
+ "title": "My Post",
267
+ "content": "Content here",
268
+ "user": {"username": "jane_doe"}, # Will automatically link to existing user
269
+ "comments": [ # Create multiple comments in a single transaction
270
+ {"text": "Great post!", "user": {"username": "reader1"}},
271
+ {"text": "Thanks for sharing", "user": {"username": "reader2"}}
272
+ ]
273
+ })
274
+ # Access nested data without requerying
275
+ print(f"Post by {new_post.user.username} with {len(new_post.comments)} comments")
276
+
277
+ # Convert to dictionary with nested relationships
278
+ post_dict = post.to_dict(include_relationships=True, max_depth=2)
279
+ ```
280
+
281
+ ## Automatic Relationship Detection
282
+
283
+ The package can automatically detect and set up bidirectional relationships between models:
284
+
285
+ ```python
286
+ class User(EasyModel, table=True):
287
+ username: str
288
+
289
+ class Post(EasyModel, table=True):
290
+ title: str
291
+ user_id: int = Field(foreign_key="user.id")
292
+
293
+ # After init_db():
294
+ # - post.user relationship is automatically available
295
+ # - user.posts relationship is automatically available
296
+ ```
297
+
298
+ ## Database Configuration
299
+
300
+ ```python
301
+ # SQLite Configuration
302
+ db_config.configure_sqlite("database.db")
303
+ db_config.configure_sqlite(":memory:") # In-memory database
304
+
305
+ # PostgreSQL Configuration
306
+ db_config.configure_postgres(
307
+ user="your_user",
308
+ password="your_password",
309
+ host="localhost",
310
+ port="5432",
311
+ database="your_database"
312
+ )
313
+
314
+ # Custom Connection URL
315
+ db_config.set_connection_url("postgresql+asyncpg://user:password@localhost:5432/database")
316
+ ```
317
+
318
+ ## Documentation
319
+
320
+ For more detailed documentation, please visit the [GitHub repository](https://github.com/puntorigen/easy-model) or refer to the [DOCS.md](https://github.com/puntorigen/easy-model/blob/master/DOCS.md) file.
321
+
322
+ ## License
323
+
324
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -6,7 +6,7 @@ from typing import Optional, Any
6
6
  from .model import EasyModel, init_db, db_config
7
7
  from sqlmodel import Field, Relationship as SQLModelRelationship
8
8
 
9
- __version__ = "0.1.12"
9
+ __version__ = "0.2.3"
10
10
  __all__ = ["EasyModel", "init_db", "db_config", "Field", "Relationship", "Relation", "enable_auto_relationships", "disable_auto_relationships", "process_auto_relationships", "MigrationManager", "check_and_migrate_models"]
11
11
 
12
12
  # Create a more user-friendly Relationship function