Skip to content

Commit 777154e

Browse files
authored
Merge pull request #269 from novafloss/add-json-migrations
Add JSON migrations
2 parents 3547b78 + 8fab2f6 commit 777154e

11 files changed

+112
-19
lines changed

CHANGELOG.rst

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ master (unreleased)
1010
- Added perf rec tests
1111
- Add configuration for py.test
1212
- Reactivate accidentally skipped ``test_validations.py`` tests
13+
- Add JSON migrations
1314

1415
Release 1.0.2 (2017-10-10)
1516
==========================

demo/tests/test_json_migrations.py

+22-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import mock
22
import os
3-
from copy import deepcopy
43

54
from django.test import TestCase
65

@@ -12,18 +11,21 @@
1211
@mock.patch('formidable.json_migrations.package',
1312
'tests.json_migrations')
1413
class JSONMigrationTestCase(TestCase):
15-
def setUp(self):
16-
super(JSONMigrationTestCase, self).setUp()
17-
18-
self.data = deepcopy({
14+
def _fixtures(self, version=None):
15+
data = {
1916
'fields': [
2017
{'foo': 'bar', 'help_text': 'SOS'},
2118
{'foo': 'baz', 'help_text': 'SAS'},
2219
]
23-
})
20+
}
21+
if version:
22+
data['version'] = version
23+
24+
return data
2425

2526
def test_migration_from_scratch(self):
26-
updated_data = migrate(self.data)
27+
data = self._fixtures()
28+
updated_data = migrate(data)
2729

2830
self.assertEqual(updated_data, {
2931
'version': 2,
@@ -32,9 +34,11 @@ def test_migration_from_scratch(self):
3234
{'foo': 'baz', 'description': 'SAS'},
3335
]
3436
})
37+
self.assertEqual(updated_data['version'], 2)
3538

3639
def test_migration_from_version_1(self):
37-
updated_data = migrate(self.data, 1)
40+
data = self._fixtures(version=1)
41+
updated_data = migrate(data, 1)
3842

3943
self.assertEqual(updated_data, {
4044
'version': 2,
@@ -43,28 +47,33 @@ def test_migration_from_version_1(self):
4347
{'foo': 'baz', 'help_text': 'SAS'},
4448
],
4549
})
50+
self.assertEqual(updated_data['version'], 2)
4651

4752
def test_migration_from_version_2(self):
48-
updated_data = migrate(self.data, 2)
49-
self.assertEqual(updated_data, self.data)
53+
data = self._fixtures(version=2)
54+
updated_data = migrate(data, 2)
55+
self.assertEqual(updated_data, data)
5056

5157
@mock.patch('tests.json_migrations.0002_add_version.migrate')
5258
@mock.patch('tests.json_migrations.0001_rename_helptext.migrate')
5359
def test_migration_from_scratch_call_count(self, migrate_1, migrate_2):
54-
migrate(self.data)
60+
data = self._fixtures()
61+
migrate(data)
5562
self.assertEqual(migrate_1.call_count, 1)
5663
self.assertEqual(migrate_2.call_count, 1)
5764

5865
@mock.patch('tests.json_migrations.0002_add_version.migrate')
5966
@mock.patch('tests.json_migrations.0001_rename_helptext.migrate')
6067
def test_migration_from_version_1_call_count(self, migrate_1, migrate_2):
61-
migrate(self.data, 1)
68+
data = self._fixtures(version=1)
69+
migrate(data, 1)
6270
self.assertEqual(migrate_1.call_count, 0)
6371
self.assertEqual(migrate_2.call_count, 1)
6472

6573
@mock.patch('tests.json_migrations.0002_add_version.migrate')
6674
@mock.patch('tests.json_migrations.0001_rename_helptext.migrate')
6775
def test_migration_from_version_2_call_count(self, migrate_1, migrate_2):
68-
migrate(self.data, 2)
76+
data = self._fixtures(version=2)
77+
migrate(data, 2)
6978
self.assertEqual(migrate_1.call_count, 0)
7079
self.assertEqual(migrate_2.call_count, 0)

