Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,17 @@ def handle(self) -> int:

self.info(f"Model created: {os.path.join(model_directory, file_name)}")
if self.option("migration"):
migrations_directory = self.option("migrations-directory")
table = tableize(name)
if self.option("table"):
self.call(
"migration",
f"update_{tableize(name)}_table --table {tableize(name)} --directory {migrations_directory}",
)
arguments = f"update_{table}_table --table {table}"
else:
self.call(
"migration",
f"create_{tableize(name)}_table --create {tableize(name)} --directory {migrations_directory}",
)
arguments = f"create_{table}_table --create {table}"
self.call_command("db:make:migration", f"{arguments} --directory {self.option('migrations-directory')}")

if self.option("seeder"):
directory = self.option("seeders-directory")
self.call("seed", f"{self.argument('name')} --directory {directory}")
self.call_command("seed", f"{name} --directory {self.option('seeders-directory')}")

return 0

def call_command(self, name: str, arguments: str) -> int:
return self.call(name, f"{name} {arguments}")
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


class MakeObserverCommand(Command):
name = "observer"
name = "db:make:observer"
description = "Creates a new observer file."

arguments = [argument("name", description="The name of the observer")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
""" __CLASS__ Model """

from masoniteorm.models import Model
from fastapi_startkit.masoniteorm.models import Model


class __CLASS__(Model):
"""__CLASS__ Model"""

pass
Original file line number Diff line number Diff line change
@@ -1,101 +1,27 @@
"""__CLASS__ Observer"""

from masoniteorm.models import Model
from fastapi_startkit.masoniteorm.models import Model


class __CLASS__Observer:
def created(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "created" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def saving(self, __MODEL_VARIABLE__: Model) -> None:
pass

def creating(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "creating" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def creating(self, __MODEL_VARIABLE__: Model) -> None:
pass

def saving(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "saving" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def updating(self, __MODEL_VARIABLE__: Model) -> None:
pass

def saved(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "saved" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def created(self, __MODEL_VARIABLE__: Model) -> None:
pass

def updating(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "updating" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def updated(self, __MODEL_VARIABLE__: Model) -> None:
pass

def updated(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "updated" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def saved(self, __MODEL_VARIABLE__: Model) -> None:
pass

def booted(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "booted" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
pass

def booting(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "booting" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def deleting(self, __MODEL_VARIABLE__: Model) -> None:
pass

def hydrating(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "hydrating" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
pass

def hydrated(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "hydrated" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
pass

def deleting(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "deleting" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
pass

def deleted(self, __MODEL_VARIABLE__):
"""Handle the __MODEL__ "deleted" event.

Args:
__MODEL_VARIABLE__ (masoniteorm.models.Model): __MODEL__ model.
"""
async def deleted(self, __MODEL_VARIABLE__: Model) -> None:
pass
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
DBSeedCommand,
MakeMigrationCommand,
MakeModelCommand,
MakeObserverCommand,
MakeSeedCommand,
MigrateRollbackCommand,
MigrateFreshCommand,
Expand Down Expand Up @@ -59,6 +60,7 @@ def boot(self) -> None:
MigrateStatusCommand,
MigrateRollbackCommand,
MakeModelCommand,
MakeObserverCommand,
MakeSeedCommand,
MigrateFreshCommand,
MigrateRefreshCommand,
Expand Down
86 changes: 80 additions & 6 deletions fastapi_startkit/tests/masoniteorm/commands/test_make_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from fastapi_startkit.masoniteorm.commands.MakeObserverCommand import MakeObserverCommand
from fastapi_startkit.masoniteorm.commands.MakeSeedCommand import MakeSeedCommand
from fastapi_startkit.masoniteorm.migrations.Migration import Migration
from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.seeders import Seeder

from .fixtures.app import create_app, DB_PATH
Expand All @@ -37,6 +38,12 @@ def tearDown(self):
def _tester(self, command_class):
return CommandTester(command_class())

def _load_class(self, path, class_name):
spec = importlib.util.spec_from_file_location(class_name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return getattr(module, class_name)

def _generated_file(self, directory):
files = [f for f in os.listdir(directory) if f.endswith(".py")]
self.assertEqual(len(files), 1, f"expected one generated file in {directory}, got {files}")
Expand Down Expand Up @@ -189,6 +196,50 @@ def test_creates_model_file(self):
content = open(os.path.join("app", "Post.py")).read()
self.assertIn("class Post(Model)", content)

def test_generated_model_imports(self):
os.makedirs("app")
self._tester(MakeModelCommand).execute("Post")

content = open(os.path.join("app", "Post.py")).read()
self.assertIn("from fastapi_startkit.masoniteorm.models import Model", content)
self.assertNotIn('"""', content)

post_class = self._load_class(os.path.join("app", "Post.py"), "Post")
self.assertTrue(issubclass(post_class, Model))

def test_migration_option_creates_migration_through_console(self):
os.makedirs("app")
os.makedirs("databases/migrations")
app = create_app()

self.assertEqual(app.run("db:make:model", "Post --migration"), 0)

migration = self._generated_file("databases/migrations")
self.assertTrue(migration.endswith("_create_posts_table.py"))
content = open(migration).read()
self.assertIn('self.schema.create("posts")', content)

def test_migration_and_table_options_create_update_migration_through_console(self):
os.makedirs("app")
os.makedirs("databases/migrations")
app = create_app()

self.assertEqual(app.run("db:make:model", "Post --migration --table"), 0)

migration = self._generated_file("databases/migrations")
self.assertTrue(migration.endswith("_update_posts_table.py"))
content = open(migration).read()
self.assertIn('self.schema.table("posts")', content)

def test_seeder_option_creates_seeder_through_console(self):
os.makedirs("app")
os.makedirs("databases/seeders")
app = create_app()

self.assertEqual(app.run("db:make:model", "Post --seeder"), 0)

self.assertTrue(os.path.exists(os.path.join("databases/seeders", "post_table_seeder.py")))

def test_pep_option_uses_underscore_filename(self):
os.makedirs("app")
tester = self._tester(MakeModelCommand)
Expand Down Expand Up @@ -263,8 +314,8 @@ def _forget_modules(package):


class TestMakeObserverCommand(_TempCwdTestCase):
# make:observer emits a plain observer class with no schema side effects, so
# the generated file content is the only meaningful contract to assert.
LIFECYCLE_EVENTS = ["saving", "creating", "updating", "created", "updated", "saved", "deleting", "deleted"]

def test_creates_observer_file(self):
tester = self._tester(MakeObserverCommand)
tester.execute("Post")
Expand All @@ -273,17 +324,40 @@ def test_creates_observer_file(self):
self.assertIn("Observer created:", output)

content = open(os.path.join("app/observers", "PostObserver.py")).read()
self.assertIn("from fastapi_startkit.masoniteorm.models import Model", content)
self.assertIn("class PostObserver:", content)
self.assertIn("def created(self, post):", content)
self.assertIn("async def created(self, post: Model) -> None:", content)
self.assertNotIn('"""', content)
self.assertNotIn("#", content)

def test_model_option_controls_variable_and_type(self):
def test_model_option_controls_variable_name(self):
tester = self._tester(MakeObserverCommand)
tester.execute("Audit --model User")

content = open(os.path.join("app/observers", "AuditObserver.py")).read()
self.assertIn("class AuditObserver:", content)
self.assertIn("def created(self, user):", content)
self.assertIn("User model.", content)
self.assertIn("async def created(self, user: Model) -> None:", content)

def test_generated_observer_imports_and_handles_lifecycle_events(self):
self._tester(MakeObserverCommand).execute("Post")

observer_class = self._load_class(os.path.join("app/observers", "PostObserver.py"), "PostObserver")
handlers = [name for name in vars(observer_class) if not name.startswith("_")]
self.assertEqual(handlers, self.LIFECYCLE_EVENTS)

class Post(Model):
__observers__ = {}

Post.observe(observer_class())
post = Post()
for event in self.LIFECYCLE_EVENTS:
asyncio.run(post.observe_events(post, event))

def test_runs_through_console_as_db_make_observer(self):
app = create_app()

self.assertEqual(app.run("db:make:observer", "Order"), 0)
self.assertTrue(os.path.exists(os.path.join("app/observers", "OrderObserver.py")))

def test_reports_when_observer_already_exists(self):
self._tester(MakeObserverCommand).execute("Post")
Expand Down
Loading