Merge remote-tracking branch 'origin/master'
This commit is contained in:
		| @@ -9,6 +9,9 @@ MongoEngine | ||||
| .. image:: https://secure.travis-ci.org/MongoEngine/mongoengine.png?branch=master | ||||
|   :target: http://travis-ci.org/MongoEngine/mongoengine | ||||
|    | ||||
| .. image:: https://coveralls.io/repos/MongoEngine/mongoengine/badge.png?branch=master  | ||||
|   :target: https://coveralls.io/r/MongoEngine/mongoengine?branch=master | ||||
|  | ||||
| About | ||||
| ===== | ||||
| MongoEngine is a Python Object-Document Mapper for working with MongoDB. | ||||
| @@ -92,4 +95,4 @@ Community | ||||
|  | ||||
| Contributing | ||||
| ============ | ||||
| We welcome contributions! see  the`Contribution guidelines <https://github.com/MongoEngine/mongoengine/blob/master/CONTRIBUTING.rst>`_ | ||||
| We welcome contributions! see  the `Contribution guidelines <https://github.com/MongoEngine/mongoengine/blob/master/CONTRIBUTING.rst>`_ | ||||
|   | ||||
| @@ -38,6 +38,7 @@ Context Managers | ||||
| ================ | ||||
|  | ||||
| .. autoclass:: mongoengine.context_managers.switch_db | ||||
| .. autoclass:: mongoengine.context_managers.switch_collection | ||||
| .. autoclass:: mongoengine.context_managers.no_dereference | ||||
| .. autoclass:: mongoengine.context_managers.query_counter | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,12 @@ | ||||
| Changelog | ||||
| ========= | ||||
|  | ||||
| Changes in 0.8.7 | ||||
| ================ | ||||
| - Calling reload on deleted / nonexistant documents raises DoesNotExist (#538) | ||||
| - Stop ensure_indexes running on a secondaries (#555) | ||||
| - Fix circular import issue with django auth (#531) (#545) | ||||
|  | ||||
| Changes in 0.8.6 | ||||
| ================ | ||||
| - Fix django auth import (#531) | ||||
|   | ||||
| @@ -100,3 +100,18 @@ access to the same User document across databases:: | ||||
|  | ||||
| .. note:: Make sure any aliases have been registered with | ||||
|     :func:`~mongoengine.register_connection` before using the context manager. | ||||
|  | ||||
| There is also a switch collection context manager as well.  The | ||||
| :class:`~mongoengine.context_managers.switch_collection` context manager allows | ||||
| you to change the collection for a given class allowing quick and easy | ||||
| access to the same Group document across collection:: | ||||
|  | ||||
|         from mongoengine.context_managers import switch_db | ||||
|  | ||||
|         class Group(Document): | ||||
|             name = StringField() | ||||
|  | ||||
|         Group(name="test").save()  # Saves in the default db | ||||
|  | ||||
|         with switch_collection(Group, 'group2000') as Group: | ||||
|             Group(name="hello Group 2000 collection!").save()  # Saves in group2000 collection | ||||
|   | ||||
| @@ -92,8 +92,8 @@ were added in 0.8 for:  :class:`~mongoengine.fields.PointField`, | ||||
| * ``geo_within`` -- Check if a geometry is within a polygon.  For ease of use | ||||
|     it accepts either a geojson geometry or just the polygon coordinates eg:: | ||||
|  | ||||
|         loc.objects(point__geo_with=[[[40, 5], [40, 6], [41, 6], [40, 5]]]) | ||||
|         loc.objects(point__geo_with={"type": "Polygon", | ||||
|         loc.objects(point__geo_within=[[[40, 5], [40, 6], [41, 6], [40, 5]]]) | ||||
|         loc.objects(point__geo_within={"type": "Polygon", | ||||
|                                  "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]}) | ||||
|  | ||||
| * ``geo_within_box`` - simplified geo_within searching with a box eg:: | ||||
|   | ||||
| @@ -2,6 +2,12 @@ | ||||
| Upgrading | ||||
| ######### | ||||
|  | ||||
| 0.8.7 | ||||
| ***** | ||||
|  | ||||
| Calling reload on deleted / nonexistant documents now raises a DoesNotExist | ||||
| exception. | ||||
|  | ||||
|  | ||||
| 0.8.2 to 0.8.3 | ||||
| ************** | ||||
| @@ -270,7 +276,7 @@ queryset you should upgrade to use count:: | ||||
|     len(Animal.objects(type="mammal")) | ||||
|  | ||||
|     # New code | ||||
|     Animal.objects(type="mammal").count()) | ||||
|     Animal.objects(type="mammal").count() | ||||
|  | ||||
|  | ||||
| .only() now inline with .exclude() | ||||
|   | ||||
| @@ -15,7 +15,7 @@ import django | ||||
| __all__ = (list(document.__all__) + fields.__all__ + connection.__all__ + | ||||
|            list(queryset.__all__) + signals.__all__ + list(errors.__all__)) | ||||
|  | ||||
| VERSION = (0, 8, 6) | ||||
| VERSION = (0, 8, 7) | ||||
|  | ||||
|  | ||||
| def get_version(): | ||||
|   | ||||
| @@ -9,7 +9,6 @@ from django.contrib.auth.models import AnonymousUser | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
|  | ||||
| from .utils import datetime_now | ||||
| from .mongo_auth.models import get_user_document | ||||
|  | ||||
| REDIRECT_FIELD_NAME = 'next' | ||||
|  | ||||
| @@ -382,9 +381,10 @@ class MongoEngineBackend(object): | ||||
|     supports_object_permissions = False | ||||
|     supports_anonymous_user = False | ||||
|     supports_inactive_user = False | ||||
|     _user_doc = False | ||||
|  | ||||
|     def authenticate(self, username=None, password=None): | ||||
|         user = get_user_document().objects(username=username).first() | ||||
|         user = self.user_document.objects(username=username).first() | ||||
|         if user: | ||||
|             if password and user.check_password(password): | ||||
|                 backend = auth.get_backends()[0] | ||||
| @@ -393,8 +393,14 @@ class MongoEngineBackend(object): | ||||
|         return None | ||||
|  | ||||
|     def get_user(self, user_id): | ||||
|         return get_user_document().objects.with_id(user_id) | ||||
|         return self.user_document.objects.with_id(user_id) | ||||
|  | ||||
|     @property | ||||
|     def user_document(self): | ||||
|         if self._user_doc is False: | ||||
|             from .mongo_auth.models import get_user_document | ||||
|             self._user_doc = get_user_document() | ||||
|         return self._user_doc | ||||
|  | ||||
| def get_user(userid): | ||||
|     """Returns a User object from an id (User.id). Django's equivalent takes | ||||
|   | ||||
| @@ -12,6 +12,7 @@ from mongoengine.common import _import_class | ||||
| from mongoengine.base import (DocumentMetaclass, TopLevelDocumentMetaclass, | ||||
|                               BaseDocument, BaseDict, BaseList, | ||||
|                               ALLOW_INHERITANCE, get_document) | ||||
| from mongoengine.errors import ValidationError | ||||
| from mongoengine.queryset import OperationError, NotUniqueError, QuerySet | ||||
| from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME | ||||
| from mongoengine.context_managers import switch_db, switch_collection | ||||
| @@ -280,7 +281,9 @@ class Document(BaseDocument): | ||||
|                     kwargs.update(cascade_kwargs) | ||||
|                 kwargs['_refs'] = _refs | ||||
|                 self.cascade_save(**kwargs) | ||||
|  | ||||
|         except pymongo.errors.DuplicateKeyError, err: | ||||
|             message = u'Tried to save duplicate unique keys (%s)' | ||||
|             raise NotUniqueError(message % unicode(err)) | ||||
|         except pymongo.errors.OperationFailure, err: | ||||
|             message = 'Could not save document (%s)' | ||||
|             if re.match('^E1100[01] duplicate key', unicode(err)): | ||||
| @@ -450,14 +453,16 @@ class Document(BaseDocument): | ||||
|         .. versionadded:: 0.1.2 | ||||
|         .. versionchanged:: 0.6  Now chainable | ||||
|         """ | ||||
|         if not self.pk: | ||||
|             raise self.DoesNotExist("Document does not exist") | ||||
|         obj = self._qs.read_preference(ReadPreference.PRIMARY).filter( | ||||
|                     **self._object_key).limit(1).select_related(max_depth=max_depth) | ||||
|  | ||||
|  | ||||
|         if obj: | ||||
|             obj = obj[0] | ||||
|         else: | ||||
|             msg = "Reloaded document has been deleted" | ||||
|             raise OperationError(msg) | ||||
|             raise self.DoesNotExist("Document does not exist") | ||||
|         for field in self._fields_ordered: | ||||
|             setattr(self, field, self._reload(field, obj[field])) | ||||
|         self._changed_fields = obj._changed_fields | ||||
| @@ -547,6 +552,8 @@ class Document(BaseDocument): | ||||
|         index_cls = cls._meta.get('index_cls', True) | ||||
|  | ||||
|         collection = cls._get_collection() | ||||
|         if collection.read_preference > 1: | ||||
|             return | ||||
|  | ||||
|         # determine if an index which we are creating includes | ||||
|         # _cls as its first field; if so, we can avoid creating | ||||
|   | ||||
| @@ -153,7 +153,7 @@ class EmailField(StringField): | ||||
|     EMAIL_REGEX = re.compile( | ||||
|         r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom | ||||
|         r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"'  # quoted-string | ||||
|         r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,253}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE  # domain | ||||
|         r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,253}[A-Z0-9])?\.)+[A-Z]{2,6}$', re.IGNORECASE  # domain | ||||
|     ) | ||||
|  | ||||
|     def validate(self, value): | ||||
|   | ||||
| @@ -302,8 +302,11 @@ class BaseQuerySet(object): | ||||
|         signals.pre_bulk_insert.send(self._document, documents=docs) | ||||
|         try: | ||||
|             ids = self._collection.insert(raw, **write_concern) | ||||
|         except pymongo.errors.DuplicateKeyError, err: | ||||
|             message = 'Could not save document (%s)'; | ||||
|             raise NotUniqueError(message % unicode(err)) | ||||
|         except pymongo.errors.OperationFailure, err: | ||||
|             message = 'Could not save document (%s)' | ||||
|             message = 'Could not save document (%s)'; | ||||
|             if re.match('^E1100[01] duplicate key', unicode(err)): | ||||
|                 # E11000 - duplicate key error index | ||||
|                 # E11001 - duplicate key on update | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| %define srcname mongoengine | ||||
|  | ||||
| Name:           python-%{srcname} | ||||
| Version:        0.8.6 | ||||
| Version:        0.8.7 | ||||
| Release:        1%{?dist} | ||||
| Summary:        A Python Document-Object Mapper for working with MongoDB | ||||
|  | ||||
|   | ||||
| @@ -491,7 +491,7 @@ class IndexesTest(unittest.TestCase): | ||||
|  | ||||
|         def invalid_index_2(): | ||||
|             return BlogPost.objects.hint(('tags', 1)) | ||||
|         self.assertRaises(TypeError, invalid_index_2) | ||||
|         self.assertRaises(Exception, invalid_index_2) | ||||
|  | ||||
|     def test_unique(self): | ||||
|         """Ensure that uniqueness constraints are applied to fields. | ||||
|   | ||||
| @@ -409,6 +409,27 @@ class InstanceTest(unittest.TestCase): | ||||
|         self.assertEqual(len(doc.embedded_field.list_field), 4) | ||||
|         self.assertEqual(len(doc.embedded_field.dict_field), 2) | ||||
|  | ||||
|     def test_reload_doesnt_exist(self): | ||||
|         class Foo(Document): | ||||
|             pass | ||||
|  | ||||
|         f = Foo() | ||||
|         try: | ||||
|             f.reload() | ||||
|         except Foo.DoesNotExist: | ||||
|             pass | ||||
|         except Exception as ex: | ||||
|             self.assertFalse("Threw wrong exception") | ||||
|  | ||||
|         f.save() | ||||
|         f.delete() | ||||
|         try: | ||||
|             f.reload() | ||||
|         except Foo.DoesNotExist: | ||||
|             pass | ||||
|         except Exception as ex: | ||||
|             self.assertFalse("Threw wrong exception") | ||||
|  | ||||
|     def test_dictionary_access(self): | ||||
|         """Ensure that dictionary-style field access works properly. | ||||
|         """ | ||||
|   | ||||
| @@ -2499,6 +2499,9 @@ class FieldTest(unittest.TestCase): | ||||
|         user = User(email="ross@example.com") | ||||
|         self.assertTrue(user.validate() is None) | ||||
|  | ||||
|         user = User(email="ross@example.co.uk") | ||||
|         self.assertTrue(user.validate() is None) | ||||
|  | ||||
|         user = User(email=("Kofq@rhom0e4klgauOhpbpNdogawnyIKvQS0wk2mjqrgGQ5S" | ||||
|                            "ucictfqpdkK9iS1zeFw8sg7s7cwAF7suIfUfeyueLpfosjn3" | ||||
|                            "aJIazqqWkm7.net")) | ||||
| @@ -2507,6 +2510,9 @@ class FieldTest(unittest.TestCase): | ||||
|         user = User(email='me@localhost') | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|  | ||||
|         user = User(email="ross@example.com.") | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|  | ||||
|     def test_email_field_honors_regex(self): | ||||
|         class User(Document): | ||||
|             email = EmailField(regex=r'\w+@example.com') | ||||
|   | ||||
| @@ -16,6 +16,7 @@ settings.configure( | ||||
|     USE_TZ=True, | ||||
|     INSTALLED_APPS=('django.contrib.auth', 'mongoengine.django.mongo_auth'), | ||||
|     AUTH_USER_MODEL=('mongo_auth.MongoUser'), | ||||
|     AUTHENTICATION_BACKENDS = ('mongoengine.django.auth.MongoEngineBackend',) | ||||
| ) | ||||
|  | ||||
| try: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user