diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 70c210c16..9f20a5fe6 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1141,11 +1141,13 @@ class DecimalField(Field): return value context = decimal.getcontext().copy() + # For Python 2.7 compatibility when using cdecimal + rounding = context.rounding if self.rounding is None else self.rounding if self.max_digits is not None: context.prec = self.max_digits return value.quantize( decimal.Decimal('.1') ** self.decimal_places, - rounding=self.rounding, + rounding=rounding, context=context ) diff --git a/tests/test_fields.py b/tests/test_fields.py index 9a1d04979..a63974ac2 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -7,6 +7,7 @@ from decimal import ROUND_DOWN, ROUND_UP, Decimal import pytest import pytz +from _pytest.monkeypatch import MonkeyPatch from django.core.exceptions import ValidationError as DjangoValidationError from django.http import QueryDict from django.test import TestCase, override_settings @@ -18,6 +19,11 @@ from rest_framework import exceptions, serializers from rest_framework.compat import ProhibitNullCharactersValidator from rest_framework.fields import DjangoImageField, is_simple_callable +try: + import cdecimal +except ImportError: + cdecimal = False + try: import typings except ImportError: @@ -1150,6 +1156,16 @@ class TestQuantizedValueForDecimal(TestCase): expected_digit_tuple = (0, (1, 2, 0, 0), -2) assert value == expected_digit_tuple + @unittest.skipUnless(cdecimal, 'requires python 2.7') + def test_quantize_on_monkey_patched_cdecimal(self): + # Monkey-patch cdecimal to replace decimal in for DecimalField + monkeypatch = MonkeyPatch() + + with monkeypatch.context() as m: + m.setattr('rest_framework.fields.decimal', cdecimal) + f = rest_framework.fields.DecimalField(max_digits=4, decimal_places=2) + f.quantize(cdecimal.Decimal('1.234')) + class TestNoDecimalPlaces(FieldValues): valid_inputs = { diff --git a/tox.ini b/tox.ini index 968ec1ef1..3646d5deb 100644 --- a/tox.ini +++ b/tox.ini @@ -24,6 +24,7 @@ deps = django20: Django>=2.0,<2.1 django21: Django>=2.1,<2.2 djangomaster: https://github.com/django/django/archive/master.tar.gz + py27: m3-cdecimal -rrequirements/requirements-testing.txt -rrequirements/requirements-optionals.txt