Merge branch 'master' of github.com:MongoEngine/mongoengine into mongodb_40
This commit is contained in:
		
							
								
								
									
										22
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ | ||||
| # with a very large number of jobs, hence we only test a subset of all the | ||||
| # combinations: | ||||
| # * MongoDB v3.4 & the latest PyMongo v3.x is currently the "main" setup, | ||||
| #   tested against Python v2.7, v3.5, v3.6, v3.7, PyPy and PyPy3. | ||||
| #   tested against Python v2.7, v3.5, v3.6, v3.7, v3.8, PyPy and PyPy3. | ||||
| # * Besides that, we test the lowest actively supported Python/MongoDB/PyMongo | ||||
| #   combination: MongoDB v3.4, PyMongo v3.4, Python v2.7. | ||||
| # * MongoDB v3.6 is tested against Python v3.6, and PyMongo v3.6, v3.7, v3.8. | ||||
| @@ -23,6 +23,7 @@ python: | ||||
| - 3.5 | ||||
| - 3.6 | ||||
| - 3.7 | ||||
| - 3.8 | ||||
| - pypy | ||||
| - pypy3 | ||||
|  | ||||
| @@ -33,11 +34,12 @@ env: | ||||
|     - MONGODB_4_0=4.0.12 | ||||
|     - MONGODB_3_4=3.4.17 | ||||
|     - MONGODB_3_6=3.6.12 | ||||
|     - PYMONGO_3_10=3.10 | ||||
|     - PYMONGO_3_9=3.9 | ||||
|     - PYMONGO_3_6=3.6 | ||||
|     - PYMONGO_3_4=3.4 | ||||
|   matrix: | ||||
|     - MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_9} | ||||
|     - MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_10} | ||||
|  | ||||
| matrix: | ||||
|   # Finish the build as soon as one job fails | ||||
| @@ -49,7 +51,11 @@ matrix: | ||||
|   - python: 3.7 | ||||
|     env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_6} | ||||
|   - python: 3.7 | ||||
|     env: MONGODB=${MONGODB_4_0} PYMONGO=${PYMONGO_3_9} | ||||
|     env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_9} | ||||
|   - python: 3.7 | ||||
|     env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_10} | ||||
|   - python: 3.8 | ||||
|     env: MONGODB=${MONGODB_4_0} PYMONGO=${PYMONGO_3_10} | ||||
|  | ||||
| install: | ||||
|   # Install Mongo | ||||
| @@ -62,8 +68,8 @@ install: | ||||
|   - pip install flake8 flake8-import-order | ||||
|   - pip install tox         # tox 3.11.0 has requirement virtualenv>=14.0.0 | ||||
|   - pip install virtualenv  # virtualenv>=14.0.0 has dropped Python 3.2 support (and pypy3 is based on py32) | ||||
|   # Install the tox venv. | ||||
|   - tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -e test | ||||
|   # tox dryrun to setup the tox venv (we run a mock test). | ||||
|   - tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "-k=test_ci_placeholder" | ||||
|   # Install black for Python v3.7 only. | ||||
|   - if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then pip install black; fi | ||||
|  | ||||
| @@ -75,13 +81,13 @@ before_script: | ||||
|   - mongo --eval 'db.version();'    # Make sure mongo is awake | ||||
|  | ||||
| script: | ||||
|   - tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- --with-coverage | ||||
|   - tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "--cov=mongoengine" | ||||
|  | ||||
| # For now only submit coveralls for Python v2.7. Python v3.x currently shows | ||||
| # 0% coverage. That's caused by 'use_2to3', which builds the py3-compatible | ||||
| # code in a separate dir and runs tests on that. | ||||
| after_success: | ||||
| - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then coveralls --verbose; fi | ||||
| - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then coveralls --verbose; else echo "coveralls only sent for py27"; fi | ||||
|  | ||||
| notifications: | ||||
|   irc: irc.freenode.org#mongoengine | ||||
| @@ -109,5 +115,5 @@ deploy: | ||||
|   on: | ||||
|     tags: true | ||||
|     repo: MongoEngine/mongoengine | ||||
|     condition: ($PYMONGO = ${PYMONGO_3_6}) && ($MONGODB = ${MONGODB_3_4}) | ||||
|     condition: ($PYMONGO = ${PYMONGO_3_10}) && ($MONGODB = ${MONGODB_3_4}) | ||||
|     python: 2.7 | ||||
|   | ||||
							
								
								
									
										3
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -252,3 +252,6 @@ that much better: | ||||
|  * Paulo Amaral (https://github.com/pauloAmaral) | ||||
|  * Gaurav Dadhania (https://github.com/GVRV) | ||||
|  * Yurii Andrieiev (https://github.com/yandrieiev) | ||||
|  * Filip Kucharczyk (https://github.com/Pacu2) | ||||
|  * Eric Timmons (https://github.com/daewok) | ||||
|  * Matthew Simpson (https://github.com/mcsimps2) | ||||
|   | ||||
| @@ -54,7 +54,7 @@ General Guidelines | ||||
|   should adapt to the breaking change in docs/upgrade.rst. | ||||
| - Write inline documentation for new classes and methods. | ||||
| - Write tests and make sure they pass (make sure you have a mongod | ||||
|   running on the default port, then execute ``python setup.py nosetests`` | ||||
|   running on the default port, then execute ``python setup.py test`` | ||||
|   from the cmd line to run the test suite). | ||||
| - Ensure tests pass on all supported Python, PyMongo, and MongoDB versions. | ||||
|   You can test various Python and PyMongo versions locally by executing | ||||
|   | ||||
							
								
								
									
										18
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.rst
									
									
									
									
									
								
							| @@ -91,12 +91,11 @@ Some simple examples of what MongoEngine code looks like: | ||||
|  | ||||
|     # Iterate over all posts using the BlogPost superclass | ||||
|     >>> for post in BlogPost.objects: | ||||
|     ...     print '===', post.title, '===' | ||||
|     ...     print('===', post.title, '===') | ||||
|     ...     if isinstance(post, TextPost): | ||||
|     ...         print post.content | ||||
|     ...         print(post.content) | ||||
|     ...     elif isinstance(post, LinkPost): | ||||
|     ...         print 'Link:', post.url | ||||
|     ...     print | ||||
|     ...         print('Link:', post.url) | ||||
|     ... | ||||
|  | ||||
|     # Count all blog posts and its subtypes | ||||
| @@ -116,7 +115,8 @@ Some simple examples of what MongoEngine code looks like: | ||||
| Tests | ||||
| ===== | ||||
| To run the test suite, ensure you are running a local instance of MongoDB on | ||||
| the standard port and have ``nose`` installed. Then, run ``python setup.py nosetests``. | ||||
| the standard port and have ``pytest`` installed. Then, run ``python setup.py test`` | ||||
| or simply ``pytest``. | ||||
|  | ||||
| To run the test suite on every supported Python and PyMongo version, you can | ||||
| use ``tox``. You'll need to make sure you have each supported Python version | ||||
| @@ -129,16 +129,14 @@ installed in your environment and then: | ||||
|     # Run the test suites | ||||
|     $ tox | ||||
|  | ||||
| If you wish to run a subset of tests, use the nosetests convention: | ||||
| If you wish to run a subset of tests, use the pytest convention: | ||||
|  | ||||
| .. code-block:: shell | ||||
|  | ||||
|     # Run all the tests in a particular test file | ||||
|     $ python setup.py nosetests --tests tests/fields/fields.py | ||||
|     $ pytest tests/fields/test_fields.py | ||||
|     # Run only particular test class in that file | ||||
|     $ python setup.py nosetests --tests tests/fields/fields.py:FieldTest | ||||
|     # Use the -s option if you want to print some debug statements or use pdb | ||||
|     $ python setup.py nosetests --tests tests/fields/fields.py:FieldTest -s | ||||
|     $ pytest tests/fields/test_fields.py::TestField | ||||
|  | ||||
| Community | ||||
| ========= | ||||
|   | ||||
| @@ -6,6 +6,15 @@ Changelog | ||||
| Development | ||||
| =========== | ||||
| - (Fill this out as you fix issues and develop your features). | ||||
|  | ||||
| Changes in 0.19.1 | ||||
| ================= | ||||
| - Requires Pillow < 7.0.0 as it dropped Python2 support | ||||
| - DEPRECATION: The interface of ``QuerySet.aggregate`` method was changed, it no longer takes an unpacked list of | ||||
|     pipeline steps (*pipeline) but simply takes the pipeline list just like ``pymongo.Collection.aggregate`` does. #2079 | ||||
|  | ||||
| Changes in 0.19.0 | ||||
| ================= | ||||
| - BREAKING CHANGE: ``class_check`` and ``read_preference`` keyword arguments are no longer available when filtering a ``QuerySet``. #2112 | ||||
|     - Instead of ``Doc.objects(foo=bar, read_preference=...)`` use ``Doc.objects(foo=bar).read_preference(...)``. | ||||
|     - Instead of ``Doc.objects(foo=bar, class_check=False)`` use ``Doc.objects(foo=bar).clear_cls_query(...)``. | ||||
| @@ -15,10 +24,23 @@ Development | ||||
|     - If you catch/use ``MongoEngineConnectionError`` in your code, you'll have to rename it. | ||||
| - BREAKING CHANGE: Positional arguments when instantiating a document are no longer supported. #2103 | ||||
|     - From now on keyword arguments (e.g. ``Doc(field_name=value)``) are required. | ||||
| - BREAKING CHANGE: A ``LazyReferenceField`` is now stored in the ``_data`` field of its parent as a ``DBRef``, ``Document``, or ``EmbeddedDocument`` (``ObjectId`` is no longer allowed). #2182 | ||||
| - DEPRECATION: ``Q.empty`` & ``QNode.empty`` are marked as deprecated and will be removed in a next version of MongoEngine. #2210 | ||||
|     - Added ability to check if Q or QNode are empty by parsing them to bool. | ||||
|     - Instead of ``Q(name="John").empty`` use ``not Q(name="John")``. | ||||
| - Fix updating/modifying/deleting/reloading a document that's sharded by a field with ``db_field`` specified. #2125 | ||||
| - Only set no_cursor_timeout when requested (fixes an incompatibility with MongoDB 4.2) #2148 | ||||
| - ``ListField`` now accepts an optional ``max_length`` parameter. #2110 | ||||
| - Improve error message related to InvalidDocumentError #2180 | ||||
| - Added BulkWriteError to replace NotUniqueError which was misleading in bulk write insert #2152 | ||||
| - Added ability to compare Q and Q operations #2204 | ||||
| - Added ability to use a db alias on query_counter #2194 | ||||
| - Added ability to specify collations for querysets with ``Doc.objects.collation`` #2024 | ||||
| - Fix updates of a list field by negative index #2094 | ||||
| - Switch from nosetest to pytest as test runner #2114 | ||||
| - The codebase is now formatted using ``black``. #2109 | ||||
| - In bulk write insert, the detailed error message would raise in exception. | ||||
| - Documentation improvements: | ||||
|     - Documented how `pymongo.monitoring` can be used to log all queries issued by MongoEngine to the driver. | ||||
|  | ||||
| Changes in 0.18.2 | ||||
| ================= | ||||
|   | ||||
| @@ -11,7 +11,8 @@ | ||||
| # All configuration values have a default; values that are commented out | ||||
| # serve to show the default. | ||||
|  | ||||
| import sys, os | ||||
| import os | ||||
| import sys | ||||
|  | ||||
| import sphinx_rtd_theme | ||||
|  | ||||
|   | ||||
							
								
								
									
										13
									
								
								docs/faq.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								docs/faq.rst
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| ========================== | ||||
| Frequently Asked Questions | ||||
| ========================== | ||||
|  | ||||
| Does MongoEngine support asynchronous drivers (Motor, TxMongo)? | ||||
| --------------------------------------------------------------- | ||||
|  | ||||
| No, MongoEngine is exclusively based on PyMongo and isn't designed to support other driver. | ||||
| If this is a requirement for your project, check the alternative:  `uMongo`_ and `MotorEngine`_. | ||||
|  | ||||
| .. _uMongo: https://umongo.readthedocs.io/ | ||||
| .. _MotorEngine: https://motorengine.readthedocs.io/ | ||||
|  | ||||
| @@ -352,7 +352,7 @@ Its value can take any of the following constants: | ||||
|   Deletion is denied if there still exist references to the object being | ||||
|   deleted. | ||||
| :const:`mongoengine.NULLIFY` | ||||
|   Any object's fields still referring to the object being deleted are removed | ||||
|   Any object's fields still referring to the object being deleted are set to None | ||||
|   (using MongoDB's "unset" operation), effectively nullifying the relationship. | ||||
| :const:`mongoengine.CASCADE` | ||||
|   Any object containing fields that are referring to the object being deleted | ||||
| @@ -744,7 +744,7 @@ Document inheritance | ||||
|  | ||||
| To create a specialised type of a :class:`~mongoengine.Document` you have | ||||
| defined, you may subclass it and add any extra fields or methods you may need. | ||||
| As this is new class is not a direct subclass of | ||||
| As this new class is not a direct subclass of | ||||
| :class:`~mongoengine.Document`, it will not be stored in its own collection; it | ||||
| will use the same collection as its superclass uses. This allows for more | ||||
| convenient and efficient retrieval of related documents -- all you need do is | ||||
| @@ -767,6 +767,27 @@ document.:: | ||||
|           Setting :attr:`allow_inheritance` to True should also be used in | ||||
|           :class:`~mongoengine.EmbeddedDocument` class in case you need to subclass it | ||||
|  | ||||
| When it comes to querying using :attr:`.objects()`, querying `Page.objects()` will query | ||||
| both `Page` and `DatedPage` whereas querying `DatedPage` will only query the `DatedPage` documents. | ||||
| Behind the scenes, MongoEngine deals with inheritance by adding a :attr:`_cls` attribute that contains | ||||
| the class name in every documents. When a document is loaded, MongoEngine checks | ||||
| it's :attr:`_cls` attribute and use that class to construct the instance.:: | ||||
|  | ||||
|     Page(title='a funky title').save() | ||||
|     DatedPage(title='another title', date=datetime.utcnow()).save() | ||||
|  | ||||
|     print(Page.objects().count())         # 2 | ||||
|     print(DatedPage.objects().count())    # 1 | ||||
|  | ||||
|     # print documents in their native form | ||||
|     # we remove 'id' to avoid polluting the output with unnecessary detail | ||||
|     qs = Page.objects.exclude('id').as_pymongo() | ||||
|     print(list(qs)) | ||||
|     # [ | ||||
|     #   {'_cls': u 'Page', 'title': 'a funky title'}, | ||||
|     #   {'_cls': u 'Page.DatedPage', 'title': u 'another title', 'date': datetime.datetime(2019, 12, 13, 20, 16, 59, 993000)} | ||||
|     # ] | ||||
|  | ||||
| Working with existing data | ||||
| -------------------------- | ||||
| As MongoEngine no longer defaults to needing :attr:`_cls`, you can quickly and | ||||
|   | ||||
| @@ -10,8 +10,9 @@ Writing | ||||
| GridFS support comes in the form of the :class:`~mongoengine.fields.FileField` field | ||||
| object. This field acts as a file-like object and provides a couple of | ||||
| different ways of inserting and retrieving data. Arbitrary metadata such as | ||||
| content type can also be stored alongside the files. In the following example, | ||||
| a document is created to store details about animals, including a photo:: | ||||
| content type can also be stored alongside the files. The object returned when accessing a | ||||
| FileField is a proxy to `Pymongo's GridFS <https://api.mongodb.com/python/current/examples/gridfs.html#gridfs-example>`_ | ||||
| In the following example, a document is created to store details about animals, including a photo:: | ||||
|  | ||||
|     class Animal(Document): | ||||
|         genus = StringField() | ||||
| @@ -20,8 +21,8 @@ a document is created to store details about animals, including a photo:: | ||||
|  | ||||
|     marmot = Animal(genus='Marmota', family='Sciuridae') | ||||
|  | ||||
|     marmot_photo = open('marmot.jpg', 'rb') | ||||
|     marmot.photo.put(marmot_photo, content_type = 'image/jpeg') | ||||
|     with open('marmot.jpg', 'rb') as fd: | ||||
|         marmot.photo.put(fd, content_type = 'image/jpeg') | ||||
|     marmot.save() | ||||
|  | ||||
| Retrieval | ||||
| @@ -34,6 +35,20 @@ field. The file can also be retrieved just as easily:: | ||||
|     photo = marmot.photo.read() | ||||
|     content_type = marmot.photo.content_type | ||||
|  | ||||
| .. note:: If you need to read() the content of a file multiple times, you'll need to "rewind" | ||||
|     the file-like object using `seek`:: | ||||
|  | ||||
|         marmot = Animal.objects(genus='Marmota').first() | ||||
|         content1 = marmot.photo.read() | ||||
|         assert content1 != "" | ||||
|  | ||||
|         content2 = marmot.photo.read()    # will be empty | ||||
|         assert content2 == "" | ||||
|  | ||||
|         marmot.photo.seek(0)              # rewind the file by setting the current position of the cursor in the file to 0 | ||||
|         content3 = marmot.photo.read() | ||||
|         assert content3 == content1 | ||||
|  | ||||
| Streaming | ||||
| --------- | ||||
|  | ||||
|   | ||||
| @@ -13,4 +13,5 @@ User Guide | ||||
|    gridfs | ||||
|    signals | ||||
|    text-indexes | ||||
|    logging-monitoring | ||||
|    mongomock | ||||
|   | ||||
							
								
								
									
										80
									
								
								docs/guide/logging-monitoring.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								docs/guide/logging-monitoring.rst
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| ================== | ||||
| Logging/Monitoring | ||||
| ================== | ||||
|  | ||||
| It is possible to use `pymongo.monitoring <https://api.mongodb.com/python/current/api/pymongo/monitoring.html>`_ to monitor | ||||
| the driver events (e.g: queries, connections, etc). This can be handy if you want to monitor the queries issued by | ||||
| MongoEngine to the driver. | ||||
|  | ||||
| To use `pymongo.monitoring` with MongoEngine, you need to make sure that you are registering the listeners | ||||
| **before** establishing the database connection (i.e calling `connect`): | ||||
|  | ||||
| The following snippet provides a basic logging of all command events: | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     import logging | ||||
|     from pymongo import monitoring | ||||
|     from mongoengine import * | ||||
|  | ||||
|     log = logging.getLogger() | ||||
|     log.setLevel(logging.DEBUG) | ||||
|     logging.basicConfig(level=logging.DEBUG) | ||||
|  | ||||
|  | ||||
|     class CommandLogger(monitoring.CommandListener): | ||||
|  | ||||
|         def started(self, event): | ||||
|             log.debug("Command {0.command_name} with request id " | ||||
|                      "{0.request_id} started on server " | ||||
|                      "{0.connection_id}".format(event)) | ||||
|  | ||||
|         def succeeded(self, event): | ||||
|             log.debug("Command {0.command_name} with request id " | ||||
|                      "{0.request_id} on server {0.connection_id} " | ||||
|                      "succeeded in {0.duration_micros} " | ||||
|                      "microseconds".format(event)) | ||||
|  | ||||
|         def failed(self, event): | ||||
|             log.debug("Command {0.command_name} with request id " | ||||
|                      "{0.request_id} on server {0.connection_id} " | ||||
|                      "failed in {0.duration_micros} " | ||||
|                      "microseconds".format(event)) | ||||
|  | ||||
|     monitoring.register(CommandLogger()) | ||||
|  | ||||
|  | ||||
|     class Jedi(Document): | ||||
|         name = StringField() | ||||
|  | ||||
|  | ||||
|     connect() | ||||
|  | ||||
|  | ||||
|     log.info('GO!') | ||||
|  | ||||
|     log.info('Saving an item through MongoEngine...') | ||||
|     Jedi(name='Obi-Wan Kenobii').save() | ||||
|  | ||||
|     log.info('Querying through MongoEngine...') | ||||
|     obiwan = Jedi.objects.first() | ||||
|  | ||||
|     log.info('Updating through MongoEngine...') | ||||
|     obiwan.name = 'Obi-Wan Kenobi' | ||||
|     obiwan.save() | ||||
|  | ||||
|  | ||||
| Executing this prints the following output:: | ||||
|  | ||||
|     INFO:root:GO! | ||||
|     INFO:root:Saving an item through MongoEngine... | ||||
|     DEBUG:root:Command insert with request id 1681692777 started on server ('localhost', 27017) | ||||
|     DEBUG:root:Command insert with request id 1681692777 on server ('localhost', 27017) succeeded in 562 microseconds | ||||
|     INFO:root:Querying through MongoEngine... | ||||
|     DEBUG:root:Command find with request id 1714636915 started on server ('localhost', 27017) | ||||
|     DEBUG:root:Command find with request id 1714636915 on server ('localhost', 27017) succeeded in 341 microseconds | ||||
|     INFO:root:Updating through MongoEngine... | ||||
|     DEBUG:root:Command update with request id 1957747793 started on server ('localhost', 27017) | ||||
|     DEBUG:root:Command update with request id 1957747793 on server ('localhost', 27017) succeeded in 455 microseconds | ||||
|  | ||||
| More details can of course be obtained by checking the `event` argument from the `CommandListener`. | ||||
| @@ -2,10 +2,10 @@ | ||||
| Use mongomock for testing | ||||
| ============================== | ||||
|  | ||||
| `mongomock <https://github.com/vmalloc/mongomock/>`_ is a package to do just  | ||||
| `mongomock <https://github.com/vmalloc/mongomock/>`_ is a package to do just | ||||
| what the name implies, mocking a mongo database. | ||||
|  | ||||
| To use with mongoengine, simply specify mongomock when connecting with  | ||||
| To use with mongoengine, simply specify mongomock when connecting with | ||||
| mongoengine: | ||||
|  | ||||
| .. code-block:: python | ||||
| @@ -21,7 +21,7 @@ or with an alias: | ||||
|     conn = get_connection('testdb') | ||||
|  | ||||
| Example of test file: | ||||
| -------- | ||||
| --------------------- | ||||
| .. code-block:: python | ||||
|  | ||||
|     import unittest | ||||
| @@ -45,4 +45,4 @@ Example of test file: | ||||
|             pers.save() | ||||
|  | ||||
|             fresh_pers = Person.objects().first() | ||||
|             self.assertEqual(fresh_pers.name, 'John') | ||||
|             assert fresh_pers.name ==  'John' | ||||
|   | ||||
| @@ -222,6 +222,18 @@ keyword argument:: | ||||
|  | ||||
| .. versionadded:: 0.4 | ||||
|  | ||||
| Sorting/Ordering results | ||||
| ======================== | ||||
| It is possible to order the results by 1 or more keys using :meth:`~mongoengine.queryset.QuerySet.order_by`. | ||||
| The order may be specified by prepending each of the keys by "+" or "-". Ascending order is assumed if there's no prefix.:: | ||||
|  | ||||
|     # Order by ascending date | ||||
|     blogs = BlogPost.objects().order_by('date')    # equivalent to .order_by('+date') | ||||
|  | ||||
|     # Order by ascending date first, then descending title | ||||
|     blogs = BlogPost.objects().order_by('+date', '-title') | ||||
|  | ||||
|  | ||||
| Limiting and skipping results | ||||
| ============================= | ||||
| Just as with traditional ORMs, you may limit the number of results returned or | ||||
| @@ -388,7 +400,7 @@ would be generating "tag-clouds":: | ||||
|  | ||||
| MongoDB aggregation API | ||||
| ----------------------- | ||||
| If you need to run aggregation pipelines, MongoEngine provides an entry point `Pymongo's aggregation framework <https://api.mongodb.com/python/current/examples/aggregation.html#aggregation-framework>`_ | ||||
| If you need to run aggregation pipelines, MongoEngine provides an entry point to `Pymongo's aggregation framework <https://api.mongodb.com/python/current/examples/aggregation.html#aggregation-framework>`_ | ||||
| through :meth:`~mongoengine.queryset.QuerySet.aggregate`. Check out Pymongo's documentation for the syntax and pipeline. | ||||
| An example of its use would be:: | ||||
|  | ||||
| @@ -402,7 +414,7 @@ An example of its use would be:: | ||||
|             {"$sort" : {"name" : -1}}, | ||||
|             {"$project": {"_id": 0, "name": {"$toUpper": "$name"}}} | ||||
|             ] | ||||
|         data = Person.objects().aggregate(*pipeline) | ||||
|         data = Person.objects().aggregate(pipeline) | ||||
|         assert data == [{'name': 'BOB'}, {'name': 'JOHN'}] | ||||
|  | ||||
| Query efficiency and performance | ||||
| @@ -585,7 +597,8 @@ cannot use the `$` syntax in keyword arguments it has been mapped to `S`:: | ||||
|     ['database', 'mongodb'] | ||||
|  | ||||
| From MongoDB version 2.6, push operator supports $position value which allows | ||||
| to push values with index. | ||||
| to push values with index:: | ||||
|  | ||||
|     >>> post = BlogPost(title="Test", tags=["mongo"]) | ||||
|     >>> post.save() | ||||
|     >>> post.update(push__tags__0=["database", "code"]) | ||||
|   | ||||
| @@ -23,9 +23,18 @@ MongoDB. To install it, simply run | ||||
| :doc:`upgrade` | ||||
|   How to upgrade MongoEngine. | ||||
|  | ||||
| :doc:`faq` | ||||
|   Frequently Asked Questions | ||||
|  | ||||
| :doc:`django` | ||||
|   Using MongoEngine and Django | ||||
|  | ||||
| MongoDB and driver support | ||||
| -------------------------- | ||||
|  | ||||
| MongoEngine is based on the PyMongo driver and tested against multiple versions of MongoDB. | ||||
| For further details, please refer to the `readme <https://github.com/MongoEngine/mongoengine#mongoengine>`_. | ||||
|  | ||||
| Community | ||||
| --------- | ||||
|  | ||||
| @@ -73,6 +82,7 @@ formats for offline reading. | ||||
|     apireference | ||||
|     changelog | ||||
|     upgrade | ||||
|     faq | ||||
|     django | ||||
|  | ||||
| Indices and tables | ||||
|   | ||||
| @@ -52,7 +52,7 @@ rename its occurrences. | ||||
| This release includes a major rehaul of MongoEngine's code quality and | ||||
| introduces a few breaking changes. It also touches many different parts of | ||||
| the package and although all the changes have been tested and scrutinized, | ||||
| you're encouraged to thorougly test the upgrade. | ||||
| you're encouraged to thoroughly test the upgrade. | ||||
|  | ||||
| First breaking change involves renaming `ConnectionError` to `MongoEngineConnectionError`. | ||||
| If you import or catch this exception, you'll need to rename it in your code. | ||||
|   | ||||
| @@ -28,7 +28,7 @@ __all__ = ( | ||||
| ) | ||||
|  | ||||
|  | ||||
| VERSION = (0, 18, 2) | ||||
| VERSION = (0, 19, 1) | ||||
|  | ||||
|  | ||||
| def get_version(): | ||||
|   | ||||
| @@ -120,6 +120,9 @@ class BaseList(list): | ||||
|         super(BaseList, self).__init__(list_items) | ||||
|  | ||||
|     def __getitem__(self, key): | ||||
|         # change index to positive value because MongoDB does not support negative one | ||||
|         if isinstance(key, int) and key < 0: | ||||
|             key = len(self) + key | ||||
|         value = super(BaseList, self).__getitem__(key) | ||||
|  | ||||
|         if isinstance(key, slice): | ||||
|   | ||||
| @@ -62,13 +62,13 @@ class BaseDocument(object): | ||||
|         """ | ||||
|         Initialise a document or an embedded document. | ||||
|  | ||||
|         :param dict values: A dictionary of keys and values for the document. | ||||
|         :param values: A dictionary of keys and values for the document. | ||||
|             It may contain additional reserved keywords, e.g. "__auto_convert". | ||||
|         :param bool __auto_convert: If True, supplied values will be converted | ||||
|         :param __auto_convert: If True, supplied values will be converted | ||||
|             to Python-type values via each field's `to_python` method. | ||||
|         :param set __only_fields: A set of fields that have been loaded for | ||||
|         :param __only_fields: A set of fields that have been loaded for | ||||
|             this document. Empty if all fields have been loaded. | ||||
|         :param bool _created: Indicates whether this is a brand new document | ||||
|         :param _created: Indicates whether this is a brand new document | ||||
|             or whether it's already been persisted before. Defaults to true. | ||||
|         """ | ||||
|         self._initialised = False | ||||
| @@ -732,7 +732,10 @@ class BaseDocument(object): | ||||
|             only_fields = [] | ||||
|  | ||||
|         if son and not isinstance(son, dict): | ||||
|             raise ValueError("The source SON object needs to be of type 'dict'") | ||||
|             raise ValueError( | ||||
|                 "The source SON object needs to be of type 'dict' but a '%s' was found" | ||||
|                 % type(son) | ||||
|             ) | ||||
|  | ||||
|         # Get the class name from the document, falling back to the given | ||||
|         # class if unavailable | ||||
| @@ -770,7 +773,9 @@ class BaseDocument(object): | ||||
|                     errors_dict[field_name] = e | ||||
|  | ||||
|         if errors_dict: | ||||
|             errors = "\n".join(["%s - %s" % (k, v) for k, v in errors_dict.items()]) | ||||
|             errors = "\n".join( | ||||
|                 ["Field '%s' - %s" % (k, v) for k, v in errors_dict.items()] | ||||
|             ) | ||||
|             msg = "Invalid data to create a `%s` instance.\n%s" % ( | ||||
|                 cls._class_name, | ||||
|                 errors, | ||||
|   | ||||
| @@ -171,7 +171,7 @@ class no_sub_classes(object): | ||||
| class query_counter(object): | ||||
|     """Query_counter context manager to get the number of queries. | ||||
|     This works by updating the `profiling_level` of the database so that all queries get logged, | ||||
|     resetting the db.system.profile collection at the beginnig of the context and counting the new entries. | ||||
|     resetting the db.system.profile collection at the beginning of the context and counting the new entries. | ||||
|  | ||||
|     This was designed for debugging purpose. In fact it is a global counter so queries issued by other threads/processes | ||||
|     can interfere with it | ||||
| @@ -182,10 +182,10 @@ class query_counter(object): | ||||
|     - Some queries are ignored by default by the counter (killcursors, db.system.indexes) | ||||
|     """ | ||||
|  | ||||
|     def __init__(self): | ||||
|     def __init__(self, alias=DEFAULT_CONNECTION_NAME): | ||||
|         """Construct the query_counter | ||||
|         """ | ||||
|         self.db = get_db() | ||||
|         self.db = get_db(alias=alias) | ||||
|         self.initial_profiling_level = None | ||||
|         self._ctx_query_counter = 0  # number of queries issued by the context | ||||
|  | ||||
| @@ -247,8 +247,8 @@ class query_counter(object): | ||||
|             - self._ctx_query_counter | ||||
|         ) | ||||
|         self._ctx_query_counter += ( | ||||
|             1 | ||||
|         )  # Account for the query we just issued to gather the information | ||||
|             1  # Account for the query we just issued to gather the information | ||||
|         ) | ||||
|         return count | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -41,6 +41,7 @@ from mongoengine.common import _import_class | ||||
| from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_db | ||||
| from mongoengine.document import Document, EmbeddedDocument | ||||
| from mongoengine.errors import DoesNotExist, InvalidQueryError, ValidationError | ||||
| from mongoengine.mongodb_support import MONGODB_36, get_mongodb_version | ||||
| from mongoengine.python_support import StringIO | ||||
| from mongoengine.queryset import DO_NOTHING | ||||
| from mongoengine.queryset.base import BaseQuerySet | ||||
| @@ -1051,6 +1052,15 @@ def key_has_dot_or_dollar(d): | ||||
|             return True | ||||
|  | ||||
|  | ||||
| def key_starts_with_dollar(d): | ||||
|     """Helper function to recursively determine if any key in a | ||||
|     dictionary starts with a dollar | ||||
|     """ | ||||
|     for k, v in d.items(): | ||||
|         if (k.startswith("$")) or (isinstance(v, dict) and key_starts_with_dollar(v)): | ||||
|             return True | ||||
|  | ||||
|  | ||||
| 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. | ||||
| @@ -1077,11 +1087,18 @@ class DictField(ComplexBaseField): | ||||
|         if key_not_string(value): | ||||
|             msg = "Invalid dictionary key - documents must have only string keys" | ||||
|             self.error(msg) | ||||
|         if key_has_dot_or_dollar(value): | ||||
|  | ||||
|         curr_mongo_ver = get_mongodb_version() | ||||
|  | ||||
|         if curr_mongo_ver < MONGODB_36 and key_has_dot_or_dollar(value): | ||||
|             self.error( | ||||
|                 'Invalid dictionary key name - keys may not contain "."' | ||||
|                 ' or startswith "$" characters' | ||||
|             ) | ||||
|         elif curr_mongo_ver >= MONGODB_36 and key_starts_with_dollar(value): | ||||
|             self.error( | ||||
|                 'Invalid dictionary key name - keys may not startswith "$" characters' | ||||
|             ) | ||||
|         super(DictField, self).validate(value) | ||||
|  | ||||
|     def lookup_member(self, member_name): | ||||
| @@ -2502,6 +2519,13 @@ class LazyReferenceField(BaseField): | ||||
|         else: | ||||
|             return pk | ||||
|  | ||||
|     def to_python(self, value): | ||||
|         """Convert a MongoDB-compatible type to a Python type.""" | ||||
|         if not isinstance(value, (DBRef, Document, EmbeddedDocument)): | ||||
|             collection = self.document_type._get_collection_name() | ||||
|             value = DBRef(collection, self.document_type.id.to_python(value)) | ||||
|         return value | ||||
|  | ||||
|     def validate(self, value): | ||||
|         if isinstance(value, LazyReference): | ||||
|             if value.collection != self.document_type._get_collection_name(): | ||||
|   | ||||
| @@ -302,7 +302,7 @@ class BaseQuerySet(object): | ||||
|                 ``insert(..., {w: 2, fsync: True})`` will wait until at least | ||||
|                 two servers have recorded the write and will force an fsync on | ||||
|                 each server being written to. | ||||
|         :parm signal_kwargs: (optional) kwargs dictionary to be passed to | ||||
|         :param signal_kwargs: (optional) kwargs dictionary to be passed to | ||||
|             the signal calls. | ||||
|  | ||||
|         By default returns document instances, set ``load_bulk`` to False to | ||||
| @@ -1193,9 +1193,7 @@ class BaseQuerySet(object): | ||||
|         validate_read_preference("read_preference", read_preference) | ||||
|         queryset = self.clone() | ||||
|         queryset._read_preference = read_preference | ||||
|         queryset._cursor_obj = ( | ||||
|             None | ||||
|         )  # we need to re-create the cursor object whenever we apply read_preference | ||||
|         queryset._cursor_obj = None  # we need to re-create the cursor object whenever we apply read_preference | ||||
|         return queryset | ||||
|  | ||||
|     def scalar(self, *fields): | ||||
| @@ -1257,16 +1255,27 @@ class BaseQuerySet(object): | ||||
|             for data in son_data | ||||
|         ] | ||||
|  | ||||
|     def aggregate(self, *pipeline, **kwargs): | ||||
|         """ | ||||
|         Perform a aggregate function based in your queryset params | ||||
|     def aggregate(self, pipeline, *suppl_pipeline, **kwargs): | ||||
|         """Perform a aggregate function based in your queryset params | ||||
|  | ||||
|         :param pipeline: list of aggregation commands,\ | ||||
|             see: http://docs.mongodb.org/manual/core/aggregation-pipeline/ | ||||
|  | ||||
|         :param suppl_pipeline: unpacked list of pipeline (added to support deprecation of the old interface) | ||||
|             parameter will be removed shortly | ||||
|         :param kwargs: (optional) kwargs dictionary to be passed to pymongo's aggregate call | ||||
|             See https://api.mongodb.com/python/current/api/pymongo/collection.html#pymongo.collection.Collection.aggregate | ||||
|         .. versionadded:: 0.9 | ||||
|         """ | ||||
|         initial_pipeline = [] | ||||
|         using_deprecated_interface = isinstance(pipeline, dict) or bool(suppl_pipeline) | ||||
|         user_pipeline = [pipeline] if isinstance(pipeline, dict) else list(pipeline) | ||||
|  | ||||
|         if using_deprecated_interface: | ||||
|             msg = "Calling .aggregate() with un unpacked list (*pipeline) is deprecated, it will soon change and will expect a list (similar to pymongo.Collection.aggregate interface), see documentation" | ||||
|             warnings.warn(msg, DeprecationWarning) | ||||
|  | ||||
|         user_pipeline += suppl_pipeline | ||||
|  | ||||
|         initial_pipeline = [] | ||||
|         if self._query: | ||||
|             initial_pipeline.append({"$match": self._query}) | ||||
|  | ||||
| @@ -1283,14 +1292,14 @@ class BaseQuerySet(object): | ||||
|         if self._skip is not None: | ||||
|             initial_pipeline.append({"$skip": self._skip}) | ||||
|  | ||||
|         pipeline = initial_pipeline + list(pipeline) | ||||
|         final_pipeline = initial_pipeline + user_pipeline | ||||
|  | ||||
|         collection = self._collection | ||||
|         if self._read_preference is not None: | ||||
|             return self._collection.with_options( | ||||
|             collection = self._collection.with_options( | ||||
|                 read_preference=self._read_preference | ||||
|             ).aggregate(pipeline, cursor={}, **kwargs) | ||||
|  | ||||
|         return self._collection.aggregate(pipeline, cursor={}, **kwargs) | ||||
|             ) | ||||
|         return collection.aggregate(final_pipeline, cursor={}, **kwargs) | ||||
|  | ||||
|     # JS functionality | ||||
|     def map_reduce( | ||||
| @@ -1639,6 +1648,7 @@ class BaseQuerySet(object): | ||||
|             ).find(self._query, **self._cursor_args) | ||||
|         else: | ||||
|             self._cursor_obj = self._collection.find(self._query, **self._cursor_args) | ||||
|  | ||||
|         # Apply "where" clauses to cursor | ||||
|         if self._where_clause: | ||||
|             where_clause = self._sub_js_fields(self._where_clause) | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import copy | ||||
| import warnings | ||||
|  | ||||
| from mongoengine.errors import InvalidQueryError | ||||
| from mongoengine.queryset import transform | ||||
| @@ -96,9 +97,11 @@ class QNode(object): | ||||
|         """Combine this node with another node into a QCombination | ||||
|         object. | ||||
|         """ | ||||
|         # If the other Q() is empty, ignore it and just use `self`. | ||||
|         if getattr(other, "empty", True): | ||||
|             return self | ||||
|  | ||||
|         # Or if this Q is empty, ignore it and just use `other`. | ||||
|         if self.empty: | ||||
|             return other | ||||
|  | ||||
| @@ -106,6 +109,8 @@ class QNode(object): | ||||
|  | ||||
|     @property | ||||
|     def empty(self): | ||||
|         msg = "'empty' property is deprecated in favour of using 'not bool(filter)'" | ||||
|         warnings.warn(msg, DeprecationWarning) | ||||
|         return False | ||||
|  | ||||
|     def __or__(self, other): | ||||
| @@ -135,6 +140,11 @@ class QCombination(QNode): | ||||
|         op = " & " if self.operation is self.AND else " | " | ||||
|         return "(%s)" % op.join([repr(node) for node in self.children]) | ||||
|  | ||||
|     def __bool__(self): | ||||
|         return bool(self.children) | ||||
|  | ||||
|     __nonzero__ = __bool__  # For Py2 support | ||||
|  | ||||
|     def accept(self, visitor): | ||||
|         for i in range(len(self.children)): | ||||
|             if isinstance(self.children[i], QNode): | ||||
| @@ -144,8 +154,17 @@ class QCombination(QNode): | ||||
|  | ||||
|     @property | ||||
|     def empty(self): | ||||
|         msg = "'empty' property is deprecated in favour of using 'not bool(filter)'" | ||||
|         warnings.warn(msg, DeprecationWarning) | ||||
|         return not bool(self.children) | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         return ( | ||||
|             self.__class__ == other.__class__ | ||||
|             and self.operation == other.operation | ||||
|             and self.children == other.children | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class Q(QNode): | ||||
|     """A simple query object, used in a query tree to build up more complex | ||||
| @@ -158,6 +177,14 @@ class Q(QNode): | ||||
|     def __repr__(self): | ||||
|         return "Q(**%s)" % repr(self.query) | ||||
|  | ||||
|     def __bool__(self): | ||||
|         return bool(self.query) | ||||
|  | ||||
|     __nonzero__ = __bool__  # For Py2 support | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         return self.__class__ == other.__class__ and self.query == other.query | ||||
|  | ||||
|     def accept(self, visitor): | ||||
|         return visitor.visit_query(self) | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| nose | ||||
| pymongo>=3.4 | ||||
| six==1.10.0 | ||||
| Sphinx==1.5.5 | ||||
|   | ||||
							
								
								
									
										11
									
								
								setup.cfg
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								setup.cfg
									
									
									
									
									
								
							| @@ -1,11 +1,10 @@ | ||||
| [nosetests] | ||||
| verbosity=2 | ||||
| detailed-errors=1 | ||||
| #tests=tests | ||||
| cover-package=mongoengine | ||||
|  | ||||
| [flake8] | ||||
| ignore=E501,F401,F403,F405,I201,I202,W504, W605, W503 | ||||
| exclude=build,dist,docs,venv,venv3,.tox,.eggs,tests | ||||
| max-complexity=47 | ||||
| application-import-names=mongoengine,tests | ||||
|  | ||||
| [tool:pytest] | ||||
| # Limits the discovery to tests directory | ||||
| # avoids that it runs for instance the benchmark | ||||
| testpaths = tests | ||||
|   | ||||
							
								
								
									
										73
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								setup.py
									
									
									
									
									
								
							| @@ -1,6 +1,9 @@ | ||||
| import os | ||||
| import sys | ||||
|  | ||||
| from pkg_resources import normalize_path | ||||
| from setuptools import find_packages, setup | ||||
| from setuptools.command.test import test as TestCommand | ||||
|  | ||||
| # Hack to silence atexit traceback in newer python versions | ||||
| try: | ||||
| @@ -24,6 +27,62 @@ def get_version(version_tuple): | ||||
|     return ".".join(map(str, version_tuple)) | ||||
|  | ||||
|  | ||||
| class PyTest(TestCommand): | ||||
|     """Will force pytest to search for tests inside the build directory | ||||
|     for 2to3 converted code (used by tox), instead of the current directory. | ||||
|     Required as long as we need 2to3 | ||||
|  | ||||
|     Known Limitation: https://tox.readthedocs.io/en/latest/example/pytest.html#known-issues-and-limitations | ||||
|     Source: https://www.hackzine.org/python-testing-with-pytest-and-2to3-plus-tox-and-travis-ci.html | ||||
|     """ | ||||
|  | ||||
|     # https://pytest.readthedocs.io/en/2.7.3/goodpractises.html#integration-with-setuptools-test-commands | ||||
|     # Allows to provide pytest command argument through the test runner command `python setup.py test` | ||||
|     # e.g: `python setup.py test -a "-k=test"` | ||||
|     # This only works for 1 argument though | ||||
|     user_options = [("pytest-args=", "a", "Arguments to pass to py.test")] | ||||
|  | ||||
|     def initialize_options(self): | ||||
|         TestCommand.initialize_options(self) | ||||
|         self.pytest_args = "" | ||||
|  | ||||
|     def finalize_options(self): | ||||
|         TestCommand.finalize_options(self) | ||||
|         self.test_args = ["tests"] | ||||
|         self.test_suite = True | ||||
|  | ||||
|     def run_tests(self): | ||||
|         # import here, cause outside the eggs aren't loaded | ||||
|         from pkg_resources import _namespace_packages | ||||
|         import pytest | ||||
|  | ||||
|         # Purge modules under test from sys.modules. The test loader will | ||||
|         # re-import them from the build location. Required when 2to3 is used | ||||
|         # with namespace packages. | ||||
|         if sys.version_info >= (3,) and getattr(self.distribution, "use_2to3", False): | ||||
|             module = self.test_args[-1].split(".")[0] | ||||
|             if module in _namespace_packages: | ||||
|                 del_modules = [] | ||||
|                 if module in sys.modules: | ||||
|                     del_modules.append(module) | ||||
|                 module += "." | ||||
|                 for name in sys.modules: | ||||
|                     if name.startswith(module): | ||||
|                         del_modules.append(name) | ||||
|                 map(sys.modules.__delitem__, del_modules) | ||||
|  | ||||
|             # Run on the build directory for 2to3-built code | ||||
|             # This will prevent the old 2.x code from being found | ||||
|             # by py.test discovery mechanism, that apparently | ||||
|             # ignores sys.path.. | ||||
|             ei_cmd = self.get_finalized_command("egg_info") | ||||
|             self.test_args = [normalize_path(ei_cmd.egg_base)] | ||||
|  | ||||
|         cmd_args = self.test_args + ([self.pytest_args] if self.pytest_args else []) | ||||
|         errno = pytest.main(cmd_args) | ||||
|         sys.exit(errno) | ||||
|  | ||||
|  | ||||
| # Dirty hack to get version number from monogengine/__init__.py - we can't | ||||
| # import it as it depends on PyMongo and PyMongo isn't installed until this | ||||
| # file is read | ||||
| @@ -51,11 +110,17 @@ CLASSIFIERS = [ | ||||
|  | ||||
| extra_opts = { | ||||
|     "packages": find_packages(exclude=["tests", "tests.*"]), | ||||
|     "tests_require": ["nose", "coverage==4.2", "blinker", "Pillow>=2.0.0"], | ||||
|     "tests_require": [ | ||||
|         "pytest<5.0", | ||||
|         "pytest-cov", | ||||
|         "coverage<5.0",  # recent coverage switched to sqlite format for the .coverage file which isn't handled properly by coveralls | ||||
|         "blinker", | ||||
|         "Pillow>=2.0.0, <7.0.0",  # 7.0.0 dropped Python2 support | ||||
|     ], | ||||
| } | ||||
| if sys.version_info[0] == 3: | ||||
|     extra_opts["use_2to3"] = True | ||||
|     if "test" in sys.argv or "nosetests" in sys.argv: | ||||
|     if "test" in sys.argv: | ||||
|         extra_opts["packages"] = find_packages() | ||||
|         extra_opts["package_data"] = { | ||||
|             "tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"] | ||||
| @@ -78,7 +143,7 @@ setup( | ||||
|     long_description=LONG_DESCRIPTION, | ||||
|     platforms=["any"], | ||||
|     classifiers=CLASSIFIERS, | ||||
|     install_requires=["pymongo>=3.4", "six"], | ||||
|     test_suite="nose.collector", | ||||
|     install_requires=["pymongo>=3.4, <4.0", "six>=1.10.0"], | ||||
|     cmdclass={"test": PyTest}, | ||||
|     **extra_opts | ||||
| ) | ||||
|   | ||||
| @@ -31,7 +31,5 @@ class TestAllWarnings(unittest.TestCase): | ||||
|             meta = {"collection": "fail"} | ||||
|  | ||||
|         warning = self.warning_list[0] | ||||
|         self.assertEqual(SyntaxWarning, warning["category"]) | ||||
|         self.assertEqual( | ||||
|             "non_abstract_base", InheritedDocumentFailTest._get_collection_name() | ||||
|         ) | ||||
|         assert SyntaxWarning == warning["category"] | ||||
|         assert "non_abstract_base" == InheritedDocumentFailTest._get_collection_name() | ||||
|   | ||||
| @@ -29,43 +29,40 @@ class TestClassMethods(unittest.TestCase): | ||||
|     def test_definition(self): | ||||
|         """Ensure that document may be defined using fields. | ||||
|         """ | ||||
|         self.assertEqual( | ||||
|             ["_cls", "age", "id", "name"], sorted(self.Person._fields.keys()) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             ["IntField", "ObjectIdField", "StringField", "StringField"], | ||||
|             sorted([x.__class__.__name__ for x in self.Person._fields.values()]), | ||||
|         assert ["_cls", "age", "id", "name"] == sorted(self.Person._fields.keys()) | ||||
|         assert ["IntField", "ObjectIdField", "StringField", "StringField"] == sorted( | ||||
|             [x.__class__.__name__ for x in self.Person._fields.values()] | ||||
|         ) | ||||
|  | ||||
|     def test_get_db(self): | ||||
|         """Ensure that get_db returns the expected db. | ||||
|         """ | ||||
|         db = self.Person._get_db() | ||||
|         self.assertEqual(self.db, db) | ||||
|         assert self.db == db | ||||
|  | ||||
|     def test_get_collection_name(self): | ||||
|         """Ensure that get_collection_name returns the expected collection | ||||
|         name. | ||||
|         """ | ||||
|         collection_name = "person" | ||||
|         self.assertEqual(collection_name, self.Person._get_collection_name()) | ||||
|         assert collection_name == self.Person._get_collection_name() | ||||
|  | ||||
|     def test_get_collection(self): | ||||
|         """Ensure that get_collection returns the expected collection. | ||||
|         """ | ||||
|         collection_name = "person" | ||||
|         collection = self.Person._get_collection() | ||||
|         self.assertEqual(self.db[collection_name], collection) | ||||
|         assert self.db[collection_name] == collection | ||||
|  | ||||
|     def test_drop_collection(self): | ||||
|         """Ensure that the collection may be dropped from the database. | ||||
|         """ | ||||
|         collection_name = "person" | ||||
|         self.Person(name="Test").save() | ||||
|         self.assertIn(collection_name, list_collection_names(self.db)) | ||||
|         assert collection_name in list_collection_names(self.db) | ||||
|  | ||||
|         self.Person.drop_collection() | ||||
|         self.assertNotIn(collection_name, list_collection_names(self.db)) | ||||
|         assert collection_name not in list_collection_names(self.db) | ||||
|  | ||||
|     def test_register_delete_rule(self): | ||||
|         """Ensure that register delete rule adds a delete rule to the document | ||||
| @@ -75,12 +72,10 @@ class TestClassMethods(unittest.TestCase): | ||||
|         class Job(Document): | ||||
|             employee = ReferenceField(self.Person) | ||||
|  | ||||
|         self.assertEqual(self.Person._meta.get("delete_rules"), None) | ||||
|         assert self.Person._meta.get("delete_rules") is None | ||||
|  | ||||
|         self.Person.register_delete_rule(Job, "employee", NULLIFY) | ||||
|         self.assertEqual( | ||||
|             self.Person._meta["delete_rules"], {(Job, "employee"): NULLIFY} | ||||
|         ) | ||||
|         assert self.Person._meta["delete_rules"] == {(Job, "employee"): NULLIFY} | ||||
|  | ||||
|     def test_compare_indexes(self): | ||||
|         """ Ensure that the indexes are properly created and that | ||||
| @@ -98,22 +93,22 @@ class TestClassMethods(unittest.TestCase): | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
|         BlogPost.ensure_indexes() | ||||
|         self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) | ||||
|         assert BlogPost.compare_indexes() == {"missing": [], "extra": []} | ||||
|  | ||||
|         BlogPost.ensure_index(["author", "description"]) | ||||
|         self.assertEqual( | ||||
|             BlogPost.compare_indexes(), | ||||
|             {"missing": [], "extra": [[("author", 1), ("description", 1)]]}, | ||||
|         ) | ||||
|         assert BlogPost.compare_indexes() == { | ||||
|             "missing": [], | ||||
|             "extra": [[("author", 1), ("description", 1)]], | ||||
|         } | ||||
|  | ||||
|         BlogPost._get_collection().drop_index("author_1_description_1") | ||||
|         self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) | ||||
|         assert BlogPost.compare_indexes() == {"missing": [], "extra": []} | ||||
|  | ||||
|         BlogPost._get_collection().drop_index("author_1_title_1") | ||||
|         self.assertEqual( | ||||
|             BlogPost.compare_indexes(), | ||||
|             {"missing": [[("author", 1), ("title", 1)]], "extra": []}, | ||||
|         ) | ||||
|         assert BlogPost.compare_indexes() == { | ||||
|             "missing": [[("author", 1), ("title", 1)]], | ||||
|             "extra": [], | ||||
|         } | ||||
|  | ||||
|     def test_compare_indexes_inheritance(self): | ||||
|         """ Ensure that the indexes are properly created and that | ||||
| @@ -138,22 +133,22 @@ class TestClassMethods(unittest.TestCase): | ||||
|  | ||||
|         BlogPost.ensure_indexes() | ||||
|         BlogPostWithTags.ensure_indexes() | ||||
|         self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) | ||||
|         assert BlogPost.compare_indexes() == {"missing": [], "extra": []} | ||||
|  | ||||
|         BlogPostWithTags.ensure_index(["author", "tag_list"]) | ||||
|         self.assertEqual( | ||||
|             BlogPost.compare_indexes(), | ||||
|             {"missing": [], "extra": [[("_cls", 1), ("author", 1), ("tag_list", 1)]]}, | ||||
|         ) | ||||
|         assert BlogPost.compare_indexes() == { | ||||
|             "missing": [], | ||||
|             "extra": [[("_cls", 1), ("author", 1), ("tag_list", 1)]], | ||||
|         } | ||||
|  | ||||
|         BlogPostWithTags._get_collection().drop_index("_cls_1_author_1_tag_list_1") | ||||
|         self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) | ||||
|         assert BlogPost.compare_indexes() == {"missing": [], "extra": []} | ||||
|  | ||||
|         BlogPostWithTags._get_collection().drop_index("_cls_1_author_1_tags_1") | ||||
|         self.assertEqual( | ||||
|             BlogPost.compare_indexes(), | ||||
|             {"missing": [[("_cls", 1), ("author", 1), ("tags", 1)]], "extra": []}, | ||||
|         ) | ||||
|         assert BlogPost.compare_indexes() == { | ||||
|             "missing": [[("_cls", 1), ("author", 1), ("tags", 1)]], | ||||
|             "extra": [], | ||||
|         } | ||||
|  | ||||
|     def test_compare_indexes_multiple_subclasses(self): | ||||
|         """ Ensure that compare_indexes behaves correctly if called from a | ||||
| @@ -182,13 +177,9 @@ class TestClassMethods(unittest.TestCase): | ||||
|         BlogPostWithTags.ensure_indexes() | ||||
|         BlogPostWithCustomField.ensure_indexes() | ||||
|  | ||||
|         self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) | ||||
|         self.assertEqual( | ||||
|             BlogPostWithTags.compare_indexes(), {"missing": [], "extra": []} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             BlogPostWithCustomField.compare_indexes(), {"missing": [], "extra": []} | ||||
|         ) | ||||
|         assert BlogPost.compare_indexes() == {"missing": [], "extra": []} | ||||
|         assert BlogPostWithTags.compare_indexes() == {"missing": [], "extra": []} | ||||
|         assert BlogPostWithCustomField.compare_indexes() == {"missing": [], "extra": []} | ||||
|  | ||||
|     def test_compare_indexes_for_text_indexes(self): | ||||
|         """ Ensure that compare_indexes behaves correctly for text indexes """ | ||||
| @@ -210,7 +201,7 @@ class TestClassMethods(unittest.TestCase): | ||||
|         Doc.ensure_indexes() | ||||
|         actual = Doc.compare_indexes() | ||||
|         expected = {"missing": [], "extra": []} | ||||
|         self.assertEqual(actual, expected) | ||||
|         assert actual == expected | ||||
|  | ||||
|     def test_list_indexes_inheritance(self): | ||||
|         """ ensure that all of the indexes are listed regardless of the super- | ||||
| @@ -240,19 +231,14 @@ class TestClassMethods(unittest.TestCase): | ||||
|         BlogPostWithTags.ensure_indexes() | ||||
|         BlogPostWithTagsAndExtraText.ensure_indexes() | ||||
|  | ||||
|         self.assertEqual(BlogPost.list_indexes(), BlogPostWithTags.list_indexes()) | ||||
|         self.assertEqual( | ||||
|             BlogPost.list_indexes(), BlogPostWithTagsAndExtraText.list_indexes() | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             BlogPost.list_indexes(), | ||||
|             [ | ||||
|                 [("_cls", 1), ("author", 1), ("tags", 1)], | ||||
|                 [("_cls", 1), ("author", 1), ("tags", 1), ("extra_text", 1)], | ||||
|                 [(u"_id", 1)], | ||||
|                 [("_cls", 1)], | ||||
|             ], | ||||
|         ) | ||||
|         assert BlogPost.list_indexes() == BlogPostWithTags.list_indexes() | ||||
|         assert BlogPost.list_indexes() == BlogPostWithTagsAndExtraText.list_indexes() | ||||
|         assert BlogPost.list_indexes() == [ | ||||
|             [("_cls", 1), ("author", 1), ("tags", 1)], | ||||
|             [("_cls", 1), ("author", 1), ("tags", 1), ("extra_text", 1)], | ||||
|             [(u"_id", 1)], | ||||
|             [("_cls", 1)], | ||||
|         ] | ||||
|  | ||||
|     def test_register_delete_rule_inherited(self): | ||||
|         class Vaccine(Document): | ||||
| @@ -271,8 +257,8 @@ class TestClassMethods(unittest.TestCase): | ||||
|         class Cat(Animal): | ||||
|             name = StringField(required=True) | ||||
|  | ||||
|         self.assertEqual(Vaccine._meta["delete_rules"][(Animal, "vaccine_made")], PULL) | ||||
|         self.assertEqual(Vaccine._meta["delete_rules"][(Cat, "vaccine_made")], PULL) | ||||
|         assert Vaccine._meta["delete_rules"][(Animal, "vaccine_made")] == PULL | ||||
|         assert Vaccine._meta["delete_rules"][(Cat, "vaccine_made")] == PULL | ||||
|  | ||||
|     def test_collection_naming(self): | ||||
|         """Ensure that a collection with a specified name may be used. | ||||
| @@ -281,19 +267,17 @@ class TestClassMethods(unittest.TestCase): | ||||
|         class DefaultNamingTest(Document): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "default_naming_test", DefaultNamingTest._get_collection_name() | ||||
|         ) | ||||
|         assert "default_naming_test" == DefaultNamingTest._get_collection_name() | ||||
|  | ||||
|         class CustomNamingTest(Document): | ||||
|             meta = {"collection": "pimp_my_collection"} | ||||
|  | ||||
|         self.assertEqual("pimp_my_collection", CustomNamingTest._get_collection_name()) | ||||
|         assert "pimp_my_collection" == CustomNamingTest._get_collection_name() | ||||
|  | ||||
|         class DynamicNamingTest(Document): | ||||
|             meta = {"collection": lambda c: "DYNAMO"} | ||||
|  | ||||
|         self.assertEqual("DYNAMO", DynamicNamingTest._get_collection_name()) | ||||
|         assert "DYNAMO" == DynamicNamingTest._get_collection_name() | ||||
|  | ||||
|         # Use Abstract class to handle backwards compatibility | ||||
|         class BaseDocument(Document): | ||||
| @@ -302,14 +286,12 @@ class TestClassMethods(unittest.TestCase): | ||||
|         class OldNamingConvention(BaseDocument): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "oldnamingconvention", OldNamingConvention._get_collection_name() | ||||
|         ) | ||||
|         assert "oldnamingconvention" == OldNamingConvention._get_collection_name() | ||||
|  | ||||
|         class InheritedAbstractNamingTest(BaseDocument): | ||||
|             meta = {"collection": "wibble"} | ||||
|  | ||||
|         self.assertEqual("wibble", InheritedAbstractNamingTest._get_collection_name()) | ||||
|         assert "wibble" == InheritedAbstractNamingTest._get_collection_name() | ||||
|  | ||||
|         # Mixin tests | ||||
|         class BaseMixin(object): | ||||
| @@ -318,8 +300,9 @@ class TestClassMethods(unittest.TestCase): | ||||
|         class OldMixinNamingConvention(Document, BaseMixin): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "oldmixinnamingconvention", OldMixinNamingConvention._get_collection_name() | ||||
|         assert ( | ||||
|             "oldmixinnamingconvention" | ||||
|             == OldMixinNamingConvention._get_collection_name() | ||||
|         ) | ||||
|  | ||||
|         class BaseMixin(object): | ||||
| @@ -331,7 +314,7 @@ class TestClassMethods(unittest.TestCase): | ||||
|         class MyDocument(BaseDocument): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual("basedocument", MyDocument._get_collection_name()) | ||||
|         assert "basedocument" == MyDocument._get_collection_name() | ||||
|  | ||||
|     def test_custom_collection_name_operations(self): | ||||
|         """Ensure that a collection with a specified name is used as expected. | ||||
| @@ -343,16 +326,16 @@ class TestClassMethods(unittest.TestCase): | ||||
|             meta = {"collection": collection_name} | ||||
|  | ||||
|         Person(name="Test User").save() | ||||
|         self.assertIn(collection_name, list_collection_names(self.db)) | ||||
|         assert collection_name in list_collection_names(self.db) | ||||
|  | ||||
|         user_obj = self.db[collection_name].find_one() | ||||
|         self.assertEqual(user_obj["name"], "Test User") | ||||
|         assert user_obj["name"] == "Test User" | ||||
|  | ||||
|         user_obj = Person.objects[0] | ||||
|         self.assertEqual(user_obj.name, "Test User") | ||||
|         assert user_obj.name == "Test User" | ||||
|  | ||||
|         Person.drop_collection() | ||||
|         self.assertNotIn(collection_name, list_collection_names(self.db)) | ||||
|         assert collection_name not in list_collection_names(self.db) | ||||
|  | ||||
|     def test_collection_name_and_primary(self): | ||||
|         """Ensure that a collection with a specified name may be used. | ||||
| @@ -365,7 +348,7 @@ class TestClassMethods(unittest.TestCase): | ||||
|         Person(name="Test User").save() | ||||
|  | ||||
|         user_obj = Person.objects.first() | ||||
|         self.assertEqual(user_obj.name, "Test User") | ||||
|         assert user_obj.name == "Test User" | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|   | ||||
| @@ -41,40 +41,40 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc.save() | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc._get_changed_fields(), []) | ||||
|         self.assertEqual(doc._delta(), ({}, {})) | ||||
|         assert doc._get_changed_fields() == [] | ||||
|         assert doc._delta() == ({}, {}) | ||||
|  | ||||
|         doc.string_field = "hello" | ||||
|         self.assertEqual(doc._get_changed_fields(), ["string_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"string_field": "hello"}, {})) | ||||
|         assert doc._get_changed_fields() == ["string_field"] | ||||
|         assert doc._delta() == ({"string_field": "hello"}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         doc.int_field = 1 | ||||
|         self.assertEqual(doc._get_changed_fields(), ["int_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"int_field": 1}, {})) | ||||
|         assert doc._get_changed_fields() == ["int_field"] | ||||
|         assert doc._delta() == ({"int_field": 1}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         dict_value = {"hello": "world", "ping": "pong"} | ||||
|         doc.dict_field = dict_value | ||||
|         self.assertEqual(doc._get_changed_fields(), ["dict_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"dict_field": dict_value}, {})) | ||||
|         assert doc._get_changed_fields() == ["dict_field"] | ||||
|         assert doc._delta() == ({"dict_field": dict_value}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         list_value = ["1", 2, {"hello": "world"}] | ||||
|         doc.list_field = list_value | ||||
|         self.assertEqual(doc._get_changed_fields(), ["list_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"list_field": list_value}, {})) | ||||
|         assert doc._get_changed_fields() == ["list_field"] | ||||
|         assert doc._delta() == ({"list_field": list_value}, {}) | ||||
|  | ||||
|         # Test unsetting | ||||
|         doc._changed_fields = [] | ||||
|         doc.dict_field = {} | ||||
|         self.assertEqual(doc._get_changed_fields(), ["dict_field"]) | ||||
|         self.assertEqual(doc._delta(), ({}, {"dict_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["dict_field"] | ||||
|         assert doc._delta() == ({}, {"dict_field": 1}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         doc.list_field = [] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["list_field"]) | ||||
|         self.assertEqual(doc._delta(), ({}, {"list_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["list_field"] | ||||
|         assert doc._delta() == ({}, {"list_field": 1}) | ||||
|  | ||||
|     def test_delta_recursive(self): | ||||
|         self.delta_recursive(Document, EmbeddedDocument) | ||||
| @@ -102,8 +102,8 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc.save() | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc._get_changed_fields(), []) | ||||
|         self.assertEqual(doc._delta(), ({}, {})) | ||||
|         assert doc._get_changed_fields() == [] | ||||
|         assert doc._delta() == ({}, {}) | ||||
|  | ||||
|         embedded_1 = Embedded() | ||||
|         embedded_1.id = "010101" | ||||
| @@ -113,7 +113,7 @@ class TestDelta(MongoDBTestCase): | ||||
|         embedded_1.list_field = ["1", 2, {"hello": "world"}] | ||||
|         doc.embedded_field = embedded_1 | ||||
|  | ||||
|         self.assertEqual(doc._get_changed_fields(), ["embedded_field"]) | ||||
|         assert doc._get_changed_fields() == ["embedded_field"] | ||||
|  | ||||
|         embedded_delta = { | ||||
|             "id": "010101", | ||||
| @@ -122,27 +122,27 @@ class TestDelta(MongoDBTestCase): | ||||
|             "dict_field": {"hello": "world"}, | ||||
|             "list_field": ["1", 2, {"hello": "world"}], | ||||
|         } | ||||
|         self.assertEqual(doc.embedded_field._delta(), (embedded_delta, {})) | ||||
|         self.assertEqual(doc._delta(), ({"embedded_field": embedded_delta}, {})) | ||||
|         assert doc.embedded_field._delta() == (embedded_delta, {}) | ||||
|         assert doc._delta() == ({"embedded_field": embedded_delta}, {}) | ||||
|  | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         doc.embedded_field.dict_field = {} | ||||
|         self.assertEqual(doc._get_changed_fields(), ["embedded_field.dict_field"]) | ||||
|         self.assertEqual(doc.embedded_field._delta(), ({}, {"dict_field": 1})) | ||||
|         self.assertEqual(doc._delta(), ({}, {"embedded_field.dict_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["embedded_field.dict_field"] | ||||
|         assert doc.embedded_field._delta() == ({}, {"dict_field": 1}) | ||||
|         assert doc._delta() == ({}, {"embedded_field.dict_field": 1}) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.dict_field, {}) | ||||
|         assert doc.embedded_field.dict_field == {} | ||||
|  | ||||
|         doc.embedded_field.list_field = [] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["embedded_field.list_field"]) | ||||
|         self.assertEqual(doc.embedded_field._delta(), ({}, {"list_field": 1})) | ||||
|         self.assertEqual(doc._delta(), ({}, {"embedded_field.list_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["embedded_field.list_field"] | ||||
|         assert doc.embedded_field._delta() == ({}, {"list_field": 1}) | ||||
|         assert doc._delta() == ({}, {"embedded_field.list_field": 1}) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.list_field, []) | ||||
|         assert doc.embedded_field.list_field == [] | ||||
|  | ||||
|         embedded_2 = Embedded() | ||||
|         embedded_2.string_field = "hello" | ||||
| @@ -151,148 +151,128 @@ class TestDelta(MongoDBTestCase): | ||||
|         embedded_2.list_field = ["1", 2, {"hello": "world"}] | ||||
|  | ||||
|         doc.embedded_field.list_field = ["1", 2, embedded_2] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["embedded_field.list_field"]) | ||||
|         assert doc._get_changed_fields() == ["embedded_field.list_field"] | ||||
|  | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "list_field": [ | ||||
|                         "1", | ||||
|                         2, | ||||
|                         { | ||||
|                             "_cls": "Embedded", | ||||
|                             "string_field": "hello", | ||||
|                             "dict_field": {"hello": "world"}, | ||||
|                             "int_field": 1, | ||||
|                             "list_field": ["1", 2, {"hello": "world"}], | ||||
|                         }, | ||||
|                     ] | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc.embedded_field._delta() == ( | ||||
|             { | ||||
|                 "list_field": [ | ||||
|                     "1", | ||||
|                     2, | ||||
|                     { | ||||
|                         "_cls": "Embedded", | ||||
|                         "string_field": "hello", | ||||
|                         "dict_field": {"hello": "world"}, | ||||
|                         "int_field": 1, | ||||
|                         "list_field": ["1", 2, {"hello": "world"}], | ||||
|                     }, | ||||
|                 ] | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "embedded_field.list_field": [ | ||||
|                         "1", | ||||
|                         2, | ||||
|                         { | ||||
|                             "_cls": "Embedded", | ||||
|                             "string_field": "hello", | ||||
|                             "dict_field": {"hello": "world"}, | ||||
|                             "int_field": 1, | ||||
|                             "list_field": ["1", 2, {"hello": "world"}], | ||||
|                         }, | ||||
|                     ] | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             { | ||||
|                 "embedded_field.list_field": [ | ||||
|                     "1", | ||||
|                     2, | ||||
|                     { | ||||
|                         "_cls": "Embedded", | ||||
|                         "string_field": "hello", | ||||
|                         "dict_field": {"hello": "world"}, | ||||
|                         "int_field": 1, | ||||
|                         "list_field": ["1", 2, {"hello": "world"}], | ||||
|                     }, | ||||
|                 ] | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         self.assertEqual(doc.embedded_field.list_field[0], "1") | ||||
|         self.assertEqual(doc.embedded_field.list_field[1], 2) | ||||
|         assert doc.embedded_field.list_field[0] == "1" | ||||
|         assert doc.embedded_field.list_field[1] == 2 | ||||
|         for k in doc.embedded_field.list_field[2]._fields: | ||||
|             self.assertEqual(doc.embedded_field.list_field[2][k], embedded_2[k]) | ||||
|             assert doc.embedded_field.list_field[2][k] == embedded_2[k] | ||||
|  | ||||
|         doc.embedded_field.list_field[2].string_field = "world" | ||||
|         self.assertEqual( | ||||
|             doc._get_changed_fields(), ["embedded_field.list_field.2.string_field"] | ||||
|         assert doc._get_changed_fields() == ["embedded_field.list_field.2.string_field"] | ||||
|         assert doc.embedded_field._delta() == ( | ||||
|             {"list_field.2.string_field": "world"}, | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field._delta(), ({"list_field.2.string_field": "world"}, {}) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), ({"embedded_field.list_field.2.string_field": "world"}, {}) | ||||
|         assert doc._delta() == ( | ||||
|             {"embedded_field.list_field.2.string_field": "world"}, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.list_field[2].string_field, "world") | ||||
|         assert doc.embedded_field.list_field[2].string_field == "world" | ||||
|  | ||||
|         # Test multiple assignments | ||||
|         doc.embedded_field.list_field[2].string_field = "hello world" | ||||
|         doc.embedded_field.list_field[2] = doc.embedded_field.list_field[2] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["embedded_field.list_field.2"]) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "list_field.2": { | ||||
|                         "_cls": "Embedded", | ||||
|                         "string_field": "hello world", | ||||
|                         "int_field": 1, | ||||
|                         "list_field": ["1", 2, {"hello": "world"}], | ||||
|                         "dict_field": {"hello": "world"}, | ||||
|                     } | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._get_changed_fields() == ["embedded_field.list_field.2"] | ||||
|         assert doc.embedded_field._delta() == ( | ||||
|             { | ||||
|                 "list_field.2": { | ||||
|                     "_cls": "Embedded", | ||||
|                     "string_field": "hello world", | ||||
|                     "int_field": 1, | ||||
|                     "list_field": ["1", 2, {"hello": "world"}], | ||||
|                     "dict_field": {"hello": "world"}, | ||||
|                 } | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "embedded_field.list_field.2": { | ||||
|                         "_cls": "Embedded", | ||||
|                         "string_field": "hello world", | ||||
|                         "int_field": 1, | ||||
|                         "list_field": ["1", 2, {"hello": "world"}], | ||||
|                         "dict_field": {"hello": "world"}, | ||||
|                     } | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             { | ||||
|                 "embedded_field.list_field.2": { | ||||
|                     "_cls": "Embedded", | ||||
|                     "string_field": "hello world", | ||||
|                     "int_field": 1, | ||||
|                     "list_field": ["1", 2, {"hello": "world"}], | ||||
|                     "dict_field": {"hello": "world"}, | ||||
|                 } | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.list_field[2].string_field, "hello world") | ||||
|         assert doc.embedded_field.list_field[2].string_field == "hello world" | ||||
|  | ||||
|         # Test list native methods | ||||
|         doc.embedded_field.list_field[2].list_field.pop(0) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ({"embedded_field.list_field.2.list_field": [2, {"hello": "world"}]}, {}), | ||||
|         assert doc._delta() == ( | ||||
|             {"embedded_field.list_field.2.list_field": [2, {"hello": "world"}]}, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         doc.embedded_field.list_field[2].list_field.append(1) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 {"embedded_field.list_field.2.list_field": [2, {"hello": "world"}, 1]}, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             {"embedded_field.list_field.2.list_field": [2, {"hello": "world"}, 1]}, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field.list_field[2].list_field, [2, {"hello": "world"}, 1] | ||||
|         ) | ||||
|         assert doc.embedded_field.list_field[2].list_field == [2, {"hello": "world"}, 1] | ||||
|  | ||||
|         doc.embedded_field.list_field[2].list_field.sort(key=str) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field.list_field[2].list_field, [1, 2, {"hello": "world"}] | ||||
|         ) | ||||
|         assert doc.embedded_field.list_field[2].list_field == [1, 2, {"hello": "world"}] | ||||
|  | ||||
|         del doc.embedded_field.list_field[2].list_field[2]["hello"] | ||||
|         self.assertEqual( | ||||
|             doc._delta(), ({}, {"embedded_field.list_field.2.list_field.2.hello": 1}) | ||||
|         assert doc._delta() == ( | ||||
|             {}, | ||||
|             {"embedded_field.list_field.2.list_field.2.hello": 1}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         del doc.embedded_field.list_field[2].list_field | ||||
|         self.assertEqual( | ||||
|             doc._delta(), ({}, {"embedded_field.list_field.2.list_field": 1}) | ||||
|         ) | ||||
|         assert doc._delta() == ({}, {"embedded_field.list_field.2.list_field": 1}) | ||||
|  | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
| @@ -302,12 +282,8 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         doc.dict_field["Embedded"].string_field = "Hello World" | ||||
|         self.assertEqual( | ||||
|             doc._get_changed_fields(), ["dict_field.Embedded.string_field"] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), ({"dict_field.Embedded.string_field": "Hello World"}, {}) | ||||
|         ) | ||||
|         assert doc._get_changed_fields() == ["dict_field.Embedded.string_field"] | ||||
|         assert doc._delta() == ({"dict_field.Embedded.string_field": "Hello World"}, {}) | ||||
|  | ||||
|     def test_circular_reference_deltas(self): | ||||
|         self.circular_reference_deltas(Document, Document) | ||||
| @@ -338,8 +314,8 @@ class TestDelta(MongoDBTestCase): | ||||
|  | ||||
|         p = Person.objects[0].select_related() | ||||
|         o = Organization.objects.first() | ||||
|         self.assertEqual(p.owns[0], o) | ||||
|         self.assertEqual(o.owner, p) | ||||
|         assert p.owns[0] == o | ||||
|         assert o.owner == p | ||||
|  | ||||
|     def test_circular_reference_deltas_2(self): | ||||
|         self.circular_reference_deltas_2(Document, Document) | ||||
| @@ -379,9 +355,9 @@ class TestDelta(MongoDBTestCase): | ||||
|         e = Person.objects.get(name="employee") | ||||
|         o = Organization.objects.first() | ||||
|  | ||||
|         self.assertEqual(p.owns[0], o) | ||||
|         self.assertEqual(o.owner, p) | ||||
|         self.assertEqual(e.employer, o) | ||||
|         assert p.owns[0] == o | ||||
|         assert o.owner == p | ||||
|         assert e.employer == o | ||||
|  | ||||
|         return person, organization, employee | ||||
|  | ||||
| @@ -401,40 +377,40 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc.save() | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc._get_changed_fields(), []) | ||||
|         self.assertEqual(doc._delta(), ({}, {})) | ||||
|         assert doc._get_changed_fields() == [] | ||||
|         assert doc._delta() == ({}, {}) | ||||
|  | ||||
|         doc.string_field = "hello" | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_string_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"db_string_field": "hello"}, {})) | ||||
|         assert doc._get_changed_fields() == ["db_string_field"] | ||||
|         assert doc._delta() == ({"db_string_field": "hello"}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         doc.int_field = 1 | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_int_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"db_int_field": 1}, {})) | ||||
|         assert doc._get_changed_fields() == ["db_int_field"] | ||||
|         assert doc._delta() == ({"db_int_field": 1}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         dict_value = {"hello": "world", "ping": "pong"} | ||||
|         doc.dict_field = dict_value | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_dict_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"db_dict_field": dict_value}, {})) | ||||
|         assert doc._get_changed_fields() == ["db_dict_field"] | ||||
|         assert doc._delta() == ({"db_dict_field": dict_value}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         list_value = ["1", 2, {"hello": "world"}] | ||||
|         doc.list_field = list_value | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_list_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"db_list_field": list_value}, {})) | ||||
|         assert doc._get_changed_fields() == ["db_list_field"] | ||||
|         assert doc._delta() == ({"db_list_field": list_value}, {}) | ||||
|  | ||||
|         # Test unsetting | ||||
|         doc._changed_fields = [] | ||||
|         doc.dict_field = {} | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_dict_field"]) | ||||
|         self.assertEqual(doc._delta(), ({}, {"db_dict_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["db_dict_field"] | ||||
|         assert doc._delta() == ({}, {"db_dict_field": 1}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         doc.list_field = [] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_list_field"]) | ||||
|         self.assertEqual(doc._delta(), ({}, {"db_list_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["db_list_field"] | ||||
|         assert doc._delta() == ({}, {"db_list_field": 1}) | ||||
|  | ||||
|         # Test it saves that data | ||||
|         doc = Doc() | ||||
| @@ -447,10 +423,10 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         self.assertEqual(doc.string_field, "hello") | ||||
|         self.assertEqual(doc.int_field, 1) | ||||
|         self.assertEqual(doc.dict_field, {"hello": "world"}) | ||||
|         self.assertEqual(doc.list_field, ["1", 2, {"hello": "world"}]) | ||||
|         assert doc.string_field == "hello" | ||||
|         assert doc.int_field == 1 | ||||
|         assert doc.dict_field == {"hello": "world"} | ||||
|         assert doc.list_field == ["1", 2, {"hello": "world"}] | ||||
|  | ||||
|     def test_delta_recursive_db_field(self): | ||||
|         self.delta_recursive_db_field(Document, EmbeddedDocument) | ||||
| @@ -479,8 +455,8 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc.save() | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc._get_changed_fields(), []) | ||||
|         self.assertEqual(doc._delta(), ({}, {})) | ||||
|         assert doc._get_changed_fields() == [] | ||||
|         assert doc._delta() == ({}, {}) | ||||
|  | ||||
|         embedded_1 = Embedded() | ||||
|         embedded_1.string_field = "hello" | ||||
| @@ -489,7 +465,7 @@ class TestDelta(MongoDBTestCase): | ||||
|         embedded_1.list_field = ["1", 2, {"hello": "world"}] | ||||
|         doc.embedded_field = embedded_1 | ||||
|  | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_embedded_field"]) | ||||
|         assert doc._get_changed_fields() == ["db_embedded_field"] | ||||
|  | ||||
|         embedded_delta = { | ||||
|             "db_string_field": "hello", | ||||
| @@ -497,27 +473,27 @@ class TestDelta(MongoDBTestCase): | ||||
|             "db_dict_field": {"hello": "world"}, | ||||
|             "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|         } | ||||
|         self.assertEqual(doc.embedded_field._delta(), (embedded_delta, {})) | ||||
|         self.assertEqual(doc._delta(), ({"db_embedded_field": embedded_delta}, {})) | ||||
|         assert doc.embedded_field._delta() == (embedded_delta, {}) | ||||
|         assert doc._delta() == ({"db_embedded_field": embedded_delta}, {}) | ||||
|  | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         doc.embedded_field.dict_field = {} | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_embedded_field.db_dict_field"]) | ||||
|         self.assertEqual(doc.embedded_field._delta(), ({}, {"db_dict_field": 1})) | ||||
|         self.assertEqual(doc._delta(), ({}, {"db_embedded_field.db_dict_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["db_embedded_field.db_dict_field"] | ||||
|         assert doc.embedded_field._delta() == ({}, {"db_dict_field": 1}) | ||||
|         assert doc._delta() == ({}, {"db_embedded_field.db_dict_field": 1}) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.dict_field, {}) | ||||
|         assert doc.embedded_field.dict_field == {} | ||||
|  | ||||
|         doc.embedded_field.list_field = [] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_embedded_field.db_list_field"]) | ||||
|         self.assertEqual(doc.embedded_field._delta(), ({}, {"db_list_field": 1})) | ||||
|         self.assertEqual(doc._delta(), ({}, {"db_embedded_field.db_list_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["db_embedded_field.db_list_field"] | ||||
|         assert doc.embedded_field._delta() == ({}, {"db_list_field": 1}) | ||||
|         assert doc._delta() == ({}, {"db_embedded_field.db_list_field": 1}) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.list_field, []) | ||||
|         assert doc.embedded_field.list_field == [] | ||||
|  | ||||
|         embedded_2 = Embedded() | ||||
|         embedded_2.string_field = "hello" | ||||
| @@ -526,166 +502,142 @@ class TestDelta(MongoDBTestCase): | ||||
|         embedded_2.list_field = ["1", 2, {"hello": "world"}] | ||||
|  | ||||
|         doc.embedded_field.list_field = ["1", 2, embedded_2] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["db_embedded_field.db_list_field"]) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "db_list_field": [ | ||||
|                         "1", | ||||
|                         2, | ||||
|                         { | ||||
|                             "_cls": "Embedded", | ||||
|                             "db_string_field": "hello", | ||||
|                             "db_dict_field": {"hello": "world"}, | ||||
|                             "db_int_field": 1, | ||||
|                             "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                         }, | ||||
|                     ] | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._get_changed_fields() == ["db_embedded_field.db_list_field"] | ||||
|         assert doc.embedded_field._delta() == ( | ||||
|             { | ||||
|                 "db_list_field": [ | ||||
|                     "1", | ||||
|                     2, | ||||
|                     { | ||||
|                         "_cls": "Embedded", | ||||
|                         "db_string_field": "hello", | ||||
|                         "db_dict_field": {"hello": "world"}, | ||||
|                         "db_int_field": 1, | ||||
|                         "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                     }, | ||||
|                 ] | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "db_embedded_field.db_list_field": [ | ||||
|                         "1", | ||||
|                         2, | ||||
|                         { | ||||
|                             "_cls": "Embedded", | ||||
|                             "db_string_field": "hello", | ||||
|                             "db_dict_field": {"hello": "world"}, | ||||
|                             "db_int_field": 1, | ||||
|                             "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                         }, | ||||
|                     ] | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             { | ||||
|                 "db_embedded_field.db_list_field": [ | ||||
|                     "1", | ||||
|                     2, | ||||
|                     { | ||||
|                         "_cls": "Embedded", | ||||
|                         "db_string_field": "hello", | ||||
|                         "db_dict_field": {"hello": "world"}, | ||||
|                         "db_int_field": 1, | ||||
|                         "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                     }, | ||||
|                 ] | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         self.assertEqual(doc.embedded_field.list_field[0], "1") | ||||
|         self.assertEqual(doc.embedded_field.list_field[1], 2) | ||||
|         assert doc.embedded_field.list_field[0] == "1" | ||||
|         assert doc.embedded_field.list_field[1] == 2 | ||||
|         for k in doc.embedded_field.list_field[2]._fields: | ||||
|             self.assertEqual(doc.embedded_field.list_field[2][k], embedded_2[k]) | ||||
|             assert doc.embedded_field.list_field[2][k] == embedded_2[k] | ||||
|  | ||||
|         doc.embedded_field.list_field[2].string_field = "world" | ||||
|         self.assertEqual( | ||||
|             doc._get_changed_fields(), | ||||
|             ["db_embedded_field.db_list_field.2.db_string_field"], | ||||
|         assert doc._get_changed_fields() == [ | ||||
|             "db_embedded_field.db_list_field.2.db_string_field" | ||||
|         ] | ||||
|         assert doc.embedded_field._delta() == ( | ||||
|             {"db_list_field.2.db_string_field": "world"}, | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field._delta(), | ||||
|             ({"db_list_field.2.db_string_field": "world"}, {}), | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ({"db_embedded_field.db_list_field.2.db_string_field": "world"}, {}), | ||||
|         assert doc._delta() == ( | ||||
|             {"db_embedded_field.db_list_field.2.db_string_field": "world"}, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.list_field[2].string_field, "world") | ||||
|         assert doc.embedded_field.list_field[2].string_field == "world" | ||||
|  | ||||
|         # Test multiple assignments | ||||
|         doc.embedded_field.list_field[2].string_field = "hello world" | ||||
|         doc.embedded_field.list_field[2] = doc.embedded_field.list_field[2] | ||||
|         self.assertEqual( | ||||
|             doc._get_changed_fields(), ["db_embedded_field.db_list_field.2"] | ||||
|         assert doc._get_changed_fields() == ["db_embedded_field.db_list_field.2"] | ||||
|         assert doc.embedded_field._delta() == ( | ||||
|             { | ||||
|                 "db_list_field.2": { | ||||
|                     "_cls": "Embedded", | ||||
|                     "db_string_field": "hello world", | ||||
|                     "db_int_field": 1, | ||||
|                     "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                     "db_dict_field": {"hello": "world"}, | ||||
|                 } | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "db_list_field.2": { | ||||
|                         "_cls": "Embedded", | ||||
|                         "db_string_field": "hello world", | ||||
|                         "db_int_field": 1, | ||||
|                         "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                         "db_dict_field": {"hello": "world"}, | ||||
|                     } | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "db_embedded_field.db_list_field.2": { | ||||
|                         "_cls": "Embedded", | ||||
|                         "db_string_field": "hello world", | ||||
|                         "db_int_field": 1, | ||||
|                         "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                         "db_dict_field": {"hello": "world"}, | ||||
|                     } | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             { | ||||
|                 "db_embedded_field.db_list_field.2": { | ||||
|                     "_cls": "Embedded", | ||||
|                     "db_string_field": "hello world", | ||||
|                     "db_int_field": 1, | ||||
|                     "db_list_field": ["1", 2, {"hello": "world"}], | ||||
|                     "db_dict_field": {"hello": "world"}, | ||||
|                 } | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual(doc.embedded_field.list_field[2].string_field, "hello world") | ||||
|         assert doc.embedded_field.list_field[2].string_field == "hello world" | ||||
|  | ||||
|         # Test list native methods | ||||
|         doc.embedded_field.list_field[2].list_field.pop(0) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "db_embedded_field.db_list_field.2.db_list_field": [ | ||||
|                         2, | ||||
|                         {"hello": "world"}, | ||||
|                     ] | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             { | ||||
|                 "db_embedded_field.db_list_field.2.db_list_field": [ | ||||
|                     2, | ||||
|                     {"hello": "world"}, | ||||
|                 ] | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         doc.embedded_field.list_field[2].list_field.append(1) | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ( | ||||
|                 { | ||||
|                     "db_embedded_field.db_list_field.2.db_list_field": [ | ||||
|                         2, | ||||
|                         {"hello": "world"}, | ||||
|                         1, | ||||
|                     ] | ||||
|                 }, | ||||
|                 {}, | ||||
|             ), | ||||
|         assert doc._delta() == ( | ||||
|             { | ||||
|                 "db_embedded_field.db_list_field.2.db_list_field": [ | ||||
|                     2, | ||||
|                     {"hello": "world"}, | ||||
|                     1, | ||||
|                 ] | ||||
|             }, | ||||
|             {}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field.list_field[2].list_field, [2, {"hello": "world"}, 1] | ||||
|         ) | ||||
|         assert doc.embedded_field.list_field[2].list_field == [2, {"hello": "world"}, 1] | ||||
|  | ||||
|         doc.embedded_field.list_field[2].list_field.sort(key=str) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|         self.assertEqual( | ||||
|             doc.embedded_field.list_field[2].list_field, [1, 2, {"hello": "world"}] | ||||
|         ) | ||||
|         assert doc.embedded_field.list_field[2].list_field == [1, 2, {"hello": "world"}] | ||||
|  | ||||
|         del doc.embedded_field.list_field[2].list_field[2]["hello"] | ||||
|         self.assertEqual( | ||||
|             doc._delta(), | ||||
|             ({}, {"db_embedded_field.db_list_field.2.db_list_field.2.hello": 1}), | ||||
|         assert doc._delta() == ( | ||||
|             {}, | ||||
|             {"db_embedded_field.db_list_field.2.db_list_field.2.hello": 1}, | ||||
|         ) | ||||
|         doc.save() | ||||
|         doc = doc.reload(10) | ||||
|  | ||||
|         del doc.embedded_field.list_field[2].list_field | ||||
|         self.assertEqual( | ||||
|             doc._delta(), ({}, {"db_embedded_field.db_list_field.2.db_list_field": 1}) | ||||
|         assert doc._delta() == ( | ||||
|             {}, | ||||
|             {"db_embedded_field.db_list_field.2.db_list_field": 1}, | ||||
|         ) | ||||
|  | ||||
|     def test_delta_for_dynamic_documents(self): | ||||
| @@ -696,14 +648,16 @@ class TestDelta(MongoDBTestCase): | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p = Person(name="James", age=34) | ||||
|         self.assertEqual( | ||||
|             p._delta(), (SON([("_cls", "Person"), ("name", "James"), ("age", 34)]), {}) | ||||
|         assert p._delta() == ( | ||||
|             SON([("_cls", "Person"), ("name", "James"), ("age", 34)]), | ||||
|             {}, | ||||
|         ) | ||||
|  | ||||
|         p.doc = 123 | ||||
|         del p.doc | ||||
|         self.assertEqual( | ||||
|             p._delta(), (SON([("_cls", "Person"), ("name", "James"), ("age", 34)]), {}) | ||||
|         assert p._delta() == ( | ||||
|             SON([("_cls", "Person"), ("name", "James"), ("age", 34)]), | ||||
|             {}, | ||||
|         ) | ||||
|  | ||||
|         p = Person() | ||||
| @@ -712,18 +666,18 @@ class TestDelta(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         p.age = 24 | ||||
|         self.assertEqual(p.age, 24) | ||||
|         self.assertEqual(p._get_changed_fields(), ["age"]) | ||||
|         self.assertEqual(p._delta(), ({"age": 24}, {})) | ||||
|         assert p.age == 24 | ||||
|         assert p._get_changed_fields() == ["age"] | ||||
|         assert p._delta() == ({"age": 24}, {}) | ||||
|  | ||||
|         p = Person.objects(age=22).get() | ||||
|         p.age = 24 | ||||
|         self.assertEqual(p.age, 24) | ||||
|         self.assertEqual(p._get_changed_fields(), ["age"]) | ||||
|         self.assertEqual(p._delta(), ({"age": 24}, {})) | ||||
|         assert p.age == 24 | ||||
|         assert p._get_changed_fields() == ["age"] | ||||
|         assert p._delta() == ({"age": 24}, {}) | ||||
|  | ||||
|         p.save() | ||||
|         self.assertEqual(1, Person.objects(age=24).count()) | ||||
|         assert 1 == Person.objects(age=24).count() | ||||
|  | ||||
|     def test_dynamic_delta(self): | ||||
|         class Doc(DynamicDocument): | ||||
| @@ -734,40 +688,40 @@ class TestDelta(MongoDBTestCase): | ||||
|         doc.save() | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc._get_changed_fields(), []) | ||||
|         self.assertEqual(doc._delta(), ({}, {})) | ||||
|         assert doc._get_changed_fields() == [] | ||||
|         assert doc._delta() == ({}, {}) | ||||
|  | ||||
|         doc.string_field = "hello" | ||||
|         self.assertEqual(doc._get_changed_fields(), ["string_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"string_field": "hello"}, {})) | ||||
|         assert doc._get_changed_fields() == ["string_field"] | ||||
|         assert doc._delta() == ({"string_field": "hello"}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         doc.int_field = 1 | ||||
|         self.assertEqual(doc._get_changed_fields(), ["int_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"int_field": 1}, {})) | ||||
|         assert doc._get_changed_fields() == ["int_field"] | ||||
|         assert doc._delta() == ({"int_field": 1}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         dict_value = {"hello": "world", "ping": "pong"} | ||||
|         doc.dict_field = dict_value | ||||
|         self.assertEqual(doc._get_changed_fields(), ["dict_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"dict_field": dict_value}, {})) | ||||
|         assert doc._get_changed_fields() == ["dict_field"] | ||||
|         assert doc._delta() == ({"dict_field": dict_value}, {}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         list_value = ["1", 2, {"hello": "world"}] | ||||
|         doc.list_field = list_value | ||||
|         self.assertEqual(doc._get_changed_fields(), ["list_field"]) | ||||
|         self.assertEqual(doc._delta(), ({"list_field": list_value}, {})) | ||||
|         assert doc._get_changed_fields() == ["list_field"] | ||||
|         assert doc._delta() == ({"list_field": list_value}, {}) | ||||
|  | ||||
|         # Test unsetting | ||||
|         doc._changed_fields = [] | ||||
|         doc.dict_field = {} | ||||
|         self.assertEqual(doc._get_changed_fields(), ["dict_field"]) | ||||
|         self.assertEqual(doc._delta(), ({}, {"dict_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["dict_field"] | ||||
|         assert doc._delta() == ({}, {"dict_field": 1}) | ||||
|  | ||||
|         doc._changed_fields = [] | ||||
|         doc.list_field = [] | ||||
|         self.assertEqual(doc._get_changed_fields(), ["list_field"]) | ||||
|         self.assertEqual(doc._delta(), ({}, {"list_field": 1})) | ||||
|         assert doc._get_changed_fields() == ["list_field"] | ||||
|         assert doc._delta() == ({}, {"list_field": 1}) | ||||
|  | ||||
|     def test_delta_with_dbref_true(self): | ||||
|         person, organization, employee = self.circular_reference_deltas_2( | ||||
| @@ -775,16 +729,16 @@ class TestDelta(MongoDBTestCase): | ||||
|         ) | ||||
|         employee.name = "test" | ||||
|  | ||||
|         self.assertEqual(organization._get_changed_fields(), []) | ||||
|         assert organization._get_changed_fields() == [] | ||||
|  | ||||
|         updates, removals = organization._delta() | ||||
|         self.assertEqual({}, removals) | ||||
|         self.assertEqual({}, updates) | ||||
|         assert {} == removals | ||||
|         assert {} == updates | ||||
|  | ||||
|         organization.employees.append(person) | ||||
|         updates, removals = organization._delta() | ||||
|         self.assertEqual({}, removals) | ||||
|         self.assertIn("employees", updates) | ||||
|         assert {} == removals | ||||
|         assert "employees" in updates | ||||
|  | ||||
|     def test_delta_with_dbref_false(self): | ||||
|         person, organization, employee = self.circular_reference_deltas_2( | ||||
| @@ -792,16 +746,16 @@ class TestDelta(MongoDBTestCase): | ||||
|         ) | ||||
|         employee.name = "test" | ||||
|  | ||||
|         self.assertEqual(organization._get_changed_fields(), []) | ||||
|         assert organization._get_changed_fields() == [] | ||||
|  | ||||
|         updates, removals = organization._delta() | ||||
|         self.assertEqual({}, removals) | ||||
|         self.assertEqual({}, updates) | ||||
|         assert {} == removals | ||||
|         assert {} == updates | ||||
|  | ||||
|         organization.employees.append(person) | ||||
|         updates, removals = organization._delta() | ||||
|         self.assertEqual({}, removals) | ||||
|         self.assertIn("employees", updates) | ||||
|         assert {} == removals | ||||
|         assert "employees" in updates | ||||
|  | ||||
|     def test_nested_nested_fields_mark_as_changed(self): | ||||
|         class EmbeddedDoc(EmbeddedDocument): | ||||
| @@ -821,11 +775,11 @@ class TestDelta(MongoDBTestCase): | ||||
|         subdoc = mydoc.subs["a"]["b"] | ||||
|         subdoc.name = "bar" | ||||
|  | ||||
|         self.assertEqual(["name"], subdoc._get_changed_fields()) | ||||
|         self.assertEqual(["subs.a.b.name"], mydoc._get_changed_fields()) | ||||
|         assert ["name"] == subdoc._get_changed_fields() | ||||
|         assert ["subs.a.b.name"] == mydoc._get_changed_fields() | ||||
|  | ||||
|         mydoc._clear_changed_fields() | ||||
|         self.assertEqual([], mydoc._get_changed_fields()) | ||||
|         assert [] == mydoc._get_changed_fields() | ||||
|  | ||||
|     def test_lower_level_mark_as_changed(self): | ||||
|         class EmbeddedDoc(EmbeddedDocument): | ||||
| @@ -840,17 +794,17 @@ class TestDelta(MongoDBTestCase): | ||||
|  | ||||
|         mydoc = MyDoc.objects.first() | ||||
|         mydoc.subs["a"] = EmbeddedDoc() | ||||
|         self.assertEqual(["subs.a"], mydoc._get_changed_fields()) | ||||
|         assert ["subs.a"] == mydoc._get_changed_fields() | ||||
|  | ||||
|         subdoc = mydoc.subs["a"] | ||||
|         subdoc.name = "bar" | ||||
|  | ||||
|         self.assertEqual(["name"], subdoc._get_changed_fields()) | ||||
|         self.assertEqual(["subs.a"], mydoc._get_changed_fields()) | ||||
|         assert ["name"] == subdoc._get_changed_fields() | ||||
|         assert ["subs.a"] == mydoc._get_changed_fields() | ||||
|         mydoc.save() | ||||
|  | ||||
|         mydoc._clear_changed_fields() | ||||
|         self.assertEqual([], mydoc._get_changed_fields()) | ||||
|         assert [] == mydoc._get_changed_fields() | ||||
|  | ||||
|     def test_upper_level_mark_as_changed(self): | ||||
|         class EmbeddedDoc(EmbeddedDocument): | ||||
| @@ -867,15 +821,15 @@ class TestDelta(MongoDBTestCase): | ||||
|         subdoc = mydoc.subs["a"] | ||||
|         subdoc.name = "bar" | ||||
|  | ||||
|         self.assertEqual(["name"], subdoc._get_changed_fields()) | ||||
|         self.assertEqual(["subs.a.name"], mydoc._get_changed_fields()) | ||||
|         assert ["name"] == subdoc._get_changed_fields() | ||||
|         assert ["subs.a.name"] == mydoc._get_changed_fields() | ||||
|  | ||||
|         mydoc.subs["a"] = EmbeddedDoc() | ||||
|         self.assertEqual(["subs.a"], mydoc._get_changed_fields()) | ||||
|         assert ["subs.a"] == mydoc._get_changed_fields() | ||||
|         mydoc.save() | ||||
|  | ||||
|         mydoc._clear_changed_fields() | ||||
|         self.assertEqual([], mydoc._get_changed_fields()) | ||||
|         assert [] == mydoc._get_changed_fields() | ||||
|  | ||||
|     def test_referenced_object_changed_attributes(self): | ||||
|         """Ensures that when you save a new reference to a field, the referenced object isn't altered""" | ||||
| @@ -902,22 +856,22 @@ class TestDelta(MongoDBTestCase): | ||||
|         org1.reload() | ||||
|         org2.reload() | ||||
|         user.reload() | ||||
|         self.assertEqual(org1.name, "Org 1") | ||||
|         self.assertEqual(org2.name, "Org 2") | ||||
|         self.assertEqual(user.name, "Fred") | ||||
|         assert org1.name == "Org 1" | ||||
|         assert org2.name == "Org 2" | ||||
|         assert user.name == "Fred" | ||||
|  | ||||
|         user.name = "Harold" | ||||
|         user.org = org2 | ||||
|  | ||||
|         org2.name = "New Org 2" | ||||
|         self.assertEqual(org2.name, "New Org 2") | ||||
|         assert org2.name == "New Org 2" | ||||
|  | ||||
|         user.save() | ||||
|         org2.save() | ||||
|  | ||||
|         self.assertEqual(org2.name, "New Org 2") | ||||
|         assert org2.name == "New Org 2" | ||||
|         org2.reload() | ||||
|         self.assertEqual(org2.name, "New Org 2") | ||||
|         assert org2.name == "New Org 2" | ||||
|  | ||||
|     def test_delta_for_nested_map_fields(self): | ||||
|         class UInfoDocument(Document): | ||||
| @@ -950,12 +904,12 @@ class TestDelta(MongoDBTestCase): | ||||
|         d.users["007"]["rolist"].append(EmbeddedRole(type="oops")) | ||||
|         d.users["007"]["info"] = uinfo | ||||
|         delta = d._delta() | ||||
|         self.assertEqual(True, "users.007.roles.666" in delta[0]) | ||||
|         self.assertEqual(True, "users.007.rolist" in delta[0]) | ||||
|         self.assertEqual(True, "users.007.info" in delta[0]) | ||||
|         self.assertEqual("superadmin", delta[0]["users.007.roles.666"]["type"]) | ||||
|         self.assertEqual("oops", delta[0]["users.007.rolist"][0]["type"]) | ||||
|         self.assertEqual(uinfo.id, delta[0]["users.007.info"]) | ||||
|         assert True == ("users.007.roles.666" in delta[0]) | ||||
|         assert True == ("users.007.rolist" in delta[0]) | ||||
|         assert True == ("users.007.info" in delta[0]) | ||||
|         assert "superadmin" == delta[0]["users.007.roles.666"]["type"] | ||||
|         assert "oops" == delta[0]["users.007.rolist"][0]["type"] | ||||
|         assert uinfo.id == delta[0]["users.007.info"] | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| import unittest | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
| @@ -25,15 +27,15 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.name = "James" | ||||
|         p.age = 34 | ||||
|  | ||||
|         self.assertEqual(p.to_mongo(), {"_cls": "Person", "name": "James", "age": 34}) | ||||
|         self.assertEqual(p.to_mongo().keys(), ["_cls", "name", "age"]) | ||||
|         assert p.to_mongo() == {"_cls": "Person", "name": "James", "age": 34} | ||||
|         assert p.to_mongo().keys() == ["_cls", "name", "age"] | ||||
|         p.save() | ||||
|         self.assertEqual(p.to_mongo().keys(), ["_id", "_cls", "name", "age"]) | ||||
|         assert p.to_mongo().keys() == ["_id", "_cls", "name", "age"] | ||||
|  | ||||
|         self.assertEqual(self.Person.objects.first().age, 34) | ||||
|         assert self.Person.objects.first().age == 34 | ||||
|  | ||||
|         # Confirm no changes to self.Person | ||||
|         self.assertFalse(hasattr(self.Person, "age")) | ||||
|         assert not hasattr(self.Person, "age") | ||||
|  | ||||
|     def test_change_scope_of_variable(self): | ||||
|         """Test changing the scope of a dynamic field has no adverse effects""" | ||||
| @@ -47,7 +49,7 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         p = self.Person.objects.get() | ||||
|         self.assertEqual(p.misc, {"hello": "world"}) | ||||
|         assert p.misc == {"hello": "world"} | ||||
|  | ||||
|     def test_delete_dynamic_field(self): | ||||
|         """Test deleting a dynamic field works""" | ||||
| @@ -62,19 +64,19 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         p = self.Person.objects.get() | ||||
|         self.assertEqual(p.misc, {"hello": "world"}) | ||||
|         assert p.misc == {"hello": "world"} | ||||
|         collection = self.db[self.Person._get_collection_name()] | ||||
|         obj = collection.find_one() | ||||
|         self.assertEqual(sorted(obj.keys()), ["_cls", "_id", "misc", "name"]) | ||||
|         assert sorted(obj.keys()) == ["_cls", "_id", "misc", "name"] | ||||
|  | ||||
|         del p.misc | ||||
|         p.save() | ||||
|  | ||||
|         p = self.Person.objects.get() | ||||
|         self.assertFalse(hasattr(p, "misc")) | ||||
|         assert not hasattr(p, "misc") | ||||
|  | ||||
|         obj = collection.find_one() | ||||
|         self.assertEqual(sorted(obj.keys()), ["_cls", "_id", "name"]) | ||||
|         assert sorted(obj.keys()) == ["_cls", "_id", "name"] | ||||
|  | ||||
|     def test_reload_after_unsetting(self): | ||||
|         p = self.Person() | ||||
| @@ -88,12 +90,12 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p = self.Person.objects.create() | ||||
|         p.update(age=1) | ||||
|  | ||||
|         self.assertEqual(len(p._data), 3) | ||||
|         self.assertEqual(sorted(p._data.keys()), ["_cls", "id", "name"]) | ||||
|         assert len(p._data) == 3 | ||||
|         assert sorted(p._data.keys()) == ["_cls", "id", "name"] | ||||
|  | ||||
|         p.reload() | ||||
|         self.assertEqual(len(p._data), 4) | ||||
|         self.assertEqual(sorted(p._data.keys()), ["_cls", "age", "id", "name"]) | ||||
|         assert len(p._data) == 4 | ||||
|         assert sorted(p._data.keys()) == ["_cls", "age", "id", "name"] | ||||
|  | ||||
|     def test_fields_without_underscore(self): | ||||
|         """Ensure we can query dynamic fields""" | ||||
| @@ -103,16 +105,18 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         raw_p = Person.objects.as_pymongo().get(id=p.id) | ||||
|         self.assertEqual(raw_p, {"_cls": u"Person", "_id": p.id, "name": u"Dean"}) | ||||
|         assert raw_p == {"_cls": u"Person", "_id": p.id, "name": u"Dean"} | ||||
|  | ||||
|         p.name = "OldDean" | ||||
|         p.newattr = "garbage" | ||||
|         p.save() | ||||
|         raw_p = Person.objects.as_pymongo().get(id=p.id) | ||||
|         self.assertEqual( | ||||
|             raw_p, | ||||
|             {"_cls": u"Person", "_id": p.id, "name": "OldDean", "newattr": u"garbage"}, | ||||
|         ) | ||||
|         assert raw_p == { | ||||
|             "_cls": u"Person", | ||||
|             "_id": p.id, | ||||
|             "name": "OldDean", | ||||
|             "newattr": u"garbage", | ||||
|         } | ||||
|  | ||||
|     def test_fields_containing_underscore(self): | ||||
|         """Ensure we can query dynamic fields""" | ||||
| @@ -127,14 +131,14 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id) | ||||
|         self.assertEqual(raw_p, {"_id": p.id, "_name": u"Dean", "name": u"Dean"}) | ||||
|         assert raw_p == {"_id": p.id, "_name": u"Dean", "name": u"Dean"} | ||||
|  | ||||
|         p.name = "OldDean" | ||||
|         p._name = "NewDean" | ||||
|         p._newattr1 = "garbage"  # Unknown fields won't be added | ||||
|         p.save() | ||||
|         raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id) | ||||
|         self.assertEqual(raw_p, {"_id": p.id, "_name": u"NewDean", "name": u"OldDean"}) | ||||
|         assert raw_p == {"_id": p.id, "_name": u"NewDean", "name": u"OldDean"} | ||||
|  | ||||
|     def test_dynamic_document_queries(self): | ||||
|         """Ensure we can query dynamic fields""" | ||||
| @@ -143,10 +147,10 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.age = 22 | ||||
|         p.save() | ||||
|  | ||||
|         self.assertEqual(1, self.Person.objects(age=22).count()) | ||||
|         assert 1 == self.Person.objects(age=22).count() | ||||
|         p = self.Person.objects(age=22) | ||||
|         p = p.get() | ||||
|         self.assertEqual(22, p.age) | ||||
|         assert 22 == p.age | ||||
|  | ||||
|     def test_complex_dynamic_document_queries(self): | ||||
|         class Person(DynamicDocument): | ||||
| @@ -166,8 +170,8 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p2.age = 10 | ||||
|         p2.save() | ||||
|  | ||||
|         self.assertEqual(Person.objects(age__icontains="ten").count(), 2) | ||||
|         self.assertEqual(Person.objects(age__gte=10).count(), 1) | ||||
|         assert Person.objects(age__icontains="ten").count() == 2 | ||||
|         assert Person.objects(age__gte=10).count() == 1 | ||||
|  | ||||
|     def test_complex_data_lookups(self): | ||||
|         """Ensure you can query dynamic document dynamic fields""" | ||||
| @@ -175,12 +179,12 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         p.misc = {"hello": "world"} | ||||
|         p.save() | ||||
|  | ||||
|         self.assertEqual(1, self.Person.objects(misc__hello="world").count()) | ||||
|         assert 1 == self.Person.objects(misc__hello="world").count() | ||||
|  | ||||
|     def test_three_level_complex_data_lookups(self): | ||||
|         """Ensure you can query three level document dynamic fields""" | ||||
|         self.Person.objects.create(misc={"hello": {"hello2": "world"}}) | ||||
|         self.assertEqual(1, self.Person.objects(misc__hello__hello2="world").count()) | ||||
|         assert 1 == self.Person.objects(misc__hello__hello2="world").count() | ||||
|  | ||||
|     def test_complex_embedded_document_validation(self): | ||||
|         """Ensure embedded dynamic documents may be validated""" | ||||
| @@ -198,11 +202,13 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         embedded_doc_1.validate() | ||||
|  | ||||
|         embedded_doc_2 = Embedded(content="this is not a url") | ||||
|         self.assertRaises(ValidationError, embedded_doc_2.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             embedded_doc_2.validate() | ||||
|  | ||||
|         doc.embedded_field_1 = embedded_doc_1 | ||||
|         doc.embedded_field_2 = embedded_doc_2 | ||||
|         self.assertRaises(ValidationError, doc.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             doc.validate() | ||||
|  | ||||
|     def test_inheritance(self): | ||||
|         """Ensure that dynamic document plays nice with inheritance""" | ||||
| @@ -212,11 +218,9 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|  | ||||
|         Employee.drop_collection() | ||||
|  | ||||
|         self.assertIn("name", Employee._fields) | ||||
|         self.assertIn("salary", Employee._fields) | ||||
|         self.assertEqual( | ||||
|             Employee._get_collection_name(), self.Person._get_collection_name() | ||||
|         ) | ||||
|         assert "name" in Employee._fields | ||||
|         assert "salary" in Employee._fields | ||||
|         assert Employee._get_collection_name() == self.Person._get_collection_name() | ||||
|  | ||||
|         joe_bloggs = Employee() | ||||
|         joe_bloggs.name = "Joe Bloggs" | ||||
| @@ -224,11 +228,11 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         joe_bloggs.age = 20 | ||||
|         joe_bloggs.save() | ||||
|  | ||||
|         self.assertEqual(1, self.Person.objects(age=20).count()) | ||||
|         self.assertEqual(1, Employee.objects(age=20).count()) | ||||
|         assert 1 == self.Person.objects(age=20).count() | ||||
|         assert 1 == Employee.objects(age=20).count() | ||||
|  | ||||
|         joe_bloggs = self.Person.objects.first() | ||||
|         self.assertIsInstance(joe_bloggs, Employee) | ||||
|         assert isinstance(joe_bloggs, Employee) | ||||
|  | ||||
|     def test_embedded_dynamic_document(self): | ||||
|         """Test dynamic embedded documents""" | ||||
| @@ -249,26 +253,23 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         embedded_1.list_field = ["1", 2, {"hello": "world"}] | ||||
|         doc.embedded_field = embedded_1 | ||||
|  | ||||
|         self.assertEqual( | ||||
|             doc.to_mongo(), | ||||
|             { | ||||
|                 "embedded_field": { | ||||
|                     "_cls": "Embedded", | ||||
|                     "string_field": "hello", | ||||
|                     "int_field": 1, | ||||
|                     "dict_field": {"hello": "world"}, | ||||
|                     "list_field": ["1", 2, {"hello": "world"}], | ||||
|                 } | ||||
|             }, | ||||
|         ) | ||||
|         assert doc.to_mongo() == { | ||||
|             "embedded_field": { | ||||
|                 "_cls": "Embedded", | ||||
|                 "string_field": "hello", | ||||
|                 "int_field": 1, | ||||
|                 "dict_field": {"hello": "world"}, | ||||
|                 "list_field": ["1", 2, {"hello": "world"}], | ||||
|             } | ||||
|         } | ||||
|         doc.save() | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc.embedded_field.__class__, Embedded) | ||||
|         self.assertEqual(doc.embedded_field.string_field, "hello") | ||||
|         self.assertEqual(doc.embedded_field.int_field, 1) | ||||
|         self.assertEqual(doc.embedded_field.dict_field, {"hello": "world"}) | ||||
|         self.assertEqual(doc.embedded_field.list_field, ["1", 2, {"hello": "world"}]) | ||||
|         assert doc.embedded_field.__class__ == Embedded | ||||
|         assert doc.embedded_field.string_field == "hello" | ||||
|         assert doc.embedded_field.int_field == 1 | ||||
|         assert doc.embedded_field.dict_field == {"hello": "world"} | ||||
|         assert doc.embedded_field.list_field == ["1", 2, {"hello": "world"}] | ||||
|  | ||||
|     def test_complex_embedded_documents(self): | ||||
|         """Test complex dynamic embedded documents setups""" | ||||
| @@ -296,44 +297,41 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         embedded_1.list_field = ["1", 2, embedded_2] | ||||
|         doc.embedded_field = embedded_1 | ||||
|  | ||||
|         self.assertEqual( | ||||
|             doc.to_mongo(), | ||||
|             { | ||||
|                 "embedded_field": { | ||||
|                     "_cls": "Embedded", | ||||
|                     "string_field": "hello", | ||||
|                     "int_field": 1, | ||||
|                     "dict_field": {"hello": "world"}, | ||||
|                     "list_field": [ | ||||
|                         "1", | ||||
|                         2, | ||||
|                         { | ||||
|                             "_cls": "Embedded", | ||||
|                             "string_field": "hello", | ||||
|                             "int_field": 1, | ||||
|                             "dict_field": {"hello": "world"}, | ||||
|                             "list_field": ["1", 2, {"hello": "world"}], | ||||
|                         }, | ||||
|                     ], | ||||
|                 } | ||||
|             }, | ||||
|         ) | ||||
|         assert doc.to_mongo() == { | ||||
|             "embedded_field": { | ||||
|                 "_cls": "Embedded", | ||||
|                 "string_field": "hello", | ||||
|                 "int_field": 1, | ||||
|                 "dict_field": {"hello": "world"}, | ||||
|                 "list_field": [ | ||||
|                     "1", | ||||
|                     2, | ||||
|                     { | ||||
|                         "_cls": "Embedded", | ||||
|                         "string_field": "hello", | ||||
|                         "int_field": 1, | ||||
|                         "dict_field": {"hello": "world"}, | ||||
|                         "list_field": ["1", 2, {"hello": "world"}], | ||||
|                     }, | ||||
|                 ], | ||||
|             } | ||||
|         } | ||||
|         doc.save() | ||||
|         doc = Doc.objects.first() | ||||
|         self.assertEqual(doc.embedded_field.__class__, Embedded) | ||||
|         self.assertEqual(doc.embedded_field.string_field, "hello") | ||||
|         self.assertEqual(doc.embedded_field.int_field, 1) | ||||
|         self.assertEqual(doc.embedded_field.dict_field, {"hello": "world"}) | ||||
|         self.assertEqual(doc.embedded_field.list_field[0], "1") | ||||
|         self.assertEqual(doc.embedded_field.list_field[1], 2) | ||||
|         assert doc.embedded_field.__class__ == Embedded | ||||
|         assert doc.embedded_field.string_field == "hello" | ||||
|         assert doc.embedded_field.int_field == 1 | ||||
|         assert doc.embedded_field.dict_field == {"hello": "world"} | ||||
|         assert doc.embedded_field.list_field[0] == "1" | ||||
|         assert doc.embedded_field.list_field[1] == 2 | ||||
|  | ||||
|         embedded_field = doc.embedded_field.list_field[2] | ||||
|  | ||||
|         self.assertEqual(embedded_field.__class__, Embedded) | ||||
|         self.assertEqual(embedded_field.string_field, "hello") | ||||
|         self.assertEqual(embedded_field.int_field, 1) | ||||
|         self.assertEqual(embedded_field.dict_field, {"hello": "world"}) | ||||
|         self.assertEqual(embedded_field.list_field, ["1", 2, {"hello": "world"}]) | ||||
|         assert embedded_field.__class__ == Embedded | ||||
|         assert embedded_field.string_field == "hello" | ||||
|         assert embedded_field.int_field == 1 | ||||
|         assert embedded_field.dict_field == {"hello": "world"} | ||||
|         assert embedded_field.list_field == ["1", 2, {"hello": "world"}] | ||||
|  | ||||
|     def test_dynamic_and_embedded(self): | ||||
|         """Ensure embedded documents play nicely""" | ||||
| @@ -352,18 +350,18 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         person.address.city = "Lundenne" | ||||
|         person.save() | ||||
|  | ||||
|         self.assertEqual(Person.objects.first().address.city, "Lundenne") | ||||
|         assert Person.objects.first().address.city == "Lundenne" | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         person.address = Address(city="Londinium") | ||||
|         person.save() | ||||
|  | ||||
|         self.assertEqual(Person.objects.first().address.city, "Londinium") | ||||
|         assert Person.objects.first().address.city == "Londinium" | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         person.age = 35 | ||||
|         person.save() | ||||
|         self.assertEqual(Person.objects.first().age, 35) | ||||
|         assert Person.objects.first().age == 35 | ||||
|  | ||||
|     def test_dynamic_embedded_works_with_only(self): | ||||
|         """Ensure custom fieldnames on a dynamic embedded document are found by qs.only()""" | ||||
| @@ -380,10 +378,10 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|             name="Eric", address=Address(city="San Francisco", street_number="1337") | ||||
|         ).save() | ||||
|  | ||||
|         self.assertEqual(Person.objects.first().address.street_number, "1337") | ||||
|         self.assertEqual( | ||||
|             Person.objects.only("address__street_number").first().address.street_number, | ||||
|             "1337", | ||||
|         assert Person.objects.first().address.street_number == "1337" | ||||
|         assert ( | ||||
|             Person.objects.only("address__street_number").first().address.street_number | ||||
|             == "1337" | ||||
|         ) | ||||
|  | ||||
|     def test_dynamic_and_embedded_dict_access(self): | ||||
| @@ -408,20 +406,20 @@ class TestDynamicDocument(MongoDBTestCase): | ||||
|         person["address"]["city"] = "Lundenne" | ||||
|         person.save() | ||||
|  | ||||
|         self.assertEqual(Person.objects.first().address.city, "Lundenne") | ||||
|         assert Person.objects.first().address.city == "Lundenne" | ||||
|  | ||||
|         self.assertEqual(Person.objects.first().phone, "555-1212") | ||||
|         assert Person.objects.first().phone == "555-1212" | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         person.address = Address(city="Londinium") | ||||
|         person.save() | ||||
|  | ||||
|         self.assertEqual(Person.objects.first().address.city, "Londinium") | ||||
|         assert Person.objects.first().address.city == "Londinium" | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         person["age"] = 35 | ||||
|         person.save() | ||||
|         self.assertEqual(Person.objects.first().age, 35) | ||||
|         assert Person.objects.first().age == 35 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -2,9 +2,9 @@ | ||||
| import unittest | ||||
| from datetime import datetime | ||||
|  | ||||
| from nose.plugins.skip import SkipTest | ||||
| from pymongo.collation import Collation | ||||
| from pymongo.errors import OperationFailure | ||||
| import pytest | ||||
| from six import iteritems | ||||
|  | ||||
| from mongoengine import * | ||||
| @@ -53,15 +53,15 @@ class TestIndexes(unittest.TestCase): | ||||
|             {"fields": [("tags", 1)]}, | ||||
|             {"fields": [("category", 1), ("addDate", -1)]}, | ||||
|         ] | ||||
|         self.assertEqual(expected_specs, BlogPost._meta["index_specs"]) | ||||
|         assert expected_specs == BlogPost._meta["index_specs"] | ||||
|  | ||||
|         BlogPost.ensure_indexes() | ||||
|         info = BlogPost.objects._collection.index_information() | ||||
|         # _id, '-date', 'tags', ('cat', 'date') | ||||
|         self.assertEqual(len(info), 4) | ||||
|         assert len(info) == 4 | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         for expected in expected_specs: | ||||
|             self.assertIn(expected["fields"], info) | ||||
|             assert expected["fields"] in info | ||||
|  | ||||
|     def _index_test_inheritance(self, InheritFrom): | ||||
|         class BlogPost(InheritFrom): | ||||
| @@ -78,7 +78,7 @@ class TestIndexes(unittest.TestCase): | ||||
|             {"fields": [("_cls", 1), ("tags", 1)]}, | ||||
|             {"fields": [("_cls", 1), ("category", 1), ("addDate", -1)]}, | ||||
|         ] | ||||
|         self.assertEqual(expected_specs, BlogPost._meta["index_specs"]) | ||||
|         assert expected_specs == BlogPost._meta["index_specs"] | ||||
|  | ||||
|         BlogPost.ensure_indexes() | ||||
|         info = BlogPost.objects._collection.index_information() | ||||
| @@ -86,17 +86,17 @@ class TestIndexes(unittest.TestCase): | ||||
|         # NB: there is no index on _cls by itself, since | ||||
|         # the indices on -date and tags will both contain | ||||
|         # _cls as first element in the key | ||||
|         self.assertEqual(len(info), 4) | ||||
|         assert len(info) == 4 | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         for expected in expected_specs: | ||||
|             self.assertIn(expected["fields"], info) | ||||
|             assert expected["fields"] in info | ||||
|  | ||||
|         class ExtendedBlogPost(BlogPost): | ||||
|             title = StringField() | ||||
|             meta = {"indexes": ["title"]} | ||||
|  | ||||
|         expected_specs.append({"fields": [("_cls", 1), ("title", 1)]}) | ||||
|         self.assertEqual(expected_specs, ExtendedBlogPost._meta["index_specs"]) | ||||
|         assert expected_specs == ExtendedBlogPost._meta["index_specs"] | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -104,7 +104,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         info = ExtendedBlogPost.objects._collection.index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         for expected in expected_specs: | ||||
|             self.assertIn(expected["fields"], info) | ||||
|             assert expected["fields"] in info | ||||
|  | ||||
|     def test_indexes_document_inheritance(self): | ||||
|         """Ensure that indexes are used when meta[indexes] is specified for | ||||
| @@ -128,10 +128,8 @@ class TestIndexes(unittest.TestCase): | ||||
|         class B(A): | ||||
|             description = StringField() | ||||
|  | ||||
|         self.assertEqual(A._meta["index_specs"], B._meta["index_specs"]) | ||||
|         self.assertEqual( | ||||
|             [{"fields": [("_cls", 1), ("title", 1)]}], A._meta["index_specs"] | ||||
|         ) | ||||
|         assert A._meta["index_specs"] == B._meta["index_specs"] | ||||
|         assert [{"fields": [("_cls", 1), ("title", 1)]}] == A._meta["index_specs"] | ||||
|  | ||||
|     def test_index_no_cls(self): | ||||
|         """Ensure index specs are inhertited correctly""" | ||||
| @@ -144,11 +142,11 @@ class TestIndexes(unittest.TestCase): | ||||
|                 "index_cls": False, | ||||
|             } | ||||
|  | ||||
|         self.assertEqual([("title", 1)], A._meta["index_specs"][0]["fields"]) | ||||
|         assert [("title", 1)] == A._meta["index_specs"][0]["fields"] | ||||
|         A._get_collection().drop_indexes() | ||||
|         A.ensure_indexes() | ||||
|         info = A._get_collection().index_information() | ||||
|         self.assertEqual(len(info.keys()), 2) | ||||
|         assert len(info.keys()) == 2 | ||||
|  | ||||
|         class B(A): | ||||
|             c = StringField() | ||||
| @@ -158,8 +156,8 @@ class TestIndexes(unittest.TestCase): | ||||
|                 "allow_inheritance": True, | ||||
|             } | ||||
|  | ||||
|         self.assertEqual([("c", 1)], B._meta["index_specs"][1]["fields"]) | ||||
|         self.assertEqual([("_cls", 1), ("d", 1)], B._meta["index_specs"][2]["fields"]) | ||||
|         assert [("c", 1)] == B._meta["index_specs"][1]["fields"] | ||||
|         assert [("_cls", 1), ("d", 1)] == B._meta["index_specs"][2]["fields"] | ||||
|  | ||||
|     def test_build_index_spec_is_not_destructive(self): | ||||
|         class MyDoc(Document): | ||||
| @@ -167,12 +165,12 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|             meta = {"indexes": ["keywords"], "allow_inheritance": False} | ||||
|  | ||||
|         self.assertEqual(MyDoc._meta["index_specs"], [{"fields": [("keywords", 1)]}]) | ||||
|         assert MyDoc._meta["index_specs"] == [{"fields": [("keywords", 1)]}] | ||||
|  | ||||
|         # Force index creation | ||||
|         MyDoc.ensure_indexes() | ||||
|  | ||||
|         self.assertEqual(MyDoc._meta["index_specs"], [{"fields": [("keywords", 1)]}]) | ||||
|         assert MyDoc._meta["index_specs"] == [{"fields": [("keywords", 1)]}] | ||||
|  | ||||
|     def test_embedded_document_index_meta(self): | ||||
|         """Ensure that embedded document indexes are created explicitly | ||||
| @@ -187,7 +185,7 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|             meta = {"indexes": ["rank.title"], "allow_inheritance": False} | ||||
|  | ||||
|         self.assertEqual([{"fields": [("rank.title", 1)]}], Person._meta["index_specs"]) | ||||
|         assert [{"fields": [("rank.title", 1)]}] == Person._meta["index_specs"] | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
| @@ -195,7 +193,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         list(Person.objects) | ||||
|         info = Person.objects._collection.index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("rank.title", 1)], info) | ||||
|         assert [("rank.title", 1)] in info | ||||
|  | ||||
|     def test_explicit_geo2d_index(self): | ||||
|         """Ensure that geo2d indexes work when created via meta[indexes] | ||||
| @@ -205,14 +203,12 @@ class TestIndexes(unittest.TestCase): | ||||
|             location = DictField() | ||||
|             meta = {"allow_inheritance": True, "indexes": ["*location.point"]} | ||||
|  | ||||
|         self.assertEqual( | ||||
|             [{"fields": [("location.point", "2d")]}], Place._meta["index_specs"] | ||||
|         ) | ||||
|         assert [{"fields": [("location.point", "2d")]}] == Place._meta["index_specs"] | ||||
|  | ||||
|         Place.ensure_indexes() | ||||
|         info = Place._get_collection().index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("location.point", "2d")], info) | ||||
|         assert [("location.point", "2d")] in info | ||||
|  | ||||
|     def test_explicit_geo2d_index_embedded(self): | ||||
|         """Ensure that geo2d indexes work when created via meta[indexes] | ||||
| @@ -225,14 +221,14 @@ class TestIndexes(unittest.TestCase): | ||||
|             current = DictField(field=EmbeddedDocumentField("EmbeddedLocation")) | ||||
|             meta = {"allow_inheritance": True, "indexes": ["*current.location.point"]} | ||||
|  | ||||
|         self.assertEqual( | ||||
|             [{"fields": [("current.location.point", "2d")]}], Place._meta["index_specs"] | ||||
|         ) | ||||
|         assert [{"fields": [("current.location.point", "2d")]}] == Place._meta[ | ||||
|             "index_specs" | ||||
|         ] | ||||
|  | ||||
|         Place.ensure_indexes() | ||||
|         info = Place._get_collection().index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("current.location.point", "2d")], info) | ||||
|         assert [("current.location.point", "2d")] in info | ||||
|  | ||||
|     def test_explicit_geosphere_index(self): | ||||
|         """Ensure that geosphere indexes work when created via meta[indexes] | ||||
| @@ -242,19 +238,19 @@ class TestIndexes(unittest.TestCase): | ||||
|             location = DictField() | ||||
|             meta = {"allow_inheritance": True, "indexes": ["(location.point"]} | ||||
|  | ||||
|         self.assertEqual( | ||||
|             [{"fields": [("location.point", "2dsphere")]}], Place._meta["index_specs"] | ||||
|         ) | ||||
|         assert [{"fields": [("location.point", "2dsphere")]}] == Place._meta[ | ||||
|             "index_specs" | ||||
|         ] | ||||
|  | ||||
|         Place.ensure_indexes() | ||||
|         info = Place._get_collection().index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("location.point", "2dsphere")], info) | ||||
|         assert [("location.point", "2dsphere")] in info | ||||
|  | ||||
|     def test_explicit_geohaystack_index(self): | ||||
|         """Ensure that geohaystack indexes work when created via meta[indexes] | ||||
|         """ | ||||
|         raise SkipTest( | ||||
|         pytest.skip( | ||||
|             "GeoHaystack index creation is not supported for now" | ||||
|             "from meta, as it requires a bucketSize parameter." | ||||
|         ) | ||||
| @@ -264,15 +260,14 @@ class TestIndexes(unittest.TestCase): | ||||
|             name = StringField() | ||||
|             meta = {"indexes": [(")location.point", "name")]} | ||||
|  | ||||
|         self.assertEqual( | ||||
|             [{"fields": [("location.point", "geoHaystack"), ("name", 1)]}], | ||||
|             Place._meta["index_specs"], | ||||
|         ) | ||||
|         assert [ | ||||
|             {"fields": [("location.point", "geoHaystack"), ("name", 1)]} | ||||
|         ] == Place._meta["index_specs"] | ||||
|  | ||||
|         Place.ensure_indexes() | ||||
|         info = Place._get_collection().index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("location.point", "geoHaystack")], info) | ||||
|         assert [("location.point", "geoHaystack")] in info | ||||
|  | ||||
|     def test_create_geohaystack_index(self): | ||||
|         """Ensure that geohaystack indexes can be created | ||||
| @@ -285,7 +280,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         Place.create_index({"fields": (")location.point", "name")}, bucketSize=10) | ||||
|         info = Place._get_collection().index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("location.point", "geoHaystack"), ("name", 1)], info) | ||||
|         assert [("location.point", "geoHaystack"), ("name", 1)] in info | ||||
|  | ||||
|     def test_dictionary_indexes(self): | ||||
|         """Ensure that indexes are used when meta[indexes] contains | ||||
| @@ -298,16 +293,15 @@ class TestIndexes(unittest.TestCase): | ||||
|             tags = ListField(StringField()) | ||||
|             meta = {"indexes": [{"fields": ["-date"], "unique": True, "sparse": True}]} | ||||
|  | ||||
|         self.assertEqual( | ||||
|             [{"fields": [("addDate", -1)], "unique": True, "sparse": True}], | ||||
|             BlogPost._meta["index_specs"], | ||||
|         ) | ||||
|         assert [ | ||||
|             {"fields": [("addDate", -1)], "unique": True, "sparse": True} | ||||
|         ] == BlogPost._meta["index_specs"] | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
|         info = BlogPost.objects._collection.index_information() | ||||
|         # _id, '-date' | ||||
|         self.assertEqual(len(info), 2) | ||||
|         assert len(info) == 2 | ||||
|  | ||||
|         # Indexes are lazy so use list() to perform query | ||||
|         list(BlogPost.objects) | ||||
| @@ -316,7 +310,7 @@ class TestIndexes(unittest.TestCase): | ||||
|             (value["key"], value.get("unique", False), value.get("sparse", False)) | ||||
|             for key, value in iteritems(info) | ||||
|         ] | ||||
|         self.assertIn(([("addDate", -1)], True, True), info) | ||||
|         assert ([("addDate", -1)], True, True) in info | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -338,11 +332,9 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         Person(name="test", user_guid="123").save() | ||||
|  | ||||
|         self.assertEqual(1, Person.objects.count()) | ||||
|         assert 1 == Person.objects.count() | ||||
|         info = Person.objects._collection.index_information() | ||||
|         self.assertEqual( | ||||
|             sorted(info.keys()), ["_cls_1_name_1", "_cls_1_user_guid_1", "_id_"] | ||||
|         ) | ||||
|         assert sorted(info.keys()) == ["_cls_1_name_1", "_cls_1_user_guid_1", "_id_"] | ||||
|  | ||||
|     def test_disable_index_creation(self): | ||||
|         """Tests setting auto_create_index to False on the connection will | ||||
| @@ -365,13 +357,13 @@ class TestIndexes(unittest.TestCase): | ||||
|         User(user_guid="123").save() | ||||
|         MongoUser(user_guid="123").save() | ||||
|  | ||||
|         self.assertEqual(2, User.objects.count()) | ||||
|         assert 2 == User.objects.count() | ||||
|         info = User.objects._collection.index_information() | ||||
|         self.assertEqual(list(info.keys()), ["_id_"]) | ||||
|         assert list(info.keys()) == ["_id_"] | ||||
|  | ||||
|         User.ensure_indexes() | ||||
|         info = User.objects._collection.index_information() | ||||
|         self.assertEqual(sorted(info.keys()), ["_cls_1_user_guid_1", "_id_"]) | ||||
|         assert sorted(info.keys()) == ["_cls_1_user_guid_1", "_id_"] | ||||
|  | ||||
|     def test_embedded_document_index(self): | ||||
|         """Tests settings an index on an embedded document | ||||
| @@ -389,7 +381,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
|         info = BlogPost.objects._collection.index_information() | ||||
|         self.assertEqual(sorted(info.keys()), ["_id_", "date.yr_-1"]) | ||||
|         assert sorted(info.keys()) == ["_id_", "date.yr_-1"] | ||||
|  | ||||
|     def test_list_embedded_document_index(self): | ||||
|         """Ensure list embedded documents can be indexed | ||||
| @@ -408,7 +400,7 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         info = BlogPost.objects._collection.index_information() | ||||
|         # we don't use _cls in with list fields by default | ||||
|         self.assertEqual(sorted(info.keys()), ["_id_", "tags.tag_1"]) | ||||
|         assert sorted(info.keys()) == ["_id_", "tags.tag_1"] | ||||
|  | ||||
|         post1 = BlogPost( | ||||
|             title="Embedded Indexes tests in place", | ||||
| @@ -426,7 +418,7 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         RecursiveDocument.ensure_indexes() | ||||
|         info = RecursiveDocument._get_collection().index_information() | ||||
|         self.assertEqual(sorted(info.keys()), ["_cls_1", "_id_"]) | ||||
|         assert sorted(info.keys()) == ["_cls_1", "_id_"] | ||||
|  | ||||
|     def test_covered_index(self): | ||||
|         """Ensure that covered indexes can be used | ||||
| @@ -446,46 +438,45 @@ class TestIndexes(unittest.TestCase): | ||||
|         # Need to be explicit about covered indexes as mongoDB doesn't know if | ||||
|         # the documents returned might have more keys in that here. | ||||
|         query_plan = Test.objects(id=obj.id).exclude("a").explain() | ||||
|         self.assertEqual( | ||||
|         assert ( | ||||
|             query_plan.get("queryPlanner") | ||||
|             .get("winningPlan") | ||||
|             .get("inputStage") | ||||
|             .get("stage"), | ||||
|             "IDHACK", | ||||
|             .get("stage") | ||||
|             == "IDHACK" | ||||
|         ) | ||||
|  | ||||
|         query_plan = Test.objects(id=obj.id).only("id").explain() | ||||
|         self.assertEqual( | ||||
|         assert ( | ||||
|             query_plan.get("queryPlanner") | ||||
|             .get("winningPlan") | ||||
|             .get("inputStage") | ||||
|             .get("stage"), | ||||
|             "IDHACK", | ||||
|             .get("stage") | ||||
|             == "IDHACK" | ||||
|         ) | ||||
|  | ||||
|         query_plan = Test.objects(a=1).only("a").exclude("id").explain() | ||||
|         self.assertEqual( | ||||
|         assert ( | ||||
|             query_plan.get("queryPlanner") | ||||
|             .get("winningPlan") | ||||
|             .get("inputStage") | ||||
|             .get("stage"), | ||||
|             "IXSCAN", | ||||
|             .get("stage") | ||||
|             == "IXSCAN" | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             query_plan.get("queryPlanner").get("winningPlan").get("stage"), "PROJECTION" | ||||
|         assert ( | ||||
|             query_plan.get("queryPlanner").get("winningPlan").get("stage") | ||||
|             == "PROJECTION" | ||||
|         ) | ||||
|  | ||||
|         query_plan = Test.objects(a=1).explain() | ||||
|         self.assertEqual( | ||||
|         assert ( | ||||
|             query_plan.get("queryPlanner") | ||||
|             .get("winningPlan") | ||||
|             .get("inputStage") | ||||
|             .get("stage"), | ||||
|             "IXSCAN", | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             query_plan.get("queryPlanner").get("winningPlan").get("stage"), "FETCH" | ||||
|             .get("stage") | ||||
|             == "IXSCAN" | ||||
|         ) | ||||
|         assert query_plan.get("queryPlanner").get("winningPlan").get("stage") == "FETCH" | ||||
|  | ||||
|     def test_index_on_id(self): | ||||
|         class BlogPost(Document): | ||||
| @@ -498,9 +489,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
|         indexes = BlogPost.objects._collection.index_information() | ||||
|         self.assertEqual( | ||||
|             indexes["categories_1__id_1"]["key"], [("categories", 1), ("_id", 1)] | ||||
|         ) | ||||
|         assert indexes["categories_1__id_1"]["key"] == [("categories", 1), ("_id", 1)] | ||||
|  | ||||
|     def test_hint(self): | ||||
|         TAGS_INDEX_NAME = "tags_1" | ||||
| @@ -516,25 +505,25 @@ class TestIndexes(unittest.TestCase): | ||||
|             BlogPost(tags=tags).save() | ||||
|  | ||||
|         # Hinting by shape should work. | ||||
|         self.assertEqual(BlogPost.objects.hint([("tags", 1)]).count(), 10) | ||||
|         assert BlogPost.objects.hint([("tags", 1)]).count() == 10 | ||||
|  | ||||
|         # Hinting by index name should work. | ||||
|         self.assertEqual(BlogPost.objects.hint(TAGS_INDEX_NAME).count(), 10) | ||||
|         assert BlogPost.objects.hint(TAGS_INDEX_NAME).count() == 10 | ||||
|  | ||||
|         # Clearing the hint should work fine. | ||||
|         self.assertEqual(BlogPost.objects.hint().count(), 10) | ||||
|         self.assertEqual(BlogPost.objects.hint([("ZZ", 1)]).hint().count(), 10) | ||||
|         assert BlogPost.objects.hint().count() == 10 | ||||
|         assert BlogPost.objects.hint([("ZZ", 1)]).hint().count() == 10 | ||||
|  | ||||
|         # Hinting on a non-existent index shape should fail. | ||||
|         with self.assertRaises(OperationFailure): | ||||
|         with pytest.raises(OperationFailure): | ||||
|             BlogPost.objects.hint([("ZZ", 1)]).count() | ||||
|  | ||||
|         # Hinting on a non-existent index name should fail. | ||||
|         with self.assertRaises(OperationFailure): | ||||
|         with pytest.raises(OperationFailure): | ||||
|             BlogPost.objects.hint("Bad Name").count() | ||||
|  | ||||
|         # Invalid shape argument (missing list brackets) should fail. | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|             BlogPost.objects.hint(("tags", 1)).count() | ||||
|  | ||||
|     def test_collation(self): | ||||
| @@ -555,23 +544,19 @@ class TestIndexes(unittest.TestCase): | ||||
|             BlogPost(name=name).save() | ||||
|  | ||||
|         query_result = BlogPost.objects.collation(base).order_by("name") | ||||
|         self.assertEqual( | ||||
|             [x.name for x in query_result], sorted(names, key=lambda x: x.lower()) | ||||
|         ) | ||||
|         self.assertEqual(5, query_result.count()) | ||||
|         assert [x.name for x in query_result] == sorted(names, key=lambda x: x.lower()) | ||||
|         assert 5 == query_result.count() | ||||
|  | ||||
|         query_result = BlogPost.objects.collation(Collation(**base)).order_by("name") | ||||
|         self.assertEqual( | ||||
|             [x.name for x in query_result], sorted(names, key=lambda x: x.lower()) | ||||
|         ) | ||||
|         self.assertEqual(5, query_result.count()) | ||||
|         assert [x.name for x in query_result] == sorted(names, key=lambda x: x.lower()) | ||||
|         assert 5 == query_result.count() | ||||
|  | ||||
|         incorrect_collation = {"arndom": "wrdo"} | ||||
|         with self.assertRaises(OperationFailure): | ||||
|         with pytest.raises(OperationFailure): | ||||
|             BlogPost.objects.collation(incorrect_collation).count() | ||||
|  | ||||
|         query_result = BlogPost.objects.collation({}).order_by("name") | ||||
|         self.assertEqual([x.name for x in query_result], sorted(names)) | ||||
|         assert [x.name for x in query_result] == sorted(names) | ||||
|  | ||||
|     def test_unique(self): | ||||
|         """Ensure that uniqueness constraints are applied to fields. | ||||
| @@ -588,11 +573,14 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         # Two posts with the same slug is not allowed | ||||
|         post2 = BlogPost(title="test2", slug="test") | ||||
|         self.assertRaises(NotUniqueError, post2.save) | ||||
|         self.assertRaises(NotUniqueError, BlogPost.objects.insert, post2) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post2.save() | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             BlogPost.objects.insert(post2) | ||||
|  | ||||
|         # Ensure backwards compatibility for errors | ||||
|         self.assertRaises(OperationError, post2.save) | ||||
|         with pytest.raises(OperationError): | ||||
|             post2.save() | ||||
|  | ||||
|     def test_primary_key_unique_not_working(self): | ||||
|         """Relates to #1445""" | ||||
| @@ -602,23 +590,21 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         Blog.drop_collection() | ||||
|  | ||||
|         with self.assertRaises(OperationFailure) as ctx_err: | ||||
|         with pytest.raises(OperationFailure) as exc_info: | ||||
|             Blog(id="garbage").save() | ||||
|  | ||||
|         # One of the errors below should happen. Which one depends on the | ||||
|         # PyMongo version and dict order. | ||||
|         err_msg = str(ctx_err.exception) | ||||
|         self.assertTrue( | ||||
|             any( | ||||
|                 [ | ||||
|                     "The field 'unique' is not valid for an _id index specification" | ||||
|                     in err_msg, | ||||
|                     "The field 'background' is not valid for an _id index specification" | ||||
|                     in err_msg, | ||||
|                     "The field 'sparse' is not valid for an _id index specification" | ||||
|                     in err_msg, | ||||
|                 ] | ||||
|             ) | ||||
|         err_msg = str(exc_info.value) | ||||
|         assert any( | ||||
|             [ | ||||
|                 "The field 'unique' is not valid for an _id index specification" | ||||
|                 in err_msg, | ||||
|                 "The field 'background' is not valid for an _id index specification" | ||||
|                 in err_msg, | ||||
|                 "The field 'sparse' is not valid for an _id index specification" | ||||
|                 in err_msg, | ||||
|             ] | ||||
|         ) | ||||
|  | ||||
|     def test_unique_with(self): | ||||
| @@ -644,7 +630,8 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         # Now there will be two docs with the same slug and the same day: fail | ||||
|         post3 = BlogPost(title="test3", date=Date(year=2010), slug="test") | ||||
|         self.assertRaises(OperationError, post3.save) | ||||
|         with pytest.raises(OperationError): | ||||
|             post3.save() | ||||
|  | ||||
|     def test_unique_embedded_document(self): | ||||
|         """Ensure that uniqueness constraints are applied to fields on embedded documents. | ||||
| @@ -669,7 +656,8 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         # Now there will be two docs with the same sub.slug | ||||
|         post3 = BlogPost(title="test3", sub=SubDocument(year=2010, slug="test")) | ||||
|         self.assertRaises(NotUniqueError, post3.save) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post3.save() | ||||
|  | ||||
|     def test_unique_embedded_document_in_list(self): | ||||
|         """ | ||||
| @@ -699,7 +687,8 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         post2 = BlogPost(title="test2", subs=[SubDocument(year=2014, slug="conflict")]) | ||||
|  | ||||
|         self.assertRaises(NotUniqueError, post2.save) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post2.save() | ||||
|  | ||||
|     def test_unique_embedded_document_in_sorted_list(self): | ||||
|         """ | ||||
| @@ -729,12 +718,13 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         # confirm that the unique index is created | ||||
|         indexes = BlogPost._get_collection().index_information() | ||||
|         self.assertIn("subs.slug_1", indexes) | ||||
|         self.assertTrue(indexes["subs.slug_1"]["unique"]) | ||||
|         assert "subs.slug_1" in indexes | ||||
|         assert indexes["subs.slug_1"]["unique"] | ||||
|  | ||||
|         post2 = BlogPost(title="test2", subs=[SubDocument(year=2014, slug="conflict")]) | ||||
|  | ||||
|         self.assertRaises(NotUniqueError, post2.save) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post2.save() | ||||
|  | ||||
|     def test_unique_embedded_document_in_embedded_document_list(self): | ||||
|         """ | ||||
| @@ -764,12 +754,13 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         # confirm that the unique index is created | ||||
|         indexes = BlogPost._get_collection().index_information() | ||||
|         self.assertIn("subs.slug_1", indexes) | ||||
|         self.assertTrue(indexes["subs.slug_1"]["unique"]) | ||||
|         assert "subs.slug_1" in indexes | ||||
|         assert indexes["subs.slug_1"]["unique"] | ||||
|  | ||||
|         post2 = BlogPost(title="test2", subs=[SubDocument(year=2014, slug="conflict")]) | ||||
|  | ||||
|         self.assertRaises(NotUniqueError, post2.save) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post2.save() | ||||
|  | ||||
|     def test_unique_with_embedded_document_and_embedded_unique(self): | ||||
|         """Ensure that uniqueness constraints are applied to fields on | ||||
| @@ -795,11 +786,13 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         # Now there will be two docs with the same sub.slug | ||||
|         post3 = BlogPost(title="test3", sub=SubDocument(year=2010, slug="test")) | ||||
|         self.assertRaises(NotUniqueError, post3.save) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post3.save() | ||||
|  | ||||
|         # Now there will be two docs with the same title and year | ||||
|         post3 = BlogPost(title="test1", sub=SubDocument(year=2009, slug="test-1")) | ||||
|         self.assertRaises(NotUniqueError, post3.save) | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             post3.save() | ||||
|  | ||||
|     def test_ttl_indexes(self): | ||||
|         class Log(Document): | ||||
| @@ -811,7 +804,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         # Indexes are lazy so use list() to perform query | ||||
|         list(Log.objects) | ||||
|         info = Log.objects._collection.index_information() | ||||
|         self.assertEqual(3600, info["created_1"]["expireAfterSeconds"]) | ||||
|         assert 3600 == info["created_1"]["expireAfterSeconds"] | ||||
|  | ||||
|     def test_index_drop_dups_silently_ignored(self): | ||||
|         class Customer(Document): | ||||
| @@ -839,14 +832,14 @@ class TestIndexes(unittest.TestCase): | ||||
|         cust.save() | ||||
|  | ||||
|         cust_dupe = Customer(cust_id=1) | ||||
|         with self.assertRaises(NotUniqueError): | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             cust_dupe.save() | ||||
|  | ||||
|         cust = Customer(cust_id=2) | ||||
|         cust.save() | ||||
|  | ||||
|         # duplicate key on update | ||||
|         with self.assertRaises(NotUniqueError): | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             cust.cust_id = 1 | ||||
|             cust.save() | ||||
|  | ||||
| @@ -867,8 +860,8 @@ class TestIndexes(unittest.TestCase): | ||||
|         user = User(name="huangz", password="secret2") | ||||
|         user.save() | ||||
|  | ||||
|         self.assertEqual(User.objects.count(), 1) | ||||
|         self.assertEqual(User.objects.get().password, "secret2") | ||||
|         assert User.objects.count() == 1 | ||||
|         assert User.objects.get().password == "secret2" | ||||
|  | ||||
|     def test_unique_and_primary_create(self): | ||||
|         """Create a new record with a duplicate primary key | ||||
| @@ -882,11 +875,11 @@ class TestIndexes(unittest.TestCase): | ||||
|         User.drop_collection() | ||||
|  | ||||
|         User.objects.create(name="huangz", password="secret") | ||||
|         with self.assertRaises(NotUniqueError): | ||||
|         with pytest.raises(NotUniqueError): | ||||
|             User.objects.create(name="huangz", password="secret2") | ||||
|  | ||||
|         self.assertEqual(User.objects.count(), 1) | ||||
|         self.assertEqual(User.objects.get().password, "secret") | ||||
|         assert User.objects.count() == 1 | ||||
|         assert User.objects.get().password == "secret" | ||||
|  | ||||
|     def test_index_with_pk(self): | ||||
|         """Ensure you can use `pk` as part of a query""" | ||||
| @@ -910,7 +903,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         info = BlogPost.objects._collection.index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         index_item = [("_id", 1), ("comments.comment_id", 1)] | ||||
|         self.assertIn(index_item, info) | ||||
|         assert index_item in info | ||||
|  | ||||
|     def test_compound_key_embedded(self): | ||||
|         class CompoundKey(EmbeddedDocument): | ||||
| @@ -924,10 +917,8 @@ class TestIndexes(unittest.TestCase): | ||||
|         my_key = CompoundKey(name="n", term="ok") | ||||
|         report = ReportEmbedded(text="OK", key=my_key).save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             {"text": "OK", "_id": {"term": "ok", "name": "n"}}, report.to_mongo() | ||||
|         ) | ||||
|         self.assertEqual(report, ReportEmbedded.objects.get(pk=my_key)) | ||||
|         assert {"text": "OK", "_id": {"term": "ok", "name": "n"}} == report.to_mongo() | ||||
|         assert report == ReportEmbedded.objects.get(pk=my_key) | ||||
|  | ||||
|     def test_compound_key_dictfield(self): | ||||
|         class ReportDictField(Document): | ||||
| @@ -937,15 +928,13 @@ class TestIndexes(unittest.TestCase): | ||||
|         my_key = {"name": "n", "term": "ok"} | ||||
|         report = ReportDictField(text="OK", key=my_key).save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             {"text": "OK", "_id": {"term": "ok", "name": "n"}}, report.to_mongo() | ||||
|         ) | ||||
|         assert {"text": "OK", "_id": {"term": "ok", "name": "n"}} == report.to_mongo() | ||||
|  | ||||
|         # We can't directly call ReportDictField.objects.get(pk=my_key), | ||||
|         # because dicts are unordered, and if the order in MongoDB is | ||||
|         # different than the one in `my_key`, this test will fail. | ||||
|         self.assertEqual(report, ReportDictField.objects.get(pk__name=my_key["name"])) | ||||
|         self.assertEqual(report, ReportDictField.objects.get(pk__term=my_key["term"])) | ||||
|         assert report == ReportDictField.objects.get(pk__name=my_key["name"]) | ||||
|         assert report == ReportDictField.objects.get(pk__term=my_key["term"]) | ||||
|  | ||||
|     def test_string_indexes(self): | ||||
|         class MyDoc(Document): | ||||
| @@ -954,8 +943,8 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|         info = MyDoc.objects._collection.index_information() | ||||
|         info = [value["key"] for key, value in iteritems(info)] | ||||
|         self.assertIn([("provider_ids.foo", 1)], info) | ||||
|         self.assertIn([("provider_ids.bar", 1)], info) | ||||
|         assert [("provider_ids.foo", 1)] in info | ||||
|         assert [("provider_ids.bar", 1)] in info | ||||
|  | ||||
|     def test_sparse_compound_indexes(self): | ||||
|         class MyDoc(Document): | ||||
| @@ -967,11 +956,10 @@ class TestIndexes(unittest.TestCase): | ||||
|             } | ||||
|  | ||||
|         info = MyDoc.objects._collection.index_information() | ||||
|         self.assertEqual( | ||||
|             [("provider_ids.foo", 1), ("provider_ids.bar", 1)], | ||||
|             info["provider_ids.foo_1_provider_ids.bar_1"]["key"], | ||||
|         ) | ||||
|         self.assertTrue(info["provider_ids.foo_1_provider_ids.bar_1"]["sparse"]) | ||||
|         assert [("provider_ids.foo", 1), ("provider_ids.bar", 1)] == info[ | ||||
|             "provider_ids.foo_1_provider_ids.bar_1" | ||||
|         ]["key"] | ||||
|         assert info["provider_ids.foo_1_provider_ids.bar_1"]["sparse"] | ||||
|  | ||||
|     def test_text_indexes(self): | ||||
|         class Book(Document): | ||||
| @@ -979,9 +967,9 @@ class TestIndexes(unittest.TestCase): | ||||
|             meta = {"indexes": ["$title"]} | ||||
|  | ||||
|         indexes = Book.objects._collection.index_information() | ||||
|         self.assertIn("title_text", indexes) | ||||
|         assert "title_text" in indexes | ||||
|         key = indexes["title_text"]["key"] | ||||
|         self.assertIn(("_fts", "text"), key) | ||||
|         assert ("_fts", "text") in key | ||||
|  | ||||
|     def test_hashed_indexes(self): | ||||
|         class Book(Document): | ||||
| @@ -989,8 +977,8 @@ class TestIndexes(unittest.TestCase): | ||||
|             meta = {"indexes": ["#ref_id"]} | ||||
|  | ||||
|         indexes = Book.objects._collection.index_information() | ||||
|         self.assertIn("ref_id_hashed", indexes) | ||||
|         self.assertIn(("ref_id", "hashed"), indexes["ref_id_hashed"]["key"]) | ||||
|         assert "ref_id_hashed" in indexes | ||||
|         assert ("ref_id", "hashed") in indexes["ref_id_hashed"]["key"] | ||||
|  | ||||
|     def test_indexes_after_database_drop(self): | ||||
|         """ | ||||
| @@ -1027,7 +1015,8 @@ class TestIndexes(unittest.TestCase): | ||||
|  | ||||
|             # Create Post #2 | ||||
|             post2 = BlogPost(title="test2", slug="test") | ||||
|             self.assertRaises(NotUniqueError, post2.save) | ||||
|             with pytest.raises(NotUniqueError): | ||||
|                 post2.save() | ||||
|         finally: | ||||
|             # Drop the temporary database at the end | ||||
|             connection.drop_database("tempdatabase") | ||||
| @@ -1074,15 +1063,12 @@ class TestIndexes(unittest.TestCase): | ||||
|                     "dropDups" | ||||
|                 ]  # drop the index dropDups - it is deprecated in MongoDB 3+ | ||||
|  | ||||
|         self.assertEqual( | ||||
|             index_info, | ||||
|             { | ||||
|                 "txt_1": {"key": [("txt", 1)], "background": False}, | ||||
|                 "_id_": {"key": [("_id", 1)]}, | ||||
|                 "txt2_1": {"key": [("txt2", 1)], "background": False}, | ||||
|                 "_cls_1": {"key": [("_cls", 1)], "background": False}, | ||||
|             }, | ||||
|         ) | ||||
|         assert index_info == { | ||||
|             "txt_1": {"key": [("txt", 1)], "background": False}, | ||||
|             "_id_": {"key": [("_id", 1)]}, | ||||
|             "txt2_1": {"key": [("txt2", 1)], "background": False}, | ||||
|             "_cls_1": {"key": [("_cls", 1)], "background": False}, | ||||
|         } | ||||
|  | ||||
|     def test_compound_index_underscore_cls_not_overwritten(self): | ||||
|         """ | ||||
| @@ -1105,7 +1091,7 @@ class TestIndexes(unittest.TestCase): | ||||
|         TestDoc.ensure_indexes() | ||||
|  | ||||
|         index_info = TestDoc._get_collection().index_information() | ||||
|         self.assertIn("shard_1_1__cls_1_txt_1_1", index_info) | ||||
|         assert "shard_1_1__cls_1_txt_1_1" in index_info | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| import unittest | ||||
| import warnings | ||||
|  | ||||
| import pytest | ||||
| from six import iteritems | ||||
|  | ||||
| from mongoengine import ( | ||||
| @@ -37,12 +38,12 @@ class TestInheritance(MongoDBTestCase): | ||||
|             meta = {"allow_inheritance": True} | ||||
|  | ||||
|         test_doc = DataDoc(name="test", embed=EmbedData(data="data")) | ||||
|         self.assertEqual(test_doc._cls, "DataDoc") | ||||
|         self.assertEqual(test_doc.embed._cls, "EmbedData") | ||||
|         assert test_doc._cls == "DataDoc" | ||||
|         assert test_doc.embed._cls == "EmbedData" | ||||
|         test_doc.save() | ||||
|         saved_doc = DataDoc.objects.with_id(test_doc.id) | ||||
|         self.assertEqual(test_doc._cls, saved_doc._cls) | ||||
|         self.assertEqual(test_doc.embed._cls, saved_doc.embed._cls) | ||||
|         assert test_doc._cls == saved_doc._cls | ||||
|         assert test_doc.embed._cls == saved_doc.embed._cls | ||||
|         test_doc.delete() | ||||
|  | ||||
|     def test_superclasses(self): | ||||
| @@ -67,12 +68,12 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Human(Mammal): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual(Animal._superclasses, ()) | ||||
|         self.assertEqual(Fish._superclasses, ("Animal",)) | ||||
|         self.assertEqual(Guppy._superclasses, ("Animal", "Animal.Fish")) | ||||
|         self.assertEqual(Mammal._superclasses, ("Animal",)) | ||||
|         self.assertEqual(Dog._superclasses, ("Animal", "Animal.Mammal")) | ||||
|         self.assertEqual(Human._superclasses, ("Animal", "Animal.Mammal")) | ||||
|         assert Animal._superclasses == () | ||||
|         assert Fish._superclasses == ("Animal",) | ||||
|         assert Guppy._superclasses == ("Animal", "Animal.Fish") | ||||
|         assert Mammal._superclasses == ("Animal",) | ||||
|         assert Dog._superclasses == ("Animal", "Animal.Mammal") | ||||
|         assert Human._superclasses == ("Animal", "Animal.Mammal") | ||||
|  | ||||
|     def test_external_superclasses(self): | ||||
|         """Ensure that the correct list of super classes is assembled when | ||||
| @@ -97,18 +98,12 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Human(Mammal): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual(Animal._superclasses, ("Base",)) | ||||
|         self.assertEqual(Fish._superclasses, ("Base", "Base.Animal")) | ||||
|         self.assertEqual( | ||||
|             Guppy._superclasses, ("Base", "Base.Animal", "Base.Animal.Fish") | ||||
|         ) | ||||
|         self.assertEqual(Mammal._superclasses, ("Base", "Base.Animal")) | ||||
|         self.assertEqual( | ||||
|             Dog._superclasses, ("Base", "Base.Animal", "Base.Animal.Mammal") | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Human._superclasses, ("Base", "Base.Animal", "Base.Animal.Mammal") | ||||
|         ) | ||||
|         assert Animal._superclasses == ("Base",) | ||||
|         assert Fish._superclasses == ("Base", "Base.Animal") | ||||
|         assert Guppy._superclasses == ("Base", "Base.Animal", "Base.Animal.Fish") | ||||
|         assert Mammal._superclasses == ("Base", "Base.Animal") | ||||
|         assert Dog._superclasses == ("Base", "Base.Animal", "Base.Animal.Mammal") | ||||
|         assert Human._superclasses == ("Base", "Base.Animal", "Base.Animal.Mammal") | ||||
|  | ||||
|     def test_subclasses(self): | ||||
|         """Ensure that the correct list of _subclasses (subclasses) is | ||||
| @@ -133,24 +128,22 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Human(Mammal): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual( | ||||
|             Animal._subclasses, | ||||
|             ( | ||||
|                 "Animal", | ||||
|                 "Animal.Fish", | ||||
|                 "Animal.Fish.Guppy", | ||||
|                 "Animal.Mammal", | ||||
|                 "Animal.Mammal.Dog", | ||||
|                 "Animal.Mammal.Human", | ||||
|             ), | ||||
|         assert Animal._subclasses == ( | ||||
|             "Animal", | ||||
|             "Animal.Fish", | ||||
|             "Animal.Fish.Guppy", | ||||
|             "Animal.Mammal", | ||||
|             "Animal.Mammal.Dog", | ||||
|             "Animal.Mammal.Human", | ||||
|         ) | ||||
|         self.assertEqual(Fish._subclasses, ("Animal.Fish", "Animal.Fish.Guppy")) | ||||
|         self.assertEqual(Guppy._subclasses, ("Animal.Fish.Guppy",)) | ||||
|         self.assertEqual( | ||||
|             Mammal._subclasses, | ||||
|             ("Animal.Mammal", "Animal.Mammal.Dog", "Animal.Mammal.Human"), | ||||
|         assert Fish._subclasses == ("Animal.Fish", "Animal.Fish.Guppy") | ||||
|         assert Guppy._subclasses == ("Animal.Fish.Guppy",) | ||||
|         assert Mammal._subclasses == ( | ||||
|             "Animal.Mammal", | ||||
|             "Animal.Mammal.Dog", | ||||
|             "Animal.Mammal.Human", | ||||
|         ) | ||||
|         self.assertEqual(Human._subclasses, ("Animal.Mammal.Human",)) | ||||
|         assert Human._subclasses == ("Animal.Mammal.Human",) | ||||
|  | ||||
|     def test_external_subclasses(self): | ||||
|         """Ensure that the correct list of _subclasses (subclasses) is | ||||
| @@ -175,30 +168,22 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Human(Mammal): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual( | ||||
|             Animal._subclasses, | ||||
|             ( | ||||
|                 "Base.Animal", | ||||
|                 "Base.Animal.Fish", | ||||
|                 "Base.Animal.Fish.Guppy", | ||||
|                 "Base.Animal.Mammal", | ||||
|                 "Base.Animal.Mammal.Dog", | ||||
|                 "Base.Animal.Mammal.Human", | ||||
|             ), | ||||
|         assert Animal._subclasses == ( | ||||
|             "Base.Animal", | ||||
|             "Base.Animal.Fish", | ||||
|             "Base.Animal.Fish.Guppy", | ||||
|             "Base.Animal.Mammal", | ||||
|             "Base.Animal.Mammal.Dog", | ||||
|             "Base.Animal.Mammal.Human", | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Fish._subclasses, ("Base.Animal.Fish", "Base.Animal.Fish.Guppy") | ||||
|         assert Fish._subclasses == ("Base.Animal.Fish", "Base.Animal.Fish.Guppy") | ||||
|         assert Guppy._subclasses == ("Base.Animal.Fish.Guppy",) | ||||
|         assert Mammal._subclasses == ( | ||||
|             "Base.Animal.Mammal", | ||||
|             "Base.Animal.Mammal.Dog", | ||||
|             "Base.Animal.Mammal.Human", | ||||
|         ) | ||||
|         self.assertEqual(Guppy._subclasses, ("Base.Animal.Fish.Guppy",)) | ||||
|         self.assertEqual( | ||||
|             Mammal._subclasses, | ||||
|             ( | ||||
|                 "Base.Animal.Mammal", | ||||
|                 "Base.Animal.Mammal.Dog", | ||||
|                 "Base.Animal.Mammal.Human", | ||||
|             ), | ||||
|         ) | ||||
|         self.assertEqual(Human._subclasses, ("Base.Animal.Mammal.Human",)) | ||||
|         assert Human._subclasses == ("Base.Animal.Mammal.Human",) | ||||
|  | ||||
|     def test_dynamic_declarations(self): | ||||
|         """Test that declaring an extra class updates meta data""" | ||||
| @@ -206,33 +191,31 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Animal(Document): | ||||
|             meta = {"allow_inheritance": True} | ||||
|  | ||||
|         self.assertEqual(Animal._superclasses, ()) | ||||
|         self.assertEqual(Animal._subclasses, ("Animal",)) | ||||
|         assert Animal._superclasses == () | ||||
|         assert Animal._subclasses == ("Animal",) | ||||
|  | ||||
|         # Test dynamically adding a class changes the meta data | ||||
|         class Fish(Animal): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual(Animal._superclasses, ()) | ||||
|         self.assertEqual(Animal._subclasses, ("Animal", "Animal.Fish")) | ||||
|         assert Animal._superclasses == () | ||||
|         assert Animal._subclasses == ("Animal", "Animal.Fish") | ||||
|  | ||||
|         self.assertEqual(Fish._superclasses, ("Animal",)) | ||||
|         self.assertEqual(Fish._subclasses, ("Animal.Fish",)) | ||||
|         assert Fish._superclasses == ("Animal",) | ||||
|         assert Fish._subclasses == ("Animal.Fish",) | ||||
|  | ||||
|         # Test dynamically adding an inherited class changes the meta data | ||||
|         class Pike(Fish): | ||||
|             pass | ||||
|  | ||||
|         self.assertEqual(Animal._superclasses, ()) | ||||
|         self.assertEqual( | ||||
|             Animal._subclasses, ("Animal", "Animal.Fish", "Animal.Fish.Pike") | ||||
|         ) | ||||
|         assert Animal._superclasses == () | ||||
|         assert Animal._subclasses == ("Animal", "Animal.Fish", "Animal.Fish.Pike") | ||||
|  | ||||
|         self.assertEqual(Fish._superclasses, ("Animal",)) | ||||
|         self.assertEqual(Fish._subclasses, ("Animal.Fish", "Animal.Fish.Pike")) | ||||
|         assert Fish._superclasses == ("Animal",) | ||||
|         assert Fish._subclasses == ("Animal.Fish", "Animal.Fish.Pike") | ||||
|  | ||||
|         self.assertEqual(Pike._superclasses, ("Animal", "Animal.Fish")) | ||||
|         self.assertEqual(Pike._subclasses, ("Animal.Fish.Pike",)) | ||||
|         assert Pike._superclasses == ("Animal", "Animal.Fish") | ||||
|         assert Pike._subclasses == ("Animal.Fish.Pike",) | ||||
|  | ||||
|     def test_inheritance_meta_data(self): | ||||
|         """Ensure that document may inherit fields from a superclass document. | ||||
| @@ -247,10 +230,10 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Employee(Person): | ||||
|             salary = IntField() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             ["_cls", "age", "id", "name", "salary"], sorted(Employee._fields.keys()) | ||||
|         assert ["_cls", "age", "id", "name", "salary"] == sorted( | ||||
|             Employee._fields.keys() | ||||
|         ) | ||||
|         self.assertEqual(Employee._get_collection_name(), Person._get_collection_name()) | ||||
|         assert Employee._get_collection_name() == Person._get_collection_name() | ||||
|  | ||||
|     def test_inheritance_to_mongo_keys(self): | ||||
|         """Ensure that document may inherit fields from a superclass document. | ||||
| @@ -265,17 +248,17 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Employee(Person): | ||||
|             salary = IntField() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             ["_cls", "age", "id", "name", "salary"], sorted(Employee._fields.keys()) | ||||
|         assert ["_cls", "age", "id", "name", "salary"] == sorted( | ||||
|             Employee._fields.keys() | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Person(name="Bob", age=35).to_mongo().keys(), ["_cls", "name", "age"] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Employee(name="Bob", age=35, salary=0).to_mongo().keys(), | ||||
|             ["_cls", "name", "age", "salary"], | ||||
|         ) | ||||
|         self.assertEqual(Employee._get_collection_name(), Person._get_collection_name()) | ||||
|         assert Person(name="Bob", age=35).to_mongo().keys() == ["_cls", "name", "age"] | ||||
|         assert Employee(name="Bob", age=35, salary=0).to_mongo().keys() == [ | ||||
|             "_cls", | ||||
|             "name", | ||||
|             "age", | ||||
|             "salary", | ||||
|         ] | ||||
|         assert Employee._get_collection_name() == Person._get_collection_name() | ||||
|  | ||||
|     def test_indexes_and_multiple_inheritance(self): | ||||
|         """ Ensure that all of the indexes are created for a document with | ||||
| @@ -301,13 +284,10 @@ class TestInheritance(MongoDBTestCase): | ||||
|  | ||||
|         C.ensure_indexes() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             sorted( | ||||
|                 [idx["key"] for idx in C._get_collection().index_information().values()] | ||||
|             ), | ||||
|             sorted( | ||||
|                 [[(u"_cls", 1), (u"b", 1)], [(u"_id", 1)], [(u"_cls", 1), (u"a", 1)]] | ||||
|             ), | ||||
|         assert sorted( | ||||
|             [idx["key"] for idx in C._get_collection().index_information().values()] | ||||
|         ) == sorted( | ||||
|             [[(u"_cls", 1), (u"b", 1)], [(u"_id", 1)], [(u"_cls", 1), (u"a", 1)]] | ||||
|         ) | ||||
|  | ||||
|     def test_polymorphic_queries(self): | ||||
| @@ -338,13 +318,13 @@ class TestInheritance(MongoDBTestCase): | ||||
|         Human().save() | ||||
|  | ||||
|         classes = [obj.__class__ for obj in Animal.objects] | ||||
|         self.assertEqual(classes, [Animal, Fish, Mammal, Dog, Human]) | ||||
|         assert classes == [Animal, Fish, Mammal, Dog, Human] | ||||
|  | ||||
|         classes = [obj.__class__ for obj in Mammal.objects] | ||||
|         self.assertEqual(classes, [Mammal, Dog, Human]) | ||||
|         assert classes == [Mammal, Dog, Human] | ||||
|  | ||||
|         classes = [obj.__class__ for obj in Human.objects] | ||||
|         self.assertEqual(classes, [Human]) | ||||
|         assert classes == [Human] | ||||
|  | ||||
|     def test_allow_inheritance(self): | ||||
|         """Ensure that inheritance is disabled by default on simple | ||||
| @@ -355,20 +335,18 @@ class TestInheritance(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|  | ||||
|         # can't inherit because Animal didn't explicitly allow inheritance | ||||
|         with self.assertRaises(ValueError) as cm: | ||||
|         with pytest.raises(ValueError, match="Document Animal may not be subclassed"): | ||||
|  | ||||
|             class Dog(Animal): | ||||
|                 pass | ||||
|  | ||||
|         self.assertIn("Document Animal may not be subclassed", str(cm.exception)) | ||||
|  | ||||
|         # Check that _cls etc aren't present on simple documents | ||||
|         dog = Animal(name="dog").save() | ||||
|         self.assertEqual(dog.to_mongo().keys(), ["_id", "name"]) | ||||
|         assert dog.to_mongo().keys() == ["_id", "name"] | ||||
|  | ||||
|         collection = self.db[Animal._get_collection_name()] | ||||
|         obj = collection.find_one() | ||||
|         self.assertNotIn("_cls", obj) | ||||
|         assert "_cls" not in obj | ||||
|  | ||||
|     def test_cant_turn_off_inheritance_on_subclass(self): | ||||
|         """Ensure if inheritance is on in a subclass you cant turn it off. | ||||
| @@ -378,14 +356,14 @@ class TestInheritance(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|             meta = {"allow_inheritance": True} | ||||
|  | ||||
|         with self.assertRaises(ValueError) as cm: | ||||
|         with pytest.raises(ValueError) as exc_info: | ||||
|  | ||||
|             class Mammal(Animal): | ||||
|                 meta = {"allow_inheritance": False} | ||||
|  | ||||
|         self.assertEqual( | ||||
|             str(cm.exception), | ||||
|             'Only direct subclasses of Document may set "allow_inheritance" to False', | ||||
|         assert ( | ||||
|             str(exc_info.value) | ||||
|             == 'Only direct subclasses of Document may set "allow_inheritance" to False' | ||||
|         ) | ||||
|  | ||||
|     def test_allow_inheritance_abstract_document(self): | ||||
| @@ -399,14 +377,14 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Animal(FinalDocument): | ||||
|             name = StringField() | ||||
|  | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|  | ||||
|             class Mammal(Animal): | ||||
|                 pass | ||||
|  | ||||
|         # Check that _cls isn't present in simple documents | ||||
|         doc = Animal(name="dog") | ||||
|         self.assertNotIn("_cls", doc.to_mongo()) | ||||
|         assert "_cls" not in doc.to_mongo() | ||||
|  | ||||
|     def test_using_abstract_class_in_reference_field(self): | ||||
|         # Ensures no regression of #1920 | ||||
| @@ -452,10 +430,10 @@ class TestInheritance(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|  | ||||
|         berlin = EuropeanCity(name="Berlin", continent="Europe") | ||||
|         self.assertEqual(len(berlin._db_field_map), len(berlin._fields_ordered)) | ||||
|         self.assertEqual(len(berlin._reverse_db_field_map), len(berlin._fields_ordered)) | ||||
|         self.assertEqual(len(berlin._fields_ordered), 3) | ||||
|         self.assertEqual(berlin._fields_ordered[0], "id") | ||||
|         assert len(berlin._db_field_map) == len(berlin._fields_ordered) | ||||
|         assert len(berlin._reverse_db_field_map) == len(berlin._fields_ordered) | ||||
|         assert len(berlin._fields_ordered) == 3 | ||||
|         assert berlin._fields_ordered[0] == "id" | ||||
|  | ||||
|     def test_auto_id_not_set_if_specific_in_parent_class(self): | ||||
|         class City(Document): | ||||
| @@ -467,10 +445,10 @@ class TestInheritance(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|  | ||||
|         berlin = EuropeanCity(name="Berlin", continent="Europe") | ||||
|         self.assertEqual(len(berlin._db_field_map), len(berlin._fields_ordered)) | ||||
|         self.assertEqual(len(berlin._reverse_db_field_map), len(berlin._fields_ordered)) | ||||
|         self.assertEqual(len(berlin._fields_ordered), 3) | ||||
|         self.assertEqual(berlin._fields_ordered[0], "city_id") | ||||
|         assert len(berlin._db_field_map) == len(berlin._fields_ordered) | ||||
|         assert len(berlin._reverse_db_field_map) == len(berlin._fields_ordered) | ||||
|         assert len(berlin._fields_ordered) == 3 | ||||
|         assert berlin._fields_ordered[0] == "city_id" | ||||
|  | ||||
|     def test_auto_id_vs_non_pk_id_field(self): | ||||
|         class City(Document): | ||||
| @@ -482,12 +460,12 @@ class TestInheritance(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|  | ||||
|         berlin = EuropeanCity(name="Berlin", continent="Europe") | ||||
|         self.assertEqual(len(berlin._db_field_map), len(berlin._fields_ordered)) | ||||
|         self.assertEqual(len(berlin._reverse_db_field_map), len(berlin._fields_ordered)) | ||||
|         self.assertEqual(len(berlin._fields_ordered), 4) | ||||
|         self.assertEqual(berlin._fields_ordered[0], "auto_id_0") | ||||
|         assert len(berlin._db_field_map) == len(berlin._fields_ordered) | ||||
|         assert len(berlin._reverse_db_field_map) == len(berlin._fields_ordered) | ||||
|         assert len(berlin._fields_ordered) == 4 | ||||
|         assert berlin._fields_ordered[0] == "auto_id_0" | ||||
|         berlin.save() | ||||
|         self.assertEqual(berlin.pk, berlin.auto_id_0) | ||||
|         assert berlin.pk == berlin.auto_id_0 | ||||
|  | ||||
|     def test_abstract_document_creation_does_not_fail(self): | ||||
|         class City(Document): | ||||
| @@ -495,9 +473,9 @@ class TestInheritance(MongoDBTestCase): | ||||
|             meta = {"abstract": True, "allow_inheritance": False} | ||||
|  | ||||
|         city = City(continent="asia") | ||||
|         self.assertEqual(None, city.pk) | ||||
|         assert city.pk is None | ||||
|         # TODO: expected error? Shouldn't we create a new error type? | ||||
|         with self.assertRaises(KeyError): | ||||
|         with pytest.raises(KeyError): | ||||
|             setattr(city, "pk", 1) | ||||
|  | ||||
|     def test_allow_inheritance_embedded_document(self): | ||||
| @@ -506,20 +484,20 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class Comment(EmbeddedDocument): | ||||
|             content = StringField() | ||||
|  | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|  | ||||
|             class SpecialComment(Comment): | ||||
|                 pass | ||||
|  | ||||
|         doc = Comment(content="test") | ||||
|         self.assertNotIn("_cls", doc.to_mongo()) | ||||
|         assert "_cls" not in doc.to_mongo() | ||||
|  | ||||
|         class Comment(EmbeddedDocument): | ||||
|             content = StringField() | ||||
|             meta = {"allow_inheritance": True} | ||||
|  | ||||
|         doc = Comment(content="test") | ||||
|         self.assertIn("_cls", doc.to_mongo()) | ||||
|         assert "_cls" in doc.to_mongo() | ||||
|  | ||||
|     def test_document_inheritance(self): | ||||
|         """Ensure mutliple inheritance of abstract documents | ||||
| @@ -537,7 +515,7 @@ class TestInheritance(MongoDBTestCase): | ||||
|                 pass | ||||
|  | ||||
|         except Exception: | ||||
|             self.assertTrue(False, "Couldn't create MyDocument class") | ||||
|             assert False, "Couldn't create MyDocument class" | ||||
|  | ||||
|     def test_abstract_documents(self): | ||||
|         """Ensure that a document superclass can be marked as abstract | ||||
| @@ -574,20 +552,20 @@ class TestInheritance(MongoDBTestCase): | ||||
|  | ||||
|         for k, v in iteritems(defaults): | ||||
|             for cls in [Animal, Fish, Guppy]: | ||||
|                 self.assertEqual(cls._meta[k], v) | ||||
|                 assert cls._meta[k] == v | ||||
|  | ||||
|         self.assertNotIn("collection", Animal._meta) | ||||
|         self.assertNotIn("collection", Mammal._meta) | ||||
|         assert "collection" not in Animal._meta | ||||
|         assert "collection" not in Mammal._meta | ||||
|  | ||||
|         self.assertEqual(Animal._get_collection_name(), None) | ||||
|         self.assertEqual(Mammal._get_collection_name(), None) | ||||
|         assert Animal._get_collection_name() is None | ||||
|         assert Mammal._get_collection_name() is None | ||||
|  | ||||
|         self.assertEqual(Fish._get_collection_name(), "fish") | ||||
|         self.assertEqual(Guppy._get_collection_name(), "fish") | ||||
|         self.assertEqual(Human._get_collection_name(), "human") | ||||
|         assert Fish._get_collection_name() == "fish" | ||||
|         assert Guppy._get_collection_name() == "fish" | ||||
|         assert Human._get_collection_name() == "human" | ||||
|  | ||||
|         # ensure that a subclass of a non-abstract class can't be abstract | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|  | ||||
|             class EvilHuman(Human): | ||||
|                 evil = BooleanField(default=True) | ||||
| @@ -601,7 +579,7 @@ class TestInheritance(MongoDBTestCase): | ||||
|         class B(A): | ||||
|             pass | ||||
|  | ||||
|         self.assertFalse(B._meta["abstract"]) | ||||
|         assert not B._meta["abstract"] | ||||
|  | ||||
|     def test_inherited_collections(self): | ||||
|         """Ensure that subclassed documents don't override parents' | ||||
| @@ -647,8 +625,8 @@ class TestInheritance(MongoDBTestCase): | ||||
|         real_person = Drinker(drink=beer) | ||||
|         real_person.save() | ||||
|  | ||||
|         self.assertEqual(Drinker.objects[0].drink.name, red_bull.name) | ||||
|         self.assertEqual(Drinker.objects[1].drink.name, beer.name) | ||||
|         assert Drinker.objects[0].drink.name == red_bull.name | ||||
|         assert Drinker.objects[1].drink.name == beer.name | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -32,7 +32,7 @@ class TestJson(MongoDBTestCase): | ||||
|  | ||||
|         expected_json = """{"embedded":{"string":"Inner Hello"},"string":"Hello"}""" | ||||
|  | ||||
|         self.assertEqual(doc_json, expected_json) | ||||
|         assert doc_json == expected_json | ||||
|  | ||||
|     def test_json_simple(self): | ||||
|         class Embedded(EmbeddedDocument): | ||||
| @@ -52,9 +52,9 @@ class TestJson(MongoDBTestCase): | ||||
|  | ||||
|         doc_json = doc.to_json(sort_keys=True, separators=(",", ":")) | ||||
|         expected_json = """{"embedded_field":{"string":"Hi"},"string":"Hi"}""" | ||||
|         self.assertEqual(doc_json, expected_json) | ||||
|         assert doc_json == expected_json | ||||
|  | ||||
|         self.assertEqual(doc, Doc.from_json(doc.to_json())) | ||||
|         assert doc == Doc.from_json(doc.to_json()) | ||||
|  | ||||
|     def test_json_complex(self): | ||||
|         class EmbeddedDoc(EmbeddedDocument): | ||||
| @@ -99,7 +99,7 @@ class TestJson(MongoDBTestCase): | ||||
|                 return json.loads(self.to_json()) == json.loads(other.to_json()) | ||||
|  | ||||
|         doc = Doc() | ||||
|         self.assertEqual(doc, Doc.from_json(doc.to_json())) | ||||
|         assert doc == Doc.from_json(doc.to_json()) | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
| import unittest | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
| @@ -11,12 +13,12 @@ class TestValidatorError(MongoDBTestCase): | ||||
|         """Ensure a ValidationError handles error to_dict correctly. | ||||
|         """ | ||||
|         error = ValidationError("root") | ||||
|         self.assertEqual(error.to_dict(), {}) | ||||
|         assert error.to_dict() == {} | ||||
|  | ||||
|         # 1st level error schema | ||||
|         error.errors = {"1st": ValidationError("bad 1st")} | ||||
|         self.assertIn("1st", error.to_dict()) | ||||
|         self.assertEqual(error.to_dict()["1st"], "bad 1st") | ||||
|         assert "1st" in error.to_dict() | ||||
|         assert error.to_dict()["1st"] == "bad 1st" | ||||
|  | ||||
|         # 2nd level error schema | ||||
|         error.errors = { | ||||
| @@ -24,10 +26,10 @@ class TestValidatorError(MongoDBTestCase): | ||||
|                 "bad 1st", errors={"2nd": ValidationError("bad 2nd")} | ||||
|             ) | ||||
|         } | ||||
|         self.assertIn("1st", error.to_dict()) | ||||
|         self.assertIsInstance(error.to_dict()["1st"], dict) | ||||
|         self.assertIn("2nd", error.to_dict()["1st"]) | ||||
|         self.assertEqual(error.to_dict()["1st"]["2nd"], "bad 2nd") | ||||
|         assert "1st" in error.to_dict() | ||||
|         assert isinstance(error.to_dict()["1st"], dict) | ||||
|         assert "2nd" in error.to_dict()["1st"] | ||||
|         assert error.to_dict()["1st"]["2nd"] == "bad 2nd" | ||||
|  | ||||
|         # moar levels | ||||
|         error.errors = { | ||||
| @@ -45,13 +47,13 @@ class TestValidatorError(MongoDBTestCase): | ||||
|                 }, | ||||
|             ) | ||||
|         } | ||||
|         self.assertIn("1st", error.to_dict()) | ||||
|         self.assertIn("2nd", error.to_dict()["1st"]) | ||||
|         self.assertIn("3rd", error.to_dict()["1st"]["2nd"]) | ||||
|         self.assertIn("4th", error.to_dict()["1st"]["2nd"]["3rd"]) | ||||
|         self.assertEqual(error.to_dict()["1st"]["2nd"]["3rd"]["4th"], "Inception") | ||||
|         assert "1st" in error.to_dict() | ||||
|         assert "2nd" in error.to_dict()["1st"] | ||||
|         assert "3rd" in error.to_dict()["1st"]["2nd"] | ||||
|         assert "4th" in error.to_dict()["1st"]["2nd"]["3rd"] | ||||
|         assert error.to_dict()["1st"]["2nd"]["3rd"]["4th"] == "Inception" | ||||
|  | ||||
|         self.assertEqual(error.message, "root(2nd.3rd.4th.Inception: ['1st'])") | ||||
|         assert error.message == "root(2nd.3rd.4th.Inception: ['1st'])" | ||||
|  | ||||
|     def test_model_validation(self): | ||||
|         class User(Document): | ||||
| @@ -61,19 +63,19 @@ class TestValidatorError(MongoDBTestCase): | ||||
|         try: | ||||
|             User().validate() | ||||
|         except ValidationError as e: | ||||
|             self.assertIn("User:None", e.message) | ||||
|             self.assertEqual( | ||||
|                 e.to_dict(), | ||||
|                 {"username": "Field is required", "name": "Field is required"}, | ||||
|             ) | ||||
|             assert "User:None" in e.message | ||||
|             assert e.to_dict() == { | ||||
|                 "username": "Field is required", | ||||
|                 "name": "Field is required", | ||||
|             } | ||||
|  | ||||
|         user = User(username="RossC0", name="Ross").save() | ||||
|         user.name = None | ||||
|         try: | ||||
|             user.save() | ||||
|         except ValidationError as e: | ||||
|             self.assertIn("User:RossC0", e.message) | ||||
|             self.assertEqual(e.to_dict(), {"name": "Field is required"}) | ||||
|             assert "User:RossC0" in e.message | ||||
|             assert e.to_dict() == {"name": "Field is required"} | ||||
|  | ||||
|     def test_fields_rewrite(self): | ||||
|         class BasePerson(Document): | ||||
| @@ -85,7 +87,8 @@ class TestValidatorError(MongoDBTestCase): | ||||
|             name = StringField(required=True) | ||||
|  | ||||
|         p = Person(age=15) | ||||
|         self.assertRaises(ValidationError, p.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             p.validate() | ||||
|  | ||||
|     def test_embedded_document_validation(self): | ||||
|         """Ensure that embedded documents may be validated. | ||||
| @@ -96,17 +99,19 @@ class TestValidatorError(MongoDBTestCase): | ||||
|             content = StringField(required=True) | ||||
|  | ||||
|         comment = Comment() | ||||
|         self.assertRaises(ValidationError, comment.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             comment.validate() | ||||
|  | ||||
|         comment.content = "test" | ||||
|         comment.validate() | ||||
|  | ||||
|         comment.date = 4 | ||||
|         self.assertRaises(ValidationError, comment.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             comment.validate() | ||||
|  | ||||
|         comment.date = datetime.now() | ||||
|         comment.validate() | ||||
|         self.assertEqual(comment._instance, None) | ||||
|         assert comment._instance is None | ||||
|  | ||||
|     def test_embedded_db_field_validate(self): | ||||
|         class SubDoc(EmbeddedDocument): | ||||
| @@ -119,10 +124,8 @@ class TestValidatorError(MongoDBTestCase): | ||||
|         try: | ||||
|             Doc(id="bad").validate() | ||||
|         except ValidationError as e: | ||||
|             self.assertIn("SubDoc:None", e.message) | ||||
|             self.assertEqual( | ||||
|                 e.to_dict(), {"e": {"val": "OK could not be converted to int"}} | ||||
|             ) | ||||
|             assert "SubDoc:None" in e.message | ||||
|             assert e.to_dict() == {"e": {"val": "OK could not be converted to int"}} | ||||
|  | ||||
|         Doc.drop_collection() | ||||
|  | ||||
| @@ -130,18 +133,16 @@ class TestValidatorError(MongoDBTestCase): | ||||
|  | ||||
|         doc = Doc.objects.first() | ||||
|         keys = doc._data.keys() | ||||
|         self.assertEqual(2, len(keys)) | ||||
|         self.assertIn("e", keys) | ||||
|         self.assertIn("id", keys) | ||||
|         assert 2 == len(keys) | ||||
|         assert "e" in keys | ||||
|         assert "id" in keys | ||||
|  | ||||
|         doc.e.val = "OK" | ||||
|         try: | ||||
|             doc.save() | ||||
|         except ValidationError as e: | ||||
|             self.assertIn("Doc:test", e.message) | ||||
|             self.assertEqual( | ||||
|                 e.to_dict(), {"e": {"val": "OK could not be converted to int"}} | ||||
|             ) | ||||
|             assert "Doc:test" in e.message | ||||
|             assert e.to_dict() == {"e": {"val": "OK could not be converted to int"}} | ||||
|  | ||||
|     def test_embedded_weakref(self): | ||||
|         class SubDoc(EmbeddedDocument): | ||||
| @@ -157,14 +158,16 @@ class TestValidatorError(MongoDBTestCase): | ||||
|  | ||||
|         s = SubDoc() | ||||
|  | ||||
|         self.assertRaises(ValidationError, s.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             s.validate() | ||||
|  | ||||
|         d1.e = s | ||||
|         d2.e = s | ||||
|  | ||||
|         del d1 | ||||
|  | ||||
|         self.assertRaises(ValidationError, d2.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             d2.validate() | ||||
|  | ||||
|     def test_parent_reference_in_child_document(self): | ||||
|         """ | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| import uuid | ||||
|  | ||||
| from bson import Binary | ||||
| from nose.plugins.skip import SkipTest | ||||
| import pytest | ||||
| import six | ||||
|  | ||||
| from mongoengine import * | ||||
| @@ -31,8 +31,8 @@ class TestBinaryField(MongoDBTestCase): | ||||
|         attachment.save() | ||||
|  | ||||
|         attachment_1 = Attachment.objects().first() | ||||
|         self.assertEqual(MIME_TYPE, attachment_1.content_type) | ||||
|         self.assertEqual(BLOB, six.binary_type(attachment_1.blob)) | ||||
|         assert MIME_TYPE == attachment_1.content_type | ||||
|         assert BLOB == six.binary_type(attachment_1.blob) | ||||
|  | ||||
|     def test_validation_succeeds(self): | ||||
|         """Ensure that valid values can be assigned to binary fields. | ||||
| @@ -45,13 +45,15 @@ class TestBinaryField(MongoDBTestCase): | ||||
|             blob = BinaryField(max_bytes=4) | ||||
|  | ||||
|         attachment_required = AttachmentRequired() | ||||
|         self.assertRaises(ValidationError, attachment_required.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             attachment_required.validate() | ||||
|         attachment_required.blob = Binary(six.b("\xe6\x00\xc4\xff\x07")) | ||||
|         attachment_required.validate() | ||||
|  | ||||
|         _5_BYTES = six.b("\xe6\x00\xc4\xff\x07") | ||||
|         _4_BYTES = six.b("\xe6\x00\xc4\xff") | ||||
|         self.assertRaises(ValidationError, AttachmentSizeLimit(blob=_5_BYTES).validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             AttachmentSizeLimit(blob=_5_BYTES).validate() | ||||
|         AttachmentSizeLimit(blob=_4_BYTES).validate() | ||||
|  | ||||
|     def test_validation_fails(self): | ||||
| @@ -61,7 +63,8 @@ class TestBinaryField(MongoDBTestCase): | ||||
|             blob = BinaryField() | ||||
|  | ||||
|         for invalid_data in (2, u"Im_a_unicode", ["some_str"]): | ||||
|             self.assertRaises(ValidationError, Attachment(blob=invalid_data).validate) | ||||
|             with pytest.raises(ValidationError): | ||||
|                 Attachment(blob=invalid_data).validate() | ||||
|  | ||||
|     def test__primary(self): | ||||
|         class Attachment(Document): | ||||
| @@ -70,10 +73,10 @@ class TestBinaryField(MongoDBTestCase): | ||||
|         Attachment.drop_collection() | ||||
|         binary_id = uuid.uuid4().bytes | ||||
|         att = Attachment(id=binary_id).save() | ||||
|         self.assertEqual(1, Attachment.objects.count()) | ||||
|         self.assertEqual(1, Attachment.objects.filter(id=att.id).count()) | ||||
|         assert 1 == Attachment.objects.count() | ||||
|         assert 1 == Attachment.objects.filter(id=att.id).count() | ||||
|         att.delete() | ||||
|         self.assertEqual(0, Attachment.objects.count()) | ||||
|         assert 0 == Attachment.objects.count() | ||||
|  | ||||
|     def test_primary_filter_by_binary_pk_as_str(self): | ||||
|         class Attachment(Document): | ||||
| @@ -82,9 +85,9 @@ class TestBinaryField(MongoDBTestCase): | ||||
|         Attachment.drop_collection() | ||||
|         binary_id = uuid.uuid4().bytes | ||||
|         att = Attachment(id=binary_id).save() | ||||
|         self.assertEqual(1, Attachment.objects.filter(id=binary_id).count()) | ||||
|         assert 1 == Attachment.objects.filter(id=binary_id).count() | ||||
|         att.delete() | ||||
|         self.assertEqual(0, Attachment.objects.count()) | ||||
|         assert 0 == Attachment.objects.count() | ||||
|  | ||||
|     def test_match_querying_with_bytes(self): | ||||
|         class MyDocument(Document): | ||||
| @@ -94,7 +97,7 @@ class TestBinaryField(MongoDBTestCase): | ||||
|  | ||||
|         doc = MyDocument(bin_field=BIN_VALUE).save() | ||||
|         matched_doc = MyDocument.objects(bin_field=BIN_VALUE).first() | ||||
|         self.assertEqual(matched_doc.id, doc.id) | ||||
|         assert matched_doc.id == doc.id | ||||
|  | ||||
|     def test_match_querying_with_binary(self): | ||||
|         class MyDocument(Document): | ||||
| @@ -105,7 +108,7 @@ class TestBinaryField(MongoDBTestCase): | ||||
|         doc = MyDocument(bin_field=BIN_VALUE).save() | ||||
|  | ||||
|         matched_doc = MyDocument.objects(bin_field=Binary(BIN_VALUE)).first() | ||||
|         self.assertEqual(matched_doc.id, doc.id) | ||||
|         assert matched_doc.id == doc.id | ||||
|  | ||||
|     def test_modify_operation__set(self): | ||||
|         """Ensures no regression of bug #1127""" | ||||
| @@ -119,11 +122,11 @@ class TestBinaryField(MongoDBTestCase): | ||||
|         doc = MyDocument.objects(some_field="test").modify( | ||||
|             upsert=True, new=True, set__bin_field=BIN_VALUE | ||||
|         ) | ||||
|         self.assertEqual(doc.some_field, "test") | ||||
|         assert doc.some_field == "test" | ||||
|         if six.PY3: | ||||
|             self.assertEqual(doc.bin_field, BIN_VALUE) | ||||
|             assert doc.bin_field == BIN_VALUE | ||||
|         else: | ||||
|             self.assertEqual(doc.bin_field, Binary(BIN_VALUE)) | ||||
|             assert doc.bin_field == Binary(BIN_VALUE) | ||||
|  | ||||
|     def test_update_one(self): | ||||
|         """Ensures no regression of bug #1127""" | ||||
| @@ -139,9 +142,9 @@ class TestBinaryField(MongoDBTestCase): | ||||
|         n_updated = MyDocument.objects(bin_field=bin_data).update_one( | ||||
|             bin_field=BIN_VALUE | ||||
|         ) | ||||
|         self.assertEqual(n_updated, 1) | ||||
|         assert n_updated == 1 | ||||
|         fetched = MyDocument.objects.with_id(doc.id) | ||||
|         if six.PY3: | ||||
|             self.assertEqual(fetched.bin_field, BIN_VALUE) | ||||
|             assert fetched.bin_field == BIN_VALUE | ||||
|         else: | ||||
|             self.assertEqual(fetched.bin_field, Binary(BIN_VALUE)) | ||||
|             assert fetched.bin_field == Binary(BIN_VALUE) | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| from mongoengine import * | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase, get_as_pymongo | ||||
|  | ||||
|  | ||||
| @@ -11,7 +12,7 @@ class TestBooleanField(MongoDBTestCase): | ||||
|  | ||||
|         person = Person(admin=True) | ||||
|         person.save() | ||||
|         self.assertEqual(get_as_pymongo(person), {"_id": person.id, "admin": True}) | ||||
|         assert get_as_pymongo(person) == {"_id": person.id, "admin": True} | ||||
|  | ||||
|     def test_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to boolean | ||||
| @@ -26,11 +27,14 @@ class TestBooleanField(MongoDBTestCase): | ||||
|         person.validate() | ||||
|  | ||||
|         person.admin = 2 | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.admin = "Yes" | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.admin = "False" | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|     def test_weirdness_constructor(self): | ||||
|         """When attribute is set in contructor, it gets cast into a bool | ||||
| @@ -42,7 +46,7 @@ class TestBooleanField(MongoDBTestCase): | ||||
|             admin = BooleanField() | ||||
|  | ||||
|         new_person = Person(admin="False") | ||||
|         self.assertTrue(new_person.admin) | ||||
|         assert new_person.admin | ||||
|  | ||||
|         new_person = Person(admin="0") | ||||
|         self.assertTrue(new_person.admin) | ||||
|         assert new_person.admin | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| from decimal import Decimal | ||||
|  | ||||
| from mongoengine import * | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| @@ -46,29 +47,29 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         a = Animal(name="Leopard", tag="heavy") | ||||
|         a.save() | ||||
|  | ||||
|         self.assertEqual(Animal._cached_reference_fields, [Ocorrence.animal]) | ||||
|         assert Animal._cached_reference_fields == [Ocorrence.animal] | ||||
|         o = Ocorrence(person="teste", animal=a) | ||||
|         o.save() | ||||
|  | ||||
|         p = Ocorrence(person="Wilson") | ||||
|         p.save() | ||||
|  | ||||
|         self.assertEqual(Ocorrence.objects(animal=None).count(), 1) | ||||
|         assert Ocorrence.objects(animal=None).count() == 1 | ||||
|  | ||||
|         self.assertEqual(a.to_mongo(fields=["tag"]), {"tag": "heavy", "_id": a.pk}) | ||||
|         assert a.to_mongo(fields=["tag"]) == {"tag": "heavy", "_id": a.pk} | ||||
|  | ||||
|         self.assertEqual(o.to_mongo()["animal"]["tag"], "heavy") | ||||
|         assert o.to_mongo()["animal"]["tag"] == "heavy" | ||||
|  | ||||
|         # counts | ||||
|         Ocorrence(person="teste 2").save() | ||||
|         Ocorrence(person="teste 3").save() | ||||
|  | ||||
|         count = Ocorrence.objects(animal__tag="heavy").count() | ||||
|         self.assertEqual(count, 1) | ||||
|         assert count == 1 | ||||
|  | ||||
|         ocorrence = Ocorrence.objects(animal__tag="heavy").first() | ||||
|         self.assertEqual(ocorrence.person, "teste") | ||||
|         self.assertIsInstance(ocorrence.animal, Animal) | ||||
|         assert ocorrence.person == "teste" | ||||
|         assert isinstance(ocorrence.animal, Animal) | ||||
|  | ||||
|     def test_with_decimal(self): | ||||
|         class PersonAuto(Document): | ||||
| @@ -88,10 +89,11 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         s = SocialTest(group="dev", person=p) | ||||
|         s.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             SocialTest.objects._collection.find_one({"person.salary": 7000.00}), | ||||
|             {"_id": s.pk, "group": s.group, "person": {"_id": p.pk, "salary": 7000.00}}, | ||||
|         ) | ||||
|         assert SocialTest.objects._collection.find_one({"person.salary": 7000.00}) == { | ||||
|             "_id": s.pk, | ||||
|             "group": s.group, | ||||
|             "person": {"_id": p.pk, "salary": 7000.00}, | ||||
|         } | ||||
|  | ||||
|     def test_cached_reference_field_reference(self): | ||||
|         class Group(Document): | ||||
| @@ -131,18 +133,15 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         s2 = SocialData(obs="testing 321", person=p3, tags=["tag3", "tag4"]) | ||||
|         s2.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             SocialData.objects._collection.find_one({"tags": "tag2"}), | ||||
|             { | ||||
|                 "_id": s1.pk, | ||||
|                 "obs": "testing 123", | ||||
|                 "tags": ["tag1", "tag2"], | ||||
|                 "person": {"_id": p1.pk, "group": g1.pk}, | ||||
|             }, | ||||
|         ) | ||||
|         assert SocialData.objects._collection.find_one({"tags": "tag2"}) == { | ||||
|             "_id": s1.pk, | ||||
|             "obs": "testing 123", | ||||
|             "tags": ["tag1", "tag2"], | ||||
|             "person": {"_id": p1.pk, "group": g1.pk}, | ||||
|         } | ||||
|  | ||||
|         self.assertEqual(SocialData.objects(person__group=g2).count(), 1) | ||||
|         self.assertEqual(SocialData.objects(person__group=g2).first(), s2) | ||||
|         assert SocialData.objects(person__group=g2).count() == 1 | ||||
|         assert SocialData.objects(person__group=g2).first() == s2 | ||||
|  | ||||
|     def test_cached_reference_field_push_with_fields(self): | ||||
|         class Product(Document): | ||||
| @@ -157,26 +156,20 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         product1 = Product(name="abc").save() | ||||
|         product2 = Product(name="def").save() | ||||
|         basket = Basket(products=[product1]).save() | ||||
|         self.assertEqual( | ||||
|             Basket.objects._collection.find_one(), | ||||
|             { | ||||
|                 "_id": basket.pk, | ||||
|                 "products": [{"_id": product1.pk, "name": product1.name}], | ||||
|             }, | ||||
|         ) | ||||
|         assert Basket.objects._collection.find_one() == { | ||||
|             "_id": basket.pk, | ||||
|             "products": [{"_id": product1.pk, "name": product1.name}], | ||||
|         } | ||||
|         # push to list | ||||
|         basket.update(push__products=product2) | ||||
|         basket.reload() | ||||
|         self.assertEqual( | ||||
|             Basket.objects._collection.find_one(), | ||||
|             { | ||||
|                 "_id": basket.pk, | ||||
|                 "products": [ | ||||
|                     {"_id": product1.pk, "name": product1.name}, | ||||
|                     {"_id": product2.pk, "name": product2.name}, | ||||
|                 ], | ||||
|             }, | ||||
|         ) | ||||
|         assert Basket.objects._collection.find_one() == { | ||||
|             "_id": basket.pk, | ||||
|             "products": [ | ||||
|                 {"_id": product1.pk, "name": product1.name}, | ||||
|                 {"_id": product2.pk, "name": product2.name}, | ||||
|             ], | ||||
|         } | ||||
|  | ||||
|     def test_cached_reference_field_update_all(self): | ||||
|         class Person(Document): | ||||
| @@ -194,37 +187,31 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         a2.save() | ||||
|  | ||||
|         a2 = Person.objects.with_id(a2.id) | ||||
|         self.assertEqual(a2.father.tp, a1.tp) | ||||
|         assert a2.father.tp == a1.tp | ||||
|  | ||||
|         self.assertEqual( | ||||
|             dict(a2.to_mongo()), | ||||
|             { | ||||
|                 "_id": a2.pk, | ||||
|                 "name": u"Wilson Junior", | ||||
|                 "tp": u"pf", | ||||
|                 "father": {"_id": a1.pk, "tp": u"pj"}, | ||||
|             }, | ||||
|         ) | ||||
|         assert dict(a2.to_mongo()) == { | ||||
|             "_id": a2.pk, | ||||
|             "name": u"Wilson Junior", | ||||
|             "tp": u"pf", | ||||
|             "father": {"_id": a1.pk, "tp": u"pj"}, | ||||
|         } | ||||
|  | ||||
|         self.assertEqual(Person.objects(father=a1)._query, {"father._id": a1.pk}) | ||||
|         self.assertEqual(Person.objects(father=a1).count(), 1) | ||||
|         assert Person.objects(father=a1)._query == {"father._id": a1.pk} | ||||
|         assert Person.objects(father=a1).count() == 1 | ||||
|  | ||||
|         Person.objects.update(set__tp="pf") | ||||
|         Person.father.sync_all() | ||||
|  | ||||
|         a2.reload() | ||||
|         self.assertEqual( | ||||
|             dict(a2.to_mongo()), | ||||
|             { | ||||
|                 "_id": a2.pk, | ||||
|                 "name": u"Wilson Junior", | ||||
|                 "tp": u"pf", | ||||
|                 "father": {"_id": a1.pk, "tp": u"pf"}, | ||||
|             }, | ||||
|         ) | ||||
|         assert dict(a2.to_mongo()) == { | ||||
|             "_id": a2.pk, | ||||
|             "name": u"Wilson Junior", | ||||
|             "tp": u"pf", | ||||
|             "father": {"_id": a1.pk, "tp": u"pf"}, | ||||
|         } | ||||
|  | ||||
|     def test_cached_reference_fields_on_embedded_documents(self): | ||||
|         with self.assertRaises(InvalidDocumentError): | ||||
|         with pytest.raises(InvalidDocumentError): | ||||
|  | ||||
|             class Test(Document): | ||||
|                 name = StringField() | ||||
| @@ -255,15 +242,12 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         a1.save() | ||||
|  | ||||
|         a2.reload() | ||||
|         self.assertEqual( | ||||
|             dict(a2.to_mongo()), | ||||
|             { | ||||
|                 "_id": a2.pk, | ||||
|                 "name": "Wilson Junior", | ||||
|                 "tp": "pf", | ||||
|                 "father": {"_id": a1.pk, "tp": "pf"}, | ||||
|             }, | ||||
|         ) | ||||
|         assert dict(a2.to_mongo()) == { | ||||
|             "_id": a2.pk, | ||||
|             "name": "Wilson Junior", | ||||
|             "tp": "pf", | ||||
|             "father": {"_id": a1.pk, "tp": "pf"}, | ||||
|         } | ||||
|  | ||||
|     def test_cached_reference_auto_sync_disabled(self): | ||||
|         class Persone(Document): | ||||
| @@ -284,15 +268,12 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         a1.tp = "pf" | ||||
|         a1.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             Persone.objects._collection.find_one({"_id": a2.pk}), | ||||
|             { | ||||
|                 "_id": a2.pk, | ||||
|                 "name": "Wilson Junior", | ||||
|                 "tp": "pf", | ||||
|                 "father": {"_id": a1.pk, "tp": "pj"}, | ||||
|             }, | ||||
|         ) | ||||
|         assert Persone.objects._collection.find_one({"_id": a2.pk}) == { | ||||
|             "_id": a2.pk, | ||||
|             "name": "Wilson Junior", | ||||
|             "tp": "pf", | ||||
|             "father": {"_id": a1.pk, "tp": "pj"}, | ||||
|         } | ||||
|  | ||||
|     def test_cached_reference_embedded_fields(self): | ||||
|         class Owner(EmbeddedDocument): | ||||
| @@ -320,28 +301,29 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         o = Ocorrence(person="teste", animal=a) | ||||
|         o.save() | ||||
|         self.assertEqual( | ||||
|             dict(a.to_mongo(fields=["tag", "owner.tp"])), | ||||
|             {"_id": a.pk, "tag": "heavy", "owner": {"t": "u"}}, | ||||
|         ) | ||||
|         self.assertEqual(o.to_mongo()["animal"]["tag"], "heavy") | ||||
|         self.assertEqual(o.to_mongo()["animal"]["owner"]["t"], "u") | ||||
|         assert dict(a.to_mongo(fields=["tag", "owner.tp"])) == { | ||||
|             "_id": a.pk, | ||||
|             "tag": "heavy", | ||||
|             "owner": {"t": "u"}, | ||||
|         } | ||||
|         assert o.to_mongo()["animal"]["tag"] == "heavy" | ||||
|         assert o.to_mongo()["animal"]["owner"]["t"] == "u" | ||||
|  | ||||
|         # Check to_mongo with fields | ||||
|         self.assertNotIn("animal", o.to_mongo(fields=["person"])) | ||||
|         assert "animal" not in o.to_mongo(fields=["person"]) | ||||
|  | ||||
|         # counts | ||||
|         Ocorrence(person="teste 2").save() | ||||
|         Ocorrence(person="teste 3").save() | ||||
|  | ||||
|         count = Ocorrence.objects(animal__tag="heavy", animal__owner__tp="u").count() | ||||
|         self.assertEqual(count, 1) | ||||
|         assert count == 1 | ||||
|  | ||||
|         ocorrence = Ocorrence.objects( | ||||
|             animal__tag="heavy", animal__owner__tp="u" | ||||
|         ).first() | ||||
|         self.assertEqual(ocorrence.person, "teste") | ||||
|         self.assertIsInstance(ocorrence.animal, Animal) | ||||
|         assert ocorrence.person == "teste" | ||||
|         assert isinstance(ocorrence.animal, Animal) | ||||
|  | ||||
|     def test_cached_reference_embedded_list_fields(self): | ||||
|         class Owner(EmbeddedDocument): | ||||
| @@ -370,13 +352,14 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         o = Ocorrence(person="teste 2", animal=a) | ||||
|         o.save() | ||||
|         self.assertEqual( | ||||
|             dict(a.to_mongo(fields=["tag", "owner.tags"])), | ||||
|             {"_id": a.pk, "tag": "heavy", "owner": {"tags": ["cool", "funny"]}}, | ||||
|         ) | ||||
|         assert dict(a.to_mongo(fields=["tag", "owner.tags"])) == { | ||||
|             "_id": a.pk, | ||||
|             "tag": "heavy", | ||||
|             "owner": {"tags": ["cool", "funny"]}, | ||||
|         } | ||||
|  | ||||
|         self.assertEqual(o.to_mongo()["animal"]["tag"], "heavy") | ||||
|         self.assertEqual(o.to_mongo()["animal"]["owner"]["tags"], ["cool", "funny"]) | ||||
|         assert o.to_mongo()["animal"]["tag"] == "heavy" | ||||
|         assert o.to_mongo()["animal"]["owner"]["tags"] == ["cool", "funny"] | ||||
|  | ||||
|         # counts | ||||
|         Ocorrence(person="teste 2").save() | ||||
| @@ -385,10 +368,10 @@ class TestCachedReferenceField(MongoDBTestCase): | ||||
|         query = Ocorrence.objects( | ||||
|             animal__tag="heavy", animal__owner__tags="cool" | ||||
|         )._query | ||||
|         self.assertEqual(query, {"animal.owner.tags": "cool", "animal.tag": "heavy"}) | ||||
|         assert query == {"animal.owner.tags": "cool", "animal.tag": "heavy"} | ||||
|  | ||||
|         ocorrence = Ocorrence.objects( | ||||
|             animal__tag="heavy", animal__owner__tags="cool" | ||||
|         ).first() | ||||
|         self.assertEqual(ocorrence.person, "teste 2") | ||||
|         self.assertIsInstance(ocorrence.animal, Animal) | ||||
|         assert ocorrence.person == "teste 2" | ||||
|         assert isinstance(ocorrence.animal, Animal) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime | ||||
| import math | ||||
| import itertools | ||||
| import math | ||||
| import re | ||||
|  | ||||
| from mongoengine import * | ||||
| @@ -28,7 +28,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|         assert log.date == d1 | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond - with | ||||
|         # default datetimefields | ||||
| @@ -36,7 +36,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|         assert log.date == d1 | ||||
|  | ||||
|         # Pre UTC dates microseconds below 1000 are dropped - with default | ||||
|         # datetimefields | ||||
| @@ -44,7 +44,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1) | ||||
|         assert 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 | ||||
| @@ -54,9 +54,9 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertEqual(log.date, d1) | ||||
|             assert log.date == d1 | ||||
|             log1 = LogEntry.objects.get(date=d1) | ||||
|             self.assertEqual(log, log1) | ||||
|             assert log == log1 | ||||
|  | ||||
|         # Test string padding | ||||
|         microsecond = map(int, [math.pow(10, x) for x in range(6)]) | ||||
| @@ -64,7 +64,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|  | ||||
|         for values in itertools.product([2014], mm, dd, hh, ii, ss, microsecond): | ||||
|             stored = LogEntry(date=datetime.datetime(*values)).to_mongo()["date"] | ||||
|             self.assertTrue( | ||||
|             assert ( | ||||
|                 re.match("^\d{4},\d{2},\d{2},\d{2},\d{2},\d{2},\d{6}$", stored) | ||||
|                 is not None | ||||
|             ) | ||||
| @@ -73,7 +73,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()[ | ||||
|             "date_with_dots" | ||||
|         ] | ||||
|         self.assertTrue( | ||||
|         assert ( | ||||
|             re.match("^\d{4}.\d{2}.\d{2}.\d{2}.\d{2}.\d{2}.\d{6}$", stored) is not None | ||||
|         ) | ||||
|  | ||||
| @@ -93,40 +93,40 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         log.save() | ||||
|  | ||||
|         log1 = LogEntry.objects.get(date=d1) | ||||
|         self.assertEqual(log, log1) | ||||
|         assert 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) | ||||
|         assert 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) | ||||
|             assert 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) | ||||
|             assert 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) | ||||
|         assert logs.count() == 30 | ||||
|  | ||||
|         logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 30) | ||||
|         assert 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) | ||||
|         assert logs.count() == 10 | ||||
|  | ||||
|         LogEntry.drop_collection() | ||||
|  | ||||
| @@ -137,17 +137,17 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         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) | ||||
|             assert 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) | ||||
|             assert 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) | ||||
|         assert logs.count() == 4 | ||||
|  | ||||
|     def test_no_default_value(self): | ||||
|         class Log(Document): | ||||
| @@ -156,11 +156,11 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertIsNone(log.timestamp) | ||||
|         assert log.timestamp is None | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertIsNone(fetched_log.timestamp) | ||||
|         assert fetched_log.timestamp is None | ||||
|  | ||||
|     def test_default_static_value(self): | ||||
|         NOW = datetime.datetime.utcnow() | ||||
| @@ -171,11 +171,11 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertEqual(log.timestamp, NOW) | ||||
|         assert log.timestamp == NOW | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertEqual(fetched_log.timestamp, NOW) | ||||
|         assert fetched_log.timestamp == NOW | ||||
|  | ||||
|     def test_default_callable(self): | ||||
|         NOW = datetime.datetime.utcnow() | ||||
| @@ -186,8 +186,8 @@ class ComplexDateTimeFieldTest(MongoDBTestCase): | ||||
|         Log.drop_collection() | ||||
|  | ||||
|         log = Log() | ||||
|         self.assertGreaterEqual(log.timestamp, NOW) | ||||
|         assert log.timestamp >= NOW | ||||
|         log.save() | ||||
|  | ||||
|         fetched_log = Log.objects.with_id(log.id) | ||||
|         self.assertGreaterEqual(fetched_log.timestamp, NOW) | ||||
|         assert fetched_log.timestamp >= NOW | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime | ||||
|  | ||||
| import pytest | ||||
| import six | ||||
|  | ||||
| try: | ||||
| @@ -8,7 +10,6 @@ except ImportError: | ||||
|     dateutil = None | ||||
|  | ||||
| from mongoengine import * | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| @@ -23,7 +24,8 @@ class TestDateField(MongoDBTestCase): | ||||
|             dt = DateField() | ||||
|  | ||||
|         md = MyDoc(dt="") | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             md.save() | ||||
|  | ||||
|     def test_date_from_whitespace_string(self): | ||||
|         """ | ||||
| @@ -35,7 +37,8 @@ class TestDateField(MongoDBTestCase): | ||||
|             dt = DateField() | ||||
|  | ||||
|         md = MyDoc(dt="   ") | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             md.save() | ||||
|  | ||||
|     def test_default_values_today(self): | ||||
|         """Ensure that default field values are used when creating | ||||
| @@ -47,9 +50,9 @@ class TestDateField(MongoDBTestCase): | ||||
|  | ||||
|         person = Person() | ||||
|         person.validate() | ||||
|         self.assertEqual(person.day, person.day) | ||||
|         self.assertEqual(person.day, datetime.date.today()) | ||||
|         self.assertEqual(person._data["day"], person.day) | ||||
|         assert person.day == person.day | ||||
|         assert person.day == datetime.date.today() | ||||
|         assert person._data["day"] == person.day | ||||
|  | ||||
|     def test_date(self): | ||||
|         """Tests showing pymongo date fields | ||||
| @@ -67,7 +70,7 @@ class TestDateField(MongoDBTestCase): | ||||
|         log.date = datetime.date.today() | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, datetime.date.today()) | ||||
|         assert log.date == datetime.date.today() | ||||
|  | ||||
|         d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999) | ||||
|         d2 = datetime.datetime(1970, 1, 1, 0, 0, 1) | ||||
| @@ -75,16 +78,16 @@ class TestDateField(MongoDBTestCase): | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date, d1.date()) | ||||
|         self.assertEqual(log.date, d2.date()) | ||||
|         assert log.date == d1.date() | ||||
|         assert 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()) | ||||
|         assert log.date == d1.date() | ||||
|         assert log.date == d2.date() | ||||
|  | ||||
|         if not six.PY3: | ||||
|             # Pre UTC dates microseconds below 1000 are dropped | ||||
| @@ -94,8 +97,8 @@ class TestDateField(MongoDBTestCase): | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertEqual(log.date, d1.date()) | ||||
|             self.assertEqual(log.date, d2.date()) | ||||
|             assert log.date == d1.date() | ||||
|             assert log.date == d2.date() | ||||
|  | ||||
|     def test_regular_usage(self): | ||||
|         """Tests for regular datetime fields""" | ||||
| @@ -113,35 +116,35 @@ class TestDateField(MongoDBTestCase): | ||||
|  | ||||
|         for query in (d1, d1.isoformat(" ")): | ||||
|             log1 = LogEntry.objects.get(date=query) | ||||
|             self.assertEqual(log, log1) | ||||
|             assert log == log1 | ||||
|  | ||||
|         if dateutil: | ||||
|             log1 = LogEntry.objects.get(date=d1.isoformat("T")) | ||||
|             self.assertEqual(log, log1) | ||||
|             assert 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) | ||||
|         assert 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) | ||||
|             assert 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) | ||||
|             assert 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) | ||||
|         assert logs.count() == 10 | ||||
|  | ||||
|     def test_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to datetime | ||||
| @@ -166,6 +169,8 @@ class TestDateField(MongoDBTestCase): | ||||
|             log.validate() | ||||
|  | ||||
|         log.time = -1 | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|         log.time = "ABC" | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime as dt | ||||
|  | ||||
| import pytest | ||||
| import six | ||||
|  | ||||
| try: | ||||
| @@ -24,7 +26,8 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|             dt = DateTimeField() | ||||
|  | ||||
|         md = MyDoc(dt="") | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             md.save() | ||||
|  | ||||
|     def test_datetime_from_whitespace_string(self): | ||||
|         """ | ||||
| @@ -36,7 +39,8 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|             dt = DateTimeField() | ||||
|  | ||||
|         md = MyDoc(dt="   ") | ||||
|         self.assertRaises(ValidationError, md.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             md.save() | ||||
|  | ||||
|     def test_default_value_utcnow(self): | ||||
|         """Ensure that default field values are used when creating | ||||
| @@ -50,11 +54,9 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|         person = Person() | ||||
|         person.validate() | ||||
|         person_created_t0 = person.created | ||||
|         self.assertLess(person.created - utcnow, dt.timedelta(seconds=1)) | ||||
|         self.assertEqual( | ||||
|             person_created_t0, person.created | ||||
|         )  # make sure it does not change | ||||
|         self.assertEqual(person._data["created"], person.created) | ||||
|         assert person.created - utcnow < dt.timedelta(seconds=1) | ||||
|         assert person_created_t0 == person.created  # make sure it does not change | ||||
|         assert person._data["created"] == person.created | ||||
|  | ||||
|     def test_handling_microseconds(self): | ||||
|         """Tests showing pymongo datetime fields handling of microseconds. | ||||
| @@ -74,7 +76,7 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|         log.date = dt.date.today() | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertEqual(log.date.date(), dt.date.today()) | ||||
|         assert log.date.date() == dt.date.today() | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond and | ||||
|         # dropped | ||||
| @@ -84,8 +86,8 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertNotEqual(log.date, d1) | ||||
|         self.assertEqual(log.date, d2) | ||||
|         assert log.date != d1 | ||||
|         assert log.date == d2 | ||||
|  | ||||
|         # Post UTC - microseconds are rounded (down) nearest millisecond | ||||
|         d1 = dt.datetime(1970, 1, 1, 0, 0, 1, 9999) | ||||
| @@ -93,8 +95,8 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|         log.date = d1 | ||||
|         log.save() | ||||
|         log.reload() | ||||
|         self.assertNotEqual(log.date, d1) | ||||
|         self.assertEqual(log.date, d2) | ||||
|         assert log.date != d1 | ||||
|         assert log.date == d2 | ||||
|  | ||||
|         if not six.PY3: | ||||
|             # Pre UTC dates microseconds below 1000 are dropped | ||||
| @@ -104,8 +106,8 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|             log.date = d1 | ||||
|             log.save() | ||||
|             log.reload() | ||||
|             self.assertNotEqual(log.date, d1) | ||||
|             self.assertEqual(log.date, d2) | ||||
|             assert log.date != d1 | ||||
|             assert log.date == d2 | ||||
|  | ||||
|     def test_regular_usage(self): | ||||
|         """Tests for regular datetime fields""" | ||||
| @@ -123,43 +125,43 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|  | ||||
|         for query in (d1, d1.isoformat(" ")): | ||||
|             log1 = LogEntry.objects.get(date=query) | ||||
|             self.assertEqual(log, log1) | ||||
|             assert log == log1 | ||||
|  | ||||
|         if dateutil: | ||||
|             log1 = LogEntry.objects.get(date=d1.isoformat("T")) | ||||
|             self.assertEqual(log, log1) | ||||
|             assert log == log1 | ||||
|  | ||||
|         # create additional 19 log entries for a total of 20 | ||||
|         for i in range(1971, 1990): | ||||
|             d = dt.datetime(i, 1, 1, 0, 0, 1) | ||||
|             LogEntry(date=d).save() | ||||
|  | ||||
|         self.assertEqual(LogEntry.objects.count(), 20) | ||||
|         assert 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) | ||||
|             assert 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) | ||||
|             assert logs[i].date >= logs[i + 1].date | ||||
|             i += 1 | ||||
|  | ||||
|         # Test searching | ||||
|         logs = LogEntry.objects.filter(date__gte=dt.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|         assert logs.count() == 10 | ||||
|  | ||||
|         logs = LogEntry.objects.filter(date__lte=dt.datetime(1980, 1, 1)) | ||||
|         self.assertEqual(logs.count(), 10) | ||||
|         assert logs.count() == 10 | ||||
|  | ||||
|         logs = LogEntry.objects.filter( | ||||
|             date__lte=dt.datetime(1980, 1, 1), date__gte=dt.datetime(1975, 1, 1) | ||||
|         ) | ||||
|         self.assertEqual(logs.count(), 5) | ||||
|         assert logs.count() == 5 | ||||
|  | ||||
|     def test_datetime_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to datetime | ||||
| @@ -187,15 +189,20 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|             log.validate() | ||||
|  | ||||
|         log.time = -1 | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|         log.time = "ABC" | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|         log.time = "2019-05-16 21:GARBAGE:12" | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|         log.time = "2019-05-16 21:42:57.GARBAGE" | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|         log.time = "2019-05-16 21:42:57.123.456" | ||||
|         self.assertRaises(ValidationError, log.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             log.validate() | ||||
|  | ||||
|     def test_parse_datetime_as_str(self): | ||||
|         class DTDoc(Document): | ||||
| @@ -206,15 +213,16 @@ class TestDateTimeField(MongoDBTestCase): | ||||
|         # make sure that passing a parsable datetime works | ||||
|         dtd = DTDoc() | ||||
|         dtd.date = date_str | ||||
|         self.assertIsInstance(dtd.date, six.string_types) | ||||
|         assert isinstance(dtd.date, six.string_types) | ||||
|         dtd.save() | ||||
|         dtd.reload() | ||||
|  | ||||
|         self.assertIsInstance(dtd.date, dt.datetime) | ||||
|         self.assertEqual(str(dtd.date), date_str) | ||||
|         assert isinstance(dtd.date, dt.datetime) | ||||
|         assert str(dtd.date) == date_str | ||||
|  | ||||
|         dtd.date = "January 1st, 9999999999" | ||||
|         self.assertRaises(ValidationError, dtd.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             dtd.validate() | ||||
|  | ||||
|  | ||||
| class TestDateTimeTzAware(MongoDBTestCase): | ||||
| @@ -235,4 +243,4 @@ class TestDateTimeTzAware(MongoDBTestCase): | ||||
|  | ||||
|         log = LogEntry.objects.first() | ||||
|         log.time = dt.datetime(2013, 1, 1, 0, 0, 0) | ||||
|         self.assertEqual(["time"], log._changed_fields) | ||||
|         assert ["time"] == log._changed_fields | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| from decimal import Decimal | ||||
|  | ||||
| from mongoengine import * | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| @@ -18,21 +19,26 @@ class TestDecimalField(MongoDBTestCase): | ||||
|  | ||||
|         Person(height=Decimal("1.89")).save() | ||||
|         person = Person.objects.first() | ||||
|         self.assertEqual(person.height, Decimal("1.89")) | ||||
|         assert person.height == Decimal("1.89") | ||||
|  | ||||
|         person.height = "2.0" | ||||
|         person.save() | ||||
|         person.height = 0.01 | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.height = Decimal("0.01") | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.height = Decimal("4.0") | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.height = "something invalid" | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|         person_2 = Person(height="something invalid") | ||||
|         self.assertRaises(ValidationError, person_2.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person_2.validate() | ||||
|  | ||||
|     def test_comparison(self): | ||||
|         class Person(Document): | ||||
| @@ -45,11 +51,11 @@ class TestDecimalField(MongoDBTestCase): | ||||
|         Person(money=8).save() | ||||
|         Person(money=10).save() | ||||
|  | ||||
|         self.assertEqual(2, Person.objects(money__gt=Decimal("7")).count()) | ||||
|         self.assertEqual(2, Person.objects(money__gt=7).count()) | ||||
|         self.assertEqual(2, Person.objects(money__gt="7").count()) | ||||
|         assert 2 == Person.objects(money__gt=Decimal("7")).count() | ||||
|         assert 2 == Person.objects(money__gt=7).count() | ||||
|         assert 2 == Person.objects(money__gt="7").count() | ||||
|  | ||||
|         self.assertEqual(3, Person.objects(money__gte="7").count()) | ||||
|         assert 3 == Person.objects(money__gte="7").count() | ||||
|  | ||||
|     def test_storage(self): | ||||
|         class Person(Document): | ||||
| @@ -87,7 +93,7 @@ class TestDecimalField(MongoDBTestCase): | ||||
|         ] | ||||
|         expected.extend(expected) | ||||
|         actual = list(Person.objects.exclude("id").as_pymongo()) | ||||
|         self.assertEqual(expected, actual) | ||||
|         assert expected == actual | ||||
|  | ||||
|         # How it comes out locally | ||||
|         expected = [ | ||||
| @@ -101,4 +107,4 @@ class TestDecimalField(MongoDBTestCase): | ||||
|         expected.extend(expected) | ||||
|         for field_name in ["float_value", "string_value"]: | ||||
|             actual = list(Person.objects().scalar(field_name)) | ||||
|             self.assertEqual(expected, actual) | ||||
|             assert expected == actual | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.base import BaseDict | ||||
| from mongoengine.mongodb_support import MONGODB_36, get_mongodb_version | ||||
|  | ||||
| from tests.utils import MongoDBTestCase, get_as_pymongo | ||||
|  | ||||
| @@ -14,7 +17,7 @@ class TestDictField(MongoDBTestCase): | ||||
|  | ||||
|         info = {"testkey": "testvalue"} | ||||
|         post = BlogPost(info=info).save() | ||||
|         self.assertEqual(get_as_pymongo(post), {"_id": post.id, "info": info}) | ||||
|         assert get_as_pymongo(post) == {"_id": post.id, "info": info} | ||||
|  | ||||
|     def test_general_things(self): | ||||
|         """Ensure that dict types work as expected.""" | ||||
| @@ -26,25 +29,42 @@ class TestDictField(MongoDBTestCase): | ||||
|  | ||||
|         post = BlogPost() | ||||
|         post.info = "my post" | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = ["test", "test"] | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {"$title": "test"} | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {"nested": {"$title": "test"}} | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {"the.title": "test"} | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|  | ||||
|         post.info = {"nested": {"the.title": "test"}} | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|         post.info = {"$title.test": "test"} | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {1: "test"} | ||||
|         self.assertRaises(ValidationError, post.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {"nested": {"the.title": "test"}} | ||||
|         if get_mongodb_version() < MONGODB_36: | ||||
|             with pytest.raises(ValidationError): | ||||
|                 post.validate() | ||||
|         else: | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {"dollar_and_dot": {"te$st.test": "test"}} | ||||
|         if get_mongodb_version() < MONGODB_36: | ||||
|             with pytest.raises(ValidationError): | ||||
|                 post.validate() | ||||
|         else: | ||||
|             post.validate() | ||||
|  | ||||
|         post.info = {"title": "test"} | ||||
|         post.save() | ||||
| @@ -61,33 +81,27 @@ class TestDictField(MongoDBTestCase): | ||||
|         post.info = {"details": {"test": 3}} | ||||
|         post.save() | ||||
|  | ||||
|         self.assertEqual(BlogPost.objects.count(), 4) | ||||
|         self.assertEqual(BlogPost.objects.filter(info__title__exact="test").count(), 1) | ||||
|         self.assertEqual( | ||||
|             BlogPost.objects.filter(info__details__test__exact="test").count(), 1 | ||||
|         ) | ||||
|         assert BlogPost.objects.count() == 4 | ||||
|         assert BlogPost.objects.filter(info__title__exact="test").count() == 1 | ||||
|         assert BlogPost.objects.filter(info__details__test__exact="test").count() == 1 | ||||
|  | ||||
|         post = BlogPost.objects.filter(info__title__exact="dollar_sign").first() | ||||
|         self.assertIn("te$t", post["info"]["details"]) | ||||
|         assert "te$t" in post["info"]["details"] | ||||
|  | ||||
|         # Confirm handles non strings or non existing keys | ||||
|         self.assertEqual( | ||||
|             BlogPost.objects.filter(info__details__test__exact=5).count(), 0 | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             BlogPost.objects.filter(info__made_up__test__exact="test").count(), 0 | ||||
|         ) | ||||
|         assert BlogPost.objects.filter(info__details__test__exact=5).count() == 0 | ||||
|         assert BlogPost.objects.filter(info__made_up__test__exact="test").count() == 0 | ||||
|  | ||||
|         post = BlogPost.objects.create(info={"title": "original"}) | ||||
|         post.info.update({"title": "updated"}) | ||||
|         post.save() | ||||
|         post.reload() | ||||
|         self.assertEqual("updated", post.info["title"]) | ||||
|         assert "updated" == post.info["title"] | ||||
|  | ||||
|         post.info.setdefault("authors", []) | ||||
|         post.save() | ||||
|         post.reload() | ||||
|         self.assertEqual([], post.info["authors"]) | ||||
|         assert [] == post.info["authors"] | ||||
|  | ||||
|     def test_dictfield_dump_document(self): | ||||
|         """Ensure a DictField can handle another document's dump.""" | ||||
| @@ -114,10 +128,8 @@ class TestDictField(MongoDBTestCase): | ||||
|         ).save() | ||||
|         doc = Doc(field=to_embed.to_mongo().to_dict()) | ||||
|         doc.save() | ||||
|         self.assertIsInstance(doc.field, dict) | ||||
|         self.assertEqual( | ||||
|             doc.field, {"_id": 2, "recursive": {"_id": 1, "recursive": {}}} | ||||
|         ) | ||||
|         assert isinstance(doc.field, dict) | ||||
|         assert doc.field == {"_id": 2, "recursive": {"_id": 1, "recursive": {}}} | ||||
|         # Same thing with a Document with a _cls field | ||||
|         to_embed_recursive = ToEmbedChild(id=1).save() | ||||
|         to_embed_child = ToEmbedChild( | ||||
| @@ -125,7 +137,7 @@ class TestDictField(MongoDBTestCase): | ||||
|         ).save() | ||||
|         doc = Doc(field=to_embed_child.to_mongo().to_dict()) | ||||
|         doc.save() | ||||
|         self.assertIsInstance(doc.field, dict) | ||||
|         assert isinstance(doc.field, dict) | ||||
|         expected = { | ||||
|             "_id": 2, | ||||
|             "_cls": "ToEmbedParent.ToEmbedChild", | ||||
| @@ -135,7 +147,7 @@ class TestDictField(MongoDBTestCase): | ||||
|                 "recursive": {}, | ||||
|             }, | ||||
|         } | ||||
|         self.assertEqual(doc.field, expected) | ||||
|         assert doc.field == expected | ||||
|  | ||||
|     def test_dictfield_strict(self): | ||||
|         """Ensure that dict field handles validation if provided a strict field type.""" | ||||
| @@ -150,7 +162,7 @@ class TestDictField(MongoDBTestCase): | ||||
|         e.save() | ||||
|  | ||||
|         # try creating an invalid mapping | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|             e.mapping["somestring"] = "abc" | ||||
|             e.save() | ||||
|  | ||||
| @@ -184,22 +196,21 @@ class TestDictField(MongoDBTestCase): | ||||
|         e.save() | ||||
|  | ||||
|         e2 = Simple.objects.get(id=e.id) | ||||
|         self.assertIsInstance(e2.mapping["somestring"], StringSetting) | ||||
|         self.assertIsInstance(e2.mapping["someint"], IntegerSetting) | ||||
|         assert isinstance(e2.mapping["somestring"], StringSetting) | ||||
|         assert isinstance(e2.mapping["someint"], IntegerSetting) | ||||
|  | ||||
|         # Test querying | ||||
|         self.assertEqual(Simple.objects.filter(mapping__someint__value=42).count(), 1) | ||||
|         self.assertEqual( | ||||
|             Simple.objects.filter(mapping__nested_dict__number=1).count(), 1 | ||||
|         assert Simple.objects.filter(mapping__someint__value=42).count() == 1 | ||||
|         assert Simple.objects.filter(mapping__nested_dict__number=1).count() == 1 | ||||
|         assert ( | ||||
|             Simple.objects.filter(mapping__nested_dict__complex__value=42).count() == 1 | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Simple.objects.filter(mapping__nested_dict__complex__value=42).count(), 1 | ||||
|         assert ( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__0__value=42).count() == 1 | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__0__value=42).count(), 1 | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count(), 1 | ||||
|         assert ( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count() | ||||
|             == 1 | ||||
|         ) | ||||
|  | ||||
|         # Confirm can update | ||||
| @@ -207,11 +218,13 @@ class TestDictField(MongoDBTestCase): | ||||
|         Simple.objects().update( | ||||
|             set__mapping__nested_dict__list__1=StringSetting(value="Boo") | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count(), 0 | ||||
|         assert ( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count() | ||||
|             == 0 | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__1__value="Boo").count(), 1 | ||||
|         assert ( | ||||
|             Simple.objects.filter(mapping__nested_dict__list__1__value="Boo").count() | ||||
|             == 1 | ||||
|         ) | ||||
|  | ||||
|     def test_push_dict(self): | ||||
| @@ -221,12 +234,12 @@ class TestDictField(MongoDBTestCase): | ||||
|         doc = MyModel(events=[{"a": 1}]).save() | ||||
|         raw_doc = get_as_pymongo(doc) | ||||
|         expected_raw_doc = {"_id": doc.id, "events": [{"a": 1}]} | ||||
|         self.assertEqual(raw_doc, expected_raw_doc) | ||||
|         assert raw_doc == expected_raw_doc | ||||
|  | ||||
|         MyModel.objects(id=doc.id).update(push__events={}) | ||||
|         raw_doc = get_as_pymongo(doc) | ||||
|         expected_raw_doc = {"_id": doc.id, "events": [{"a": 1}, {}]} | ||||
|         self.assertEqual(raw_doc, expected_raw_doc) | ||||
|         assert raw_doc == expected_raw_doc | ||||
|  | ||||
|     def test_ensure_unique_default_instances(self): | ||||
|         """Ensure that every field has it's own unique default instance.""" | ||||
| @@ -239,8 +252,8 @@ class TestDictField(MongoDBTestCase): | ||||
|         d1.data["foo"] = "bar" | ||||
|         d1.data2["foo"] = "bar" | ||||
|         d2 = D() | ||||
|         self.assertEqual(d2.data, {}) | ||||
|         self.assertEqual(d2.data2, {}) | ||||
|         assert d2.data == {} | ||||
|         assert d2.data2 == {} | ||||
|  | ||||
|     def test_dict_field_invalid_dict_value(self): | ||||
|         class DictFieldTest(Document): | ||||
| @@ -250,11 +263,13 @@ class TestDictField(MongoDBTestCase): | ||||
|  | ||||
|         test = DictFieldTest(dictionary=None) | ||||
|         test.dictionary  # Just access to test getter | ||||
|         self.assertRaises(ValidationError, test.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             test.validate() | ||||
|  | ||||
|         test = DictFieldTest(dictionary=False) | ||||
|         test.dictionary  # Just access to test getter | ||||
|         self.assertRaises(ValidationError, test.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             test.validate() | ||||
|  | ||||
|     def test_dict_field_raises_validation_error_if_wrongly_assign_embedded_doc(self): | ||||
|         class DictFieldTest(Document): | ||||
| @@ -267,12 +282,12 @@ class TestDictField(MongoDBTestCase): | ||||
|  | ||||
|         embed = Embedded(name="garbage") | ||||
|         doc = DictFieldTest(dictionary=embed) | ||||
|         with self.assertRaises(ValidationError) as ctx_err: | ||||
|         with pytest.raises(ValidationError) as exc_info: | ||||
|             doc.validate() | ||||
|         self.assertIn("'dictionary'", str(ctx_err.exception)) | ||||
|         self.assertIn( | ||||
|             "Only dictionaries may be used in a DictField", str(ctx_err.exception) | ||||
|         ) | ||||
|  | ||||
|         error_msg = str(exc_info.value) | ||||
|         assert "'dictionary'" in error_msg | ||||
|         assert "Only dictionaries may be used in a DictField" in error_msg | ||||
|  | ||||
|     def test_atomic_update_dict_field(self): | ||||
|         """Ensure that the entire DictField can be atomically updated.""" | ||||
| @@ -287,11 +302,11 @@ class TestDictField(MongoDBTestCase): | ||||
|         e.save() | ||||
|         e.update(set__mapping={"ints": [3, 4]}) | ||||
|         e.reload() | ||||
|         self.assertEqual(BaseDict, type(e.mapping)) | ||||
|         self.assertEqual({"ints": [3, 4]}, e.mapping) | ||||
|         assert isinstance(e.mapping, BaseDict) | ||||
|         assert {"ints": [3, 4]} == e.mapping | ||||
|  | ||||
|         # try creating an invalid mapping | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|             e.update(set__mapping={"somestrings": ["foo", "bar"]}) | ||||
|  | ||||
|     def test_dictfield_with_referencefield_complex_nesting_cases(self): | ||||
| @@ -329,13 +344,13 @@ class TestDictField(MongoDBTestCase): | ||||
|         e.save() | ||||
|  | ||||
|         s = Simple.objects.first() | ||||
|         self.assertIsInstance(s.mapping0["someint"], Doc) | ||||
|         self.assertIsInstance(s.mapping1["someint"], Doc) | ||||
|         self.assertIsInstance(s.mapping2["someint"][0], Doc) | ||||
|         self.assertIsInstance(s.mapping3["someint"][0], Doc) | ||||
|         self.assertIsInstance(s.mapping4["someint"]["d"], Doc) | ||||
|         self.assertIsInstance(s.mapping5["someint"]["d"], Doc) | ||||
|         self.assertIsInstance(s.mapping6["someint"][0]["d"], Doc) | ||||
|         self.assertIsInstance(s.mapping7["someint"][0]["d"], Doc) | ||||
|         self.assertIsInstance(s.mapping8["someint"][0]["d"][0], Doc) | ||||
|         self.assertIsInstance(s.mapping9["someint"][0]["d"][0], Doc) | ||||
|         assert isinstance(s.mapping0["someint"], Doc) | ||||
|         assert isinstance(s.mapping1["someint"], Doc) | ||||
|         assert isinstance(s.mapping2["someint"][0], Doc) | ||||
|         assert isinstance(s.mapping3["someint"][0], Doc) | ||||
|         assert isinstance(s.mapping4["someint"]["d"], Doc) | ||||
|         assert isinstance(s.mapping5["someint"]["d"], Doc) | ||||
|         assert isinstance(s.mapping6["someint"][0]["d"], Doc) | ||||
|         assert isinstance(s.mapping7["someint"][0]["d"], Doc) | ||||
|         assert isinstance(s.mapping8["someint"][0]["d"][0], Doc) | ||||
|         assert isinstance(s.mapping9["someint"][0]["d"][0], Doc) | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import sys | ||||
| from unittest import SkipTest | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| @@ -27,7 +27,8 @@ class TestEmailField(MongoDBTestCase): | ||||
|         user.validate() | ||||
|  | ||||
|         user = User(email="ross@example.com.") | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         # unicode domain | ||||
|         user = User(email=u"user@пример.рф") | ||||
| @@ -35,24 +36,22 @@ class TestEmailField(MongoDBTestCase): | ||||
|  | ||||
|         # invalid unicode domain | ||||
|         user = User(email=u"user@пример") | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         # invalid data type | ||||
|         user = User(email=123) | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|     def test_email_field_unicode_user(self): | ||||
|         # Don't run this test on pypy3, which doesn't support unicode regex: | ||||
|         # https://bitbucket.org/pypy/pypy/issues/1821/regular-expression-doesnt-find-unicode | ||||
|         if sys.version_info[:2] == (3, 2): | ||||
|             raise SkipTest("unicode email addresses are not supported on PyPy 3") | ||||
|  | ||||
|         class User(Document): | ||||
|             email = EmailField() | ||||
|  | ||||
|         # unicode user shouldn't validate by default... | ||||
|         user = User(email=u"Dörte@Sörensen.example.com") | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         # ...but it should be fine with allow_utf8_user set to True | ||||
|         class User(Document): | ||||
| @@ -67,7 +66,8 @@ class TestEmailField(MongoDBTestCase): | ||||
|  | ||||
|         # localhost domain shouldn't validate by default... | ||||
|         user = User(email="me@localhost") | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         # ...but it should be fine if it's whitelisted | ||||
|         class User(Document): | ||||
| @@ -82,9 +82,10 @@ class TestEmailField(MongoDBTestCase): | ||||
|  | ||||
|         invalid_idn = ".google.com" | ||||
|         user = User(email="me@%s" % invalid_idn) | ||||
|         with self.assertRaises(ValidationError) as ctx_err: | ||||
|  | ||||
|         with pytest.raises(ValidationError) as exc_info: | ||||
|             user.validate() | ||||
|         self.assertIn("domain failed IDN encoding", str(ctx_err.exception)) | ||||
|         assert "domain failed IDN encoding" in str(exc_info.value) | ||||
|  | ||||
|     def test_email_field_ip_domain(self): | ||||
|         class User(Document): | ||||
| @@ -96,13 +97,16 @@ class TestEmailField(MongoDBTestCase): | ||||
|  | ||||
|         # IP address as a domain shouldn't validate by default... | ||||
|         user = User(email=valid_ipv4) | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         user = User(email=valid_ipv6) | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         user = User(email=invalid_ip) | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         # ...but it should be fine with allow_ip_domain set to True | ||||
|         class User(Document): | ||||
| @@ -116,7 +120,8 @@ class TestEmailField(MongoDBTestCase): | ||||
|  | ||||
|         # invalid IP should still fail validation | ||||
|         user = User(email=invalid_ip) | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|     def test_email_field_honors_regex(self): | ||||
|         class User(Document): | ||||
| @@ -124,8 +129,9 @@ class TestEmailField(MongoDBTestCase): | ||||
|  | ||||
|         # Fails regex validation | ||||
|         user = User(email="me@foo.com") | ||||
|         self.assertRaises(ValidationError, user.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             user.validate() | ||||
|  | ||||
|         # Passes regex validation | ||||
|         user = User(email="me@example.com") | ||||
|         self.assertIsNone(user.validate()) | ||||
|         assert user.validate() is None | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import ( | ||||
|     Document, | ||||
|     StringField, | ||||
|     ValidationError, | ||||
|     EmbeddedDocument, | ||||
|     EmbeddedDocumentField, | ||||
|     InvalidQueryError, | ||||
|     LookUpError, | ||||
|     IntField, | ||||
|     GenericEmbeddedDocumentField, | ||||
|     IntField, | ||||
|     InvalidQueryError, | ||||
|     ListField, | ||||
|     EmbeddedDocumentListField, | ||||
|     ReferenceField, | ||||
|     LookUpError, | ||||
|     StringField, | ||||
|     ValidationError, | ||||
| ) | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
| @@ -23,13 +23,13 @@ class TestEmbeddedDocumentField(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|  | ||||
|         field = EmbeddedDocumentField(MyDoc) | ||||
|         self.assertEqual(field.document_type_obj, MyDoc) | ||||
|         assert field.document_type_obj == MyDoc | ||||
|  | ||||
|         field2 = EmbeddedDocumentField("MyDoc") | ||||
|         self.assertEqual(field2.document_type_obj, "MyDoc") | ||||
|         assert field2.document_type_obj == "MyDoc" | ||||
|  | ||||
|     def test___init___throw_error_if_document_type_is_not_EmbeddedDocument(self): | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|             EmbeddedDocumentField(dict) | ||||
|  | ||||
|     def test_document_type_throw_error_if_not_EmbeddedDocument_subclass(self): | ||||
| @@ -37,11 +37,11 @@ class TestEmbeddedDocumentField(MongoDBTestCase): | ||||
|             name = StringField() | ||||
|  | ||||
|         emb = EmbeddedDocumentField("MyDoc") | ||||
|         with self.assertRaises(ValidationError) as ctx: | ||||
|         with pytest.raises(ValidationError) as exc_info: | ||||
|             emb.document_type | ||||
|         self.assertIn( | ||||
|             "Invalid embedded document class provided to an EmbeddedDocumentField", | ||||
|             str(ctx.exception), | ||||
|         assert ( | ||||
|             "Invalid embedded document class provided to an EmbeddedDocumentField" | ||||
|             in str(exc_info.value) | ||||
|         ) | ||||
|  | ||||
|     def test_embedded_document_field_only_allow_subclasses_of_embedded_document(self): | ||||
| @@ -49,12 +49,12 @@ class TestEmbeddedDocumentField(MongoDBTestCase): | ||||
|         class MyDoc(Document): | ||||
|             name = StringField() | ||||
|  | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|  | ||||
|             class MyFailingDoc(Document): | ||||
|                 emb = EmbeddedDocumentField(MyDoc) | ||||
|  | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|  | ||||
|             class MyFailingdoc2(Document): | ||||
|                 emb = EmbeddedDocumentField("MyDoc") | ||||
| @@ -73,24 +73,24 @@ class TestEmbeddedDocumentField(MongoDBTestCase): | ||||
|         p = Person(settings=AdminSettings(foo1="bar1", foo2="bar2"), name="John").save() | ||||
|  | ||||
|         # Test non exiting attribute | ||||
|         with self.assertRaises(InvalidQueryError) as ctx_err: | ||||
|         with pytest.raises(InvalidQueryError) as exc_info: | ||||
|             Person.objects(settings__notexist="bar").first() | ||||
|         self.assertEqual(unicode(ctx_err.exception), u'Cannot resolve field "notexist"') | ||||
|         assert unicode(exc_info.value) == u'Cannot resolve field "notexist"' | ||||
|  | ||||
|         with self.assertRaises(LookUpError): | ||||
|         with pytest.raises(LookUpError): | ||||
|             Person.objects.only("settings.notexist") | ||||
|  | ||||
|         # Test existing attribute | ||||
|         self.assertEqual(Person.objects(settings__foo1="bar1").first().id, p.id) | ||||
|         assert Person.objects(settings__foo1="bar1").first().id == p.id | ||||
|         only_p = Person.objects.only("settings.foo1").first() | ||||
|         self.assertEqual(only_p.settings.foo1, p.settings.foo1) | ||||
|         self.assertIsNone(only_p.settings.foo2) | ||||
|         self.assertIsNone(only_p.name) | ||||
|         assert only_p.settings.foo1 == p.settings.foo1 | ||||
|         assert only_p.settings.foo2 is None | ||||
|         assert only_p.name is None | ||||
|  | ||||
|         exclude_p = Person.objects.exclude("settings.foo1").first() | ||||
|         self.assertIsNone(exclude_p.settings.foo1) | ||||
|         self.assertEqual(exclude_p.settings.foo2, p.settings.foo2) | ||||
|         self.assertEqual(exclude_p.name, p.name) | ||||
|         assert exclude_p.settings.foo1 is None | ||||
|         assert exclude_p.settings.foo2 == p.settings.foo2 | ||||
|         assert exclude_p.name == p.name | ||||
|  | ||||
|     def test_query_embedded_document_attribute_with_inheritance(self): | ||||
|         class BaseSettings(EmbeddedDocument): | ||||
| @@ -109,17 +109,17 @@ class TestEmbeddedDocumentField(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         # Test non exiting attribute | ||||
|         with self.assertRaises(InvalidQueryError) as ctx_err: | ||||
|             self.assertEqual(Person.objects(settings__notexist="bar").first().id, p.id) | ||||
|         self.assertEqual(unicode(ctx_err.exception), u'Cannot resolve field "notexist"') | ||||
|         with pytest.raises(InvalidQueryError) as exc_info: | ||||
|             assert Person.objects(settings__notexist="bar").first().id == p.id | ||||
|         assert unicode(exc_info.value) == u'Cannot resolve field "notexist"' | ||||
|  | ||||
|         # Test existing attribute | ||||
|         self.assertEqual(Person.objects(settings__base_foo="basefoo").first().id, p.id) | ||||
|         self.assertEqual(Person.objects(settings__sub_foo="subfoo").first().id, p.id) | ||||
|         assert Person.objects(settings__base_foo="basefoo").first().id == p.id | ||||
|         assert Person.objects(settings__sub_foo="subfoo").first().id == p.id | ||||
|  | ||||
|         only_p = Person.objects.only("settings.base_foo", "settings._cls").first() | ||||
|         self.assertEqual(only_p.settings.base_foo, "basefoo") | ||||
|         self.assertIsNone(only_p.settings.sub_foo) | ||||
|         assert only_p.settings.base_foo == "basefoo" | ||||
|         assert only_p.settings.sub_foo is None | ||||
|  | ||||
|     def test_query_list_embedded_document_with_inheritance(self): | ||||
|         class Post(EmbeddedDocument): | ||||
| @@ -139,14 +139,14 @@ class TestEmbeddedDocumentField(MongoDBTestCase): | ||||
|         record_text = Record(posts=[TextPost(content="a", title="foo")]).save() | ||||
|  | ||||
|         records = list(Record.objects(posts__author=record_movie.posts[0].author)) | ||||
|         self.assertEqual(len(records), 1) | ||||
|         self.assertEqual(records[0].id, record_movie.id) | ||||
|         assert len(records) == 1 | ||||
|         assert records[0].id == record_movie.id | ||||
|  | ||||
|         records = list(Record.objects(posts__content=record_text.posts[0].content)) | ||||
|         self.assertEqual(len(records), 1) | ||||
|         self.assertEqual(records[0].id, record_text.id) | ||||
|         assert len(records) == 1 | ||||
|         assert records[0].id == record_text.id | ||||
|  | ||||
|         self.assertEqual(Record.objects(posts__title="foo").count(), 2) | ||||
|         assert Record.objects(posts__title="foo").count() == 2 | ||||
|  | ||||
|  | ||||
| class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
| @@ -169,13 +169,13 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|         person.save() | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         self.assertIsInstance(person.like, Car) | ||||
|         assert isinstance(person.like, Car) | ||||
|  | ||||
|         person.like = Dish(food="arroz", number=15) | ||||
|         person.save() | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         self.assertIsInstance(person.like, Dish) | ||||
|         assert isinstance(person.like, Dish) | ||||
|  | ||||
|     def test_generic_embedded_document_choices(self): | ||||
|         """Ensure you can limit GenericEmbeddedDocument choices.""" | ||||
| @@ -195,13 +195,14 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|  | ||||
|         person = Person(name="Test User") | ||||
|         person.like = Car(name="Fiat") | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|         person.like = Dish(food="arroz", number=15) | ||||
|         person.save() | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         self.assertIsInstance(person.like, Dish) | ||||
|         assert isinstance(person.like, Dish) | ||||
|  | ||||
|     def test_generic_list_embedded_document_choices(self): | ||||
|         """Ensure you can limit GenericEmbeddedDocument choices inside | ||||
| @@ -223,13 +224,14 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|  | ||||
|         person = Person(name="Test User") | ||||
|         person.likes = [Car(name="Fiat")] | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|         person.likes = [Dish(food="arroz", number=15)] | ||||
|         person.save() | ||||
|  | ||||
|         person = Person.objects.first() | ||||
|         self.assertIsInstance(person.likes[0], Dish) | ||||
|         assert isinstance(person.likes[0], Dish) | ||||
|  | ||||
|     def test_choices_validation_documents(self): | ||||
|         """ | ||||
| @@ -265,7 +267,8 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|  | ||||
|         # Single Entry Failure | ||||
|         post = BlogPost(comments=[ModeratorComments(author="mod1", message="message1")]) | ||||
|         self.assertRaises(ValidationError, post.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.save() | ||||
|  | ||||
|         # Mixed Entry Failure | ||||
|         post = BlogPost( | ||||
| @@ -274,7 +277,8 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|                 UserComments(author="user2", message="message2"), | ||||
|             ] | ||||
|         ) | ||||
|         self.assertRaises(ValidationError, post.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post.save() | ||||
|  | ||||
|     def test_choices_validation_documents_inheritance(self): | ||||
|         """ | ||||
| @@ -313,16 +317,16 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|         p2 = Person(settings=NonAdminSettings(foo2="bar2")).save() | ||||
|  | ||||
|         # Test non exiting attribute | ||||
|         with self.assertRaises(InvalidQueryError) as ctx_err: | ||||
|         with pytest.raises(InvalidQueryError) as exc_info: | ||||
|             Person.objects(settings__notexist="bar").first() | ||||
|         self.assertEqual(unicode(ctx_err.exception), u'Cannot resolve field "notexist"') | ||||
|         assert unicode(exc_info.value) == u'Cannot resolve field "notexist"' | ||||
|  | ||||
|         with self.assertRaises(LookUpError): | ||||
|         with pytest.raises(LookUpError): | ||||
|             Person.objects.only("settings.notexist") | ||||
|  | ||||
|         # Test existing attribute | ||||
|         self.assertEqual(Person.objects(settings__foo1="bar1").first().id, p1.id) | ||||
|         self.assertEqual(Person.objects(settings__foo2="bar2").first().id, p2.id) | ||||
|         assert Person.objects(settings__foo1="bar1").first().id == p1.id | ||||
|         assert Person.objects(settings__foo2="bar2").first().id == p2.id | ||||
|  | ||||
|     def test_query_generic_embedded_document_attribute_with_inheritance(self): | ||||
|         class BaseSettings(EmbeddedDocument): | ||||
| @@ -341,10 +345,10 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase): | ||||
|         p.save() | ||||
|  | ||||
|         # Test non exiting attribute | ||||
|         with self.assertRaises(InvalidQueryError) as ctx_err: | ||||
|             self.assertEqual(Person.objects(settings__notexist="bar").first().id, p.id) | ||||
|         self.assertEqual(unicode(ctx_err.exception), u'Cannot resolve field "notexist"') | ||||
|         with pytest.raises(InvalidQueryError) as exc_info: | ||||
|             assert Person.objects(settings__notexist="bar").first().id == p.id | ||||
|         assert unicode(exc_info.value) == u'Cannot resolve field "notexist"' | ||||
|  | ||||
|         # Test existing attribute | ||||
|         self.assertEqual(Person.objects(settings__base_foo="basefoo").first().id, p.id) | ||||
|         self.assertEqual(Person.objects(settings__sub_foo="subfoo").first().id, p.id) | ||||
|         assert Person.objects(settings__base_foo="basefoo").first().id == p.id | ||||
|         assert Person.objects(settings__sub_foo="subfoo").first().id == p.id | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -5,7 +5,7 @@ import tempfile | ||||
| import unittest | ||||
|  | ||||
| import gridfs | ||||
| from nose.plugins.skip import SkipTest | ||||
| import pytest | ||||
| import six | ||||
|  | ||||
| from mongoengine import * | ||||
| @@ -21,6 +21,8 @@ except ImportError: | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
| require_pil = pytest.mark.skipif(not HAS_PIL, reason="PIL not installed") | ||||
|  | ||||
| TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__), "mongoengine.png") | ||||
| TEST_IMAGE2_PATH = os.path.join(os.path.dirname(__file__), "mongodb_leaf.png") | ||||
|  | ||||
| @@ -64,13 +66,13 @@ class TestFileField(MongoDBTestCase): | ||||
|         putfile.save() | ||||
|  | ||||
|         result = PutFile.objects.first() | ||||
|         self.assertEqual(putfile, result) | ||||
|         self.assertEqual( | ||||
|             "%s" % result.the_file, | ||||
|             "<GridFSProxy: hello (%s)>" % result.the_file.grid_id, | ||||
|         assert putfile == result | ||||
|         assert ( | ||||
|             "%s" % result.the_file | ||||
|             == "<GridFSProxy: hello (%s)>" % result.the_file.grid_id | ||||
|         ) | ||||
|         self.assertEqual(result.the_file.read(), text) | ||||
|         self.assertEqual(result.the_file.content_type, content_type) | ||||
|         assert result.the_file.read() == text | ||||
|         assert result.the_file.content_type == content_type | ||||
|         result.the_file.delete()  # Remove file from GridFS | ||||
|         PutFile.objects.delete() | ||||
|  | ||||
| @@ -85,9 +87,9 @@ class TestFileField(MongoDBTestCase): | ||||
|         putfile.save() | ||||
|  | ||||
|         result = PutFile.objects.first() | ||||
|         self.assertEqual(putfile, result) | ||||
|         self.assertEqual(result.the_file.read(), text) | ||||
|         self.assertEqual(result.the_file.content_type, content_type) | ||||
|         assert putfile == result | ||||
|         assert result.the_file.read() == text | ||||
|         assert result.the_file.content_type == content_type | ||||
|         result.the_file.delete() | ||||
|  | ||||
|     def test_file_fields_stream(self): | ||||
| @@ -111,19 +113,19 @@ class TestFileField(MongoDBTestCase): | ||||
|         streamfile.save() | ||||
|  | ||||
|         result = StreamFile.objects.first() | ||||
|         self.assertEqual(streamfile, result) | ||||
|         self.assertEqual(result.the_file.read(), text + more_text) | ||||
|         self.assertEqual(result.the_file.content_type, content_type) | ||||
|         assert streamfile == result | ||||
|         assert result.the_file.read() == text + more_text | ||||
|         assert result.the_file.content_type == content_type | ||||
|         result.the_file.seek(0) | ||||
|         self.assertEqual(result.the_file.tell(), 0) | ||||
|         self.assertEqual(result.the_file.read(len(text)), text) | ||||
|         self.assertEqual(result.the_file.tell(), len(text)) | ||||
|         self.assertEqual(result.the_file.read(len(more_text)), more_text) | ||||
|         self.assertEqual(result.the_file.tell(), len(text + more_text)) | ||||
|         assert result.the_file.tell() == 0 | ||||
|         assert result.the_file.read(len(text)) == text | ||||
|         assert result.the_file.tell() == len(text) | ||||
|         assert result.the_file.read(len(more_text)) == more_text | ||||
|         assert result.the_file.tell() == len(text + more_text) | ||||
|         result.the_file.delete() | ||||
|  | ||||
|         # Ensure deleted file returns None | ||||
|         self.assertTrue(result.the_file.read() is None) | ||||
|         assert result.the_file.read() is None | ||||
|  | ||||
|     def test_file_fields_stream_after_none(self): | ||||
|         """Ensure that a file field can be written to after it has been saved as | ||||
| @@ -137,7 +139,6 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         text = six.b("Hello, World!") | ||||
|         more_text = six.b("Foo Bar") | ||||
|         content_type = "text/plain" | ||||
|  | ||||
|         streamfile = StreamFile() | ||||
|         streamfile.save() | ||||
| @@ -148,19 +149,19 @@ class TestFileField(MongoDBTestCase): | ||||
|         streamfile.save() | ||||
|  | ||||
|         result = StreamFile.objects.first() | ||||
|         self.assertEqual(streamfile, result) | ||||
|         self.assertEqual(result.the_file.read(), text + more_text) | ||||
|         # self.assertEqual(result.the_file.content_type, content_type) | ||||
|         assert streamfile == result | ||||
|         assert result.the_file.read() == text + more_text | ||||
|         # assert result.the_file.content_type == content_type | ||||
|         result.the_file.seek(0) | ||||
|         self.assertEqual(result.the_file.tell(), 0) | ||||
|         self.assertEqual(result.the_file.read(len(text)), text) | ||||
|         self.assertEqual(result.the_file.tell(), len(text)) | ||||
|         self.assertEqual(result.the_file.read(len(more_text)), more_text) | ||||
|         self.assertEqual(result.the_file.tell(), len(text + more_text)) | ||||
|         assert result.the_file.tell() == 0 | ||||
|         assert result.the_file.read(len(text)) == text | ||||
|         assert result.the_file.tell() == len(text) | ||||
|         assert result.the_file.read(len(more_text)) == more_text | ||||
|         assert result.the_file.tell() == len(text + more_text) | ||||
|         result.the_file.delete() | ||||
|  | ||||
|         # Ensure deleted file returns None | ||||
|         self.assertTrue(result.the_file.read() is None) | ||||
|         assert result.the_file.read() is None | ||||
|  | ||||
|     def test_file_fields_set(self): | ||||
|         class SetFile(Document): | ||||
| @@ -176,16 +177,16 @@ class TestFileField(MongoDBTestCase): | ||||
|         setfile.save() | ||||
|  | ||||
|         result = SetFile.objects.first() | ||||
|         self.assertEqual(setfile, result) | ||||
|         self.assertEqual(result.the_file.read(), text) | ||||
|         assert setfile == result | ||||
|         assert result.the_file.read() == text | ||||
|  | ||||
|         # Try replacing file with new one | ||||
|         result.the_file.replace(more_text) | ||||
|         result.save() | ||||
|  | ||||
|         result = SetFile.objects.first() | ||||
|         self.assertEqual(setfile, result) | ||||
|         self.assertEqual(result.the_file.read(), more_text) | ||||
|         assert setfile == result | ||||
|         assert result.the_file.read() == more_text | ||||
|         result.the_file.delete() | ||||
|  | ||||
|     def test_file_field_no_default(self): | ||||
| @@ -205,28 +206,28 @@ class TestFileField(MongoDBTestCase): | ||||
|             doc_b = GridDocument.objects.with_id(doc_a.id) | ||||
|             doc_b.the_file.replace(f, filename="doc_b") | ||||
|             doc_b.save() | ||||
|             self.assertNotEqual(doc_b.the_file.grid_id, None) | ||||
|             assert doc_b.the_file.grid_id is not None | ||||
|  | ||||
|             # Test it matches | ||||
|             doc_c = GridDocument.objects.with_id(doc_b.id) | ||||
|             self.assertEqual(doc_b.the_file.grid_id, doc_c.the_file.grid_id) | ||||
|             assert doc_b.the_file.grid_id == doc_c.the_file.grid_id | ||||
|  | ||||
|             # Test with default | ||||
|             doc_d = GridDocument(the_file=six.b("")) | ||||
|             doc_d.save() | ||||
|  | ||||
|             doc_e = GridDocument.objects.with_id(doc_d.id) | ||||
|             self.assertEqual(doc_d.the_file.grid_id, doc_e.the_file.grid_id) | ||||
|             assert doc_d.the_file.grid_id == doc_e.the_file.grid_id | ||||
|  | ||||
|             doc_e.the_file.replace(f, filename="doc_e") | ||||
|             doc_e.save() | ||||
|  | ||||
|             doc_f = GridDocument.objects.with_id(doc_e.id) | ||||
|             self.assertEqual(doc_e.the_file.grid_id, doc_f.the_file.grid_id) | ||||
|             assert doc_e.the_file.grid_id == doc_f.the_file.grid_id | ||||
|  | ||||
|         db = GridDocument._get_db() | ||||
|         grid_fs = gridfs.GridFS(db) | ||||
|         self.assertEqual(["doc_b", "doc_e"], grid_fs.list()) | ||||
|         assert ["doc_b", "doc_e"] == grid_fs.list() | ||||
|  | ||||
|     def test_file_uniqueness(self): | ||||
|         """Ensure that each instance of a FileField is unique | ||||
| @@ -246,8 +247,8 @@ class TestFileField(MongoDBTestCase): | ||||
|         test_file_dupe = TestFile() | ||||
|         data = test_file_dupe.the_file.read()  # Should be None | ||||
|  | ||||
|         self.assertNotEqual(test_file.name, test_file_dupe.name) | ||||
|         self.assertNotEqual(test_file.the_file.read(), data) | ||||
|         assert test_file.name != test_file_dupe.name | ||||
|         assert test_file.the_file.read() != data | ||||
|  | ||||
|         TestFile.drop_collection() | ||||
|  | ||||
| @@ -268,8 +269,8 @@ class TestFileField(MongoDBTestCase): | ||||
|         marmot.save() | ||||
|  | ||||
|         marmot = Animal.objects.get() | ||||
|         self.assertEqual(marmot.photo.content_type, "image/jpeg") | ||||
|         self.assertEqual(marmot.photo.foo, "bar") | ||||
|         assert marmot.photo.content_type == "image/jpeg" | ||||
|         assert marmot.photo.foo == "bar" | ||||
|  | ||||
|     def test_file_reassigning(self): | ||||
|         class TestFile(Document): | ||||
| @@ -278,12 +279,12 @@ class TestFileField(MongoDBTestCase): | ||||
|         TestFile.drop_collection() | ||||
|  | ||||
|         test_file = TestFile(the_file=get_file(TEST_IMAGE_PATH)).save() | ||||
|         self.assertEqual(test_file.the_file.get().length, 8313) | ||||
|         assert test_file.the_file.get().length == 8313 | ||||
|  | ||||
|         test_file = TestFile.objects.first() | ||||
|         test_file.the_file = get_file(TEST_IMAGE2_PATH) | ||||
|         test_file.save() | ||||
|         self.assertEqual(test_file.the_file.get().length, 4971) | ||||
|         assert test_file.the_file.get().length == 4971 | ||||
|  | ||||
|     def test_file_boolean(self): | ||||
|         """Ensure that a boolean test of a FileField indicates its presence | ||||
| @@ -295,13 +296,13 @@ class TestFileField(MongoDBTestCase): | ||||
|         TestFile.drop_collection() | ||||
|  | ||||
|         test_file = TestFile() | ||||
|         self.assertFalse(bool(test_file.the_file)) | ||||
|         assert not bool(test_file.the_file) | ||||
|         test_file.the_file.put(six.b("Hello, World!"), content_type="text/plain") | ||||
|         test_file.save() | ||||
|         self.assertTrue(bool(test_file.the_file)) | ||||
|         assert bool(test_file.the_file) | ||||
|  | ||||
|         test_file = TestFile.objects.first() | ||||
|         self.assertEqual(test_file.the_file.content_type, "text/plain") | ||||
|         assert test_file.the_file.content_type == "text/plain" | ||||
|  | ||||
|     def test_file_cmp(self): | ||||
|         """Test comparing against other types""" | ||||
| @@ -310,7 +311,7 @@ class TestFileField(MongoDBTestCase): | ||||
|             the_file = FileField() | ||||
|  | ||||
|         test_file = TestFile() | ||||
|         self.assertNotIn(test_file.the_file, [{"test": 1}]) | ||||
|         assert test_file.the_file not in [{"test": 1}] | ||||
|  | ||||
|     def test_file_disk_space(self): | ||||
|         """ Test disk space usage when we delete/replace a file """ | ||||
| @@ -330,16 +331,16 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         files = db.fs.files.find() | ||||
|         chunks = db.fs.chunks.find() | ||||
|         self.assertEqual(len(list(files)), 1) | ||||
|         self.assertEqual(len(list(chunks)), 1) | ||||
|         assert len(list(files)) == 1 | ||||
|         assert len(list(chunks)) == 1 | ||||
|  | ||||
|         # Deleting the docoument should delete the files | ||||
|         testfile.delete() | ||||
|  | ||||
|         files = db.fs.files.find() | ||||
|         chunks = db.fs.chunks.find() | ||||
|         self.assertEqual(len(list(files)), 0) | ||||
|         self.assertEqual(len(list(chunks)), 0) | ||||
|         assert len(list(files)) == 0 | ||||
|         assert len(list(chunks)) == 0 | ||||
|  | ||||
|         # Test case where we don't store a file in the first place | ||||
|         testfile = TestFile() | ||||
| @@ -347,15 +348,15 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         files = db.fs.files.find() | ||||
|         chunks = db.fs.chunks.find() | ||||
|         self.assertEqual(len(list(files)), 0) | ||||
|         self.assertEqual(len(list(chunks)), 0) | ||||
|         assert len(list(files)) == 0 | ||||
|         assert len(list(chunks)) == 0 | ||||
|  | ||||
|         testfile.delete() | ||||
|  | ||||
|         files = db.fs.files.find() | ||||
|         chunks = db.fs.chunks.find() | ||||
|         self.assertEqual(len(list(files)), 0) | ||||
|         self.assertEqual(len(list(chunks)), 0) | ||||
|         assert len(list(files)) == 0 | ||||
|         assert len(list(chunks)) == 0 | ||||
|  | ||||
|         # Test case where we overwrite the file | ||||
|         testfile = TestFile() | ||||
| @@ -368,20 +369,18 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         files = db.fs.files.find() | ||||
|         chunks = db.fs.chunks.find() | ||||
|         self.assertEqual(len(list(files)), 1) | ||||
|         self.assertEqual(len(list(chunks)), 1) | ||||
|         assert len(list(files)) == 1 | ||||
|         assert len(list(chunks)) == 1 | ||||
|  | ||||
|         testfile.delete() | ||||
|  | ||||
|         files = db.fs.files.find() | ||||
|         chunks = db.fs.chunks.find() | ||||
|         self.assertEqual(len(list(files)), 0) | ||||
|         self.assertEqual(len(list(chunks)), 0) | ||||
|         assert len(list(files)) == 0 | ||||
|         assert len(list(chunks)) == 0 | ||||
|  | ||||
|     @require_pil | ||||
|     def test_image_field(self): | ||||
|         if not HAS_PIL: | ||||
|             raise SkipTest("PIL not installed") | ||||
|  | ||||
|         class TestImage(Document): | ||||
|             image = ImageField() | ||||
|  | ||||
| @@ -396,9 +395,7 @@ class TestFileField(MongoDBTestCase): | ||||
|                 t.image.put(f) | ||||
|                 self.fail("Should have raised an invalidation error") | ||||
|             except ValidationError as e: | ||||
|                 self.assertEqual( | ||||
|                     "%s" % e, "Invalid image: cannot identify image file %s" % f | ||||
|                 ) | ||||
|                 assert "%s" % e == "Invalid image: cannot identify image file %s" % f | ||||
|  | ||||
|         t = TestImage() | ||||
|         t.image.put(get_file(TEST_IMAGE_PATH)) | ||||
| @@ -406,35 +403,31 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         t = TestImage.objects.first() | ||||
|  | ||||
|         self.assertEqual(t.image.format, "PNG") | ||||
|         assert t.image.format == "PNG" | ||||
|  | ||||
|         w, h = t.image.size | ||||
|         self.assertEqual(w, 371) | ||||
|         self.assertEqual(h, 76) | ||||
|         assert w == 371 | ||||
|         assert h == 76 | ||||
|  | ||||
|         t.image.delete() | ||||
|  | ||||
|     @require_pil | ||||
|     def test_image_field_reassigning(self): | ||||
|         if not HAS_PIL: | ||||
|             raise SkipTest("PIL not installed") | ||||
|  | ||||
|         class TestFile(Document): | ||||
|             the_file = ImageField() | ||||
|  | ||||
|         TestFile.drop_collection() | ||||
|  | ||||
|         test_file = TestFile(the_file=get_file(TEST_IMAGE_PATH)).save() | ||||
|         self.assertEqual(test_file.the_file.size, (371, 76)) | ||||
|         assert test_file.the_file.size == (371, 76) | ||||
|  | ||||
|         test_file = TestFile.objects.first() | ||||
|         test_file.the_file = get_file(TEST_IMAGE2_PATH) | ||||
|         test_file.save() | ||||
|         self.assertEqual(test_file.the_file.size, (45, 101)) | ||||
|         assert test_file.the_file.size == (45, 101) | ||||
|  | ||||
|     @require_pil | ||||
|     def test_image_field_resize(self): | ||||
|         if not HAS_PIL: | ||||
|             raise SkipTest("PIL not installed") | ||||
|  | ||||
|         class TestImage(Document): | ||||
|             image = ImageField(size=(185, 37)) | ||||
|  | ||||
| @@ -446,18 +439,16 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         t = TestImage.objects.first() | ||||
|  | ||||
|         self.assertEqual(t.image.format, "PNG") | ||||
|         assert t.image.format == "PNG" | ||||
|         w, h = t.image.size | ||||
|  | ||||
|         self.assertEqual(w, 185) | ||||
|         self.assertEqual(h, 37) | ||||
|         assert w == 185 | ||||
|         assert h == 37 | ||||
|  | ||||
|         t.image.delete() | ||||
|  | ||||
|     @require_pil | ||||
|     def test_image_field_resize_force(self): | ||||
|         if not HAS_PIL: | ||||
|             raise SkipTest("PIL not installed") | ||||
|  | ||||
|         class TestImage(Document): | ||||
|             image = ImageField(size=(185, 37, True)) | ||||
|  | ||||
| @@ -469,18 +460,16 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         t = TestImage.objects.first() | ||||
|  | ||||
|         self.assertEqual(t.image.format, "PNG") | ||||
|         assert t.image.format == "PNG" | ||||
|         w, h = t.image.size | ||||
|  | ||||
|         self.assertEqual(w, 185) | ||||
|         self.assertEqual(h, 37) | ||||
|         assert w == 185 | ||||
|         assert h == 37 | ||||
|  | ||||
|         t.image.delete() | ||||
|  | ||||
|     @require_pil | ||||
|     def test_image_field_thumbnail(self): | ||||
|         if not HAS_PIL: | ||||
|             raise SkipTest("PIL not installed") | ||||
|  | ||||
|         class TestImage(Document): | ||||
|             image = ImageField(thumbnail_size=(92, 18)) | ||||
|  | ||||
| @@ -492,9 +481,9 @@ class TestFileField(MongoDBTestCase): | ||||
|  | ||||
|         t = TestImage.objects.first() | ||||
|  | ||||
|         self.assertEqual(t.image.thumbnail.format, "PNG") | ||||
|         self.assertEqual(t.image.thumbnail.width, 92) | ||||
|         self.assertEqual(t.image.thumbnail.height, 18) | ||||
|         assert t.image.thumbnail.format == "PNG" | ||||
|         assert t.image.thumbnail.width == 92 | ||||
|         assert t.image.thumbnail.height == 18 | ||||
|  | ||||
|         t.image.delete() | ||||
|  | ||||
| @@ -518,17 +507,17 @@ class TestFileField(MongoDBTestCase): | ||||
|         test_file.save() | ||||
|  | ||||
|         data = get_db("test_files").macumba.files.find_one() | ||||
|         self.assertEqual(data.get("name"), "hello.txt") | ||||
|         assert data.get("name") == "hello.txt" | ||||
|  | ||||
|         test_file = TestFile.objects.first() | ||||
|         self.assertEqual(test_file.the_file.read(), six.b("Hello, World!")) | ||||
|         assert test_file.the_file.read() == six.b("Hello, World!") | ||||
|  | ||||
|         test_file = TestFile.objects.first() | ||||
|         test_file.the_file = six.b("HELLO, WORLD!") | ||||
|         test_file.save() | ||||
|  | ||||
|         test_file = TestFile.objects.first() | ||||
|         self.assertEqual(test_file.the_file.read(), six.b("HELLO, WORLD!")) | ||||
|         assert test_file.the_file.read() == six.b("HELLO, WORLD!") | ||||
|  | ||||
|     def test_copyable(self): | ||||
|         class PutFile(Document): | ||||
| @@ -546,14 +535,11 @@ class TestFileField(MongoDBTestCase): | ||||
|         class TestFile(Document): | ||||
|             name = StringField() | ||||
|  | ||||
|         self.assertEqual(putfile, copy.copy(putfile)) | ||||
|         self.assertEqual(putfile, copy.deepcopy(putfile)) | ||||
|         assert putfile == copy.copy(putfile) | ||||
|         assert putfile == copy.deepcopy(putfile) | ||||
|  | ||||
|     @require_pil | ||||
|     def test_get_image_by_grid_id(self): | ||||
|  | ||||
|         if not HAS_PIL: | ||||
|             raise SkipTest("PIL not installed") | ||||
|  | ||||
|         class TestImage(Document): | ||||
|  | ||||
|             image1 = ImageField() | ||||
| @@ -569,9 +555,7 @@ class TestFileField(MongoDBTestCase): | ||||
|         test = TestImage.objects.first() | ||||
|         grid_id = test.image1.grid_id | ||||
|  | ||||
|         self.assertEqual( | ||||
|             1, TestImage.objects(Q(image1=grid_id) or Q(image2=grid_id)).count() | ||||
|         ) | ||||
|         assert 1 == TestImage.objects(Q(image1=grid_id) or Q(image2=grid_id)).count() | ||||
|  | ||||
|     def test_complex_field_filefield(self): | ||||
|         """Ensure you can add meta data to file""" | ||||
| @@ -593,9 +577,9 @@ class TestFileField(MongoDBTestCase): | ||||
|         marmot.save() | ||||
|  | ||||
|         marmot = Animal.objects.get() | ||||
|         self.assertEqual(marmot.photos[0].content_type, "image/jpeg") | ||||
|         self.assertEqual(marmot.photos[0].foo, "bar") | ||||
|         self.assertEqual(marmot.photos[0].get().length, 8313) | ||||
|         assert marmot.photos[0].content_type == "image/jpeg" | ||||
|         assert marmot.photos[0].foo == "bar" | ||||
|         assert marmot.photos[0].get().length == 8313 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
| import six | ||||
|  | ||||
| from mongoengine import * | ||||
| @@ -16,8 +17,8 @@ class TestFloatField(MongoDBTestCase): | ||||
|         TestDocument(float_fld=None).save() | ||||
|         TestDocument(float_fld=1).save() | ||||
|  | ||||
|         self.assertEqual(1, TestDocument.objects(float_fld__ne=None).count()) | ||||
|         self.assertEqual(1, TestDocument.objects(float_fld__ne=1).count()) | ||||
|         assert 1 == TestDocument.objects(float_fld__ne=None).count() | ||||
|         assert 1 == TestDocument.objects(float_fld__ne=1).count() | ||||
|  | ||||
|     def test_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to float fields. | ||||
| @@ -34,16 +35,20 @@ class TestFloatField(MongoDBTestCase): | ||||
|         person.validate() | ||||
|  | ||||
|         person.height = "2.0" | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|         person.height = 0.01 | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|         person.height = 4.0 | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|         person_2 = Person(height="something invalid") | ||||
|         self.assertRaises(ValidationError, person_2.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person_2.validate() | ||||
|  | ||||
|         big_person = BigPerson() | ||||
|  | ||||
| @@ -55,4 +60,5 @@ class TestFloatField(MongoDBTestCase): | ||||
|         big_person.validate() | ||||
|  | ||||
|         big_person.height = 2 ** 100000  # Too big for a float value | ||||
|         self.assertRaises(ValidationError, big_person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             big_person.validate() | ||||
|   | ||||
| @@ -11,7 +11,7 @@ class TestGeoField(MongoDBTestCase): | ||||
|             Cls(loc=loc).validate() | ||||
|             self.fail("Should not validate the location {0}".format(loc)) | ||||
|         except ValidationError as e: | ||||
|             self.assertEqual(expected, e.to_dict()["loc"]) | ||||
|             assert expected == e.to_dict()["loc"] | ||||
|  | ||||
|     def test_geopoint_validation(self): | ||||
|         class Location(Document): | ||||
| @@ -299,7 +299,7 @@ class TestGeoField(MongoDBTestCase): | ||||
|             location = GeoPointField() | ||||
|  | ||||
|         geo_indicies = Event._geo_indices() | ||||
|         self.assertEqual(geo_indicies, [{"fields": [("location", "2d")]}]) | ||||
|         assert geo_indicies == [{"fields": [("location", "2d")]}] | ||||
|  | ||||
|     def test_geopoint_embedded_indexes(self): | ||||
|         """Ensure that indexes are created automatically for GeoPointFields on | ||||
| @@ -315,7 +315,7 @@ class TestGeoField(MongoDBTestCase): | ||||
|             venue = EmbeddedDocumentField(Venue) | ||||
|  | ||||
|         geo_indicies = Event._geo_indices() | ||||
|         self.assertEqual(geo_indicies, [{"fields": [("venue.location", "2d")]}]) | ||||
|         assert geo_indicies == [{"fields": [("venue.location", "2d")]}] | ||||
|  | ||||
|     def test_indexes_2dsphere(self): | ||||
|         """Ensure that indexes are created automatically for GeoPointFields. | ||||
| @@ -328,9 +328,9 @@ class TestGeoField(MongoDBTestCase): | ||||
|             polygon = PolygonField() | ||||
|  | ||||
|         geo_indicies = Event._geo_indices() | ||||
|         self.assertIn({"fields": [("line", "2dsphere")]}, geo_indicies) | ||||
|         self.assertIn({"fields": [("polygon", "2dsphere")]}, geo_indicies) | ||||
|         self.assertIn({"fields": [("point", "2dsphere")]}, geo_indicies) | ||||
|         assert {"fields": [("line", "2dsphere")]} in geo_indicies | ||||
|         assert {"fields": [("polygon", "2dsphere")]} in geo_indicies | ||||
|         assert {"fields": [("point", "2dsphere")]} in geo_indicies | ||||
|  | ||||
|     def test_indexes_2dsphere_embedded(self): | ||||
|         """Ensure that indexes are created automatically for GeoPointFields. | ||||
| @@ -347,9 +347,9 @@ class TestGeoField(MongoDBTestCase): | ||||
|             venue = EmbeddedDocumentField(Venue) | ||||
|  | ||||
|         geo_indicies = Event._geo_indices() | ||||
|         self.assertIn({"fields": [("venue.line", "2dsphere")]}, geo_indicies) | ||||
|         self.assertIn({"fields": [("venue.polygon", "2dsphere")]}, geo_indicies) | ||||
|         self.assertIn({"fields": [("venue.point", "2dsphere")]}, geo_indicies) | ||||
|         assert {"fields": [("venue.line", "2dsphere")]} in geo_indicies | ||||
|         assert {"fields": [("venue.polygon", "2dsphere")]} in geo_indicies | ||||
|         assert {"fields": [("venue.point", "2dsphere")]} in geo_indicies | ||||
|  | ||||
|     def test_geo_indexes_recursion(self): | ||||
|         class Location(Document): | ||||
| @@ -365,12 +365,12 @@ class TestGeoField(MongoDBTestCase): | ||||
|  | ||||
|         Parent(name="Berlin").save() | ||||
|         info = Parent._get_collection().index_information() | ||||
|         self.assertNotIn("location_2d", info) | ||||
|         assert "location_2d" not in info | ||||
|         info = Location._get_collection().index_information() | ||||
|         self.assertIn("location_2d", info) | ||||
|         assert "location_2d" in info | ||||
|  | ||||
|         self.assertEqual(len(Parent._geo_indices()), 0) | ||||
|         self.assertEqual(len(Location._geo_indices()), 1) | ||||
|         assert len(Parent._geo_indices()) == 0 | ||||
|         assert len(Location._geo_indices()) == 1 | ||||
|  | ||||
|     def test_geo_indexes_auto_index(self): | ||||
|  | ||||
| @@ -381,16 +381,16 @@ class TestGeoField(MongoDBTestCase): | ||||
|  | ||||
|             meta = {"indexes": [[("location", "2dsphere"), ("datetime", 1)]]} | ||||
|  | ||||
|         self.assertEqual([], Log._geo_indices()) | ||||
|         assert [] == Log._geo_indices() | ||||
|  | ||||
|         Log.drop_collection() | ||||
|         Log.ensure_indexes() | ||||
|  | ||||
|         info = Log._get_collection().index_information() | ||||
|         self.assertEqual( | ||||
|             info["location_2dsphere_datetime_1"]["key"], | ||||
|             [("location", "2dsphere"), ("datetime", 1)], | ||||
|         ) | ||||
|         assert info["location_2dsphere_datetime_1"]["key"] == [ | ||||
|             ("location", "2dsphere"), | ||||
|             ("datetime", 1), | ||||
|         ] | ||||
|  | ||||
|         # Test listing explicitly | ||||
|         class Log(Document): | ||||
| @@ -401,16 +401,16 @@ class TestGeoField(MongoDBTestCase): | ||||
|                 "indexes": [{"fields": [("location", "2dsphere"), ("datetime", 1)]}] | ||||
|             } | ||||
|  | ||||
|         self.assertEqual([], Log._geo_indices()) | ||||
|         assert [] == Log._geo_indices() | ||||
|  | ||||
|         Log.drop_collection() | ||||
|         Log.ensure_indexes() | ||||
|  | ||||
|         info = Log._get_collection().index_information() | ||||
|         self.assertEqual( | ||||
|             info["location_2dsphere_datetime_1"]["key"], | ||||
|             [("location", "2dsphere"), ("datetime", 1)], | ||||
|         ) | ||||
|         assert info["location_2dsphere_datetime_1"]["key"] == [ | ||||
|             ("location", "2dsphere"), | ||||
|             ("datetime", 1), | ||||
|         ] | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
| @@ -23,11 +25,14 @@ class TestIntField(MongoDBTestCase): | ||||
|         person.validate() | ||||
|  | ||||
|         person.age = -1 | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.age = 120 | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|         person.age = "ten" | ||||
|         self.assertRaises(ValidationError, person.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             person.validate() | ||||
|  | ||||
|     def test_ne_operator(self): | ||||
|         class TestDocument(Document): | ||||
| @@ -38,5 +43,5 @@ class TestIntField(MongoDBTestCase): | ||||
|         TestDocument(int_fld=None).save() | ||||
|         TestDocument(int_fld=1).save() | ||||
|  | ||||
|         self.assertEqual(1, TestDocument.objects(int_fld__ne=None).count()) | ||||
|         self.assertEqual(1, TestDocument.objects(int_fld__ne=1).count()) | ||||
|         assert 1 == TestDocument.objects(int_fld__ne=None).count() | ||||
|         assert 1 == TestDocument.objects(int_fld__ne=1).count() | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| from bson import DBRef, ObjectId | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.base import LazyReference | ||||
| @@ -11,7 +12,8 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|     def test_lazy_reference_config(self): | ||||
|         # Make sure ReferenceField only accepts a document class or a string | ||||
|         # with a document class name. | ||||
|         self.assertRaises(ValidationError, LazyReferenceField, EmbeddedDocument) | ||||
|         with pytest.raises(ValidationError): | ||||
|             LazyReferenceField(EmbeddedDocument) | ||||
|  | ||||
|     def test___repr__(self): | ||||
|         class Animal(Document): | ||||
| @@ -25,7 +27,7 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         animal = Animal() | ||||
|         oc = Ocurrence(animal=animal) | ||||
|         self.assertIn("LazyReference", repr(oc.animal)) | ||||
|         assert "LazyReference" in repr(oc.animal) | ||||
|  | ||||
|     def test___getattr___unknown_attr_raises_attribute_error(self): | ||||
|         class Animal(Document): | ||||
| @@ -39,7 +41,7 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         animal = Animal().save() | ||||
|         oc = Ocurrence(animal=animal) | ||||
|         with self.assertRaises(AttributeError): | ||||
|         with pytest.raises(AttributeError): | ||||
|             oc.animal.not_exist | ||||
|  | ||||
|     def test_lazy_reference_simple(self): | ||||
| @@ -57,19 +59,19 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         animal = Animal(name="Leopard", tag="heavy").save() | ||||
|         Ocurrence(person="test", animal=animal).save() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertIsInstance(p.animal, LazyReference) | ||||
|         assert isinstance(p.animal, LazyReference) | ||||
|         fetched_animal = p.animal.fetch() | ||||
|         self.assertEqual(fetched_animal, animal) | ||||
|         assert fetched_animal == animal | ||||
|         # `fetch` keep cache on referenced document by default... | ||||
|         animal.tag = "not so heavy" | ||||
|         animal.save() | ||||
|         double_fetch = p.animal.fetch() | ||||
|         self.assertIs(fetched_animal, double_fetch) | ||||
|         self.assertEqual(double_fetch.tag, "heavy") | ||||
|         assert fetched_animal is double_fetch | ||||
|         assert double_fetch.tag == "heavy" | ||||
|         # ...unless specified otherwise | ||||
|         fetch_force = p.animal.fetch(force=True) | ||||
|         self.assertIsNot(fetch_force, fetched_animal) | ||||
|         self.assertEqual(fetch_force.tag, "not so heavy") | ||||
|         assert fetch_force is not fetched_animal | ||||
|         assert fetch_force.tag == "not so heavy" | ||||
|  | ||||
|     def test_lazy_reference_fetch_invalid_ref(self): | ||||
|         class Animal(Document): | ||||
| @@ -87,8 +89,8 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         Ocurrence(person="test", animal=animal).save() | ||||
|         animal.delete() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertIsInstance(p.animal, LazyReference) | ||||
|         with self.assertRaises(DoesNotExist): | ||||
|         assert isinstance(p.animal, LazyReference) | ||||
|         with pytest.raises(DoesNotExist): | ||||
|             p.animal.fetch() | ||||
|  | ||||
|     def test_lazy_reference_set(self): | ||||
| @@ -122,7 +124,7 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         ): | ||||
|             p = Ocurrence(person="test", animal=ref).save() | ||||
|             p.reload() | ||||
|             self.assertIsInstance(p.animal, LazyReference) | ||||
|             assert isinstance(p.animal, LazyReference) | ||||
|             p.animal.fetch() | ||||
|  | ||||
|     def test_lazy_reference_bad_set(self): | ||||
| @@ -149,7 +151,7 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|             DBRef(baddoc._get_collection_name(), animal.pk), | ||||
|             LazyReference(BadDoc, animal.pk), | ||||
|         ): | ||||
|             with self.assertRaises(ValidationError): | ||||
|             with pytest.raises(ValidationError): | ||||
|                 p = Ocurrence(person="test", animal=bad).save() | ||||
|  | ||||
|     def test_lazy_reference_query_conversion(self): | ||||
| @@ -179,14 +181,14 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         post2.save() | ||||
|  | ||||
|         post = BlogPost.objects(author=m1).first() | ||||
|         self.assertEqual(post.id, post1.id) | ||||
|         assert post.id == post1.id | ||||
|  | ||||
|         post = BlogPost.objects(author=m2).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|         # Same thing by passing a LazyReference instance | ||||
|         post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|     def test_lazy_reference_query_conversion_dbref(self): | ||||
|         """Ensure that LazyReferenceFields can be queried using objects and values | ||||
| @@ -215,14 +217,14 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         post2.save() | ||||
|  | ||||
|         post = BlogPost.objects(author=m1).first() | ||||
|         self.assertEqual(post.id, post1.id) | ||||
|         assert post.id == post1.id | ||||
|  | ||||
|         post = BlogPost.objects(author=m2).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|         # Same thing by passing a LazyReference instance | ||||
|         post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|     def test_lazy_reference_passthrough(self): | ||||
|         class Animal(Document): | ||||
| @@ -239,20 +241,20 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         animal = Animal(name="Leopard", tag="heavy").save() | ||||
|         Ocurrence(animal=animal, animal_passthrough=animal).save() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertIsInstance(p.animal, LazyReference) | ||||
|         with self.assertRaises(KeyError): | ||||
|         assert isinstance(p.animal, LazyReference) | ||||
|         with pytest.raises(KeyError): | ||||
|             p.animal["name"] | ||||
|         with self.assertRaises(AttributeError): | ||||
|         with pytest.raises(AttributeError): | ||||
|             p.animal.name | ||||
|         self.assertEqual(p.animal.pk, animal.pk) | ||||
|         assert p.animal.pk == animal.pk | ||||
|  | ||||
|         self.assertEqual(p.animal_passthrough.name, "Leopard") | ||||
|         self.assertEqual(p.animal_passthrough["name"], "Leopard") | ||||
|         assert p.animal_passthrough.name == "Leopard" | ||||
|         assert p.animal_passthrough["name"] == "Leopard" | ||||
|  | ||||
|         # Should not be able to access referenced document's methods | ||||
|         with self.assertRaises(AttributeError): | ||||
|         with pytest.raises(AttributeError): | ||||
|             p.animal.save | ||||
|         with self.assertRaises(KeyError): | ||||
|         with pytest.raises(KeyError): | ||||
|             p.animal["save"] | ||||
|  | ||||
|     def test_lazy_reference_not_set(self): | ||||
| @@ -269,7 +271,7 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         Ocurrence(person="foo").save() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertIs(p.animal, None) | ||||
|         assert p.animal is None | ||||
|  | ||||
|     def test_lazy_reference_equality(self): | ||||
|         class Animal(Document): | ||||
| @@ -280,12 +282,12 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         animal = Animal(name="Leopard", tag="heavy").save() | ||||
|         animalref = LazyReference(Animal, animal.pk) | ||||
|         self.assertEqual(animal, animalref) | ||||
|         self.assertEqual(animalref, animal) | ||||
|         assert animal == animalref | ||||
|         assert animalref == animal | ||||
|  | ||||
|         other_animalref = LazyReference(Animal, ObjectId("54495ad94c934721ede76f90")) | ||||
|         self.assertNotEqual(animal, other_animalref) | ||||
|         self.assertNotEqual(other_animalref, animal) | ||||
|         assert animal != other_animalref | ||||
|         assert other_animalref != animal | ||||
|  | ||||
|     def test_lazy_reference_embedded(self): | ||||
|         class Animal(Document): | ||||
| @@ -308,12 +310,12 @@ class TestLazyReferenceField(MongoDBTestCase): | ||||
|         animal2 = Animal(name="cheeta").save() | ||||
|  | ||||
|         def check_fields_type(occ): | ||||
|             self.assertIsInstance(occ.direct, LazyReference) | ||||
|             assert isinstance(occ.direct, LazyReference) | ||||
|             for elem in occ.in_list: | ||||
|                 self.assertIsInstance(elem, LazyReference) | ||||
|             self.assertIsInstance(occ.in_embedded.direct, LazyReference) | ||||
|                 assert isinstance(elem, LazyReference) | ||||
|             assert isinstance(occ.in_embedded.direct, LazyReference) | ||||
|             for elem in occ.in_embedded.in_list: | ||||
|                 self.assertIsInstance(elem, LazyReference) | ||||
|                 assert isinstance(elem, LazyReference) | ||||
|  | ||||
|         occ = Ocurrence( | ||||
|             in_list=[animal1, animal2], | ||||
| @@ -346,19 +348,19 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|         animal = Animal(name="Leopard", tag="heavy").save() | ||||
|         Ocurrence(person="test", animal=animal).save() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertIsInstance(p.animal, LazyReference) | ||||
|         assert isinstance(p.animal, LazyReference) | ||||
|         fetched_animal = p.animal.fetch() | ||||
|         self.assertEqual(fetched_animal, animal) | ||||
|         assert fetched_animal == animal | ||||
|         # `fetch` keep cache on referenced document by default... | ||||
|         animal.tag = "not so heavy" | ||||
|         animal.save() | ||||
|         double_fetch = p.animal.fetch() | ||||
|         self.assertIs(fetched_animal, double_fetch) | ||||
|         self.assertEqual(double_fetch.tag, "heavy") | ||||
|         assert fetched_animal is double_fetch | ||||
|         assert double_fetch.tag == "heavy" | ||||
|         # ...unless specified otherwise | ||||
|         fetch_force = p.animal.fetch(force=True) | ||||
|         self.assertIsNot(fetch_force, fetched_animal) | ||||
|         self.assertEqual(fetch_force.tag, "not so heavy") | ||||
|         assert fetch_force is not fetched_animal | ||||
|         assert fetch_force.tag == "not so heavy" | ||||
|  | ||||
|     def test_generic_lazy_reference_choices(self): | ||||
|         class Animal(Document): | ||||
| @@ -385,13 +387,13 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         occ_animal = Ocurrence(living_thing=animal, thing=animal).save() | ||||
|         occ_vegetal = Ocurrence(living_thing=vegetal, thing=vegetal).save() | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|             Ocurrence(living_thing=mineral).save() | ||||
|  | ||||
|         occ = Ocurrence.objects.get(living_thing=animal) | ||||
|         self.assertEqual(occ, occ_animal) | ||||
|         self.assertIsInstance(occ.thing, LazyReference) | ||||
|         self.assertIsInstance(occ.living_thing, LazyReference) | ||||
|         assert occ == occ_animal | ||||
|         assert isinstance(occ.thing, LazyReference) | ||||
|         assert isinstance(occ.living_thing, LazyReference) | ||||
|  | ||||
|         occ.thing = vegetal | ||||
|         occ.living_thing = vegetal | ||||
| @@ -399,7 +401,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         occ.thing = mineral | ||||
|         occ.living_thing = mineral | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|             occ.save() | ||||
|  | ||||
|     def test_generic_lazy_reference_set(self): | ||||
| @@ -434,7 +436,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|         ): | ||||
|             p = Ocurrence(person="test", animal=ref).save() | ||||
|             p.reload() | ||||
|             self.assertIsInstance(p.animal, (LazyReference, Document)) | ||||
|             assert isinstance(p.animal, (LazyReference, Document)) | ||||
|             p.animal.fetch() | ||||
|  | ||||
|     def test_generic_lazy_reference_bad_set(self): | ||||
| @@ -455,7 +457,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|         animal = Animal(name="Leopard", tag="heavy").save() | ||||
|         baddoc = BadDoc().save() | ||||
|         for bad in (42, "foo", baddoc, LazyReference(BadDoc, animal.pk)): | ||||
|             with self.assertRaises(ValidationError): | ||||
|             with pytest.raises(ValidationError): | ||||
|                 p = Ocurrence(person="test", animal=bad).save() | ||||
|  | ||||
|     def test_generic_lazy_reference_query_conversion(self): | ||||
| @@ -481,14 +483,14 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|         post2.save() | ||||
|  | ||||
|         post = BlogPost.objects(author=m1).first() | ||||
|         self.assertEqual(post.id, post1.id) | ||||
|         assert post.id == post1.id | ||||
|  | ||||
|         post = BlogPost.objects(author=m2).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|         # Same thing by passing a LazyReference instance | ||||
|         post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|     def test_generic_lazy_reference_not_set(self): | ||||
|         class Animal(Document): | ||||
| @@ -504,7 +506,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         Ocurrence(person="foo").save() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertIs(p.animal, None) | ||||
|         assert p.animal is None | ||||
|  | ||||
|     def test_generic_lazy_reference_accepts_string_instead_of_class(self): | ||||
|         class Animal(Document): | ||||
| @@ -521,7 +523,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|         animal = Animal().save() | ||||
|         Ocurrence(animal=animal).save() | ||||
|         p = Ocurrence.objects.get() | ||||
|         self.assertEqual(p.animal, animal) | ||||
|         assert p.animal == animal | ||||
|  | ||||
|     def test_generic_lazy_reference_embedded(self): | ||||
|         class Animal(Document): | ||||
| @@ -544,12 +546,12 @@ class TestGenericLazyReferenceField(MongoDBTestCase): | ||||
|         animal2 = Animal(name="cheeta").save() | ||||
|  | ||||
|         def check_fields_type(occ): | ||||
|             self.assertIsInstance(occ.direct, LazyReference) | ||||
|             assert isinstance(occ.direct, LazyReference) | ||||
|             for elem in occ.in_list: | ||||
|                 self.assertIsInstance(elem, LazyReference) | ||||
|             self.assertIsInstance(occ.in_embedded.direct, LazyReference) | ||||
|                 assert isinstance(elem, LazyReference) | ||||
|             assert isinstance(occ.in_embedded.direct, LazyReference) | ||||
|             for elem in occ.in_embedded.in_list: | ||||
|                 self.assertIsInstance(elem, LazyReference) | ||||
|                 assert isinstance(elem, LazyReference) | ||||
|  | ||||
|         occ = Ocurrence( | ||||
|             in_list=[animal1, animal2], | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
| import six | ||||
|  | ||||
| try: | ||||
| @@ -24,10 +25,10 @@ class TestLongField(MongoDBTestCase): | ||||
|  | ||||
|         doc = TestLongFieldConsideredAsInt64(some_long=42).save() | ||||
|         db = get_db() | ||||
|         self.assertIsInstance( | ||||
|         assert isinstance( | ||||
|             db.test_long_field_considered_as_int64.find()[0]["some_long"], Int64 | ||||
|         ) | ||||
|         self.assertIsInstance(doc.some_long, six.integer_types) | ||||
|         assert isinstance(doc.some_long, six.integer_types) | ||||
|  | ||||
|     def test_long_validation(self): | ||||
|         """Ensure that invalid values cannot be assigned to long fields. | ||||
| @@ -41,11 +42,14 @@ class TestLongField(MongoDBTestCase): | ||||
|         doc.validate() | ||||
|  | ||||
|         doc.value = -1 | ||||
|         self.assertRaises(ValidationError, doc.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             doc.validate() | ||||
|         doc.value = 120 | ||||
|         self.assertRaises(ValidationError, doc.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             doc.validate() | ||||
|         doc.value = "ten" | ||||
|         self.assertRaises(ValidationError, doc.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             doc.validate() | ||||
|  | ||||
|     def test_long_ne_operator(self): | ||||
|         class TestDocument(Document): | ||||
| @@ -56,4 +60,4 @@ class TestLongField(MongoDBTestCase): | ||||
|         TestDocument(long_fld=None).save() | ||||
|         TestDocument(long_fld=1).save() | ||||
|  | ||||
|         self.assertEqual(1, TestDocument.objects(long_fld__ne=None).count()) | ||||
|         assert 1 == TestDocument.objects(long_fld__ne=None).count() | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import datetime | ||||
|  | ||||
| from mongoengine import * | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| @@ -19,11 +20,11 @@ class TestMapField(MongoDBTestCase): | ||||
|         e.mapping["someint"] = 1 | ||||
|         e.save() | ||||
|  | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|             e.mapping["somestring"] = "abc" | ||||
|             e.save() | ||||
|  | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|  | ||||
|             class NoDeclaredType(Document): | ||||
|                 mapping = MapField() | ||||
| @@ -51,10 +52,10 @@ class TestMapField(MongoDBTestCase): | ||||
|         e.save() | ||||
|  | ||||
|         e2 = Extensible.objects.get(id=e.id) | ||||
|         self.assertIsInstance(e2.mapping["somestring"], StringSetting) | ||||
|         self.assertIsInstance(e2.mapping["someint"], IntegerSetting) | ||||
|         assert isinstance(e2.mapping["somestring"], StringSetting) | ||||
|         assert isinstance(e2.mapping["someint"], IntegerSetting) | ||||
|  | ||||
|         with self.assertRaises(ValidationError): | ||||
|         with pytest.raises(ValidationError): | ||||
|             e.mapping["someint"] = 123 | ||||
|             e.save() | ||||
|  | ||||
| @@ -74,9 +75,9 @@ class TestMapField(MongoDBTestCase): | ||||
|         Test.objects.update_one(inc__my_map__DICTIONARY_KEY__number=1) | ||||
|  | ||||
|         test = Test.objects.get() | ||||
|         self.assertEqual(test.my_map["DICTIONARY_KEY"].number, 2) | ||||
|         assert test.my_map["DICTIONARY_KEY"].number == 2 | ||||
|         doc = self.db.test.find_one() | ||||
|         self.assertEqual(doc["x"]["DICTIONARY_KEY"]["i"], 2) | ||||
|         assert doc["x"]["DICTIONARY_KEY"]["i"] == 2 | ||||
|  | ||||
|     def test_mapfield_numerical_index(self): | ||||
|         """Ensure that MapField accept numeric strings as indexes.""" | ||||
| @@ -116,13 +117,13 @@ class TestMapField(MongoDBTestCase): | ||||
|             actions={"friends": Action(operation="drink", object="beer")}, | ||||
|         ).save() | ||||
|  | ||||
|         self.assertEqual(1, Log.objects(visited__friends__exists=True).count()) | ||||
|         assert 1 == Log.objects(visited__friends__exists=True).count() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             1, | ||||
|             Log.objects( | ||||
|         assert ( | ||||
|             1 | ||||
|             == Log.objects( | ||||
|                 actions__friends__operation="drink", actions__friends__object="beer" | ||||
|             ).count(), | ||||
|             ).count() | ||||
|         ) | ||||
|  | ||||
|     def test_map_field_unicode(self): | ||||
| @@ -139,7 +140,7 @@ class TestMapField(MongoDBTestCase): | ||||
|  | ||||
|         tree.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             BlogPost.objects.get(id=tree.id).info_dict[u"éééé"].description, | ||||
|             u"VALUE: éééé", | ||||
|         assert ( | ||||
|             BlogPost.objects.get(id=tree.id).info_dict[u"éééé"].description | ||||
|             == u"VALUE: éééé" | ||||
|         ) | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| from bson import SON, DBRef | ||||
| from bson import DBRef, SON | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| @@ -24,19 +24,22 @@ class TestReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         # Make sure ReferenceField only accepts a document class or a string | ||||
|         # with a document class name. | ||||
|         self.assertRaises(ValidationError, ReferenceField, EmbeddedDocument) | ||||
|         with pytest.raises(ValidationError): | ||||
|             ReferenceField(EmbeddedDocument) | ||||
|  | ||||
|         user = User(name="Test User") | ||||
|  | ||||
|         # Ensure that the referenced object must have been saved | ||||
|         post1 = BlogPost(content="Chips and gravy taste good.") | ||||
|         post1.author = user | ||||
|         self.assertRaises(ValidationError, post1.save) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post1.save() | ||||
|  | ||||
|         # Check that an invalid object type cannot be used | ||||
|         post2 = BlogPost(content="Chips and chilli taste good.") | ||||
|         post1.author = post2 | ||||
|         self.assertRaises(ValidationError, post1.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post1.validate() | ||||
|  | ||||
|         # Ensure ObjectID's are accepted as references | ||||
|         user_object_id = user.pk | ||||
| @@ -52,22 +55,8 @@ class TestReferenceField(MongoDBTestCase): | ||||
|         # Make sure referencing a saved document of the *wrong* type fails | ||||
|         post2.save() | ||||
|         post1.author = post2 | ||||
|         self.assertRaises(ValidationError, post1.validate) | ||||
|  | ||||
|     def test_objectid_reference_fields(self): | ||||
|         """Make sure storing Object ID references works.""" | ||||
|  | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             parent = ReferenceField("self") | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="John").save() | ||||
|         Person(name="Ross", parent=p1.pk).save() | ||||
|  | ||||
|         p = Person.objects.get(name="Ross") | ||||
|         self.assertEqual(p.parent, p1) | ||||
|         with pytest.raises(ValidationError): | ||||
|             post1.validate() | ||||
|  | ||||
|     def test_dbref_reference_fields(self): | ||||
|         """Make sure storing references as bson.dbref.DBRef works.""" | ||||
| @@ -81,13 +70,12 @@ class TestReferenceField(MongoDBTestCase): | ||||
|         p1 = Person(name="John").save() | ||||
|         Person(name="Ross", parent=p1).save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             Person._get_collection().find_one({"name": "Ross"})["parent"], | ||||
|             DBRef("person", p1.pk), | ||||
|         assert Person._get_collection().find_one({"name": "Ross"})["parent"] == DBRef( | ||||
|             "person", p1.pk | ||||
|         ) | ||||
|  | ||||
|         p = Person.objects.get(name="Ross") | ||||
|         self.assertEqual(p.parent, p1) | ||||
|         assert p.parent == p1 | ||||
|  | ||||
|     def test_dbref_to_mongo(self): | ||||
|         """Make sure that calling to_mongo on a ReferenceField which | ||||
| @@ -100,9 +88,7 @@ class TestReferenceField(MongoDBTestCase): | ||||
|             parent = ReferenceField("self", dbref=False) | ||||
|  | ||||
|         p = Person(name="Steve", parent=DBRef("person", "abcdefghijklmnop")) | ||||
|         self.assertEqual( | ||||
|             p.to_mongo(), SON([("name", u"Steve"), ("parent", "abcdefghijklmnop")]) | ||||
|         ) | ||||
|         assert p.to_mongo() == SON([("name", u"Steve"), ("parent", "abcdefghijklmnop")]) | ||||
|  | ||||
|     def test_objectid_reference_fields(self): | ||||
|         class Person(Document): | ||||
| @@ -116,10 +102,10 @@ class TestReferenceField(MongoDBTestCase): | ||||
|  | ||||
|         col = Person._get_collection() | ||||
|         data = col.find_one({"name": "Ross"}) | ||||
|         self.assertEqual(data["parent"], p1.pk) | ||||
|         assert data["parent"] == p1.pk | ||||
|  | ||||
|         p = Person.objects.get(name="Ross") | ||||
|         self.assertEqual(p.parent, p1) | ||||
|         assert p.parent == p1 | ||||
|  | ||||
|     def test_undefined_reference(self): | ||||
|         """Ensure that ReferenceFields may reference undefined Documents. | ||||
| @@ -144,14 +130,14 @@ class TestReferenceField(MongoDBTestCase): | ||||
|         me.save() | ||||
|  | ||||
|         obj = Product.objects(company=ten_gen).first() | ||||
|         self.assertEqual(obj, mongodb) | ||||
|         self.assertEqual(obj.company, ten_gen) | ||||
|         assert obj == mongodb | ||||
|         assert obj.company == ten_gen | ||||
|  | ||||
|         obj = Product.objects(company=None).first() | ||||
|         self.assertEqual(obj, me) | ||||
|         assert obj == me | ||||
|  | ||||
|         obj = Product.objects.get(company=None) | ||||
|         self.assertEqual(obj, me) | ||||
|         assert obj == me | ||||
|  | ||||
|     def test_reference_query_conversion(self): | ||||
|         """Ensure that ReferenceFields can be queried using objects and values | ||||
| @@ -180,10 +166,10 @@ class TestReferenceField(MongoDBTestCase): | ||||
|         post2.save() | ||||
|  | ||||
|         post = BlogPost.objects(author=m1).first() | ||||
|         self.assertEqual(post.id, post1.id) | ||||
|         assert post.id == post1.id | ||||
|  | ||||
|         post = BlogPost.objects(author=m2).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|  | ||||
|     def test_reference_query_conversion_dbref(self): | ||||
|         """Ensure that ReferenceFields can be queried using objects and values | ||||
| @@ -212,7 +198,7 @@ class TestReferenceField(MongoDBTestCase): | ||||
|         post2.save() | ||||
|  | ||||
|         post = BlogPost.objects(author=m1).first() | ||||
|         self.assertEqual(post.id, post1.id) | ||||
|         assert post.id == post1.id | ||||
|  | ||||
|         post = BlogPost.objects(author=m2).first() | ||||
|         self.assertEqual(post.id, post2.id) | ||||
|         assert post.id == post2.id | ||||
|   | ||||
| @@ -18,17 +18,17 @@ class TestSequenceField(MongoDBTestCase): | ||||
|             Person(name="Person %s" % x).save() | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         ids = [i.id for i in Person.objects] | ||||
|         self.assertEqual(ids, range(1, 11)) | ||||
|         assert ids == range(1, 11) | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         Person.id.set_next_value(1000) | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 1000) | ||||
|         assert c["next"] == 1000 | ||||
|  | ||||
|     def test_sequence_field_get_next_value(self): | ||||
|         class Person(Document): | ||||
| @@ -41,10 +41,10 @@ class TestSequenceField(MongoDBTestCase): | ||||
|         for x in range(10): | ||||
|             Person(name="Person %s" % x).save() | ||||
|  | ||||
|         self.assertEqual(Person.id.get_next_value(), 11) | ||||
|         assert Person.id.get_next_value() == 11 | ||||
|         self.db["mongoengine.counters"].drop() | ||||
|  | ||||
|         self.assertEqual(Person.id.get_next_value(), 1) | ||||
|         assert Person.id.get_next_value() == 1 | ||||
|  | ||||
|         class Person(Document): | ||||
|             id = SequenceField(primary_key=True, value_decorator=str) | ||||
| @@ -56,10 +56,10 @@ class TestSequenceField(MongoDBTestCase): | ||||
|         for x in range(10): | ||||
|             Person(name="Person %s" % x).save() | ||||
|  | ||||
|         self.assertEqual(Person.id.get_next_value(), "11") | ||||
|         assert Person.id.get_next_value() == "11" | ||||
|         self.db["mongoengine.counters"].drop() | ||||
|  | ||||
|         self.assertEqual(Person.id.get_next_value(), "1") | ||||
|         assert Person.id.get_next_value() == "1" | ||||
|  | ||||
|     def test_sequence_field_sequence_name(self): | ||||
|         class Person(Document): | ||||
| @@ -73,17 +73,17 @@ class TestSequenceField(MongoDBTestCase): | ||||
|             Person(name="Person %s" % x).save() | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "jelly.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         ids = [i.id for i in Person.objects] | ||||
|         self.assertEqual(ids, range(1, 11)) | ||||
|         assert ids == range(1, 11) | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "jelly.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         Person.id.set_next_value(1000) | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "jelly.id"}) | ||||
|         self.assertEqual(c["next"], 1000) | ||||
|         assert c["next"] == 1000 | ||||
|  | ||||
|     def test_multiple_sequence_fields(self): | ||||
|         class Person(Document): | ||||
| @@ -98,24 +98,24 @@ class TestSequenceField(MongoDBTestCase): | ||||
|             Person(name="Person %s" % x).save() | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         ids = [i.id for i in Person.objects] | ||||
|         self.assertEqual(ids, range(1, 11)) | ||||
|         assert ids == range(1, 11) | ||||
|  | ||||
|         counters = [i.counter for i in Person.objects] | ||||
|         self.assertEqual(counters, range(1, 11)) | ||||
|         assert counters == range(1, 11) | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         Person.id.set_next_value(1000) | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 1000) | ||||
|         assert c["next"] == 1000 | ||||
|  | ||||
|         Person.counter.set_next_value(999) | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.counter"}) | ||||
|         self.assertEqual(c["next"], 999) | ||||
|         assert c["next"] == 999 | ||||
|  | ||||
|     def test_sequence_fields_reload(self): | ||||
|         class Animal(Document): | ||||
| @@ -127,20 +127,20 @@ class TestSequenceField(MongoDBTestCase): | ||||
|  | ||||
|         a = Animal(name="Boi").save() | ||||
|  | ||||
|         self.assertEqual(a.counter, 1) | ||||
|         assert a.counter == 1 | ||||
|         a.reload() | ||||
|         self.assertEqual(a.counter, 1) | ||||
|         assert a.counter == 1 | ||||
|  | ||||
|         a.counter = None | ||||
|         self.assertEqual(a.counter, 2) | ||||
|         assert a.counter == 2 | ||||
|         a.save() | ||||
|  | ||||
|         self.assertEqual(a.counter, 2) | ||||
|         assert a.counter == 2 | ||||
|  | ||||
|         a = Animal.objects.first() | ||||
|         self.assertEqual(a.counter, 2) | ||||
|         assert a.counter == 2 | ||||
|         a.reload() | ||||
|         self.assertEqual(a.counter, 2) | ||||
|         assert a.counter == 2 | ||||
|  | ||||
|     def test_multiple_sequence_fields_on_docs(self): | ||||
|         class Animal(Document): | ||||
| @@ -160,22 +160,22 @@ class TestSequenceField(MongoDBTestCase): | ||||
|             Person(name="Person %s" % x).save() | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "animal.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         ids = [i.id for i in Person.objects] | ||||
|         self.assertEqual(ids, range(1, 11)) | ||||
|         assert ids == range(1, 11) | ||||
|  | ||||
|         id = [i.id for i in Animal.objects] | ||||
|         self.assertEqual(id, range(1, 11)) | ||||
|         assert id == range(1, 11) | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "animal.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|     def test_sequence_field_value_decorator(self): | ||||
|         class Person(Document): | ||||
| @@ -190,13 +190,13 @@ class TestSequenceField(MongoDBTestCase): | ||||
|             p.save() | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|         ids = [i.id for i in Person.objects] | ||||
|         self.assertEqual(ids, map(str, range(1, 11))) | ||||
|         assert ids == map(str, range(1, 11)) | ||||
|  | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) | ||||
|         self.assertEqual(c["next"], 10) | ||||
|         assert c["next"] == 10 | ||||
|  | ||||
|     def test_embedded_sequence_field(self): | ||||
|         class Comment(EmbeddedDocument): | ||||
| @@ -218,10 +218,10 @@ class TestSequenceField(MongoDBTestCase): | ||||
|             ], | ||||
|         ).save() | ||||
|         c = self.db["mongoengine.counters"].find_one({"_id": "comment.id"}) | ||||
|         self.assertEqual(c["next"], 2) | ||||
|         assert c["next"] == 2 | ||||
|         post = Post.objects.first() | ||||
|         self.assertEqual(1, post.comments[0].id) | ||||
|         self.assertEqual(2, post.comments[1].id) | ||||
|         assert 1 == post.comments[0].id | ||||
|         assert 2 == post.comments[1].id | ||||
|  | ||||
|     def test_inherited_sequencefield(self): | ||||
|         class Base(Document): | ||||
| @@ -241,16 +241,14 @@ class TestSequenceField(MongoDBTestCase): | ||||
|         foo = Foo(name="Foo") | ||||
|         foo.save() | ||||
|  | ||||
|         self.assertTrue( | ||||
|             "base.counter" in self.db["mongoengine.counters"].find().distinct("_id") | ||||
|         ) | ||||
|         self.assertFalse( | ||||
|         assert "base.counter" in self.db["mongoengine.counters"].find().distinct("_id") | ||||
|         assert not ( | ||||
|             ("foo.counter" or "bar.counter") | ||||
|             in self.db["mongoengine.counters"].find().distinct("_id") | ||||
|         ) | ||||
|         self.assertNotEqual(foo.counter, bar.counter) | ||||
|         self.assertEqual(foo._fields["counter"].owner_document, Base) | ||||
|         self.assertEqual(bar._fields["counter"].owner_document, Base) | ||||
|         assert foo.counter != bar.counter | ||||
|         assert foo._fields["counter"].owner_document == Base | ||||
|         assert bar._fields["counter"].owner_document == Base | ||||
|  | ||||
|     def test_no_inherited_sequencefield(self): | ||||
|         class Base(Document): | ||||
| @@ -269,13 +267,12 @@ class TestSequenceField(MongoDBTestCase): | ||||
|         foo = Foo(name="Foo") | ||||
|         foo.save() | ||||
|  | ||||
|         self.assertFalse( | ||||
|         assert not ( | ||||
|             "base.counter" in self.db["mongoengine.counters"].find().distinct("_id") | ||||
|         ) | ||||
|         self.assertTrue( | ||||
|             ("foo.counter" and "bar.counter") | ||||
|             in self.db["mongoengine.counters"].find().distinct("_id") | ||||
|         ) | ||||
|         self.assertEqual(foo.counter, bar.counter) | ||||
|         self.assertEqual(foo._fields["counter"].owner_document, Foo) | ||||
|         self.assertEqual(bar._fields["counter"].owner_document, Bar) | ||||
|         assert ("foo.counter" and "bar.counter") in self.db[ | ||||
|             "mongoengine.counters" | ||||
|         ].find().distinct("_id") | ||||
|         assert foo.counter == bar.counter | ||||
|         assert foo._fields["counter"].owner_document == Foo | ||||
|         assert bar._fields["counter"].owner_document == Bar | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
|  | ||||
| from tests.utils import MongoDBTestCase | ||||
| @@ -13,7 +15,8 @@ class TestURLField(MongoDBTestCase): | ||||
|  | ||||
|         link = Link() | ||||
|         link.url = "google" | ||||
|         self.assertRaises(ValidationError, link.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             link.validate() | ||||
|  | ||||
|         link.url = "http://www.google.com:8080" | ||||
|         link.validate() | ||||
| @@ -29,11 +32,11 @@ class TestURLField(MongoDBTestCase): | ||||
|  | ||||
|         # TODO fix URL validation - this *IS* a valid URL | ||||
|         # For now we just want to make sure that the error message is correct | ||||
|         with self.assertRaises(ValidationError) as ctx_err: | ||||
|         with pytest.raises(ValidationError) as exc_info: | ||||
|             link.validate() | ||||
|         self.assertEqual( | ||||
|             unicode(ctx_err.exception), | ||||
|             u"ValidationError (Link:None) (Invalid URL: http://\u043f\u0440\u0438\u0432\u0435\u0442.com: ['url'])", | ||||
|         assert ( | ||||
|             unicode(exc_info.value) | ||||
|             == u"ValidationError (Link:None) (Invalid URL: http://\u043f\u0440\u0438\u0432\u0435\u0442.com: ['url'])" | ||||
|         ) | ||||
|  | ||||
|     def test_url_scheme_validation(self): | ||||
| @@ -48,7 +51,8 @@ class TestURLField(MongoDBTestCase): | ||||
|  | ||||
|         link = Link() | ||||
|         link.url = "ws://google.com" | ||||
|         self.assertRaises(ValidationError, link.validate) | ||||
|         with pytest.raises(ValidationError): | ||||
|             link.validate() | ||||
|  | ||||
|         scheme_link = SchemeLink() | ||||
|         scheme_link.url = "ws://google.com" | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import uuid | ||||
|  | ||||
| from mongoengine import * | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase, get_as_pymongo | ||||
|  | ||||
|  | ||||
| @@ -14,9 +15,7 @@ class TestUUIDField(MongoDBTestCase): | ||||
|     def test_storage(self): | ||||
|         uid = uuid.uuid4() | ||||
|         person = Person(api_key=uid).save() | ||||
|         self.assertEqual( | ||||
|             get_as_pymongo(person), {"_id": person.id, "api_key": str(uid)} | ||||
|         ) | ||||
|         assert get_as_pymongo(person) == {"_id": person.id, "api_key": str(uid)} | ||||
|  | ||||
|     def test_field_string(self): | ||||
|         """Test UUID fields storing as String | ||||
| @@ -25,8 +24,8 @@ class TestUUIDField(MongoDBTestCase): | ||||
|  | ||||
|         uu = uuid.uuid4() | ||||
|         Person(api_key=uu).save() | ||||
|         self.assertEqual(1, Person.objects(api_key=uu).count()) | ||||
|         self.assertEqual(uu, Person.objects.first().api_key) | ||||
|         assert 1 == Person.objects(api_key=uu).count() | ||||
|         assert uu == Person.objects.first().api_key | ||||
|  | ||||
|         person = Person() | ||||
|         valid = (uuid.uuid4(), uuid.uuid1()) | ||||
| @@ -40,7 +39,8 @@ class TestUUIDField(MongoDBTestCase): | ||||
|         ) | ||||
|         for api_key in invalid: | ||||
|             person.api_key = api_key | ||||
|             self.assertRaises(ValidationError, person.validate) | ||||
|             with pytest.raises(ValidationError): | ||||
|                 person.validate() | ||||
|  | ||||
|     def test_field_binary(self): | ||||
|         """Test UUID fields storing as Binary object.""" | ||||
| @@ -48,8 +48,8 @@ class TestUUIDField(MongoDBTestCase): | ||||
|  | ||||
|         uu = uuid.uuid4() | ||||
|         Person(api_key=uu).save() | ||||
|         self.assertEqual(1, Person.objects(api_key=uu).count()) | ||||
|         self.assertEqual(uu, Person.objects.first().api_key) | ||||
|         assert 1 == Person.objects(api_key=uu).count() | ||||
|         assert uu == Person.objects.first().api_key | ||||
|  | ||||
|         person = Person() | ||||
|         valid = (uuid.uuid4(), uuid.uuid1()) | ||||
| @@ -63,4 +63,5 @@ class TestUUIDField(MongoDBTestCase): | ||||
|         ) | ||||
|         for api_key in invalid: | ||||
|             person.api_key = api_key | ||||
|             self.assertRaises(ValidationError, person.validate) | ||||
|             with pytest.raises(ValidationError): | ||||
|                 person.validate() | ||||
|   | ||||
| @@ -42,11 +42,11 @@ class PickleSignalsTest(Document): | ||||
|  | ||||
|     @classmethod | ||||
|     def post_save(self, sender, document, created, **kwargs): | ||||
|         pickled = pickle.dumps(document) | ||||
|         pickle.dumps(document) | ||||
|  | ||||
|     @classmethod | ||||
|     def post_delete(self, sender, document, **kwargs): | ||||
|         pickled = pickle.dumps(document) | ||||
|         pickle.dumps(document) | ||||
|  | ||||
|  | ||||
| signals.post_save.connect(PickleSignalsTest.post_save, sender=PickleSignalsTest) | ||||
|   | ||||
| @@ -1,67 +1,69 @@ | ||||
| import unittest | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.queryset import QueryFieldList | ||||
|  | ||||
|  | ||||
| class TestQueryFieldList(unittest.TestCase): | ||||
| class TestQueryFieldList: | ||||
|     def test_empty(self): | ||||
|         q = QueryFieldList() | ||||
|         self.assertFalse(q) | ||||
|         assert not q | ||||
|  | ||||
|         q = QueryFieldList(always_include=["_cls"]) | ||||
|         self.assertFalse(q) | ||||
|         assert not q | ||||
|  | ||||
|     def test_include_include(self): | ||||
|         q = QueryFieldList() | ||||
|         q += QueryFieldList( | ||||
|             fields=["a", "b"], value=QueryFieldList.ONLY, _only_called=True | ||||
|         ) | ||||
|         self.assertEqual(q.as_dict(), {"a": 1, "b": 1}) | ||||
|         assert q.as_dict() == {"a": 1, "b": 1} | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) | ||||
|         self.assertEqual(q.as_dict(), {"a": 1, "b": 1, "c": 1}) | ||||
|         assert q.as_dict() == {"a": 1, "b": 1, "c": 1} | ||||
|  | ||||
|     def test_include_exclude(self): | ||||
|         q = QueryFieldList() | ||||
|         q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.ONLY) | ||||
|         self.assertEqual(q.as_dict(), {"a": 1, "b": 1}) | ||||
|         assert q.as_dict() == {"a": 1, "b": 1} | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.EXCLUDE) | ||||
|         self.assertEqual(q.as_dict(), {"a": 1}) | ||||
|         assert q.as_dict() == {"a": 1} | ||||
|  | ||||
|     def test_exclude_exclude(self): | ||||
|         q = QueryFieldList() | ||||
|         q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.EXCLUDE) | ||||
|         self.assertEqual(q.as_dict(), {"a": 0, "b": 0}) | ||||
|         assert q.as_dict() == {"a": 0, "b": 0} | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.EXCLUDE) | ||||
|         self.assertEqual(q.as_dict(), {"a": 0, "b": 0, "c": 0}) | ||||
|         assert q.as_dict() == {"a": 0, "b": 0, "c": 0} | ||||
|  | ||||
|     def test_exclude_include(self): | ||||
|         q = QueryFieldList() | ||||
|         q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.EXCLUDE) | ||||
|         self.assertEqual(q.as_dict(), {"a": 0, "b": 0}) | ||||
|         assert q.as_dict() == {"a": 0, "b": 0} | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) | ||||
|         self.assertEqual(q.as_dict(), {"c": 1}) | ||||
|         assert q.as_dict() == {"c": 1} | ||||
|  | ||||
|     def test_always_include(self): | ||||
|         q = QueryFieldList(always_include=["x", "y"]) | ||||
|         q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE) | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) | ||||
|         self.assertEqual(q.as_dict(), {"x": 1, "y": 1, "c": 1}) | ||||
|         assert q.as_dict() == {"x": 1, "y": 1, "c": 1} | ||||
|  | ||||
|     def test_reset(self): | ||||
|         q = QueryFieldList(always_include=["x", "y"]) | ||||
|         q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE) | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) | ||||
|         self.assertEqual(q.as_dict(), {"x": 1, "y": 1, "c": 1}) | ||||
|         assert q.as_dict() == {"x": 1, "y": 1, "c": 1} | ||||
|         q.reset() | ||||
|         self.assertFalse(q) | ||||
|         assert not q | ||||
|         q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) | ||||
|         self.assertEqual(q.as_dict(), {"x": 1, "y": 1, "b": 1, "c": 1}) | ||||
|         assert q.as_dict() == {"x": 1, "y": 1, "b": 1, "c": 1} | ||||
|  | ||||
|     def test_using_a_slice(self): | ||||
|         q = QueryFieldList() | ||||
|         q += QueryFieldList(fields=["a"], value={"$slice": 5}) | ||||
|         self.assertEqual(q.as_dict(), {"a": {"$slice": 5}}) | ||||
|         assert q.as_dict() == {"a": {"$slice": 5}} | ||||
|  | ||||
|  | ||||
| class TestOnlyExcludeAll(unittest.TestCase): | ||||
| @@ -90,25 +92,23 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         only = ["b", "c"] | ||||
|  | ||||
|         qs = MyDoc.objects.fields(**{i: 1 for i in include}) | ||||
|         self.assertEqual( | ||||
|             qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1, "d": 1, "e": 1} | ||||
|         ) | ||||
|         assert qs._loaded_fields.as_dict() == {"a": 1, "b": 1, "c": 1, "d": 1, "e": 1} | ||||
|         qs = qs.only(*only) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"b": 1, "c": 1} | ||||
|         qs = qs.exclude(*exclude) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"b": 1, "c": 1} | ||||
|  | ||||
|         qs = MyDoc.objects.fields(**{i: 1 for i in include}) | ||||
|         qs = qs.exclude(*exclude) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"a": 1, "b": 1, "c": 1} | ||||
|         qs = qs.only(*only) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"b": 1, "c": 1} | ||||
|  | ||||
|         qs = MyDoc.objects.exclude(*exclude) | ||||
|         qs = qs.fields(**{i: 1 for i in include}) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"a": 1, "b": 1, "c": 1} | ||||
|         qs = qs.only(*only) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"b": 1, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"b": 1, "c": 1} | ||||
|  | ||||
|     def test_slicing(self): | ||||
|         class MyDoc(Document): | ||||
| @@ -127,15 +127,16 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         qs = qs.exclude(*exclude) | ||||
|         qs = qs.only(*only) | ||||
|         qs = qs.fields(slice__b=5) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"b": {"$slice": 5}, "c": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"b": {"$slice": 5}, "c": 1} | ||||
|  | ||||
|         qs = qs.fields(slice__c=[5, 1]) | ||||
|         self.assertEqual( | ||||
|             qs._loaded_fields.as_dict(), {"b": {"$slice": 5}, "c": {"$slice": [5, 1]}} | ||||
|         ) | ||||
|         assert qs._loaded_fields.as_dict() == { | ||||
|             "b": {"$slice": 5}, | ||||
|             "c": {"$slice": [5, 1]}, | ||||
|         } | ||||
|  | ||||
|         qs = qs.exclude("c") | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"b": {"$slice": 5}}) | ||||
|         assert qs._loaded_fields.as_dict() == {"b": {"$slice": 5}} | ||||
|  | ||||
|     def test_mix_slice_with_other_fields(self): | ||||
|         class MyDoc(Document): | ||||
| @@ -144,7 +145,7 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|             c = ListField() | ||||
|  | ||||
|         qs = MyDoc.objects.fields(a=1, b=0, slice__c=2) | ||||
|         self.assertEqual(qs._loaded_fields.as_dict(), {"c": {"$slice": 2}, "a": 1}) | ||||
|         assert qs._loaded_fields.as_dict() == {"c": {"$slice": 2}, "a": 1} | ||||
|  | ||||
|     def test_only(self): | ||||
|         """Ensure that QuerySet.only only returns the requested fields. | ||||
| @@ -153,20 +154,20 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         person.save() | ||||
|  | ||||
|         obj = self.Person.objects.only("name").get() | ||||
|         self.assertEqual(obj.name, person.name) | ||||
|         self.assertEqual(obj.age, None) | ||||
|         assert obj.name == person.name | ||||
|         assert obj.age is None | ||||
|  | ||||
|         obj = self.Person.objects.only("age").get() | ||||
|         self.assertEqual(obj.name, None) | ||||
|         self.assertEqual(obj.age, person.age) | ||||
|         assert obj.name is None | ||||
|         assert obj.age == person.age | ||||
|  | ||||
|         obj = self.Person.objects.only("name", "age").get() | ||||
|         self.assertEqual(obj.name, person.name) | ||||
|         self.assertEqual(obj.age, person.age) | ||||
|         assert obj.name == person.name | ||||
|         assert obj.age == person.age | ||||
|  | ||||
|         obj = self.Person.objects.only(*("id", "name")).get() | ||||
|         self.assertEqual(obj.name, person.name) | ||||
|         self.assertEqual(obj.age, None) | ||||
|         assert obj.name == person.name | ||||
|         assert obj.age is None | ||||
|  | ||||
|         # Check polymorphism still works | ||||
|         class Employee(self.Person): | ||||
| @@ -176,12 +177,12 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         employee.save() | ||||
|  | ||||
|         obj = self.Person.objects(id=employee.id).only("age").get() | ||||
|         self.assertIsInstance(obj, Employee) | ||||
|         assert isinstance(obj, Employee) | ||||
|  | ||||
|         # Check field names are looked up properly | ||||
|         obj = Employee.objects(id=employee.id).only("salary").get() | ||||
|         self.assertEqual(obj.salary, employee.salary) | ||||
|         self.assertEqual(obj.name, None) | ||||
|         assert obj.salary == employee.salary | ||||
|         assert obj.name is None | ||||
|  | ||||
|     def test_only_with_subfields(self): | ||||
|         class User(EmbeddedDocument): | ||||
| @@ -215,29 +216,29 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         post.save() | ||||
|  | ||||
|         obj = BlogPost.objects.only("author.name").get() | ||||
|         self.assertEqual(obj.content, None) | ||||
|         self.assertEqual(obj.author.email, None) | ||||
|         self.assertEqual(obj.author.name, "Test User") | ||||
|         self.assertEqual(obj.comments, []) | ||||
|         assert obj.content is None | ||||
|         assert obj.author.email is None | ||||
|         assert obj.author.name == "Test User" | ||||
|         assert obj.comments == [] | ||||
|  | ||||
|         obj = BlogPost.objects.only("various.test_dynamic.some").get() | ||||
|         self.assertEqual(obj.various["test_dynamic"].some, True) | ||||
|         assert obj.various["test_dynamic"].some is True | ||||
|  | ||||
|         obj = BlogPost.objects.only("content", "comments.title").get() | ||||
|         self.assertEqual(obj.content, "Had a good coffee today...") | ||||
|         self.assertEqual(obj.author, None) | ||||
|         self.assertEqual(obj.comments[0].title, "I aggree") | ||||
|         self.assertEqual(obj.comments[1].title, "Coffee") | ||||
|         self.assertEqual(obj.comments[0].text, None) | ||||
|         self.assertEqual(obj.comments[1].text, None) | ||||
|         assert obj.content == "Had a good coffee today..." | ||||
|         assert obj.author is None | ||||
|         assert obj.comments[0].title == "I aggree" | ||||
|         assert obj.comments[1].title == "Coffee" | ||||
|         assert obj.comments[0].text is None | ||||
|         assert obj.comments[1].text is None | ||||
|  | ||||
|         obj = BlogPost.objects.only("comments").get() | ||||
|         self.assertEqual(obj.content, None) | ||||
|         self.assertEqual(obj.author, None) | ||||
|         self.assertEqual(obj.comments[0].title, "I aggree") | ||||
|         self.assertEqual(obj.comments[1].title, "Coffee") | ||||
|         self.assertEqual(obj.comments[0].text, "Great post!") | ||||
|         self.assertEqual(obj.comments[1].text, "I hate coffee") | ||||
|         assert obj.content is None | ||||
|         assert obj.author is None | ||||
|         assert obj.comments[0].title == "I aggree" | ||||
|         assert obj.comments[1].title == "Coffee" | ||||
|         assert obj.comments[0].text == "Great post!" | ||||
|         assert obj.comments[1].text == "I hate coffee" | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -266,10 +267,10 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         post.save() | ||||
|  | ||||
|         obj = BlogPost.objects.exclude("author", "comments.text").get() | ||||
|         self.assertEqual(obj.author, None) | ||||
|         self.assertEqual(obj.content, "Had a good coffee today...") | ||||
|         self.assertEqual(obj.comments[0].title, "I aggree") | ||||
|         self.assertEqual(obj.comments[0].text, None) | ||||
|         assert obj.author is None | ||||
|         assert obj.content == "Had a good coffee today..." | ||||
|         assert obj.comments[0].title == "I aggree" | ||||
|         assert obj.comments[0].text is None | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -301,18 +302,18 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         email.save() | ||||
|  | ||||
|         obj = Email.objects.exclude("content_type").exclude("body").get() | ||||
|         self.assertEqual(obj.sender, "me") | ||||
|         self.assertEqual(obj.to, "you") | ||||
|         self.assertEqual(obj.subject, "From Russia with Love") | ||||
|         self.assertEqual(obj.body, None) | ||||
|         self.assertEqual(obj.content_type, None) | ||||
|         assert obj.sender == "me" | ||||
|         assert obj.to == "you" | ||||
|         assert obj.subject == "From Russia with Love" | ||||
|         assert obj.body is None | ||||
|         assert obj.content_type is None | ||||
|  | ||||
|         obj = Email.objects.only("sender", "to").exclude("body", "sender").get() | ||||
|         self.assertEqual(obj.sender, None) | ||||
|         self.assertEqual(obj.to, "you") | ||||
|         self.assertEqual(obj.subject, None) | ||||
|         self.assertEqual(obj.body, None) | ||||
|         self.assertEqual(obj.content_type, None) | ||||
|         assert obj.sender is None | ||||
|         assert obj.to == "you" | ||||
|         assert obj.subject is None | ||||
|         assert obj.body is None | ||||
|         assert obj.content_type is None | ||||
|  | ||||
|         obj = ( | ||||
|             Email.objects.exclude("attachments.content") | ||||
| @@ -320,13 +321,13 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|             .only("to", "attachments.name") | ||||
|             .get() | ||||
|         ) | ||||
|         self.assertEqual(obj.attachments[0].name, "file1.doc") | ||||
|         self.assertEqual(obj.attachments[0].content, None) | ||||
|         self.assertEqual(obj.sender, None) | ||||
|         self.assertEqual(obj.to, "you") | ||||
|         self.assertEqual(obj.subject, None) | ||||
|         self.assertEqual(obj.body, None) | ||||
|         self.assertEqual(obj.content_type, None) | ||||
|         assert obj.attachments[0].name == "file1.doc" | ||||
|         assert obj.attachments[0].content is None | ||||
|         assert obj.sender is None | ||||
|         assert obj.to == "you" | ||||
|         assert obj.subject is None | ||||
|         assert obj.body is None | ||||
|         assert obj.content_type is None | ||||
|  | ||||
|         Email.drop_collection() | ||||
|  | ||||
| @@ -355,11 +356,11 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|             .all_fields() | ||||
|             .get() | ||||
|         ) | ||||
|         self.assertEqual(obj.sender, "me") | ||||
|         self.assertEqual(obj.to, "you") | ||||
|         self.assertEqual(obj.subject, "From Russia with Love") | ||||
|         self.assertEqual(obj.body, "Hello!") | ||||
|         self.assertEqual(obj.content_type, "text/plain") | ||||
|         assert obj.sender == "me" | ||||
|         assert obj.to == "you" | ||||
|         assert obj.subject == "From Russia with Love" | ||||
|         assert obj.body == "Hello!" | ||||
|         assert obj.content_type == "text/plain" | ||||
|  | ||||
|         Email.drop_collection() | ||||
|  | ||||
| @@ -377,27 +378,27 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|  | ||||
|         # first three | ||||
|         numbers = Numbers.objects.fields(slice__n=3).get() | ||||
|         self.assertEqual(numbers.n, [0, 1, 2]) | ||||
|         assert numbers.n == [0, 1, 2] | ||||
|  | ||||
|         # last three | ||||
|         numbers = Numbers.objects.fields(slice__n=-3).get() | ||||
|         self.assertEqual(numbers.n, [-3, -2, -1]) | ||||
|         assert numbers.n == [-3, -2, -1] | ||||
|  | ||||
|         # skip 2, limit 3 | ||||
|         numbers = Numbers.objects.fields(slice__n=[2, 3]).get() | ||||
|         self.assertEqual(numbers.n, [2, 3, 4]) | ||||
|         assert numbers.n == [2, 3, 4] | ||||
|  | ||||
|         # skip to fifth from last, limit 4 | ||||
|         numbers = Numbers.objects.fields(slice__n=[-5, 4]).get() | ||||
|         self.assertEqual(numbers.n, [-5, -4, -3, -2]) | ||||
|         assert numbers.n == [-5, -4, -3, -2] | ||||
|  | ||||
|         # skip to fifth from last, limit 10 | ||||
|         numbers = Numbers.objects.fields(slice__n=[-5, 10]).get() | ||||
|         self.assertEqual(numbers.n, [-5, -4, -3, -2, -1]) | ||||
|         assert numbers.n == [-5, -4, -3, -2, -1] | ||||
|  | ||||
|         # skip to fifth from last, limit 10 dict method | ||||
|         numbers = Numbers.objects.fields(n={"$slice": [-5, 10]}).get() | ||||
|         self.assertEqual(numbers.n, [-5, -4, -3, -2, -1]) | ||||
|         assert numbers.n == [-5, -4, -3, -2, -1] | ||||
|  | ||||
|     def test_slicing_nested_fields(self): | ||||
|         """Ensure that query slicing an embedded array works. | ||||
| @@ -417,27 +418,27 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|  | ||||
|         # first three | ||||
|         numbers = Numbers.objects.fields(slice__embedded__n=3).get() | ||||
|         self.assertEqual(numbers.embedded.n, [0, 1, 2]) | ||||
|         assert numbers.embedded.n == [0, 1, 2] | ||||
|  | ||||
|         # last three | ||||
|         numbers = Numbers.objects.fields(slice__embedded__n=-3).get() | ||||
|         self.assertEqual(numbers.embedded.n, [-3, -2, -1]) | ||||
|         assert numbers.embedded.n == [-3, -2, -1] | ||||
|  | ||||
|         # skip 2, limit 3 | ||||
|         numbers = Numbers.objects.fields(slice__embedded__n=[2, 3]).get() | ||||
|         self.assertEqual(numbers.embedded.n, [2, 3, 4]) | ||||
|         assert numbers.embedded.n == [2, 3, 4] | ||||
|  | ||||
|         # skip to fifth from last, limit 4 | ||||
|         numbers = Numbers.objects.fields(slice__embedded__n=[-5, 4]).get() | ||||
|         self.assertEqual(numbers.embedded.n, [-5, -4, -3, -2]) | ||||
|         assert numbers.embedded.n == [-5, -4, -3, -2] | ||||
|  | ||||
|         # skip to fifth from last, limit 10 | ||||
|         numbers = Numbers.objects.fields(slice__embedded__n=[-5, 10]).get() | ||||
|         self.assertEqual(numbers.embedded.n, [-5, -4, -3, -2, -1]) | ||||
|         assert numbers.embedded.n == [-5, -4, -3, -2, -1] | ||||
|  | ||||
|         # skip to fifth from last, limit 10 dict method | ||||
|         numbers = Numbers.objects.fields(embedded__n={"$slice": [-5, 10]}).get() | ||||
|         self.assertEqual(numbers.embedded.n, [-5, -4, -3, -2, -1]) | ||||
|         assert numbers.embedded.n == [-5, -4, -3, -2, -1] | ||||
|  | ||||
|     def test_exclude_from_subclasses_docs(self): | ||||
|         class Base(Document): | ||||
| @@ -456,9 +457,10 @@ class TestOnlyExcludeAll(unittest.TestCase): | ||||
|         User(username="mongodb", password="secret").save() | ||||
|  | ||||
|         user = Base.objects().exclude("password", "wibble").first() | ||||
|         self.assertEqual(user.password, None) | ||||
|         assert user.password is None | ||||
|  | ||||
|         self.assertRaises(LookUpError, Base.objects.exclude, "made_up") | ||||
|         with pytest.raises(LookUpError): | ||||
|             Base.objects.exclude("made_up") | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -48,14 +48,14 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # note that "near" will show the san francisco event, too, | ||||
|         # although it sorts to last. | ||||
|         events = self.Event.objects(location__near=[-87.67892, 41.9120459]) | ||||
|         self.assertEqual(events.count(), 3) | ||||
|         self.assertEqual(list(events), [event1, event3, event2]) | ||||
|         assert events.count() == 3 | ||||
|         assert list(events) == [event1, event3, event2] | ||||
|  | ||||
|         # ensure ordering is respected by "near" | ||||
|         events = self.Event.objects(location__near=[-87.67892, 41.9120459]) | ||||
|         events = events.order_by("-date") | ||||
|         self.assertEqual(events.count(), 3) | ||||
|         self.assertEqual(list(events), [event3, event1, event2]) | ||||
|         assert events.count() == 3 | ||||
|         assert list(events) == [event3, event1, event2] | ||||
|  | ||||
|     def test_near_and_max_distance(self): | ||||
|         """Ensure the "max_distance" operator works alongside the "near" | ||||
| @@ -66,8 +66,8 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # find events within 10 degrees of san francisco | ||||
|         point = [-122.415579, 37.7566023] | ||||
|         events = self.Event.objects(location__near=point, location__max_distance=10) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0], event2) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0] == event2 | ||||
|  | ||||
|     def test_near_and_min_distance(self): | ||||
|         """Ensure the "min_distance" operator works alongside the "near" | ||||
| @@ -78,7 +78,7 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # find events at least 10 degrees away of san francisco | ||||
|         point = [-122.415579, 37.7566023] | ||||
|         events = self.Event.objects(location__near=point, location__min_distance=10) | ||||
|         self.assertEqual(events.count(), 2) | ||||
|         assert events.count() == 2 | ||||
|  | ||||
|     def test_within_distance(self): | ||||
|         """Make sure the "within_distance" operator works.""" | ||||
| @@ -87,29 +87,29 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # find events within 5 degrees of pitchfork office, chicago | ||||
|         point_and_distance = [[-87.67892, 41.9120459], 5] | ||||
|         events = self.Event.objects(location__within_distance=point_and_distance) | ||||
|         self.assertEqual(events.count(), 2) | ||||
|         assert events.count() == 2 | ||||
|         events = list(events) | ||||
|         self.assertNotIn(event2, events) | ||||
|         self.assertIn(event1, events) | ||||
|         self.assertIn(event3, events) | ||||
|         assert event2 not in events | ||||
|         assert event1 in events | ||||
|         assert event3 in events | ||||
|  | ||||
|         # find events within 10 degrees of san francisco | ||||
|         point_and_distance = [[-122.415579, 37.7566023], 10] | ||||
|         events = self.Event.objects(location__within_distance=point_and_distance) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0], event2) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0] == event2 | ||||
|  | ||||
|         # find events within 1 degree of greenpoint, broolyn, nyc, ny | ||||
|         point_and_distance = [[-73.9509714, 40.7237134], 1] | ||||
|         events = self.Event.objects(location__within_distance=point_and_distance) | ||||
|         self.assertEqual(events.count(), 0) | ||||
|         assert events.count() == 0 | ||||
|  | ||||
|         # ensure ordering is respected by "within_distance" | ||||
|         point_and_distance = [[-87.67892, 41.9120459], 10] | ||||
|         events = self.Event.objects(location__within_distance=point_and_distance) | ||||
|         events = events.order_by("-date") | ||||
|         self.assertEqual(events.count(), 2) | ||||
|         self.assertEqual(events[0], event3) | ||||
|         assert events.count() == 2 | ||||
|         assert events[0] == event3 | ||||
|  | ||||
|     def test_within_box(self): | ||||
|         """Ensure the "within_box" operator works.""" | ||||
| @@ -118,8 +118,8 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # check that within_box works | ||||
|         box = [(-125.0, 35.0), (-100.0, 40.0)] | ||||
|         events = self.Event.objects(location__within_box=box) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0].id, event2.id) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0].id == event2.id | ||||
|  | ||||
|     def test_within_polygon(self): | ||||
|         """Ensure the "within_polygon" operator works.""" | ||||
| @@ -133,8 +133,8 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             (-87.656164, 41.898061), | ||||
|         ] | ||||
|         events = self.Event.objects(location__within_polygon=polygon) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0].id, event1.id) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0].id == event1.id | ||||
|  | ||||
|         polygon2 = [ | ||||
|             (-1.742249, 54.033586), | ||||
| @@ -142,7 +142,7 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             (-4.40094, 53.389881), | ||||
|         ] | ||||
|         events = self.Event.objects(location__within_polygon=polygon2) | ||||
|         self.assertEqual(events.count(), 0) | ||||
|         assert events.count() == 0 | ||||
|  | ||||
|     def test_2dsphere_near(self): | ||||
|         """Make sure the "near" operator works with a PointField, which | ||||
| @@ -154,14 +154,14 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # note that "near" will show the san francisco event, too, | ||||
|         # although it sorts to last. | ||||
|         events = self.Event.objects(location__near=[-87.67892, 41.9120459]) | ||||
|         self.assertEqual(events.count(), 3) | ||||
|         self.assertEqual(list(events), [event1, event3, event2]) | ||||
|         assert events.count() == 3 | ||||
|         assert list(events) == [event1, event3, event2] | ||||
|  | ||||
|         # ensure ordering is respected by "near" | ||||
|         events = self.Event.objects(location__near=[-87.67892, 41.9120459]) | ||||
|         events = events.order_by("-date") | ||||
|         self.assertEqual(events.count(), 3) | ||||
|         self.assertEqual(list(events), [event3, event1, event2]) | ||||
|         assert events.count() == 3 | ||||
|         assert list(events) == [event3, event1, event2] | ||||
|  | ||||
|     def test_2dsphere_near_and_max_distance(self): | ||||
|         """Ensure the "max_distance" operator works alongside the "near" | ||||
| @@ -172,21 +172,21 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # find events within 10km of san francisco | ||||
|         point = [-122.415579, 37.7566023] | ||||
|         events = self.Event.objects(location__near=point, location__max_distance=10000) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0], event2) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0] == event2 | ||||
|  | ||||
|         # find events within 1km of greenpoint, broolyn, nyc, ny | ||||
|         events = self.Event.objects( | ||||
|             location__near=[-73.9509714, 40.7237134], location__max_distance=1000 | ||||
|         ) | ||||
|         self.assertEqual(events.count(), 0) | ||||
|         assert events.count() == 0 | ||||
|  | ||||
|         # ensure ordering is respected by "near" | ||||
|         events = self.Event.objects( | ||||
|             location__near=[-87.67892, 41.9120459], location__max_distance=10000 | ||||
|         ).order_by("-date") | ||||
|         self.assertEqual(events.count(), 2) | ||||
|         self.assertEqual(events[0], event3) | ||||
|         assert events.count() == 2 | ||||
|         assert events[0] == event3 | ||||
|  | ||||
|     def test_2dsphere_geo_within_box(self): | ||||
|         """Ensure the "geo_within_box" operator works with a 2dsphere | ||||
| @@ -197,8 +197,8 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # check that within_box works | ||||
|         box = [(-125.0, 35.0), (-100.0, 40.0)] | ||||
|         events = self.Event.objects(location__geo_within_box=box) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0].id, event2.id) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0].id == event2.id | ||||
|  | ||||
|     def test_2dsphere_geo_within_polygon(self): | ||||
|         """Ensure the "geo_within_polygon" operator works with a | ||||
| @@ -214,8 +214,8 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             (-87.656164, 41.898061), | ||||
|         ] | ||||
|         events = self.Event.objects(location__geo_within_polygon=polygon) | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0].id, event1.id) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0].id == event1.id | ||||
|  | ||||
|         polygon2 = [ | ||||
|             (-1.742249, 54.033586), | ||||
| @@ -223,7 +223,7 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             (-4.40094, 53.389881), | ||||
|         ] | ||||
|         events = self.Event.objects(location__geo_within_polygon=polygon2) | ||||
|         self.assertEqual(events.count(), 0) | ||||
|         assert events.count() == 0 | ||||
|  | ||||
|     def test_2dsphere_near_and_min_max_distance(self): | ||||
|         """Ensure "min_distace" and "max_distance" operators work well | ||||
| @@ -237,15 +237,15 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             location__min_distance=1000, | ||||
|             location__max_distance=10000, | ||||
|         ).order_by("-date") | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0], event3) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0] == event3 | ||||
|  | ||||
|         # ensure ordering is respected by "near" with "min_distance" | ||||
|         events = self.Event.objects( | ||||
|             location__near=[-87.67892, 41.9120459], location__min_distance=10000 | ||||
|         ).order_by("-date") | ||||
|         self.assertEqual(events.count(), 1) | ||||
|         self.assertEqual(events[0], event2) | ||||
|         assert events.count() == 1 | ||||
|         assert events[0] == event2 | ||||
|  | ||||
|     def test_2dsphere_geo_within_center(self): | ||||
|         """Make sure the "geo_within_center" operator works with a | ||||
| @@ -256,11 +256,11 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # find events within 5 degrees of pitchfork office, chicago | ||||
|         point_and_distance = [[-87.67892, 41.9120459], 2] | ||||
|         events = self.Event.objects(location__geo_within_center=point_and_distance) | ||||
|         self.assertEqual(events.count(), 2) | ||||
|         assert events.count() == 2 | ||||
|         events = list(events) | ||||
|         self.assertNotIn(event2, events) | ||||
|         self.assertIn(event1, events) | ||||
|         self.assertIn(event3, events) | ||||
|         assert event2 not in events | ||||
|         assert event1 in events | ||||
|         assert event3 in events | ||||
|  | ||||
|     def _test_embedded(self, point_field_class): | ||||
|         """Helper test method ensuring given point field class works | ||||
| @@ -290,8 +290,8 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # note that "near" will show the san francisco event, too, | ||||
|         # although it sorts to last. | ||||
|         events = Event.objects(venue__location__near=[-87.67892, 41.9120459]) | ||||
|         self.assertEqual(events.count(), 3) | ||||
|         self.assertEqual(list(events), [event1, event3, event2]) | ||||
|         assert events.count() == 3 | ||||
|         assert list(events) == [event1, event3, event2] | ||||
|  | ||||
|     def test_geo_spatial_embedded(self): | ||||
|         """Make sure GeoPointField works properly in an embedded document.""" | ||||
| @@ -319,55 +319,55 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # Finds both points because they are within 60 km of the reference | ||||
|         # point equidistant between them. | ||||
|         points = Point.objects(location__near_sphere=[-122, 37.5]) | ||||
|         self.assertEqual(points.count(), 2) | ||||
|         assert points.count() == 2 | ||||
|  | ||||
|         # Same behavior for _within_spherical_distance | ||||
|         points = Point.objects( | ||||
|             location__within_spherical_distance=[[-122, 37.5], 60 / earth_radius] | ||||
|         ) | ||||
|         self.assertEqual(points.count(), 2) | ||||
|         assert points.count() == 2 | ||||
|  | ||||
|         points = Point.objects( | ||||
|             location__near_sphere=[-122, 37.5], location__max_distance=60 / earth_radius | ||||
|         ) | ||||
|         self.assertEqual(points.count(), 2) | ||||
|         assert points.count() == 2 | ||||
|  | ||||
|         # Test query works with max_distance, being farer from one point | ||||
|         points = Point.objects( | ||||
|             location__near_sphere=[-122, 37.8], location__max_distance=60 / earth_radius | ||||
|         ) | ||||
|         close_point = points.first() | ||||
|         self.assertEqual(points.count(), 1) | ||||
|         assert points.count() == 1 | ||||
|  | ||||
|         # Test query works with min_distance, being farer from one point | ||||
|         points = Point.objects( | ||||
|             location__near_sphere=[-122, 37.8], location__min_distance=60 / earth_radius | ||||
|         ) | ||||
|         self.assertEqual(points.count(), 1) | ||||
|         assert points.count() == 1 | ||||
|         far_point = points.first() | ||||
|         self.assertNotEqual(close_point, far_point) | ||||
|         assert close_point != far_point | ||||
|  | ||||
|         # Finds both points, but orders the north point first because it's | ||||
|         # closer to the reference point to the north. | ||||
|         points = Point.objects(location__near_sphere=[-122, 38.5]) | ||||
|         self.assertEqual(points.count(), 2) | ||||
|         self.assertEqual(points[0].id, north_point.id) | ||||
|         self.assertEqual(points[1].id, south_point.id) | ||||
|         assert points.count() == 2 | ||||
|         assert points[0].id == north_point.id | ||||
|         assert points[1].id == south_point.id | ||||
|  | ||||
|         # Finds both points, but orders the south point first because it's | ||||
|         # closer to the reference point to the south. | ||||
|         points = Point.objects(location__near_sphere=[-122, 36.5]) | ||||
|         self.assertEqual(points.count(), 2) | ||||
|         self.assertEqual(points[0].id, south_point.id) | ||||
|         self.assertEqual(points[1].id, north_point.id) | ||||
|         assert points.count() == 2 | ||||
|         assert points[0].id == south_point.id | ||||
|         assert points[1].id == north_point.id | ||||
|  | ||||
|         # Finds only one point because only the first point is within 60km of | ||||
|         # the reference point to the south. | ||||
|         points = Point.objects( | ||||
|             location__within_spherical_distance=[[-122, 36.5], 60 / earth_radius] | ||||
|         ) | ||||
|         self.assertEqual(points.count(), 1) | ||||
|         self.assertEqual(points[0].id, south_point.id) | ||||
|         assert points.count() == 1 | ||||
|         assert points[0].id == south_point.id | ||||
|  | ||||
|     def test_linestring(self): | ||||
|         class Road(Document): | ||||
| @@ -381,13 +381,13 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # near | ||||
|         point = {"type": "Point", "coordinates": [40, 5]} | ||||
|         roads = Road.objects.filter(line__near=point["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__near=point).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__near={"$geometry": point}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         # Within | ||||
|         polygon = { | ||||
| @@ -395,37 +395,37 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], | ||||
|         } | ||||
|         roads = Road.objects.filter(line__geo_within=polygon["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__geo_within=polygon).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__geo_within={"$geometry": polygon}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         # Intersects | ||||
|         line = {"type": "LineString", "coordinates": [[40, 5], [40, 6]]} | ||||
|         roads = Road.objects.filter(line__geo_intersects=line["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__geo_intersects=line).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__geo_intersects={"$geometry": line}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         polygon = { | ||||
|             "type": "Polygon", | ||||
|             "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], | ||||
|         } | ||||
|         roads = Road.objects.filter(line__geo_intersects=polygon["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__geo_intersects=polygon).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(line__geo_intersects={"$geometry": polygon}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|     def test_polygon(self): | ||||
|         class Road(Document): | ||||
| @@ -439,13 +439,13 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         # near | ||||
|         point = {"type": "Point", "coordinates": [40, 5]} | ||||
|         roads = Road.objects.filter(poly__near=point["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__near=point).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__near={"$geometry": point}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         # Within | ||||
|         polygon = { | ||||
| @@ -453,37 +453,37 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|             "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], | ||||
|         } | ||||
|         roads = Road.objects.filter(poly__geo_within=polygon["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__geo_within=polygon).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__geo_within={"$geometry": polygon}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         # Intersects | ||||
|         line = {"type": "LineString", "coordinates": [[40, 5], [41, 6]]} | ||||
|         roads = Road.objects.filter(poly__geo_intersects=line["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__geo_intersects=line).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__geo_intersects={"$geometry": line}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         polygon = { | ||||
|             "type": "Polygon", | ||||
|             "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], | ||||
|         } | ||||
|         roads = Road.objects.filter(poly__geo_intersects=polygon["coordinates"]).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__geo_intersects=polygon).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|         roads = Road.objects.filter(poly__geo_intersects={"$geometry": polygon}).count() | ||||
|         self.assertEqual(1, roads) | ||||
|         assert 1 == roads | ||||
|  | ||||
|     def test_aspymongo_with_only(self): | ||||
|         """Ensure as_pymongo works with only""" | ||||
| @@ -495,13 +495,10 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|         p = Place(location=[24.946861267089844, 60.16311983618494]) | ||||
|         p.save() | ||||
|         qs = Place.objects().only("location") | ||||
|         self.assertDictEqual( | ||||
|             qs.as_pymongo()[0]["location"], | ||||
|             { | ||||
|                 u"type": u"Point", | ||||
|                 u"coordinates": [24.946861267089844, 60.16311983618494], | ||||
|             }, | ||||
|         ) | ||||
|         assert qs.as_pymongo()[0]["location"] == { | ||||
|             u"type": u"Point", | ||||
|             u"coordinates": [24.946861267089844, 60.16311983618494], | ||||
|         } | ||||
|  | ||||
|     def test_2dsphere_point_sets_correctly(self): | ||||
|         class Location(Document): | ||||
| @@ -511,11 +508,11 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|  | ||||
|         Location(loc=[1, 2]).save() | ||||
|         loc = Location.objects.as_pymongo()[0] | ||||
|         self.assertEqual(loc["loc"], {"type": "Point", "coordinates": [1, 2]}) | ||||
|         assert loc["loc"] == {"type": "Point", "coordinates": [1, 2]} | ||||
|  | ||||
|         Location.objects.update(set__loc=[2, 1]) | ||||
|         loc = Location.objects.as_pymongo()[0] | ||||
|         self.assertEqual(loc["loc"], {"type": "Point", "coordinates": [2, 1]}) | ||||
|         assert loc["loc"] == {"type": "Point", "coordinates": [2, 1]} | ||||
|  | ||||
|     def test_2dsphere_linestring_sets_correctly(self): | ||||
|         class Location(Document): | ||||
| @@ -525,15 +522,11 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|  | ||||
|         Location(line=[[1, 2], [2, 2]]).save() | ||||
|         loc = Location.objects.as_pymongo()[0] | ||||
|         self.assertEqual( | ||||
|             loc["line"], {"type": "LineString", "coordinates": [[1, 2], [2, 2]]} | ||||
|         ) | ||||
|         assert loc["line"] == {"type": "LineString", "coordinates": [[1, 2], [2, 2]]} | ||||
|  | ||||
|         Location.objects.update(set__line=[[2, 1], [1, 2]]) | ||||
|         loc = Location.objects.as_pymongo()[0] | ||||
|         self.assertEqual( | ||||
|             loc["line"], {"type": "LineString", "coordinates": [[2, 1], [1, 2]]} | ||||
|         ) | ||||
|         assert loc["line"] == {"type": "LineString", "coordinates": [[2, 1], [1, 2]]} | ||||
|  | ||||
|     def test_geojson_PolygonField(self): | ||||
|         class Location(Document): | ||||
| @@ -543,17 +536,17 @@ class TestGeoQueries(MongoDBTestCase): | ||||
|  | ||||
|         Location(poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]]).save() | ||||
|         loc = Location.objects.as_pymongo()[0] | ||||
|         self.assertEqual( | ||||
|             loc["poly"], | ||||
|             {"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]}, | ||||
|         ) | ||||
|         assert loc["poly"] == { | ||||
|             "type": "Polygon", | ||||
|             "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], | ||||
|         } | ||||
|  | ||||
|         Location.objects.update(set__poly=[[[40, 4], [40, 6], [41, 6], [40, 4]]]) | ||||
|         loc = Location.objects.as_pymongo()[0] | ||||
|         self.assertEqual( | ||||
|             loc["poly"], | ||||
|             {"type": "Polygon", "coordinates": [[[40, 4], [40, 6], [41, 6], [40, 4]]]}, | ||||
|         ) | ||||
|         assert loc["poly"] == { | ||||
|             "type": "Polygon", | ||||
|             "coordinates": [[[40, 4], [40, 6], [41, 6], [40, 4]]], | ||||
|         } | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -14,14 +14,14 @@ class TestFindAndModify(unittest.TestCase): | ||||
|         Doc.drop_collection() | ||||
|  | ||||
|     def assertDbEqual(self, docs): | ||||
|         self.assertEqual(list(Doc._collection.find().sort("id")), docs) | ||||
|         assert list(Doc._collection.find().sort("id")) == docs | ||||
|  | ||||
|     def test_modify(self): | ||||
|         Doc(id=0, value=0).save() | ||||
|         doc = Doc(id=1, value=1).save() | ||||
|  | ||||
|         old_doc = Doc.objects(id=1).modify(set__value=-1) | ||||
|         self.assertEqual(old_doc.to_json(), doc.to_json()) | ||||
|         assert old_doc.to_json() == doc.to_json() | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}]) | ||||
|  | ||||
|     def test_modify_with_new(self): | ||||
| @@ -30,18 +30,18 @@ class TestFindAndModify(unittest.TestCase): | ||||
|  | ||||
|         new_doc = Doc.objects(id=1).modify(set__value=-1, new=True) | ||||
|         doc.value = -1 | ||||
|         self.assertEqual(new_doc.to_json(), doc.to_json()) | ||||
|         assert new_doc.to_json() == doc.to_json() | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}]) | ||||
|  | ||||
|     def test_modify_not_existing(self): | ||||
|         Doc(id=0, value=0).save() | ||||
|         self.assertEqual(Doc.objects(id=1).modify(set__value=-1), None) | ||||
|         assert Doc.objects(id=1).modify(set__value=-1) is None | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}]) | ||||
|  | ||||
|     def test_modify_with_upsert(self): | ||||
|         Doc(id=0, value=0).save() | ||||
|         old_doc = Doc.objects(id=1).modify(set__value=1, upsert=True) | ||||
|         self.assertEqual(old_doc, None) | ||||
|         assert old_doc is None | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": 1}]) | ||||
|  | ||||
|     def test_modify_with_upsert_existing(self): | ||||
| @@ -49,13 +49,13 @@ class TestFindAndModify(unittest.TestCase): | ||||
|         doc = Doc(id=1, value=1).save() | ||||
|  | ||||
|         old_doc = Doc.objects(id=1).modify(set__value=-1, upsert=True) | ||||
|         self.assertEqual(old_doc.to_json(), doc.to_json()) | ||||
|         assert old_doc.to_json() == doc.to_json() | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}]) | ||||
|  | ||||
|     def test_modify_with_upsert_with_new(self): | ||||
|         Doc(id=0, value=0).save() | ||||
|         new_doc = Doc.objects(id=1).modify(upsert=True, new=True, set__value=1) | ||||
|         self.assertEqual(new_doc.to_mongo(), {"_id": 1, "value": 1}) | ||||
|         assert new_doc.to_mongo() == {"_id": 1, "value": 1} | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": 1}]) | ||||
|  | ||||
|     def test_modify_with_remove(self): | ||||
| @@ -63,12 +63,12 @@ class TestFindAndModify(unittest.TestCase): | ||||
|         doc = Doc(id=1, value=1).save() | ||||
|  | ||||
|         old_doc = Doc.objects(id=1).modify(remove=True) | ||||
|         self.assertEqual(old_doc.to_json(), doc.to_json()) | ||||
|         assert old_doc.to_json() == doc.to_json() | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}]) | ||||
|  | ||||
|     def test_find_and_modify_with_remove_not_existing(self): | ||||
|         Doc(id=0, value=0).save() | ||||
|         self.assertEqual(Doc.objects(id=1).modify(remove=True), None) | ||||
|         assert Doc.objects(id=1).modify(remove=True) is None | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}]) | ||||
|  | ||||
|     def test_modify_with_order_by(self): | ||||
| @@ -78,7 +78,7 @@ class TestFindAndModify(unittest.TestCase): | ||||
|         doc = Doc(id=3, value=0).save() | ||||
|  | ||||
|         old_doc = Doc.objects().order_by("-id").modify(set__value=-1) | ||||
|         self.assertEqual(old_doc.to_json(), doc.to_json()) | ||||
|         assert old_doc.to_json() == doc.to_json() | ||||
|         self.assertDbEqual( | ||||
|             [ | ||||
|                 {"_id": 0, "value": 3}, | ||||
| @@ -93,7 +93,7 @@ class TestFindAndModify(unittest.TestCase): | ||||
|         Doc(id=1, value=1).save() | ||||
|  | ||||
|         old_doc = Doc.objects(id=1).only("id").modify(set__value=-1) | ||||
|         self.assertEqual(old_doc.to_mongo(), {"_id": 1}) | ||||
|         assert old_doc.to_mongo() == {"_id": 1} | ||||
|         self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}]) | ||||
|  | ||||
|     def test_modify_with_push(self): | ||||
| @@ -106,23 +106,23 @@ class TestFindAndModify(unittest.TestCase): | ||||
|  | ||||
|         # Push a new tag via modify with new=False (default). | ||||
|         BlogPost(id=blog.id).modify(push__tags="code") | ||||
|         self.assertEqual(blog.tags, []) | ||||
|         assert blog.tags == [] | ||||
|         blog.reload() | ||||
|         self.assertEqual(blog.tags, ["code"]) | ||||
|         assert blog.tags == ["code"] | ||||
|  | ||||
|         # Push a new tag via modify with new=True. | ||||
|         blog = BlogPost.objects(id=blog.id).modify(push__tags="java", new=True) | ||||
|         self.assertEqual(blog.tags, ["code", "java"]) | ||||
|         assert blog.tags == ["code", "java"] | ||||
|  | ||||
|         # Push a new tag with a positional argument. | ||||
|         blog = BlogPost.objects(id=blog.id).modify(push__tags__0="python", new=True) | ||||
|         self.assertEqual(blog.tags, ["python", "code", "java"]) | ||||
|         assert blog.tags == ["python", "code", "java"] | ||||
|  | ||||
|         # Push multiple new tags with a positional argument. | ||||
|         blog = BlogPost.objects(id=blog.id).modify( | ||||
|             push__tags__1=["go", "rust"], new=True | ||||
|         ) | ||||
|         self.assertEqual(blog.tags, ["python", "go", "rust", "code", "java"]) | ||||
|         assert blog.tags == ["python", "go", "rust", "code", "java"] | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -37,13 +37,13 @@ class TestQuerysetPickable(MongoDBTestCase): | ||||
|  | ||||
|         loadedQs = self._get_loaded(qs) | ||||
|  | ||||
|         self.assertEqual(qs.count(), loadedQs.count()) | ||||
|         assert qs.count() == loadedQs.count() | ||||
|  | ||||
|         # can update loadedQs | ||||
|         loadedQs.update(age=23) | ||||
|  | ||||
|         # check | ||||
|         self.assertEqual(Person.objects.first().age, 23) | ||||
|         assert Person.objects.first().age == 23 | ||||
|  | ||||
|     def test_pickle_support_filtration(self): | ||||
|         Person.objects.create(name="Alice", age=22) | ||||
| @@ -51,9 +51,9 @@ class TestQuerysetPickable(MongoDBTestCase): | ||||
|         Person.objects.create(name="Bob", age=23) | ||||
|  | ||||
|         qs = Person.objects.filter(age__gte=22) | ||||
|         self.assertEqual(qs.count(), 2) | ||||
|         assert qs.count() == 2 | ||||
|  | ||||
|         loaded = self._get_loaded(qs) | ||||
|  | ||||
|         self.assertEqual(loaded.count(), 2) | ||||
|         self.assertEqual(loaded.filter(name="Bob").first().age, 23) | ||||
|         assert loaded.count() == 2 | ||||
|         assert loaded.filter(name="Bob").first().age == 23 | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										255
									
								
								tests/queryset/test_queryset_aggregation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								tests/queryset/test_queryset_aggregation.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| import unittest | ||||
| import warnings | ||||
|  | ||||
| from pymongo.read_preferences import ReadPreference | ||||
|  | ||||
| from mongoengine import * | ||||
| from tests.utils import MongoDBTestCase | ||||
|  | ||||
|  | ||||
| class TestQuerysetAggregate(MongoDBTestCase): | ||||
|     def test_read_preference_aggregation_framework(self): | ||||
|         class Bar(Document): | ||||
|             txt = StringField() | ||||
|  | ||||
|             meta = {"indexes": ["txt"]} | ||||
|  | ||||
|         # Aggregates with read_preference | ||||
|         pipeline = [] | ||||
|         bars = Bar.objects.read_preference( | ||||
|             ReadPreference.SECONDARY_PREFERRED | ||||
|         ).aggregate(pipeline) | ||||
|         assert ( | ||||
|             bars._CommandCursor__collection.read_preference | ||||
|             == ReadPreference.SECONDARY_PREFERRED | ||||
|         ) | ||||
|  | ||||
|     def test_queryset_aggregation_framework(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects(age__lte=22).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [ | ||||
|             {"_id": p1.pk, "name": "ISABELLA LUANNA"}, | ||||
|             {"_id": p2.pk, "name": "WILSON JUNIOR"}, | ||||
|         ] | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects(age__lte=22).order_by("-name").aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [ | ||||
|             {"_id": p2.pk, "name": "WILSON JUNIOR"}, | ||||
|             {"_id": p1.pk, "name": "ISABELLA LUANNA"}, | ||||
|         ] | ||||
|  | ||||
|         pipeline = [ | ||||
|             {"$group": {"_id": None, "total": {"$sum": 1}, "avg": {"$avg": "$age"}}} | ||||
|         ] | ||||
|         data = ( | ||||
|             Person.objects(age__gte=17, age__lte=40) | ||||
|             .order_by("-age") | ||||
|             .aggregate(pipeline) | ||||
|         ) | ||||
|         assert list(data) == [{"_id": None, "avg": 29, "total": 2}] | ||||
|  | ||||
|         pipeline = [{"$match": {"name": "Isabella Luanna"}}] | ||||
|         data = Person.objects().aggregate(pipeline) | ||||
|         assert list(data) == [{u"_id": p1.pk, u"age": 16, u"name": u"Isabella Luanna"}] | ||||
|  | ||||
|     def test_queryset_aggregation_with_skip(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects.skip(1).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [ | ||||
|             {"_id": p2.pk, "name": "WILSON JUNIOR"}, | ||||
|             {"_id": p3.pk, "name": "SANDRA MARA"}, | ||||
|         ] | ||||
|  | ||||
|     def test_queryset_aggregation_with_limit(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects.limit(1).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [{"_id": p1.pk, "name": "ISABELLA LUANNA"}] | ||||
|  | ||||
|     def test_queryset_aggregation_with_sort(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects.order_by("name").aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [ | ||||
|             {"_id": p1.pk, "name": "ISABELLA LUANNA"}, | ||||
|             {"_id": p3.pk, "name": "SANDRA MARA"}, | ||||
|             {"_id": p2.pk, "name": "WILSON JUNIOR"}, | ||||
|         ] | ||||
|  | ||||
|     def test_queryset_aggregation_with_skip_with_limit(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = list(Person.objects.skip(1).limit(1).aggregate(pipeline)) | ||||
|  | ||||
|         assert list(data) == [{"_id": p2.pk, "name": "WILSON JUNIOR"}] | ||||
|  | ||||
|         # Make sure limit/skip chaining order has no impact | ||||
|         data2 = Person.objects.limit(1).skip(1).aggregate(pipeline) | ||||
|  | ||||
|         assert data == list(data2) | ||||
|  | ||||
|     def test_queryset_aggregation_with_sort_with_limit(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects.order_by("name").limit(2).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [ | ||||
|             {"_id": p1.pk, "name": "ISABELLA LUANNA"}, | ||||
|             {"_id": p3.pk, "name": "SANDRA MARA"}, | ||||
|         ] | ||||
|  | ||||
|         # Verify adding limit/skip steps works as expected | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}, {"$limit": 1}] | ||||
|         data = Person.objects.order_by("name").limit(2).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [{"_id": p1.pk, "name": "ISABELLA LUANNA"}] | ||||
|  | ||||
|         pipeline = [ | ||||
|             {"$project": {"name": {"$toUpper": "$name"}}}, | ||||
|             {"$skip": 1}, | ||||
|             {"$limit": 1}, | ||||
|         ] | ||||
|         data = Person.objects.order_by("name").limit(2).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [{"_id": p3.pk, "name": "SANDRA MARA"}] | ||||
|  | ||||
|     def test_queryset_aggregation_with_sort_with_skip(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects.order_by("name").skip(2).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [{"_id": p2.pk, "name": "WILSON JUNIOR"}] | ||||
|  | ||||
|     def test_queryset_aggregation_with_sort_with_skip_with_limit(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|             age = IntField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna", age=16) | ||||
|         p2 = Person(name="Wilson Junior", age=21) | ||||
|         p3 = Person(name="Sandra Mara", age=37) | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|         data = Person.objects.order_by("name").skip(1).limit(1).aggregate(pipeline) | ||||
|  | ||||
|         assert list(data) == [{"_id": p3.pk, "name": "SANDRA MARA"}] | ||||
|  | ||||
|     def test_queryset_aggregation_deprecated_interface(self): | ||||
|         class Person(Document): | ||||
|             name = StringField() | ||||
|  | ||||
|         Person.drop_collection() | ||||
|  | ||||
|         p1 = Person(name="Isabella Luanna") | ||||
|         p2 = Person(name="Wilson Junior") | ||||
|         p3 = Person(name="Sandra Mara") | ||||
|         Person.objects.insert([p1, p2, p3]) | ||||
|  | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}] | ||||
|  | ||||
|         # Make sure a warning is emitted | ||||
|         with warnings.catch_warnings(): | ||||
|             warnings.simplefilter("error", DeprecationWarning) | ||||
|             with self.assertRaises(DeprecationWarning): | ||||
|                 Person.objects.order_by("name").limit(2).aggregate(*pipeline) | ||||
|  | ||||
|         # Make sure old interface works as expected with a 1-step pipeline | ||||
|         data = Person.objects.order_by("name").limit(2).aggregate(*pipeline) | ||||
|  | ||||
|         assert list(data) == [ | ||||
|             {"_id": p1.pk, "name": "ISABELLA LUANNA"}, | ||||
|             {"_id": p3.pk, "name": "SANDRA MARA"}, | ||||
|         ] | ||||
|  | ||||
|         # Make sure old interface works as expected with a 2-steps pipeline | ||||
|         pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}, {"$limit": 1}] | ||||
|         data = Person.objects.order_by("name").limit(2).aggregate(*pipeline) | ||||
|  | ||||
|         assert list(data) == [{"_id": p1.pk, "name": "ISABELLA LUANNA"}] | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
| @@ -1,6 +1,7 @@ | ||||
| import unittest | ||||
|  | ||||
| from bson.son import SON | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.queryset import Q, transform | ||||
| @@ -13,23 +14,16 @@ class TestTransform(unittest.TestCase): | ||||
|     def test_transform_query(self): | ||||
|         """Ensure that the _transform_query function operates correctly. | ||||
|         """ | ||||
|         self.assertEqual( | ||||
|             transform.query(name="test", age=30), {"name": "test", "age": 30} | ||||
|         ) | ||||
|         self.assertEqual(transform.query(age__lt=30), {"age": {"$lt": 30}}) | ||||
|         self.assertEqual( | ||||
|             transform.query(age__gt=20, age__lt=50), {"age": {"$gt": 20, "$lt": 50}} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             transform.query(age=20, age__gt=50), | ||||
|             {"$and": [{"age": {"$gt": 50}}, {"age": 20}]}, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             transform.query(friend__age__gte=30), {"friend.age": {"$gte": 30}} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             transform.query(name__exists=True), {"name": {"$exists": True}} | ||||
|         ) | ||||
|         assert transform.query(name="test", age=30) == {"name": "test", "age": 30} | ||||
|         assert transform.query(age__lt=30) == {"age": {"$lt": 30}} | ||||
|         assert transform.query(age__gt=20, age__lt=50) == { | ||||
|             "age": {"$gt": 20, "$lt": 50} | ||||
|         } | ||||
|         assert transform.query(age=20, age__gt=50) == { | ||||
|             "$and": [{"age": {"$gt": 50}}, {"age": 20}] | ||||
|         } | ||||
|         assert transform.query(friend__age__gte=30) == {"friend.age": {"$gte": 30}} | ||||
|         assert transform.query(name__exists=True) == {"name": {"$exists": True}} | ||||
|  | ||||
|     def test_transform_update(self): | ||||
|         class LisDoc(Document): | ||||
| @@ -54,17 +48,17 @@ class TestTransform(unittest.TestCase): | ||||
|             ("push", "$push"), | ||||
|         ): | ||||
|             update = transform.update(DicDoc, **{"%s__dictField__test" % k: doc}) | ||||
|             self.assertIsInstance(update[v]["dictField.test"], dict) | ||||
|             assert isinstance(update[v]["dictField.test"], dict) | ||||
|  | ||||
|         # Update special cases | ||||
|         update = transform.update(DicDoc, unset__dictField__test=doc) | ||||
|         self.assertEqual(update["$unset"]["dictField.test"], 1) | ||||
|         assert update["$unset"]["dictField.test"] == 1 | ||||
|  | ||||
|         update = transform.update(DicDoc, pull__dictField__test=doc) | ||||
|         self.assertIsInstance(update["$pull"]["dictField"]["test"], dict) | ||||
|         assert isinstance(update["$pull"]["dictField"]["test"], dict) | ||||
|  | ||||
|         update = transform.update(LisDoc, pull__foo__in=["a"]) | ||||
|         self.assertEqual(update, {"$pull": {"foo": {"$in": ["a"]}}}) | ||||
|         assert update == {"$pull": {"foo": {"$in": ["a"]}}} | ||||
|  | ||||
|     def test_transform_update_push(self): | ||||
|         """Ensure the differences in behvaior between 'push' and 'push_all'""" | ||||
| @@ -73,10 +67,10 @@ class TestTransform(unittest.TestCase): | ||||
|             tags = ListField(StringField()) | ||||
|  | ||||
|         update = transform.update(BlogPost, push__tags=["mongo", "db"]) | ||||
|         self.assertEqual(update, {"$push": {"tags": ["mongo", "db"]}}) | ||||
|         assert update == {"$push": {"tags": ["mongo", "db"]}} | ||||
|  | ||||
|         update = transform.update(BlogPost, push_all__tags=["mongo", "db"]) | ||||
|         self.assertEqual(update, {"$push": {"tags": {"$each": ["mongo", "db"]}}}) | ||||
|         assert update == {"$push": {"tags": {"$each": ["mongo", "db"]}}} | ||||
|  | ||||
|     def test_transform_update_no_operator_default_to_set(self): | ||||
|         """Ensure the differences in behvaior between 'push' and 'push_all'""" | ||||
| @@ -85,7 +79,7 @@ class TestTransform(unittest.TestCase): | ||||
|             tags = ListField(StringField()) | ||||
|  | ||||
|         update = transform.update(BlogPost, tags=["mongo", "db"]) | ||||
|         self.assertEqual(update, {"$set": {"tags": ["mongo", "db"]}}) | ||||
|         assert update == {"$set": {"tags": ["mongo", "db"]}} | ||||
|  | ||||
|     def test_query_field_name(self): | ||||
|         """Ensure that the correct field name is used when querying. | ||||
| @@ -106,18 +100,18 @@ class TestTransform(unittest.TestCase): | ||||
|         post = BlogPost(**data) | ||||
|         post.save() | ||||
|  | ||||
|         self.assertIn("postTitle", BlogPost.objects(title=data["title"])._query) | ||||
|         self.assertFalse("title" in BlogPost.objects(title=data["title"])._query) | ||||
|         self.assertEqual(BlogPost.objects(title=data["title"]).count(), 1) | ||||
|         assert "postTitle" in BlogPost.objects(title=data["title"])._query | ||||
|         assert not ("title" in BlogPost.objects(title=data["title"])._query) | ||||
|         assert BlogPost.objects(title=data["title"]).count() == 1 | ||||
|  | ||||
|         self.assertIn("_id", BlogPost.objects(pk=post.id)._query) | ||||
|         self.assertEqual(BlogPost.objects(pk=post.id).count(), 1) | ||||
|         assert "_id" in BlogPost.objects(pk=post.id)._query | ||||
|         assert BlogPost.objects(pk=post.id).count() == 1 | ||||
|  | ||||
|         self.assertIn( | ||||
|             "postComments.commentContent", | ||||
|             BlogPost.objects(comments__content="test")._query, | ||||
|         assert ( | ||||
|             "postComments.commentContent" | ||||
|             in BlogPost.objects(comments__content="test")._query | ||||
|         ) | ||||
|         self.assertEqual(BlogPost.objects(comments__content="test").count(), 1) | ||||
|         assert BlogPost.objects(comments__content="test").count() == 1 | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -135,9 +129,9 @@ class TestTransform(unittest.TestCase): | ||||
|         post = BlogPost(**data) | ||||
|         post.save() | ||||
|  | ||||
|         self.assertIn("_id", BlogPost.objects(pk=data["title"])._query) | ||||
|         self.assertIn("_id", BlogPost.objects(title=data["title"])._query) | ||||
|         self.assertEqual(BlogPost.objects(pk=data["title"]).count(), 1) | ||||
|         assert "_id" in BlogPost.objects(pk=data["title"])._query | ||||
|         assert "_id" in BlogPost.objects(title=data["title"])._query | ||||
|         assert BlogPost.objects(pk=data["title"]).count() == 1 | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -163,7 +157,7 @@ class TestTransform(unittest.TestCase): | ||||
|         q2 = B.objects.filter(a__in=[a1, a2]) | ||||
|         q2 = q2.filter(a=a1)._query | ||||
|  | ||||
|         self.assertEqual(q1, q2) | ||||
|         assert q1 == q2 | ||||
|  | ||||
|     def test_raw_query_and_Q_objects(self): | ||||
|         """ | ||||
| @@ -179,11 +173,11 @@ class TestTransform(unittest.TestCase): | ||||
|             meta = {"allow_inheritance": False} | ||||
|  | ||||
|         query = Foo.objects(__raw__={"$nor": [{"name": "bar"}]})._query | ||||
|         self.assertEqual(query, {"$nor": [{"name": "bar"}]}) | ||||
|         assert query == {"$nor": [{"name": "bar"}]} | ||||
|  | ||||
|         q1 = {"$or": [{"a": 1}, {"b": 1}]} | ||||
|         query = Foo.objects(Q(__raw__=q1) & Q(c=1))._query | ||||
|         self.assertEqual(query, {"$or": [{"a": 1}, {"b": 1}], "c": 1}) | ||||
|         assert query == {"$or": [{"a": 1}, {"b": 1}], "c": 1} | ||||
|  | ||||
|     def test_raw_and_merging(self): | ||||
|         class Doc(Document): | ||||
| @@ -200,51 +194,39 @@ class TestTransform(unittest.TestCase): | ||||
|             } | ||||
|         )._query | ||||
|  | ||||
|         self.assertEqual( | ||||
|             raw_query, | ||||
|             { | ||||
|                 "deleted": False, | ||||
|                 "scraped": "yes", | ||||
|                 "$nor": [ | ||||
|                     {"views.extracted": "no"}, | ||||
|                     {"attachments.views.extracted": "no"}, | ||||
|                 ], | ||||
|             }, | ||||
|         ) | ||||
|         assert raw_query == { | ||||
|             "deleted": False, | ||||
|             "scraped": "yes", | ||||
|             "$nor": [{"views.extracted": "no"}, {"attachments.views.extracted": "no"}], | ||||
|         } | ||||
|  | ||||
|     def test_geojson_PointField(self): | ||||
|         class Location(Document): | ||||
|             loc = PointField() | ||||
|  | ||||
|         update = transform.update(Location, set__loc=[1, 2]) | ||||
|         self.assertEqual( | ||||
|             update, {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}} | ||||
|         ) | ||||
|         assert update == {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}} | ||||
|  | ||||
|         update = transform.update( | ||||
|             Location, set__loc={"type": "Point", "coordinates": [1, 2]} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             update, {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}} | ||||
|         ) | ||||
|         assert update == {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}} | ||||
|  | ||||
|     def test_geojson_LineStringField(self): | ||||
|         class Location(Document): | ||||
|             line = LineStringField() | ||||
|  | ||||
|         update = transform.update(Location, set__line=[[1, 2], [2, 2]]) | ||||
|         self.assertEqual( | ||||
|             update, | ||||
|             {"$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}}, | ||||
|         ) | ||||
|         assert update == { | ||||
|             "$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}} | ||||
|         } | ||||
|  | ||||
|         update = transform.update( | ||||
|             Location, set__line={"type": "LineString", "coordinates": [[1, 2], [2, 2]]} | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             update, | ||||
|             {"$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}}, | ||||
|         ) | ||||
|         assert update == { | ||||
|             "$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}} | ||||
|         } | ||||
|  | ||||
|     def test_geojson_PolygonField(self): | ||||
|         class Location(Document): | ||||
| @@ -253,17 +235,14 @@ class TestTransform(unittest.TestCase): | ||||
|         update = transform.update( | ||||
|             Location, set__poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             update, | ||||
|             { | ||||
|                 "$set": { | ||||
|                     "poly": { | ||||
|                         "type": "Polygon", | ||||
|                         "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], | ||||
|                     } | ||||
|         assert update == { | ||||
|             "$set": { | ||||
|                 "poly": { | ||||
|                     "type": "Polygon", | ||||
|                     "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], | ||||
|                 } | ||||
|             }, | ||||
|         ) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         update = transform.update( | ||||
|             Location, | ||||
| @@ -272,17 +251,14 @@ class TestTransform(unittest.TestCase): | ||||
|                 "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             update, | ||||
|             { | ||||
|                 "$set": { | ||||
|                     "poly": { | ||||
|                         "type": "Polygon", | ||||
|                         "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], | ||||
|                     } | ||||
|         assert update == { | ||||
|             "$set": { | ||||
|                 "poly": { | ||||
|                     "type": "Polygon", | ||||
|                     "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], | ||||
|                 } | ||||
|             }, | ||||
|         ) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     def test_type(self): | ||||
|         class Doc(Document): | ||||
| @@ -291,10 +267,10 @@ class TestTransform(unittest.TestCase): | ||||
|         Doc(df=True).save() | ||||
|         Doc(df=7).save() | ||||
|         Doc(df="df").save() | ||||
|         self.assertEqual(Doc.objects(df__type=1).count(), 0)  # double | ||||
|         self.assertEqual(Doc.objects(df__type=8).count(), 1)  # bool | ||||
|         self.assertEqual(Doc.objects(df__type=2).count(), 1)  # str | ||||
|         self.assertEqual(Doc.objects(df__type=16).count(), 1)  # int | ||||
|         assert Doc.objects(df__type=1).count() == 0  # double | ||||
|         assert Doc.objects(df__type=8).count() == 1  # bool | ||||
|         assert Doc.objects(df__type=2).count() == 1  # str | ||||
|         assert Doc.objects(df__type=16).count() == 1  # int | ||||
|  | ||||
|     def test_last_field_name_like_operator(self): | ||||
|         class EmbeddedItem(EmbeddedDocument): | ||||
| @@ -309,12 +285,12 @@ class TestTransform(unittest.TestCase): | ||||
|         doc = Doc(item=EmbeddedItem(type="axe", name="Heroic axe")) | ||||
|         doc.save() | ||||
|  | ||||
|         self.assertEqual(1, Doc.objects(item__type__="axe").count()) | ||||
|         self.assertEqual(1, Doc.objects(item__name__="Heroic axe").count()) | ||||
|         assert 1 == Doc.objects(item__type__="axe").count() | ||||
|         assert 1 == Doc.objects(item__name__="Heroic axe").count() | ||||
|  | ||||
|         Doc.objects(id=doc.id).update(set__item__type__="sword") | ||||
|         self.assertEqual(1, Doc.objects(item__type__="sword").count()) | ||||
|         self.assertEqual(0, Doc.objects(item__type__="axe").count()) | ||||
|         assert 1 == Doc.objects(item__type__="sword").count() | ||||
|         assert 0 == Doc.objects(item__type__="axe").count() | ||||
|  | ||||
|     def test_understandable_error_raised(self): | ||||
|         class Event(Document): | ||||
| @@ -324,7 +300,7 @@ class TestTransform(unittest.TestCase): | ||||
|         box = [(35.0, -125.0), (40.0, -100.0)] | ||||
|         # I *meant* to execute location__within_box=box | ||||
|         events = Event.objects(location__within=box) | ||||
|         with self.assertRaises(InvalidQueryError): | ||||
|         with pytest.raises(InvalidQueryError): | ||||
|             events.count() | ||||
|  | ||||
|     def test_update_pull_for_list_fields(self): | ||||
| @@ -347,24 +323,20 @@ class TestTransform(unittest.TestCase): | ||||
|  | ||||
|         word = Word(word="abc", index=1) | ||||
|         update = transform.update(MainDoc, pull__content__text=word) | ||||
|         self.assertEqual( | ||||
|             update, {"$pull": {"content.text": SON([("word", u"abc"), ("index", 1)])}} | ||||
|         ) | ||||
|         assert update == { | ||||
|             "$pull": {"content.text": SON([("word", u"abc"), ("index", 1)])} | ||||
|         } | ||||
|  | ||||
|         update = transform.update(MainDoc, pull__content__heading="xyz") | ||||
|         self.assertEqual(update, {"$pull": {"content.heading": "xyz"}}) | ||||
|         assert update == {"$pull": {"content.heading": "xyz"}} | ||||
|  | ||||
|         update = transform.update(MainDoc, pull__content__text__word__in=["foo", "bar"]) | ||||
|         self.assertEqual( | ||||
|             update, {"$pull": {"content.text": {"word": {"$in": ["foo", "bar"]}}}} | ||||
|         ) | ||||
|         assert update == {"$pull": {"content.text": {"word": {"$in": ["foo", "bar"]}}}} | ||||
|  | ||||
|         update = transform.update( | ||||
|             MainDoc, pull__content__text__word__nin=["foo", "bar"] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             update, {"$pull": {"content.text": {"word": {"$nin": ["foo", "bar"]}}}} | ||||
|         ) | ||||
|         assert update == {"$pull": {"content.text": {"word": {"$nin": ["foo", "bar"]}}}} | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import re | ||||
| import unittest | ||||
|  | ||||
| from bson import ObjectId | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.errors import InvalidQueryError | ||||
| @@ -35,10 +36,10 @@ class TestQ(unittest.TestCase): | ||||
|             age = IntField() | ||||
|  | ||||
|         query = {"$or": [{"age": {"$gte": 18}}, {"name": "test"}]} | ||||
|         self.assertEqual((q1 | q2 | q3 | q4 | q5).to_query(Person), query) | ||||
|         assert (q1 | q2 | q3 | q4 | q5).to_query(Person) == query | ||||
|  | ||||
|         query = {"age": {"$gte": 18}, "name": "test"} | ||||
|         self.assertEqual((q1 & q2 & q3 & q4 & q5).to_query(Person), query) | ||||
|         assert (q1 & q2 & q3 & q4 & q5).to_query(Person) == query | ||||
|  | ||||
|     def test_q_with_dbref(self): | ||||
|         """Ensure Q objects handle DBRefs correctly""" | ||||
| @@ -53,8 +54,8 @@ class TestQ(unittest.TestCase): | ||||
|         user = User.objects.create() | ||||
|         Post.objects.create(created_user=user) | ||||
|  | ||||
|         self.assertEqual(Post.objects.filter(created_user=user).count(), 1) | ||||
|         self.assertEqual(Post.objects.filter(Q(created_user=user)).count(), 1) | ||||
|         assert Post.objects.filter(created_user=user).count() == 1 | ||||
|         assert Post.objects.filter(Q(created_user=user)).count() == 1 | ||||
|  | ||||
|     def test_and_combination(self): | ||||
|         """Ensure that Q-objects correctly AND together. | ||||
| @@ -65,12 +66,10 @@ class TestQ(unittest.TestCase): | ||||
|             y = StringField() | ||||
|  | ||||
|         query = (Q(x__lt=7) & Q(x__lt=3)).to_query(TestDoc) | ||||
|         self.assertEqual(query, {"$and": [{"x": {"$lt": 7}}, {"x": {"$lt": 3}}]}) | ||||
|         assert query == {"$and": [{"x": {"$lt": 7}}, {"x": {"$lt": 3}}]} | ||||
|  | ||||
|         query = (Q(y="a") & Q(x__lt=7) & Q(x__lt=3)).to_query(TestDoc) | ||||
|         self.assertEqual( | ||||
|             query, {"$and": [{"y": "a"}, {"x": {"$lt": 7}}, {"x": {"$lt": 3}}]} | ||||
|         ) | ||||
|         assert query == {"$and": [{"y": "a"}, {"x": {"$lt": 7}}, {"x": {"$lt": 3}}]} | ||||
|  | ||||
|         # Check normal cases work without an error | ||||
|         query = Q(x__lt=7) & Q(x__gt=3) | ||||
| @@ -78,7 +77,7 @@ class TestQ(unittest.TestCase): | ||||
|         q1 = Q(x__lt=7) | ||||
|         q2 = Q(x__gt=3) | ||||
|         query = (q1 & q2).to_query(TestDoc) | ||||
|         self.assertEqual(query, {"x": {"$lt": 7, "$gt": 3}}) | ||||
|         assert query == {"x": {"$lt": 7, "$gt": 3}} | ||||
|  | ||||
|         # More complex nested example | ||||
|         query = Q(x__lt=100) & Q(y__ne="NotMyString") | ||||
| @@ -87,7 +86,7 @@ class TestQ(unittest.TestCase): | ||||
|             "x": {"$lt": 100, "$gt": -100}, | ||||
|             "y": {"$ne": "NotMyString", "$in": ["a", "b", "c"]}, | ||||
|         } | ||||
|         self.assertEqual(query.to_query(TestDoc), mongo_query) | ||||
|         assert query.to_query(TestDoc) == mongo_query | ||||
|  | ||||
|     def test_or_combination(self): | ||||
|         """Ensure that Q-objects correctly OR together. | ||||
| @@ -99,7 +98,7 @@ class TestQ(unittest.TestCase): | ||||
|         q1 = Q(x__lt=3) | ||||
|         q2 = Q(x__gt=7) | ||||
|         query = (q1 | q2).to_query(TestDoc) | ||||
|         self.assertEqual(query, {"$or": [{"x": {"$lt": 3}}, {"x": {"$gt": 7}}]}) | ||||
|         assert query == {"$or": [{"x": {"$lt": 3}}, {"x": {"$gt": 7}}]} | ||||
|  | ||||
|     def test_and_or_combination(self): | ||||
|         """Ensure that Q-objects handle ANDing ORed components. | ||||
| @@ -113,15 +112,12 @@ class TestQ(unittest.TestCase): | ||||
|  | ||||
|         query = Q(x__gt=0) | Q(x__exists=False) | ||||
|         query &= Q(x__lt=100) | ||||
|         self.assertEqual( | ||||
|             query.to_query(TestDoc), | ||||
|             { | ||||
|                 "$and": [ | ||||
|                     {"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]}, | ||||
|                     {"x": {"$lt": 100}}, | ||||
|                 ] | ||||
|             }, | ||||
|         ) | ||||
|         assert query.to_query(TestDoc) == { | ||||
|             "$and": [ | ||||
|                 {"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]}, | ||||
|                 {"x": {"$lt": 100}}, | ||||
|             ] | ||||
|         } | ||||
|  | ||||
|         q1 = Q(x__gt=0) | Q(x__exists=False) | ||||
|         q2 = Q(x__lt=100) | Q(y=True) | ||||
| @@ -131,16 +127,13 @@ class TestQ(unittest.TestCase): | ||||
|         TestDoc(x=10).save() | ||||
|         TestDoc(y=True).save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             query, | ||||
|             { | ||||
|                 "$and": [ | ||||
|                     {"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]}, | ||||
|                     {"$or": [{"x": {"$lt": 100}}, {"y": True}]}, | ||||
|                 ] | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(2, TestDoc.objects(q1 & q2).count()) | ||||
|         assert query == { | ||||
|             "$and": [ | ||||
|                 {"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]}, | ||||
|                 {"$or": [{"x": {"$lt": 100}}, {"y": True}]}, | ||||
|             ] | ||||
|         } | ||||
|         assert 2 == TestDoc.objects(q1 & q2).count() | ||||
|  | ||||
|     def test_or_and_or_combination(self): | ||||
|         """Ensure that Q-objects handle ORing ANDed ORed components. :) | ||||
| @@ -160,26 +153,23 @@ class TestQ(unittest.TestCase): | ||||
|         q2 = Q(x__lt=100) & (Q(y=False) | Q(y__exists=False)) | ||||
|         query = (q1 | q2).to_query(TestDoc) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             query, | ||||
|             { | ||||
|                 "$or": [ | ||||
|                     { | ||||
|                         "$and": [ | ||||
|                             {"x": {"$gt": 0}}, | ||||
|                             {"$or": [{"y": True}, {"y": {"$exists": False}}]}, | ||||
|                         ] | ||||
|                     }, | ||||
|                     { | ||||
|                         "$and": [ | ||||
|                             {"x": {"$lt": 100}}, | ||||
|                             {"$or": [{"y": False}, {"y": {"$exists": False}}]}, | ||||
|                         ] | ||||
|                     }, | ||||
|                 ] | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(2, TestDoc.objects(q1 | q2).count()) | ||||
|         assert query == { | ||||
|             "$or": [ | ||||
|                 { | ||||
|                     "$and": [ | ||||
|                         {"x": {"$gt": 0}}, | ||||
|                         {"$or": [{"y": True}, {"y": {"$exists": False}}]}, | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "$and": [ | ||||
|                         {"x": {"$lt": 100}}, | ||||
|                         {"$or": [{"y": False}, {"y": {"$exists": False}}]}, | ||||
|                     ] | ||||
|                 }, | ||||
|             ] | ||||
|         } | ||||
|         assert 2 == TestDoc.objects(q1 | q2).count() | ||||
|  | ||||
|     def test_multiple_occurence_in_field(self): | ||||
|         class Test(Document): | ||||
| @@ -192,8 +182,8 @@ class TestQ(unittest.TestCase): | ||||
|         q3 = q1 & q2 | ||||
|  | ||||
|         query = q3.to_query(Test) | ||||
|         self.assertEqual(query["$and"][0], q1.to_query(Test)) | ||||
|         self.assertEqual(query["$and"][1], q2.to_query(Test)) | ||||
|         assert query["$and"][0] == q1.to_query(Test) | ||||
|         assert query["$and"][1] == q2.to_query(Test) | ||||
|  | ||||
|     def test_q_clone(self): | ||||
|         class TestDoc(Document): | ||||
| @@ -207,15 +197,15 @@ class TestQ(unittest.TestCase): | ||||
|         # Check normal cases work without an error | ||||
|         test = TestDoc.objects(Q(x__lt=7) & Q(x__gt=3)) | ||||
|  | ||||
|         self.assertEqual(test.count(), 3) | ||||
|         assert test.count() == 3 | ||||
|  | ||||
|         test2 = test.clone() | ||||
|         self.assertEqual(test2.count(), 3) | ||||
|         self.assertNotEqual(test2, test) | ||||
|         assert test2.count() == 3 | ||||
|         assert test2 != test | ||||
|  | ||||
|         test3 = test2.filter(x=6) | ||||
|         self.assertEqual(test3.count(), 1) | ||||
|         self.assertEqual(test.count(), 3) | ||||
|         assert test3.count() == 1 | ||||
|         assert test.count() == 3 | ||||
|  | ||||
|     def test_q(self): | ||||
|         """Ensure that Q objects may be used to query for documents. | ||||
| @@ -252,19 +242,19 @@ class TestQ(unittest.TestCase): | ||||
|  | ||||
|         # Check ObjectId lookup works | ||||
|         obj = BlogPost.objects(id=post1.id).first() | ||||
|         self.assertEqual(obj, post1) | ||||
|         assert obj == post1 | ||||
|  | ||||
|         # Check Q object combination with one does not exist | ||||
|         q = BlogPost.objects(Q(title="Test 5") | Q(published=True)) | ||||
|         posts = [post.id for post in q] | ||||
|  | ||||
|         published_posts = (post2, post3) | ||||
|         self.assertTrue(all(obj.id in posts for obj in published_posts)) | ||||
|         assert all(obj.id in posts for obj in published_posts) | ||||
|  | ||||
|         q = BlogPost.objects(Q(title="Test 1") | Q(published=True)) | ||||
|         posts = [post.id for post in q] | ||||
|         published_posts = (post1, post2, post3, post5, post6) | ||||
|         self.assertTrue(all(obj.id in posts for obj in published_posts)) | ||||
|         assert all(obj.id in posts for obj in published_posts) | ||||
|  | ||||
|         # Check Q object combination | ||||
|         date = datetime.datetime(2010, 1, 10) | ||||
| @@ -272,9 +262,9 @@ class TestQ(unittest.TestCase): | ||||
|         posts = [post.id for post in q] | ||||
|  | ||||
|         published_posts = (post1, post2, post3, post4) | ||||
|         self.assertTrue(all(obj.id in posts for obj in published_posts)) | ||||
|         assert all(obj.id in posts for obj in published_posts) | ||||
|  | ||||
|         self.assertFalse(any(obj.id in posts for obj in [post5, post6])) | ||||
|         assert not any(obj.id in posts for obj in [post5, post6]) | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -284,15 +274,15 @@ class TestQ(unittest.TestCase): | ||||
|         self.Person(name="user3", age=30).save() | ||||
|         self.Person(name="user4", age=40).save() | ||||
|  | ||||
|         self.assertEqual(self.Person.objects(Q(age__in=[20])).count(), 2) | ||||
|         self.assertEqual(self.Person.objects(Q(age__in=[20, 30])).count(), 3) | ||||
|         assert self.Person.objects(Q(age__in=[20])).count() == 2 | ||||
|         assert self.Person.objects(Q(age__in=[20, 30])).count() == 3 | ||||
|  | ||||
|         # Test invalid query objs | ||||
|         with self.assertRaises(InvalidQueryError): | ||||
|         with pytest.raises(InvalidQueryError): | ||||
|             self.Person.objects("user1") | ||||
|  | ||||
|         # filter should fail, too | ||||
|         with self.assertRaises(InvalidQueryError): | ||||
|         with pytest.raises(InvalidQueryError): | ||||
|             self.Person.objects.filter("user1") | ||||
|  | ||||
|     def test_q_regex(self): | ||||
| @@ -302,31 +292,31 @@ class TestQ(unittest.TestCase): | ||||
|         person.save() | ||||
|  | ||||
|         obj = self.Person.objects(Q(name=re.compile("^Gui"))).first() | ||||
|         self.assertEqual(obj, person) | ||||
|         assert obj == person | ||||
|         obj = self.Person.objects(Q(name=re.compile("^gui"))).first() | ||||
|         self.assertEqual(obj, None) | ||||
|         assert obj is None | ||||
|  | ||||
|         obj = self.Person.objects(Q(name=re.compile("^gui", re.I))).first() | ||||
|         self.assertEqual(obj, person) | ||||
|         assert obj == person | ||||
|  | ||||
|         obj = self.Person.objects(Q(name__not=re.compile("^bob"))).first() | ||||
|         self.assertEqual(obj, person) | ||||
|         assert obj == person | ||||
|  | ||||
|         obj = self.Person.objects(Q(name__not=re.compile("^Gui"))).first() | ||||
|         self.assertEqual(obj, None) | ||||
|         assert obj is None | ||||
|  | ||||
|     def test_q_repr(self): | ||||
|         self.assertEqual(repr(Q()), "Q(**{})") | ||||
|         self.assertEqual(repr(Q(name="test")), "Q(**{'name': 'test'})") | ||||
|         assert repr(Q()) == "Q(**{})" | ||||
|         assert repr(Q(name="test")) == "Q(**{'name': 'test'})" | ||||
|  | ||||
|         self.assertEqual( | ||||
|             repr(Q(name="test") & Q(age__gte=18)), | ||||
|             "(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))", | ||||
|         assert ( | ||||
|             repr(Q(name="test") & Q(age__gte=18)) | ||||
|             == "(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))" | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             repr(Q(name="test") | Q(age__gte=18)), | ||||
|             "(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))", | ||||
|         assert ( | ||||
|             repr(Q(name="test") | Q(age__gte=18)) | ||||
|             == "(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))" | ||||
|         ) | ||||
|  | ||||
|     def test_q_lists(self): | ||||
| @@ -341,8 +331,8 @@ class TestQ(unittest.TestCase): | ||||
|         BlogPost(tags=["python", "mongo"]).save() | ||||
|         BlogPost(tags=["python"]).save() | ||||
|  | ||||
|         self.assertEqual(BlogPost.objects(Q(tags="mongo")).count(), 1) | ||||
|         self.assertEqual(BlogPost.objects(Q(tags="python")).count(), 2) | ||||
|         assert BlogPost.objects(Q(tags="mongo")).count() == 1 | ||||
|         assert BlogPost.objects(Q(tags="python")).count() == 2 | ||||
|  | ||||
|         BlogPost.drop_collection() | ||||
|  | ||||
| @@ -355,12 +345,12 @@ class TestQ(unittest.TestCase): | ||||
|         pk = ObjectId() | ||||
|         User(email="example@example.com", pk=pk).save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             1, | ||||
|             User.objects.filter(Q(email="example@example.com") | Q(name="John Doe")) | ||||
|         assert ( | ||||
|             1 | ||||
|             == User.objects.filter(Q(email="example@example.com") | Q(name="John Doe")) | ||||
|             .limit(2) | ||||
|             .filter(pk=pk) | ||||
|             .count(), | ||||
|             .count() | ||||
|         ) | ||||
|  | ||||
|     def test_chained_q_or_filtering(self): | ||||
| @@ -376,16 +366,58 @@ class TestQ(unittest.TestCase): | ||||
|         Item(postables=[Post(name="a"), Post(name="c")]).save() | ||||
|         Item(postables=[Post(name="a"), Post(name="b"), Post(name="c")]).save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             Item.objects(Q(postables__name="a") & Q(postables__name="b")).count(), 2 | ||||
|         assert ( | ||||
|             Item.objects(Q(postables__name="a") & Q(postables__name="b")).count() == 2 | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             Item.objects.filter(postables__name="a") | ||||
|             .filter(postables__name="b") | ||||
|             .count(), | ||||
|             2, | ||||
|         assert ( | ||||
|             Item.objects.filter(postables__name="a").filter(postables__name="b").count() | ||||
|             == 2 | ||||
|         ) | ||||
|  | ||||
|     def test_equality(self): | ||||
|         assert Q(name="John") == Q(name="John") | ||||
|         assert Q() == Q() | ||||
|  | ||||
|     def test_inequality(self): | ||||
|         assert Q(name="John") != Q(name="Ralph") | ||||
|  | ||||
|     def test_operation_equality(self): | ||||
|         q1 = Q(name="John") | Q(title="Sir") & Q(surname="Paul") | ||||
|         q2 = Q(name="John") | Q(title="Sir") & Q(surname="Paul") | ||||
|         assert q1 == q2 | ||||
|  | ||||
|     def test_operation_inequality(self): | ||||
|         q1 = Q(name="John") | Q(title="Sir") | ||||
|         q2 = Q(title="Sir") | Q(name="John") | ||||
|         assert q1 != q2 | ||||
|  | ||||
|     def test_combine_and_empty(self): | ||||
|         q = Q(x=1) | ||||
|         assert q & Q() == q | ||||
|         assert Q() & q == q | ||||
|  | ||||
|     def test_combine_and_both_empty(self): | ||||
|         assert Q() & Q() == Q() | ||||
|  | ||||
|     def test_combine_or_empty(self): | ||||
|         q = Q(x=1) | ||||
|         assert q | Q() == q | ||||
|         assert Q() | q == q | ||||
|  | ||||
|     def test_combine_or_both_empty(self): | ||||
|         assert Q() | Q() == Q() | ||||
|  | ||||
|     def test_q_bool(self): | ||||
|         assert Q(name="John") | ||||
|         assert not Q() | ||||
|  | ||||
|     def test_combine_bool(self): | ||||
|         assert not Q() & Q() | ||||
|         assert Q() & Q(name="John") | ||||
|         assert Q(name="John") & Q() | ||||
|         assert Q() | Q(name="John") | ||||
|         assert Q(name="John") | Q() | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|   | ||||
							
								
								
									
										9
									
								
								tests/test_ci.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/test_ci.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| def test_ci_placeholder(): | ||||
|     # This empty test is used within the CI to | ||||
|     # setup the tox venv without running the test suite | ||||
|     # if we simply skip all test with pytest -k=wrong_pattern | ||||
|     # pytest command would return with exit_code=5 (i.e "no tests run") | ||||
|     # making travis fail | ||||
|     # this empty test is the recommended way to handle this | ||||
|     # as described in https://github.com/pytest-dev/pytest/issues/2393 | ||||
|     pass | ||||
| @@ -1,14 +1,16 @@ | ||||
| import unittest | ||||
|  | ||||
| from mongoengine.common import _import_class | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import Document | ||||
| from mongoengine.common import _import_class | ||||
|  | ||||
|  | ||||
| class TestCommon(unittest.TestCase): | ||||
| class TestCommon: | ||||
|     def test__import_class(self): | ||||
|         doc_cls = _import_class("Document") | ||||
|         self.assertIs(doc_cls, Document) | ||||
|         assert doc_cls is Document | ||||
|  | ||||
|     def test__import_class_raise_if_not_known(self): | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|             _import_class("UnknownClass") | ||||
|   | ||||
| @@ -1,35 +1,32 @@ | ||||
| import datetime | ||||
|  | ||||
| from pymongo import MongoClient | ||||
| from pymongo.errors import OperationFailure, InvalidName | ||||
| from pymongo import ReadPreference | ||||
| from bson.tz_util import utc | ||||
| import pymongo | ||||
|  | ||||
| from mongoengine import Document | ||||
| from pymongo import MongoClient, ReadPreference | ||||
| from pymongo.errors import InvalidName, OperationFailure | ||||
| import pytest | ||||
|  | ||||
| try: | ||||
|     import unittest2 as unittest | ||||
| except ImportError: | ||||
|     import unittest | ||||
| from nose.plugins.skip import SkipTest | ||||
|  | ||||
| import pymongo | ||||
| from bson.tz_util import utc | ||||
|  | ||||
| from mongoengine import ( | ||||
|     connect, | ||||
|     register_connection, | ||||
|     Document, | ||||
|     DateTimeField, | ||||
|     disconnect_all, | ||||
|     StringField, | ||||
| ) | ||||
| import mongoengine.connection | ||||
| from mongoengine import ( | ||||
|     DateTimeField, | ||||
|     Document, | ||||
|     StringField, | ||||
|     connect, | ||||
|     disconnect_all, | ||||
|     register_connection, | ||||
| ) | ||||
| from mongoengine.connection import ( | ||||
|     ConnectionFailure, | ||||
|     get_db, | ||||
|     get_connection, | ||||
|     disconnect, | ||||
|     DEFAULT_DATABASE_NAME, | ||||
|     disconnect, | ||||
|     get_connection, | ||||
|     get_db, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @@ -37,6 +34,18 @@ def get_tz_awareness(connection): | ||||
|     return connection.codec_options.tz_aware | ||||
|  | ||||
|  | ||||
| try: | ||||
|     import mongomock | ||||
|  | ||||
|     MONGOMOCK_INSTALLED = True | ||||
| except ImportError: | ||||
|     MONGOMOCK_INSTALLED = False | ||||
|  | ||||
| require_mongomock = pytest.mark.skipif( | ||||
|     not MONGOMOCK_INSTALLED, reason="you need mongomock installed to run this testcase" | ||||
| ) | ||||
|  | ||||
|  | ||||
| class ConnectionTest(unittest.TestCase): | ||||
|     @classmethod | ||||
|     def setUpClass(cls): | ||||
| @@ -56,15 +65,15 @@ class ConnectionTest(unittest.TestCase): | ||||
|         connect("mongoenginetest") | ||||
|  | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "mongoenginetest") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "mongoenginetest" | ||||
|  | ||||
|         connect("mongoenginetest2", alias="testdb") | ||||
|         conn = get_connection("testdb") | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|     def test_connect_disconnect_works_properly(self): | ||||
|         class History1(Document): | ||||
| @@ -84,31 +93,27 @@ class ConnectionTest(unittest.TestCase): | ||||
|         h = History1(name="default").save() | ||||
|         h1 = History2(name="db1").save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             list(History1.objects().as_pymongo()), [{"_id": h.id, "name": "default"}] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             list(History2.objects().as_pymongo()), [{"_id": h1.id, "name": "db1"}] | ||||
|         ) | ||||
|         assert list(History1.objects().as_pymongo()) == [ | ||||
|             {"_id": h.id, "name": "default"} | ||||
|         ] | ||||
|         assert list(History2.objects().as_pymongo()) == [{"_id": h1.id, "name": "db1"}] | ||||
|  | ||||
|         disconnect("db1") | ||||
|         disconnect("db2") | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure): | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             list(History1.objects().as_pymongo()) | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure): | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             list(History2.objects().as_pymongo()) | ||||
|  | ||||
|         connect("db1", alias="db1") | ||||
|         connect("db2", alias="db2") | ||||
|  | ||||
|         self.assertEqual( | ||||
|             list(History1.objects().as_pymongo()), [{"_id": h.id, "name": "default"}] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             list(History2.objects().as_pymongo()), [{"_id": h1.id, "name": "db1"}] | ||||
|         ) | ||||
|         assert list(History1.objects().as_pymongo()) == [ | ||||
|             {"_id": h.id, "name": "default"} | ||||
|         ] | ||||
|         assert list(History2.objects().as_pymongo()) == [{"_id": h1.id, "name": "db1"}] | ||||
|  | ||||
|     def test_connect_different_documents_to_different_database(self): | ||||
|         class History(Document): | ||||
| @@ -134,68 +139,64 @@ class ConnectionTest(unittest.TestCase): | ||||
|         h1 = History1(name="db1").save() | ||||
|         h2 = History2(name="db2").save() | ||||
|  | ||||
|         self.assertEqual(History._collection.database.name, DEFAULT_DATABASE_NAME) | ||||
|         self.assertEqual(History1._collection.database.name, "db1") | ||||
|         self.assertEqual(History2._collection.database.name, "db2") | ||||
|         assert History._collection.database.name == DEFAULT_DATABASE_NAME | ||||
|         assert History1._collection.database.name == "db1" | ||||
|         assert History2._collection.database.name == "db2" | ||||
|  | ||||
|         self.assertEqual( | ||||
|             list(History.objects().as_pymongo()), [{"_id": h.id, "name": "default"}] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             list(History1.objects().as_pymongo()), [{"_id": h1.id, "name": "db1"}] | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             list(History2.objects().as_pymongo()), [{"_id": h2.id, "name": "db2"}] | ||||
|         ) | ||||
|         assert list(History.objects().as_pymongo()) == [ | ||||
|             {"_id": h.id, "name": "default"} | ||||
|         ] | ||||
|         assert list(History1.objects().as_pymongo()) == [{"_id": h1.id, "name": "db1"}] | ||||
|         assert list(History2.objects().as_pymongo()) == [{"_id": h2.id, "name": "db2"}] | ||||
|  | ||||
|     def test_connect_fails_if_connect_2_times_with_default_alias(self): | ||||
|         connect("mongoenginetest") | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure) as ctx_err: | ||||
|         with pytest.raises(ConnectionFailure) as exc_info: | ||||
|             connect("mongoenginetest2") | ||||
|         self.assertEqual( | ||||
|             "A different connection with alias `default` was already registered. Use disconnect() first", | ||||
|             str(ctx_err.exception), | ||||
|         assert ( | ||||
|             "A different connection with alias `default` was already registered. Use disconnect() first" | ||||
|             == str(exc_info.value) | ||||
|         ) | ||||
|  | ||||
|     def test_connect_fails_if_connect_2_times_with_custom_alias(self): | ||||
|         connect("mongoenginetest", alias="alias1") | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure) as ctx_err: | ||||
|         with pytest.raises(ConnectionFailure) as exc_info: | ||||
|             connect("mongoenginetest2", alias="alias1") | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "A different connection with alias `alias1` was already registered. Use disconnect() first", | ||||
|             str(ctx_err.exception), | ||||
|         assert ( | ||||
|             "A different connection with alias `alias1` was already registered. Use disconnect() first" | ||||
|             == str(exc_info.value) | ||||
|         ) | ||||
|  | ||||
|     def test_connect_fails_if_similar_connection_settings_arent_defined_the_same_way( | ||||
|         self | ||||
|         self, | ||||
|     ): | ||||
|         """Intended to keep the detecton function simple but robust""" | ||||
|         db_name = "mongoenginetest" | ||||
|         db_alias = "alias1" | ||||
|         connect(db=db_name, alias=db_alias, host="localhost", port=27017) | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure): | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             connect(host="mongodb://localhost:27017/%s" % db_name, alias=db_alias) | ||||
|  | ||||
|     def test_connect_passes_silently_connect_multiple_times_with_same_config(self): | ||||
|         # test default connection to `test` | ||||
|         connect() | ||||
|         connect() | ||||
|         self.assertEqual(len(mongoengine.connection._connections), 1) | ||||
|         assert len(mongoengine.connection._connections) == 1 | ||||
|         connect("test01", alias="test01") | ||||
|         connect("test01", alias="test01") | ||||
|         self.assertEqual(len(mongoengine.connection._connections), 2) | ||||
|         assert len(mongoengine.connection._connections) == 2 | ||||
|         connect(host="mongodb://localhost:27017/mongoenginetest02", alias="test02") | ||||
|         connect(host="mongodb://localhost:27017/mongoenginetest02", alias="test02") | ||||
|         self.assertEqual(len(mongoengine.connection._connections), 3) | ||||
|         assert len(mongoengine.connection._connections) == 3 | ||||
|  | ||||
|     def test_connect_with_invalid_db_name(self): | ||||
|         """Ensure that connect() method fails fast if db name is invalid | ||||
|         """ | ||||
|         with self.assertRaises(InvalidName): | ||||
|         with pytest.raises(InvalidName): | ||||
|             connect("mongomock://localhost") | ||||
|  | ||||
|     def test_connect_with_db_name_external(self): | ||||
| @@ -205,38 +206,34 @@ class ConnectionTest(unittest.TestCase): | ||||
|         connect("$external") | ||||
|  | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "$external") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "$external" | ||||
|  | ||||
|         connect("$external", alias="testdb") | ||||
|         conn = get_connection("testdb") | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|     def test_connect_with_invalid_db_name_type(self): | ||||
|         """Ensure that connect() method fails fast if db name has invalid type | ||||
|         """ | ||||
|         with self.assertRaises(TypeError): | ||||
|         with pytest.raises(TypeError): | ||||
|             non_string_db_name = ["e. g. list instead of a string"] | ||||
|             connect(non_string_db_name) | ||||
|  | ||||
|     @require_mongomock | ||||
|     def test_connect_in_mocking(self): | ||||
|         """Ensure that the connect() method works properly in mocking. | ||||
|         """ | ||||
|         try: | ||||
|             import mongomock | ||||
|         except ImportError: | ||||
|             raise SkipTest("you need mongomock installed to run this testcase") | ||||
|  | ||||
|         connect("mongoenginetest", host="mongomock://localhost") | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect("mongoenginetest2", host="mongomock://localhost", alias="testdb2") | ||||
|         conn = get_connection("testdb2") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect( | ||||
|             "mongoenginetest3", | ||||
| @@ -245,11 +242,11 @@ class ConnectionTest(unittest.TestCase): | ||||
|             alias="testdb3", | ||||
|         ) | ||||
|         conn = get_connection("testdb3") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect("mongoenginetest4", is_mock=True, alias="testdb4") | ||||
|         conn = get_connection("testdb4") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect( | ||||
|             host="mongodb://localhost:27017/mongoenginetest5", | ||||
| @@ -257,11 +254,11 @@ class ConnectionTest(unittest.TestCase): | ||||
|             alias="testdb5", | ||||
|         ) | ||||
|         conn = get_connection("testdb5") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect(host="mongomock://localhost:27017/mongoenginetest6", alias="testdb6") | ||||
|         conn = get_connection("testdb6") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect( | ||||
|             host="mongomock://localhost:27017/mongoenginetest7", | ||||
| @@ -269,16 +266,12 @@ class ConnectionTest(unittest.TestCase): | ||||
|             alias="testdb7", | ||||
|         ) | ||||
|         conn = get_connection("testdb7") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|     @require_mongomock | ||||
|     def test_default_database_with_mocking(self): | ||||
|         """Ensure that the default database is correctly set when using mongomock. | ||||
|         """ | ||||
|         try: | ||||
|             import mongomock | ||||
|         except ImportError: | ||||
|             raise SkipTest("you need mongomock installed to run this testcase") | ||||
|  | ||||
|         disconnect_all() | ||||
|  | ||||
|         class SomeDocument(Document): | ||||
| @@ -288,37 +281,33 @@ class ConnectionTest(unittest.TestCase): | ||||
|         some_document = SomeDocument() | ||||
|         # database won't exist until we save a document | ||||
|         some_document.save() | ||||
|         self.assertEqual(conn.get_default_database().name, "mongoenginetest") | ||||
|         self.assertEqual(conn.database_names()[0], "mongoenginetest") | ||||
|         assert conn.get_default_database().name == "mongoenginetest" | ||||
|         assert conn.database_names()[0] == "mongoenginetest" | ||||
|  | ||||
|     @require_mongomock | ||||
|     def test_connect_with_host_list(self): | ||||
|         """Ensure that the connect() method works when host is a list | ||||
|  | ||||
|         Uses mongomock to test w/o needing multiple mongod/mongos processes | ||||
|         """ | ||||
|         try: | ||||
|             import mongomock | ||||
|         except ImportError: | ||||
|             raise SkipTest("you need mongomock installed to run this testcase") | ||||
|  | ||||
|         connect(host=["mongomock://localhost"]) | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect(host=["mongodb://localhost"], is_mock=True, alias="testdb2") | ||||
|         conn = get_connection("testdb2") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect(host=["localhost"], is_mock=True, alias="testdb3") | ||||
|         conn = get_connection("testdb3") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect( | ||||
|             host=["mongomock://localhost:27017", "mongomock://localhost:27018"], | ||||
|             alias="testdb4", | ||||
|         ) | ||||
|         conn = get_connection("testdb4") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect( | ||||
|             host=["mongodb://localhost:27017", "mongodb://localhost:27018"], | ||||
| @@ -326,13 +315,13 @@ class ConnectionTest(unittest.TestCase): | ||||
|             alias="testdb5", | ||||
|         ) | ||||
|         conn = get_connection("testdb5") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|         connect( | ||||
|             host=["localhost:27017", "localhost:27018"], is_mock=True, alias="testdb6" | ||||
|         ) | ||||
|         conn = get_connection("testdb6") | ||||
|         self.assertIsInstance(conn, mongomock.MongoClient) | ||||
|         assert isinstance(conn, mongomock.MongoClient) | ||||
|  | ||||
|     def test_disconnect_cleans_globals(self): | ||||
|         """Ensure that the disconnect() method cleans the globals objects""" | ||||
| @@ -342,20 +331,20 @@ class ConnectionTest(unittest.TestCase): | ||||
|  | ||||
|         connect("mongoenginetest") | ||||
|  | ||||
|         self.assertEqual(len(connections), 1) | ||||
|         self.assertEqual(len(dbs), 0) | ||||
|         self.assertEqual(len(connection_settings), 1) | ||||
|         assert len(connections) == 1 | ||||
|         assert len(dbs) == 0 | ||||
|         assert len(connection_settings) == 1 | ||||
|  | ||||
|         class TestDoc(Document): | ||||
|             pass | ||||
|  | ||||
|         TestDoc.drop_collection()  # triggers the db | ||||
|         self.assertEqual(len(dbs), 1) | ||||
|         assert len(dbs) == 1 | ||||
|  | ||||
|         disconnect() | ||||
|         self.assertEqual(len(connections), 0) | ||||
|         self.assertEqual(len(dbs), 0) | ||||
|         self.assertEqual(len(connection_settings), 0) | ||||
|         assert len(connections) == 0 | ||||
|         assert len(dbs) == 0 | ||||
|         assert len(connection_settings) == 0 | ||||
|  | ||||
|     def test_disconnect_cleans_cached_collection_attribute_in_document(self): | ||||
|         """Ensure that the disconnect() method works properly""" | ||||
| @@ -364,22 +353,20 @@ class ConnectionTest(unittest.TestCase): | ||||
|         class History(Document): | ||||
|             pass | ||||
|  | ||||
|         self.assertIsNone(History._collection) | ||||
|         assert History._collection is None | ||||
|  | ||||
|         History.drop_collection() | ||||
|  | ||||
|         History.objects.first()  # will trigger the caching of _collection attribute | ||||
|         self.assertIsNotNone(History._collection) | ||||
|         assert History._collection is not None | ||||
|  | ||||
|         disconnect() | ||||
|  | ||||
|         self.assertIsNone(History._collection) | ||||
|         assert History._collection is None | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure) as ctx_err: | ||||
|         with pytest.raises(ConnectionFailure) as exc_info: | ||||
|             History.objects.first() | ||||
|         self.assertEqual( | ||||
|             "You have not defined a default connection", str(ctx_err.exception) | ||||
|         ) | ||||
|         assert "You have not defined a default connection" == str(exc_info.value) | ||||
|  | ||||
|     def test_connect_disconnect_works_on_same_document(self): | ||||
|         """Ensure that the connect/disconnect works properly with a single Document""" | ||||
| @@ -401,7 +388,7 @@ class ConnectionTest(unittest.TestCase): | ||||
|         disconnect() | ||||
|  | ||||
|         # Make sure save doesnt work at this stage | ||||
|         with self.assertRaises(ConnectionFailure): | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             User(name="Wont work").save() | ||||
|  | ||||
|         # Save in db2 | ||||
| @@ -410,13 +397,13 @@ class ConnectionTest(unittest.TestCase): | ||||
|         disconnect() | ||||
|  | ||||
|         db1_users = list(client[db1].user.find()) | ||||
|         self.assertEqual(db1_users, [{"_id": user1.id, "name": "John is in db1"}]) | ||||
|         assert db1_users == [{"_id": user1.id, "name": "John is in db1"}] | ||||
|         db2_users = list(client[db2].user.find()) | ||||
|         self.assertEqual(db2_users, [{"_id": user2.id, "name": "Bob is in db2"}]) | ||||
|         assert db2_users == [{"_id": user2.id, "name": "Bob is in db2"}] | ||||
|  | ||||
|     def test_disconnect_silently_pass_if_alias_does_not_exist(self): | ||||
|         connections = mongoengine.connection._connections | ||||
|         self.assertEqual(len(connections), 0) | ||||
|         assert len(connections) == 0 | ||||
|         disconnect(alias="not_exist") | ||||
|  | ||||
|     def test_disconnect_all(self): | ||||
| @@ -439,26 +426,26 @@ class ConnectionTest(unittest.TestCase): | ||||
|         History1.drop_collection() | ||||
|         History1.objects.first() | ||||
|  | ||||
|         self.assertIsNotNone(History._collection) | ||||
|         self.assertIsNotNone(History1._collection) | ||||
|         assert History._collection is not None | ||||
|         assert History1._collection is not None | ||||
|  | ||||
|         self.assertEqual(len(connections), 2) | ||||
|         self.assertEqual(len(dbs), 2) | ||||
|         self.assertEqual(len(connection_settings), 2) | ||||
|         assert len(connections) == 2 | ||||
|         assert len(dbs) == 2 | ||||
|         assert len(connection_settings) == 2 | ||||
|  | ||||
|         disconnect_all() | ||||
|  | ||||
|         self.assertIsNone(History._collection) | ||||
|         self.assertIsNone(History1._collection) | ||||
|         assert History._collection is None | ||||
|         assert History1._collection is None | ||||
|  | ||||
|         self.assertEqual(len(connections), 0) | ||||
|         self.assertEqual(len(dbs), 0) | ||||
|         self.assertEqual(len(connection_settings), 0) | ||||
|         assert len(connections) == 0 | ||||
|         assert len(dbs) == 0 | ||||
|         assert len(connection_settings) == 0 | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure): | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             History.objects.first() | ||||
|  | ||||
|         with self.assertRaises(ConnectionFailure): | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             History1.objects.first() | ||||
|  | ||||
|     def test_disconnect_all_silently_pass_if_no_connection_exist(self): | ||||
| @@ -475,7 +462,7 @@ class ConnectionTest(unittest.TestCase): | ||||
|  | ||||
|         expected_connection.server_info() | ||||
|  | ||||
|         self.assertEqual(expected_connection, actual_connection) | ||||
|         assert expected_connection == actual_connection | ||||
|  | ||||
|     def test_connect_uri(self): | ||||
|         """Ensure that the connect() method works properly with URIs.""" | ||||
| @@ -492,11 +479,11 @@ class ConnectionTest(unittest.TestCase): | ||||
|         ) | ||||
|  | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "mongoenginetest") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "mongoenginetest" | ||||
|  | ||||
|         c.admin.system.users.delete_many({}) | ||||
|         c.mongoenginetest.system.users.delete_many({}) | ||||
| @@ -508,11 +495,11 @@ class ConnectionTest(unittest.TestCase): | ||||
|         connect("mongoenginetest", host="mongodb://localhost/") | ||||
|  | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "mongoenginetest") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "mongoenginetest" | ||||
|  | ||||
|     def test_connect_uri_default_db(self): | ||||
|         """Ensure connect() defaults to the right database name if | ||||
| @@ -521,11 +508,11 @@ class ConnectionTest(unittest.TestCase): | ||||
|         connect(host="mongodb://localhost/") | ||||
|  | ||||
|         conn = get_connection() | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "test") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "test" | ||||
|  | ||||
|     def test_uri_without_credentials_doesnt_override_conn_settings(self): | ||||
|         """Ensure connect() uses the username & password params if the URI | ||||
| @@ -538,7 +525,8 @@ class ConnectionTest(unittest.TestCase): | ||||
|         # OperationFailure means that mongoengine attempted authentication | ||||
|         # w/ the provided username/password and failed - that's the desired | ||||
|         # behavior. If the MongoDB URI would override the credentials | ||||
|         self.assertRaises(OperationFailure, get_db) | ||||
|         with pytest.raises(OperationFailure): | ||||
|             get_db() | ||||
|  | ||||
|     def test_connect_uri_with_authsource(self): | ||||
|         """Ensure that the connect() method works well with `authSource` | ||||
| @@ -556,7 +544,8 @@ class ConnectionTest(unittest.TestCase): | ||||
|             alias="test1", | ||||
|             host="mongodb://username2:password@localhost/mongoenginetest", | ||||
|         ) | ||||
|         self.assertRaises(OperationFailure, test_conn.server_info) | ||||
|         with pytest.raises(OperationFailure): | ||||
|             test_conn.server_info() | ||||
|  | ||||
|         # Authentication succeeds with "authSource" | ||||
|         authd_conn = connect( | ||||
| @@ -568,8 +557,8 @@ class ConnectionTest(unittest.TestCase): | ||||
|             ), | ||||
|         ) | ||||
|         db = get_db("test2") | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "mongoenginetest") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "mongoenginetest" | ||||
|  | ||||
|         # Clear all users | ||||
|         authd_conn.admin.system.users.delete_many({}) | ||||
| @@ -579,13 +568,14 @@ class ConnectionTest(unittest.TestCase): | ||||
|         """ | ||||
|         register_connection("testdb", "mongoenginetest2") | ||||
|  | ||||
|         self.assertRaises(ConnectionFailure, get_connection) | ||||
|         with pytest.raises(ConnectionFailure): | ||||
|             get_connection() | ||||
|         conn = get_connection("testdb") | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|         db = get_db("testdb") | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "mongoenginetest2") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "mongoenginetest2" | ||||
|  | ||||
|     def test_register_connection_defaults(self): | ||||
|         """Ensure that defaults are used when the host and port are None. | ||||
| @@ -593,18 +583,18 @@ class ConnectionTest(unittest.TestCase): | ||||
|         register_connection("testdb", "mongoenginetest", host=None, port=None) | ||||
|  | ||||
|         conn = get_connection("testdb") | ||||
|         self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) | ||||
|         assert isinstance(conn, pymongo.mongo_client.MongoClient) | ||||
|  | ||||
|     def test_connection_kwargs(self): | ||||
|         """Ensure that connection kwargs get passed to pymongo.""" | ||||
|         connect("mongoenginetest", alias="t1", tz_aware=True) | ||||
|         conn = get_connection("t1") | ||||
|  | ||||
|         self.assertTrue(get_tz_awareness(conn)) | ||||
|         assert get_tz_awareness(conn) | ||||
|  | ||||
|         connect("mongoenginetest2", alias="t2") | ||||
|         conn = get_connection("t2") | ||||
|         self.assertFalse(get_tz_awareness(conn)) | ||||
|         assert not get_tz_awareness(conn) | ||||
|  | ||||
|     def test_connection_pool_via_kwarg(self): | ||||
|         """Ensure we can specify a max connection pool size using | ||||
| @@ -615,7 +605,7 @@ class ConnectionTest(unittest.TestCase): | ||||
|         conn = connect( | ||||
|             "mongoenginetest", alias="max_pool_size_via_kwarg", **pool_size_kwargs | ||||
|         ) | ||||
|         self.assertEqual(conn.max_pool_size, 100) | ||||
|         assert conn.max_pool_size == 100 | ||||
|  | ||||
|     def test_connection_pool_via_uri(self): | ||||
|         """Ensure we can specify a max connection pool size using | ||||
| @@ -625,16 +615,18 @@ class ConnectionTest(unittest.TestCase): | ||||
|             host="mongodb://localhost/test?maxpoolsize=100", | ||||
|             alias="max_pool_size_via_uri", | ||||
|         ) | ||||
|         self.assertEqual(conn.max_pool_size, 100) | ||||
|         assert conn.max_pool_size == 100 | ||||
|  | ||||
|     def test_write_concern(self): | ||||
|         """Ensure write concern can be specified in connect() via | ||||
|         a kwarg or as part of the connection URI. | ||||
|         """ | ||||
|         conn1 = connect(alias="conn1", host="mongodb://localhost/testing?w=1&j=true") | ||||
|         conn2 = connect("testing", alias="conn2", w=1, j=True) | ||||
|         self.assertEqual(conn1.write_concern.document, {"w": 1, "j": True}) | ||||
|         self.assertEqual(conn2.write_concern.document, {"w": 1, "j": True}) | ||||
|         conn1 = connect( | ||||
|             alias="conn1", host="mongodb://localhost/testing?w=1&journal=true" | ||||
|         ) | ||||
|         conn2 = connect("testing", alias="conn2", w=1, journal=True) | ||||
|         assert conn1.write_concern.document == {"w": 1, "j": True} | ||||
|         assert conn2.write_concern.document == {"w": 1, "j": True} | ||||
|  | ||||
|     def test_connect_with_replicaset_via_uri(self): | ||||
|         """Ensure connect() works when specifying a replicaSet via the | ||||
| @@ -642,18 +634,18 @@ class ConnectionTest(unittest.TestCase): | ||||
|         """ | ||||
|         c = connect(host="mongodb://localhost/test?replicaSet=local-rs") | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "test") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "test" | ||||
|  | ||||
|     def test_connect_with_replicaset_via_kwargs(self): | ||||
|         """Ensure connect() works when specifying a replicaSet via the | ||||
|         connection kwargs | ||||
|         """ | ||||
|         c = connect(replicaset="local-rs") | ||||
|         self.assertEqual(c._MongoClient__options.replica_set_name, "local-rs") | ||||
|         assert c._MongoClient__options.replica_set_name == "local-rs" | ||||
|         db = get_db() | ||||
|         self.assertIsInstance(db, pymongo.database.Database) | ||||
|         self.assertEqual(db.name, "test") | ||||
|         assert isinstance(db, pymongo.database.Database) | ||||
|         assert db.name == "test" | ||||
|  | ||||
|     def test_connect_tz_aware(self): | ||||
|         connect("mongoenginetest", tz_aware=True) | ||||
| @@ -666,13 +658,13 @@ class ConnectionTest(unittest.TestCase): | ||||
|         DateDoc(the_date=d).save() | ||||
|  | ||||
|         date_doc = DateDoc.objects.first() | ||||
|         self.assertEqual(d, date_doc.the_date) | ||||
|         assert d == date_doc.the_date | ||||
|  | ||||
|     def test_read_preference_from_parse(self): | ||||
|         conn = connect( | ||||
|             host="mongodb://a1.vpc,a2.vpc,a3.vpc/prod?readPreference=secondaryPreferred" | ||||
|         ) | ||||
|         self.assertEqual(conn.read_preference, ReadPreference.SECONDARY_PREFERRED) | ||||
|         assert conn.read_preference == ReadPreference.SECONDARY_PREFERRED | ||||
|  | ||||
|     def test_multiple_connection_settings(self): | ||||
|         connect("mongoenginetest", alias="t1", host="localhost") | ||||
| @@ -680,27 +672,27 @@ class ConnectionTest(unittest.TestCase): | ||||
|         connect("mongoenginetest2", alias="t2", host="127.0.0.1") | ||||
|  | ||||
|         mongo_connections = mongoengine.connection._connections | ||||
|         self.assertEqual(len(mongo_connections.items()), 2) | ||||
|         self.assertIn("t1", mongo_connections.keys()) | ||||
|         self.assertIn("t2", mongo_connections.keys()) | ||||
|         assert len(mongo_connections.items()) == 2 | ||||
|         assert "t1" in mongo_connections.keys() | ||||
|         assert "t2" in mongo_connections.keys() | ||||
|  | ||||
|         # Handle PyMongo 3+ Async Connection | ||||
|         # Ensure we are connected, throws ServerSelectionTimeoutError otherwise. | ||||
|         # Purposely not catching exception to fail test if thrown. | ||||
|         mongo_connections["t1"].server_info() | ||||
|         mongo_connections["t2"].server_info() | ||||
|         self.assertEqual(mongo_connections["t1"].address[0], "localhost") | ||||
|         self.assertEqual(mongo_connections["t2"].address[0], "127.0.0.1") | ||||
|         assert mongo_connections["t1"].address[0] == "localhost" | ||||
|         assert mongo_connections["t2"].address[0] == "127.0.0.1" | ||||
|  | ||||
|     def test_connect_2_databases_uses_same_client_if_only_dbname_differs(self): | ||||
|         c1 = connect(alias="testdb1", db="testdb1") | ||||
|         c2 = connect(alias="testdb2", db="testdb2") | ||||
|         self.assertIs(c1, c2) | ||||
|         assert c1 is c2 | ||||
|  | ||||
|     def test_connect_2_databases_uses_different_client_if_different_parameters(self): | ||||
|         c1 = connect(alias="testdb1", db="testdb1", username="u1") | ||||
|         c2 = connect(alias="testdb2", db="testdb2", username="u2") | ||||
|         self.assertIsNot(c1, c2) | ||||
|         assert c1 is not c2 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,18 +1,20 @@ | ||||
| import unittest | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import * | ||||
| from mongoengine.connection import get_db | ||||
| from mongoengine.context_managers import ( | ||||
|     switch_db, | ||||
|     switch_collection, | ||||
|     no_sub_classes, | ||||
|     no_dereference, | ||||
|     no_sub_classes, | ||||
|     query_counter, | ||||
|     switch_collection, | ||||
|     switch_db, | ||||
| ) | ||||
| from mongoengine.pymongo_support import count_documents | ||||
|  | ||||
|  | ||||
| class ContextManagersTest(unittest.TestCase): | ||||
| class TestContextManagers: | ||||
|     def test_switch_db_context_manager(self): | ||||
|         connect("mongoenginetest") | ||||
|         register_connection("testdb-1", "mongoenginetest2") | ||||
| @@ -23,20 +25,20 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         Group.drop_collection() | ||||
|  | ||||
|         Group(name="hello - default").save() | ||||
|         self.assertEqual(1, Group.objects.count()) | ||||
|         assert 1 == Group.objects.count() | ||||
|  | ||||
|         with switch_db(Group, "testdb-1") as Group: | ||||
|  | ||||
|             self.assertEqual(0, Group.objects.count()) | ||||
|             assert 0 == Group.objects.count() | ||||
|  | ||||
|             Group(name="hello").save() | ||||
|  | ||||
|             self.assertEqual(1, Group.objects.count()) | ||||
|             assert 1 == Group.objects.count() | ||||
|  | ||||
|             Group.drop_collection() | ||||
|             self.assertEqual(0, Group.objects.count()) | ||||
|             assert 0 == Group.objects.count() | ||||
|  | ||||
|         self.assertEqual(1, Group.objects.count()) | ||||
|         assert 1 == Group.objects.count() | ||||
|  | ||||
|     def test_switch_collection_context_manager(self): | ||||
|         connect("mongoenginetest") | ||||
| @@ -51,20 +53,20 @@ class ContextManagersTest(unittest.TestCase): | ||||
|             Group.drop_collection()  # drops in group1 | ||||
|  | ||||
|         Group(name="hello - group").save() | ||||
|         self.assertEqual(1, Group.objects.count()) | ||||
|         assert 1 == Group.objects.count() | ||||
|  | ||||
|         with switch_collection(Group, "group1") as Group: | ||||
|  | ||||
|             self.assertEqual(0, Group.objects.count()) | ||||
|             assert 0 == Group.objects.count() | ||||
|  | ||||
|             Group(name="hello - group1").save() | ||||
|  | ||||
|             self.assertEqual(1, Group.objects.count()) | ||||
|             assert 1 == Group.objects.count() | ||||
|  | ||||
|             Group.drop_collection() | ||||
|             self.assertEqual(0, Group.objects.count()) | ||||
|             assert 0 == Group.objects.count() | ||||
|  | ||||
|         self.assertEqual(1, Group.objects.count()) | ||||
|         assert 1 == Group.objects.count() | ||||
|  | ||||
|     def test_no_dereference_context_manager_object_id(self): | ||||
|         """Ensure that DBRef items in ListFields aren't dereferenced. | ||||
| @@ -89,20 +91,20 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         Group(ref=user, members=User.objects, generic=user).save() | ||||
|  | ||||
|         with no_dereference(Group) as NoDeRefGroup: | ||||
|             self.assertTrue(Group._fields["members"]._auto_dereference) | ||||
|             self.assertFalse(NoDeRefGroup._fields["members"]._auto_dereference) | ||||
|             assert Group._fields["members"]._auto_dereference | ||||
|             assert not NoDeRefGroup._fields["members"]._auto_dereference | ||||
|  | ||||
|         with no_dereference(Group) as Group: | ||||
|             group = Group.objects.first() | ||||
|             for m in group.members: | ||||
|                 self.assertNotIsInstance(m, User) | ||||
|             self.assertNotIsInstance(group.ref, User) | ||||
|             self.assertNotIsInstance(group.generic, User) | ||||
|                 assert not isinstance(m, User) | ||||
|             assert not isinstance(group.ref, User) | ||||
|             assert not isinstance(group.generic, User) | ||||
|  | ||||
|         for m in group.members: | ||||
|             self.assertIsInstance(m, User) | ||||
|         self.assertIsInstance(group.ref, User) | ||||
|         self.assertIsInstance(group.generic, User) | ||||
|             assert isinstance(m, User) | ||||
|         assert isinstance(group.ref, User) | ||||
|         assert isinstance(group.generic, User) | ||||
|  | ||||
|     def test_no_dereference_context_manager_dbref(self): | ||||
|         """Ensure that DBRef items in ListFields aren't dereferenced. | ||||
| @@ -127,18 +129,18 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         Group(ref=user, members=User.objects, generic=user).save() | ||||
|  | ||||
|         with no_dereference(Group) as NoDeRefGroup: | ||||
|             self.assertTrue(Group._fields["members"]._auto_dereference) | ||||
|             self.assertFalse(NoDeRefGroup._fields["members"]._auto_dereference) | ||||
|             assert Group._fields["members"]._auto_dereference | ||||
|             assert not NoDeRefGroup._fields["members"]._auto_dereference | ||||
|  | ||||
|         with no_dereference(Group) as Group: | ||||
|             group = Group.objects.first() | ||||
|             self.assertTrue(all([not isinstance(m, User) for m in group.members])) | ||||
|             self.assertNotIsInstance(group.ref, User) | ||||
|             self.assertNotIsInstance(group.generic, User) | ||||
|             assert all([not isinstance(m, User) for m in group.members]) | ||||
|             assert not isinstance(group.ref, User) | ||||
|             assert not isinstance(group.generic, User) | ||||
|  | ||||
|         self.assertTrue(all([isinstance(m, User) for m in group.members])) | ||||
|         self.assertIsInstance(group.ref, User) | ||||
|         self.assertIsInstance(group.generic, User) | ||||
|         assert all([isinstance(m, User) for m in group.members]) | ||||
|         assert isinstance(group.ref, User) | ||||
|         assert isinstance(group.generic, User) | ||||
|  | ||||
|     def test_no_sub_classes(self): | ||||
|         class A(Document): | ||||
| @@ -159,32 +161,32 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         B(x=30).save() | ||||
|         C(x=40).save() | ||||
|  | ||||
|         self.assertEqual(A.objects.count(), 5) | ||||
|         self.assertEqual(B.objects.count(), 3) | ||||
|         self.assertEqual(C.objects.count(), 1) | ||||
|         assert A.objects.count() == 5 | ||||
|         assert B.objects.count() == 3 | ||||
|         assert C.objects.count() == 1 | ||||
|  | ||||
|         with no_sub_classes(A): | ||||
|             self.assertEqual(A.objects.count(), 2) | ||||
|             assert A.objects.count() == 2 | ||||
|  | ||||
|             for obj in A.objects: | ||||
|                 self.assertEqual(obj.__class__, A) | ||||
|                 assert obj.__class__ == A | ||||
|  | ||||
|         with no_sub_classes(B): | ||||
|             self.assertEqual(B.objects.count(), 2) | ||||
|             assert B.objects.count() == 2 | ||||
|  | ||||
|             for obj in B.objects: | ||||
|                 self.assertEqual(obj.__class__, B) | ||||
|                 assert obj.__class__ == B | ||||
|  | ||||
|         with no_sub_classes(C): | ||||
|             self.assertEqual(C.objects.count(), 1) | ||||
|             assert C.objects.count() == 1 | ||||
|  | ||||
|             for obj in C.objects: | ||||
|                 self.assertEqual(obj.__class__, C) | ||||
|                 assert obj.__class__ == C | ||||
|  | ||||
|         # Confirm context manager exit correctly | ||||
|         self.assertEqual(A.objects.count(), 5) | ||||
|         self.assertEqual(B.objects.count(), 3) | ||||
|         self.assertEqual(C.objects.count(), 1) | ||||
|         assert A.objects.count() == 5 | ||||
|         assert B.objects.count() == 3 | ||||
|         assert C.objects.count() == 1 | ||||
|  | ||||
|     def test_no_sub_classes_modification_to_document_class_are_temporary(self): | ||||
|         class A(Document): | ||||
| @@ -194,27 +196,26 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         class B(A): | ||||
|             z = IntField() | ||||
|  | ||||
|         self.assertEqual(A._subclasses, ("A", "A.B")) | ||||
|         assert A._subclasses == ("A", "A.B") | ||||
|         with no_sub_classes(A): | ||||
|             self.assertEqual(A._subclasses, ("A",)) | ||||
|         self.assertEqual(A._subclasses, ("A", "A.B")) | ||||
|             assert A._subclasses == ("A",) | ||||
|         assert A._subclasses == ("A", "A.B") | ||||
|  | ||||
|         self.assertEqual(B._subclasses, ("A.B",)) | ||||
|         assert B._subclasses == ("A.B",) | ||||
|         with no_sub_classes(B): | ||||
|             self.assertEqual(B._subclasses, ("A.B",)) | ||||
|         self.assertEqual(B._subclasses, ("A.B",)) | ||||
|             assert B._subclasses == ("A.B",) | ||||
|         assert B._subclasses == ("A.B",) | ||||
|  | ||||
|     def test_no_subclass_context_manager_does_not_swallow_exception(self): | ||||
|         class User(Document): | ||||
|             name = StringField() | ||||
|  | ||||
|         with self.assertRaises(TypeError): | ||||
|         with pytest.raises(TypeError): | ||||
|             with no_sub_classes(User): | ||||
|                 raise TypeError() | ||||
|  | ||||
|     def test_query_counter_does_not_swallow_exception(self): | ||||
|  | ||||
|         with self.assertRaises(TypeError): | ||||
|         with pytest.raises(TypeError): | ||||
|             with query_counter() as q: | ||||
|                 raise TypeError() | ||||
|  | ||||
| @@ -227,10 +228,10 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         try: | ||||
|             NEW_LEVEL = 1 | ||||
|             db.set_profiling_level(NEW_LEVEL) | ||||
|             self.assertEqual(db.profiling_level(), NEW_LEVEL) | ||||
|             assert db.profiling_level() == NEW_LEVEL | ||||
|             with query_counter() as q: | ||||
|                 self.assertEqual(db.profiling_level(), 2) | ||||
|             self.assertEqual(db.profiling_level(), NEW_LEVEL) | ||||
|                 assert db.profiling_level() == 2 | ||||
|             assert db.profiling_level() == NEW_LEVEL | ||||
|         except Exception: | ||||
|             db.set_profiling_level( | ||||
|                 initial_profiling_level | ||||
| @@ -255,33 +256,77 @@ class ContextManagersTest(unittest.TestCase): | ||||
|  | ||||
|         counter = 0 | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, counter) | ||||
|             self.assertEqual( | ||||
|                 q, counter | ||||
|             )  # Ensures previous count query did not get counted | ||||
|             assert q == counter | ||||
|             assert q == counter  # Ensures previous count query did not get counted | ||||
|  | ||||
|             for _ in range(10): | ||||
|                 issue_1_insert_query() | ||||
|                 counter += 1 | ||||
|             self.assertEqual(q, counter) | ||||
|             assert q == counter | ||||
|  | ||||
|             for _ in range(4): | ||||
|                 issue_1_find_query() | ||||
|                 counter += 1 | ||||
|             self.assertEqual(q, counter) | ||||
|             assert q == counter | ||||
|  | ||||
|             for _ in range(3): | ||||
|                 issue_1_count_query() | ||||
|                 counter += 1 | ||||
|             self.assertEqual(q, counter) | ||||
|             assert q == counter | ||||
|  | ||||
|             self.assertEqual(int(q), counter)  # test __int__ | ||||
|             self.assertEqual(repr(q), str(int(q)))  # test __repr__ | ||||
|             self.assertGreater(q, -1)  # test __gt__ | ||||
|             self.assertGreaterEqual(q, int(q))  # test __gte__ | ||||
|             self.assertNotEqual(q, -1) | ||||
|             self.assertLess(q, 1000) | ||||
|             self.assertLessEqual(q, int(q)) | ||||
|             assert int(q) == counter  # test __int__ | ||||
|             assert repr(q) == str(int(q))  # test __repr__ | ||||
|             assert q > -1  # test __gt__ | ||||
|             assert q >= int(q)  # test __gte__ | ||||
|             assert q != -1 | ||||
|             assert q < 1000 | ||||
|             assert q <= int(q) | ||||
|  | ||||
|     def test_query_counter_alias(self): | ||||
|         """query_counter works properly with db aliases?""" | ||||
|         # Register a connection with db_alias testdb-1 | ||||
|         register_connection("testdb-1", "mongoenginetest2") | ||||
|  | ||||
|         class A(Document): | ||||
|             """Uses default db_alias""" | ||||
|  | ||||
|             name = StringField() | ||||
|  | ||||
|         class B(Document): | ||||
|             """Uses testdb-1 db_alias""" | ||||
|  | ||||
|             name = StringField() | ||||
|             meta = {"db_alias": "testdb-1"} | ||||
|  | ||||
|         A.drop_collection() | ||||
|         B.drop_collection() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             assert q == 0 | ||||
|             A.objects.create(name="A") | ||||
|             assert q == 1 | ||||
|             a = A.objects.first() | ||||
|             assert q == 2 | ||||
|             a.name = "Test A" | ||||
|             a.save() | ||||
|             assert q == 3 | ||||
|             # querying the other db should'nt alter the counter | ||||
|             B.objects().first() | ||||
|             assert q == 3 | ||||
|  | ||||
|         with query_counter(alias="testdb-1") as q: | ||||
|             assert q == 0 | ||||
|             B.objects.create(name="B") | ||||
|             assert q == 1 | ||||
|             b = B.objects.first() | ||||
|             assert q == 2 | ||||
|             b.name = "Test B" | ||||
|             b.save() | ||||
|             assert b.name == "Test B" | ||||
|             assert q == 3 | ||||
|             # querying the other db should'nt alter the counter | ||||
|             A.objects().first() | ||||
|             assert q == 3 | ||||
|  | ||||
|     def test_query_counter_counts_getmore_queries(self): | ||||
|         connect("mongoenginetest") | ||||
| @@ -296,9 +341,9 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         )  # first batch of documents contains 101 documents | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|             list(collection.find()) | ||||
|             self.assertEqual(q, 2)  # 1st select + 1 getmore | ||||
|             assert q == 2  # 1st select + 1 getmore | ||||
|  | ||||
|     def test_query_counter_ignores_particular_queries(self): | ||||
|         connect("mongoenginetest") | ||||
| @@ -308,18 +353,18 @@ class ContextManagersTest(unittest.TestCase): | ||||
|         collection.insert_many([{"test": "garbage %s" % i} for i in range(10)]) | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|             cursor = collection.find() | ||||
|             self.assertEqual(q, 0)  # cursor wasn't opened yet | ||||
|             assert q == 0  # cursor wasn't opened yet | ||||
|             _ = next(cursor)  # opens the cursor and fires the find query | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             cursor.close()  # issues a `killcursors` query that is ignored by the context | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|             _ = ( | ||||
|                 db.system.indexes.find_one() | ||||
|             )  # queries on db.system.indexes are ignored as well | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| import unittest | ||||
|  | ||||
| import pytest | ||||
| from six import iterkeys | ||||
|  | ||||
| from mongoengine import Document | ||||
| from mongoengine.base.datastructures import StrictDict, BaseList, BaseDict | ||||
| from mongoengine.base.datastructures import BaseDict, BaseList, StrictDict | ||||
|  | ||||
|  | ||||
| class DocumentStub(object): | ||||
| @@ -13,15 +15,15 @@ class DocumentStub(object): | ||||
|         self._changed_fields.append(key) | ||||
|  | ||||
|  | ||||
| class TestBaseDict(unittest.TestCase): | ||||
| class TestBaseDict: | ||||
|     @staticmethod | ||||
|     def _get_basedict(dict_items): | ||||
|         """Get a BaseList bound to a fake document instance""" | ||||
|         fake_doc = DocumentStub() | ||||
|         base_list = BaseDict(dict_items, instance=None, name="my_name") | ||||
|         base_list._instance = ( | ||||
|             fake_doc | ||||
|         )  # hack to inject the mock, it does not work in the constructor | ||||
|             fake_doc  # hack to inject the mock, it does not work in the constructor | ||||
|         ) | ||||
|         return base_list | ||||
|  | ||||
|     def test___init___(self): | ||||
| @@ -31,48 +33,48 @@ class TestBaseDict(unittest.TestCase): | ||||
|         dict_items = {"k": "v"} | ||||
|         doc = MyDoc() | ||||
|         base_dict = BaseDict(dict_items, instance=doc, name="my_name") | ||||
|         self.assertIsInstance(base_dict._instance, Document) | ||||
|         self.assertEqual(base_dict._name, "my_name") | ||||
|         self.assertEqual(base_dict, dict_items) | ||||
|         assert isinstance(base_dict._instance, Document) | ||||
|         assert base_dict._name == "my_name" | ||||
|         assert base_dict == dict_items | ||||
|  | ||||
|     def test_setdefault_calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         base_dict.setdefault("k", "v") | ||||
|         self.assertEqual(base_dict._instance._changed_fields, [base_dict._name]) | ||||
|         assert base_dict._instance._changed_fields == [base_dict._name] | ||||
|  | ||||
|     def test_popitems_calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({"k": "v"}) | ||||
|         self.assertEqual(base_dict.popitem(), ("k", "v")) | ||||
|         self.assertEqual(base_dict._instance._changed_fields, [base_dict._name]) | ||||
|         self.assertFalse(base_dict) | ||||
|         assert base_dict.popitem() == ("k", "v") | ||||
|         assert base_dict._instance._changed_fields == [base_dict._name] | ||||
|         assert not base_dict | ||||
|  | ||||
|     def test_pop_calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({"k": "v"}) | ||||
|         self.assertEqual(base_dict.pop("k"), "v") | ||||
|         self.assertEqual(base_dict._instance._changed_fields, [base_dict._name]) | ||||
|         self.assertFalse(base_dict) | ||||
|         assert base_dict.pop("k") == "v" | ||||
|         assert base_dict._instance._changed_fields == [base_dict._name] | ||||
|         assert not base_dict | ||||
|  | ||||
|     def test_pop_calls_does_not_mark_as_changed_when_it_fails(self): | ||||
|         base_dict = self._get_basedict({"k": "v"}) | ||||
|         with self.assertRaises(KeyError): | ||||
|         with pytest.raises(KeyError): | ||||
|             base_dict.pop("X") | ||||
|         self.assertFalse(base_dict._instance._changed_fields) | ||||
|         assert not base_dict._instance._changed_fields | ||||
|  | ||||
|     def test_clear_calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({"k": "v"}) | ||||
|         base_dict.clear() | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_dict, {}) | ||||
|         assert base_dict._instance._changed_fields == ["my_name"] | ||||
|         assert base_dict == {} | ||||
|  | ||||
|     def test___delitem___calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({"k": "v"}) | ||||
|         del base_dict["k"] | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name.k"]) | ||||
|         self.assertEqual(base_dict, {}) | ||||
|         assert base_dict._instance._changed_fields == ["my_name.k"] | ||||
|         assert base_dict == {} | ||||
|  | ||||
|     def test___getitem____KeyError(self): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         with self.assertRaises(KeyError): | ||||
|         with pytest.raises(KeyError): | ||||
|             base_dict["new"] | ||||
|  | ||||
|     def test___getitem____simple_value(self): | ||||
| @@ -82,62 +84,62 @@ class TestBaseDict(unittest.TestCase): | ||||
|     def test___getitem____sublist_gets_converted_to_BaseList(self): | ||||
|         base_dict = self._get_basedict({"k": [0, 1, 2]}) | ||||
|         sub_list = base_dict["k"] | ||||
|         self.assertEqual(sub_list, [0, 1, 2]) | ||||
|         self.assertIsInstance(sub_list, BaseList) | ||||
|         self.assertIs(sub_list._instance, base_dict._instance) | ||||
|         self.assertEqual(sub_list._name, "my_name.k") | ||||
|         self.assertEqual(base_dict._instance._changed_fields, []) | ||||
|         assert sub_list == [0, 1, 2] | ||||
|         assert isinstance(sub_list, BaseList) | ||||
|         assert sub_list._instance is base_dict._instance | ||||
|         assert sub_list._name == "my_name.k" | ||||
|         assert base_dict._instance._changed_fields == [] | ||||
|  | ||||
|         # Challenge mark_as_changed from sublist | ||||
|         sub_list[1] = None | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name.k.1"]) | ||||
|         assert base_dict._instance._changed_fields == ["my_name.k.1"] | ||||
|  | ||||
|     def test___getitem____subdict_gets_converted_to_BaseDict(self): | ||||
|         base_dict = self._get_basedict({"k": {"subk": "subv"}}) | ||||
|         sub_dict = base_dict["k"] | ||||
|         self.assertEqual(sub_dict, {"subk": "subv"}) | ||||
|         self.assertIsInstance(sub_dict, BaseDict) | ||||
|         self.assertIs(sub_dict._instance, base_dict._instance) | ||||
|         self.assertEqual(sub_dict._name, "my_name.k") | ||||
|         self.assertEqual(base_dict._instance._changed_fields, []) | ||||
|         assert sub_dict == {"subk": "subv"} | ||||
|         assert isinstance(sub_dict, BaseDict) | ||||
|         assert sub_dict._instance is base_dict._instance | ||||
|         assert sub_dict._name == "my_name.k" | ||||
|         assert base_dict._instance._changed_fields == [] | ||||
|  | ||||
|         # Challenge mark_as_changed from subdict | ||||
|         sub_dict["subk"] = None | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name.k.subk"]) | ||||
|         assert base_dict._instance._changed_fields == ["my_name.k.subk"] | ||||
|  | ||||
|     def test_get_sublist_gets_converted_to_BaseList_just_like__getitem__(self): | ||||
|         base_dict = self._get_basedict({"k": [0, 1, 2]}) | ||||
|         sub_list = base_dict.get("k") | ||||
|         self.assertEqual(sub_list, [0, 1, 2]) | ||||
|         self.assertIsInstance(sub_list, BaseList) | ||||
|         assert sub_list == [0, 1, 2] | ||||
|         assert isinstance(sub_list, BaseList) | ||||
|  | ||||
|     def test_get_returns_the_same_as___getitem__(self): | ||||
|         base_dict = self._get_basedict({"k": [0, 1, 2]}) | ||||
|         get_ = base_dict.get("k") | ||||
|         getitem_ = base_dict["k"] | ||||
|         self.assertEqual(get_, getitem_) | ||||
|         assert get_ == getitem_ | ||||
|  | ||||
|     def test_get_default(self): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         sentinel = object() | ||||
|         self.assertEqual(base_dict.get("new"), None) | ||||
|         self.assertIs(base_dict.get("new", sentinel), sentinel) | ||||
|         assert base_dict.get("new") is None | ||||
|         assert base_dict.get("new", sentinel) is sentinel | ||||
|  | ||||
|     def test___setitem___calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         base_dict["k"] = "v" | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name.k"]) | ||||
|         self.assertEqual(base_dict, {"k": "v"}) | ||||
|         assert base_dict._instance._changed_fields == ["my_name.k"] | ||||
|         assert base_dict == {"k": "v"} | ||||
|  | ||||
|     def test_update_calls_mark_as_changed(self): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         base_dict.update({"k": "v"}) | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name"]) | ||||
|         assert base_dict._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test___setattr____not_tracked_by_changes(self): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         base_dict.a_new_attr = "test" | ||||
|         self.assertEqual(base_dict._instance._changed_fields, []) | ||||
|         assert base_dict._instance._changed_fields == [] | ||||
|  | ||||
|     def test___delattr____tracked_by_changes(self): | ||||
|         # This is probably a bug as __setattr__ is not tracked | ||||
| @@ -146,18 +148,18 @@ class TestBaseDict(unittest.TestCase): | ||||
|         base_dict = self._get_basedict({}) | ||||
|         base_dict.a_new_attr = "test" | ||||
|         del base_dict.a_new_attr | ||||
|         self.assertEqual(base_dict._instance._changed_fields, ["my_name.a_new_attr"]) | ||||
|         assert base_dict._instance._changed_fields == ["my_name.a_new_attr"] | ||||
|  | ||||
|  | ||||
| class TestBaseList(unittest.TestCase): | ||||
| class TestBaseList: | ||||
|     @staticmethod | ||||
|     def _get_baselist(list_items): | ||||
|         """Get a BaseList bound to a fake document instance""" | ||||
|         fake_doc = DocumentStub() | ||||
|         base_list = BaseList(list_items, instance=None, name="my_name") | ||||
|         base_list._instance = ( | ||||
|             fake_doc | ||||
|         )  # hack to inject the mock, it does not work in the constructor | ||||
|             fake_doc  # hack to inject the mock, it does not work in the constructor | ||||
|         ) | ||||
|         return base_list | ||||
|  | ||||
|     def test___init___(self): | ||||
| @@ -167,14 +169,14 @@ class TestBaseList(unittest.TestCase): | ||||
|         list_items = [True] | ||||
|         doc = MyDoc() | ||||
|         base_list = BaseList(list_items, instance=doc, name="my_name") | ||||
|         self.assertIsInstance(base_list._instance, Document) | ||||
|         self.assertEqual(base_list._name, "my_name") | ||||
|         self.assertEqual(base_list, list_items) | ||||
|         assert isinstance(base_list._instance, Document) | ||||
|         assert base_list._name == "my_name" | ||||
|         assert base_list == list_items | ||||
|  | ||||
|     def test___iter__(self): | ||||
|         values = [True, False, True, False] | ||||
|         base_list = BaseList(values, instance=None, name="my_name") | ||||
|         self.assertEqual(values, list(base_list)) | ||||
|         assert values == list(base_list) | ||||
|  | ||||
|     def test___iter___allow_modification_while_iterating_withou_error(self): | ||||
|         # regular list allows for this, thus this subclass must comply to that | ||||
| @@ -185,9 +187,9 @@ class TestBaseList(unittest.TestCase): | ||||
|  | ||||
|     def test_append_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([]) | ||||
|         self.assertFalse(base_list._instance._changed_fields) | ||||
|         assert not base_list._instance._changed_fields | ||||
|         base_list.append(True) | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_subclass_append(self): | ||||
|         # Due to the way mark_as_changed_wrapper is implemented | ||||
| @@ -200,85 +202,85 @@ class TestBaseList(unittest.TestCase): | ||||
|  | ||||
|     def test___getitem__using_simple_index(self): | ||||
|         base_list = self._get_baselist([0, 1, 2]) | ||||
|         self.assertEqual(base_list[0], 0) | ||||
|         self.assertEqual(base_list[1], 1) | ||||
|         self.assertEqual(base_list[-1], 2) | ||||
|         assert base_list[0] == 0 | ||||
|         assert base_list[1] == 1 | ||||
|         assert base_list[-1] == 2 | ||||
|  | ||||
|     def test___getitem__using_slice(self): | ||||
|         base_list = self._get_baselist([0, 1, 2]) | ||||
|         self.assertEqual(base_list[1:3], [1, 2]) | ||||
|         self.assertEqual(base_list[0:3:2], [0, 2]) | ||||
|         assert base_list[1:3] == [1, 2] | ||||
|         assert base_list[0:3:2] == [0, 2] | ||||
|  | ||||
|     def test___getitem___using_slice_returns_list(self): | ||||
|         # Bug: using slice does not properly handles the instance | ||||
|         # and mark_as_changed behaviour. | ||||
|         base_list = self._get_baselist([0, 1, 2]) | ||||
|         sliced = base_list[1:3] | ||||
|         self.assertEqual(sliced, [1, 2]) | ||||
|         self.assertIsInstance(sliced, list) | ||||
|         self.assertEqual(base_list._instance._changed_fields, []) | ||||
|         assert sliced == [1, 2] | ||||
|         assert isinstance(sliced, list) | ||||
|         assert base_list._instance._changed_fields == [] | ||||
|  | ||||
|     def test___getitem__sublist_returns_BaseList_bound_to_instance(self): | ||||
|         base_list = self._get_baselist([[1, 2], [3, 4]]) | ||||
|         sub_list = base_list[0] | ||||
|         self.assertEqual(sub_list, [1, 2]) | ||||
|         self.assertIsInstance(sub_list, BaseList) | ||||
|         self.assertIs(sub_list._instance, base_list._instance) | ||||
|         self.assertEqual(sub_list._name, "my_name.0") | ||||
|         self.assertEqual(base_list._instance._changed_fields, []) | ||||
|         assert sub_list == [1, 2] | ||||
|         assert isinstance(sub_list, BaseList) | ||||
|         assert sub_list._instance is base_list._instance | ||||
|         assert sub_list._name == "my_name.0" | ||||
|         assert base_list._instance._changed_fields == [] | ||||
|  | ||||
|         # Challenge mark_as_changed from sublist | ||||
|         sub_list[1] = None | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name.0.1"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name.0.1"] | ||||
|  | ||||
|     def test___getitem__subdict_returns_BaseList_bound_to_instance(self): | ||||
|         base_list = self._get_baselist([{"subk": "subv"}]) | ||||
|         sub_dict = base_list[0] | ||||
|         self.assertEqual(sub_dict, {"subk": "subv"}) | ||||
|         self.assertIsInstance(sub_dict, BaseDict) | ||||
|         self.assertIs(sub_dict._instance, base_list._instance) | ||||
|         self.assertEqual(sub_dict._name, "my_name.0") | ||||
|         self.assertEqual(base_list._instance._changed_fields, []) | ||||
|         assert sub_dict == {"subk": "subv"} | ||||
|         assert isinstance(sub_dict, BaseDict) | ||||
|         assert sub_dict._instance is base_list._instance | ||||
|         assert sub_dict._name == "my_name.0" | ||||
|         assert base_list._instance._changed_fields == [] | ||||
|  | ||||
|         # Challenge mark_as_changed from subdict | ||||
|         sub_dict["subk"] = None | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name.0.subk"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name.0.subk"] | ||||
|  | ||||
|     def test_extend_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([]) | ||||
|         base_list.extend([True]) | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_insert_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([]) | ||||
|         base_list.insert(0, True) | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_remove_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         base_list.remove(True) | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_remove_not_mark_as_changed_when_it_fails(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         with self.assertRaises(ValueError): | ||||
|         with pytest.raises(ValueError): | ||||
|             base_list.remove(False) | ||||
|         self.assertFalse(base_list._instance._changed_fields) | ||||
|         assert not base_list._instance._changed_fields | ||||
|  | ||||
|     def test_pop_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         base_list.pop() | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_reverse_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True, False]) | ||||
|         base_list.reverse() | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test___delitem___calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         del base_list[0] | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test___setitem___calls_with_full_slice_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([]) | ||||
| @@ -286,8 +288,8 @@ class TestBaseList(unittest.TestCase): | ||||
|             0, | ||||
|             1, | ||||
|         ]  # Will use __setslice__ under py2 and __setitem__ under py3 | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_list, [0, 1]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|         assert base_list == [0, 1] | ||||
|  | ||||
|     def test___setitem___calls_with_partial_slice_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([0, 1, 2]) | ||||
| @@ -295,103 +297,103 @@ class TestBaseList(unittest.TestCase): | ||||
|             1, | ||||
|             0, | ||||
|         ]  # Will use __setslice__ under py2 and __setitem__ under py3 | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_list, [1, 0, 2]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|         assert base_list == [1, 0, 2] | ||||
|  | ||||
|     def test___setitem___calls_with_step_slice_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([0, 1, 2]) | ||||
|         base_list[0:3:2] = [-1, -2]  # uses __setitem__ in both py2 & 3 | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_list, [-1, 1, -2]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|         assert base_list == [-1, 1, -2] | ||||
|  | ||||
|     def test___setitem___with_slice(self): | ||||
|         base_list = self._get_baselist([0, 1, 2, 3, 4, 5]) | ||||
|         base_list[0:6:2] = [None, None, None] | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_list, [None, 1, None, 3, None, 5]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|         assert base_list == [None, 1, None, 3, None, 5] | ||||
|  | ||||
|     def test___setitem___item_0_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         base_list[0] = False | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_list, [False]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|         assert base_list == [False] | ||||
|  | ||||
|     def test___setitem___item_1_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True, True]) | ||||
|         base_list[1] = False | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name.1"]) | ||||
|         self.assertEqual(base_list, [True, False]) | ||||
|         assert base_list._instance._changed_fields == ["my_name.1"] | ||||
|         assert base_list == [True, False] | ||||
|  | ||||
|     def test___delslice___calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([0, 1]) | ||||
|         del base_list[0:1] | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         self.assertEqual(base_list, [1]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|         assert base_list == [1] | ||||
|  | ||||
|     def test___iadd___calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         base_list += [False] | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test___imul___calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         self.assertEqual(base_list._instance._changed_fields, []) | ||||
|         assert base_list._instance._changed_fields == [] | ||||
|         base_list *= 2 | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_sort_calls_not_marked_as_changed_when_it_fails(self): | ||||
|         base_list = self._get_baselist([True]) | ||||
|         with self.assertRaises(TypeError): | ||||
|         with pytest.raises(TypeError): | ||||
|             base_list.sort(key=1) | ||||
|  | ||||
|         self.assertEqual(base_list._instance._changed_fields, []) | ||||
|         assert base_list._instance._changed_fields == [] | ||||
|  | ||||
|     def test_sort_calls_mark_as_changed(self): | ||||
|         base_list = self._get_baselist([True, False]) | ||||
|         base_list.sort() | ||||
|         self.assertEqual(base_list._instance._changed_fields, ["my_name"]) | ||||
|         assert base_list._instance._changed_fields == ["my_name"] | ||||
|  | ||||
|     def test_sort_calls_with_key(self): | ||||
|         base_list = self._get_baselist([1, 2, 11]) | ||||
|         base_list.sort(key=lambda i: str(i)) | ||||
|         self.assertEqual(base_list, [1, 11, 2]) | ||||
|         assert base_list == [1, 11, 2] | ||||
|  | ||||
|  | ||||
| class TestStrictDict(unittest.TestCase): | ||||
|     def strict_dict_class(self, *args, **kwargs): | ||||
|         return StrictDict.create(*args, **kwargs) | ||||
|  | ||||
|     def setUp(self): | ||||
|         self.dtype = self.strict_dict_class(("a", "b", "c")) | ||||
|  | ||||
|     def strict_dict_class(self, *args, **kwargs): | ||||
|         return StrictDict.create(*args, **kwargs) | ||||
|  | ||||
|     def test_init(self): | ||||
|         d = self.dtype(a=1, b=1, c=1) | ||||
|         self.assertEqual((d.a, d.b, d.c), (1, 1, 1)) | ||||
|         assert (d.a, d.b, d.c) == (1, 1, 1) | ||||
|  | ||||
|     def test_iterkeys(self): | ||||
|         d = self.dtype(a=1) | ||||
|         self.assertEqual(list(iterkeys(d)), ["a"]) | ||||
|         assert list(iterkeys(d)) == ["a"] | ||||
|  | ||||
|     def test_len(self): | ||||
|         d = self.dtype(a=1) | ||||
|         self.assertEqual(len(d), 1) | ||||
|         assert len(d) == 1 | ||||
|  | ||||
|     def test_pop(self): | ||||
|         d = self.dtype(a=1) | ||||
|         self.assertIn("a", d) | ||||
|         assert "a" in d | ||||
|         d.pop("a") | ||||
|         self.assertNotIn("a", d) | ||||
|         assert "a" not in d | ||||
|  | ||||
|     def test_repr(self): | ||||
|         d = self.dtype(a=1, b=2, c=3) | ||||
|         self.assertEqual(repr(d), '{"a": 1, "b": 2, "c": 3}') | ||||
|         assert repr(d) == '{"a": 1, "b": 2, "c": 3}' | ||||
|  | ||||
|         # make sure quotes are escaped properly | ||||
|         d = self.dtype(a='"', b="'", c="") | ||||
|         self.assertEqual(repr(d), '{"a": \'"\', "b": "\'", "c": \'\'}') | ||||
|         assert repr(d) == '{"a": \'"\', "b": "\'", "c": \'\'}' | ||||
|  | ||||
|     def test_init_fails_on_nonexisting_attrs(self): | ||||
|         with self.assertRaises(AttributeError): | ||||
|         with pytest.raises(AttributeError): | ||||
|             self.dtype(a=1, b=2, d=3) | ||||
|  | ||||
|     def test_eq(self): | ||||
| @@ -403,45 +405,46 @@ class TestStrictDict(unittest.TestCase): | ||||
|         h = self.strict_dict_class(("a", "c", "b"))(a=1, b=1, c=1) | ||||
|         i = self.strict_dict_class(("a", "c", "b"))(a=1, b=1, c=2) | ||||
|  | ||||
|         self.assertEqual(d, dd) | ||||
|         self.assertNotEqual(d, e) | ||||
|         self.assertNotEqual(d, f) | ||||
|         self.assertNotEqual(d, g) | ||||
|         self.assertNotEqual(f, d) | ||||
|         self.assertEqual(d, h) | ||||
|         self.assertNotEqual(d, i) | ||||
|         assert d == dd | ||||
|         assert d != e | ||||
|         assert d != f | ||||
|         assert d != g | ||||
|         assert f != d | ||||
|         assert d == h | ||||
|         assert d != i | ||||
|  | ||||
|     def test_setattr_getattr(self): | ||||
|         d = self.dtype() | ||||
|         d.a = 1 | ||||
|         self.assertEqual(d.a, 1) | ||||
|         self.assertRaises(AttributeError, getattr, d, "b") | ||||
|         assert d.a == 1 | ||||
|         with pytest.raises(AttributeError): | ||||
|             getattr(d, "b") | ||||
|  | ||||
|     def test_setattr_raises_on_nonexisting_attr(self): | ||||
|         d = self.dtype() | ||||
|         with self.assertRaises(AttributeError): | ||||
|         with pytest.raises(AttributeError): | ||||
|             d.x = 1 | ||||
|  | ||||
|     def test_setattr_getattr_special(self): | ||||
|         d = self.strict_dict_class(["items"]) | ||||
|         d.items = 1 | ||||
|         self.assertEqual(d.items, 1) | ||||
|         assert d.items == 1 | ||||
|  | ||||
|     def test_get(self): | ||||
|         d = self.dtype(a=1) | ||||
|         self.assertEqual(d.get("a"), 1) | ||||
|         self.assertEqual(d.get("b", "bla"), "bla") | ||||
|         assert d.get("a") == 1 | ||||
|         assert d.get("b", "bla") == "bla" | ||||
|  | ||||
|     def test_items(self): | ||||
|         d = self.dtype(a=1) | ||||
|         self.assertEqual(d.items(), [("a", 1)]) | ||||
|         assert d.items() == [("a", 1)] | ||||
|         d = self.dtype(a=1, b=2) | ||||
|         self.assertEqual(d.items(), [("a", 1), ("b", 2)]) | ||||
|         assert d.items() == [("a", 1), ("b", 2)] | ||||
|  | ||||
|     def test_mappings_protocol(self): | ||||
|         d = self.dtype(a=1, b=2) | ||||
|         self.assertEqual(dict(d), {"a": 1, "b": 2}) | ||||
|         self.assertEqual(dict(**d), {"a": 1, "b": 2}) | ||||
|         assert dict(d) == {"a": 1, "b": 2} | ||||
|         assert dict(**d) == {"a": 1, "b": 2} | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -42,37 +42,37 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             len(group_obj._data["members"]) | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             len(group_obj.members) | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert q == 2 | ||||
|  | ||||
|         User.drop_collection() | ||||
|         Group.drop_collection() | ||||
| @@ -99,40 +99,40 @@ class FieldTest(unittest.TestCase): | ||||
|         group.reload()  # Confirm reload works | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             self.assertTrue(group_obj._data["members"]._dereferenced) | ||||
|             assert q == 2 | ||||
|             assert group_obj._data["members"]._dereferenced | ||||
|  | ||||
|             # verifies that no additional queries gets executed | ||||
|             # if we re-iterate over the ListField once it is | ||||
|             # dereferenced | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             self.assertTrue(group_obj._data["members"]._dereferenced) | ||||
|             assert q == 2 | ||||
|             assert group_obj._data["members"]._dereferenced | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|  | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert q == 2 | ||||
|  | ||||
|     def test_list_item_dereference_orphan_dbref(self): | ||||
|         """Ensure that orphan DBRef items in ListFields are dereferenced. | ||||
| @@ -159,21 +159,21 @@ class FieldTest(unittest.TestCase): | ||||
|         # Group.members list is an orphan DBRef | ||||
|         User.objects[0].delete() | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             self.assertTrue(group_obj._data["members"]._dereferenced) | ||||
|             assert q == 2 | ||||
|             assert group_obj._data["members"]._dereferenced | ||||
|  | ||||
|             # verifies that no additional queries gets executed | ||||
|             # if we re-iterate over the ListField once it is | ||||
|             # dereferenced | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             self.assertTrue(group_obj._data["members"]._dereferenced) | ||||
|             assert q == 2 | ||||
|             assert group_obj._data["members"]._dereferenced | ||||
|  | ||||
|         User.drop_collection() | ||||
|         Group.drop_collection() | ||||
| @@ -197,8 +197,8 @@ class FieldTest(unittest.TestCase): | ||||
|         Group(members=User.objects).save() | ||||
|         group = Group.objects.first() | ||||
|  | ||||
|         self.assertEqual(Group._get_collection().find_one()["members"], [1]) | ||||
|         self.assertEqual(group.members, [user]) | ||||
|         assert Group._get_collection().find_one()["members"] == [1] | ||||
|         assert group.members == [user] | ||||
|  | ||||
|     def test_handle_old_style_references(self): | ||||
|         """Ensure that DBRef items in ListFields are dereferenced. | ||||
| @@ -231,8 +231,8 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         group = Group.objects.first() | ||||
|         self.assertEqual(group.members[0].name, "user 1") | ||||
|         self.assertEqual(group.members[-1].name, "String!") | ||||
|         assert group.members[0].name == "user 1" | ||||
|         assert group.members[-1].name == "String!" | ||||
|  | ||||
|     def test_migrate_references(self): | ||||
|         """Example of migrating ReferenceField storage | ||||
| @@ -253,12 +253,12 @@ class FieldTest(unittest.TestCase): | ||||
|         group = Group(author=user, members=[user]).save() | ||||
|  | ||||
|         raw_data = Group._get_collection().find_one() | ||||
|         self.assertIsInstance(raw_data["author"], DBRef) | ||||
|         self.assertIsInstance(raw_data["members"][0], DBRef) | ||||
|         assert isinstance(raw_data["author"], DBRef) | ||||
|         assert isinstance(raw_data["members"][0], DBRef) | ||||
|         group = Group.objects.first() | ||||
|  | ||||
|         self.assertEqual(group.author, user) | ||||
|         self.assertEqual(group.members, [user]) | ||||
|         assert group.author == user | ||||
|         assert group.members == [user] | ||||
|  | ||||
|         # Migrate the model definition | ||||
|         class Group(Document): | ||||
| @@ -273,12 +273,12 @@ class FieldTest(unittest.TestCase): | ||||
|             g.save() | ||||
|  | ||||
|         group = Group.objects.first() | ||||
|         self.assertEqual(group.author, user) | ||||
|         self.assertEqual(group.members, [user]) | ||||
|         assert group.author == user | ||||
|         assert group.members == [user] | ||||
|  | ||||
|         raw_data = Group._get_collection().find_one() | ||||
|         self.assertIsInstance(raw_data["author"], ObjectId) | ||||
|         self.assertIsInstance(raw_data["members"][0], ObjectId) | ||||
|         assert isinstance(raw_data["author"], ObjectId) | ||||
|         assert isinstance(raw_data["members"][0], ObjectId) | ||||
|  | ||||
|     def test_recursive_reference(self): | ||||
|         """Ensure that ReferenceFields can reference their own documents. | ||||
| @@ -309,43 +309,43 @@ class FieldTest(unittest.TestCase): | ||||
|         Employee(name="Funky Gibbon", boss=bill, friends=friends).save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             peter = Employee.objects.with_id(peter.id) | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             peter.boss | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             peter.friends | ||||
|             self.assertEqual(q, 3) | ||||
|             assert q == 3 | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             peter = Employee.objects.with_id(peter.id).select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             self.assertEqual(peter.boss, bill) | ||||
|             self.assertEqual(q, 2) | ||||
|             assert peter.boss == bill | ||||
|             assert q == 2 | ||||
|  | ||||
|             self.assertEqual(peter.friends, friends) | ||||
|             self.assertEqual(q, 2) | ||||
|             assert peter.friends == friends | ||||
|             assert q == 2 | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             employees = Employee.objects(boss=bill).select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for employee in employees: | ||||
|                 self.assertEqual(employee.boss, bill) | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert employee.boss == bill | ||||
|                 assert q == 2 | ||||
|  | ||||
|                 self.assertEqual(employee.friends, friends) | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert employee.friends == friends | ||||
|                 assert q == 2 | ||||
|  | ||||
|     def test_list_of_lists_of_references(self): | ||||
|         class User(Document): | ||||
| @@ -366,10 +366,10 @@ class FieldTest(unittest.TestCase): | ||||
|         u3 = User.objects.create(name="u3") | ||||
|  | ||||
|         SimpleList.objects.create(users=[u1, u2, u3]) | ||||
|         self.assertEqual(SimpleList.objects.all()[0].users, [u1, u2, u3]) | ||||
|         assert SimpleList.objects.all()[0].users == [u1, u2, u3] | ||||
|  | ||||
|         Post.objects.create(user_lists=[[u1, u2], [u3]]) | ||||
|         self.assertEqual(Post.objects.all()[0].user_lists, [[u1, u2], [u3]]) | ||||
|         assert Post.objects.all()[0].user_lists == [[u1, u2], [u3]] | ||||
|  | ||||
|     def test_circular_reference(self): | ||||
|         """Ensure you can handle circular references | ||||
| @@ -403,9 +403,7 @@ class FieldTest(unittest.TestCase): | ||||
|         daughter.relations.append(self_rel) | ||||
|         daughter.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "[<Person: Mother>, <Person: Daughter>]", "%s" % Person.objects() | ||||
|         ) | ||||
|         assert "[<Person: Mother>, <Person: Daughter>]" == "%s" % Person.objects() | ||||
|  | ||||
|     def test_circular_reference_on_self(self): | ||||
|         """Ensure you can handle circular references | ||||
| @@ -432,9 +430,7 @@ class FieldTest(unittest.TestCase): | ||||
|         daughter.relations.append(daughter) | ||||
|         daughter.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "[<Person: Mother>, <Person: Daughter>]", "%s" % Person.objects() | ||||
|         ) | ||||
|         assert "[<Person: Mother>, <Person: Daughter>]" == "%s" % Person.objects() | ||||
|  | ||||
|     def test_circular_tree_reference(self): | ||||
|         """Ensure you can handle circular references with more than one level | ||||
| @@ -473,9 +469,9 @@ class FieldTest(unittest.TestCase): | ||||
|         anna.other.name = "Anna's friends" | ||||
|         anna.save() | ||||
|  | ||||
|         self.assertEqual( | ||||
|             "[<Person: Paul>, <Person: Maria>, <Person: Julia>, <Person: Anna>]", | ||||
|             "%s" % Person.objects(), | ||||
|         assert ( | ||||
|             "[<Person: Paul>, <Person: Maria>, <Person: Julia>, <Person: Anna>]" | ||||
|             == "%s" % Person.objects() | ||||
|         ) | ||||
|  | ||||
|     def test_generic_reference(self): | ||||
| @@ -516,52 +512,52 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for m in group_obj.members: | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for m in group_obj.members: | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 for m in group_obj.members: | ||||
|                     self.assertIn("User", m.__class__.__name__) | ||||
|                     assert "User" in m.__class__.__name__ | ||||
|  | ||||
|     def test_generic_reference_orphan_dbref(self): | ||||
|         """Ensure that generic orphan DBRef items in ListFields are dereferenced. | ||||
| @@ -604,18 +600,18 @@ class FieldTest(unittest.TestCase): | ||||
|         # an orphan DBRef in the GenericReference ListField | ||||
|         UserA.objects[0].delete() | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             self.assertTrue(group_obj._data["members"]._dereferenced) | ||||
|             assert q == 4 | ||||
|             assert group_obj._data["members"]._dereferenced | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             self.assertTrue(group_obj._data["members"]._dereferenced) | ||||
|             assert q == 4 | ||||
|             assert group_obj._data["members"]._dereferenced | ||||
|  | ||||
|         UserA.drop_collection() | ||||
|         UserB.drop_collection() | ||||
| @@ -660,52 +656,52 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for m in group_obj.members: | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for m in group_obj.members: | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 for m in group_obj.members: | ||||
|                     self.assertIn("User", m.__class__.__name__) | ||||
|                     assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         UserA.drop_collection() | ||||
|         UserB.drop_collection() | ||||
| @@ -735,43 +731,43 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIsInstance(m, User) | ||||
|                 assert isinstance(m, User) | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIsInstance(m, User) | ||||
|                 assert isinstance(m, User) | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert q == 2 | ||||
|  | ||||
|                 for k, m in iteritems(group_obj.members): | ||||
|                     self.assertIsInstance(m, User) | ||||
|                     assert isinstance(m, User) | ||||
|  | ||||
|         User.drop_collection() | ||||
|         Group.drop_collection() | ||||
| @@ -813,65 +809,65 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 for k, m in iteritems(group_obj.members): | ||||
|                     self.assertIn("User", m.__class__.__name__) | ||||
|                     assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         Group.objects.delete() | ||||
|         Group().save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 1) | ||||
|             self.assertEqual(group_obj.members, {}) | ||||
|             assert q == 1 | ||||
|             assert group_obj.members == {} | ||||
|  | ||||
|         UserA.drop_collection() | ||||
|         UserB.drop_collection() | ||||
| @@ -903,52 +899,52 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIsInstance(m, UserA) | ||||
|                 assert isinstance(m, UserA) | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIsInstance(m, UserA) | ||||
|                 assert isinstance(m, UserA) | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert q == 2 | ||||
|  | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 2) | ||||
|                 assert q == 2 | ||||
|  | ||||
|                 for k, m in iteritems(group_obj.members): | ||||
|                     self.assertIsInstance(m, UserA) | ||||
|                     assert isinstance(m, UserA) | ||||
|  | ||||
|         UserA.drop_collection() | ||||
|         Group.drop_collection() | ||||
| @@ -990,64 +986,64 @@ class FieldTest(unittest.TestCase): | ||||
|         group.save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Document select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first().select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for k, m in iteritems(group_obj.members): | ||||
|                 self.assertIn("User", m.__class__.__name__) | ||||
|                 assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         # Queryset select_related | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_objs = Group.objects.select_related() | ||||
|             self.assertEqual(q, 4) | ||||
|             assert q == 4 | ||||
|  | ||||
|             for group_obj in group_objs: | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 [m for m in group_obj.members] | ||||
|                 self.assertEqual(q, 4) | ||||
|                 assert q == 4 | ||||
|  | ||||
|                 for k, m in iteritems(group_obj.members): | ||||
|                     self.assertIn("User", m.__class__.__name__) | ||||
|                     assert "User" in m.__class__.__name__ | ||||
|  | ||||
|         Group.objects.delete() | ||||
|         Group().save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             [m for m in group_obj.members] | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|         UserA.drop_collection() | ||||
|         UserB.drop_collection() | ||||
| @@ -1075,8 +1071,8 @@ class FieldTest(unittest.TestCase): | ||||
|         root.save() | ||||
|  | ||||
|         root = root.reload() | ||||
|         self.assertEqual(root.children, [company]) | ||||
|         self.assertEqual(company.parents, [root]) | ||||
|         assert root.children == [company] | ||||
|         assert company.parents == [root] | ||||
|  | ||||
|     def test_dict_in_dbref_instance(self): | ||||
|         class Person(Document): | ||||
| @@ -1102,8 +1098,8 @@ class FieldTest(unittest.TestCase): | ||||
|         room_101.save() | ||||
|  | ||||
|         room = Room.objects.first().select_related() | ||||
|         self.assertEqual(room.staffs_with_position[0]["staff"], sarah) | ||||
|         self.assertEqual(room.staffs_with_position[1]["staff"], bob) | ||||
|         assert room.staffs_with_position[0]["staff"] == sarah | ||||
|         assert room.staffs_with_position[1]["staff"] == bob | ||||
|  | ||||
|     def test_document_reload_no_inheritance(self): | ||||
|         class Foo(Document): | ||||
| @@ -1133,8 +1129,8 @@ class FieldTest(unittest.TestCase): | ||||
|         foo.save() | ||||
|         foo.reload() | ||||
|  | ||||
|         self.assertEqual(type(foo.bar), Bar) | ||||
|         self.assertEqual(type(foo.baz), Baz) | ||||
|         assert type(foo.bar) == Bar | ||||
|         assert type(foo.baz) == Baz | ||||
|  | ||||
|     def test_document_reload_reference_integrity(self): | ||||
|         """ | ||||
| @@ -1166,13 +1162,13 @@ class FieldTest(unittest.TestCase): | ||||
|         concurrent_change_user = User.objects.get(id=1) | ||||
|         concurrent_change_user.name = "new-name" | ||||
|         concurrent_change_user.save() | ||||
|         self.assertNotEqual(user.name, "new-name") | ||||
|         assert user.name != "new-name" | ||||
|  | ||||
|         msg = Message.objects.get(id=1) | ||||
|         msg.reload() | ||||
|         self.assertEqual(msg.topic, topic) | ||||
|         self.assertEqual(msg.author, user) | ||||
|         self.assertEqual(msg.author.name, "new-name") | ||||
|         assert msg.topic == topic | ||||
|         assert msg.author == user | ||||
|         assert msg.author.name == "new-name" | ||||
|  | ||||
|     def test_list_lookup_not_checked_in_map(self): | ||||
|         """Ensure we dereference list data correctly | ||||
| @@ -1194,8 +1190,8 @@ class FieldTest(unittest.TestCase): | ||||
|         Message(id=1, comments=[c1, c2]).save() | ||||
|  | ||||
|         msg = Message.objects.get(id=1) | ||||
|         self.assertEqual(0, msg.comments[0].id) | ||||
|         self.assertEqual(1, msg.comments[1].id) | ||||
|         assert 0 == msg.comments[0].id | ||||
|         assert 1 == msg.comments[1].id | ||||
|  | ||||
|     def test_list_item_dereference_dref_false_save_doesnt_cause_extra_queries(self): | ||||
|         """Ensure that DBRef items in ListFields are dereferenced. | ||||
| @@ -1217,15 +1213,15 @@ class FieldTest(unittest.TestCase): | ||||
|         Group(name="Test", members=User.objects).save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             group_obj.name = "new test" | ||||
|             group_obj.save() | ||||
|  | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|     def test_list_item_dereference_dref_true_save_doesnt_cause_extra_queries(self): | ||||
|         """Ensure that DBRef items in ListFields are dereferenced. | ||||
| @@ -1247,15 +1243,15 @@ class FieldTest(unittest.TestCase): | ||||
|         Group(name="Test", members=User.objects).save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             group_obj.name = "new test" | ||||
|             group_obj.save() | ||||
|  | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|     def test_generic_reference_save_doesnt_cause_extra_queries(self): | ||||
|         class UserA(Document): | ||||
| @@ -1287,15 +1283,15 @@ class FieldTest(unittest.TestCase): | ||||
|         Group(name="test", members=members).save() | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             group_obj = Group.objects.first() | ||||
|             self.assertEqual(q, 1) | ||||
|             assert q == 1 | ||||
|  | ||||
|             group_obj.name = "new test" | ||||
|             group_obj.save() | ||||
|  | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|     def test_objectid_reference_across_databases(self): | ||||
|         # mongoenginetest - Is default connection alias from setUp() | ||||
| @@ -1319,10 +1315,10 @@ class FieldTest(unittest.TestCase): | ||||
|  | ||||
|         # Can't use query_counter across databases - so test the _data object | ||||
|         book = Book.objects.first() | ||||
|         self.assertNotIsInstance(book._data["author"], User) | ||||
|         assert not isinstance(book._data["author"], User) | ||||
|  | ||||
|         book.select_related() | ||||
|         self.assertIsInstance(book._data["author"], User) | ||||
|         assert isinstance(book._data["author"], User) | ||||
|  | ||||
|     def test_non_ascii_pk(self): | ||||
|         """ | ||||
| @@ -1346,7 +1342,7 @@ class FieldTest(unittest.TestCase): | ||||
|         BrandGroup(title="top_brands", brands=[brand1, brand2]).save() | ||||
|         brand_groups = BrandGroup.objects().all() | ||||
|  | ||||
|         self.assertEqual(2, len([brand for bg in brand_groups for brand in bg.brands])) | ||||
|         assert 2 == len([brand for bg in brand_groups for brand in bg.brands]) | ||||
|  | ||||
|     def test_dereferencing_embedded_listfield_referencefield(self): | ||||
|         class Tag(Document): | ||||
| @@ -1370,7 +1366,7 @@ class FieldTest(unittest.TestCase): | ||||
|         Page(tags=[tag], posts=[post]).save() | ||||
|  | ||||
|         page = Page.objects.first() | ||||
|         self.assertEqual(page.tags[0], page.posts[0].tags[0]) | ||||
|         assert page.tags[0] == page.posts[0].tags[0] | ||||
|  | ||||
|     def test_select_related_follows_embedded_referencefields(self): | ||||
|         class Song(Document): | ||||
| @@ -1390,12 +1386,12 @@ class FieldTest(unittest.TestCase): | ||||
|         playlist = Playlist.objects.create(items=items) | ||||
|  | ||||
|         with query_counter() as q: | ||||
|             self.assertEqual(q, 0) | ||||
|             assert q == 0 | ||||
|  | ||||
|             playlist = Playlist.objects.first().select_related() | ||||
|             songs = [item.song for item in playlist.items] | ||||
|  | ||||
|             self.assertEqual(q, 2) | ||||
|             assert q == 2 | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import unittest | ||||
|  | ||||
| from pymongo import ReadPreference | ||||
| from pymongo import MongoClient | ||||
| from pymongo import MongoClient, ReadPreference | ||||
|  | ||||
| import mongoengine | ||||
| from mongoengine.connection import ConnectionFailure | ||||
| @@ -25,21 +24,20 @@ class ConnectionTest(unittest.TestCase): | ||||
|     def test_replicaset_uri_passes_read_preference(self): | ||||
|         """Requires a replica set called "rs" on port 27017 | ||||
|         """ | ||||
|  | ||||
|         try: | ||||
|             conn = mongoengine.connect( | ||||
|                 db="mongoenginetest", | ||||
|                 host="mongodb://localhost/mongoenginetest?replicaSet=rs", | ||||
|                 read_preference=READ_PREF, | ||||
|             ) | ||||
|         except ConnectionFailure as e: | ||||
|         except ConnectionFailure: | ||||
|             return | ||||
|  | ||||
|         if not isinstance(conn, CONN_CLASS): | ||||
|             # really??? | ||||
|             return | ||||
|  | ||||
|         self.assertEqual(conn.read_preference, READ_PREF) | ||||
|         assert conn.read_preference == READ_PREF | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -7,7 +7,7 @@ from mongoengine import signals | ||||
| signal_output = [] | ||||
|  | ||||
|  | ||||
| class SignalTests(unittest.TestCase): | ||||
| class TestSignal(unittest.TestCase): | ||||
|     """ | ||||
|     Testing signals before/after saving and deleting. | ||||
|     """ | ||||
| @@ -245,7 +245,7 @@ class SignalTests(unittest.TestCase): | ||||
|         # Note that there is a chance that the following assert fails in case | ||||
|         # some receivers (eventually created in other tests) | ||||
|         # gets garbage collected (https://pythonhosted.org/blinker/#blinker.base.Signal.connect) | ||||
|         self.assertEqual(self.pre_signals, post_signals) | ||||
|         assert self.pre_signals == post_signals | ||||
|  | ||||
|     def test_model_signals(self): | ||||
|         """ Model saves should throw some signals. """ | ||||
| @@ -267,97 +267,76 @@ class SignalTests(unittest.TestCase): | ||||
|             self.get_signal_output(lambda: None)  # eliminate signal output | ||||
|             a1 = self.Author.objects(name="Bill Shakespeare")[0] | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(create_author), | ||||
|             [ | ||||
|                 "pre_init signal, Author", | ||||
|                 {"name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = True", | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(create_author) == [ | ||||
|             "pre_init signal, Author", | ||||
|             {"name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = True", | ||||
|         ] | ||||
|  | ||||
|         a1 = self.Author(name="Bill Shakespeare") | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(a1.save), | ||||
|             [ | ||||
|                 "pre_save signal, Bill Shakespeare", | ||||
|                 {}, | ||||
|                 "pre_save_post_validation signal, Bill Shakespeare", | ||||
|                 "Is created", | ||||
|                 {}, | ||||
|                 "post_save signal, Bill Shakespeare", | ||||
|                 "post_save dirty keys, ['name']", | ||||
|                 "Is created", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(a1.save) == [ | ||||
|             "pre_save signal, Bill Shakespeare", | ||||
|             {}, | ||||
|             "pre_save_post_validation signal, Bill Shakespeare", | ||||
|             "Is created", | ||||
|             {}, | ||||
|             "post_save signal, Bill Shakespeare", | ||||
|             "post_save dirty keys, ['name']", | ||||
|             "Is created", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|         a1.reload() | ||||
|         a1.name = "William Shakespeare" | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(a1.save), | ||||
|             [ | ||||
|                 "pre_save signal, William Shakespeare", | ||||
|                 {}, | ||||
|                 "pre_save_post_validation signal, William Shakespeare", | ||||
|                 "Is updated", | ||||
|                 {}, | ||||
|                 "post_save signal, William Shakespeare", | ||||
|                 "post_save dirty keys, ['name']", | ||||
|                 "Is updated", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(a1.save) == [ | ||||
|             "pre_save signal, William Shakespeare", | ||||
|             {}, | ||||
|             "pre_save_post_validation signal, William Shakespeare", | ||||
|             "Is updated", | ||||
|             {}, | ||||
|             "post_save signal, William Shakespeare", | ||||
|             "post_save dirty keys, ['name']", | ||||
|             "Is updated", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(a1.delete), | ||||
|             [ | ||||
|                 "pre_delete signal, William Shakespeare", | ||||
|                 {}, | ||||
|                 "post_delete signal, William Shakespeare", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(a1.delete) == [ | ||||
|             "pre_delete signal, William Shakespeare", | ||||
|             {}, | ||||
|             "post_delete signal, William Shakespeare", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(load_existing_author), | ||||
|             [ | ||||
|                 "pre_init signal, Author", | ||||
|                 {"id": 2, "name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = False", | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(load_existing_author) == [ | ||||
|             "pre_init signal, Author", | ||||
|             {"id": 2, "name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = False", | ||||
|         ] | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(bulk_create_author_with_load), | ||||
|             [ | ||||
|                 "pre_init signal, Author", | ||||
|                 {"name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = True", | ||||
|                 "pre_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|                 {}, | ||||
|                 "pre_init signal, Author", | ||||
|                 {"id": 3, "name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = False", | ||||
|                 "post_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|                 "Is loaded", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(bulk_create_author_with_load) == [ | ||||
|             "pre_init signal, Author", | ||||
|             {"name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = True", | ||||
|             "pre_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|             {}, | ||||
|             "pre_init signal, Author", | ||||
|             {"id": 3, "name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = False", | ||||
|             "post_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|             "Is loaded", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(bulk_create_author_without_load), | ||||
|             [ | ||||
|                 "pre_init signal, Author", | ||||
|                 {"name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = True", | ||||
|                 "pre_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|                 {}, | ||||
|                 "post_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|                 "Not loaded", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(bulk_create_author_without_load) == [ | ||||
|             "pre_init signal, Author", | ||||
|             {"name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = True", | ||||
|             "pre_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|             {}, | ||||
|             "post_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|             "Not loaded", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|     def test_signal_kwargs(self): | ||||
|         """ Make sure signal_kwargs is passed to signals calls. """ | ||||
| @@ -367,83 +346,74 @@ class SignalTests(unittest.TestCase): | ||||
|             a.save(signal_kwargs={"live": True, "die": False}) | ||||
|             a.delete(signal_kwargs={"live": False, "die": True}) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(live_and_let_die), | ||||
|             [ | ||||
|                 "pre_init signal, Author", | ||||
|                 {"name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = True", | ||||
|                 "pre_save signal, Bill Shakespeare", | ||||
|                 {"die": False, "live": True}, | ||||
|                 "pre_save_post_validation signal, Bill Shakespeare", | ||||
|                 "Is created", | ||||
|                 {"die": False, "live": True}, | ||||
|                 "post_save signal, Bill Shakespeare", | ||||
|                 "post_save dirty keys, ['name']", | ||||
|                 "Is created", | ||||
|                 {"die": False, "live": True}, | ||||
|                 "pre_delete signal, Bill Shakespeare", | ||||
|                 {"die": True, "live": False}, | ||||
|                 "post_delete signal, Bill Shakespeare", | ||||
|                 {"die": True, "live": False}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(live_and_let_die) == [ | ||||
|             "pre_init signal, Author", | ||||
|             {"name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = True", | ||||
|             "pre_save signal, Bill Shakespeare", | ||||
|             {"die": False, "live": True}, | ||||
|             "pre_save_post_validation signal, Bill Shakespeare", | ||||
|             "Is created", | ||||
|             {"die": False, "live": True}, | ||||
|             "post_save signal, Bill Shakespeare", | ||||
|             "post_save dirty keys, ['name']", | ||||
|             "Is created", | ||||
|             {"die": False, "live": True}, | ||||
|             "pre_delete signal, Bill Shakespeare", | ||||
|             {"die": True, "live": False}, | ||||
|             "post_delete signal, Bill Shakespeare", | ||||
|             {"die": True, "live": False}, | ||||
|         ] | ||||
|  | ||||
|         def bulk_create_author(): | ||||
|             a1 = self.Author(name="Bill Shakespeare") | ||||
|             self.Author.objects.insert([a1], signal_kwargs={"key": True}) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(bulk_create_author), | ||||
|             [ | ||||
|                 "pre_init signal, Author", | ||||
|                 {"name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = True", | ||||
|                 "pre_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|                 {"key": True}, | ||||
|                 "pre_init signal, Author", | ||||
|                 {"id": 2, "name": "Bill Shakespeare"}, | ||||
|                 "post_init signal, Bill Shakespeare, document._created = False", | ||||
|                 "post_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|                 "Is loaded", | ||||
|                 {"key": True}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(bulk_create_author) == [ | ||||
|             "pre_init signal, Author", | ||||
|             {"name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = True", | ||||
|             "pre_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|             {"key": True}, | ||||
|             "pre_init signal, Author", | ||||
|             {"id": 2, "name": "Bill Shakespeare"}, | ||||
|             "post_init signal, Bill Shakespeare, document._created = False", | ||||
|             "post_bulk_insert signal, [<Author: Bill Shakespeare>]", | ||||
|             "Is loaded", | ||||
|             {"key": True}, | ||||
|         ] | ||||
|  | ||||
|     def test_queryset_delete_signals(self): | ||||
|         """ Queryset delete should throw some signals. """ | ||||
|  | ||||
|         self.Another(name="Bill Shakespeare").save() | ||||
|         self.assertEqual( | ||||
|             self.get_signal_output(self.Another.objects.delete), | ||||
|             [ | ||||
|                 "pre_delete signal, Bill Shakespeare", | ||||
|                 {}, | ||||
|                 "post_delete signal, Bill Shakespeare", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert self.get_signal_output(self.Another.objects.delete) == [ | ||||
|             "pre_delete signal, Bill Shakespeare", | ||||
|             {}, | ||||
|             "post_delete signal, Bill Shakespeare", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|     def test_signals_with_explicit_doc_ids(self): | ||||
|         """ Model saves must have a created flag the first time.""" | ||||
|         ei = self.ExplicitId(id=123) | ||||
|         # post save must received the created flag, even if there's already | ||||
|         # an object id present | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|         # second time, it must be an update | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is updated"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is updated"] | ||||
|  | ||||
|     def test_signals_with_switch_collection(self): | ||||
|         ei = self.ExplicitId(id=123) | ||||
|         ei.switch_collection("explicit__1") | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|         ei.switch_collection("explicit__1") | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is updated"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is updated"] | ||||
|  | ||||
|         ei.switch_collection("explicit__1", keep_created=False) | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|         ei.switch_collection("explicit__1", keep_created=False) | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|  | ||||
|     def test_signals_with_switch_db(self): | ||||
|         connect("mongoenginetest") | ||||
| @@ -451,14 +421,14 @@ class SignalTests(unittest.TestCase): | ||||
|  | ||||
|         ei = self.ExplicitId(id=123) | ||||
|         ei.switch_db("testdb-1") | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|         ei.switch_db("testdb-1") | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is updated"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is updated"] | ||||
|  | ||||
|         ei.switch_db("testdb-1", keep_created=False) | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|         ei.switch_db("testdb-1", keep_created=False) | ||||
|         self.assertEqual(self.get_signal_output(ei.save), ["Is created"]) | ||||
|         assert self.get_signal_output(ei.save) == ["Is created"] | ||||
|  | ||||
|     def test_signals_bulk_insert(self): | ||||
|         def bulk_set_active_post(): | ||||
| @@ -470,16 +440,13 @@ class SignalTests(unittest.TestCase): | ||||
|             self.Post.objects.insert(posts) | ||||
|  | ||||
|         results = self.get_signal_output(bulk_set_active_post) | ||||
|         self.assertEqual( | ||||
|             results, | ||||
|             [ | ||||
|                 "pre_bulk_insert signal, [(<Post: Post 1>, {'active': False}), (<Post: Post 2>, {'active': False}), (<Post: Post 3>, {'active': False})]", | ||||
|                 {}, | ||||
|                 "post_bulk_insert signal, [(<Post: Post 1>, {'active': True}), (<Post: Post 2>, {'active': True}), (<Post: Post 3>, {'active': True})]", | ||||
|                 "Is loaded", | ||||
|                 {}, | ||||
|             ], | ||||
|         ) | ||||
|         assert results == [ | ||||
|             "pre_bulk_insert signal, [(<Post: Post 1>, {'active': False}), (<Post: Post 2>, {'active': False}), (<Post: Post 3>, {'active': False})]", | ||||
|             {}, | ||||
|             "post_bulk_insert signal, [(<Post: Post 1>, {'active': True}), (<Post: Post 2>, {'active': True}), (<Post: Post 3>, {'active': True})]", | ||||
|             "Is loaded", | ||||
|             {}, | ||||
|         ] | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|   | ||||
| @@ -1,32 +1,34 @@ | ||||
| import unittest | ||||
| import re | ||||
| import unittest | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from mongoengine.base.utils import LazyRegexCompiler | ||||
|  | ||||
| signal_output = [] | ||||
|  | ||||
|  | ||||
| class LazyRegexCompilerTest(unittest.TestCase): | ||||
| class TestLazyRegexCompiler: | ||||
|     def test_lazy_regex_compiler_verify_laziness_of_descriptor(self): | ||||
|         class UserEmail(object): | ||||
|             EMAIL_REGEX = LazyRegexCompiler("@", flags=32) | ||||
|  | ||||
|         descriptor = UserEmail.__dict__["EMAIL_REGEX"] | ||||
|         self.assertIsNone(descriptor._compiled_regex) | ||||
|         assert descriptor._compiled_regex is None | ||||
|  | ||||
|         regex = UserEmail.EMAIL_REGEX | ||||
|         self.assertEqual(regex, re.compile("@", flags=32)) | ||||
|         self.assertEqual(regex.search("user@domain.com").group(), "@") | ||||
|         assert regex == re.compile("@", flags=32) | ||||
|         assert regex.search("user@domain.com").group() == "@" | ||||
|  | ||||
|         user_email = UserEmail() | ||||
|         self.assertIs(user_email.EMAIL_REGEX, UserEmail.EMAIL_REGEX) | ||||
|         assert user_email.EMAIL_REGEX is UserEmail.EMAIL_REGEX | ||||
|  | ||||
|     def test_lazy_regex_compiler_verify_cannot_set_descriptor_on_instance(self): | ||||
|         class UserEmail(object): | ||||
|             EMAIL_REGEX = LazyRegexCompiler("@") | ||||
|  | ||||
|         user_email = UserEmail() | ||||
|         with self.assertRaises(AttributeError): | ||||
|         with pytest.raises(AttributeError): | ||||
|             user_email.EMAIL_REGEX = re.compile("@") | ||||
|  | ||||
|     def test_lazy_regex_compiler_verify_can_override_class_attr(self): | ||||
| @@ -34,6 +36,4 @@ class LazyRegexCompilerTest(unittest.TestCase): | ||||
|             EMAIL_REGEX = LazyRegexCompiler("@") | ||||
|  | ||||
|         UserEmail.EMAIL_REGEX = re.compile("cookies") | ||||
|         self.assertEqual( | ||||
|             UserEmail.EMAIL_REGEX.search("Cake & cookies").group(), "cookies" | ||||
|         ) | ||||
|         assert UserEmail.EMAIL_REGEX.search("Cake & cookies").group() == "cookies" | ||||
|   | ||||
| @@ -1,10 +1,9 @@ | ||||
| import operator | ||||
| import unittest | ||||
|  | ||||
| from nose.plugins.skip import SkipTest | ||||
| import pytest | ||||
|  | ||||
| from mongoengine import connect | ||||
| from mongoengine.connection import get_db, disconnect_all | ||||
| from mongoengine.connection import disconnect_all, get_db | ||||
| from mongoengine.mongodb_support import get_mongodb_version | ||||
|  | ||||
|  | ||||
| @@ -37,7 +36,7 @@ def get_as_pymongo(doc): | ||||
| def _decorated_with_ver_requirement(func, mongo_version_req, oper): | ||||
|     """Return a MongoDB version requirement decorator. | ||||
|  | ||||
|     The resulting decorator will raise a SkipTest exception if the current | ||||
|     The resulting decorator will skip the test if the current | ||||
|     MongoDB version doesn't match the provided version/operator. | ||||
|  | ||||
|     For example, if you define a decorator like so: | ||||
| @@ -59,9 +58,8 @@ def _decorated_with_ver_requirement(func, mongo_version_req, oper): | ||||
|         if oper(mongodb_v, mongo_version_req): | ||||
|             return func(*args, **kwargs) | ||||
|  | ||||
|         raise SkipTest( | ||||
|             "Needs MongoDB v{}+".format(".".join(str(n) for n in mongo_version_req)) | ||||
|         ) | ||||
|         pretty_version = ".".join(str(n) for n in mongo_version_req) | ||||
|         pytest.skip("Needs MongoDB v{}+".format(pretty_version)) | ||||
|  | ||||
|     _inner.__name__ = func.__name__ | ||||
|     _inner.__doc__ = func.__doc__ | ||||
|   | ||||
							
								
								
									
										6
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tox.ini
									
									
									
									
									
								
							| @@ -3,11 +3,11 @@ envlist = {py27,py35,pypy,pypy3}-{mg34,mg36, mg39} | ||||
|  | ||||
| [testenv] | ||||
| commands = | ||||
|     python setup.py nosetests {posargs} | ||||
|     python setup.py test {posargs} | ||||
| deps = | ||||
|     nose | ||||
|     mg34: pymongo>=3.4,<3.5 | ||||
|     mg36: pymongo>=3.6,<3.7 | ||||
|     mg39: pymongo>=3.9,<4.0 | ||||
|     mg39: pymongo>=3.9,<3.10 | ||||
|     mg310: pymongo>=3.10,<3.11 | ||||
| setenv = | ||||
|     PYTHON_EGG_CACHE = {envdir}/python-eggs | ||||
|   | ||||
		Reference in New Issue
	
	Block a user