From 51065e7a4dda96943dadfcbdfcca6111dfa1f9f5 Mon Sep 17 00:00:00 2001 From: flosch Date: Sun, 25 Jul 2010 18:33:33 +0200 Subject: [PATCH 1/9] Closes #46 by instantiating a new default instance for every field by request. --- mongoengine/base.py | 5 ++++- mongoengine/fields.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mongoengine/base.py b/mongoengine/base.py index 086c7874..10ff1219 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -52,7 +52,10 @@ class BaseField(object): # Get value from document instance if available, if not use default value = instance._data.get(self.name) if value is None: - value = self.default + if callable(self.default): # fixes #46 + value = self.default() + else: + value = self.default # Allow callable default values if callable(value): value = value() diff --git a/mongoengine/fields.py b/mongoengine/fields.py index f84f751b..670e3cd3 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -263,7 +263,7 @@ class ListField(BaseField): raise ValidationError('Argument to ListField constructor must be ' 'a valid field') self.field = field - kwargs.setdefault('default', []) + kwargs.setdefault('default', lambda: []) super(ListField, self).__init__(**kwargs) def __get__(self, instance, owner): @@ -356,7 +356,7 @@ class DictField(BaseField): def __init__(self, basecls=None, *args, **kwargs): self.basecls = basecls or BaseField assert issubclass(self.basecls, BaseField) - kwargs.setdefault('default', {}) + kwargs.setdefault('default', lambda: {}) super(DictField, self).__init__(*args, **kwargs) def validate(self, value): From 9d82911f6338747411788291175739f436d95709 Mon Sep 17 00:00:00 2001 From: flosch Date: Sun, 25 Jul 2010 18:38:24 +0200 Subject: [PATCH 2/9] Added tests for #46. --- tests/fields.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/fields.py b/tests/fields.py index 136437b8..ef776d4a 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -693,5 +693,18 @@ class FieldTest(unittest.TestCase): Event.drop_collection() + def test_ensure_unique_default_instances(self): + """Ensure that every document has it's own unique default instance.""" + class D(Document): + data = DictField() + data2 = DictField(default=lambda: {}) + + d1 = D() + d1.data['foo'] = 'bar' + d1.data2['foo'] = 'bar' + d2 = D() + self.assertEqual(d2.data, {}) + self.assertEqual(d2.data2, {}) + if __name__ == '__main__': unittest.main() From 386c48b116191a754e3cec550ccdbd5246efdc97 Mon Sep 17 00:00:00 2001 From: flosch Date: Sun, 25 Jul 2010 18:43:11 +0200 Subject: [PATCH 3/9] Typo. --- tests/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fields.py b/tests/fields.py index ef776d4a..6e42ea4d 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -694,7 +694,7 @@ class FieldTest(unittest.TestCase): Event.drop_collection() def test_ensure_unique_default_instances(self): - """Ensure that every document has it's own unique default instance.""" + """Ensure that every field has it's own unique default instance.""" class D(Document): data = DictField() data2 = DictField(default=lambda: {}) From 9411b38508ac261f166dac1f8f8adc7f01084334 Mon Sep 17 00:00:00 2001 From: flosch Date: Sun, 25 Jul 2010 18:45:49 +0200 Subject: [PATCH 4/9] Removed unnecessary comment. --- mongoengine/queryset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 00a7f7a2..be29ae83 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -135,7 +135,6 @@ class Q(object): # Handle DBRef if isinstance(value, pymongo.dbref.DBRef): - # this.created_user.$id == "4c4c56f8cc1831418c000000" op_js = '(this.%(field)s.$id == "%(id)s" &&'\ ' this.%(field)s.$ref == "%(ref)s")' % { 'field': key, From 2f991ac6f18172008ed71f1d97ab6ee71ea360ba Mon Sep 17 00:00:00 2001 From: flosch Date: Sun, 25 Jul 2010 19:02:15 +0200 Subject: [PATCH 5/9] Added all() method to get all document instances from a document. Extended the FileField's tests with testing on empty filefield. --- mongoengine/queryset.py | 4 ++++ tests/fields.py | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index be29ae83..ffbe5255 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -238,6 +238,10 @@ class QuerySet(object): """An alias of :meth:`~mongoengine.queryset.QuerySet.__call__` """ return self.__call__(*q_objs, **query) + + def all(self): + """Returns all documents.""" + return self.__call__() @property def _collection(self): diff --git a/tests/fields.py b/tests/fields.py index 6e42ea4d..1e53d23d 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -674,7 +674,12 @@ class FieldTest(unittest.TestCase): PutFile.drop_collection() StreamFile.drop_collection() SetFile.drop_collection() - + + # Make sure FileField is optional and not required + class DemoFile(Document): + file = FileField() + d = DemoFile.objects.create() + def test_geo_indexes(self): """Ensure that indexes are created automatically for GeoPointFields. """ From 7ab2e21c106fc89875b1ae4ae79ecd7e0988ded3 Mon Sep 17 00:00:00 2001 From: flosch Date: Mon, 26 Jul 2010 16:42:10 +0200 Subject: [PATCH 6/9] Handle unsafe expressions when using startswith/endswith/contains with unsafe expressions. Closes #58 --- mongoengine/fields.py | 3 +++ tests/queryset.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 670e3cd3..bd81d3a8 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -66,6 +66,9 @@ class StringField(BaseField): regex = r'%s$' elif op == 'exact': regex = r'^%s$' + + # escape unsafe characters which could lead to a re.error + value = re.escape(value) value = re.compile(regex % value, flags) return value diff --git a/tests/queryset.py b/tests/queryset.py index 8cbd9a40..1efd034c 100644 --- a/tests/queryset.py +++ b/tests/queryset.py @@ -288,6 +288,13 @@ class QuerySetTest(unittest.TestCase): self.assertEqual(obj, person) obj = self.Person.objects(Q(name__iexact='gUIDO VAN rOSSU')).first() self.assertEqual(obj, None) + + # Test unsafe expressions + person = self.Person(name='Guido van Rossum [.\'Geek\']') + person.save() + + obj = self.Person.objects(Q(name__icontains='[.\'Geek')).first() + self.assertEqual(obj, person) def test_filter_chaining(self): """Ensure filters can be chained together. From 6791f205af3d15a0f4ccaf357692ba868b6ebfff Mon Sep 17 00:00:00 2001 From: flosch Date: Mon, 26 Jul 2010 16:50:09 +0200 Subject: [PATCH 7/9] Style fix. --- mongoengine/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index bd81d3a8..30a11f20 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -66,7 +66,7 @@ class StringField(BaseField): regex = r'%s$' elif op == 'exact': regex = r'^%s$' - + # escape unsafe characters which could lead to a re.error value = re.escape(value) value = re.compile(regex % value, flags) From 21d267cb112e9030a0f17271fecd052dbe35b50a Mon Sep 17 00:00:00 2001 From: flosch Date: Mon, 26 Jul 2010 17:28:59 +0200 Subject: [PATCH 8/9] Now order_by() works like queries for referencing deeper fields (replacing . with __). old: order_by('mydoc.myattr') / new: order_by('mydoc__myattr'). Closes #45 --- mongoengine/queryset.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index ffbe5255..0b9218af 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -670,11 +670,13 @@ class QuerySet(object): """ key_list = [] for key in keys: + if not key: continue direction = pymongo.ASCENDING if key[0] == '-': direction = pymongo.DESCENDING if key[0] in ('-', '+'): key = key[1:] + key = key.replace('__', '.') key_list.append((key, direction)) self._ordering = key_list From 1147ac43506283a37554d09242894e9088f2133b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Peignier?= Date: Sun, 23 May 2010 00:19:50 +0800 Subject: [PATCH 9/9] ignore virtualenv directory --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 42dcc6e6..57cf1b7b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ docs/.build docs/_build build/ dist/ -mongoengine.egg-info/ \ No newline at end of file +mongoengine.egg-info/ +env/ \ No newline at end of file