Added Binary support to UUID (MongoEngine/mongoengine#47)

This commit is contained in:
Ross Lawley 2012-08-01 16:03:33 +01:00
parent 2420b5e937
commit 4b3cea9e78
3 changed files with 74 additions and 21 deletions

View File

@ -5,6 +5,7 @@ Changelog
Changes in 0.6.X Changes in 0.6.X
================ ================
- Added Binary support to UUID (MongoEngine/mongoengine#47)
- Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46) - Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46)
- Fixed BinaryField python value issue (MongoEngine/mongoengine#48) - Fixed BinaryField python value issue (MongoEngine/mongoengine#48)
- Fixed SequenceField non numeric value lookup (MongoEngine/mongoengine#41) - Fixed SequenceField non numeric value lookup (MongoEngine/mongoengine#41)

View File

@ -4,9 +4,9 @@ import decimal
import gridfs import gridfs
import re import re
import uuid import uuid
import warnings
from bson import Binary, DBRef, SON, ObjectId from bson import Binary, DBRef, SON, ObjectId
from base import (BaseField, ComplexBaseField, ObjectIdField, from base import (BaseField, ComplexBaseField, ObjectIdField,
ValidationError, get_document, BaseDocument) ValidationError, get_document, BaseDocument)
from queryset import DO_NOTHING, QuerySet from queryset import DO_NOTHING, QuerySet
@ -1308,17 +1308,40 @@ class UUIDField(BaseField):
.. versionadded:: 0.6 .. versionadded:: 0.6
""" """
_binary = None
def __init__(self, **kwargs): def __init__(self, binary=None, **kwargs):
"""
Store UUID data in the database
:param binary: (optional) boolean store as binary.
.. versionchanged:: 0.6.19
"""
if binary is None:
binary = False
msg = ("UUIDFields will soon default to store as binary, please "
"configure binary=False if you wish to store as a string")
warnings.warn(msg, FutureWarning)
self._binary = binary
super(UUIDField, self).__init__(**kwargs) super(UUIDField, self).__init__(**kwargs)
def to_python(self, value): def to_python(self, value):
if not isinstance(value, basestring): if not self.binary:
value = unicode(value) if not isinstance(value, basestring):
return uuid.UUID(value) value = unicode(value)
return uuid.UUID(value)
return value
def to_mongo(self, value): def to_mongo(self, value):
return unicode(value) if not self._binary:
return unicode(value)
return value
def prepare_query_value(self, op, value):
if value is None:
return None
return self.to_mongo(value)
def validate(self, value): def validate(self, value):
if not isinstance(value, uuid.UUID): if not isinstance(value, uuid.UUID):

View File

@ -272,25 +272,54 @@ class FieldTest(unittest.TestCase):
person.admin = 'Yes' person.admin = 'Yes'
self.assertRaises(ValidationError, person.validate) self.assertRaises(ValidationError, person.validate)
def test_uuid_validation(self): def test_uuid_field_string(self):
"""Ensure that invalid values cannot be assigned to UUID fields. """Test UUID fields storing as String
""" """
class Person(Document): class Person(Document):
api_key = UUIDField() api_key = UUIDField(binary=False)
Person.drop_collection()
uu = uuid.uuid4()
Person(api_key=uu).save()
self.assertEqual(1, Person.objects(api_key=uu).count())
person = Person() person = Person()
# any uuid type is valid valid = (uuid.uuid4(), uuid.uuid1())
person.api_key = uuid.uuid4() for api_key in valid:
person.validate() person.api_key = api_key
person.api_key = uuid.uuid1() person.validate()
person.validate()
invalid = ('9d159858-549b-4975-9f98-dd2f987c113g',
'9d159858-549b-4975-9f98-dd2f987c113')
for api_key in invalid:
person.api_key = api_key
self.assertRaises(ValidationError, person.validate)
def test_uuid_field_binary(self):
"""Test UUID fields storing as Binary object
"""
class Person(Document):
api_key = UUIDField(binary=True)
Person.drop_collection()
uu = uuid.uuid4()
Person(api_key=uu).save()
self.assertEqual(1, Person.objects(api_key=uu).count())
person = Person()
valid = (uuid.uuid4(), uuid.uuid1())
for api_key in valid:
person.api_key = api_key
person.validate()
invalid = ('9d159858-549b-4975-9f98-dd2f987c113g',
'9d159858-549b-4975-9f98-dd2f987c113')
for api_key in invalid:
person.api_key = api_key
self.assertRaises(ValidationError, person.validate)
# last g cannot belong to an hex number
person.api_key = '9d159858-549b-4975-9f98-dd2f987c113g'
self.assertRaises(ValidationError, person.validate)
# short strings don't validate
person.api_key = '9d159858-549b-4975-9f98-dd2f987c113'
self.assertRaises(ValidationError, person.validate)
def test_datetime_validation(self): def test_datetime_validation(self):
"""Ensure that invalid values cannot be assigned to datetime fields. """Ensure that invalid values cannot be assigned to datetime fields.
@ -937,7 +966,7 @@ class FieldTest(unittest.TestCase):
visited = MapField(DateTimeField()) visited = MapField(DateTimeField())
Log.drop_collection() Log.drop_collection()
Log(name="wilson", visited={'friends': datetime.now()}).save() Log(name="wilson", visited={'friends': datetime.datetime.now()}).save()
self.assertEqual(1, Log.objects( self.assertEqual(1, Log.objects(
visited__friends__exists=True).count()) visited__friends__exists=True).count())