Skip to content

Commit 48eae5f

Browse files
committed
refactoring migrations backward command
1 parent 1ed8b5b commit 48eae5f

File tree

2 files changed

+71
-45
lines changed

2 files changed

+71
-45
lines changed

piccolo/apps/migrations/commands/backwards.py

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import sys
44

55
from piccolo.apps.migrations.auto import MigrationManager
6-
from piccolo.apps.migrations.commands.base import BaseMigrationManager
6+
from piccolo.apps.migrations.commands.base import (
7+
BaseMigrationManager,
8+
MigrationResult,
9+
)
710
from piccolo.apps.migrations.tables import Migration
811

912

@@ -21,12 +24,12 @@ def __init__(
2124
self.clean = clean
2225
super().__init__()
2326

24-
async def run(self):
27+
async def run(self) -> MigrationResult:
2528
await self.create_migration_table()
2629

2730
app_modules = self.get_app_modules()
2831

29-
migration_modules = []
32+
migration_modules = {}
3033

3134
for app_module in app_modules:
3235
app_config = getattr(app_module, "APP_CONFIG")
@@ -42,8 +45,9 @@ async def run(self):
4245
if len(ran_migration_ids) == 0:
4346
# Make sure a status of 0 is returned, as we don't want this
4447
# to appear as an error in automated scripts.
45-
print("No migrations to reverse!")
46-
sys.exit(0)
48+
message = "No migrations to reverse!"
49+
print(message)
50+
return MigrationResult(success=True, message=message)
4751

4852
#######################################################################
4953

@@ -55,10 +59,12 @@ async def run(self):
5559
earliest_migration_id = self.migration_id
5660

5761
if earliest_migration_id not in ran_migration_ids:
58-
sys.exit(
62+
message = (
5963
"Unrecognized migration name - must be one of "
6064
f"{ran_migration_ids}"
6165
)
66+
print(message, file=sys.stderr)
67+
return MigrationResult(success=False, message=message)
6268

6369
#######################################################################
6470

@@ -99,33 +105,20 @@ async def run(self):
99105
if self.clean:
100106
os.unlink(migration_module.__file__)
101107

108+
return MigrationResult(success=True)
109+
102110
else: # pragma: no cover
103-
sys.exit("Not proceeding.")
111+
message = "Not proceeding."
112+
print(message, file=sys.stderr)
113+
return MigrationResult(success=False, message=message)
104114

105115

106-
async def backwards(
116+
async def run_backwards(
107117
app_name: str,
108118
migration_id: str = "1",
109119
auto_agree: bool = False,
110120
clean: bool = False,
111-
):
112-
"""
113-
Undo migrations up to a specific migration.
114-
115-
:param app_name:
116-
The app to reverse migrations for. Specify a value of 'all' to reverse
117-
migrations for all apps.
118-
:param migration_id:
119-
Migrations will be reversed up to and including this migration_id.
120-
Specify a value of 'all' to undo all of the migrations. Specify a
121-
value of '1' to undo the most recent migration.
122-
:param auto_agree:
123-
If true, automatically agree to any input prompts.
124-
:param clean:
125-
If true, the migration files which have been run backwards are deleted
126-
from the disk after completing.
127-
128-
"""
121+
) -> MigrationResult:
129122
if app_name == "all":
130123
sorted_app_names = BaseMigrationManager().get_sorted_app_names()
131124
sorted_app_names.reverse()
@@ -149,11 +142,48 @@ async def backwards(
149142
auto_agree=auto_agree,
150143
)
151144
await manager.run()
145+
return MigrationResult(success=True)
146+
else:
147+
return MigrationResult(success=False, message="User cancelled")
152148
else:
153149
manager = BackwardsMigrationManager(
154150
app_name=app_name,
155151
migration_id=migration_id,
156152
auto_agree=auto_agree,
157153
clean=clean,
158154
)
159-
await manager.run()
155+
return await manager.run()
156+
157+
158+
async def backwards(
159+
app_name: str,
160+
migration_id: str = "1",
161+
auto_agree: bool = False,
162+
clean: bool = False,
163+
):
164+
"""
165+
Undo migrations up to a specific migration.
166+
167+
:param app_name:
168+
The app to reverse migrations for. Specify a value of 'all' to reverse
169+
migrations for all apps.
170+
:param migration_id:
171+
Migrations will be reversed up to and including this migration_id.
172+
Specify a value of 'all' to undo all of the migrations. Specify a
173+
value of '1' to undo the most recent migration.
174+
:param auto_agree:
175+
If true, automatically agree to any input prompts.
176+
:param clean:
177+
If true, the migration files which have been run backwards are deleted
178+
from the disk after completing.
179+
180+
"""
181+
response = await run_backwards(
182+
app_name=app_name,
183+
migration_id=migration_id,
184+
auto_agree=auto_agree,
185+
clean=clean,
186+
)
187+
188+
if not response.success:
189+
sys.exit(1)

tests/apps/migrations/commands/test_forwards_backwards.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def test_forwards_backwards_single_migration(self):
8888
self.assertTrue(not table_class.table_exists().run_sync())
8989

9090
@patch("piccolo.apps.migrations.commands.forwards.print")
91-
def test_forwards_unknown_migration(self, print_):
91+
def test_forwards_unknown_migration(self, print_: MagicMock):
9292
"""
9393
Test running an unknown migrations forwards.
9494
"""
@@ -104,13 +104,14 @@ def test_forwards_unknown_migration(self, print_):
104104
in print_.mock_calls
105105
)
106106

107-
def test_backwards_unknown_migration(self):
107+
@patch("piccolo.apps.migrations.commands.backwards.print")
108+
def test_backwards_unknown_migration(self, print_: MagicMock):
108109
"""
109110
Test running an unknown migrations backwards.
110111
"""
111112
run_sync(forwards(app_name="example_app", migration_id="all"))
112113

113-
with self.assertRaises(SystemExit) as manager:
114+
with self.assertRaises(SystemExit):
114115
run_sync(
115116
backwards(
116117
app_name="example_app",
@@ -120,29 +121,24 @@ def test_backwards_unknown_migration(self):
120121
)
121122

122123
self.assertTrue(
123-
manager.exception.__str__().startswith(
124-
"Unrecognized migration name - must be one of "
125-
)
124+
print_.mock_calls[0]
125+
.args[0]
126+
.startswith("Unrecognized migration name - must be one of ")
126127
)
127128

128129
@patch("piccolo.apps.migrations.commands.backwards.print")
129-
def test_backwards_no_migrations(self, print_):
130+
def test_backwards_no_migrations(self, print_: MagicMock):
130131
"""
131132
Test running migrations backwards if none have been run previously.
132133
"""
133-
with self.assertRaises(SystemExit) as manager:
134-
run_sync(
135-
backwards(
136-
app_name="example_app",
137-
migration_id="2020-12-17T18:44:30",
138-
auto_agree=True,
139-
)
134+
run_sync(
135+
backwards(
136+
app_name="example_app",
137+
migration_id="2020-12-17T18:44:30",
138+
auto_agree=True,
140139
)
141-
142-
self.assertEqual(manager.exception.code, 0)
143-
self.assertTrue(
144-
print_.mock_calls[-1] == call("No migrations to reverse!")
145140
)
141+
self.assertTrue(call("No migrations to reverse!") in print_.mock_calls)
146142

147143
@patch("piccolo.apps.migrations.commands.forwards.print")
148144
def test_forwards_no_migrations(self, print_: MagicMock):

0 commit comments

Comments
 (0)