Skip to content

Commit d5bd027

Browse files
vo-vaikonst
authored andcommitted
migrate_boolean_attributes: multiple attributes (pynamodb#538)
Fix legacy boolean migration when multiple attributes are specified.
1 parent b1f557f commit d5bd027

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

pynamodb/migration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def migrate_boolean_attributes(model_class,
115115
if condition is None:
116116
condition = Path(attr_name) == (1 if old_value else 0)
117117
else:
118-
condition = condition & Path(attr_name) == (1 if old_value else 0)
118+
condition = condition & (Path(attr_name) == (1 if old_value else 0))
119119

120120
if actions:
121121
assert condition is not None

pynamodb/tests/integration/test_migration.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,54 @@ class Meta:
4444
assert 1 == len([_ for _ in BAModel.query('pkey', Path('flag') == True)])
4545

4646

47+
@pytest.mark.ddblocal
48+
def test_migrate_two_or_more_boolean_attributes_upgrade_path(ddb_url):
49+
class BAModel(Model):
50+
class Meta:
51+
table_name = 'migration_test_lba_to_ba_two_or_more_attrs'
52+
host = ddb_url
53+
id = UnicodeAttribute(hash_key=True)
54+
flag = BooleanAttribute(null=True)
55+
second_flag = BooleanAttribute(null=True)
56+
57+
class LBAModel(Model):
58+
class Meta:
59+
table_name = 'migration_test_lba_to_ba_two_or_more_attrs'
60+
host = ddb_url
61+
id = UnicodeAttribute(hash_key=True)
62+
flag = LegacyBooleanAttribute(null=True)
63+
second_flag = LegacyBooleanAttribute(null=True)
64+
65+
LBAModel.create_table(read_capacity_units=1, write_capacity_units=1)
66+
67+
# Create one "offending" object written as an integer using LBA.
68+
LBAModel('pkey', flag=True, second_flag=True).save()
69+
assert 1 == len([_ for _ in LBAModel.query('pkey', LBAModel.flag == True)])
70+
assert LBAModel.get('pkey').second_flag == True
71+
72+
# We should NOT be able to read it using BA.
73+
assert 0 == len([_ for _ in BAModel.query('pkey', BAModel.flag == True)])
74+
75+
# ... unless we jump through hoops using Path
76+
assert 1 == len([_ for _ in BAModel.query('pkey', Path('flag') == 1)])
77+
78+
# Migrate the object to being stored as Boolean.
79+
assert (1, 0) == migrate_boolean_attributes(BAModel, ['flag', 'second_flag'], allow_rate_limited_scan_without_consumed_capacity=True)
80+
81+
# We should now be able to read it using BA.
82+
assert 1 == len([_ for _ in BAModel.query('pkey', BAModel.flag == True)])
83+
84+
# ... or through the hoop jumping.
85+
assert 1 == len([_ for _ in BAModel.query('pkey', Path('flag') == True)])
86+
87+
# checking that both attributes are changed
88+
the_item = BAModel.get('pkey')
89+
assert the_item.flag == True
90+
assert the_item.second_flag == True
91+
92+
LBAModel.delete_table()
93+
94+
4795
@pytest.mark.ddblocal
4896
def test_migrate_boolean_attributes_none_okay(ddb_url):
4997
"""Ensure migration works for attributes whose value is None."""

0 commit comments

Comments
 (0)