ohmyapi 0.1.12__py3-none-any.whl → 0.1.14__py3-none-any.whl

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.
@@ -1,5 +1,7 @@
1
+ from functools import wraps
1
2
  from typing import Optional, List
2
- from ohmyapi.db import Model, field
3
+ from ohmyapi.router import HTTPException
4
+ from ohmyapi.db import Model, field, pre_save, pre_delete
3
5
  from passlib.context import CryptContext
4
6
  from tortoise.contrib.pydantic import pydantic_queryset_creator
5
7
 
@@ -7,24 +9,22 @@ pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
7
9
 
8
10
 
9
11
  class Group(Model):
10
- id = field.data.UUIDField(pk=True)
11
- name = field.CharField(max_length=42, index=True)
12
+ id: str = field.data.UUIDField(pk=True)
13
+ name: str = field.CharField(max_length=42, index=True)
12
14
 
13
15
 
14
16
  class User(Model):
15
- id = field.data.UUIDField(pk=True)
16
- email = field.CharField(max_length=255, unique=True, index=True)
17
- username = field.CharField(max_length=150, unique=True)
18
- password_hash = field.CharField(max_length=128)
19
- is_admin = field.BooleanField(default=False)
20
- is_staff = field.BooleanField(default=False)
21
- groups: Optional[List[Group]] = field.ManyToManyField("ohmyapi_auth.Group", related_name="users")
22
-
17
+ id: str = field.data.UUIDField(pk=True)
18
+ email: str = field.CharField(max_length=255, unique=True, index=True)
19
+ username: str = field.CharField(max_length=150, unique=True)
20
+ password_hash: str = field.CharField(max_length=128)
21
+ is_admin: bool = field.BooleanField(default=False)
22
+ is_staff: bool = field.BooleanField(default=False)
23
+ groups: field.ManyToManyRelation[Group] = field.ManyToManyField("ohmyapi_auth.Group", related_name="users", through='user_groups')
23
24
 
24
25
  class Schema:
25
26
  exclude = 'password_hash',
26
27
 
27
-
28
28
  def set_password(self, raw_password: str) -> None:
29
29
  """Hash and store the password."""
30
30
  self.password_hash = pwd_context.hash(raw_password)
@@ -40,4 +40,3 @@ class User(Model):
40
40
  if user and user.verify_password(password):
41
41
  return user
42
42
  return None
43
-
@@ -160,5 +160,5 @@ async def introspect(token: Dict = Depends(get_token)):
160
160
  @router.get("/me")
161
161
  async def me(user: User = Depends(get_current_user)):
162
162
  """Return the currently authenticated user."""
163
- return user
163
+ return User.Schema.one.from_orm(user)
164
164
 
ohmyapi/cli.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import atexit
2
3
  import importlib
3
4
  import sys
4
5
  import typer
@@ -45,6 +46,28 @@ def shell(root: str = "."):
45
46
  project_path = Path(root).resolve()
46
47
  project = runtime.Project(project_path)
47
48
 
49
+ # Ensure the ORM is shutdown
50
+ async def close_project():
51
+ try:
52
+ await project.close_orm()
53
+ print("Tortoise ORM closed successfully.")
54
+ except Exception as e:
55
+ print(f"Error closing ORM: {e}")
56
+
57
+ def cleanup():
58
+ loop = None
59
+ try:
60
+ loop = asyncio.get_running_loop()
61
+ except RuntimeError:
62
+ pass
63
+ if loop and loop.is_running():
64
+ asyncio.create_task(close_project())
65
+ else:
66
+ asyncio.run(close_project())
67
+
68
+ # Ensure the ORM is initialized
69
+ asyncio.run(project.init_orm())
70
+
48
71
  try:
49
72
  from IPython import start_ipython
