diff --git a/.gitignore b/.gitignore index 315674fe..0300bc77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ .* !.gitignore -*.pyc -.*.swp +*~ +*.py[co] +.*.sw[po] *.egg docs/.build docs/_build diff --git a/docs/changelog.rst b/docs/changelog.rst index b2ef802e..71f8e514 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,8 @@ Changelog Changes in dev ============== +- Updated ComplexFields so if required they won't accept empty lists / dicts +- Added spec file for rpm-based distributions - Fixed ListField so it doesnt accept strings - Added DynamicDocument and EmbeddedDynamicDocument classes for expando schemas diff --git a/mongoengine/base.py b/mongoengine/base.py index 40953f17..adf5eee9 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -282,6 +282,11 @@ class ComplexBaseField(BaseField): raise ValidationError('Invalid %s item (%s)' % ( self.field.__class__.__name__, str(v))) + # Don't allow empty values if required + if self.required and not value: + raise ValidationError('Field "%s" is required and cannot be empty' % + self.name) + def prepare_query_value(self, op, value): return self.to_mongo(value) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index a2008224..0104c56f 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -460,6 +460,9 @@ class GenericEmbeddedDocumentField(BaseField): class ListField(ComplexBaseField): """A list field that wraps a standard field, allowing multiple instances of the field to be used as a list in the database. + + .. note:: + Required means it cannot be empty - as the default for ListFields is [] """ # ListFields cannot be indexed with _types - MongoDB doesn't support this @@ -514,6 +517,9 @@ class DictField(ComplexBaseField): """A dictionary field that wraps a standard Python dictionary. This is similar to an embedded document, but the structure is not defined. + .. note:: + Required means it cannot be empty - as the default for ListFields is [] + .. versionadded:: 0.3 .. versionchanged:: 0.5 - Can now handle complex / varying types of data """ diff --git a/python-mongoengine.spec b/python-mongoengine.spec new file mode 100644 index 00000000..054993d4 --- /dev/null +++ b/python-mongoengine.spec @@ -0,0 +1,53 @@ +# sitelib for noarch packages, sitearch for others (remove the unneeded one) +%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} +%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} + +%define srcname mongoengine + +Name: python-%{srcname} +Version: 0.5.0 +Release: 2%{?dist} +Summary: A Python Document-Object Mapper for working with MongoDB + +Group: Development/Libraries +License: MIT +URL: https://github.com/namlook/mongoengine +Source0: %{srcname}-%{version}.tar.bz2 + +BuildRequires: python-devel +BuildRequires: python-setuptools + +Requires: mongodb +Requires: pymongo +Requires: python-blinker + +%description +MongoEngine is an ORM-like layer on top of PyMongo. + +%prep +%setup -q -n %{srcname}-%{version} + + +%build +# Remove CFLAGS=... for noarch packages (unneeded) +CFLAGS="$RPM_OPT_FLAGS" %{__python} setup.py build + + +%install +rm -rf $RPM_BUILD_ROOT +%{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%doc docs AUTHORS LICENSE README.rst +# For noarch packages: sitelib + %{python_sitelib}/* +# For arch-specific packages: sitearch +# %{python_sitearch}/* + +%changelog +* Fri Sep 23 2011 Pau Aliagas 0.5.0-1 +- Initial version diff --git a/tests/fields.py b/tests/fields.py index 6c183b49..c95b544e 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -503,7 +503,6 @@ class FieldTest(unittest.TestCase): post.info = [{'test': 3}] post.save() - self.assertEquals(BlogPost.objects.count(), 3) self.assertEquals(BlogPost.objects.filter(info__exact='test').count(), 1) self.assertEquals(BlogPost.objects.filter(info__0__test='test').count(), 1) @@ -533,7 +532,6 @@ class FieldTest(unittest.TestCase): Simple.drop_collection() - def test_list_field_rejects_strings(self): """Strings aren't valid list field data types""" @@ -546,6 +544,26 @@ class FieldTest(unittest.TestCase): self.assertRaises(ValidationError, e.save) + def test_complex_field_required(self): + """Ensure required cant be None / Empty""" + + class Simple(Document): + mapping = ListField(required=True) + + Simple.drop_collection() + e = Simple() + e.mapping = [] + + self.assertRaises(ValidationError, e.save) + + class Simple(Document): + mapping = DictField(required=True) + + Simple.drop_collection() + e = Simple() + e.mapping = {} + + self.assertRaises(ValidationError, e.save) def test_list_field_complex(self): """Ensure that the list fields can handle the complex types."""