ohmyapi 0.1.4__py3-none-any.whl → 0.1.6__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.
ohmyapi/core/runtime.py CHANGED
@@ -15,67 +15,6 @@ from fastapi import FastAPI, APIRouter
15
15
  from ohmyapi.db.model import Model
16
16
 
17
17
 
18
- class App:
19
- """App container holding runtime data like detected models and routes."""
20
-
21
- def __init__(self, project: "OhMyAPI Project", name: str):
22
- self.project = project
23
- self.name = name
24
-
25
- # The list of module paths (e.g. "ohmyapi_auth.models") for Tortoise and Aerich
26
- self.model_modules: List[str] = []
27
-
28
- # The APIRouter
29
- self.router: Optional[APIRouter] = None
30
-
31
- # Import the app, so its __init__.py runs.
32
- importlib.import_module(self.name)
33
-
34
- # Load the models
35
- try:
36
- models_mod = importlib.import_module(f"{self.name}.models")
37
- self.model_modules.append(f"{self.name}.models")
38
- except ModuleNotFoundError:
39
- pass
40
-
41
- # Locate the APIRouter
42
- try:
43
- routes_mod = importlib.import_module(f"{self.name}.routes")
44
- router = getattr(routes_mod, "router", None)
45
- if isinstance(router, APIRouter):
46
- self.router = router
47
- except ModuleNotFoundError:
48
- pass
49
-
50
- def __repr__(self):
51
- out = ""
52
- out += f"App: {self.name}\n"
53
- out += f"Models:\n"
54
- for model in self.models:
55
- out += f" - {model.__name__}\n"
56
- out += "Routes:\n"
57
- for route in (self.routes or []):
58
- out += f" - {route}\n"
59
- return out
60
-
61
- def __str__(self):
62
- return self.__repr__()
63
-
64
- @property
65
- def models(self) -> List[Model]:
66
- models: List[Model] = []
67
- for mod in self.model_modules:
68
- models_mod = importlib.import_module(mod)
69
- for obj in models_mod.__dict__.values():
70
- if isinstance(obj, type) and getattr(obj, "_meta", None) is not None and obj.__name__ != 'Model':
71
- models.append(obj)
72
- return models
73
-
74
- @property
75
- def routes(self):
76
- return self.router.routes
77
-
78
-
79
18
  class Project:
