Commit b45117ee authored by Paul Brown's avatar Paul Brown

fix floating point precision issues when converting filter string to integers, add tests

parent 7af0eb6d
...@@ -107,9 +107,12 @@ class BaseBooleanFilter(BaseFilter): ...@@ -107,9 +107,12 @@ class BaseBooleanFilter(BaseFilter):
class BaseIntFilter(BaseFilter): class BaseIntFilter(BaseFilter):
""" """
Base Int filter. Adds validation and changes value to python int. Base Int filter. Adds validation and changes value to python int.
Avoid using int(float(value)) to also allow using decimals, because it
causes precision issues with large numbers.
""" """
def clean(self, value): def clean(self, value):
return int(float(value)) return int(value)
class BaseFloatFilter(BaseFilter): class BaseFloatFilter(BaseFilter):
...@@ -123,9 +126,12 @@ class BaseFloatFilter(BaseFilter): ...@@ -123,9 +126,12 @@ class BaseFloatFilter(BaseFilter):
class BaseIntListFilter(BaseFilter): class BaseIntListFilter(BaseFilter):
""" """
Base Integer list filter. Adds validation for int "In List" filter. Base Integer list filter. Adds validation for int "In List" filter.
Avoid using int(float(value)) to also allow using decimals, because it
causes precision issues with large numbers.
""" """
def clean(self, value): def clean(self, value):
return [int(float(v.strip())) for v in value.split(',') if v.strip()] return [int(v.strip()) for v in value.split(',') if v.strip()]
class BaseFloatListFilter(BaseFilter): class BaseFloatListFilter(BaseFilter):
......
...@@ -63,6 +63,7 @@ def fill_db(Model1, Model2): ...@@ -63,6 +63,7 @@ def fill_db(Model1, Model2):
Model2('string_field_val_2', None, None).save() Model2('string_field_val_2', None, None).save()
Model2('string_field_val_3', 5000, 25.9).save() Model2('string_field_val_3', 5000, 25.9).save()
Model2('string_field_val_4', 9000, 75.5).save() Model2('string_field_val_4', 9000, 75.5).save()
Model2('string_field_val_5', 6169453081680413441).save()
Model1('datetime_obj1', datetime_field=datetime(2014,4,3,1,9,0)).save() Model1('datetime_obj1', datetime_field=datetime(2014,4,3,1,9,0)).save()
Model1('datetime_obj2', datetime_field=datetime(2013,3,2,0,8,0)).save() Model1('datetime_obj2', datetime_field=datetime(2013,3,2,0,8,0)).save()
...@@ -325,6 +326,13 @@ def test_column_filters(): ...@@ -325,6 +326,13 @@ def test_column_filters():
ok_('string_field_val_3' in data) ok_('string_field_val_3' in data)
ok_('string_field_val_4' not in data) ok_('string_field_val_4' not in data)
# integer - equals (huge number)
rv = client.get('/admin/model2/?flt0_0=6169453081680413441')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('string_field_val_5' in data)
ok_('string_field_val_4' not in data)
# integer - equals - test validation # integer - equals - test validation
rv = client.get('/admin/model2/?flt0_0=badval') rv = client.get('/admin/model2/?flt0_0=badval')
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
...@@ -379,6 +387,13 @@ def test_column_filters(): ...@@ -379,6 +387,13 @@ def test_column_filters():
ok_('string_field_val_3' in data) ok_('string_field_val_3' in data)
ok_('string_field_val_4' in data) ok_('string_field_val_4' in data)
# integer - in list (huge number)
rv = client.get('/admin/model2/?flt0_5=6169453081680413441')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('string_field_val_1' not in data)
ok_('string_field_val_5' in data)
# integer - in list - test validation # integer - in list - test validation
rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval') rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval')
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
......
...@@ -98,6 +98,7 @@ def fill_db(Model1, Model2): ...@@ -98,6 +98,7 @@ def fill_db(Model1, Model2):
Model2('char_field_val_2', None, None).save() Model2('char_field_val_2', None, None).save()
Model2('char_field_val_3', 5000, 25.9).save() Model2('char_field_val_3', 5000, 25.9).save()
Model2('char_field_val_4', 9000, 75.5).save() Model2('char_field_val_4', 9000, 75.5).save()
Model2('char_field_val_5', 6169453081680413441).save()
Model1('date_obj1', date_field=date(2014,11,17)).save() Model1('date_obj1', date_field=date(2014,11,17)).save()
Model1('date_obj2', date_field=date(2013,10,16)).save() Model1('date_obj2', date_field=date(2013,10,16)).save()
...@@ -359,6 +360,13 @@ def test_column_filters(): ...@@ -359,6 +360,13 @@ def test_column_filters():
ok_('char_field_val_3' in data) ok_('char_field_val_3' in data)
ok_('char_field_val_4' not in data) ok_('char_field_val_4' not in data)
# integer - equals (huge number)
rv = client.get('/admin/model2/?flt0_0=6169453081680413441')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('char_field_val_5' in data)
ok_('char_field_val_4' not in data)
# integer - equals - test validation # integer - equals - test validation
rv = client.get('/admin/model2/?flt0_0=badval') rv = client.get('/admin/model2/?flt0_0=badval')
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
...@@ -413,6 +421,13 @@ def test_column_filters(): ...@@ -413,6 +421,13 @@ def test_column_filters():
ok_('char_field_val_3' in data) ok_('char_field_val_3' in data)
ok_('char_field_val_4' in data) ok_('char_field_val_4' in data)
# integer - in list (huge number)
rv = client.get('/admin/model2/?flt0_5=6169453081680413441')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('char_field_val_1' not in data)
ok_('char_field_val_5' in data)
# integer - in list - test validation # integer - in list - test validation
rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval') rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval')
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
......
...@@ -92,6 +92,7 @@ def fill_db(db, Model1, Model2): ...@@ -92,6 +92,7 @@ def fill_db(db, Model1, Model2):
model2_obj2 = Model2('test2_val_2', model1=model1_obj2, float_field=None) model2_obj2 = Model2('test2_val_2', model1=model1_obj2, float_field=None)
model2_obj3 = Model2('test2_val_3', int_field=5000, float_field=25.9) model2_obj3 = Model2('test2_val_3', int_field=5000, float_field=25.9)
model2_obj4 = Model2('test2_val_4', int_field=9000, float_field=75.5) model2_obj4 = Model2('test2_val_4', int_field=9000, float_field=75.5)
model2_obj5 = Model2('test2_val_5', int_field=6169453081680413441)
date_obj1 = Model1('date_obj1', date_field=date(2014,11,17)) date_obj1 = Model1('date_obj1', date_field=date(2014,11,17))
date_obj2 = Model1('date_obj2', date_field=date(2013,10,16)) date_obj2 = Model1('date_obj2', date_field=date(2013,10,16))
...@@ -107,7 +108,7 @@ def fill_db(db, Model1, Model2): ...@@ -107,7 +108,7 @@ def fill_db(db, Model1, Model2):
db.session.add_all([ db.session.add_all([
model1_obj1, model1_obj2, model1_obj3, model1_obj4, model1_obj1, model1_obj2, model1_obj3, model1_obj4,
model2_obj1, model2_obj2, model2_obj3, model2_obj4, model2_obj1, model2_obj2, model2_obj3, model2_obj4, model2_obj5,
date_obj1, timeonly_obj1, datetime_obj1, date_obj1, timeonly_obj1, datetime_obj1,
date_obj2, timeonly_obj2, datetime_obj2, date_obj2, timeonly_obj2, datetime_obj2,
enum_obj1, enum_obj2, empty_obj enum_obj1, enum_obj2, empty_obj
...@@ -674,6 +675,13 @@ def test_column_filters(): ...@@ -674,6 +675,13 @@ def test_column_filters():
ok_('test2_val_3' in data) ok_('test2_val_3' in data)
ok_('test2_val_4' not in data) ok_('test2_val_4' not in data)
# integer - equals (huge number)
rv = client.get('/admin/model2/?flt0_0=6169453081680413441')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('test2_val_5' in data)
ok_('test2_val_4' not in data)
# integer - equals - test validation # integer - equals - test validation
rv = client.get('/admin/model2/?flt0_0=badval') rv = client.get('/admin/model2/?flt0_0=badval')
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
...@@ -728,6 +736,13 @@ def test_column_filters(): ...@@ -728,6 +736,13 @@ def test_column_filters():
ok_('test2_val_3' in data) ok_('test2_val_3' in data)
ok_('test2_val_4' in data) ok_('test2_val_4' in data)
# integer - in list (huge number)
rv = client.get('/admin/model2/?flt0_5=6169453081680413441')
eq_(rv.status_code, 200)
data = rv.data.decode('utf-8')
ok_('test2_val_1' not in data)
ok_('test2_val_5' in data)
# integer - in list - test validation # integer - in list - test validation
rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval') rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval')
eq_(rv.status_code, 200) eq_(rv.status_code, 200)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment