From 879bf08d18e0e0cedebd0ba950f2ec191a7c2c81 Mon Sep 17 00:00:00 2001 From: Rached Ben Mustapha Date: Mon, 8 Mar 2010 16:42:23 +0100 Subject: [PATCH 1/3] Simple implementation of BinaryField --- mongoengine/fields.py | 16 +++++++++++++++- tests/fields.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 0793f44b..29c86660 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -11,7 +11,8 @@ import decimal __all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField', 'DateTimeField', 'EmbeddedDocumentField', 'ListField', 'DictField', 'ObjectIdField', 'ReferenceField', 'ValidationError', - 'DecimalField', 'URLField', 'GenericReferenceField'] + 'DecimalField', 'URLField', 'GenericReferenceField', + 'BinaryField'] RECURSIVE_REFERENCE_CONSTANT = 'self' @@ -442,3 +443,16 @@ class GenericReferenceField(BaseField): def prepare_query_value(self, op, value): return self.to_mongo(value)['_ref'] + +class BinaryField(BaseField): + """A binary data field. + """ + + def __init__(self, **kwargs): + super(BinaryField, self).__init__(**kwargs) + + def to_mongo(self, value): + return pymongo.binary.Binary(value) + + def to_python(self, value): + return str(value) diff --git a/tests/fields.py b/tests/fields.py index 94f65186..80994b13 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -495,6 +495,24 @@ class FieldTest(unittest.TestCase): Post.drop_collection() User.drop_collection() + def test_binary_fields(self): + """Ensure that binary fields can be stored and retrieved. + """ + class Attachment(Document): + content_type = StringField() + blob = BinaryField() + + BLOB = '\xe6\x00\xc4\xff\x07' + MIME_TYPE = 'application/octet-stream' + + Attachment.drop_collection() + + attachment = Attachment(content_type=MIME_TYPE, blob=BLOB) + attachment.save() + + attachment_1 = Attachment.objects().first() + self.assertEqual(MIME_TYPE, attachment_1.content_type) + self.assertEqual(BLOB, attachment_1.blob) if __name__ == '__main__': unittest.main() From bb19ba3eb6158d66dbbc32e29b50b4f924f9c6b3 Mon Sep 17 00:00:00 2001 From: Rached Ben Mustapha Date: Mon, 8 Mar 2010 16:43:43 +0100 Subject: [PATCH 2/3] Drop collection at the end of the test --- tests/fields.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fields.py b/tests/fields.py index 80994b13..fc2edb2c 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -514,5 +514,7 @@ class FieldTest(unittest.TestCase): self.assertEqual(MIME_TYPE, attachment_1.content_type) self.assertEqual(BLOB, attachment_1.blob) + Attachment.drop_collection() + if __name__ == '__main__': unittest.main() From 0b3af2052f51dc7e64d1d8d8e1ab33727ec5d32a Mon Sep 17 00:00:00 2001 From: Rached Ben Mustapha Date: Mon, 8 Mar 2010 17:06:52 +0100 Subject: [PATCH 3/3] implement binary field size validation --- mongoengine/fields.py | 9 ++++++++- tests/fields.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 29c86660..fcae63ee 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -448,7 +448,8 @@ class BinaryField(BaseField): """A binary data field. """ - def __init__(self, **kwargs): + def __init__(self, max_bytes=None, **kwargs): + self.max_bytes = max_bytes super(BinaryField, self).__init__(**kwargs) def to_mongo(self, value): @@ -456,3 +457,9 @@ class BinaryField(BaseField): def to_python(self, value): return str(value) + + def validate(self, value): + assert isinstance(value, str) + + if self.max_bytes is not None and len(value) > self.max_bytes: + raise ValidationError('Binary value is too long') diff --git a/tests/fields.py b/tests/fields.py index fc2edb2c..986f0e26 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -516,5 +516,40 @@ class FieldTest(unittest.TestCase): Attachment.drop_collection() + def test_binary_validation(self): + """Ensure that invalid values cannot be assigned to binary fields. + """ + class Attachment(Document): + blob = BinaryField() + + class AttachmentRequired(Document): + blob = BinaryField(required=True) + + class AttachmentSizeLimit(Document): + blob = BinaryField(max_bytes=4) + + Attachment.drop_collection() + AttachmentRequired.drop_collection() + AttachmentSizeLimit.drop_collection() + + attachment = Attachment() + attachment.validate() + attachment.blob = 2 + self.assertRaises(ValidationError, attachment.validate) + + attachment_required = AttachmentRequired() + self.assertRaises(ValidationError, attachment_required.validate) + attachment_required.blob = '\xe6\x00\xc4\xff\x07' + attachment_required.validate() + + attachment_size_limit = AttachmentSizeLimit(blob='\xe6\x00\xc4\xff\x07') + self.assertRaises(ValidationError, attachment_size_limit.validate) + attachment_size_limit.blob = '\xe6\x00\xc4\xff' + attachment_size_limit.validate() + + Attachment.drop_collection() + AttachmentRequired.drop_collection() + AttachmentSizeLimit.drop_collection() + if __name__ == '__main__': unittest.main()