fix conflict
This commit is contained in:
		| @@ -7,7 +7,9 @@ Development | ||||
| - (Fill this out as you fix issues and develop your features). | ||||
| - Fix .only() working improperly after using .count() of the same instance of QuerySet | ||||
| - POTENTIAL BREAKING CHANGE: All result fields are now passed, including internal fields (_cls, _id) when using `QuerySet.as_pymongo` #1976 | ||||
| - Document a BREAKING CHANGE introduced in 0.15.3 and not reported at that time (#1995) | ||||
| - Fix InvalidStringData error when using modify on a BinaryField #1127 | ||||
| - DEPRECATION: `EmbeddedDocument.save` & `.reload` are marked as deprecated and will be removed in a next version of mongoengine #1552 | ||||
|  | ||||
| ================= | ||||
| Changes in 0.16.3 | ||||
| @@ -65,6 +67,7 @@ Changes in 0.16.0 | ||||
|  | ||||
| Changes in 0.15.3 | ||||
| ================= | ||||
| -  BREAKING CHANGES: `Queryset.update/update_one` methods now returns an UpdateResult when `full_result=True` is provided and no longer a dict (relates to #1491) | ||||
| -  Subfield resolve error in generic_emdedded_document query #1651 #1652 | ||||
| -  use each modifier only with $position #1673 #1675 | ||||
| -  Improve LazyReferenceField and GenericLazyReferenceField with nested fields #1704 | ||||
|   | ||||
| @@ -91,9 +91,15 @@ class EmbeddedDocument(six.with_metaclass(DocumentMetaclass, BaseDocument)): | ||||
|         return data | ||||
|  | ||||
|     def save(self, *args, **kwargs): | ||||
|         warnings.warn("EmbeddedDocument.save is deprecated and will be removed in a next version of mongoengine." | ||||
|                       "Use the parent document's .save() or ._instance.save()", | ||||
|                       DeprecationWarning, stacklevel=2) | ||||
|         self._instance.save(*args, **kwargs) | ||||
|  | ||||
|     def reload(self, *args, **kwargs): | ||||
|         warnings.warn("EmbeddedDocument.reload is deprecated and will be removed in a next version of mongoengine." | ||||
|                       "Use the parent document's .reload() or ._instance.reload()", | ||||
|                       DeprecationWarning, stacklevel=2) | ||||
|         self._instance.reload(*args, **kwargs) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -499,11 +499,12 @@ class BaseQuerySet(object): | ||||
|             ``save(..., write_concern={w: 2, fsync: True}, ...)`` will | ||||
|             wait until at least two servers have recorded the write and | ||||
|             will force an fsync on the primary server. | ||||
|         :param full_result: Return the full result dictionary rather than just the number | ||||
|             updated, e.g. return | ||||
|             ``{'n': 2, 'nModified': 2, 'ok': 1.0, 'updatedExisting': True}``. | ||||
|         :param full_result: Return the associated ``pymongo.UpdateResult`` rather than just the number | ||||
|             updated items | ||||
|         :param update: Django-style update keyword arguments | ||||
|  | ||||
|         :returns the number of updated documents (unless ``full_result`` is True) | ||||
|  | ||||
|         .. versionadded:: 0.2 | ||||
|         """ | ||||
|         if not update and not upsert: | ||||
| @@ -567,7 +568,7 @@ class BaseQuerySet(object): | ||||
|             document = self._document.objects.with_id(atomic_update.upserted_id) | ||||
|         return document | ||||
|  | ||||
|     def update_one(self, upsert=False, write_concern=None, **update): | ||||
|     def update_one(self, upsert=False, write_concern=None, full_result=False, **update): | ||||
|         """Perform an atomic update on the fields of the first document | ||||
|         matched by the query. | ||||
|  | ||||
| @@ -578,12 +579,19 @@ class BaseQuerySet(object): | ||||
|             ``save(..., write_concern={w: 2, fsync: True}, ...)`` will | ||||
|             wait until at least two servers have recorded the write and | ||||
|             will force an fsync on the primary server. | ||||
|         :param full_result: Return the associated ``pymongo.UpdateResult`` rather than just the number | ||||
|             updated items | ||||
|         :param update: Django-style update keyword arguments | ||||
|  | ||||
|             full_result | ||||
|         :returns the number of updated documents (unless ``full_result`` is True) | ||||
|         .. versionadded:: 0.2 | ||||
|         """ | ||||
|         return self.update( | ||||
|             upsert=upsert, multi=False, write_concern=write_concern, **update) | ||||
|             upsert=upsert, | ||||
|             multi=False, | ||||
|             write_concern=write_concern, | ||||
|             full_result=full_result, | ||||
|             **update) | ||||
|  | ||||
|     def modify(self, upsert=False, full_response=False, remove=False, new=False, **update): | ||||
|         """Update and return the updated document. | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import os | ||||
| import pickle | ||||
| import unittest | ||||
| import uuid | ||||
| import warnings | ||||
| import weakref | ||||
| from datetime import datetime | ||||
|  | ||||
| @@ -3086,6 +3087,24 @@ class InstanceTest(MongoDBTestCase): | ||||
|             "UNDEFINED", | ||||
|             system.nodes["node"].parameters["param"].macros["test"].value) | ||||
|  | ||||
|     def test_embedded_document_save_reload_warning(self): | ||||
|         """Relates to #1570""" | ||||
|         class Embedded(EmbeddedDocument): | ||||
|             pass | ||||
|  | ||||
|         class Doc(Document): | ||||
|             emb = EmbeddedDocumentField(Embedded) | ||||
|  | ||||
|         doc = Doc(emb=Embedded()).save() | ||||
|         doc.emb.save()  # Make sure its still working | ||||
|         with warnings.catch_warnings(): | ||||
|             warnings.simplefilter("error", DeprecationWarning) | ||||
|             with self.assertRaises(DeprecationWarning): | ||||
|                 doc.emb.save() | ||||
|  | ||||
|             with self.assertRaises(DeprecationWarning): | ||||
|                 doc.emb.reload() | ||||
|  | ||||
|     def test_embedded_document_equality(self): | ||||
|         class Test(Document): | ||||
|             field = StringField(required=True) | ||||
|   | ||||
| @@ -10,11 +10,6 @@ import sys | ||||
| from nose.plugins.skip import SkipTest | ||||
| import six | ||||
|  | ||||
| try: | ||||
|     import dateutil | ||||
| except ImportError: | ||||
|     dateutil = None | ||||
|  | ||||
| from decimal import Decimal | ||||
|  | ||||
| from bson import DBRef, ObjectId, SON | ||||
| @@ -30,55 +25,9 @@ from mongoengine.base import (BaseDict, BaseField, EmbeddedDocumentList, | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
| __all__ = ("FieldTest", "EmbeddedDocumentListFieldTestCase") | ||||
|  | ||||
|  | ||||
| class FieldTest(MongoDBTestCase): | ||||
|  | ||||
|     def test_datetime_from_empty_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast an empty string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateTimeField() | ||||
|  | ||||
|         md = MyDoc(dt='') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_date_from_empty_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast an empty string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateField() | ||||
|  | ||||
|         md = MyDoc(dt='') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_datetime_from_whitespace_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast a whitespace-only string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateTimeField() | ||||
|  | ||||
|         md = MyDoc(dt='   ') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_date_from_whitespace_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast a whitespace-only string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateField() | ||||
|  | ||||
|         md = MyDoc(dt='   ') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_default_values_nothing_set(self): | ||||
|         """Ensure that default field values are used when creating | ||||
|         a document. | ||||
| @@ -695,273 +644,6 @@ class FieldTest(MongoDBTestCase): | ||||
|             person.api_key = api_key | ||||
|             self.assertRaises(ValidationError, person.validate) | ||||
|  | ||||
|     def test_datetime_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to datetime | ||||
|         fields. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             time = DateTimeField() | ||||
|  | ||||
|         log = LogEntry() | ||||
|         log.time = datetime.datetime.now() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.date.today() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.datetime.now().isoformat(' ') | ||||
|         log.validate() | ||||
|  | ||||
|         if dateutil: | ||||
|             log.time = datetime.datetime.now().isoformat('T') | ||||
|             log.validate() | ||||
|  | ||||
|         log.time = -1 | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         log.time = 'ABC' | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|  | ||||
|     def test_date_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to datetime | ||||
|         fields. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             time = DateField() | ||||
|  | ||||
|         log = LogEntry() | ||||
|         log.time = datetime.datetime.now() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.date.today() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.datetime.now().isoformat(' ') | ||||
|         log.validate() | ||||
|  | ||||
|         if dateutil: | ||||
|             log.time = datetime.datetime.now().isoformat('T') | ||||
|             log.validate() | ||||
|  | ||||
|         log.time = -1 | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         log.time = 'ABC' | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|  | ||||
|     def test_datetime_tz_aware_mark_as_changed(self): | ||||
|         from mongoengine import connection | ||||
|  | ||||
|         # Reset the connections | ||||
|         connection._connection_settings = {} | ||||
|         connection._connections = {} | ||||
|         connection._dbs = {} | ||||
|  | ||||
|         connect(db='mongoenginetest', tz_aware=True) | ||||
|  | ||||
|         class LogEntry(Document): | ||||
|             time = DateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         LogEntry(time=datetime.datetime(2013, 1, 1, 0, 0, 0)).save() | ||||
|  | ||||
|         log = LogEntry.objects.first() | ||||
|         log.time = datetime.datetime(2013, 1, 1, 0, 0, 0) | ||||
|         self.assertEqual(['time'], log._changed_fields) | ||||
|  | ||||
|     def test_datetime(self): | ||||
|         """Tests showing pymongo datetime fields handling of microseconds. | ||||
|         Microseconds are rounded to the nearest millisecond and pre UTC | ||||
|         handling is wonky. | ||||
|  | ||||
|         See: http://api.mongodb.org/python/current/api/bson/son.html#dt | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = DateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Test can save dates | ||||
|         log = LogEntry() | ||||
|         log.date = datetime.date.today() | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date.date(), datetime.date.today()) | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond and | ||||
|         # dropped | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertNotEqual(log.date, d1) | ||||
|         self.assertEqual(log.date, d2) | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9000) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertNotEqual(log.date, d1) | ||||
|         self.assertEqual(log.date, d2) | ||||
|  | ||||
|         if not six.PY3: | ||||
|             # Pre UTC dates microseconds below 1000 are dropped | ||||
|             # This does not seem to be true in PY3 | ||||
|             d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999) | ||||
|             d2 = datetime.datetime(1969, 12, 31, 23, 59, 59) | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertNotEqual(log.date, d1) | ||||
|             self.assertEqual(log.date, d2) | ||||
|  | ||||
|     def test_date(self): | ||||
|         """Tests showing pymongo date fields | ||||
|  | ||||
|         See: http://api.mongodb.org/python/current/api/bson/son.html#dt | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = DateField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Test can save dates | ||||
|         log = LogEntry() | ||||
|         log.date = datetime.date.today() | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, datetime.date.today()) | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1.date()) | ||||
|         self.assertEqual(log.date, d2.date()) | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9000) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1.date()) | ||||
|         self.assertEqual(log.date, d2.date()) | ||||
|  | ||||
|         if not six.PY3: | ||||
|             # Pre UTC dates microseconds below 1000 are dropped | ||||
|             # This does not seem to be true in PY3 | ||||
|             d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999) | ||||
|             d2 = datetime.datetime(1969, 12, 31, 23, 59, 59) | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertEqual(log.date, d1.date()) | ||||
|             self.assertEqual(log.date, d2.date()) | ||||
|  | ||||
|     def test_datetime_usage(self): | ||||
|         """Tests for regular datetime fields""" | ||||
|         class LogEntry(Document): | ||||
|             date = DateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.validate() | ||||
|         log.save() | ||||
|  | ||||
|         for query in (d1, d1.isoformat(' ')): | ||||
|             log1 = LogEntry.objects.get(date=query) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         if dateutil: | ||||
|             log1 = LogEntry.objects.get(date=d1.isoformat('T')) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         # create additional 19 log entries for a total of 20 | ||||
|         for i in range(1971, 1990): | ||||
|             d = datetime.datetime(i, 1, 1, 0, 0, 1) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 20) | ||||
|  | ||||
|         # Test ordering | ||||
|         logs = LogEntry.objects.order_by("date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date <= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         logs = LogEntry.objects.order_by("-date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date >= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|         logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=datetime.datetime(1980, 1, 1), | ||||
|             date__gte=datetime.datetime(1975, 1, 1), | ||||
|         ) | ||||
|         self.assertEqual(logs.count(), 5) | ||||
|  | ||||
|     def test_date_usage(self): | ||||
|         """Tests for regular datetime fields""" | ||||
|         class LogEntry(Document): | ||||
|             date = DateField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.validate() | ||||
|         log.save() | ||||
|  | ||||
|         for query in (d1, d1.isoformat(' ')): | ||||
|             log1 = LogEntry.objects.get(date=query) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         if dateutil: | ||||
|             log1 = LogEntry.objects.get(date=d1.isoformat('T')) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         # create additional 19 log entries for a total of 20 | ||||
|         for i in range(1971, 1990): | ||||
|             d = datetime.datetime(i, 1, 1, 0, 0, 1) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 20) | ||||
|  | ||||
|         # Test ordering | ||||
|         logs = LogEntry.objects.order_by("date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date <= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         logs = LogEntry.objects.order_by("-date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date >= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|     def test_list_validation(self): | ||||
|         """Ensure that a list field only accepts lists with valid elements.""" | ||||
|         AccessLevelChoices = ( | ||||
| @@ -5328,180 +5010,5 @@ class GenericLazyReferenceFieldTest(MongoDBTestCase): | ||||
|         check_fields_type(occ) | ||||
|  | ||||
|  | ||||
| class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|     def test_complexdatetime_storage(self): | ||||
|         """Tests for complex datetime fields - which can handle | ||||
|         microseconds without rounding. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = ComplexDateTimeField() | ||||
|             date_with_dots = ComplexDateTimeField(separator='.') | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond and | ||||
|         # dropped - with default datetimefields | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond - with | ||||
|         # default datetimefields | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|  | ||||
|         # Pre UTC dates microseconds below 1000 are dropped - with default | ||||
|         # datetimefields | ||||
|         d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|  | ||||
|         # Pre UTC microseconds above 1000 is wonky - with default datetimefields | ||||
|         # log.date has an invalid microsecond value so I can't construct | ||||
|         # a date to compare. | ||||
|         for i in range(1001, 3113, 33): | ||||
|             d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, i) | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertEqual(log.date, d1) | ||||
|             log1 = LogEntry.objects.get(date=d1) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         # Test string padding | ||||
|         microsecond = map(int, [math.pow(10, x) for x in range(6)]) | ||||
|         mm = dd = hh = ii = ss = [1, 10] | ||||
|  | ||||
|         for values in itertools.product([2014], mm, dd, hh, ii, ss, microsecond): | ||||
|             stored = LogEntry(date=datetime.datetime(*values)).to_mongo()['date'] | ||||
|             self.assertTrue(re.match('^\d{4},\d{2},\d{2},\d{2},\d{2},\d{2},\d{6}$', stored) is not None) | ||||
|  | ||||
|         # Test separator | ||||
|         stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()['date_with_dots'] | ||||
|         self.assertTrue(re.match('^\d{4}.\d{2}.\d{2}.\d{2}.\d{2}.\d{2}.\d{6}$', stored) is not None) | ||||
|  | ||||
|     def test_complexdatetime_usage(self): | ||||
|         """Tests for complex datetime fields - which can handle | ||||
|         microseconds without rounding. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = ComplexDateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         d1 = datetime.datetime(1950, 1, 1, 0, 0, 1, 999) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|  | ||||
|         log1 = LogEntry.objects.get(date=d1) | ||||
|         self.assertEqual(log, log1) | ||||
|  | ||||
|         # create extra 59 log entries for a total of 60 | ||||
|         for i in range(1951, 2010): | ||||
|             d = datetime.datetime(i, 1, 1, 0, 0, 1, 999) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 60) | ||||
|  | ||||
|         # Test ordering | ||||
|         logs = LogEntry.objects.order_by("date") | ||||
|         i = 0 | ||||
|         while i < 59: | ||||
|             self.assertTrue(logs[i].date <= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         logs = LogEntry.objects.order_by("-date") | ||||
|         i = 0 | ||||
|         while i < 59: | ||||
|             self.assertTrue(logs[i].date >= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 30) | ||||
|  | ||||
|         logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 30) | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=datetime.datetime(2011, 1, 1), | ||||
|             date__gte=datetime.datetime(2000, 1, 1), | ||||
|         ) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Test microsecond-level ordering/filtering | ||||
|         for microsecond in (99, 999, 9999, 10000): | ||||
|             LogEntry( | ||||
|                 date=datetime.datetime(2015, 1, 1, 0, 0, 0, microsecond) | ||||
|             ).save() | ||||
|  | ||||
|         logs = list(LogEntry.objects.order_by('date')) | ||||
|         for next_idx, log in enumerate(logs[:-1], start=1): | ||||
|             next_log = logs[next_idx] | ||||
|             self.assertTrue(log.date < next_log.date) | ||||
|  | ||||
|         logs = list(LogEntry.objects.order_by('-date')) | ||||
|         for next_idx, log in enumerate(logs[:-1], start=1): | ||||
|             next_log = logs[next_idx] | ||||
|             self.assertTrue(log.date > next_log.date) | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=datetime.datetime(2015, 1, 1, 0, 0, 0, 10000)) | ||||
|         self.assertEqual(logs.count(), 4) | ||||
|  | ||||
|     def test_no_default_value(self): | ||||
|         class Log(Document): | ||||
|             timestamp = ComplexDateTimeField() | ||||
|  | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertIsNone(log.timestamp) | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertIsNone(fetched_log.timestamp) | ||||
|  | ||||
|     def test_default_static_value(self): | ||||
|         NOW = datetime.datetime.utcnow() | ||||
|         class Log(Document): | ||||
|             timestamp = ComplexDateTimeField(default=NOW) | ||||
|  | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertEqual(log.timestamp, NOW) | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertEqual(fetched_log.timestamp, NOW) | ||||
|  | ||||
|     def test_default_callable(self): | ||||
|         NOW = datetime.datetime.utcnow() | ||||
|  | ||||
|         class Log(Document): | ||||
|             timestamp = ComplexDateTimeField(default=datetime.datetime.utcnow) | ||||
|  | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertGreaterEqual(log.timestamp, NOW) | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertGreaterEqual(fetched_log.timestamp, NOW) | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|   | ||||
							
								
								
									
										189
									
								
								tests/fields/test_complex_datetime_field.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								tests/fields/test_complex_datetime_field.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime | ||||
| import math | ||||
| import itertools | ||||
| import re | ||||
|  | ||||
| try: | ||||
|     from bson.int64 import Int64 | ||||
| except ImportError: | ||||
|     Int64 = long | ||||
|  | ||||
| from mongoengine import * | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|     def test_complexdatetime_storage(self): | ||||
|         """Tests for complex datetime fields - which can handle | ||||
|         microseconds without rounding. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = ComplexDateTimeField() | ||||
|             date_with_dots = ComplexDateTimeField(separator='.') | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond and | ||||
|         # dropped - with default datetimefields | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond - with | ||||
|         # default datetimefields | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|  | ||||
|         # Pre UTC dates microseconds below 1000 are dropped - with default | ||||
|         # datetimefields | ||||
|         d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|  | ||||
|         # Pre UTC microseconds above 1000 is wonky - with default datetimefields | ||||
|         # log.date has an invalid microsecond value so I can't construct | ||||
|         # a date to compare. | ||||
|         for i in range(1001, 3113, 33): | ||||
|             d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, i) | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertEqual(log.date, d1) | ||||
|             log1 = LogEntry.objects.get(date=d1) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         # Test string padding | ||||
|         microsecond = map(int, [math.pow(10, x) for x in range(6)]) | ||||
|         mm = dd = hh = ii = ss = [1, 10] | ||||
|  | ||||
|         for values in itertools.product([2014], mm, dd, hh, ii, ss, microsecond): | ||||
|             stored = LogEntry(date=datetime.datetime(*values)).to_mongo()['date'] | ||||
|             self.assertTrue(re.match('^\d{4},\d{2},\d{2},\d{2},\d{2},\d{2},\d{6}$', stored) is not None) | ||||
|  | ||||
|         # Test separator | ||||
|         stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()['date_with_dots'] | ||||
|         self.assertTrue(re.match('^\d{4}.\d{2}.\d{2}.\d{2}.\d{2}.\d{2}.\d{6}$', stored) is not None) | ||||
|  | ||||
|     def test_complexdatetime_usage(self): | ||||
|         """Tests for complex datetime fields - which can handle | ||||
|         microseconds without rounding. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = ComplexDateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         d1 = datetime.datetime(1950, 1, 1, 0, 0, 1, 999) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|  | ||||
|         log1 = LogEntry.objects.get(date=d1) | ||||
|         self.assertEqual(log, log1) | ||||
|  | ||||
|         # create extra 59 log entries for a total of 60 | ||||
|         for i in range(1951, 2010): | ||||
|             d = datetime.datetime(i, 1, 1, 0, 0, 1, 999) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 60) | ||||
|  | ||||
|         # Test ordering | ||||
|         logs = LogEntry.objects.order_by("date") | ||||
|         i = 0 | ||||
|         while i < 59: | ||||
|             self.assertTrue(logs[i].date <= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         logs = LogEntry.objects.order_by("-date") | ||||
|         i = 0 | ||||
|         while i < 59: | ||||
|             self.assertTrue(logs[i].date >= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 30) | ||||
|  | ||||
|         logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 30) | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=datetime.datetime(2011, 1, 1), | ||||
|             date__gte=datetime.datetime(2000, 1, 1), | ||||
|         ) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Test microsecond-level ordering/filtering | ||||
|         for microsecond in (99, 999, 9999, 10000): | ||||
|             LogEntry( | ||||
|                 date=datetime.datetime(2015, 1, 1, 0, 0, 0, microsecond) | ||||
|             ).save() | ||||
|  | ||||
|         logs = list(LogEntry.objects.order_by('date')) | ||||
|         for next_idx, log in enumerate(logs[:-1], start=1): | ||||
|             next_log = logs[next_idx] | ||||
|             self.assertTrue(log.date < next_log.date) | ||||
|  | ||||
|         logs = list(LogEntry.objects.order_by('-date')) | ||||
|         for next_idx, log in enumerate(logs[:-1], start=1): | ||||
|             next_log = logs[next_idx] | ||||
|             self.assertTrue(log.date > next_log.date) | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=datetime.datetime(2015, 1, 1, 0, 0, 0, 10000)) | ||||
|         self.assertEqual(logs.count(), 4) | ||||
|  | ||||
|     def test_no_default_value(self): | ||||
|         class Log(Document): | ||||
|             timestamp = ComplexDateTimeField() | ||||
|  | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertIsNone(log.timestamp) | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertIsNone(fetched_log.timestamp) | ||||
|  | ||||
|     def test_default_static_value(self): | ||||
|         NOW = datetime.datetime.utcnow() | ||||
|         class Log(Document): | ||||
|             timestamp = ComplexDateTimeField(default=NOW) | ||||
|  | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertEqual(log.timestamp, NOW) | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertEqual(fetched_log.timestamp, NOW) | ||||
|  | ||||
|     def test_default_callable(self): | ||||
|         NOW = datetime.datetime.utcnow() | ||||
|  | ||||
|         class Log(Document): | ||||
|             timestamp = ComplexDateTimeField(default=datetime.datetime.utcnow) | ||||
|  | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertGreaterEqual(log.timestamp, NOW) | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertGreaterEqual(fetched_log.timestamp, NOW) | ||||
							
								
								
									
										184
									
								
								tests/fields/test_date_field.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								tests/fields/test_date_field.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime | ||||
| import unittest | ||||
| import uuid | ||||
| import math | ||||
| import itertools | ||||
| import re | ||||
| import sys | ||||
|  | ||||
| from nose.plugins.skip import SkipTest | ||||
| import six | ||||
|  | ||||
| try: | ||||
|     import dateutil | ||||
| except ImportError: | ||||
|     dateutil = None | ||||
|  | ||||
| from decimal import Decimal | ||||
|  | ||||
| from bson import Binary, DBRef, ObjectId, SON | ||||
| try: | ||||
|     from bson.int64 import Int64 | ||||
| except ImportError: | ||||
|     Int64 = long | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.connection import get_db | ||||
| from mongoengine.base import (BaseDict, BaseField, EmbeddedDocumentList, | ||||
|                               _document_registry, LazyReference) | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| class TestDateField(MongoDBTestCase): | ||||
|     def test_date_from_empty_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast an empty string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateField() | ||||
|  | ||||
|         md = MyDoc(dt='') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_date_from_whitespace_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast a whitespace-only string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateField() | ||||
|  | ||||
|         md = MyDoc(dt='   ') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_default_values_today(self): | ||||
|         """Ensure that default field values are used when creating | ||||
|         a document. | ||||
|         """ | ||||
|         class Person(Document): | ||||
|             day = DateField(default=datetime.date.today) | ||||
|  | ||||
|         person = Person() | ||||
|         person.validate() | ||||
|         self.assertEqual(person.day, person.day) | ||||
|         self.assertEqual(person.day, datetime.date.today()) | ||||
|         self.assertEqual(person._data['day'], person.day) | ||||
|  | ||||
|     def test_date(self): | ||||
|         """Tests showing pymongo date fields | ||||
|  | ||||
|         See: http://api.mongodb.org/python/current/api/bson/son.html#dt | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = DateField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Test can save dates | ||||
|         log = LogEntry() | ||||
|         log.date = datetime.date.today() | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, datetime.date.today()) | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1.date()) | ||||
|         self.assertEqual(log.date, d2.date()) | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9000) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1.date()) | ||||
|         self.assertEqual(log.date, d2.date()) | ||||
|  | ||||
|         if not six.PY3: | ||||
|             # Pre UTC dates microseconds below 1000 are dropped | ||||
|             # This does not seem to be true in PY3 | ||||
|             d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999) | ||||
|             d2 = datetime.datetime(1969, 12, 31, 23, 59, 59) | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertEqual(log.date, d1.date()) | ||||
|             self.assertEqual(log.date, d2.date()) | ||||
|  | ||||
|     def test_regular_usage(self): | ||||
|         """Tests for regular datetime fields""" | ||||
|         class LogEntry(Document): | ||||
|             date = DateField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.validate() | ||||
|         log.save() | ||||
|  | ||||
|         for query in (d1, d1.isoformat(' ')): | ||||
|             log1 = LogEntry.objects.get(date=query) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         if dateutil: | ||||
|             log1 = LogEntry.objects.get(date=d1.isoformat('T')) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         # create additional 19 log entries for a total of 20 | ||||
|         for i in range(1971, 1990): | ||||
|             d = datetime.datetime(i, 1, 1, 0, 0, 1) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 20) | ||||
|  | ||||
|         # Test ordering | ||||
|         logs = LogEntry.objects.order_by("date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date <= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         logs = LogEntry.objects.order_by("-date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date >= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|     def test_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to datetime | ||||
|         fields. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             time = DateField() | ||||
|  | ||||
|         log = LogEntry() | ||||
|         log.time = datetime.datetime.now() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.date.today() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.datetime.now().isoformat(' ') | ||||
|         log.validate() | ||||
|  | ||||
|         if dateutil: | ||||
|             log.time = datetime.datetime.now().isoformat('T') | ||||
|             log.validate() | ||||
|  | ||||
|         log.time = -1 | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         log.time = 'ABC' | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
							
								
								
									
										208
									
								
								tests/fields/test_datetime_field.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								tests/fields/test_datetime_field.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime | ||||
| import six | ||||
|  | ||||
| try: | ||||
|     import dateutil | ||||
| except ImportError: | ||||
|     dateutil = None | ||||
|  | ||||
| try: | ||||
|     from bson.int64 import Int64 | ||||
| except ImportError: | ||||
|     Int64 = long | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine import connection | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| class TestDateTimeField(MongoDBTestCase): | ||||
|     def test_datetime_from_empty_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast an empty string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateTimeField() | ||||
|  | ||||
|         md = MyDoc(dt='') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_datetime_from_whitespace_string(self): | ||||
|         """ | ||||
|         Ensure an exception is raised when trying to | ||||
|         cast a whitespace-only string to datetime. | ||||
|         """ | ||||
|         class MyDoc(Document): | ||||
|             dt = DateTimeField() | ||||
|  | ||||
|         md = MyDoc(dt='   ') | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|  | ||||
|     def test_default_value_utcnow(self): | ||||
|         """Ensure that default field values are used when creating | ||||
|         a document. | ||||
|         """ | ||||
|         class Person(Document): | ||||
|             created = DateTimeField(default=datetime.datetime.utcnow) | ||||
|  | ||||
|         utcnow = datetime.datetime.utcnow() | ||||
|         person = Person() | ||||
|         person.validate() | ||||
|         person_created_t0 = person.created | ||||
|         self.assertLess(person.created - utcnow, datetime.timedelta(seconds=1)) | ||||
|         self.assertEqual(person_created_t0, person.created)  # make sure it does not change | ||||
|         self.assertEqual(person._data['created'], person.created) | ||||
|  | ||||
|     def test_handling_microseconds(self): | ||||
|         """Tests showing pymongo datetime fields handling of microseconds. | ||||
|         Microseconds are rounded to the nearest millisecond and pre UTC | ||||
|         handling is wonky. | ||||
|  | ||||
|         See: http://api.mongodb.org/python/current/api/bson/son.html#dt | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             date = DateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         # Test can save dates | ||||
|         log = LogEntry() | ||||
|         log.date = datetime.date.today() | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date.date(), datetime.date.today()) | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond and | ||||
|         # dropped | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertNotEqual(log.date, d1) | ||||
|         self.assertEqual(log.date, d2) | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9000) | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertNotEqual(log.date, d1) | ||||
|         self.assertEqual(log.date, d2) | ||||
|  | ||||
|         if not six.PY3: | ||||
|             # Pre UTC dates microseconds below 1000 are dropped | ||||
|             # This does not seem to be true in PY3 | ||||
|             d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999) | ||||
|             d2 = datetime.datetime(1969, 12, 31, 23, 59, 59) | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertNotEqual(log.date, d1) | ||||
|             self.assertEqual(log.date, d2) | ||||
|  | ||||
|     def test_regular_usage(self): | ||||
|         """Tests for regular datetime fields""" | ||||
|         class LogEntry(Document): | ||||
|             date = DateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
|         log = LogEntry() | ||||
|         log.date = d1 | ||||
|         log.validate() | ||||
|         log.save() | ||||
|  | ||||
|         for query in (d1, d1.isoformat(' ')): | ||||
|             log1 = LogEntry.objects.get(date=query) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         if dateutil: | ||||
|             log1 = LogEntry.objects.get(date=d1.isoformat('T')) | ||||
|             self.assertEqual(log, log1) | ||||
|  | ||||
|         # create additional 19 log entries for a total of 20 | ||||
|         for i in range(1971, 1990): | ||||
|             d = datetime.datetime(i, 1, 1, 0, 0, 1) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 20) | ||||
|  | ||||
|         # Test ordering | ||||
|         logs = LogEntry.objects.order_by("date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date <= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         logs = LogEntry.objects.order_by("-date") | ||||
|         i = 0 | ||||
|         while i < 19: | ||||
|             self.assertTrue(logs[i].date >= logs[i + 1].date) | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|         logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=datetime.datetime(1980, 1, 1), | ||||
|             date__gte=datetime.datetime(1975, 1, 1), | ||||
|         ) | ||||
|         self.assertEqual(logs.count(), 5) | ||||
|  | ||||
|     def test_datetime_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to datetime | ||||
|         fields. | ||||
|         """ | ||||
|         class LogEntry(Document): | ||||
|             time = DateTimeField() | ||||
|  | ||||
|         log = LogEntry() | ||||
|         log.time = datetime.datetime.now() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.date.today() | ||||
|         log.validate() | ||||
|  | ||||
|         log.time = datetime.datetime.now().isoformat(' ') | ||||
|         log.validate() | ||||
|  | ||||
|         if dateutil: | ||||
|             log.time = datetime.datetime.now().isoformat('T') | ||||
|             log.validate() | ||||
|  | ||||
|         log.time = -1 | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         log.time = 'ABC' | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|  | ||||
|  | ||||
| class TestDateTimeTzAware(MongoDBTestCase): | ||||
|     def test_datetime_tz_aware_mark_as_changed(self): | ||||
|         # Reset the connections | ||||
|         connection._connection_settings = {} | ||||
|         connection._connections = {} | ||||
|         connection._dbs = {} | ||||
|  | ||||
|         connect(db='mongoenginetest', tz_aware=True) | ||||
|  | ||||
|         class LogEntry(Document): | ||||
|             time = DateTimeField() | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
|         LogEntry(time=datetime.datetime(2013, 1, 1, 0, 0, 0)).save() | ||||
|  | ||||
|         log = LogEntry.objects.first() | ||||
|         log.time = datetime.datetime(2013, 1, 1, 0, 0, 0) | ||||
|         self.assertEqual(['time'], log._changed_fields) | ||||
| @@ -2234,6 +2234,19 @@ class QuerySetTest(unittest.TestCase): | ||||
|         bar.reload() | ||||
|         self.assertEqual(len(bar.foos), 0) | ||||
|  | ||||
|     def test_update_one_check_return_with_full_result(self): | ||||
|         class BlogTag(Document): | ||||
|             name = StringField(required=True) | ||||
|  | ||||
|         BlogTag.drop_collection() | ||||
|  | ||||
|         BlogTag(name='garbage').save() | ||||
|         default_update = BlogTag.objects.update_one(name='new') | ||||
|         self.assertEqual(default_update, 1) | ||||
|  | ||||
|         full_result_update = BlogTag.objects.update_one(name='new', full_result=True) | ||||
|         self.assertIsInstance(full_result_update, UpdateResult) | ||||
|  | ||||
|     def test_update_one_pop_generic_reference(self): | ||||
|  | ||||
|         class BlogTag(Document): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user