Skip to content

Commit c969c83

Browse files
authored
Merge pull request piccolo-orm#27 from piccolo-orm/migration_improvements
Migration improvements
2 parents 6f605ce + facac58 commit c969c83

File tree

22 files changed

+338
-130
lines changed

22 files changed

+338
-130
lines changed

piccolo/apps/migrations/auto/migration_manager.py

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ def add_raw_backwards(self, raw: t.Union[t.Callable, t.Coroutine]):
265265

266266
###########################################################################
267267

268-
def get_table_from_snaphot(
268+
async def get_table_from_snaphot(
269269
self,
270270
table_class_name: str,
271271
app_name: t.Optional[str],
@@ -289,16 +289,13 @@ def get_table_from_snaphot(
289289
if app_name is None:
290290
app_name = self.app_name
291291

292-
return (
293-
BaseMigrationManager()
294-
.get_table_from_snaphot(
295-
app_name=app_name,
296-
table_class_name=table_class_name,
297-
max_migration_id=migration_id,
298-
offset=offset,
299-
)
300-
.to_table_class()
292+
diffable_table = await BaseMigrationManager().get_table_from_snaphot(
293+
app_name=app_name,
294+
table_class_name=table_class_name,
295+
max_migration_id=migration_id,
296+
offset=offset,
301297
)
298+
return diffable_table.to_table_class()
302299

303300
###########################################################################
304301

@@ -375,7 +372,7 @@ async def _run_alter_columns(self, backwards=False):
375372
async def _run_drop_tables(self, backwards=False):
376373
if backwards:
377374
for diffable_table in self.drop_tables:
378-
_Table = self.get_table_from_snaphot(
375+
_Table = await self.get_table_from_snaphot(
379376
table_class_name=diffable_table.class_name,
380377
app_name=self.app_name,
381378
offset=-1,
@@ -390,7 +387,7 @@ async def _run_drop_tables(self, backwards=False):
390387
async def _run_drop_columns(self, backwards=False):
391388
if backwards:
392389
for drop_column in self.drop_columns.drop_columns:
393-
_Table = self.get_table_from_snaphot(
390+
_Table = await self.get_table_from_snaphot(
394391
table_class_name=drop_column.table_class_name,
395392
app_name=self.app_name,
396393
offset=-1,
@@ -477,24 +474,21 @@ async def _run_add_tables(self, backwards=False):
477474
).run()
478475
else:
479476
for add_table in self.add_tables:
480-
columns = (
481-
self.add_columns.columns_for_table_class_name(
482-
add_table.class_name
483-
)
484-
+ add_table.columns
485-
)
486477
_Table: t.Type[Table] = type(
487478
add_table.class_name,
488479
(Table,),
489-
{column._meta.name: column for column in columns},
480+
{
481+
column._meta.name: column
482+
for column in add_table.columns
483+
},
490484
)
491485
_Table._meta.tablename = add_table.tablename
492486

493487
await _Table.create_table().run()
494488

495489
async def _run_add_columns(self, backwards=False):
496490
"""
497-
Add columns, which belong to existing tables
491+
Add columns, which belong to new and existing tables
498492
"""
499493
if backwards:
500494
for add_column in self.add_columns.add_columns:
@@ -512,12 +506,7 @@ async def _run_add_columns(self, backwards=False):
512506

513507
await _Table.alter().drop_column(add_column.column).run()
514508
else:
515-
new_table_class_names = [i.class_name for i in self.add_tables]
516-
517509
for table_class_name in self.add_columns.table_class_names:
518-
if table_class_name in new_table_class_names:
519-
continue
520-
521510
add_columns: t.List[
522511
AddColumnClass
523512
] = self.add_columns.for_table_class_name(table_class_name)
@@ -554,8 +543,8 @@ async def run(self):
554543
await self._run_add_tables()
555544
await self._run_rename_tables()
556545
await self._run_add_columns()
557-
await self._run_drop_tables()
558546
await self._run_drop_columns()
547+
await self._run_drop_tables()
559548
await self._run_rename_columns()
560549
await self._run_alter_columns()
561550

@@ -575,8 +564,8 @@ async def run_backwards(self):
575564
else:
576565
raw()
577566

578-
await self._run_add_tables(backwards=True)
579567
await self._run_add_columns(backwards=True)
568+
await self._run_add_tables(backwards=True)
580569
await self._run_drop_tables(backwards=True)
581570
await self._run_rename_tables(backwards=True)
582571
await self._run_drop_columns(backwards=True)

piccolo/apps/migrations/auto/schema_differ.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,31 @@ def check_rename_tables(self) -> RenameTableCollection:
129129
drop_column_names
130130
)
131131
if len(same_column_names) > 0:
132+
if (
133+
drop_table.class_name == new_table.class_name
134+
and drop_table.tablename != new_table.tablename
135+
):
136+
# The class names are the same, but the tablename
137+
# has changed - we can assume this is a deliberate
138+
# rename.
139+
collection.append(
140+
RenameTable(
141+
old_class_name=drop_table.class_name,
142+
old_tablename=drop_table.tablename,
143+
new_class_name=new_table.class_name,
144+
new_tablename=new_table.tablename,
145+
)
146+
)
147+
continue
148+
132149
user_response = (
133150
self.auto_input
134151
if self.auto_input
135152
else input(
136-
f"Did you rename {drop_table.class_name} to "
137-
f"{new_table.class_name}? (y/N)"
153+
f"Did you rename {drop_table.class_name} "
154+
f"(tablename: {drop_table.tablename}) to "
155+
f"{new_table.class_name} "
156+
f"(tablename: {new_table.tablename})? (y/N)"
138157
)
139158
)
140159
if user_response.lower() == "y":

piccolo/apps/migrations/commands/backwards.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from piccolo.apps.migrations.auto import MigrationManager
66
from piccolo.apps.migrations.commands.base import BaseMigrationManager
77
from piccolo.apps.migrations.tables import Migration
8-
from piccolo.utils.sync import run_sync
98

109

1110
class BackwardsMigrationManager(BaseMigrationManager):
@@ -22,8 +21,8 @@ def __init__(
2221
self.clean = clean
2322
super().__init__()
2423

25-
def run(self):
26-
self.create_migration_table()
24+
async def run(self):
25+
await self.create_migration_table()
2726

2827
app_modules = self.get_app_modules()
2928

@@ -37,7 +36,7 @@ def run(self):
3736
)
3837
break
3938

40-
ran_migration_ids = Migration.get_migrations_which_ran(
39+
ran_migration_ids = await Migration.get_migrations_which_ran(
4140
app_name=self.app_name
4241
)
4342
if len(ran_migration_ids) == 0:
@@ -85,14 +84,14 @@ def run(self):
8584
for migration_id in reversed_migration_ids:
8685
print(f"Reversing {migration_id}")
8786
migration_module = migration_modules[migration_id]
88-
response = run_sync(migration_module.forwards())
87+
response = await migration_module.forwards()
8988

9089
if isinstance(response, MigrationManager):
91-
run_sync(response.run_backwards())
90+
await response.run_backwards()
9291

93-
Migration.delete().where(
92+
await Migration.delete().where(
9493
Migration.name == migration_id
95-
).run_sync()
94+
).run()
9695

9796
if self.clean:
9897
os.unlink(migration_module.__file__)
@@ -101,7 +100,7 @@ def run(self):
101100
sys.exit("Not proceeding.")
102101

103102

104-
def backwards(
103+
async def backwards(
105104
app_name: str,
106105
migration_id: str = "1",
107106
auto_agree: bool = False,
@@ -118,7 +117,7 @@ def backwards(
118117
Specify a value of 'all' to undo all of the migrations. Specify a
119118
value of '1' to undo the most recent migration.
120119
:param auto_agree:
121-
Automatically agree to any input prompts.
120+
If true, automatically agree to any input prompts.
122121
:param clean:
123122
If true, the migration files which have been run backwards are deleted
124123
from the disk after completing.
@@ -146,12 +145,12 @@ def backwards(
146145
migration_id="all",
147146
auto_agree=auto_agree,
148147
)
149-
manager.run()
148+
await manager.run()
150149
else:
151150
manager = BackwardsMigrationManager(
152151
app_name=app_name,
153152
migration_id=migration_id,
154153
auto_agree=auto_agree,
155154
clean=clean,
156155
)
157-
manager.run()
156+
await manager.run()

piccolo/apps/migrations/commands/base.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,26 @@
1212
from piccolo.apps.migrations.auto.diffable_table import DiffableTable
1313
from piccolo.apps.migrations.auto.schema_snapshot import SchemaSnapshot
1414
from piccolo.apps.migrations.tables import Migration
15-
from piccolo.utils.sync import run_sync
1615

1716

1817
class BaseMigrationManager(Finder):
19-
def create_migration_table(self) -> bool:
18+
async def create_migration_table(self) -> bool:
2019
"""
2120
Creates the migration table in the database. Returns True/False
2221
depending on whether it was created or not.
2322
"""
24-
if not Migration.table_exists().run_sync():
25-
Migration.create_table().run_sync()
23+
if not await Migration.table_exists().run():
24+
await Migration.create_table().run()
2625
return True
2726
return False
2827

2928
def get_migration_modules(
3029
self, folder_path: str
3130
) -> t.Dict[str, MigrationModule]:
3231
"""
33-
Import the migration modules and store them in a dictionary.
32+
Imports the migration modules in the given folder path, and returns
33+
a mapping of migration ID to the corresponding migration module.
34+
3435
"""
3536
migration_modules = {}
3637

@@ -63,13 +64,17 @@ def get_migration_ids(
6364
"""
6465
return sorted(list(migration_module_dict.keys()))
6566

66-
def get_migration_managers(
67+
async def get_migration_managers(
6768
self,
6869
app_name: str,
6970
max_migration_id: t.Optional[str] = None,
7071
offset: int = 0,
7172
) -> t.List[MigrationManager]:
7273
"""
74+
Call the forwards coroutine in each migration module. Each one should
75+
return a `MigrationManger`. Combine all of the results, and return in
76+
a list.
77+
7378
:param max_migration_id:
7479
If set, only MigrationManagers up to and including the given
7580
migration ID will be returned.
@@ -84,16 +89,18 @@ def get_migration_managers(
8489
str, MigrationModule
8590
] = self.get_migration_modules(migrations_folder)
8691

87-
for _, migration_module in migration_modules.items():
88-
response = run_sync(migration_module.forwards())
92+
migration_ids = sorted(migration_modules.keys())
93+
94+
for migration_id in migration_ids:
95+
migration_module = migration_modules[migration_id]
96+
response = await migration_module.forwards()
8997
if isinstance(response, MigrationManager):
90-
if max_migration_id:
91-
if response.migration_id == max_migration_id:
92-
break
93-
else:
94-
migration_managers.append(response)
95-
else:
96-
migration_managers.append(response)
98+
migration_managers.append(response)
99+
if (
100+
max_migration_id
101+
and response.migration_id == max_migration_id
102+
):
103+
break
97104

98105
if offset > 0:
99106
raise Exception(
@@ -104,7 +111,7 @@ def get_migration_managers(
104111
else:
105112
return migration_managers
106113

107-
def get_table_from_snaphot(
114+
async def get_table_from_snaphot(
108115
self,
109116
app_name: str,
110117
table_class_name: str,
@@ -115,7 +122,7 @@ def get_table_from_snaphot(
115122
This will generate a SchemaSnapshot up to the given migration ID, and
116123
will return a DiffableTable class from that snapshot.
117124
"""
118-
migration_managers = self.get_migration_managers(
125+
migration_managers = await self.get_migration_managers(
119126
app_name=app_name, max_migration_id=max_migration_id, offset=offset
120127
)
121128
schema_snapshot = SchemaSnapshot(managers=migration_managers)

piccolo/apps/migrations/commands/check.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ def __init__(self, app_name: str):
88
self.app_name = app_name
99
super().__init__()
1010

11-
def run(self):
11+
async def run(self):
1212
print("Listing migrations ...")
1313

1414
# Make sure the migration table exists, otherwise we'll get an error.
15-
self.create_migration_table()
15+
await self.create_migration_table()
1616

1717
print(
1818
f'{get_fixed_length_string("APP NAME")} | '
@@ -37,25 +37,25 @@ def run(self):
3737
ids = self.get_migration_ids(migration_modules)
3838
for _id in ids:
3939
has_ran = (
40-
Migration.exists()
40+
await Migration.exists()
4141
.where(
4242
(Migration.name == _id)
4343
& (Migration.app_name == app_name)
4444
)
45-
.run_sync()
45+
.run()
4646
)
4747
fixed_length_id = get_fixed_length_string(_id)
4848
print(
4949
f"{fixed_length_app_name} | {fixed_length_id} | {has_ran}"
5050
)
5151

5252

53-
def check(app_name: str = "all"):
53+
async def check(app_name: str = "all"):
5454
"""
5555
Lists all migrations which have and haven't ran.
5656
5757
:param app_name:
5858
The name of the app to check. Specify a value of 'all' to check
5959
the migrations for all apps.
6060
"""
61-
CheckMigrationManager(app_name=app_name).run()
61+
await CheckMigrationManager(app_name=app_name).run()

0 commit comments

Comments
 (0)