diff --git a/src/formpack/schema/fields.py b/src/formpack/schema/fields.py index c6e9f8c..f47e570 100644 --- a/src/formpack/schema/fields.py +++ b/src/formpack/schema/fields.py @@ -922,7 +922,10 @@ def parse_values(self, raw_values): if self.data_type == 'integer': yield int(raw_values) else: - yield float(raw_values) + value = float(raw_values) + if not math.isfinite(value): + raise ValueError(f'Non-finite float value: {raw_values!r}') + yield value def format(self, val, xls_types_as_text=True, *args, **kwargs): if val is None: diff --git a/tests/test_autoreport.py b/tests/test_autoreport.py index 0a0e107..db792f3 100644 --- a/tests/test_autoreport.py +++ b/tests/test_autoreport.py @@ -647,3 +647,57 @@ def test_stats_with_non_numeric_value_for_numeric_field(self): ] for i, stat in enumerate(stats): assert stat == expected[i] + + def test_stats_with_non_finite_float_value(self): + """ + Non-finite float values (Inf, -Inf, nan) for a decimal field should + be treated as if no response was provided (not_provided). + """ + title = 'Just one decimal' + schemas = [ + { + 'content': { + 'survey': [ + { + 'type': 'decimal', + 'name': 'the_number', + 'label': 'Enter the number!', + } + ] + } + } + ] + submissions = [ + {'the_number': '1.0'}, + {'the_number': '2.0'}, + {'the_number': '3.0'}, + {'the_number': 'Inf'}, + {'the_number': '-Inf'}, + {'the_number': 'nan'}, + ] + fp = FormPack(schemas, title) + + report = fp.autoreport() + stats = report.get_stats(submissions) + + assert stats.submissions_count == len(submissions) + + stats = [(str(repr(f)), n, d) for f, n, d in stats] + expected = [ + ( + "", + 'the_number', + { + 'mean': 2.0, + 'median': 2.0, + 'mode': '*', + 'not_provided': 3, + 'provided': 3, + 'show_graph': False, + 'stdev': 1.0, + 'total_count': 6, + }, + ) + ] + for i, stat in enumerate(stats): + assert stat == expected[i]