50
73
  shell_vars = {
@@ -56,11 +79,13 @@ def shell(root: str = "."):
56
79
  c.TerminalInteractiveShell.banner2 = banner.format(**{
57
80
  "project_name": f"{f'{project.settings.PROJECT_NAME} ' if getattr(project.settings, 'PROJECT_NAME', '') else ''}[{Path(project_path).resolve()}]",
58
81
  })
82
+ atexit.register(cleanup)
59
83
  start_ipython(argv=[], user_ns=shell_vars, config=c)
60
84
  except ImportError:
61
85
  typer.echo("IPython is not installed. Falling back to built-in Python shell.")
62
86
  import code
63
- code.interact(local={"settings": project.settings})
87
+ atexit.register(cleanup)
88
+ code.interact(local={"p": project})
64
89
 
65
90
 
66
91
  @app.command()
ohmyapi/db/__init__.py CHANGED
@@ -1,3 +1,10 @@
1
1
  from .model import Model, field
2
2
  from tortoise.manager import Manager
3
+ from tortoise.queryset import QuerySet
4
+ from tortoise.signals import (
5
+ pre_delete,
6
+ post_delete,
7
+ pre_save,
8
+ post_save,
9
+ )
3
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ohmyapi
3
- Version: 0.1.12
3
+ Version: 0.1.14
4
4
  Summary: A Django-like but async web-framework based on FastAPI and TortoiseORM.
5
5
  License-Expression: MIT
6
6
  Keywords: fastapi,tortoise,orm,async,web-framework
@@ -52,11 +52,11 @@ It is ***blazingly fast***, ***fun to use*** and comes with ***batteries include
52
52
  - Highly configurable and customizable
53
53
  - 100% async
54
54
 
55
- OhMyAPI aims to:
55
+ **Goals**
56
56
 
57
57
  - combine FastAPI, TortoiseORM and Aerich migrations into a high-productivity web-application framework
58
- - tying everything neatly together into a project structure consisting of apps with models and a router
59
- - while ***AVOIDING*** to introduce any additional abstractions ontop of Tortoise's model-system or FastAPI's routing
58
+ - tie everything neatly together into a concise API
59
+ - while ***AVOIDING*** any additional abstractions ontop of Tortoise's model-system or FastAPI's routing system
60
60
 
61
61
  ---
62
62
 
@@ -173,8 +173,8 @@ async def list():
173
173
  @router.get("/:id")
174
174
  async def get(id: str):
175
175
  try:
176
- queryset = Tournament.get(pk=id)
177
- return await Tournament.Schema.one(queryset)
176
+ tournament = await Tournament.get(pk=id)
177
+ return await Tournament.Schema.one.form_orm(tournament)
178
178
  except DoesNotExist:
179
179
  raise HTTPException(status_code=404, detail="item not found")
180
180
 
@@ -353,12 +353,17 @@ Out[2]:
353
353
  Routes:
354
354
  - APIRoute(path='/auth/login', name='login', methods=['POST'])
355
355
  - APIRoute(path='/auth/refresh', name='refresh_token', methods=['POST'])
356
- - APIRoute(path='/auth/me', name='me', methods=['GET'])
357
- - APIRoute(path='/auth/introspect', name='introspect', methods=['GET'])}
356
+ - APIRoute(path='/auth/introspect', name='introspect', methods=['GET'])
357
+ - APIRoute(path='/auth/me', name='me', methods=['GET']),
358
+ 'tournament': App: tournament
359
+ Models:
360
+ - Tournament
361
+ - Event
362
+ - Team
363
+ Routes:
364
+ - APIRoute(path='/tournament/', name='list', methods=['GET'])}
358
365
 
359
366
  In [3]: from tournament.models import Tournament