80
19
  """
81
20
  Project runtime loader + Tortoise/Aerich integration.
@@ -244,3 +183,65 @@ class Project:
244
183
  # No migrations yet, initialize then retry upgrade
245
184
  await c.init_db(safe=True)
246
185
  await c.upgrade()
186
+
187
+
188
+ class App:
189
+ """App container holding runtime data like detected models and routes."""
190
+
191
+ def __init__(self, project: Project, name: str):
192
+ self.project = project
193
+ self.name = name
194
+
195
+ # The list of module paths (e.g. "ohmyapi_auth.models") for Tortoise and Aerich
196
+ self.model_modules: List[str] = []
197
+
198
+ # The APIRouter
199
+ self.router: Optional[APIRouter] = None
200
+
201
+ # Import the app, so its __init__.py runs.
202
+ importlib.import_module(self.name)
203
+
204
+ # Load the models
205
+ try:
206
+ models_mod = importlib.import_module(f"{self.name}.models")
207
+ self.model_modules.append(f"{self.name}.models")
208
+ except ModuleNotFoundError:
209
+ pass
210
+
211
+ # Locate the APIRouter
212
+ try:
213
+ routes_mod = importlib.import_module(f"{self.name}.routes")
214
+ router = getattr(routes_mod, "router", None)
215
+ if isinstance(router, APIRouter):
216
+ self.router = router
217
+ except ModuleNotFoundError:
218
+ pass
219
+
220
+ def __repr__(self):
221
+ out = ""
222
+ out += f"App: {self.name}\n"
223
+ out += f"Models:\n"
224
+ for model in self.models:
225
+ out += f" - {model.__name__}\n"
226
+ out += "Routes:\n"
227
+ for route in (self.routes or []):
228
+ out += f" - {route}\n"
229
+ return out
230
+
231
+ def __str__(self):
232
+ return self.__repr__()
233
+
234
+ @property
235
+ def models(self) -> List[Model]:
236
+ models: List[Model] = []
237
+ for mod in self.model_modules:
238
+ models_mod = importlib.import_module(mod)
239
+ for obj in models_mod.__dict__.values():
240
+ if isinstance(obj, type) and getattr(obj, "_meta", None) is not None and obj.__name__ != 'Model':
241
+ models.append(obj)
242
+ return models
243
+
244
+ @property
245
+ def routes(self):
246
+ return self.router.routes
247
+
@@ -55,7 +55,7 @@ def startapp(name: str, project: str):
55
55
  """Create a new app inside a project: templates go into <project_dir>/<name>/"""
56
56
  target_dir = Path(project)
57
57
  os.makedirs(target_dir, exist_ok=True)
58
- render_template_dir("app", target_dir, {"project_name": project, "app_name": name}, subdir_name=name)
58
+ render_template_dir("app", target_dir, {"project_name": target_dir.resolve().name, "app_name": name}, subdir_name=name)
59
59
  print(f"✅ App '{name}' created in project '{target_dir}' successfully.")
60
60
  print(f"🔧 Remember to add '{name}' to your INSTALLED_APPS!")
61
61
 
@@ -1,6 +1,6 @@
1
1
  from ohmyapi.db import Model, field
2
2
 
3
3
 
4
- class MyModel(Model):
5
- id: int = field.IntField(min=1, pk=True)
6
- ...
4
+ # class MyModel(Model):
5
+ # id: int = field.IntField(min=1, pk=True)
6
+ # ...
@@ -1,5 +1,7 @@
1
1
  # {{ project_name }} settings.py
2
2
  PROJECT_NAME = "MyProject"
3
3
  DATABASE_URL = "sqlite://db.sqlite3"
4
- INSTALLED_APPS = []
4
+ INSTALLED_APPS = [
5
+ #'ohmyapi_auth',
6
+ ]
5
7
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ohmyapi
3
- Version: 0.1.4
3
+ Version: 0.1.6
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
@@ -5,19 +5,18 @@ ohmyapi/builtin/auth/permissions.py,sha256=gPBf01UNgXjU3v3DwMSYpKjayZSnwksp-ji4C
5
5
  ohmyapi/builtin/auth/routes.py,sha256=5jLq92z4TJw4eyiIJ5t7MwRNtYlpN7suDwW28JeEQYA,4902
6
6
  ohmyapi/cli.py,sha256=DaSf1uYxv1bD1XBwVN_rn4F7hq9AlvXwtWzbVw7WPBw,3472
7
7
  ohmyapi/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- ohmyapi/core/runtime.py,sha256=GmY3GpJRupDA8-54FHF-nyzmRaa4muDflySlC6-XQIA,8586
9
- ohmyapi/core/scaffolding.py,sha256=KsV2uNX3hSRYutLmu3IhPjVTQTMnxwGqxbJij-fhGGk,2554
8
+ ohmyapi/core/runtime.py,sha256=l5zffc4VTwQOo7G9mfiYHsPGapMONRX_jtO_z9QaKHU,8577
9
+ ohmyapi/core/scaffolding.py,sha256=iMymscokJ-YqzB0ZTC-gcc2T71o73577j9tnb2x8lH8,2572
10
10
  ohmyapi/core/templates/app/__init__.py.j2,sha256=QwVIQVUGZVhdH1d4NrvL7NTsK4-T4cihzYs8UVX2dt4,43
11
- ohmyapi/core/templates/app/models.py.j2,sha256=X0btKhxTUPAv8E1HQm14tcqXIIhrKobPjrNdpOXNOqk,113
11
+ ohmyapi/core/templates/app/models.py.j2,sha256=_3w-vFJ5fgsmncsCv34k_wyCMF78jufbSSglns4gbb0,119
12
12
  ohmyapi/core/templates/app/routes.py.j2,sha256=Ee3xeVdM_G5-TRw14_C6siJTrEXtnRUD5xhcHCbu5QA,229
13
13
  ohmyapi/core/templates/project/pyproject.toml.j2,sha256=rk5baSS-nhW2mbdl60CHoXmeTBkqnzUEMwrRNxUnkt4,250
14
- ohmyapi/core/templates/project/settings.py.j2,sha256=c8hHo5DHxNLtam_8Sk8bLYxrjhgegwpk_Rt6UFPiZRY,118
14
+ ohmyapi/core/templates/project/settings.py.j2,sha256=RBKGB8MZWPM3Bp0a57Y1YrSvSXxh502TUnJqbbu48Ig,138
15
15
  ohmyapi/db/__init__.py,sha256=p5oXqYUKT6eAoE-9JD-p6zKo9s-H84rJbrKxFna8Kvc,63
16
- ohmyapi/db/migration_manager.py,sha256=dTabeDyd6ZIa0lORlKRuiLnBTcsVAgUjgrO9_bew6pQ,3621
17
16
  ohmyapi/db/model/__init__.py,sha256=owKYpx5a2ZFTBgBqyEKN09AvY1cSP0dy1O7d3_sUVgM,33
18
17
  ohmyapi/db/model/model.py,sha256=PSzK_d8IZQExSRuTrEyPnqfa4GENQhbBZsVxxLWTR4g,1570
19
18
  ohmyapi/router.py,sha256=RzDXrtJJrk4eWdt9qoKBfz6g0S5WZq2hDQoFy5whR6A,40
20
- ohmyapi-0.1.4.dist-info/METADATA,sha256=MoXGVAZlEAlxPpHNMgnoDKD9BsNOQ7uJW8entVmYAvs,4268
21
- ohmyapi-0.1.4.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
22
- ohmyapi-0.1.4.dist-info/entry_points.txt,sha256=ZCZJLw_ojguyr1WOmb8UwHrr42hiLj6-Kzh4mMa_7Ns,44
23
- ohmyapi-0.1.4.dist-info/RECORD,,
19
+ ohmyapi-0.1.6.dist-info/METADATA,sha256=aLe3O1xcYRb-a_WG6w4QkWxneATuaHjdmWZezxBcxhw,4268
20
+ ohmyapi-0.1.6.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
21
+ ohmyapi-0.1.6.dist-info/entry_points.txt,sha256=ZCZJLw_ojguyr1WOmb8UwHrr42hiLj6-Kzh4mMa_7Ns,44
22
+ ohmyapi-0.1.6.dist-info/RECORD,,
@@ -1,90 +0,0 @@
1
- import asyncio
2
- from pathlib import Path
3
- from aerich import Command
4
- from ohmyapi.core import runtime
5
-
6
-
7
- class MigrationManager:
8
- def __init__(self, project):
9
- self.project = project
10
- self._commands = {}
11
- # Compute tortoise_config grouped by app module
12
- self._tortoise_config = self._build_tortoise_config()
13
-
14
- def _build_tortoise_config(self) -> dict:
15
- """
16
- Build Tortoise config from the flat model_registry,
17
- grouping models by app module for Aerich compatibility.
18
- """
19
- db_url = self.project.settings.DATABASE_URL
20
- registry = self.project.model_registry # flat: model_path -> class
21
-
22
- apps_modules = {}
23
- for model_path, model_cls in registry.items():
24
- if not isinstance(model_cls, type):
25
- raise TypeError(f"Registry value must be a class, got {type(model_cls)}: {model_cls}")
26
- # Extract app module by removing the model class name
27
- # Example: 'ohmyapi.apps.auth.User' -> 'ohmyapi.apps.auth'
28
- app_module = ".".join(model_path.split(".")[:-1])
29
- apps_modules.setdefault(app_module, []).append(model_cls)
30
-
31
- # Build Tortoise config
32
- apps_config = {}
33
- for app_module, models in apps_modules.items():
34
- modules_set = set(m.__module__ for m in models)
35
- apps_config[app_module] = {
36
- "models": list(modules_set),
37
- "default_connection": "default",
38
- }
39
-
40
- return {
41
- "connections": {"default": db_url},
42
- "apps": apps_config,
43
- }
44
-
45
- def get_apps(self):
46
- """Return app modules extracted from the registry"""
47
- return list(self._tortoise_config["apps"].keys())
48
-
49
- def get_migration_location(self, app_module: str) -> str:
50
- """Return the path to the app's migrations folder"""
51
- try:
52
- module = __import__(app_module, fromlist=["migrations"])
53
- if not hasattr(module, "__file__") or module.__file__ is None:
54
- raise ValueError(f"Cannot determine filesystem path for app '{app_module}'")
55
- app_path = Path(module.__file__).parent
56
- migrations_path = app_path / "migrations"
57
- migrations_path.mkdir(exist_ok=True)
58
- return str(migrations_path)
59
- except ModuleNotFoundError:
60
- raise ValueError(f"App module '{app_module}' cannot be imported")
61
-
62
- async def init_app_command(self, app_module: str) -> Command:
63
- """Initialize Aerich command for a specific app module"""
64
- location = self.get_migration_location(app_module)
65
- cmd = Command(
66
- tortoise_config=self._tortoise_config,
67
- app=app_module,
68
- location=location,
69
- )
70
- await cmd.init()
71
- self._commands[app_module] = cmd
72
- return cmd
73
-
74
- async def makemigrations(self, app_module: str):
75
- """Generate migrations for a specific app"""
76
- cmd = self._commands.get(app_module) or await self.init_app_command(app_module)
77
- await cmd.migrate()
78
-
79
- async def migrate(self, app_module: str = None):
80
- """Apply migrations. If app_module is None, migrate all apps"""
81
- apps_to_migrate = [app_module] if app_module else self.get_apps()
82
- for app in apps_to_migrate:
83
- cmd = self._commands.get(app) or await self.init_app_command(app)
84
- await cmd.upgrade()
85
-
86
- async def show_migrations(self, app_module: str):
87
- """List migrations for an app"""
88
- cmd = self._commands.get(app_module) or await self.init_app_command(app_module)
89
- await cmd.history()
90
-