From 0af96b1323b9110890ea85755c1e7fdd1ec30934 Mon Sep 17 00:00:00 2001 From: Bastien Gerard Date: Sat, 7 Aug 2021 22:38:27 +0200 Subject: [PATCH] Add test for DecimalField(precision=0) and raise exception if negative/invalid values are provided --- AUTHORS | 1 + docs/changelog.rst | 1 + mongoengine/fields.py | 10 ++++++++-- tests/fields/test_decimal_field.py | 20 ++++++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 64069d33..a35fc5f1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -261,3 +261,4 @@ that much better: * Felix Schultheiß (https://github.com/felix-smashdocs) * Jan Stein (https://github.com/janste63) * Timothé Perez (https://github.com/AchilleAsh) + * oleksandr-l5 (https://github.com/oleksandr-l5) diff --git a/docs/changelog.rst b/docs/changelog.rst index be2c38c3..5c378603 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,7 @@ Development - (Fill this out as you fix issues and develop your features). - EnumField improvements: now `choices` limits the values of an enum to allow - Fix deepcopy of EmbeddedDocument #2202 +- Fix error when using precision=0 with DecimalField #2535 Changes in 0.23.1 =========== diff --git a/mongoengine/fields.py b/mongoengine/fields.py index be07ec88..25bf37ef 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -468,6 +468,10 @@ class DecimalField(BaseField): self.min_value = min_value self.max_value = max_value self.force_string = force_string + + if precision < 0 or not isinstance(precision, int): + self.error("precision must be a positive integer") + self.precision = precision self.rounding = rounding @@ -483,10 +487,12 @@ class DecimalField(BaseField): except (TypeError, ValueError, decimal.InvalidOperation): return value if self.precision > 0: - return value.quantize(decimal.Decimal(".%s" % ("0" * self.precision)), rounding=self.rounding) + return value.quantize( + decimal.Decimal(".%s" % ("0" * self.precision)), rounding=self.rounding + ) else: return value.quantize(decimal.Decimal(), rounding=self.rounding) - + def to_mongo(self, value): if value is None: return value diff --git a/tests/fields/test_decimal_field.py b/tests/fields/test_decimal_field.py index 89a725a9..6c291971 100644 --- a/tests/fields/test_decimal_field.py +++ b/tests/fields/test_decimal_field.py @@ -118,3 +118,23 @@ class TestDecimalField(MongoDBTestCase): assert 2 == Person.objects(money__gt="7").count() assert 3 == Person.objects(money__gte="7").count() + + def test_precision_0(self): + """prevent regression of a bug that was raising an exception when using precision=0""" + + class TestDoc(Document): + d = DecimalField(precision=0) + + TestDoc.drop_collection() + + td = TestDoc(d=Decimal("12.00032678131263")) + assert td.d == Decimal("12") + + def test_precision_negative_raise(self): + """prevent regression of a bug that was raising an exception when using precision=0""" + with pytest.raises( + ValidationError, match="precision must be a positive integer" + ): + + class TestDoc(Document): + dneg = DecimalField(precision=-1)