360
- Out[3]:
361
-
362
367
  ```
363
368
 
364
369
 
@@ -1,10 +1,10 @@
1
1
  ohmyapi/__init__.py,sha256=UmLNQImTbKvHEgwQB2Wsyl6fq88X92imL9QZYJpQX4I,18
2
2
  ohmyapi/__main__.py,sha256=wcCrL4PjG51r5wVKqJhcoJPTLfHW0wNbD31DrUN0MWI,28
3
3
  ohmyapi/builtin/auth/__init__.py,sha256=TY1RKgwWmJ6FKz_v4J3m0Ang69qSmtVDLe4rqjLk4-E,69
4
- ohmyapi/builtin/auth/models.py,sha256=Xsxn9m5RTgY2a0PPfW3wTj77ocuuISytdl4ec_TR_kw,1524
4
+ ohmyapi/builtin/auth/models.py,sha256=ubdDwVKgU8q8K58a_lR93xCveQGcdM8hTyusgVx8rK0,1687
5
5
  ohmyapi/builtin/auth/permissions.py,sha256=jf-I2b9rIOw2EF4Kga-_Bz1ZPPHU0vHNaXGrDQSwhSI,145
6
- ohmyapi/builtin/auth/routes.py,sha256=iMxmgP6TSpMrtSKf-g7mc60NcOiw8FRkngUroalGCyk,5519
7
- ohmyapi/cli.py,sha256=qCGi9GtgybCh_jb_NVwu9dlG9XTbilg6qnXop2IIgC8,3768
6
+ ohmyapi/builtin/auth/routes.py,sha256=re3w7fZ9q9tUXDsQtkFcKizuEmtjxnebVA2lIO7afkM,5545
7
+ ohmyapi/cli.py,sha256=Mip1eBKYyu1hmUHbNW-1kSMc05EJOTVXqdI0c0r_B4g,4440
8
8
  ohmyapi/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  ohmyapi/core/runtime.py,sha256=l5zffc4VTwQOo7G9mfiYHsPGapMONRX_jtO_z9QaKHU,8577
10
10
  ohmyapi/core/scaffolding.py,sha256=iMymscokJ-YqzB0ZTC-gcc2T71o73577j9tnb2x8lH8,2572
@@ -14,12 +14,12 @@ ohmyapi/core/templates/app/routes.py.j2,sha256=o3XEBZDfHRhodx-6rX1ebnKpqqd-QApfw
14
14
  ohmyapi/core/templates/project/README.md.j2,sha256=SjR4JIrg-8XRE-UntUDwiw8jDpYitD_UjwoKkYJ7GLw,22
15
15
  ohmyapi/core/templates/project/pyproject.toml.j2,sha256=X0VS6YT9aL3vpHFKPTfLFsdpD8423nY57ySQpSTMxmQ,895
16
16
  ohmyapi/core/templates/project/settings.py.j2,sha256=RBKGB8MZWPM3Bp0a57Y1YrSvSXxh502TUnJqbbu48Ig,138
17
- ohmyapi/db/__init__.py,sha256=PaDrioQ1lkFAo7Al82MoV6duQeJF0dTQ7EG0TzKOOIM,70
17
+ ohmyapi/db/__init__.py,sha256=T7AUWlEXD--WOn01mKPIpkxPVwmgYHZQ4vQo3ejOkgE,204
18
18
  ohmyapi/db/exceptions.py,sha256=I7AubrdqQF_UvAvzKqz2ve08-BkXHzEWXnwG300StHE,35
19
19
  ohmyapi/db/model/__init__.py,sha256=k3StTNuKatpwZo_Z5JBFa-927eJrzibFE8U4SA82asc,32
20
20
  ohmyapi/db/model/model.py,sha256=BajFtLlQ1s0mZ2hj-_JNQhLQmxuVe-Lw2LuW5t2C7Rw,1579
21
21
  ohmyapi/router.py,sha256=hutccsrP9RT8W5O6uBDhOJehwqrkRoPzaUI5zoHPh9A,55
22
- ohmyapi-0.1.12.dist-info/METADATA,sha256=i8wVhc1RwYUKSXXQmffQCMcuawbKmD07yu48rxK3zOY,8673
23
- ohmyapi-0.1.12.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
24
- ohmyapi-0.1.12.dist-info/entry_points.txt,sha256=wb3lw8-meAlpiv1mqcQ3m25ukL7djagU_w89GkrC37k,43
25
- ohmyapi-0.1.12.dist-info/RECORD,,
22
+ ohmyapi-0.1.14.dist-info/METADATA,sha256=phAamjzQNPXdbFSrrGk_qH4CxECl5UmwTp0KiTpatWE,8766
23
+ ohmyapi-0.1.14.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
24
+ ohmyapi-0.1.14.dist-info/entry_points.txt,sha256=wb3lw8-meAlpiv1mqcQ3m25ukL7djagU_w89GkrC37k,43
25
+ ohmyapi-0.1.14.dist-info/RECORD,,