Skip to content

Commit 43a0711

Browse files
committed
Merge pull request #1 from yourlabs/decimal_normalization
Decimal normalization
2 parents 1bbacbd + 8258a8b commit 43a0711

18 files changed

+211
-6
lines changed

README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ django.core.serializers.python.Serializer.get_dump_object() - returns a dict,
4747
this app registers a slightly modified version of the default json serializer
4848
which returns OrderedDicts instead.
4949

50+
In addition, dbdiff serialization forces Decimal normalization, because
51+
trailing zeros could happen in inconsistent ways.
52+
5053
Cross-database fixture compatibility
5154
====================================
5255

dbdiff/dbdiff.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ def diff(fixture):
2626
try:
2727
out = diff.get_diff()
2828
except:
29-
DEBUG or diff.clean()
29+
if not DEBUG:
30+
diff.clean()
3031
raise
3132

32-
DEBUG or diff.clean()
33+
if not DEBUG:
34+
diff.clean()
35+
3336
return out

dbdiff/exceptions.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Exceptions for dbdiff module."""
2+
3+
4+
class DbDiffException(Exception):
5+
"""Base exception for this app."""
6+
7+
8+
class EmptyFixtures(DbDiffException):
9+
"""Raised when a fixtures file is empty."""
10+
11+
def __init__(self, path):
12+
"""Exception for when path does not contain any fixture data."""
13+
super(EmptyFixtures, self).__init__('%s is empty' % path)

dbdiff/fixture_diff.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
import ijson
1212

13+
from .exceptions import EmptyFixtures
14+
1315

1416
class FixtureDiff(object):
1517
"""
@@ -51,9 +53,12 @@ def fixture_indent(self):
5153
with open(self.fixture_path, 'r') as f:
5254
line = f.readline()
5355

54-
while ':' not in line:
56+
while line and ':' not in line:
5557
line = f.readline()
5658

59+
if not line:
60+
raise EmptyFixtures(self.fixture_path)
61+
5762
return len(line) - len(line.lstrip(' '))
5863

5964
def get_diff(self):
@@ -68,7 +73,7 @@ def get_diff(self):
6873
cmd = 'diff -u1 %s %s | sed "1,2 d"' % (
6974
self.fixture_path, self.dump_path)
7075

71-
if apps.get_app_config('dbdiff').debug:
76+
if apps.get_app_config('dbdiff').debug: # pragma: no cover
7277
print(cmd)
7378

7479
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

dbdiff/fixtures/empty.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[
2+
]

dbdiff/serializers/base.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import collections
44
import datetime
5+
import decimal
56

67

78
class BaseSerializerMixin(object):
@@ -35,9 +36,19 @@ def remove_microseconds(cls, data):
3536
tzinfo=value.tzinfo
3637
)
3738

39+
@classmethod
40+
def normalize_decimals(cls, data):
41+
"""Strip trailing zeros for constitency."""
42+
for key, value in data['fields'].items():
43+
if not isinstance(value, decimal.Decimal):
44+
continue
45+
46+
data['fields'][key] = value.normalize()
47+
3848
def get_dump_object(self, obj):
3949
"""Actual method used by Django serializers to dump dicts."""
4050
data = super(BaseSerializerMixin, self).get_dump_object(obj)
4151
self.remove_microseconds(data)
52+
self.normalize_decimals(data)
4253
data = self.recursive_dict_sort(data)
4354
return data
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""App to test DecimalField dump predictibility."""
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"fields": {
4+
"test_field": "3.1"
5+
},
6+
"model": "decimal_test.testmodel",
7+
"pk": 1
8+
},
9+
{
10+
"fields": {
11+
"test_field": "1.1"
12+
},
13+
"model": "decimal_test.testmodel",
14+
"pk": 2
15+
}
16+
]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"fields": {
4+
"test_field": "1.1"
5+
},
6+
"model": "decimal_test.testmodel",
7+
"pk": 1
8+
},
9+
{
10+
"fields": {
11+
"test_field": "1.1"
12+
},
13+
"model": "decimal_test.testmodel",
14+
"pk": 2
15+
}
16+
]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"fields": {
4+
"test_field": "1.1"
5+
},
6+
"model": "decimal_test.testmodel",
7+
"pk": 1
8+
},
9+
{
10+
"fields": {
11+
"test_field": "1.10"
12+
},
13+
"model": "decimal_test.testmodel",
14+
"pk": 2
15+
}
16+
]

0 commit comments

Comments
 (0)