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):
class BaseIntFilter(BaseFilter):
"""
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):
return int(float(value))
return int(value)
class BaseFloatFilter(BaseFilter):
......@@ -123,9 +126,12 @@ class BaseFloatFilter(BaseFilter):
class BaseIntListFilter(BaseFilter):
"""
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):
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):
......
......@@ -63,6 +63,7 @@ def fill_db(Model1, Model2):
Model2('string_field_val_2', None, None).save()
Model2('string_field_val_3', 5000, 25.9).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_obj2', datetime_field=datetime(2013,3,2,0,8,0)).save()
......@@ -325,6 +326,13 @@ def test_column_filters():
ok_('string_field_val_3' 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
rv = client.get('/admin/model2/?flt0_0=badval')
eq_(rv.status_code, 200)
......@@ -379,6 +387,13 @@ def test_column_filters():
ok_('string_field_val_3' 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
rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval')
eq_(rv.status_code, 200)
......
......@@ -98,6 +98,7 @@ def fill_db(Model1, Model2):
Model2('char_field_val_2', None, None).save()
Model2('char_field_val_3', 5000, 25.9).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_obj2', date_field=date(2013,10,16)).save()
......@@ -359,6 +360,13 @@ def test_column_filters():
ok_('char_field_val_3' 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
rv = client.get('/admin/model2/?flt0_0=badval')
eq_(rv.status_code, 200)
......@@ -413,6 +421,13 @@ def test_column_filters():
ok_('char_field_val_3' 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
rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval')
eq_(rv.status_code, 200)
......
......@@ -92,6 +92,7 @@ def fill_db(db, Model1, Model2):
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_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_obj2 = Model1('date_obj2', date_field=date(2013,10,16))
......@@ -107,7 +108,7 @@ def fill_db(db, Model1, Model2):
db.session.add_all([
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_obj2, timeonly_obj2, datetime_obj2,
enum_obj1, enum_obj2, empty_obj
......@@ -674,6 +675,13 @@ def test_column_filters():
ok_('test2_val_3' 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
rv = client.get('/admin/model2/?flt0_0=badval')
eq_(rv.status_code, 200)
......@@ -728,6 +736,13 @@ def test_column_filters():
ok_('test2_val_3' 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
rv = client.get('/admin/model2/?flt0_5=5000%2Cbadval')
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