Skip to content

Commit d624ee8

Browse files
authored
Better already migrated detection (#588)
1 parent a68bf90 commit d624ee8

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ test.db
1010
coverage.xml
1111
docs/_build
1212
.idea
13+
constance/_version.py

constance/migrations/0003_drop_pickle.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import logging
23
import pickle
34
from base64 import b64decode
@@ -11,6 +12,16 @@
1112
logger = logging.getLogger(__name__)
1213

1314

15+
def is_already_migrated(value):
16+
try:
17+
data = json.loads(value)
18+
if isinstance(data, dict) and set(data.keys()) == {'__type__', '__value__'}:
19+
return True
20+
except (json.JSONDecodeError, TypeError):
21+
return False
22+
return False
23+
24+
1425
def import_module_attr(path):
1526
package, module = path.rsplit('.', 1)
1627
return getattr(import_module(package), module)
@@ -20,8 +31,9 @@ def migrate_pickled_data(apps, schema_editor) -> None: # pragma: no cover
2031
Constance = apps.get_model('constance', 'Constance')
2132

2233
for constance in Constance.objects.exclude(value=None):
23-
constance.value = dumps(pickle.loads(b64decode(constance.value.encode()))) # noqa: S301
24-
constance.save(update_fields=['value'])
34+
if not is_already_migrated(constance.value):
35+
constance.value = dumps(pickle.loads(b64decode(constance.value.encode()))) # noqa: S301
36+
constance.save(update_fields=['value'])
2537

2638
if settings.BACKEND in ('constance.backends.redisd.RedisBackend', 'constance.backends.redisd.CachingRedisBackend'):
2739
import redis
@@ -39,15 +51,8 @@ def migrate_pickled_data(apps, schema_editor) -> None: # pragma: no cover
3951
for key in settings.CONFIG:
4052
prefixed_key = f'{_prefix}{key}'
4153
value = _rd.get(prefixed_key)
42-
if value is not None:
43-
try:
44-
redis_migrated_data[prefixed_key] = dumps(pickle.loads(value)) # noqa: S301
45-
except pickle.UnpicklingError as e:
46-
if value.startswith(b'{"__'):
47-
# Seems like we're facing already migrated data
48-
# Might be related to defaults and when config was accessed while django inits for migration
49-
continue
50-
raise e
54+
if value is not None and not is_already_migrated(value):
55+
redis_migrated_data[prefixed_key] = dumps(pickle.loads(value)) # noqa: S301
5156
for prefixed_key, value in redis_migrated_data.items():
5257
_rd.set(prefixed_key, value)
5358

0 commit comments

Comments
 (0)