formidable/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1+
from __future__ import absolute_import
2+
3+
from .json_migrations import latest_version
4+
5+
16
default_app_config = 'formidable.app.FormidableConfig'
27
version = '1.1.0.dev0'
8+
json_version = latest_version

formidable/forms/conditions.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,12 @@ def __call__(self, cleaned_data):
9999

100100
try:
101101
ref_value = cleaned_data[self.field_id]
102-
return meth(ref_value, self.values)
103-
except:
102+
except KeyError:
104103
# KeyError if self.field_id not in cleaned_data
105104
# TODO XXX add log ?
106105
return False
106+
else:
107+
return meth(ref_value, self.values)
107108

108109

109110
class Condition(six.with_metaclass(ConditionsMetaClass)):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""
2+
The field help_text has been renamed into description.
3+
4+
"""
5+
6+
7+
def migrate(data):
8+
if 'version' not in data:
9+
data['version'] = 0
10+
11+
return data
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""
2+
Uncontextualize forms.
3+
4+
"""
5+
6+
from formidable.json_migrations.utils import merge_context_forms
7+
8+
9+
def migrate(data):
10+
return merge_context_forms(data)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""
2+
Add conditions as an empty list if it doesn't exist in the form.
3+
4+
This JSON migration is related to:
5+
* 0004_formidable_conditions
6+
* 0005_conditions_default
7+
8+
"""
9+
10+
11+
def migrate(data):
12+
if 'conditions' not in data:
13+
data.setdefault('conditions', [])
14+
15+
return data
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""
2+
The presets attribute must be removed.
3+
4+
This JSON migration is related to:
5+
* 0006_drop_preset_fields
6+
* 0007_drop_preset_tables
7+
8+
"""
9+
10+
11+
def migrate(data):
12+
if 'presets' in data:
13+
data.pop('presets')
14+
15+
return data

formidable/json_migrations/__init__.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,23 @@
33
from glob import glob
44
from importlib import import_module
55

6-
__all__ = ['migrate', 'get_migrations']
6+
__all__ = ['latest_version', 'migrate']
77

88
HERE = os.path.dirname(__file__)
99

1010
package = sys.modules[__name__].__name__
1111

1212

13-
def get_migrations():
13+
def _get_migrations():
14+
"""
15+
Return a generator with all JSON migrations sorted.
16+
17+
Each item is a tuple with:
18+
- the version number (int)
19+
- the label of the migration
20+
- the reference to the migrate() function
21+
22+
"""
1423
for module in sorted(glob(os.path.join(HERE, '[0-9]*.py'))):
1524
module_name, _ = os.path.basename(module).rsplit('.', 1)
1625
mod = import_module('.' + module_name, package=package)
@@ -21,8 +30,18 @@ def get_migrations():
2130

2231

2332
def migrate(data, version_src=0):
24-
for version, label, func in list(get_migrations()):
33+
"""
34+
Apply all migrations from ``version_src`` to the latest found on
35+
``data``.
36+
37+
"""
38+
for version, label, func in list(_get_migrations()):
2539
if version_src < version:
2640
data = func(data)
41+
data['version'] = version
2742
version_src = version
43+
2844
return data
45+
46+
47+
latest_version = max(migration[0] for migration in list(_get_migrations()))

formidable/json_migrations/utils.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,14 @@ def add_fields(ref_fields, new_fields):
4040

4141

4242
def merge_context_forms(forms):
43-
# forms : role => ContextForm
43+
# forms: role => ContextForm
4444
roles = list(forms.keys())
4545

46+
if {'description', 'fields', 'label', 'id'}.issubset(roles):
47+
# If these keys are in the forms, the form is already
48+
# uncontextualized.
49+
return forms
50+
4651
# Formidable and ContextForm JSON formats only differs by the field
4752
# attribute (and some missing attributes in ContextForm). We can copy
4853
# everything and overwrite `fields`.
@@ -61,4 +66,5 @@ def merge_context_forms(forms):
6166
{'access_id': role, 'level': constants.HIDDEN}
6267
)
6368
form['fields'] = fields
69+
6470
return form

0 commit comments

Comments
 (0)