# -*- coding: utf-8 -*- from decimal import Decimal from mongoengine import * from tests.utils import MongoDBTestCase class TestDecimalField(MongoDBTestCase): def test_validation(self): """Ensure that invalid values cannot be assigned to decimal fields. """ class Person(Document): height = DecimalField(min_value=Decimal('0.1'), max_value=Decimal('3.5')) Person.drop_collection() Person(height=Decimal('1.89')).save() person = Person.objects.first() self.assertEqual(person.height, Decimal('1.89')) person.height = '2.0' person.save() person.height = 0.01 self.assertRaises(ValidationError, person.validate) person.height = Decimal('0.01') self.assertRaises(ValidationError, person.validate) person.height = Decimal('4.0') self.assertRaises(ValidationError, person.validate) person.height = 'something invalid' self.assertRaises(ValidationError, person.validate) person_2 = Person(height='something invalid') self.assertRaises(ValidationError, person_2.validate) def test_comparison(self): class Person(Document): money = DecimalField() Person.drop_collection() Person(money=6).save() Person(money=7).save() Person(money=8).save() Person(money=10).save() self.assertEqual(2, Person.objects(money__gt=Decimal("7")).count()) self.assertEqual(2, Person.objects(money__gt=7).count()) self.assertEqual(2, Person.objects(money__gt="7").count()) self.assertEqual(3, Person.objects(money__gte="7").count()) def test_storage(self): class Person(Document): float_value = DecimalField(precision=4) string_value = DecimalField(precision=4, force_string=True) Person.drop_collection() values_to_store = [10, 10.1, 10.11, "10.111", Decimal("10.1111"), Decimal("10.11111")] for store_at_creation in [True, False]: for value in values_to_store: # to_python is called explicitly if values were sent in the kwargs of __init__ if store_at_creation: Person(float_value=value, string_value=value).save() else: person = Person.objects.create() person.float_value = value person.string_value = value person.save() # How its stored expected = [ {'float_value': 10.0, 'string_value': '10.0000'}, {'float_value': 10.1, 'string_value': '10.1000'}, {'float_value': 10.11, 'string_value': '10.1100'}, {'float_value': 10.111, 'string_value': '10.1110'}, {'float_value': 10.1111, 'string_value': '10.1111'}, {'float_value': 10.1111, 'string_value': '10.1111'}] expected.extend(expected) actual = list(Person.objects.exclude('id').as_pymongo()) self.assertEqual(expected, actual) # How it comes out locally expected = [Decimal('10.0000'), Decimal('10.1000'), Decimal('10.1100'), Decimal('10.1110'), Decimal('10.1111'), Decimal('10.1111')] expected.extend(expected) for field_name in ['float_value', 'string_value']: actual = list(Person.objects().scalar(field_name)) self.assertEqual(expected, actual)