Merge branch 'master' of github.com:MongoEngine/mongoengine into mongodb_40

This commit is contained in:
Bastien Gérard 2020-01-12 21:16:48 +01:00
commit ea88806630
76 changed files with 5215 additions and 4899 deletions

View File

@ -3,7 +3,7 @@
# with a very large number of jobs, hence we only test a subset of all the # with a very large number of jobs, hence we only test a subset of all the
# combinations: # combinations:
# * MongoDB v3.4 & the latest PyMongo v3.x is currently the "main" setup, # * 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 # * Besides that, we test the lowest actively supported Python/MongoDB/PyMongo
# combination: MongoDB v3.4, PyMongo v3.4, Python v2.7. # 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. # * 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.5
- 3.6 - 3.6
- 3.7 - 3.7
- 3.8
- pypy - pypy
- pypy3 - pypy3
@ -33,11 +34,12 @@ env:
- MONGODB_4_0=4.0.12 - MONGODB_4_0=4.0.12
- MONGODB_3_4=3.4.17 - MONGODB_3_4=3.4.17
- MONGODB_3_6=3.6.12 - MONGODB_3_6=3.6.12
- PYMONGO_3_10=3.10
- PYMONGO_3_9=3.9 - PYMONGO_3_9=3.9
- PYMONGO_3_6=3.6 - PYMONGO_3_6=3.6
- PYMONGO_3_4=3.4 - PYMONGO_3_4=3.4
matrix: matrix:
- MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_9} - MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_10}
matrix: matrix:
# Finish the build as soon as one job fails # Finish the build as soon as one job fails
@ -49,7 +51,11 @@ matrix:
- python: 3.7 - python: 3.7
env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_6} env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_6}
- python: 3.7 - 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:
# Install Mongo # Install Mongo
@ -62,8 +68,8 @@ install:
- pip install flake8 flake8-import-order - pip install flake8 flake8-import-order
- pip install tox # tox 3.11.0 has requirement virtualenv>=14.0.0 - 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) - pip install virtualenv # virtualenv>=14.0.0 has dropped Python 3.2 support (and pypy3 is based on py32)
# Install the tox venv. # 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/') -- -e 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. # Install black for Python v3.7 only.
- if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then pip install black; fi - 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 - mongo --eval 'db.version();' # Make sure mongo is awake
script: 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 # 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 # 0% coverage. That's caused by 'use_2to3', which builds the py3-compatible
# code in a separate dir and runs tests on that. # code in a separate dir and runs tests on that.
after_success: 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: notifications:
irc: irc.freenode.org#mongoengine irc: irc.freenode.org#mongoengine
@ -109,5 +115,5 @@ deploy:
on: on:
tags: true tags: true
repo: MongoEngine/mongoengine repo: MongoEngine/mongoengine
condition: ($PYMONGO = ${PYMONGO_3_6}) && ($MONGODB = ${MONGODB_3_4}) condition: ($PYMONGO = ${PYMONGO_3_10}) && ($MONGODB = ${MONGODB_3_4})
python: 2.7 python: 2.7

View File

@ -252,3 +252,6 @@ that much better:
* Paulo Amaral (https://github.com/pauloAmaral) * Paulo Amaral (https://github.com/pauloAmaral)
* Gaurav Dadhania (https://github.com/GVRV) * Gaurav Dadhania (https://github.com/GVRV)
* Yurii Andrieiev (https://github.com/yandrieiev) * Yurii Andrieiev (https://github.com/yandrieiev)
* Filip Kucharczyk (https://github.com/Pacu2)
* Eric Timmons (https://github.com/daewok)
* Matthew Simpson (https://github.com/mcsimps2)

View File

@ -54,7 +54,7 @@ General Guidelines
should adapt to the breaking change in docs/upgrade.rst. should adapt to the breaking change in docs/upgrade.rst.
- Write inline documentation for new classes and methods. - Write inline documentation for new classes and methods.
- Write tests and make sure they pass (make sure you have a mongod - 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). from the cmd line to run the test suite).
- Ensure tests pass on all supported Python, PyMongo, and MongoDB versions. - Ensure tests pass on all supported Python, PyMongo, and MongoDB versions.
You can test various Python and PyMongo versions locally by executing You can test various Python and PyMongo versions locally by executing

View File

@ -91,12 +91,11 @@ Some simple examples of what MongoEngine code looks like:
# Iterate over all posts using the BlogPost superclass # Iterate over all posts using the BlogPost superclass
>>> for post in BlogPost.objects: >>> for post in BlogPost.objects:
... print '===', post.title, '===' ... print('===', post.title, '===')
... if isinstance(post, TextPost): ... if isinstance(post, TextPost):
... print post.content ... print(post.content)
... elif isinstance(post, LinkPost): ... elif isinstance(post, LinkPost):
... print 'Link:', post.url ... print('Link:', post.url)
... print
... ...
# Count all blog posts and its subtypes # Count all blog posts and its subtypes
@ -116,7 +115,8 @@ Some simple examples of what MongoEngine code looks like:
Tests Tests
===== =====
To run the test suite, ensure you are running a local instance of MongoDB on 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 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 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 # Run the test suites
$ tox $ 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 .. code-block:: shell
# Run all the tests in a particular test file # 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 # Run only particular test class in that file
$ python setup.py nosetests --tests tests/fields/fields.py:FieldTest $ pytest tests/fields/test_fields.py::TestField
# 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
Community Community
========= =========

View File

@ -6,6 +6,15 @@ Changelog
Development Development
=========== ===========
- (Fill this out as you fix issues and develop your features). - (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 - 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, 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(...)``. - 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. - 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 - 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. - 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 - 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 - ``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 - 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 Changes in 0.18.2
================= =================

View File

@ -11,7 +11,8 @@
# All configuration values have a default; values that are commented out # All configuration values have a default; values that are commented out
# serve to show the default. # serve to show the default.
import sys, os import os
import sys
import sphinx_rtd_theme import sphinx_rtd_theme

13
docs/faq.rst Normal file
View 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/

View File

@ -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 Deletion is denied if there still exist references to the object being
deleted. deleted.
:const:`mongoengine.NULLIFY` :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. (using MongoDB's "unset" operation), effectively nullifying the relationship.
:const:`mongoengine.CASCADE` :const:`mongoengine.CASCADE`
Any object containing fields that are referring to the object being deleted 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 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. 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 :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 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 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 Setting :attr:`allow_inheritance` to True should also be used in
:class:`~mongoengine.EmbeddedDocument` class in case you need to subclass it :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 Working with existing data
-------------------------- --------------------------
As MongoEngine no longer defaults to needing :attr:`_cls`, you can quickly and As MongoEngine no longer defaults to needing :attr:`_cls`, you can quickly and

View File

@ -10,8 +10,9 @@ Writing
GridFS support comes in the form of the :class:`~mongoengine.fields.FileField` field 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 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 different ways of inserting and retrieving data. Arbitrary metadata such as
content type can also be stored alongside the files. In the following example, content type can also be stored alongside the files. The object returned when accessing a
a document is created to store details about animals, including a photo:: 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): class Animal(Document):
genus = StringField() 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 = Animal(genus='Marmota', family='Sciuridae')
marmot_photo = open('marmot.jpg', 'rb') with open('marmot.jpg', 'rb') as fd:
marmot.photo.put(marmot_photo, content_type = 'image/jpeg') marmot.photo.put(fd, content_type = 'image/jpeg')
marmot.save() marmot.save()
Retrieval Retrieval
@ -34,6 +35,20 @@ field. The file can also be retrieved just as easily::
photo = marmot.photo.read() photo = marmot.photo.read()
content_type = marmot.photo.content_type 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 Streaming
--------- ---------

View File

@ -13,4 +13,5 @@ User Guide
gridfs gridfs
signals signals
text-indexes text-indexes
logging-monitoring
mongomock mongomock

View 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`.

View File

@ -21,7 +21,7 @@ or with an alias:
conn = get_connection('testdb') conn = get_connection('testdb')
Example of test file: Example of test file:
-------- ---------------------
.. code-block:: python .. code-block:: python
import unittest import unittest
@ -45,4 +45,4 @@ Example of test file:
pers.save() pers.save()
fresh_pers = Person.objects().first() fresh_pers = Person.objects().first()
self.assertEqual(fresh_pers.name, 'John') assert fresh_pers.name == 'John'

View File

@ -222,6 +222,18 @@ keyword argument::
.. versionadded:: 0.4 .. 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 Limiting and skipping results
============================= =============================
Just as with traditional ORMs, you may limit the number of results returned or 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 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. through :meth:`~mongoengine.queryset.QuerySet.aggregate`. Check out Pymongo's documentation for the syntax and pipeline.
An example of its use would be:: An example of its use would be::
@ -402,7 +414,7 @@ An example of its use would be::
{"$sort" : {"name" : -1}}, {"$sort" : {"name" : -1}},
{"$project": {"_id": 0, "name": {"$toUpper": "$name"}}} {"$project": {"_id": 0, "name": {"$toUpper": "$name"}}}
] ]
data = Person.objects().aggregate(*pipeline) data = Person.objects().aggregate(pipeline)
assert data == [{'name': 'BOB'}, {'name': 'JOHN'}] assert data == [{'name': 'BOB'}, {'name': 'JOHN'}]
Query efficiency and performance Query efficiency and performance
@ -585,7 +597,8 @@ cannot use the `$` syntax in keyword arguments it has been mapped to `S`::
['database', 'mongodb'] ['database', 'mongodb']
From MongoDB version 2.6, push operator supports $position value which allows 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 = BlogPost(title="Test", tags=["mongo"])
>>> post.save() >>> post.save()
>>> post.update(push__tags__0=["database", "code"]) >>> post.update(push__tags__0=["database", "code"])

View File

@ -23,9 +23,18 @@ MongoDB. To install it, simply run
:doc:`upgrade` :doc:`upgrade`
How to upgrade MongoEngine. How to upgrade MongoEngine.
:doc:`faq`
Frequently Asked Questions
:doc:`django` :doc:`django`
Using MongoEngine and 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 Community
--------- ---------
@ -73,6 +82,7 @@ formats for offline reading.
apireference apireference
changelog changelog
upgrade upgrade
faq
django django
Indices and tables Indices and tables

View File

@ -52,7 +52,7 @@ rename its occurrences.
This release includes a major rehaul of MongoEngine's code quality and This release includes a major rehaul of MongoEngine's code quality and
introduces a few breaking changes. It also touches many different parts of introduces a few breaking changes. It also touches many different parts of
the package and although all the changes have been tested and scrutinized, 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`. First breaking change involves renaming `ConnectionError` to `MongoEngineConnectionError`.
If you import or catch this exception, you'll need to rename it in your code. If you import or catch this exception, you'll need to rename it in your code.

View File

@ -28,7 +28,7 @@ __all__ = (
) )
VERSION = (0, 18, 2) VERSION = (0, 19, 1)
def get_version(): def get_version():

View File

@ -120,6 +120,9 @@ class BaseList(list):
super(BaseList, self).__init__(list_items) super(BaseList, self).__init__(list_items)
def __getitem__(self, key): 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) value = super(BaseList, self).__getitem__(key)
if isinstance(key, slice): if isinstance(key, slice):

View File

@ -62,13 +62,13 @@ class BaseDocument(object):
""" """
Initialise a document or an embedded document. 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". 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. 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. 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. or whether it's already been persisted before. Defaults to true.
""" """
self._initialised = False self._initialised = False
@ -732,7 +732,10 @@ class BaseDocument(object):
only_fields = [] only_fields = []
if son and not isinstance(son, dict): 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 # Get the class name from the document, falling back to the given
# class if unavailable # class if unavailable
@ -770,7 +773,9 @@ class BaseDocument(object):
errors_dict[field_name] = e errors_dict[field_name] = e
if errors_dict: 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" % ( msg = "Invalid data to create a `%s` instance.\n%s" % (
cls._class_name, cls._class_name,
errors, errors,

View File

@ -171,7 +171,7 @@ class no_sub_classes(object):
class query_counter(object): class query_counter(object):
"""Query_counter context manager to get the number of queries. """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, 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 This was designed for debugging purpose. In fact it is a global counter so queries issued by other threads/processes
can interfere with it 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) - 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 """Construct the query_counter
""" """
self.db = get_db() self.db = get_db(alias=alias)
self.initial_profiling_level = None self.initial_profiling_level = None
self._ctx_query_counter = 0 # number of queries issued by the context 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
) )
self._ctx_query_counter += ( self._ctx_query_counter += (
1 1 # Account for the query we just issued to gather the information
) # Account for the query we just issued to gather the information )
return count return count

View File

@ -41,6 +41,7 @@ from mongoengine.common import _import_class
from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_db from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_db
from mongoengine.document import Document, EmbeddedDocument from mongoengine.document import Document, EmbeddedDocument
from mongoengine.errors import DoesNotExist, InvalidQueryError, ValidationError 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.python_support import StringIO
from mongoengine.queryset import DO_NOTHING from mongoengine.queryset import DO_NOTHING
from mongoengine.queryset.base import BaseQuerySet from mongoengine.queryset.base import BaseQuerySet
@ -1051,6 +1052,15 @@ def key_has_dot_or_dollar(d):
return True 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): class DictField(ComplexBaseField):
"""A dictionary field that wraps a standard Python dictionary. This is """A dictionary field that wraps a standard Python dictionary. This is
similar to an embedded document, but the structure is not defined. similar to an embedded document, but the structure is not defined.
@ -1077,11 +1087,18 @@ class DictField(ComplexBaseField):
if key_not_string(value): if key_not_string(value):
msg = "Invalid dictionary key - documents must have only string keys" msg = "Invalid dictionary key - documents must have only string keys"
self.error(msg) 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( self.error(
'Invalid dictionary key name - keys may not contain "."' 'Invalid dictionary key name - keys may not contain "."'
' or startswith "$" characters' ' 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) super(DictField, self).validate(value)
def lookup_member(self, member_name): def lookup_member(self, member_name):
@ -2502,6 +2519,13 @@ class LazyReferenceField(BaseField):
else: else:
return pk 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): def validate(self, value):
if isinstance(value, LazyReference): if isinstance(value, LazyReference):
if value.collection != self.document_type._get_collection_name(): if value.collection != self.document_type._get_collection_name():

View File

@ -302,7 +302,7 @@ class BaseQuerySet(object):
``insert(..., {w: 2, fsync: True})`` will wait until at least ``insert(..., {w: 2, fsync: True})`` will wait until at least
two servers have recorded the write and will force an fsync on two servers have recorded the write and will force an fsync on
each server being written to. 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. the signal calls.
By default returns document instances, set ``load_bulk`` to False to 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) validate_read_preference("read_preference", read_preference)
queryset = self.clone() queryset = self.clone()
queryset._read_preference = read_preference queryset._read_preference = read_preference
queryset._cursor_obj = ( queryset._cursor_obj = None # we need to re-create the cursor object whenever we apply read_preference
None
) # we need to re-create the cursor object whenever we apply read_preference
return queryset return queryset
def scalar(self, *fields): def scalar(self, *fields):
@ -1257,16 +1255,27 @@ class BaseQuerySet(object):
for data in son_data for data in son_data
] ]
def aggregate(self, *pipeline, **kwargs): def aggregate(self, pipeline, *suppl_pipeline, **kwargs):
""" """Perform a aggregate function based in your queryset params
Perform a aggregate function based in your queryset params
:param pipeline: list of aggregation commands,\ :param pipeline: list of aggregation commands,\
see: http://docs.mongodb.org/manual/core/aggregation-pipeline/ 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 .. 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: if self._query:
initial_pipeline.append({"$match": self._query}) initial_pipeline.append({"$match": self._query})
@ -1283,14 +1292,14 @@ class BaseQuerySet(object):
if self._skip is not None: if self._skip is not None:
initial_pipeline.append({"$skip": self._skip}) 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: if self._read_preference is not None:
return self._collection.with_options( collection = self._collection.with_options(
read_preference=self._read_preference read_preference=self._read_preference
).aggregate(pipeline, cursor={}, **kwargs) )
return collection.aggregate(final_pipeline, cursor={}, **kwargs)
return self._collection.aggregate(pipeline, cursor={}, **kwargs)
# JS functionality # JS functionality
def map_reduce( def map_reduce(
@ -1639,6 +1648,7 @@ class BaseQuerySet(object):
).find(self._query, **self._cursor_args) ).find(self._query, **self._cursor_args)
else: else:
self._cursor_obj = self._collection.find(self._query, **self._cursor_args) self._cursor_obj = self._collection.find(self._query, **self._cursor_args)
# Apply "where" clauses to cursor # Apply "where" clauses to cursor
if self._where_clause: if self._where_clause:
where_clause = self._sub_js_fields(self._where_clause) where_clause = self._sub_js_fields(self._where_clause)

View File

@ -1,4 +1,5 @@
import copy import copy
import warnings
from mongoengine.errors import InvalidQueryError from mongoengine.errors import InvalidQueryError
from mongoengine.queryset import transform from mongoengine.queryset import transform
@ -96,9 +97,11 @@ class QNode(object):
"""Combine this node with another node into a QCombination """Combine this node with another node into a QCombination
object. object.
""" """
# If the other Q() is empty, ignore it and just use `self`.
if getattr(other, "empty", True): if getattr(other, "empty", True):
return self return self
# Or if this Q is empty, ignore it and just use `other`.
if self.empty: if self.empty:
return other return other
@ -106,6 +109,8 @@ class QNode(object):
@property @property
def empty(self): def empty(self):
msg = "'empty' property is deprecated in favour of using 'not bool(filter)'"
warnings.warn(msg, DeprecationWarning)
return False return False
def __or__(self, other): def __or__(self, other):
@ -135,6 +140,11 @@ class QCombination(QNode):
op = " & " if self.operation is self.AND else " | " op = " & " if self.operation is self.AND else " | "
return "(%s)" % op.join([repr(node) for node in self.children]) 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): def accept(self, visitor):
for i in range(len(self.children)): for i in range(len(self.children)):
if isinstance(self.children[i], QNode): if isinstance(self.children[i], QNode):
@ -144,8 +154,17 @@ class QCombination(QNode):
@property @property
def empty(self): def empty(self):
msg = "'empty' property is deprecated in favour of using 'not bool(filter)'"
warnings.warn(msg, DeprecationWarning)
return not bool(self.children) 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): class Q(QNode):
"""A simple query object, used in a query tree to build up more complex """A simple query object, used in a query tree to build up more complex
@ -158,6 +177,14 @@ class Q(QNode):
def __repr__(self): def __repr__(self):
return "Q(**%s)" % repr(self.query) 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): def accept(self, visitor):
return visitor.visit_query(self) return visitor.visit_query(self)

View File

@ -1,4 +1,3 @@
nose
pymongo>=3.4 pymongo>=3.4
six==1.10.0 six==1.10.0
Sphinx==1.5.5 Sphinx==1.5.5

View File

@ -1,11 +1,10 @@
[nosetests]
verbosity=2
detailed-errors=1
#tests=tests
cover-package=mongoengine
[flake8] [flake8]
ignore=E501,F401,F403,F405,I201,I202,W504, W605, W503 ignore=E501,F401,F403,F405,I201,I202,W504, W605, W503
exclude=build,dist,docs,venv,venv3,.tox,.eggs,tests exclude=build,dist,docs,venv,venv3,.tox,.eggs,tests
max-complexity=47 max-complexity=47
application-import-names=mongoengine,tests application-import-names=mongoengine,tests
[tool:pytest]
# Limits the discovery to tests directory
# avoids that it runs for instance the benchmark
testpaths = tests

View File

@ -1,6 +1,9 @@
import os import os
import sys import sys
from pkg_resources import normalize_path
from setuptools import find_packages, setup from setuptools import find_packages, setup
from setuptools.command.test import test as TestCommand
# Hack to silence atexit traceback in newer python versions # Hack to silence atexit traceback in newer python versions
try: try:
@ -24,6 +27,62 @@ def get_version(version_tuple):
return ".".join(map(str, 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 # 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 # import it as it depends on PyMongo and PyMongo isn't installed until this
# file is read # file is read
@ -51,11 +110,17 @@ CLASSIFIERS = [
extra_opts = { extra_opts = {
"packages": find_packages(exclude=["tests", "tests.*"]), "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: if sys.version_info[0] == 3:
extra_opts["use_2to3"] = True 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["packages"] = find_packages()
extra_opts["package_data"] = { extra_opts["package_data"] = {
"tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"] "tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"]
@ -78,7 +143,7 @@ setup(
long_description=LONG_DESCRIPTION, long_description=LONG_DESCRIPTION,
platforms=["any"], platforms=["any"],
classifiers=CLASSIFIERS, classifiers=CLASSIFIERS,
install_requires=["pymongo>=3.4", "six"], install_requires=["pymongo>=3.4, <4.0", "six>=1.10.0"],
test_suite="nose.collector", cmdclass={"test": PyTest},
**extra_opts **extra_opts
) )

View File

@ -31,7 +31,5 @@ class TestAllWarnings(unittest.TestCase):
meta = {"collection": "fail"} meta = {"collection": "fail"}
warning = self.warning_list[0] warning = self.warning_list[0]
self.assertEqual(SyntaxWarning, warning["category"]) assert SyntaxWarning == warning["category"]
self.assertEqual( assert "non_abstract_base" == InheritedDocumentFailTest._get_collection_name()
"non_abstract_base", InheritedDocumentFailTest._get_collection_name()
)

View File

@ -29,43 +29,40 @@ class TestClassMethods(unittest.TestCase):
def test_definition(self): def test_definition(self):
"""Ensure that document may be defined using fields. """Ensure that document may be defined using fields.
""" """
self.assertEqual( assert ["_cls", "age", "id", "name"] == sorted(self.Person._fields.keys())
["_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()]
self.assertEqual(
["IntField", "ObjectIdField", "StringField", "StringField"],
sorted([x.__class__.__name__ for x in self.Person._fields.values()]),
) )
def test_get_db(self): def test_get_db(self):
"""Ensure that get_db returns the expected db. """Ensure that get_db returns the expected db.
""" """
db = self.Person._get_db() db = self.Person._get_db()
self.assertEqual(self.db, db) assert self.db == db
def test_get_collection_name(self): def test_get_collection_name(self):
"""Ensure that get_collection_name returns the expected collection """Ensure that get_collection_name returns the expected collection
name. name.
""" """
collection_name = "person" 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): def test_get_collection(self):
"""Ensure that get_collection returns the expected collection. """Ensure that get_collection returns the expected collection.
""" """
collection_name = "person" collection_name = "person"
collection = self.Person._get_collection() collection = self.Person._get_collection()
self.assertEqual(self.db[collection_name], collection) assert self.db[collection_name] == collection
def test_drop_collection(self): def test_drop_collection(self):
"""Ensure that the collection may be dropped from the database. """Ensure that the collection may be dropped from the database.
""" """
collection_name = "person" collection_name = "person"
self.Person(name="Test").save() 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.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): def test_register_delete_rule(self):
"""Ensure that register delete rule adds a delete rule to the document """Ensure that register delete rule adds a delete rule to the document
@ -75,12 +72,10 @@ class TestClassMethods(unittest.TestCase):
class Job(Document): class Job(Document):
employee = ReferenceField(self.Person) 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.Person.register_delete_rule(Job, "employee", NULLIFY)
self.assertEqual( assert self.Person._meta["delete_rules"] == {(Job, "employee"): NULLIFY}
self.Person._meta["delete_rules"], {(Job, "employee"): NULLIFY}
)
def test_compare_indexes(self): def test_compare_indexes(self):
""" Ensure that the indexes are properly created and that """ Ensure that the indexes are properly created and that
@ -98,22 +93,22 @@ class TestClassMethods(unittest.TestCase):
BlogPost.drop_collection() BlogPost.drop_collection()
BlogPost.ensure_indexes() BlogPost.ensure_indexes()
self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) assert BlogPost.compare_indexes() == {"missing": [], "extra": []}
BlogPost.ensure_index(["author", "description"]) BlogPost.ensure_index(["author", "description"])
self.assertEqual( assert BlogPost.compare_indexes() == {
BlogPost.compare_indexes(), "missing": [],
{"missing": [], "extra": [[("author", 1), ("description", 1)]]}, "extra": [[("author", 1), ("description", 1)]],
) }
BlogPost._get_collection().drop_index("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") BlogPost._get_collection().drop_index("author_1_title_1")
self.assertEqual( assert BlogPost.compare_indexes() == {
BlogPost.compare_indexes(), "missing": [[("author", 1), ("title", 1)]],
{"missing": [[("author", 1), ("title", 1)]], "extra": []}, "extra": [],
) }
def test_compare_indexes_inheritance(self): def test_compare_indexes_inheritance(self):
""" Ensure that the indexes are properly created and that """ Ensure that the indexes are properly created and that
@ -138,22 +133,22 @@ class TestClassMethods(unittest.TestCase):
BlogPost.ensure_indexes() BlogPost.ensure_indexes()
BlogPostWithTags.ensure_indexes() BlogPostWithTags.ensure_indexes()
self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) assert BlogPost.compare_indexes() == {"missing": [], "extra": []}
BlogPostWithTags.ensure_index(["author", "tag_list"]) BlogPostWithTags.ensure_index(["author", "tag_list"])
self.assertEqual( assert BlogPost.compare_indexes() == {
BlogPost.compare_indexes(), "missing": [],
{"missing": [], "extra": [[("_cls", 1), ("author", 1), ("tag_list", 1)]]}, "extra": [[("_cls", 1), ("author", 1), ("tag_list", 1)]],
) }
BlogPostWithTags._get_collection().drop_index("_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") BlogPostWithTags._get_collection().drop_index("_cls_1_author_1_tags_1")
self.assertEqual( assert BlogPost.compare_indexes() == {
BlogPost.compare_indexes(), "missing": [[("_cls", 1), ("author", 1), ("tags", 1)]],
{"missing": [[("_cls", 1), ("author", 1), ("tags", 1)]], "extra": []}, "extra": [],
) }
def test_compare_indexes_multiple_subclasses(self): def test_compare_indexes_multiple_subclasses(self):
""" Ensure that compare_indexes behaves correctly if called from a """ Ensure that compare_indexes behaves correctly if called from a
@ -182,13 +177,9 @@ class TestClassMethods(unittest.TestCase):
BlogPostWithTags.ensure_indexes() BlogPostWithTags.ensure_indexes()
BlogPostWithCustomField.ensure_indexes() BlogPostWithCustomField.ensure_indexes()
self.assertEqual(BlogPost.compare_indexes(), {"missing": [], "extra": []}) assert BlogPost.compare_indexes() == {"missing": [], "extra": []}
self.assertEqual( assert BlogPostWithTags.compare_indexes() == {"missing": [], "extra": []}
BlogPostWithTags.compare_indexes(), {"missing": [], "extra": []} assert BlogPostWithCustomField.compare_indexes() == {"missing": [], "extra": []}
)
self.assertEqual(
BlogPostWithCustomField.compare_indexes(), {"missing": [], "extra": []}
)
def test_compare_indexes_for_text_indexes(self): def test_compare_indexes_for_text_indexes(self):
""" Ensure that compare_indexes behaves correctly for text indexes """ """ Ensure that compare_indexes behaves correctly for text indexes """
@ -210,7 +201,7 @@ class TestClassMethods(unittest.TestCase):
Doc.ensure_indexes() Doc.ensure_indexes()
actual = Doc.compare_indexes() actual = Doc.compare_indexes()
expected = {"missing": [], "extra": []} expected = {"missing": [], "extra": []}
self.assertEqual(actual, expected) assert actual == expected
def test_list_indexes_inheritance(self): def test_list_indexes_inheritance(self):
""" ensure that all of the indexes are listed regardless of the super- """ ensure that all of the indexes are listed regardless of the super-
@ -240,19 +231,14 @@ class TestClassMethods(unittest.TestCase):
BlogPostWithTags.ensure_indexes() BlogPostWithTags.ensure_indexes()
BlogPostWithTagsAndExtraText.ensure_indexes() BlogPostWithTagsAndExtraText.ensure_indexes()
self.assertEqual(BlogPost.list_indexes(), BlogPostWithTags.list_indexes()) assert BlogPost.list_indexes() == BlogPostWithTags.list_indexes()
self.assertEqual( assert BlogPost.list_indexes() == BlogPostWithTagsAndExtraText.list_indexes()
BlogPost.list_indexes(), BlogPostWithTagsAndExtraText.list_indexes() assert BlogPost.list_indexes() == [
) [("_cls", 1), ("author", 1), ("tags", 1)],
self.assertEqual( [("_cls", 1), ("author", 1), ("tags", 1), ("extra_text", 1)],
BlogPost.list_indexes(), [(u"_id", 1)],
[ [("_cls", 1)],
[("_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): def test_register_delete_rule_inherited(self):
class Vaccine(Document): class Vaccine(Document):
@ -271,8 +257,8 @@ class TestClassMethods(unittest.TestCase):
class Cat(Animal): class Cat(Animal):
name = StringField(required=True) name = StringField(required=True)
self.assertEqual(Vaccine._meta["delete_rules"][(Animal, "vaccine_made")], PULL) assert Vaccine._meta["delete_rules"][(Animal, "vaccine_made")] == PULL
self.assertEqual(Vaccine._meta["delete_rules"][(Cat, "vaccine_made")], PULL) assert Vaccine._meta["delete_rules"][(Cat, "vaccine_made")] == PULL
def test_collection_naming(self): def test_collection_naming(self):
"""Ensure that a collection with a specified name may be used. """Ensure that a collection with a specified name may be used.
@ -281,19 +267,17 @@ class TestClassMethods(unittest.TestCase):
class DefaultNamingTest(Document): class DefaultNamingTest(Document):
pass pass
self.assertEqual( assert "default_naming_test" == DefaultNamingTest._get_collection_name()
"default_naming_test", DefaultNamingTest._get_collection_name()
)
class CustomNamingTest(Document): class CustomNamingTest(Document):
meta = {"collection": "pimp_my_collection"} 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): class DynamicNamingTest(Document):
meta = {"collection": lambda c: "DYNAMO"} 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 # Use Abstract class to handle backwards compatibility
class BaseDocument(Document): class BaseDocument(Document):
@ -302,14 +286,12 @@ class TestClassMethods(unittest.TestCase):
class OldNamingConvention(BaseDocument): class OldNamingConvention(BaseDocument):
pass pass
self.assertEqual( assert "oldnamingconvention" == OldNamingConvention._get_collection_name()
"oldnamingconvention", OldNamingConvention._get_collection_name()
)
class InheritedAbstractNamingTest(BaseDocument): class InheritedAbstractNamingTest(BaseDocument):
meta = {"collection": "wibble"} meta = {"collection": "wibble"}
self.assertEqual("wibble", InheritedAbstractNamingTest._get_collection_name()) assert "wibble" == InheritedAbstractNamingTest._get_collection_name()
# Mixin tests # Mixin tests
class BaseMixin(object): class BaseMixin(object):
@ -318,8 +300,9 @@ class TestClassMethods(unittest.TestCase):
class OldMixinNamingConvention(Document, BaseMixin): class OldMixinNamingConvention(Document, BaseMixin):
pass pass
self.assertEqual( assert (
"oldmixinnamingconvention", OldMixinNamingConvention._get_collection_name() "oldmixinnamingconvention"
== OldMixinNamingConvention._get_collection_name()
) )
class BaseMixin(object): class BaseMixin(object):
@ -331,7 +314,7 @@ class TestClassMethods(unittest.TestCase):
class MyDocument(BaseDocument): class MyDocument(BaseDocument):
pass pass
self.assertEqual("basedocument", MyDocument._get_collection_name()) assert "basedocument" == MyDocument._get_collection_name()
def test_custom_collection_name_operations(self): def test_custom_collection_name_operations(self):
"""Ensure that a collection with a specified name is used as expected. """Ensure that a collection with a specified name is used as expected.
@ -343,16 +326,16 @@ class TestClassMethods(unittest.TestCase):
meta = {"collection": collection_name} meta = {"collection": collection_name}
Person(name="Test User").save() 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() 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] user_obj = Person.objects[0]
self.assertEqual(user_obj.name, "Test User") assert user_obj.name == "Test User"
Person.drop_collection() 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): def test_collection_name_and_primary(self):
"""Ensure that a collection with a specified name may be used. """Ensure that a collection with a specified name may be used.
@ -365,7 +348,7 @@ class TestClassMethods(unittest.TestCase):
Person(name="Test User").save() Person(name="Test User").save()
user_obj = Person.objects.first() user_obj = Person.objects.first()
self.assertEqual(user_obj.name, "Test User") assert user_obj.name == "Test User"
Person.drop_collection() Person.drop_collection()

View File

@ -41,40 +41,40 @@ class TestDelta(MongoDBTestCase):
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc._get_changed_fields(), []) assert doc._get_changed_fields() == []
self.assertEqual(doc._delta(), ({}, {})) assert doc._delta() == ({}, {})
doc.string_field = "hello" doc.string_field = "hello"
self.assertEqual(doc._get_changed_fields(), ["string_field"]) assert doc._get_changed_fields() == ["string_field"]
self.assertEqual(doc._delta(), ({"string_field": "hello"}, {})) assert doc._delta() == ({"string_field": "hello"}, {})
doc._changed_fields = [] doc._changed_fields = []
doc.int_field = 1 doc.int_field = 1
self.assertEqual(doc._get_changed_fields(), ["int_field"]) assert doc._get_changed_fields() == ["int_field"]
self.assertEqual(doc._delta(), ({"int_field": 1}, {})) assert doc._delta() == ({"int_field": 1}, {})
doc._changed_fields = [] doc._changed_fields = []
dict_value = {"hello": "world", "ping": "pong"} dict_value = {"hello": "world", "ping": "pong"}
doc.dict_field = dict_value doc.dict_field = dict_value
self.assertEqual(doc._get_changed_fields(), ["dict_field"]) assert doc._get_changed_fields() == ["dict_field"]
self.assertEqual(doc._delta(), ({"dict_field": dict_value}, {})) assert doc._delta() == ({"dict_field": dict_value}, {})
doc._changed_fields = [] doc._changed_fields = []
list_value = ["1", 2, {"hello": "world"}] list_value = ["1", 2, {"hello": "world"}]
doc.list_field = list_value doc.list_field = list_value
self.assertEqual(doc._get_changed_fields(), ["list_field"]) assert doc._get_changed_fields() == ["list_field"]
self.assertEqual(doc._delta(), ({"list_field": list_value}, {})) assert doc._delta() == ({"list_field": list_value}, {})
# Test unsetting # Test unsetting
doc._changed_fields = [] doc._changed_fields = []
doc.dict_field = {} doc.dict_field = {}
self.assertEqual(doc._get_changed_fields(), ["dict_field"]) assert doc._get_changed_fields() == ["dict_field"]
self.assertEqual(doc._delta(), ({}, {"dict_field": 1})) assert doc._delta() == ({}, {"dict_field": 1})
doc._changed_fields = [] doc._changed_fields = []
doc.list_field = [] doc.list_field = []
self.assertEqual(doc._get_changed_fields(), ["list_field"]) assert doc._get_changed_fields() == ["list_field"]
self.assertEqual(doc._delta(), ({}, {"list_field": 1})) assert doc._delta() == ({}, {"list_field": 1})
def test_delta_recursive(self): def test_delta_recursive(self):
self.delta_recursive(Document, EmbeddedDocument) self.delta_recursive(Document, EmbeddedDocument)
@ -102,8 +102,8 @@ class TestDelta(MongoDBTestCase):
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc._get_changed_fields(), []) assert doc._get_changed_fields() == []
self.assertEqual(doc._delta(), ({}, {})) assert doc._delta() == ({}, {})
embedded_1 = Embedded() embedded_1 = Embedded()
embedded_1.id = "010101" embedded_1.id = "010101"
@ -113,7 +113,7 @@ class TestDelta(MongoDBTestCase):
embedded_1.list_field = ["1", 2, {"hello": "world"}] embedded_1.list_field = ["1", 2, {"hello": "world"}]
doc.embedded_field = embedded_1 doc.embedded_field = embedded_1
self.assertEqual(doc._get_changed_fields(), ["embedded_field"]) assert doc._get_changed_fields() == ["embedded_field"]
embedded_delta = { embedded_delta = {
"id": "010101", "id": "010101",
@ -122,27 +122,27 @@ class TestDelta(MongoDBTestCase):
"dict_field": {"hello": "world"}, "dict_field": {"hello": "world"},
"list_field": ["1", 2, {"hello": "world"}], "list_field": ["1", 2, {"hello": "world"}],
} }
self.assertEqual(doc.embedded_field._delta(), (embedded_delta, {})) assert doc.embedded_field._delta() == (embedded_delta, {})
self.assertEqual(doc._delta(), ({"embedded_field": embedded_delta}, {})) assert doc._delta() == ({"embedded_field": embedded_delta}, {})
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
doc.embedded_field.dict_field = {} doc.embedded_field.dict_field = {}
self.assertEqual(doc._get_changed_fields(), ["embedded_field.dict_field"]) assert doc._get_changed_fields() == ["embedded_field.dict_field"]
self.assertEqual(doc.embedded_field._delta(), ({}, {"dict_field": 1})) assert doc.embedded_field._delta() == ({}, {"dict_field": 1})
self.assertEqual(doc._delta(), ({}, {"embedded_field.dict_field": 1})) assert doc._delta() == ({}, {"embedded_field.dict_field": 1})
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.embedded_field.dict_field, {}) assert doc.embedded_field.dict_field == {}
doc.embedded_field.list_field = [] doc.embedded_field.list_field = []
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})) assert doc.embedded_field._delta() == ({}, {"list_field": 1})
self.assertEqual(doc._delta(), ({}, {"embedded_field.list_field": 1})) assert doc._delta() == ({}, {"embedded_field.list_field": 1})
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.embedded_field.list_field, []) assert doc.embedded_field.list_field == []
embedded_2 = Embedded() embedded_2 = Embedded()
embedded_2.string_field = "hello" embedded_2.string_field = "hello"
@ -151,148 +151,128 @@ class TestDelta(MongoDBTestCase):
embedded_2.list_field = ["1", 2, {"hello": "world"}] embedded_2.list_field = ["1", 2, {"hello": "world"}]
doc.embedded_field.list_field = ["1", 2, embedded_2] 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( assert doc.embedded_field._delta() == (
doc.embedded_field._delta(), {
( "list_field": [
{ "1",
"list_field": [ 2,
"1", {
2, "_cls": "Embedded",
{ "string_field": "hello",
"_cls": "Embedded", "dict_field": {"hello": "world"},
"string_field": "hello", "int_field": 1,
"dict_field": {"hello": "world"}, "list_field": ["1", 2, {"hello": "world"}],
"int_field": 1, },
"list_field": ["1", 2, {"hello": "world"}], ]
}, },
] {},
},
{},
),
) )
self.assertEqual( assert doc._delta() == (
doc._delta(), {
( "embedded_field.list_field": [
{ "1",
"embedded_field.list_field": [ 2,
"1", {
2, "_cls": "Embedded",
{ "string_field": "hello",
"_cls": "Embedded", "dict_field": {"hello": "world"},
"string_field": "hello", "int_field": 1,
"dict_field": {"hello": "world"}, "list_field": ["1", 2, {"hello": "world"}],
"int_field": 1, },
"list_field": ["1", 2, {"hello": "world"}], ]
}, },
] {},
},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.embedded_field.list_field[0], "1") assert doc.embedded_field.list_field[0] == "1"
self.assertEqual(doc.embedded_field.list_field[1], 2) assert doc.embedded_field.list_field[1] == 2
for k in doc.embedded_field.list_field[2]._fields: 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" doc.embedded_field.list_field[2].string_field = "world"
self.assertEqual( assert doc._get_changed_fields() == ["embedded_field.list_field.2.string_field"]
doc._get_changed_fields(), ["embedded_field.list_field.2.string_field"] assert doc.embedded_field._delta() == (
{"list_field.2.string_field": "world"},
{},
) )
self.assertEqual( assert doc._delta() == (
doc.embedded_field._delta(), ({"list_field.2.string_field": "world"}, {}) {"embedded_field.list_field.2.string_field": "world"},
) {},
self.assertEqual(
doc._delta(), ({"embedded_field.list_field.2.string_field": "world"}, {})
) )
doc.save() doc.save()
doc = doc.reload(10) 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 # Test multiple assignments
doc.embedded_field.list_field[2].string_field = "hello world" doc.embedded_field.list_field[2].string_field = "hello world"
doc.embedded_field.list_field[2] = doc.embedded_field.list_field[2] doc.embedded_field.list_field[2] = doc.embedded_field.list_field[2]
self.assertEqual(doc._get_changed_fields(), ["embedded_field.list_field.2"]) assert doc._get_changed_fields() == ["embedded_field.list_field.2"]
self.assertEqual( assert doc.embedded_field._delta() == (
doc.embedded_field._delta(), {
( "list_field.2": {
{ "_cls": "Embedded",
"list_field.2": { "string_field": "hello world",
"_cls": "Embedded", "int_field": 1,
"string_field": "hello world", "list_field": ["1", 2, {"hello": "world"}],
"int_field": 1, "dict_field": {"hello": "world"},
"list_field": ["1", 2, {"hello": "world"}], }
"dict_field": {"hello": "world"}, },
} {},
},
{},
),
) )
self.assertEqual( assert doc._delta() == (
doc._delta(), {
( "embedded_field.list_field.2": {
{ "_cls": "Embedded",
"embedded_field.list_field.2": { "string_field": "hello world",
"_cls": "Embedded", "int_field": 1,
"string_field": "hello world", "list_field": ["1", 2, {"hello": "world"}],
"int_field": 1, "dict_field": {"hello": "world"},
"list_field": ["1", 2, {"hello": "world"}], }
"dict_field": {"hello": "world"}, },
} {},
},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) 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 # Test list native methods
doc.embedded_field.list_field[2].list_field.pop(0) doc.embedded_field.list_field[2].list_field.pop(0)
self.assertEqual( assert doc._delta() == (
doc._delta(), {"embedded_field.list_field.2.list_field": [2, {"hello": "world"}]},
({"embedded_field.list_field.2.list_field": [2, {"hello": "world"}]}, {}), {},
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
doc.embedded_field.list_field[2].list_field.append(1) doc.embedded_field.list_field[2].list_field.append(1)
self.assertEqual( assert doc._delta() == (
doc._delta(), {"embedded_field.list_field.2.list_field": [2, {"hello": "world"}, 1]},
( {},
{"embedded_field.list_field.2.list_field": [2, {"hello": "world"}, 1]},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual( assert doc.embedded_field.list_field[2].list_field == [2, {"hello": "world"}, 1]
doc.embedded_field.list_field[2].list_field, [2, {"hello": "world"}, 1]
)
doc.embedded_field.list_field[2].list_field.sort(key=str) doc.embedded_field.list_field[2].list_field.sort(key=str)
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual( assert doc.embedded_field.list_field[2].list_field == [1, 2, {"hello": "world"}]
doc.embedded_field.list_field[2].list_field, [1, 2, {"hello": "world"}]
)
del doc.embedded_field.list_field[2].list_field[2]["hello"] del doc.embedded_field.list_field[2].list_field[2]["hello"]
self.assertEqual( assert doc._delta() == (
doc._delta(), ({}, {"embedded_field.list_field.2.list_field.2.hello": 1}) {},
{"embedded_field.list_field.2.list_field.2.hello": 1},
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
del doc.embedded_field.list_field[2].list_field del doc.embedded_field.list_field[2].list_field
self.assertEqual( assert doc._delta() == ({}, {"embedded_field.list_field.2.list_field": 1})
doc._delta(), ({}, {"embedded_field.list_field.2.list_field": 1})
)
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
@ -302,12 +282,8 @@ class TestDelta(MongoDBTestCase):
doc = doc.reload(10) doc = doc.reload(10)
doc.dict_field["Embedded"].string_field = "Hello World" doc.dict_field["Embedded"].string_field = "Hello World"
self.assertEqual( assert doc._get_changed_fields() == ["dict_field.Embedded.string_field"]
doc._get_changed_fields(), ["dict_field.Embedded.string_field"] assert doc._delta() == ({"dict_field.Embedded.string_field": "Hello World"}, {})
)
self.assertEqual(
doc._delta(), ({"dict_field.Embedded.string_field": "Hello World"}, {})
)
def test_circular_reference_deltas(self): def test_circular_reference_deltas(self):
self.circular_reference_deltas(Document, Document) self.circular_reference_deltas(Document, Document)
@ -338,8 +314,8 @@ class TestDelta(MongoDBTestCase):
p = Person.objects[0].select_related() p = Person.objects[0].select_related()
o = Organization.objects.first() o = Organization.objects.first()
self.assertEqual(p.owns[0], o) assert p.owns[0] == o
self.assertEqual(o.owner, p) assert o.owner == p
def test_circular_reference_deltas_2(self): def test_circular_reference_deltas_2(self):
self.circular_reference_deltas_2(Document, Document) self.circular_reference_deltas_2(Document, Document)
@ -379,9 +355,9 @@ class TestDelta(MongoDBTestCase):
e = Person.objects.get(name="employee") e = Person.objects.get(name="employee")
o = Organization.objects.first() o = Organization.objects.first()
self.assertEqual(p.owns[0], o) assert p.owns[0] == o
self.assertEqual(o.owner, p) assert o.owner == p
self.assertEqual(e.employer, o) assert e.employer == o
return person, organization, employee return person, organization, employee
@ -401,40 +377,40 @@ class TestDelta(MongoDBTestCase):
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc._get_changed_fields(), []) assert doc._get_changed_fields() == []
self.assertEqual(doc._delta(), ({}, {})) assert doc._delta() == ({}, {})
doc.string_field = "hello" doc.string_field = "hello"
self.assertEqual(doc._get_changed_fields(), ["db_string_field"]) assert doc._get_changed_fields() == ["db_string_field"]
self.assertEqual(doc._delta(), ({"db_string_field": "hello"}, {})) assert doc._delta() == ({"db_string_field": "hello"}, {})
doc._changed_fields = [] doc._changed_fields = []
doc.int_field = 1 doc.int_field = 1
self.assertEqual(doc._get_changed_fields(), ["db_int_field"]) assert doc._get_changed_fields() == ["db_int_field"]
self.assertEqual(doc._delta(), ({"db_int_field": 1}, {})) assert doc._delta() == ({"db_int_field": 1}, {})
doc._changed_fields = [] doc._changed_fields = []
dict_value = {"hello": "world", "ping": "pong"} dict_value = {"hello": "world", "ping": "pong"}
doc.dict_field = dict_value doc.dict_field = dict_value
self.assertEqual(doc._get_changed_fields(), ["db_dict_field"]) assert doc._get_changed_fields() == ["db_dict_field"]
self.assertEqual(doc._delta(), ({"db_dict_field": dict_value}, {})) assert doc._delta() == ({"db_dict_field": dict_value}, {})
doc._changed_fields = [] doc._changed_fields = []
list_value = ["1", 2, {"hello": "world"}] list_value = ["1", 2, {"hello": "world"}]
doc.list_field = list_value doc.list_field = list_value
self.assertEqual(doc._get_changed_fields(), ["db_list_field"]) assert doc._get_changed_fields() == ["db_list_field"]
self.assertEqual(doc._delta(), ({"db_list_field": list_value}, {})) assert doc._delta() == ({"db_list_field": list_value}, {})
# Test unsetting # Test unsetting
doc._changed_fields = [] doc._changed_fields = []
doc.dict_field = {} doc.dict_field = {}
self.assertEqual(doc._get_changed_fields(), ["db_dict_field"]) assert doc._get_changed_fields() == ["db_dict_field"]
self.assertEqual(doc._delta(), ({}, {"db_dict_field": 1})) assert doc._delta() == ({}, {"db_dict_field": 1})
doc._changed_fields = [] doc._changed_fields = []
doc.list_field = [] doc.list_field = []
self.assertEqual(doc._get_changed_fields(), ["db_list_field"]) assert doc._get_changed_fields() == ["db_list_field"]
self.assertEqual(doc._delta(), ({}, {"db_list_field": 1})) assert doc._delta() == ({}, {"db_list_field": 1})
# Test it saves that data # Test it saves that data
doc = Doc() doc = Doc()
@ -447,10 +423,10 @@ class TestDelta(MongoDBTestCase):
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.string_field, "hello") assert doc.string_field == "hello"
self.assertEqual(doc.int_field, 1) assert doc.int_field == 1
self.assertEqual(doc.dict_field, {"hello": "world"}) assert doc.dict_field == {"hello": "world"}
self.assertEqual(doc.list_field, ["1", 2, {"hello": "world"}]) assert doc.list_field == ["1", 2, {"hello": "world"}]
def test_delta_recursive_db_field(self): def test_delta_recursive_db_field(self):
self.delta_recursive_db_field(Document, EmbeddedDocument) self.delta_recursive_db_field(Document, EmbeddedDocument)
@ -479,8 +455,8 @@ class TestDelta(MongoDBTestCase):
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc._get_changed_fields(), []) assert doc._get_changed_fields() == []
self.assertEqual(doc._delta(), ({}, {})) assert doc._delta() == ({}, {})
embedded_1 = Embedded() embedded_1 = Embedded()
embedded_1.string_field = "hello" embedded_1.string_field = "hello"
@ -489,7 +465,7 @@ class TestDelta(MongoDBTestCase):
embedded_1.list_field = ["1", 2, {"hello": "world"}] embedded_1.list_field = ["1", 2, {"hello": "world"}]
doc.embedded_field = embedded_1 doc.embedded_field = embedded_1
self.assertEqual(doc._get_changed_fields(), ["db_embedded_field"]) assert doc._get_changed_fields() == ["db_embedded_field"]
embedded_delta = { embedded_delta = {
"db_string_field": "hello", "db_string_field": "hello",
@ -497,27 +473,27 @@ class TestDelta(MongoDBTestCase):
"db_dict_field": {"hello": "world"}, "db_dict_field": {"hello": "world"},
"db_list_field": ["1", 2, {"hello": "world"}], "db_list_field": ["1", 2, {"hello": "world"}],
} }
self.assertEqual(doc.embedded_field._delta(), (embedded_delta, {})) assert doc.embedded_field._delta() == (embedded_delta, {})
self.assertEqual(doc._delta(), ({"db_embedded_field": embedded_delta}, {})) assert doc._delta() == ({"db_embedded_field": embedded_delta}, {})
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
doc.embedded_field.dict_field = {} doc.embedded_field.dict_field = {}
self.assertEqual(doc._get_changed_fields(), ["db_embedded_field.db_dict_field"]) assert doc._get_changed_fields() == ["db_embedded_field.db_dict_field"]
self.assertEqual(doc.embedded_field._delta(), ({}, {"db_dict_field": 1})) assert doc.embedded_field._delta() == ({}, {"db_dict_field": 1})
self.assertEqual(doc._delta(), ({}, {"db_embedded_field.db_dict_field": 1})) assert doc._delta() == ({}, {"db_embedded_field.db_dict_field": 1})
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.embedded_field.dict_field, {}) assert doc.embedded_field.dict_field == {}
doc.embedded_field.list_field = [] doc.embedded_field.list_field = []
self.assertEqual(doc._get_changed_fields(), ["db_embedded_field.db_list_field"]) assert doc._get_changed_fields() == ["db_embedded_field.db_list_field"]
self.assertEqual(doc.embedded_field._delta(), ({}, {"db_list_field": 1})) assert doc.embedded_field._delta() == ({}, {"db_list_field": 1})
self.assertEqual(doc._delta(), ({}, {"db_embedded_field.db_list_field": 1})) assert doc._delta() == ({}, {"db_embedded_field.db_list_field": 1})
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.embedded_field.list_field, []) assert doc.embedded_field.list_field == []
embedded_2 = Embedded() embedded_2 = Embedded()
embedded_2.string_field = "hello" embedded_2.string_field = "hello"
@ -526,166 +502,142 @@ class TestDelta(MongoDBTestCase):
embedded_2.list_field = ["1", 2, {"hello": "world"}] embedded_2.list_field = ["1", 2, {"hello": "world"}]
doc.embedded_field.list_field = ["1", 2, embedded_2] doc.embedded_field.list_field = ["1", 2, embedded_2]
self.assertEqual(doc._get_changed_fields(), ["db_embedded_field.db_list_field"]) assert doc._get_changed_fields() == ["db_embedded_field.db_list_field"]
self.assertEqual( assert doc.embedded_field._delta() == (
doc.embedded_field._delta(), {
( "db_list_field": [
{ "1",
"db_list_field": [ 2,
"1", {
2, "_cls": "Embedded",
{ "db_string_field": "hello",
"_cls": "Embedded", "db_dict_field": {"hello": "world"},
"db_string_field": "hello", "db_int_field": 1,
"db_dict_field": {"hello": "world"}, "db_list_field": ["1", 2, {"hello": "world"}],
"db_int_field": 1, },
"db_list_field": ["1", 2, {"hello": "world"}], ]
}, },
] {},
},
{},
),
) )
self.assertEqual( assert doc._delta() == (
doc._delta(), {
( "db_embedded_field.db_list_field": [
{ "1",
"db_embedded_field.db_list_field": [ 2,
"1", {
2, "_cls": "Embedded",
{ "db_string_field": "hello",
"_cls": "Embedded", "db_dict_field": {"hello": "world"},
"db_string_field": "hello", "db_int_field": 1,
"db_dict_field": {"hello": "world"}, "db_list_field": ["1", 2, {"hello": "world"}],
"db_int_field": 1, },
"db_list_field": ["1", 2, {"hello": "world"}], ]
}, },
] {},
},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual(doc.embedded_field.list_field[0], "1") assert doc.embedded_field.list_field[0] == "1"
self.assertEqual(doc.embedded_field.list_field[1], 2) assert doc.embedded_field.list_field[1] == 2
for k in doc.embedded_field.list_field[2]._fields: 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" doc.embedded_field.list_field[2].string_field = "world"
self.assertEqual( assert doc._get_changed_fields() == [
doc._get_changed_fields(), "db_embedded_field.db_list_field.2.db_string_field"
["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( assert doc._delta() == (
doc.embedded_field._delta(), {"db_embedded_field.db_list_field.2.db_string_field": "world"},
({"db_list_field.2.db_string_field": "world"}, {}), {},
)
self.assertEqual(
doc._delta(),
({"db_embedded_field.db_list_field.2.db_string_field": "world"}, {}),
) )
doc.save() doc.save()
doc = doc.reload(10) 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 # Test multiple assignments
doc.embedded_field.list_field[2].string_field = "hello world" doc.embedded_field.list_field[2].string_field = "hello world"
doc.embedded_field.list_field[2] = doc.embedded_field.list_field[2] doc.embedded_field.list_field[2] = doc.embedded_field.list_field[2]
self.assertEqual( assert doc._get_changed_fields() == ["db_embedded_field.db_list_field.2"]
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( assert doc._delta() == (
doc.embedded_field._delta(), {
( "db_embedded_field.db_list_field.2": {
{ "_cls": "Embedded",
"db_list_field.2": { "db_string_field": "hello world",
"_cls": "Embedded", "db_int_field": 1,
"db_string_field": "hello world", "db_list_field": ["1", 2, {"hello": "world"}],
"db_int_field": 1, "db_dict_field": {"hello": "world"},
"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"},
}
},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) 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 # Test list native methods
doc.embedded_field.list_field[2].list_field.pop(0) doc.embedded_field.list_field[2].list_field.pop(0)
self.assertEqual( assert doc._delta() == (
doc._delta(), {
( "db_embedded_field.db_list_field.2.db_list_field": [
{ 2,
"db_embedded_field.db_list_field.2.db_list_field": [ {"hello": "world"},
2, ]
{"hello": "world"}, },
] {},
},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
doc.embedded_field.list_field[2].list_field.append(1) doc.embedded_field.list_field[2].list_field.append(1)
self.assertEqual( assert doc._delta() == (
doc._delta(), {
( "db_embedded_field.db_list_field.2.db_list_field": [
{ 2,
"db_embedded_field.db_list_field.2.db_list_field": [ {"hello": "world"},
2, 1,
{"hello": "world"}, ]
1, },
] {},
},
{},
),
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual( assert doc.embedded_field.list_field[2].list_field == [2, {"hello": "world"}, 1]
doc.embedded_field.list_field[2].list_field, [2, {"hello": "world"}, 1]
)
doc.embedded_field.list_field[2].list_field.sort(key=str) doc.embedded_field.list_field[2].list_field.sort(key=str)
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
self.assertEqual( assert doc.embedded_field.list_field[2].list_field == [1, 2, {"hello": "world"}]
doc.embedded_field.list_field[2].list_field, [1, 2, {"hello": "world"}]
)
del doc.embedded_field.list_field[2].list_field[2]["hello"] del doc.embedded_field.list_field[2].list_field[2]["hello"]
self.assertEqual( assert doc._delta() == (
doc._delta(), {},
({}, {"db_embedded_field.db_list_field.2.db_list_field.2.hello": 1}), {"db_embedded_field.db_list_field.2.db_list_field.2.hello": 1},
) )
doc.save() doc.save()
doc = doc.reload(10) doc = doc.reload(10)
del doc.embedded_field.list_field[2].list_field del doc.embedded_field.list_field[2].list_field
self.assertEqual( assert doc._delta() == (
doc._delta(), ({}, {"db_embedded_field.db_list_field.2.db_list_field": 1}) {},
{"db_embedded_field.db_list_field.2.db_list_field": 1},
) )
def test_delta_for_dynamic_documents(self): def test_delta_for_dynamic_documents(self):
@ -696,14 +648,16 @@ class TestDelta(MongoDBTestCase):
Person.drop_collection() Person.drop_collection()
p = Person(name="James", age=34) p = Person(name="James", age=34)
self.assertEqual( assert p._delta() == (
p._delta(), (SON([("_cls", "Person"), ("name", "James"), ("age", 34)]), {}) SON([("_cls", "Person"), ("name", "James"), ("age", 34)]),
{},
) )
p.doc = 123 p.doc = 123
del p.doc del p.doc
self.assertEqual( assert p._delta() == (
p._delta(), (SON([("_cls", "Person"), ("name", "James"), ("age", 34)]), {}) SON([("_cls", "Person"), ("name", "James"), ("age", 34)]),
{},
) )
p = Person() p = Person()
@ -712,18 +666,18 @@ class TestDelta(MongoDBTestCase):
p.save() p.save()
p.age = 24 p.age = 24
self.assertEqual(p.age, 24) assert p.age == 24
self.assertEqual(p._get_changed_fields(), ["age"]) assert p._get_changed_fields() == ["age"]
self.assertEqual(p._delta(), ({"age": 24}, {})) assert p._delta() == ({"age": 24}, {})
p = Person.objects(age=22).get() p = Person.objects(age=22).get()
p.age = 24 p.age = 24
self.assertEqual(p.age, 24) assert p.age == 24
self.assertEqual(p._get_changed_fields(), ["age"]) assert p._get_changed_fields() == ["age"]
self.assertEqual(p._delta(), ({"age": 24}, {})) assert p._delta() == ({"age": 24}, {})
p.save() p.save()
self.assertEqual(1, Person.objects(age=24).count()) assert 1 == Person.objects(age=24).count()
def test_dynamic_delta(self): def test_dynamic_delta(self):
class Doc(DynamicDocument): class Doc(DynamicDocument):
@ -734,40 +688,40 @@ class TestDelta(MongoDBTestCase):
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc._get_changed_fields(), []) assert doc._get_changed_fields() == []
self.assertEqual(doc._delta(), ({}, {})) assert doc._delta() == ({}, {})
doc.string_field = "hello" doc.string_field = "hello"
self.assertEqual(doc._get_changed_fields(), ["string_field"]) assert doc._get_changed_fields() == ["string_field"]
self.assertEqual(doc._delta(), ({"string_field": "hello"}, {})) assert doc._delta() == ({"string_field": "hello"}, {})
doc._changed_fields = [] doc._changed_fields = []
doc.int_field = 1 doc.int_field = 1
self.assertEqual(doc._get_changed_fields(), ["int_field"]) assert doc._get_changed_fields() == ["int_field"]
self.assertEqual(doc._delta(), ({"int_field": 1}, {})) assert doc._delta() == ({"int_field": 1}, {})
doc._changed_fields = [] doc._changed_fields = []
dict_value = {"hello": "world", "ping": "pong"} dict_value = {"hello": "world", "ping": "pong"}
doc.dict_field = dict_value doc.dict_field = dict_value
self.assertEqual(doc._get_changed_fields(), ["dict_field"]) assert doc._get_changed_fields() == ["dict_field"]
self.assertEqual(doc._delta(), ({"dict_field": dict_value}, {})) assert doc._delta() == ({"dict_field": dict_value}, {})
doc._changed_fields = [] doc._changed_fields = []
list_value = ["1", 2, {"hello": "world"}] list_value = ["1", 2, {"hello": "world"}]
doc.list_field = list_value doc.list_field = list_value
self.assertEqual(doc._get_changed_fields(), ["list_field"]) assert doc._get_changed_fields() == ["list_field"]
self.assertEqual(doc._delta(), ({"list_field": list_value}, {})) assert doc._delta() == ({"list_field": list_value}, {})
# Test unsetting # Test unsetting
doc._changed_fields = [] doc._changed_fields = []
doc.dict_field = {} doc.dict_field = {}
self.assertEqual(doc._get_changed_fields(), ["dict_field"]) assert doc._get_changed_fields() == ["dict_field"]
self.assertEqual(doc._delta(), ({}, {"dict_field": 1})) assert doc._delta() == ({}, {"dict_field": 1})
doc._changed_fields = [] doc._changed_fields = []
doc.list_field = [] doc.list_field = []
self.assertEqual(doc._get_changed_fields(), ["list_field"]) assert doc._get_changed_fields() == ["list_field"]
self.assertEqual(doc._delta(), ({}, {"list_field": 1})) assert doc._delta() == ({}, {"list_field": 1})
def test_delta_with_dbref_true(self): def test_delta_with_dbref_true(self):
person, organization, employee = self.circular_reference_deltas_2( person, organization, employee = self.circular_reference_deltas_2(
@ -775,16 +729,16 @@ class TestDelta(MongoDBTestCase):
) )
employee.name = "test" employee.name = "test"
self.assertEqual(organization._get_changed_fields(), []) assert organization._get_changed_fields() == []
updates, removals = organization._delta() updates, removals = organization._delta()
self.assertEqual({}, removals) assert {} == removals
self.assertEqual({}, updates) assert {} == updates
organization.employees.append(person) organization.employees.append(person)
updates, removals = organization._delta() updates, removals = organization._delta()
self.assertEqual({}, removals) assert {} == removals
self.assertIn("employees", updates) assert "employees" in updates
def test_delta_with_dbref_false(self): def test_delta_with_dbref_false(self):
person, organization, employee = self.circular_reference_deltas_2( person, organization, employee = self.circular_reference_deltas_2(
@ -792,16 +746,16 @@ class TestDelta(MongoDBTestCase):
) )
employee.name = "test" employee.name = "test"
self.assertEqual(organization._get_changed_fields(), []) assert organization._get_changed_fields() == []
updates, removals = organization._delta() updates, removals = organization._delta()
self.assertEqual({}, removals) assert {} == removals
self.assertEqual({}, updates) assert {} == updates
organization.employees.append(person) organization.employees.append(person)
updates, removals = organization._delta() updates, removals = organization._delta()
self.assertEqual({}, removals) assert {} == removals
self.assertIn("employees", updates) assert "employees" in updates
def test_nested_nested_fields_mark_as_changed(self): def test_nested_nested_fields_mark_as_changed(self):
class EmbeddedDoc(EmbeddedDocument): class EmbeddedDoc(EmbeddedDocument):
@ -821,11 +775,11 @@ class TestDelta(MongoDBTestCase):
subdoc = mydoc.subs["a"]["b"] subdoc = mydoc.subs["a"]["b"]
subdoc.name = "bar" subdoc.name = "bar"
self.assertEqual(["name"], subdoc._get_changed_fields()) assert ["name"] == subdoc._get_changed_fields()
self.assertEqual(["subs.a.b.name"], mydoc._get_changed_fields()) assert ["subs.a.b.name"] == mydoc._get_changed_fields()
mydoc._clear_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): def test_lower_level_mark_as_changed(self):
class EmbeddedDoc(EmbeddedDocument): class EmbeddedDoc(EmbeddedDocument):
@ -840,17 +794,17 @@ class TestDelta(MongoDBTestCase):
mydoc = MyDoc.objects.first() mydoc = MyDoc.objects.first()
mydoc.subs["a"] = EmbeddedDoc() mydoc.subs["a"] = EmbeddedDoc()
self.assertEqual(["subs.a"], mydoc._get_changed_fields()) assert ["subs.a"] == mydoc._get_changed_fields()
subdoc = mydoc.subs["a"] subdoc = mydoc.subs["a"]
subdoc.name = "bar" subdoc.name = "bar"
self.assertEqual(["name"], subdoc._get_changed_fields()) assert ["name"] == subdoc._get_changed_fields()
self.assertEqual(["subs.a"], mydoc._get_changed_fields()) assert ["subs.a"] == mydoc._get_changed_fields()
mydoc.save() mydoc.save()
mydoc._clear_changed_fields() mydoc._clear_changed_fields()
self.assertEqual([], mydoc._get_changed_fields()) assert [] == mydoc._get_changed_fields()
def test_upper_level_mark_as_changed(self): def test_upper_level_mark_as_changed(self):
class EmbeddedDoc(EmbeddedDocument): class EmbeddedDoc(EmbeddedDocument):
@ -867,15 +821,15 @@ class TestDelta(MongoDBTestCase):
subdoc = mydoc.subs["a"] subdoc = mydoc.subs["a"]
subdoc.name = "bar" subdoc.name = "bar"
self.assertEqual(["name"], subdoc._get_changed_fields()) assert ["name"] == subdoc._get_changed_fields()
self.assertEqual(["subs.a.name"], mydoc._get_changed_fields()) assert ["subs.a.name"] == mydoc._get_changed_fields()
mydoc.subs["a"] = EmbeddedDoc() mydoc.subs["a"] = EmbeddedDoc()
self.assertEqual(["subs.a"], mydoc._get_changed_fields()) assert ["subs.a"] == mydoc._get_changed_fields()
mydoc.save() mydoc.save()
mydoc._clear_changed_fields() mydoc._clear_changed_fields()
self.assertEqual([], mydoc._get_changed_fields()) assert [] == mydoc._get_changed_fields()
def test_referenced_object_changed_attributes(self): def test_referenced_object_changed_attributes(self):
"""Ensures that when you save a new reference to a field, the referenced object isn't altered""" """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() org1.reload()
org2.reload() org2.reload()
user.reload() user.reload()
self.assertEqual(org1.name, "Org 1") assert org1.name == "Org 1"
self.assertEqual(org2.name, "Org 2") assert org2.name == "Org 2"
self.assertEqual(user.name, "Fred") assert user.name == "Fred"
user.name = "Harold" user.name = "Harold"
user.org = org2 user.org = org2
org2.name = "New Org 2" org2.name = "New Org 2"
self.assertEqual(org2.name, "New Org 2") assert org2.name == "New Org 2"
user.save() user.save()
org2.save() org2.save()
self.assertEqual(org2.name, "New Org 2") assert org2.name == "New Org 2"
org2.reload() org2.reload()
self.assertEqual(org2.name, "New Org 2") assert org2.name == "New Org 2"
def test_delta_for_nested_map_fields(self): def test_delta_for_nested_map_fields(self):
class UInfoDocument(Document): class UInfoDocument(Document):
@ -950,12 +904,12 @@ class TestDelta(MongoDBTestCase):
d.users["007"]["rolist"].append(EmbeddedRole(type="oops")) d.users["007"]["rolist"].append(EmbeddedRole(type="oops"))
d.users["007"]["info"] = uinfo d.users["007"]["info"] = uinfo
delta = d._delta() delta = d._delta()
self.assertEqual(True, "users.007.roles.666" in delta[0]) assert True == ("users.007.roles.666" in delta[0])
self.assertEqual(True, "users.007.rolist" in delta[0]) assert True == ("users.007.rolist" in delta[0])
self.assertEqual(True, "users.007.info" in delta[0]) assert True == ("users.007.info" in delta[0])
self.assertEqual("superadmin", delta[0]["users.007.roles.666"]["type"]) assert "superadmin" == delta[0]["users.007.roles.666"]["type"]
self.assertEqual("oops", delta[0]["users.007.rolist"][0]["type"]) assert "oops" == delta[0]["users.007.rolist"][0]["type"]
self.assertEqual(uinfo.id, delta[0]["users.007.info"]) assert uinfo.id == delta[0]["users.007.info"]
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,5 +1,7 @@
import unittest import unittest
import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -25,15 +27,15 @@ class TestDynamicDocument(MongoDBTestCase):
p.name = "James" p.name = "James"
p.age = 34 p.age = 34
self.assertEqual(p.to_mongo(), {"_cls": "Person", "name": "James", "age": 34}) assert p.to_mongo() == {"_cls": "Person", "name": "James", "age": 34}
self.assertEqual(p.to_mongo().keys(), ["_cls", "name", "age"]) assert p.to_mongo().keys() == ["_cls", "name", "age"]
p.save() 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 # 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): def test_change_scope_of_variable(self):
"""Test changing the scope of a dynamic field has no adverse effects""" """Test changing the scope of a dynamic field has no adverse effects"""
@ -47,7 +49,7 @@ class TestDynamicDocument(MongoDBTestCase):
p.save() p.save()
p = self.Person.objects.get() p = self.Person.objects.get()
self.assertEqual(p.misc, {"hello": "world"}) assert p.misc == {"hello": "world"}
def test_delete_dynamic_field(self): def test_delete_dynamic_field(self):
"""Test deleting a dynamic field works""" """Test deleting a dynamic field works"""
@ -62,19 +64,19 @@ class TestDynamicDocument(MongoDBTestCase):
p.save() p.save()
p = self.Person.objects.get() p = self.Person.objects.get()
self.assertEqual(p.misc, {"hello": "world"}) assert p.misc == {"hello": "world"}
collection = self.db[self.Person._get_collection_name()] collection = self.db[self.Person._get_collection_name()]
obj = collection.find_one() obj = collection.find_one()
self.assertEqual(sorted(obj.keys()), ["_cls", "_id", "misc", "name"]) assert sorted(obj.keys()) == ["_cls", "_id", "misc", "name"]
del p.misc del p.misc
p.save() p.save()
p = self.Person.objects.get() p = self.Person.objects.get()
self.assertFalse(hasattr(p, "misc")) assert not hasattr(p, "misc")
obj = collection.find_one() 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): def test_reload_after_unsetting(self):
p = self.Person() p = self.Person()
@ -88,12 +90,12 @@ class TestDynamicDocument(MongoDBTestCase):
p = self.Person.objects.create() p = self.Person.objects.create()
p.update(age=1) p.update(age=1)
self.assertEqual(len(p._data), 3) assert len(p._data) == 3
self.assertEqual(sorted(p._data.keys()), ["_cls", "id", "name"]) assert sorted(p._data.keys()) == ["_cls", "id", "name"]
p.reload() p.reload()
self.assertEqual(len(p._data), 4) assert len(p._data) == 4
self.assertEqual(sorted(p._data.keys()), ["_cls", "age", "id", "name"]) assert sorted(p._data.keys()) == ["_cls", "age", "id", "name"]
def test_fields_without_underscore(self): def test_fields_without_underscore(self):
"""Ensure we can query dynamic fields""" """Ensure we can query dynamic fields"""
@ -103,16 +105,18 @@ class TestDynamicDocument(MongoDBTestCase):
p.save() p.save()
raw_p = Person.objects.as_pymongo().get(id=p.id) 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.name = "OldDean"
p.newattr = "garbage" p.newattr = "garbage"
p.save() p.save()
raw_p = Person.objects.as_pymongo().get(id=p.id) raw_p = Person.objects.as_pymongo().get(id=p.id)
self.assertEqual( assert raw_p == {
raw_p, "_cls": u"Person",
{"_cls": u"Person", "_id": p.id, "name": "OldDean", "newattr": u"garbage"}, "_id": p.id,
) "name": "OldDean",
"newattr": u"garbage",
}
def test_fields_containing_underscore(self): def test_fields_containing_underscore(self):
"""Ensure we can query dynamic fields""" """Ensure we can query dynamic fields"""
@ -127,14 +131,14 @@ class TestDynamicDocument(MongoDBTestCase):
p.save() p.save()
raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id) 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 = "OldDean"
p._name = "NewDean" p._name = "NewDean"
p._newattr1 = "garbage" # Unknown fields won't be added p._newattr1 = "garbage" # Unknown fields won't be added
p.save() p.save()
raw_p = WeirdPerson.objects.as_pymongo().get(id=p.id) 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): def test_dynamic_document_queries(self):
"""Ensure we can query dynamic fields""" """Ensure we can query dynamic fields"""
@ -143,10 +147,10 @@ class TestDynamicDocument(MongoDBTestCase):
p.age = 22 p.age = 22
p.save() 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 = self.Person.objects(age=22)
p = p.get() p = p.get()
self.assertEqual(22, p.age) assert 22 == p.age
def test_complex_dynamic_document_queries(self): def test_complex_dynamic_document_queries(self):
class Person(DynamicDocument): class Person(DynamicDocument):
@ -166,8 +170,8 @@ class TestDynamicDocument(MongoDBTestCase):
p2.age = 10 p2.age = 10
p2.save() p2.save()
self.assertEqual(Person.objects(age__icontains="ten").count(), 2) assert Person.objects(age__icontains="ten").count() == 2
self.assertEqual(Person.objects(age__gte=10).count(), 1) assert Person.objects(age__gte=10).count() == 1
def test_complex_data_lookups(self): def test_complex_data_lookups(self):
"""Ensure you can query dynamic document dynamic fields""" """Ensure you can query dynamic document dynamic fields"""
@ -175,12 +179,12 @@ class TestDynamicDocument(MongoDBTestCase):
p.misc = {"hello": "world"} p.misc = {"hello": "world"}
p.save() 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): def test_three_level_complex_data_lookups(self):
"""Ensure you can query three level document dynamic fields""" """Ensure you can query three level document dynamic fields"""
self.Person.objects.create(misc={"hello": {"hello2": "world"}}) 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): def test_complex_embedded_document_validation(self):
"""Ensure embedded dynamic documents may be validated""" """Ensure embedded dynamic documents may be validated"""
@ -198,11 +202,13 @@ class TestDynamicDocument(MongoDBTestCase):
embedded_doc_1.validate() embedded_doc_1.validate()
embedded_doc_2 = Embedded(content="this is not a url") 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_1 = embedded_doc_1
doc.embedded_field_2 = embedded_doc_2 doc.embedded_field_2 = embedded_doc_2
self.assertRaises(ValidationError, doc.validate) with pytest.raises(ValidationError):
doc.validate()
def test_inheritance(self): def test_inheritance(self):
"""Ensure that dynamic document plays nice with inheritance""" """Ensure that dynamic document plays nice with inheritance"""
@ -212,11 +218,9 @@ class TestDynamicDocument(MongoDBTestCase):
Employee.drop_collection() Employee.drop_collection()
self.assertIn("name", Employee._fields) assert "name" in Employee._fields
self.assertIn("salary", Employee._fields) assert "salary" in Employee._fields
self.assertEqual( assert Employee._get_collection_name() == self.Person._get_collection_name()
Employee._get_collection_name(), self.Person._get_collection_name()
)
joe_bloggs = Employee() joe_bloggs = Employee()
joe_bloggs.name = "Joe Bloggs" joe_bloggs.name = "Joe Bloggs"
@ -224,11 +228,11 @@ class TestDynamicDocument(MongoDBTestCase):
joe_bloggs.age = 20 joe_bloggs.age = 20
joe_bloggs.save() joe_bloggs.save()
self.assertEqual(1, self.Person.objects(age=20).count()) assert 1 == self.Person.objects(age=20).count()
self.assertEqual(1, Employee.objects(age=20).count()) assert 1 == Employee.objects(age=20).count()
joe_bloggs = self.Person.objects.first() joe_bloggs = self.Person.objects.first()
self.assertIsInstance(joe_bloggs, Employee) assert isinstance(joe_bloggs, Employee)
def test_embedded_dynamic_document(self): def test_embedded_dynamic_document(self):
"""Test dynamic embedded documents""" """Test dynamic embedded documents"""
@ -249,26 +253,23 @@ class TestDynamicDocument(MongoDBTestCase):
embedded_1.list_field = ["1", 2, {"hello": "world"}] embedded_1.list_field = ["1", 2, {"hello": "world"}]
doc.embedded_field = embedded_1 doc.embedded_field = embedded_1
self.assertEqual( assert doc.to_mongo() == {
doc.to_mongo(), "embedded_field": {
{ "_cls": "Embedded",
"embedded_field": { "string_field": "hello",
"_cls": "Embedded", "int_field": 1,
"string_field": "hello", "dict_field": {"hello": "world"},
"int_field": 1, "list_field": ["1", 2, {"hello": "world"}],
"dict_field": {"hello": "world"}, }
"list_field": ["1", 2, {"hello": "world"}], }
}
},
)
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc.embedded_field.__class__, Embedded) assert doc.embedded_field.__class__ == Embedded
self.assertEqual(doc.embedded_field.string_field, "hello") assert doc.embedded_field.string_field == "hello"
self.assertEqual(doc.embedded_field.int_field, 1) assert doc.embedded_field.int_field == 1
self.assertEqual(doc.embedded_field.dict_field, {"hello": "world"}) assert doc.embedded_field.dict_field == {"hello": "world"}
self.assertEqual(doc.embedded_field.list_field, ["1", 2, {"hello": "world"}]) assert doc.embedded_field.list_field == ["1", 2, {"hello": "world"}]
def test_complex_embedded_documents(self): def test_complex_embedded_documents(self):
"""Test complex dynamic embedded documents setups""" """Test complex dynamic embedded documents setups"""
@ -296,44 +297,41 @@ class TestDynamicDocument(MongoDBTestCase):
embedded_1.list_field = ["1", 2, embedded_2] embedded_1.list_field = ["1", 2, embedded_2]
doc.embedded_field = embedded_1 doc.embedded_field = embedded_1
self.assertEqual( assert doc.to_mongo() == {
doc.to_mongo(), "embedded_field": {
{ "_cls": "Embedded",
"embedded_field": { "string_field": "hello",
"_cls": "Embedded", "int_field": 1,
"string_field": "hello", "dict_field": {"hello": "world"},
"int_field": 1, "list_field": [
"dict_field": {"hello": "world"}, "1",
"list_field": [ 2,
"1", {
2, "_cls": "Embedded",
{ "string_field": "hello",
"_cls": "Embedded", "int_field": 1,
"string_field": "hello", "dict_field": {"hello": "world"},
"int_field": 1, "list_field": ["1", 2, {"hello": "world"}],
"dict_field": {"hello": "world"}, },
"list_field": ["1", 2, {"hello": "world"}], ],
}, }
], }
}
},
)
doc.save() doc.save()
doc = Doc.objects.first() doc = Doc.objects.first()
self.assertEqual(doc.embedded_field.__class__, Embedded) assert doc.embedded_field.__class__ == Embedded
self.assertEqual(doc.embedded_field.string_field, "hello") assert doc.embedded_field.string_field == "hello"
self.assertEqual(doc.embedded_field.int_field, 1) assert doc.embedded_field.int_field == 1
self.assertEqual(doc.embedded_field.dict_field, {"hello": "world"}) assert doc.embedded_field.dict_field == {"hello": "world"}
self.assertEqual(doc.embedded_field.list_field[0], "1") assert doc.embedded_field.list_field[0] == "1"
self.assertEqual(doc.embedded_field.list_field[1], 2) assert doc.embedded_field.list_field[1] == 2
embedded_field = doc.embedded_field.list_field[2] embedded_field = doc.embedded_field.list_field[2]
self.assertEqual(embedded_field.__class__, Embedded) assert embedded_field.__class__ == Embedded
self.assertEqual(embedded_field.string_field, "hello") assert embedded_field.string_field == "hello"
self.assertEqual(embedded_field.int_field, 1) assert embedded_field.int_field == 1
self.assertEqual(embedded_field.dict_field, {"hello": "world"}) assert embedded_field.dict_field == {"hello": "world"}
self.assertEqual(embedded_field.list_field, ["1", 2, {"hello": "world"}]) assert embedded_field.list_field == ["1", 2, {"hello": "world"}]
def test_dynamic_and_embedded(self): def test_dynamic_and_embedded(self):
"""Ensure embedded documents play nicely""" """Ensure embedded documents play nicely"""
@ -352,18 +350,18 @@ class TestDynamicDocument(MongoDBTestCase):
person.address.city = "Lundenne" person.address.city = "Lundenne"
person.save() person.save()
self.assertEqual(Person.objects.first().address.city, "Lundenne") assert Person.objects.first().address.city == "Lundenne"
person = Person.objects.first() person = Person.objects.first()
person.address = Address(city="Londinium") person.address = Address(city="Londinium")
person.save() person.save()
self.assertEqual(Person.objects.first().address.city, "Londinium") assert Person.objects.first().address.city == "Londinium"
person = Person.objects.first() person = Person.objects.first()
person.age = 35 person.age = 35
person.save() person.save()
self.assertEqual(Person.objects.first().age, 35) assert Person.objects.first().age == 35
def test_dynamic_embedded_works_with_only(self): def test_dynamic_embedded_works_with_only(self):
"""Ensure custom fieldnames on a dynamic embedded document are found by qs.only()""" """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") name="Eric", address=Address(city="San Francisco", street_number="1337")
).save() ).save()
self.assertEqual(Person.objects.first().address.street_number, "1337") assert Person.objects.first().address.street_number == "1337"
self.assertEqual( assert (
Person.objects.only("address__street_number").first().address.street_number, Person.objects.only("address__street_number").first().address.street_number
"1337", == "1337"
) )
def test_dynamic_and_embedded_dict_access(self): def test_dynamic_and_embedded_dict_access(self):
@ -408,20 +406,20 @@ class TestDynamicDocument(MongoDBTestCase):
person["address"]["city"] = "Lundenne" person["address"]["city"] = "Lundenne"
person.save() 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 = Person.objects.first()
person.address = Address(city="Londinium") person.address = Address(city="Londinium")
person.save() person.save()
self.assertEqual(Person.objects.first().address.city, "Londinium") assert Person.objects.first().address.city == "Londinium"
person = Person.objects.first() person = Person.objects.first()
person["age"] = 35 person["age"] = 35
person.save() person.save()
self.assertEqual(Person.objects.first().age, 35) assert Person.objects.first().age == 35
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -2,9 +2,9 @@
import unittest import unittest
from datetime import datetime from datetime import datetime
from nose.plugins.skip import SkipTest
from pymongo.collation import Collation from pymongo.collation import Collation
from pymongo.errors import OperationFailure from pymongo.errors import OperationFailure
import pytest
from six import iteritems from six import iteritems
from mongoengine import * from mongoengine import *
@ -53,15 +53,15 @@ class TestIndexes(unittest.TestCase):
{"fields": [("tags", 1)]}, {"fields": [("tags", 1)]},
{"fields": [("category", 1), ("addDate", -1)]}, {"fields": [("category", 1), ("addDate", -1)]},
] ]
self.assertEqual(expected_specs, BlogPost._meta["index_specs"]) assert expected_specs == BlogPost._meta["index_specs"]
BlogPost.ensure_indexes() BlogPost.ensure_indexes()
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
# _id, '-date', 'tags', ('cat', 'date') # _id, '-date', 'tags', ('cat', 'date')
self.assertEqual(len(info), 4) assert len(info) == 4
info = [value["key"] for key, value in iteritems(info)] info = [value["key"] for key, value in iteritems(info)]
for expected in expected_specs: for expected in expected_specs:
self.assertIn(expected["fields"], info) assert expected["fields"] in info
def _index_test_inheritance(self, InheritFrom): def _index_test_inheritance(self, InheritFrom):
class BlogPost(InheritFrom): class BlogPost(InheritFrom):
@ -78,7 +78,7 @@ class TestIndexes(unittest.TestCase):
{"fields": [("_cls", 1), ("tags", 1)]}, {"fields": [("_cls", 1), ("tags", 1)]},
{"fields": [("_cls", 1), ("category", 1), ("addDate", -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() BlogPost.ensure_indexes()
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
@ -86,17 +86,17 @@ class TestIndexes(unittest.TestCase):
# NB: there is no index on _cls by itself, since # NB: there is no index on _cls by itself, since
# the indices on -date and tags will both contain # the indices on -date and tags will both contain
# _cls as first element in the key # _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)] info = [value["key"] for key, value in iteritems(info)]
for expected in expected_specs: for expected in expected_specs:
self.assertIn(expected["fields"], info) assert expected["fields"] in info
class ExtendedBlogPost(BlogPost): class ExtendedBlogPost(BlogPost):
title = StringField() title = StringField()
meta = {"indexes": ["title"]} meta = {"indexes": ["title"]}
expected_specs.append({"fields": [("_cls", 1), ("title", 1)]}) 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() BlogPost.drop_collection()
@ -104,7 +104,7 @@ class TestIndexes(unittest.TestCase):
info = ExtendedBlogPost.objects._collection.index_information() info = ExtendedBlogPost.objects._collection.index_information()
info = [value["key"] for key, value in iteritems(info)] info = [value["key"] for key, value in iteritems(info)]
for expected in expected_specs: for expected in expected_specs:
self.assertIn(expected["fields"], info) assert expected["fields"] in info
def test_indexes_document_inheritance(self): def test_indexes_document_inheritance(self):
"""Ensure that indexes are used when meta[indexes] is specified for """Ensure that indexes are used when meta[indexes] is specified for
@ -128,10 +128,8 @@ class TestIndexes(unittest.TestCase):
class B(A): class B(A):
description = StringField() description = StringField()
self.assertEqual(A._meta["index_specs"], B._meta["index_specs"]) assert A._meta["index_specs"] == B._meta["index_specs"]
self.assertEqual( assert [{"fields": [("_cls", 1), ("title", 1)]}] == A._meta["index_specs"]
[{"fields": [("_cls", 1), ("title", 1)]}], A._meta["index_specs"]
)
def test_index_no_cls(self): def test_index_no_cls(self):
"""Ensure index specs are inhertited correctly""" """Ensure index specs are inhertited correctly"""
@ -144,11 +142,11 @@ class TestIndexes(unittest.TestCase):
"index_cls": False, "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._get_collection().drop_indexes()
A.ensure_indexes() A.ensure_indexes()
info = A._get_collection().index_information() info = A._get_collection().index_information()
self.assertEqual(len(info.keys()), 2) assert len(info.keys()) == 2
class B(A): class B(A):
c = StringField() c = StringField()
@ -158,8 +156,8 @@ class TestIndexes(unittest.TestCase):
"allow_inheritance": True, "allow_inheritance": True,
} }
self.assertEqual([("c", 1)], B._meta["index_specs"][1]["fields"]) assert [("c", 1)] == B._meta["index_specs"][1]["fields"]
self.assertEqual([("_cls", 1), ("d", 1)], B._meta["index_specs"][2]["fields"]) assert [("_cls", 1), ("d", 1)] == B._meta["index_specs"][2]["fields"]
def test_build_index_spec_is_not_destructive(self): def test_build_index_spec_is_not_destructive(self):
class MyDoc(Document): class MyDoc(Document):
@ -167,12 +165,12 @@ class TestIndexes(unittest.TestCase):
meta = {"indexes": ["keywords"], "allow_inheritance": False} 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 # Force index creation
MyDoc.ensure_indexes() 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): def test_embedded_document_index_meta(self):
"""Ensure that embedded document indexes are created explicitly """Ensure that embedded document indexes are created explicitly
@ -187,7 +185,7 @@ class TestIndexes(unittest.TestCase):
meta = {"indexes": ["rank.title"], "allow_inheritance": False} 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() Person.drop_collection()
@ -195,7 +193,7 @@ class TestIndexes(unittest.TestCase):
list(Person.objects) list(Person.objects)
info = Person.objects._collection.index_information() info = Person.objects._collection.index_information()
info = [value["key"] for key, value in iteritems(info)] 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): def test_explicit_geo2d_index(self):
"""Ensure that geo2d indexes work when created via meta[indexes] """Ensure that geo2d indexes work when created via meta[indexes]
@ -205,14 +203,12 @@ class TestIndexes(unittest.TestCase):
location = DictField() location = DictField()
meta = {"allow_inheritance": True, "indexes": ["*location.point"]} meta = {"allow_inheritance": True, "indexes": ["*location.point"]}
self.assertEqual( assert [{"fields": [("location.point", "2d")]}] == Place._meta["index_specs"]
[{"fields": [("location.point", "2d")]}], Place._meta["index_specs"]
)
Place.ensure_indexes() Place.ensure_indexes()
info = Place._get_collection().index_information() info = Place._get_collection().index_information()
info = [value["key"] for key, value in iteritems(info)] 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): def test_explicit_geo2d_index_embedded(self):
"""Ensure that geo2d indexes work when created via meta[indexes] """Ensure that geo2d indexes work when created via meta[indexes]
@ -225,14 +221,14 @@ class TestIndexes(unittest.TestCase):
current = DictField(field=EmbeddedDocumentField("EmbeddedLocation")) current = DictField(field=EmbeddedDocumentField("EmbeddedLocation"))
meta = {"allow_inheritance": True, "indexes": ["*current.location.point"]} meta = {"allow_inheritance": True, "indexes": ["*current.location.point"]}
self.assertEqual( assert [{"fields": [("current.location.point", "2d")]}] == Place._meta[
[{"fields": [("current.location.point", "2d")]}], Place._meta["index_specs"] "index_specs"
) ]
Place.ensure_indexes() Place.ensure_indexes()
info = Place._get_collection().index_information() info = Place._get_collection().index_information()
info = [value["key"] for key, value in iteritems(info)] 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): def test_explicit_geosphere_index(self):
"""Ensure that geosphere indexes work when created via meta[indexes] """Ensure that geosphere indexes work when created via meta[indexes]
@ -242,19 +238,19 @@ class TestIndexes(unittest.TestCase):
location = DictField() location = DictField()
meta = {"allow_inheritance": True, "indexes": ["(location.point"]} meta = {"allow_inheritance": True, "indexes": ["(location.point"]}
self.assertEqual( assert [{"fields": [("location.point", "2dsphere")]}] == Place._meta[
[{"fields": [("location.point", "2dsphere")]}], Place._meta["index_specs"] "index_specs"
) ]
Place.ensure_indexes() Place.ensure_indexes()
info = Place._get_collection().index_information() info = Place._get_collection().index_information()
info = [value["key"] for key, value in iteritems(info)] 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): def test_explicit_geohaystack_index(self):
"""Ensure that geohaystack indexes work when created via meta[indexes] """Ensure that geohaystack indexes work when created via meta[indexes]
""" """
raise SkipTest( pytest.skip(
"GeoHaystack index creation is not supported for now" "GeoHaystack index creation is not supported for now"
"from meta, as it requires a bucketSize parameter." "from meta, as it requires a bucketSize parameter."
) )
@ -264,15 +260,14 @@ class TestIndexes(unittest.TestCase):
name = StringField() name = StringField()
meta = {"indexes": [(")location.point", "name")]} meta = {"indexes": [(")location.point", "name")]}
self.assertEqual( assert [
[{"fields": [("location.point", "geoHaystack"), ("name", 1)]}], {"fields": [("location.point", "geoHaystack"), ("name", 1)]}
Place._meta["index_specs"], ] == Place._meta["index_specs"]
)
Place.ensure_indexes() Place.ensure_indexes()
info = Place._get_collection().index_information() info = Place._get_collection().index_information()
info = [value["key"] for key, value in iteritems(info)] 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): def test_create_geohaystack_index(self):
"""Ensure that geohaystack indexes can be created """Ensure that geohaystack indexes can be created
@ -285,7 +280,7 @@ class TestIndexes(unittest.TestCase):
Place.create_index({"fields": (")location.point", "name")}, bucketSize=10) Place.create_index({"fields": (")location.point", "name")}, bucketSize=10)
info = Place._get_collection().index_information() info = Place._get_collection().index_information()
info = [value["key"] for key, value in iteritems(info)] 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): def test_dictionary_indexes(self):
"""Ensure that indexes are used when meta[indexes] contains """Ensure that indexes are used when meta[indexes] contains
@ -298,16 +293,15 @@ class TestIndexes(unittest.TestCase):
tags = ListField(StringField()) tags = ListField(StringField())
meta = {"indexes": [{"fields": ["-date"], "unique": True, "sparse": True}]} meta = {"indexes": [{"fields": ["-date"], "unique": True, "sparse": True}]}
self.assertEqual( assert [
[{"fields": [("addDate", -1)], "unique": True, "sparse": True}], {"fields": [("addDate", -1)], "unique": True, "sparse": True}
BlogPost._meta["index_specs"], ] == BlogPost._meta["index_specs"]
)
BlogPost.drop_collection() BlogPost.drop_collection()
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
# _id, '-date' # _id, '-date'
self.assertEqual(len(info), 2) assert len(info) == 2
# Indexes are lazy so use list() to perform query # Indexes are lazy so use list() to perform query
list(BlogPost.objects) list(BlogPost.objects)
@ -316,7 +310,7 @@ class TestIndexes(unittest.TestCase):
(value["key"], value.get("unique", False), value.get("sparse", False)) (value["key"], value.get("unique", False), value.get("sparse", False))
for key, value in iteritems(info) for key, value in iteritems(info)
] ]
self.assertIn(([("addDate", -1)], True, True), info) assert ([("addDate", -1)], True, True) in info
BlogPost.drop_collection() BlogPost.drop_collection()
@ -338,11 +332,9 @@ class TestIndexes(unittest.TestCase):
Person(name="test", user_guid="123").save() Person(name="test", user_guid="123").save()
self.assertEqual(1, Person.objects.count()) assert 1 == Person.objects.count()
info = Person.objects._collection.index_information() info = Person.objects._collection.index_information()
self.assertEqual( assert sorted(info.keys()) == ["_cls_1_name_1", "_cls_1_user_guid_1", "_id_"]
sorted(info.keys()), ["_cls_1_name_1", "_cls_1_user_guid_1", "_id_"]
)
def test_disable_index_creation(self): def test_disable_index_creation(self):
"""Tests setting auto_create_index to False on the connection will """Tests setting auto_create_index to False on the connection will
@ -365,13 +357,13 @@ class TestIndexes(unittest.TestCase):
User(user_guid="123").save() User(user_guid="123").save()
MongoUser(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() info = User.objects._collection.index_information()
self.assertEqual(list(info.keys()), ["_id_"]) assert list(info.keys()) == ["_id_"]
User.ensure_indexes() User.ensure_indexes()
info = User.objects._collection.index_information() 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): def test_embedded_document_index(self):
"""Tests settings an index on an embedded document """Tests settings an index on an embedded document
@ -389,7 +381,7 @@ class TestIndexes(unittest.TestCase):
BlogPost.drop_collection() BlogPost.drop_collection()
info = BlogPost.objects._collection.index_information() 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): def test_list_embedded_document_index(self):
"""Ensure list embedded documents can be indexed """Ensure list embedded documents can be indexed
@ -408,7 +400,7 @@ class TestIndexes(unittest.TestCase):
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
# we don't use _cls in with list fields by default # 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( post1 = BlogPost(
title="Embedded Indexes tests in place", title="Embedded Indexes tests in place",
@ -426,7 +418,7 @@ class TestIndexes(unittest.TestCase):
RecursiveDocument.ensure_indexes() RecursiveDocument.ensure_indexes()
info = RecursiveDocument._get_collection().index_information() 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): def test_covered_index(self):
"""Ensure that covered indexes can be used """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 # Need to be explicit about covered indexes as mongoDB doesn't know if
# the documents returned might have more keys in that here. # the documents returned might have more keys in that here.
query_plan = Test.objects(id=obj.id).exclude("a").explain() query_plan = Test.objects(id=obj.id).exclude("a").explain()
self.assertEqual( assert (
query_plan.get("queryPlanner") query_plan.get("queryPlanner")
.get("winningPlan") .get("winningPlan")
.get("inputStage") .get("inputStage")
.get("stage"), .get("stage")
"IDHACK", == "IDHACK"
) )
query_plan = Test.objects(id=obj.id).only("id").explain() query_plan = Test.objects(id=obj.id).only("id").explain()
self.assertEqual( assert (
query_plan.get("queryPlanner") query_plan.get("queryPlanner")
.get("winningPlan") .get("winningPlan")
.get("inputStage") .get("inputStage")
.get("stage"), .get("stage")
"IDHACK", == "IDHACK"
) )
query_plan = Test.objects(a=1).only("a").exclude("id").explain() query_plan = Test.objects(a=1).only("a").exclude("id").explain()
self.assertEqual( assert (
query_plan.get("queryPlanner") query_plan.get("queryPlanner")
.get("winningPlan") .get("winningPlan")
.get("inputStage") .get("inputStage")
.get("stage"), .get("stage")
"IXSCAN", == "IXSCAN"
) )
self.assertEqual( assert (
query_plan.get("queryPlanner").get("winningPlan").get("stage"), "PROJECTION" query_plan.get("queryPlanner").get("winningPlan").get("stage")
== "PROJECTION"
) )
query_plan = Test.objects(a=1).explain() query_plan = Test.objects(a=1).explain()
self.assertEqual( assert (
query_plan.get("queryPlanner") query_plan.get("queryPlanner")
.get("winningPlan") .get("winningPlan")
.get("inputStage") .get("inputStage")
.get("stage"), .get("stage")
"IXSCAN", == "IXSCAN"
)
self.assertEqual(
query_plan.get("queryPlanner").get("winningPlan").get("stage"), "FETCH"
) )
assert query_plan.get("queryPlanner").get("winningPlan").get("stage") == "FETCH"
def test_index_on_id(self): def test_index_on_id(self):
class BlogPost(Document): class BlogPost(Document):
@ -498,9 +489,7 @@ class TestIndexes(unittest.TestCase):
BlogPost.drop_collection() BlogPost.drop_collection()
indexes = BlogPost.objects._collection.index_information() indexes = BlogPost.objects._collection.index_information()
self.assertEqual( assert indexes["categories_1__id_1"]["key"] == [("categories", 1), ("_id", 1)]
indexes["categories_1__id_1"]["key"], [("categories", 1), ("_id", 1)]
)
def test_hint(self): def test_hint(self):
TAGS_INDEX_NAME = "tags_1" TAGS_INDEX_NAME = "tags_1"
@ -516,25 +505,25 @@ class TestIndexes(unittest.TestCase):
BlogPost(tags=tags).save() BlogPost(tags=tags).save()
# Hinting by shape should work. # 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. # 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. # Clearing the hint should work fine.
self.assertEqual(BlogPost.objects.hint().count(), 10) assert BlogPost.objects.hint().count() == 10
self.assertEqual(BlogPost.objects.hint([("ZZ", 1)]).hint().count(), 10) assert BlogPost.objects.hint([("ZZ", 1)]).hint().count() == 10
# Hinting on a non-existent index shape should fail. # Hinting on a non-existent index shape should fail.
with self.assertRaises(OperationFailure): with pytest.raises(OperationFailure):
BlogPost.objects.hint([("ZZ", 1)]).count() BlogPost.objects.hint([("ZZ", 1)]).count()
# Hinting on a non-existent index name should fail. # Hinting on a non-existent index name should fail.
with self.assertRaises(OperationFailure): with pytest.raises(OperationFailure):
BlogPost.objects.hint("Bad Name").count() BlogPost.objects.hint("Bad Name").count()
# Invalid shape argument (missing list brackets) should fail. # Invalid shape argument (missing list brackets) should fail.
with self.assertRaises(ValueError): with pytest.raises(ValueError):
BlogPost.objects.hint(("tags", 1)).count() BlogPost.objects.hint(("tags", 1)).count()
def test_collation(self): def test_collation(self):
@ -555,23 +544,19 @@ class TestIndexes(unittest.TestCase):
BlogPost(name=name).save() BlogPost(name=name).save()
query_result = BlogPost.objects.collation(base).order_by("name") query_result = BlogPost.objects.collation(base).order_by("name")
self.assertEqual( assert [x.name for x in query_result] == sorted(names, key=lambda x: x.lower())
[x.name for x in query_result], sorted(names, key=lambda x: x.lower()) assert 5 == query_result.count()
)
self.assertEqual(5, query_result.count())
query_result = BlogPost.objects.collation(Collation(**base)).order_by("name") query_result = BlogPost.objects.collation(Collation(**base)).order_by("name")
self.assertEqual( assert [x.name for x in query_result] == sorted(names, key=lambda x: x.lower())
[x.name for x in query_result], sorted(names, key=lambda x: x.lower()) assert 5 == query_result.count()
)
self.assertEqual(5, query_result.count())
incorrect_collation = {"arndom": "wrdo"} incorrect_collation = {"arndom": "wrdo"}
with self.assertRaises(OperationFailure): with pytest.raises(OperationFailure):
BlogPost.objects.collation(incorrect_collation).count() BlogPost.objects.collation(incorrect_collation).count()
query_result = BlogPost.objects.collation({}).order_by("name") 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): def test_unique(self):
"""Ensure that uniqueness constraints are applied to fields. """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 # Two posts with the same slug is not allowed
post2 = BlogPost(title="test2", slug="test") post2 = BlogPost(title="test2", slug="test")
self.assertRaises(NotUniqueError, post2.save) with pytest.raises(NotUniqueError):
self.assertRaises(NotUniqueError, BlogPost.objects.insert, post2) post2.save()
with pytest.raises(NotUniqueError):
BlogPost.objects.insert(post2)
# Ensure backwards compatibility for errors # Ensure backwards compatibility for errors
self.assertRaises(OperationError, post2.save) with pytest.raises(OperationError):
post2.save()
def test_primary_key_unique_not_working(self): def test_primary_key_unique_not_working(self):
"""Relates to #1445""" """Relates to #1445"""
@ -602,23 +590,21 @@ class TestIndexes(unittest.TestCase):
Blog.drop_collection() Blog.drop_collection()
with self.assertRaises(OperationFailure) as ctx_err: with pytest.raises(OperationFailure) as exc_info:
Blog(id="garbage").save() Blog(id="garbage").save()
# One of the errors below should happen. Which one depends on the # One of the errors below should happen. Which one depends on the
# PyMongo version and dict order. # PyMongo version and dict order.
err_msg = str(ctx_err.exception) err_msg = str(exc_info.value)
self.assertTrue( assert any(
any( [
[ "The field 'unique' is not valid for an _id index specification"
"The field 'unique' is not valid for an _id index specification" in err_msg,
in err_msg, "The field 'background' is not valid for an _id index specification"
"The field 'background' is not valid for an _id index specification" in err_msg,
in err_msg, "The field 'sparse' is not valid for an _id index specification"
"The field 'sparse' is not valid for an _id index specification" in err_msg,
in err_msg, ]
]
)
) )
def test_unique_with(self): 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 # 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") 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): def test_unique_embedded_document(self):
"""Ensure that uniqueness constraints are applied to fields on embedded documents. """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 # Now there will be two docs with the same sub.slug
post3 = BlogPost(title="test3", sub=SubDocument(year=2010, slug="test")) 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): 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")]) 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): def test_unique_embedded_document_in_sorted_list(self):
""" """
@ -729,12 +718,13 @@ class TestIndexes(unittest.TestCase):
# confirm that the unique index is created # confirm that the unique index is created
indexes = BlogPost._get_collection().index_information() indexes = BlogPost._get_collection().index_information()
self.assertIn("subs.slug_1", indexes) assert "subs.slug_1" in indexes
self.assertTrue(indexes["subs.slug_1"]["unique"]) assert indexes["subs.slug_1"]["unique"]
post2 = BlogPost(title="test2", subs=[SubDocument(year=2014, slug="conflict")]) 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): 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 # confirm that the unique index is created
indexes = BlogPost._get_collection().index_information() indexes = BlogPost._get_collection().index_information()
self.assertIn("subs.slug_1", indexes) assert "subs.slug_1" in indexes
self.assertTrue(indexes["subs.slug_1"]["unique"]) assert indexes["subs.slug_1"]["unique"]
post2 = BlogPost(title="test2", subs=[SubDocument(year=2014, slug="conflict")]) 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): def test_unique_with_embedded_document_and_embedded_unique(self):
"""Ensure that uniqueness constraints are applied to fields on """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 # Now there will be two docs with the same sub.slug
post3 = BlogPost(title="test3", sub=SubDocument(year=2010, slug="test")) 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 # Now there will be two docs with the same title and year
post3 = BlogPost(title="test1", sub=SubDocument(year=2009, slug="test-1")) 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): def test_ttl_indexes(self):
class Log(Document): class Log(Document):
@ -811,7 +804,7 @@ class TestIndexes(unittest.TestCase):
# Indexes are lazy so use list() to perform query # Indexes are lazy so use list() to perform query
list(Log.objects) list(Log.objects)
info = Log.objects._collection.index_information() 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): def test_index_drop_dups_silently_ignored(self):
class Customer(Document): class Customer(Document):
@ -839,14 +832,14 @@ class TestIndexes(unittest.TestCase):
cust.save() cust.save()
cust_dupe = Customer(cust_id=1) cust_dupe = Customer(cust_id=1)
with self.assertRaises(NotUniqueError): with pytest.raises(NotUniqueError):
cust_dupe.save() cust_dupe.save()
cust = Customer(cust_id=2) cust = Customer(cust_id=2)
cust.save() cust.save()
# duplicate key on update # duplicate key on update
with self.assertRaises(NotUniqueError): with pytest.raises(NotUniqueError):
cust.cust_id = 1 cust.cust_id = 1
cust.save() cust.save()
@ -867,8 +860,8 @@ class TestIndexes(unittest.TestCase):
user = User(name="huangz", password="secret2") user = User(name="huangz", password="secret2")
user.save() user.save()
self.assertEqual(User.objects.count(), 1) assert User.objects.count() == 1
self.assertEqual(User.objects.get().password, "secret2") assert User.objects.get().password == "secret2"
def test_unique_and_primary_create(self): def test_unique_and_primary_create(self):
"""Create a new record with a duplicate primary key """Create a new record with a duplicate primary key
@ -882,11 +875,11 @@ class TestIndexes(unittest.TestCase):
User.drop_collection() User.drop_collection()
User.objects.create(name="huangz", password="secret") User.objects.create(name="huangz", password="secret")
with self.assertRaises(NotUniqueError): with pytest.raises(NotUniqueError):
User.objects.create(name="huangz", password="secret2") User.objects.create(name="huangz", password="secret2")
self.assertEqual(User.objects.count(), 1) assert User.objects.count() == 1
self.assertEqual(User.objects.get().password, "secret") assert User.objects.get().password == "secret"
def test_index_with_pk(self): def test_index_with_pk(self):
"""Ensure you can use `pk` as part of a query""" """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 = BlogPost.objects._collection.index_information()
info = [value["key"] for key, value in iteritems(info)] info = [value["key"] for key, value in iteritems(info)]
index_item = [("_id", 1), ("comments.comment_id", 1)] index_item = [("_id", 1), ("comments.comment_id", 1)]
self.assertIn(index_item, info) assert index_item in info
def test_compound_key_embedded(self): def test_compound_key_embedded(self):
class CompoundKey(EmbeddedDocument): class CompoundKey(EmbeddedDocument):
@ -924,10 +917,8 @@ class TestIndexes(unittest.TestCase):
my_key = CompoundKey(name="n", term="ok") my_key = CompoundKey(name="n", term="ok")
report = ReportEmbedded(text="OK", key=my_key).save() report = ReportEmbedded(text="OK", key=my_key).save()
self.assertEqual( assert {"text": "OK", "_id": {"term": "ok", "name": "n"}} == report.to_mongo()
{"text": "OK", "_id": {"term": "ok", "name": "n"}}, report.to_mongo() assert report == ReportEmbedded.objects.get(pk=my_key)
)
self.assertEqual(report, ReportEmbedded.objects.get(pk=my_key))
def test_compound_key_dictfield(self): def test_compound_key_dictfield(self):
class ReportDictField(Document): class ReportDictField(Document):
@ -937,15 +928,13 @@ class TestIndexes(unittest.TestCase):
my_key = {"name": "n", "term": "ok"} my_key = {"name": "n", "term": "ok"}
report = ReportDictField(text="OK", key=my_key).save() report = ReportDictField(text="OK", key=my_key).save()
self.assertEqual( assert {"text": "OK", "_id": {"term": "ok", "name": "n"}} == report.to_mongo()
{"text": "OK", "_id": {"term": "ok", "name": "n"}}, report.to_mongo()
)
# We can't directly call ReportDictField.objects.get(pk=my_key), # We can't directly call ReportDictField.objects.get(pk=my_key),
# because dicts are unordered, and if the order in MongoDB is # because dicts are unordered, and if the order in MongoDB is
# different than the one in `my_key`, this test will fail. # different than the one in `my_key`, this test will fail.
self.assertEqual(report, ReportDictField.objects.get(pk__name=my_key["name"])) assert 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__term=my_key["term"])
def test_string_indexes(self): def test_string_indexes(self):
class MyDoc(Document): class MyDoc(Document):
@ -954,8 +943,8 @@ class TestIndexes(unittest.TestCase):
info = MyDoc.objects._collection.index_information() info = MyDoc.objects._collection.index_information()
info = [value["key"] for key, value in iteritems(info)] info = [value["key"] for key, value in iteritems(info)]
self.assertIn([("provider_ids.foo", 1)], info) assert [("provider_ids.foo", 1)] in info
self.assertIn([("provider_ids.bar", 1)], info) assert [("provider_ids.bar", 1)] in info
def test_sparse_compound_indexes(self): def test_sparse_compound_indexes(self):
class MyDoc(Document): class MyDoc(Document):
@ -967,11 +956,10 @@ class TestIndexes(unittest.TestCase):
} }
info = MyDoc.objects._collection.index_information() info = MyDoc.objects._collection.index_information()
self.assertEqual( assert [("provider_ids.foo", 1), ("provider_ids.bar", 1)] == info[
[("provider_ids.foo", 1), ("provider_ids.bar", 1)], "provider_ids.foo_1_provider_ids.bar_1"
info["provider_ids.foo_1_provider_ids.bar_1"]["key"], ]["key"]
) assert info["provider_ids.foo_1_provider_ids.bar_1"]["sparse"]
self.assertTrue(info["provider_ids.foo_1_provider_ids.bar_1"]["sparse"])
def test_text_indexes(self): def test_text_indexes(self):
class Book(Document): class Book(Document):
@ -979,9 +967,9 @@ class TestIndexes(unittest.TestCase):
meta = {"indexes": ["$title"]} meta = {"indexes": ["$title"]}
indexes = Book.objects._collection.index_information() indexes = Book.objects._collection.index_information()
self.assertIn("title_text", indexes) assert "title_text" in indexes
key = indexes["title_text"]["key"] key = indexes["title_text"]["key"]
self.assertIn(("_fts", "text"), key) assert ("_fts", "text") in key
def test_hashed_indexes(self): def test_hashed_indexes(self):
class Book(Document): class Book(Document):
@ -989,8 +977,8 @@ class TestIndexes(unittest.TestCase):
meta = {"indexes": ["#ref_id"]} meta = {"indexes": ["#ref_id"]}
indexes = Book.objects._collection.index_information() indexes = Book.objects._collection.index_information()
self.assertIn("ref_id_hashed", indexes) assert "ref_id_hashed" in indexes
self.assertIn(("ref_id", "hashed"), indexes["ref_id_hashed"]["key"]) assert ("ref_id", "hashed") in indexes["ref_id_hashed"]["key"]
def test_indexes_after_database_drop(self): def test_indexes_after_database_drop(self):
""" """
@ -1027,7 +1015,8 @@ class TestIndexes(unittest.TestCase):
# Create Post #2 # Create Post #2
post2 = BlogPost(title="test2", slug="test") post2 = BlogPost(title="test2", slug="test")
self.assertRaises(NotUniqueError, post2.save) with pytest.raises(NotUniqueError):
post2.save()
finally: finally:
# Drop the temporary database at the end # Drop the temporary database at the end
connection.drop_database("tempdatabase") connection.drop_database("tempdatabase")
@ -1074,15 +1063,12 @@ class TestIndexes(unittest.TestCase):
"dropDups" "dropDups"
] # drop the index dropDups - it is deprecated in MongoDB 3+ ] # drop the index dropDups - it is deprecated in MongoDB 3+
self.assertEqual( assert index_info == {
index_info, "txt_1": {"key": [("txt", 1)], "background": False},
{ "_id_": {"key": [("_id", 1)]},
"txt_1": {"key": [("txt", 1)], "background": False}, "txt2_1": {"key": [("txt2", 1)], "background": False},
"_id_": {"key": [("_id", 1)]}, "_cls_1": {"key": [("_cls", 1)], "background": False},
"txt2_1": {"key": [("txt2", 1)], "background": False}, }
"_cls_1": {"key": [("_cls", 1)], "background": False},
},
)
def test_compound_index_underscore_cls_not_overwritten(self): def test_compound_index_underscore_cls_not_overwritten(self):
""" """
@ -1105,7 +1091,7 @@ class TestIndexes(unittest.TestCase):
TestDoc.ensure_indexes() TestDoc.ensure_indexes()
index_info = TestDoc._get_collection().index_information() 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__": if __name__ == "__main__":

View File

@ -2,6 +2,7 @@
import unittest import unittest
import warnings import warnings
import pytest
from six import iteritems from six import iteritems
from mongoengine import ( from mongoengine import (
@ -37,12 +38,12 @@ class TestInheritance(MongoDBTestCase):
meta = {"allow_inheritance": True} meta = {"allow_inheritance": True}
test_doc = DataDoc(name="test", embed=EmbedData(data="data")) test_doc = DataDoc(name="test", embed=EmbedData(data="data"))
self.assertEqual(test_doc._cls, "DataDoc") assert test_doc._cls == "DataDoc"
self.assertEqual(test_doc.embed._cls, "EmbedData") assert test_doc.embed._cls == "EmbedData"
test_doc.save() test_doc.save()
saved_doc = DataDoc.objects.with_id(test_doc.id) saved_doc = DataDoc.objects.with_id(test_doc.id)
self.assertEqual(test_doc._cls, saved_doc._cls) assert test_doc._cls == saved_doc._cls
self.assertEqual(test_doc.embed._cls, saved_doc.embed._cls) assert test_doc.embed._cls == saved_doc.embed._cls
test_doc.delete() test_doc.delete()
def test_superclasses(self): def test_superclasses(self):
@ -67,12 +68,12 @@ class TestInheritance(MongoDBTestCase):
class Human(Mammal): class Human(Mammal):
pass pass
self.assertEqual(Animal._superclasses, ()) assert Animal._superclasses == ()
self.assertEqual(Fish._superclasses, ("Animal",)) assert Fish._superclasses == ("Animal",)
self.assertEqual(Guppy._superclasses, ("Animal", "Animal.Fish")) assert Guppy._superclasses == ("Animal", "Animal.Fish")
self.assertEqual(Mammal._superclasses, ("Animal",)) assert Mammal._superclasses == ("Animal",)
self.assertEqual(Dog._superclasses, ("Animal", "Animal.Mammal")) assert Dog._superclasses == ("Animal", "Animal.Mammal")
self.assertEqual(Human._superclasses, ("Animal", "Animal.Mammal")) assert Human._superclasses == ("Animal", "Animal.Mammal")
def test_external_superclasses(self): def test_external_superclasses(self):
"""Ensure that the correct list of super classes is assembled when """Ensure that the correct list of super classes is assembled when
@ -97,18 +98,12 @@ class TestInheritance(MongoDBTestCase):
class Human(Mammal): class Human(Mammal):
pass pass
self.assertEqual(Animal._superclasses, ("Base",)) assert Animal._superclasses == ("Base",)
self.assertEqual(Fish._superclasses, ("Base", "Base.Animal")) assert Fish._superclasses == ("Base", "Base.Animal")
self.assertEqual( assert Guppy._superclasses == ("Base", "Base.Animal", "Base.Animal.Fish")
Guppy._superclasses, ("Base", "Base.Animal", "Base.Animal.Fish") assert Mammal._superclasses == ("Base", "Base.Animal")
) assert Dog._superclasses == ("Base", "Base.Animal", "Base.Animal.Mammal")
self.assertEqual(Mammal._superclasses, ("Base", "Base.Animal")) assert Human._superclasses == ("Base", "Base.Animal", "Base.Animal.Mammal")
self.assertEqual(
Dog._superclasses, ("Base", "Base.Animal", "Base.Animal.Mammal")
)
self.assertEqual(
Human._superclasses, ("Base", "Base.Animal", "Base.Animal.Mammal")
)
def test_subclasses(self): def test_subclasses(self):
"""Ensure that the correct list of _subclasses (subclasses) is """Ensure that the correct list of _subclasses (subclasses) is
@ -133,24 +128,22 @@ class TestInheritance(MongoDBTestCase):
class Human(Mammal): class Human(Mammal):
pass pass
self.assertEqual( assert Animal._subclasses == (
Animal._subclasses, "Animal",
( "Animal.Fish",
"Animal", "Animal.Fish.Guppy",
"Animal.Fish", "Animal.Mammal",
"Animal.Fish.Guppy", "Animal.Mammal.Dog",
"Animal.Mammal", "Animal.Mammal.Human",
"Animal.Mammal.Dog",
"Animal.Mammal.Human",
),
) )
self.assertEqual(Fish._subclasses, ("Animal.Fish", "Animal.Fish.Guppy")) assert Fish._subclasses == ("Animal.Fish", "Animal.Fish.Guppy")
self.assertEqual(Guppy._subclasses, ("Animal.Fish.Guppy",)) assert Guppy._subclasses == ("Animal.Fish.Guppy",)
self.assertEqual( assert Mammal._subclasses == (
Mammal._subclasses, "Animal.Mammal",
("Animal.Mammal", "Animal.Mammal.Dog", "Animal.Mammal.Human"), "Animal.Mammal.Dog",
"Animal.Mammal.Human",
) )
self.assertEqual(Human._subclasses, ("Animal.Mammal.Human",)) assert Human._subclasses == ("Animal.Mammal.Human",)
def test_external_subclasses(self): def test_external_subclasses(self):
"""Ensure that the correct list of _subclasses (subclasses) is """Ensure that the correct list of _subclasses (subclasses) is
@ -175,30 +168,22 @@ class TestInheritance(MongoDBTestCase):
class Human(Mammal): class Human(Mammal):
pass pass
self.assertEqual( assert Animal._subclasses == (
Animal._subclasses, "Base.Animal",
( "Base.Animal.Fish",
"Base.Animal", "Base.Animal.Fish.Guppy",
"Base.Animal.Fish", "Base.Animal.Mammal",
"Base.Animal.Fish.Guppy", "Base.Animal.Mammal.Dog",
"Base.Animal.Mammal", "Base.Animal.Mammal.Human",
"Base.Animal.Mammal.Dog",
"Base.Animal.Mammal.Human",
),
) )
self.assertEqual( assert Fish._subclasses == ("Base.Animal.Fish", "Base.Animal.Fish.Guppy")
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",)) assert Human._subclasses == ("Base.Animal.Mammal.Human",)
self.assertEqual(
Mammal._subclasses,
(
"Base.Animal.Mammal",
"Base.Animal.Mammal.Dog",
"Base.Animal.Mammal.Human",
),
)
self.assertEqual(Human._subclasses, ("Base.Animal.Mammal.Human",))
def test_dynamic_declarations(self): def test_dynamic_declarations(self):
"""Test that declaring an extra class updates meta data""" """Test that declaring an extra class updates meta data"""
@ -206,33 +191,31 @@ class TestInheritance(MongoDBTestCase):
class Animal(Document): class Animal(Document):
meta = {"allow_inheritance": True} meta = {"allow_inheritance": True}
self.assertEqual(Animal._superclasses, ()) assert Animal._superclasses == ()
self.assertEqual(Animal._subclasses, ("Animal",)) assert Animal._subclasses == ("Animal",)
# Test dynamically adding a class changes the meta data # Test dynamically adding a class changes the meta data
class Fish(Animal): class Fish(Animal):
pass pass
self.assertEqual(Animal._superclasses, ()) assert Animal._superclasses == ()
self.assertEqual(Animal._subclasses, ("Animal", "Animal.Fish")) assert Animal._subclasses == ("Animal", "Animal.Fish")
self.assertEqual(Fish._superclasses, ("Animal",)) assert Fish._superclasses == ("Animal",)
self.assertEqual(Fish._subclasses, ("Animal.Fish",)) assert Fish._subclasses == ("Animal.Fish",)
# Test dynamically adding an inherited class changes the meta data # Test dynamically adding an inherited class changes the meta data
class Pike(Fish): class Pike(Fish):
pass pass
self.assertEqual(Animal._superclasses, ()) assert Animal._superclasses == ()
self.assertEqual( assert Animal._subclasses == ("Animal", "Animal.Fish", "Animal.Fish.Pike")
Animal._subclasses, ("Animal", "Animal.Fish", "Animal.Fish.Pike")
)
self.assertEqual(Fish._superclasses, ("Animal",)) assert Fish._superclasses == ("Animal",)
self.assertEqual(Fish._subclasses, ("Animal.Fish", "Animal.Fish.Pike")) assert Fish._subclasses == ("Animal.Fish", "Animal.Fish.Pike")
self.assertEqual(Pike._superclasses, ("Animal", "Animal.Fish")) assert Pike._superclasses == ("Animal", "Animal.Fish")
self.assertEqual(Pike._subclasses, ("Animal.Fish.Pike",)) assert Pike._subclasses == ("Animal.Fish.Pike",)
def test_inheritance_meta_data(self): def test_inheritance_meta_data(self):
"""Ensure that document may inherit fields from a superclass document. """Ensure that document may inherit fields from a superclass document.
@ -247,10 +230,10 @@ class TestInheritance(MongoDBTestCase):
class Employee(Person): class Employee(Person):
salary = IntField() salary = IntField()
self.assertEqual( assert ["_cls", "age", "id", "name", "salary"] == sorted(
["_cls", "age", "id", "name", "salary"], sorted(Employee._fields.keys()) 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): def test_inheritance_to_mongo_keys(self):
"""Ensure that document may inherit fields from a superclass document. """Ensure that document may inherit fields from a superclass document.
@ -265,17 +248,17 @@ class TestInheritance(MongoDBTestCase):
class Employee(Person): class Employee(Person):
salary = IntField() salary = IntField()
self.assertEqual( assert ["_cls", "age", "id", "name", "salary"] == sorted(
["_cls", "age", "id", "name", "salary"], sorted(Employee._fields.keys()) Employee._fields.keys()
) )
self.assertEqual( assert Person(name="Bob", age=35).to_mongo().keys() == ["_cls", "name", "age"]
Person(name="Bob", age=35).to_mongo().keys(), ["_cls", "name", "age"] assert Employee(name="Bob", age=35, salary=0).to_mongo().keys() == [
) "_cls",
self.assertEqual( "name",
Employee(name="Bob", age=35, salary=0).to_mongo().keys(), "age",
["_cls", "name", "age", "salary"], "salary",
) ]
self.assertEqual(Employee._get_collection_name(), Person._get_collection_name()) assert Employee._get_collection_name() == Person._get_collection_name()
def test_indexes_and_multiple_inheritance(self): def test_indexes_and_multiple_inheritance(self):
""" Ensure that all of the indexes are created for a document with """ Ensure that all of the indexes are created for a document with
@ -301,13 +284,10 @@ class TestInheritance(MongoDBTestCase):
C.ensure_indexes() C.ensure_indexes()
self.assertEqual( assert sorted(
sorted( [idx["key"] for idx in C._get_collection().index_information().values()]
[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)]]
sorted(
[[(u"_cls", 1), (u"b", 1)], [(u"_id", 1)], [(u"_cls", 1), (u"a", 1)]]
),
) )
def test_polymorphic_queries(self): def test_polymorphic_queries(self):
@ -338,13 +318,13 @@ class TestInheritance(MongoDBTestCase):
Human().save() Human().save()
classes = [obj.__class__ for obj in Animal.objects] 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] 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] classes = [obj.__class__ for obj in Human.objects]
self.assertEqual(classes, [Human]) assert classes == [Human]
def test_allow_inheritance(self): def test_allow_inheritance(self):
"""Ensure that inheritance is disabled by default on simple """Ensure that inheritance is disabled by default on simple
@ -355,20 +335,18 @@ class TestInheritance(MongoDBTestCase):
name = StringField() name = StringField()
# can't inherit because Animal didn't explicitly allow inheritance # 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): class Dog(Animal):
pass pass
self.assertIn("Document Animal may not be subclassed", str(cm.exception))
# Check that _cls etc aren't present on simple documents # Check that _cls etc aren't present on simple documents
dog = Animal(name="dog").save() 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()] collection = self.db[Animal._get_collection_name()]
obj = collection.find_one() obj = collection.find_one()
self.assertNotIn("_cls", obj) assert "_cls" not in obj
def test_cant_turn_off_inheritance_on_subclass(self): def test_cant_turn_off_inheritance_on_subclass(self):
"""Ensure if inheritance is on in a subclass you cant turn it off. """Ensure if inheritance is on in a subclass you cant turn it off.
@ -378,14 +356,14 @@ class TestInheritance(MongoDBTestCase):
name = StringField() name = StringField()
meta = {"allow_inheritance": True} meta = {"allow_inheritance": True}
with self.assertRaises(ValueError) as cm: with pytest.raises(ValueError) as exc_info:
class Mammal(Animal): class Mammal(Animal):
meta = {"allow_inheritance": False} meta = {"allow_inheritance": False}
self.assertEqual( assert (
str(cm.exception), str(exc_info.value)
'Only direct subclasses of Document may set "allow_inheritance" to False', == 'Only direct subclasses of Document may set "allow_inheritance" to False'
) )
def test_allow_inheritance_abstract_document(self): def test_allow_inheritance_abstract_document(self):
@ -399,14 +377,14 @@ class TestInheritance(MongoDBTestCase):
class Animal(FinalDocument): class Animal(FinalDocument):
name = StringField() name = StringField()
with self.assertRaises(ValueError): with pytest.raises(ValueError):
class Mammal(Animal): class Mammal(Animal):
pass pass
# Check that _cls isn't present in simple documents # Check that _cls isn't present in simple documents
doc = Animal(name="dog") 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): def test_using_abstract_class_in_reference_field(self):
# Ensures no regression of #1920 # Ensures no regression of #1920
@ -452,10 +430,10 @@ class TestInheritance(MongoDBTestCase):
name = StringField() name = StringField()
berlin = EuropeanCity(name="Berlin", continent="Europe") berlin = EuropeanCity(name="Berlin", continent="Europe")
self.assertEqual(len(berlin._db_field_map), len(berlin._fields_ordered)) assert len(berlin._db_field_map) == len(berlin._fields_ordered)
self.assertEqual(len(berlin._reverse_db_field_map), len(berlin._fields_ordered)) assert len(berlin._reverse_db_field_map) == len(berlin._fields_ordered)
self.assertEqual(len(berlin._fields_ordered), 3) assert len(berlin._fields_ordered) == 3
self.assertEqual(berlin._fields_ordered[0], "id") assert berlin._fields_ordered[0] == "id"
def test_auto_id_not_set_if_specific_in_parent_class(self): def test_auto_id_not_set_if_specific_in_parent_class(self):
class City(Document): class City(Document):
@ -467,10 +445,10 @@ class TestInheritance(MongoDBTestCase):
name = StringField() name = StringField()
berlin = EuropeanCity(name="Berlin", continent="Europe") berlin = EuropeanCity(name="Berlin", continent="Europe")
self.assertEqual(len(berlin._db_field_map), len(berlin._fields_ordered)) assert len(berlin._db_field_map) == len(berlin._fields_ordered)
self.assertEqual(len(berlin._reverse_db_field_map), len(berlin._fields_ordered)) assert len(berlin._reverse_db_field_map) == len(berlin._fields_ordered)
self.assertEqual(len(berlin._fields_ordered), 3) assert len(berlin._fields_ordered) == 3
self.assertEqual(berlin._fields_ordered[0], "city_id") assert berlin._fields_ordered[0] == "city_id"
def test_auto_id_vs_non_pk_id_field(self): def test_auto_id_vs_non_pk_id_field(self):
class City(Document): class City(Document):
@ -482,12 +460,12 @@ class TestInheritance(MongoDBTestCase):
name = StringField() name = StringField()
berlin = EuropeanCity(name="Berlin", continent="Europe") berlin = EuropeanCity(name="Berlin", continent="Europe")
self.assertEqual(len(berlin._db_field_map), len(berlin._fields_ordered)) assert len(berlin._db_field_map) == len(berlin._fields_ordered)
self.assertEqual(len(berlin._reverse_db_field_map), len(berlin._fields_ordered)) assert len(berlin._reverse_db_field_map) == len(berlin._fields_ordered)
self.assertEqual(len(berlin._fields_ordered), 4) assert len(berlin._fields_ordered) == 4
self.assertEqual(berlin._fields_ordered[0], "auto_id_0") assert berlin._fields_ordered[0] == "auto_id_0"
berlin.save() 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): def test_abstract_document_creation_does_not_fail(self):
class City(Document): class City(Document):
@ -495,9 +473,9 @@ class TestInheritance(MongoDBTestCase):
meta = {"abstract": True, "allow_inheritance": False} meta = {"abstract": True, "allow_inheritance": False}
city = City(continent="asia") 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? # TODO: expected error? Shouldn't we create a new error type?
with self.assertRaises(KeyError): with pytest.raises(KeyError):
setattr(city, "pk", 1) setattr(city, "pk", 1)
def test_allow_inheritance_embedded_document(self): def test_allow_inheritance_embedded_document(self):
@ -506,20 +484,20 @@ class TestInheritance(MongoDBTestCase):
class Comment(EmbeddedDocument): class Comment(EmbeddedDocument):
content = StringField() content = StringField()
with self.assertRaises(ValueError): with pytest.raises(ValueError):
class SpecialComment(Comment): class SpecialComment(Comment):
pass pass
doc = Comment(content="test") doc = Comment(content="test")
self.assertNotIn("_cls", doc.to_mongo()) assert "_cls" not in doc.to_mongo()
class Comment(EmbeddedDocument): class Comment(EmbeddedDocument):
content = StringField() content = StringField()
meta = {"allow_inheritance": True} meta = {"allow_inheritance": True}
doc = Comment(content="test") doc = Comment(content="test")
self.assertIn("_cls", doc.to_mongo()) assert "_cls" in doc.to_mongo()
def test_document_inheritance(self): def test_document_inheritance(self):
"""Ensure mutliple inheritance of abstract documents """Ensure mutliple inheritance of abstract documents
@ -537,7 +515,7 @@ class TestInheritance(MongoDBTestCase):
pass pass
except Exception: except Exception:
self.assertTrue(False, "Couldn't create MyDocument class") assert False, "Couldn't create MyDocument class"
def test_abstract_documents(self): def test_abstract_documents(self):
"""Ensure that a document superclass can be marked as abstract """Ensure that a document superclass can be marked as abstract
@ -574,20 +552,20 @@ class TestInheritance(MongoDBTestCase):
for k, v in iteritems(defaults): for k, v in iteritems(defaults):
for cls in [Animal, Fish, Guppy]: for cls in [Animal, Fish, Guppy]:
self.assertEqual(cls._meta[k], v) assert cls._meta[k] == v
self.assertNotIn("collection", Animal._meta) assert "collection" not in Animal._meta
self.assertNotIn("collection", Mammal._meta) assert "collection" not in Mammal._meta
self.assertEqual(Animal._get_collection_name(), None) assert Animal._get_collection_name() is None
self.assertEqual(Mammal._get_collection_name(), None) assert Mammal._get_collection_name() is None
self.assertEqual(Fish._get_collection_name(), "fish") assert Fish._get_collection_name() == "fish"
self.assertEqual(Guppy._get_collection_name(), "fish") assert Guppy._get_collection_name() == "fish"
self.assertEqual(Human._get_collection_name(), "human") assert Human._get_collection_name() == "human"
# ensure that a subclass of a non-abstract class can't be abstract # ensure that a subclass of a non-abstract class can't be abstract
with self.assertRaises(ValueError): with pytest.raises(ValueError):
class EvilHuman(Human): class EvilHuman(Human):
evil = BooleanField(default=True) evil = BooleanField(default=True)
@ -601,7 +579,7 @@ class TestInheritance(MongoDBTestCase):
class B(A): class B(A):
pass pass
self.assertFalse(B._meta["abstract"]) assert not B._meta["abstract"]
def test_inherited_collections(self): def test_inherited_collections(self):
"""Ensure that subclassed documents don't override parents' """Ensure that subclassed documents don't override parents'
@ -647,8 +625,8 @@ class TestInheritance(MongoDBTestCase):
real_person = Drinker(drink=beer) real_person = Drinker(drink=beer)
real_person.save() real_person.save()
self.assertEqual(Drinker.objects[0].drink.name, red_bull.name) assert Drinker.objects[0].drink.name == red_bull.name
self.assertEqual(Drinker.objects[1].drink.name, beer.name) assert Drinker.objects[1].drink.name == beer.name
if __name__ == "__main__": if __name__ == "__main__":

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@ class TestJson(MongoDBTestCase):
expected_json = """{"embedded":{"string":"Inner Hello"},"string":"Hello"}""" expected_json = """{"embedded":{"string":"Inner Hello"},"string":"Hello"}"""
self.assertEqual(doc_json, expected_json) assert doc_json == expected_json
def test_json_simple(self): def test_json_simple(self):
class Embedded(EmbeddedDocument): class Embedded(EmbeddedDocument):
@ -52,9 +52,9 @@ class TestJson(MongoDBTestCase):
doc_json = doc.to_json(sort_keys=True, separators=(",", ":")) doc_json = doc.to_json(sort_keys=True, separators=(",", ":"))
expected_json = """{"embedded_field":{"string":"Hi"},"string":"Hi"}""" 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): def test_json_complex(self):
class EmbeddedDoc(EmbeddedDocument): class EmbeddedDoc(EmbeddedDocument):
@ -99,7 +99,7 @@ class TestJson(MongoDBTestCase):
return json.loads(self.to_json()) == json.loads(other.to_json()) return json.loads(self.to_json()) == json.loads(other.to_json())
doc = Doc() doc = Doc()
self.assertEqual(doc, Doc.from_json(doc.to_json())) assert doc == Doc.from_json(doc.to_json())
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -2,6 +2,8 @@
import unittest import unittest
from datetime import datetime from datetime import datetime
import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -11,12 +13,12 @@ class TestValidatorError(MongoDBTestCase):
"""Ensure a ValidationError handles error to_dict correctly. """Ensure a ValidationError handles error to_dict correctly.
""" """
error = ValidationError("root") error = ValidationError("root")
self.assertEqual(error.to_dict(), {}) assert error.to_dict() == {}
# 1st level error schema # 1st level error schema
error.errors = {"1st": ValidationError("bad 1st")} error.errors = {"1st": ValidationError("bad 1st")}
self.assertIn("1st", error.to_dict()) assert "1st" in error.to_dict()
self.assertEqual(error.to_dict()["1st"], "bad 1st") assert error.to_dict()["1st"] == "bad 1st"
# 2nd level error schema # 2nd level error schema
error.errors = { error.errors = {
@ -24,10 +26,10 @@ class TestValidatorError(MongoDBTestCase):
"bad 1st", errors={"2nd": ValidationError("bad 2nd")} "bad 1st", errors={"2nd": ValidationError("bad 2nd")}
) )
} }
self.assertIn("1st", error.to_dict()) assert "1st" in error.to_dict()
self.assertIsInstance(error.to_dict()["1st"], dict) assert isinstance(error.to_dict()["1st"], dict)
self.assertIn("2nd", error.to_dict()["1st"]) assert "2nd" in error.to_dict()["1st"]
self.assertEqual(error.to_dict()["1st"]["2nd"], "bad 2nd") assert error.to_dict()["1st"]["2nd"] == "bad 2nd"
# moar levels # moar levels
error.errors = { error.errors = {
@ -45,13 +47,13 @@ class TestValidatorError(MongoDBTestCase):
}, },
) )
} }
self.assertIn("1st", error.to_dict()) assert "1st" in error.to_dict()
self.assertIn("2nd", error.to_dict()["1st"]) assert "2nd" in error.to_dict()["1st"]
self.assertIn("3rd", error.to_dict()["1st"]["2nd"]) assert "3rd" in error.to_dict()["1st"]["2nd"]
self.assertIn("4th", error.to_dict()["1st"]["2nd"]["3rd"]) assert "4th" in error.to_dict()["1st"]["2nd"]["3rd"]
self.assertEqual(error.to_dict()["1st"]["2nd"]["3rd"]["4th"], "Inception") 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): def test_model_validation(self):
class User(Document): class User(Document):
@ -61,19 +63,19 @@ class TestValidatorError(MongoDBTestCase):
try: try:
User().validate() User().validate()
except ValidationError as e: except ValidationError as e:
self.assertIn("User:None", e.message) assert "User:None" in e.message
self.assertEqual( assert e.to_dict() == {
e.to_dict(), "username": "Field is required",
{"username": "Field is required", "name": "Field is required"}, "name": "Field is required",
) }
user = User(username="RossC0", name="Ross").save() user = User(username="RossC0", name="Ross").save()
user.name = None user.name = None
try: try:
user.save() user.save()
except ValidationError as e: except ValidationError as e:
self.assertIn("User:RossC0", e.message) assert "User:RossC0" in e.message
self.assertEqual(e.to_dict(), {"name": "Field is required"}) assert e.to_dict() == {"name": "Field is required"}
def test_fields_rewrite(self): def test_fields_rewrite(self):
class BasePerson(Document): class BasePerson(Document):
@ -85,7 +87,8 @@ class TestValidatorError(MongoDBTestCase):
name = StringField(required=True) name = StringField(required=True)
p = Person(age=15) p = Person(age=15)
self.assertRaises(ValidationError, p.validate) with pytest.raises(ValidationError):
p.validate()
def test_embedded_document_validation(self): def test_embedded_document_validation(self):
"""Ensure that embedded documents may be validated. """Ensure that embedded documents may be validated.
@ -96,17 +99,19 @@ class TestValidatorError(MongoDBTestCase):
content = StringField(required=True) content = StringField(required=True)
comment = Comment() comment = Comment()
self.assertRaises(ValidationError, comment.validate) with pytest.raises(ValidationError):
comment.validate()
comment.content = "test" comment.content = "test"
comment.validate() comment.validate()
comment.date = 4 comment.date = 4
self.assertRaises(ValidationError, comment.validate) with pytest.raises(ValidationError):
comment.validate()
comment.date = datetime.now() comment.date = datetime.now()
comment.validate() comment.validate()
self.assertEqual(comment._instance, None) assert comment._instance is None
def test_embedded_db_field_validate(self): def test_embedded_db_field_validate(self):
class SubDoc(EmbeddedDocument): class SubDoc(EmbeddedDocument):
@ -119,10 +124,8 @@ class TestValidatorError(MongoDBTestCase):
try: try:
Doc(id="bad").validate() Doc(id="bad").validate()
except ValidationError as e: except ValidationError as e:
self.assertIn("SubDoc:None", e.message) assert "SubDoc:None" in e.message
self.assertEqual( assert e.to_dict() == {"e": {"val": "OK could not be converted to int"}}
e.to_dict(), {"e": {"val": "OK could not be converted to int"}}
)
Doc.drop_collection() Doc.drop_collection()
@ -130,18 +133,16 @@ class TestValidatorError(MongoDBTestCase):
doc = Doc.objects.first() doc = Doc.objects.first()
keys = doc._data.keys() keys = doc._data.keys()
self.assertEqual(2, len(keys)) assert 2 == len(keys)
self.assertIn("e", keys) assert "e" in keys
self.assertIn("id", keys) assert "id" in keys
doc.e.val = "OK" doc.e.val = "OK"
try: try:
doc.save() doc.save()
except ValidationError as e: except ValidationError as e:
self.assertIn("Doc:test", e.message) assert "Doc:test" in e.message
self.assertEqual( assert e.to_dict() == {"e": {"val": "OK could not be converted to int"}}
e.to_dict(), {"e": {"val": "OK could not be converted to int"}}
)
def test_embedded_weakref(self): def test_embedded_weakref(self):
class SubDoc(EmbeddedDocument): class SubDoc(EmbeddedDocument):
@ -157,14 +158,16 @@ class TestValidatorError(MongoDBTestCase):
s = SubDoc() s = SubDoc()
self.assertRaises(ValidationError, s.validate) with pytest.raises(ValidationError):
s.validate()
d1.e = s d1.e = s
d2.e = s d2.e = s
del d1 del d1
self.assertRaises(ValidationError, d2.validate) with pytest.raises(ValidationError):
d2.validate()
def test_parent_reference_in_child_document(self): def test_parent_reference_in_child_document(self):
""" """

View File

@ -2,7 +2,7 @@
import uuid import uuid
from bson import Binary from bson import Binary
from nose.plugins.skip import SkipTest import pytest
import six import six
from mongoengine import * from mongoengine import *
@ -31,8 +31,8 @@ class TestBinaryField(MongoDBTestCase):
attachment.save() attachment.save()
attachment_1 = Attachment.objects().first() attachment_1 = Attachment.objects().first()
self.assertEqual(MIME_TYPE, attachment_1.content_type) assert MIME_TYPE == attachment_1.content_type
self.assertEqual(BLOB, six.binary_type(attachment_1.blob)) assert BLOB == six.binary_type(attachment_1.blob)
def test_validation_succeeds(self): def test_validation_succeeds(self):
"""Ensure that valid values can be assigned to binary fields. """Ensure that valid values can be assigned to binary fields.
@ -45,13 +45,15 @@ class TestBinaryField(MongoDBTestCase):
blob = BinaryField(max_bytes=4) blob = BinaryField(max_bytes=4)
attachment_required = AttachmentRequired() 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.blob = Binary(six.b("\xe6\x00\xc4\xff\x07"))
attachment_required.validate() attachment_required.validate()
_5_BYTES = six.b("\xe6\x00\xc4\xff\x07") _5_BYTES = six.b("\xe6\x00\xc4\xff\x07")
_4_BYTES = six.b("\xe6\x00\xc4\xff") _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() AttachmentSizeLimit(blob=_4_BYTES).validate()
def test_validation_fails(self): def test_validation_fails(self):
@ -61,7 +63,8 @@ class TestBinaryField(MongoDBTestCase):
blob = BinaryField() blob = BinaryField()
for invalid_data in (2, u"Im_a_unicode", ["some_str"]): 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): def test__primary(self):
class Attachment(Document): class Attachment(Document):
@ -70,10 +73,10 @@ class TestBinaryField(MongoDBTestCase):
Attachment.drop_collection() Attachment.drop_collection()
binary_id = uuid.uuid4().bytes binary_id = uuid.uuid4().bytes
att = Attachment(id=binary_id).save() att = Attachment(id=binary_id).save()
self.assertEqual(1, Attachment.objects.count()) assert 1 == Attachment.objects.count()
self.assertEqual(1, Attachment.objects.filter(id=att.id).count()) assert 1 == Attachment.objects.filter(id=att.id).count()
att.delete() att.delete()
self.assertEqual(0, Attachment.objects.count()) assert 0 == Attachment.objects.count()
def test_primary_filter_by_binary_pk_as_str(self): def test_primary_filter_by_binary_pk_as_str(self):
class Attachment(Document): class Attachment(Document):
@ -82,9 +85,9 @@ class TestBinaryField(MongoDBTestCase):
Attachment.drop_collection() Attachment.drop_collection()
binary_id = uuid.uuid4().bytes binary_id = uuid.uuid4().bytes
att = Attachment(id=binary_id).save() 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() att.delete()
self.assertEqual(0, Attachment.objects.count()) assert 0 == Attachment.objects.count()
def test_match_querying_with_bytes(self): def test_match_querying_with_bytes(self):
class MyDocument(Document): class MyDocument(Document):
@ -94,7 +97,7 @@ class TestBinaryField(MongoDBTestCase):
doc = MyDocument(bin_field=BIN_VALUE).save() doc = MyDocument(bin_field=BIN_VALUE).save()
matched_doc = MyDocument.objects(bin_field=BIN_VALUE).first() 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): def test_match_querying_with_binary(self):
class MyDocument(Document): class MyDocument(Document):
@ -105,7 +108,7 @@ class TestBinaryField(MongoDBTestCase):
doc = MyDocument(bin_field=BIN_VALUE).save() doc = MyDocument(bin_field=BIN_VALUE).save()
matched_doc = MyDocument.objects(bin_field=Binary(BIN_VALUE)).first() 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): def test_modify_operation__set(self):
"""Ensures no regression of bug #1127""" """Ensures no regression of bug #1127"""
@ -119,11 +122,11 @@ class TestBinaryField(MongoDBTestCase):
doc = MyDocument.objects(some_field="test").modify( doc = MyDocument.objects(some_field="test").modify(
upsert=True, new=True, set__bin_field=BIN_VALUE upsert=True, new=True, set__bin_field=BIN_VALUE
) )
self.assertEqual(doc.some_field, "test") assert doc.some_field == "test"
if six.PY3: if six.PY3:
self.assertEqual(doc.bin_field, BIN_VALUE) assert doc.bin_field == BIN_VALUE
else: else:
self.assertEqual(doc.bin_field, Binary(BIN_VALUE)) assert doc.bin_field == Binary(BIN_VALUE)
def test_update_one(self): def test_update_one(self):
"""Ensures no regression of bug #1127""" """Ensures no regression of bug #1127"""
@ -139,9 +142,9 @@ class TestBinaryField(MongoDBTestCase):
n_updated = MyDocument.objects(bin_field=bin_data).update_one( n_updated = MyDocument.objects(bin_field=bin_data).update_one(
bin_field=BIN_VALUE bin_field=BIN_VALUE
) )
self.assertEqual(n_updated, 1) assert n_updated == 1
fetched = MyDocument.objects.with_id(doc.id) fetched = MyDocument.objects.with_id(doc.id)
if six.PY3: if six.PY3:
self.assertEqual(fetched.bin_field, BIN_VALUE) assert fetched.bin_field == BIN_VALUE
else: else:
self.assertEqual(fetched.bin_field, Binary(BIN_VALUE)) assert fetched.bin_field == Binary(BIN_VALUE)

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from mongoengine import * import pytest
from mongoengine import *
from tests.utils import MongoDBTestCase, get_as_pymongo from tests.utils import MongoDBTestCase, get_as_pymongo
@ -11,7 +12,7 @@ class TestBooleanField(MongoDBTestCase):
person = Person(admin=True) person = Person(admin=True)
person.save() 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): def test_validation(self):
"""Ensure that invalid values cannot be assigned to boolean """Ensure that invalid values cannot be assigned to boolean
@ -26,11 +27,14 @@ class TestBooleanField(MongoDBTestCase):
person.validate() person.validate()
person.admin = 2 person.admin = 2
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.admin = "Yes" person.admin = "Yes"
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.admin = "False" person.admin = "False"
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
def test_weirdness_constructor(self): def test_weirdness_constructor(self):
"""When attribute is set in contructor, it gets cast into a bool """When attribute is set in contructor, it gets cast into a bool
@ -42,7 +46,7 @@ class TestBooleanField(MongoDBTestCase):
admin = BooleanField() admin = BooleanField()
new_person = Person(admin="False") new_person = Person(admin="False")
self.assertTrue(new_person.admin) assert new_person.admin
new_person = Person(admin="0") new_person = Person(admin="0")
self.assertTrue(new_person.admin) assert new_person.admin

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from decimal import Decimal from decimal import Decimal
from mongoengine import * import pytest
from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -46,29 +47,29 @@ class TestCachedReferenceField(MongoDBTestCase):
a = Animal(name="Leopard", tag="heavy") a = Animal(name="Leopard", tag="heavy")
a.save() a.save()
self.assertEqual(Animal._cached_reference_fields, [Ocorrence.animal]) assert Animal._cached_reference_fields == [Ocorrence.animal]
o = Ocorrence(person="teste", animal=a) o = Ocorrence(person="teste", animal=a)
o.save() o.save()
p = Ocorrence(person="Wilson") p = Ocorrence(person="Wilson")
p.save() 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 # counts
Ocorrence(person="teste 2").save() Ocorrence(person="teste 2").save()
Ocorrence(person="teste 3").save() Ocorrence(person="teste 3").save()
count = Ocorrence.objects(animal__tag="heavy").count() count = Ocorrence.objects(animal__tag="heavy").count()
self.assertEqual(count, 1) assert count == 1
ocorrence = Ocorrence.objects(animal__tag="heavy").first() ocorrence = Ocorrence.objects(animal__tag="heavy").first()
self.assertEqual(ocorrence.person, "teste") assert ocorrence.person == "teste"
self.assertIsInstance(ocorrence.animal, Animal) assert isinstance(ocorrence.animal, Animal)
def test_with_decimal(self): def test_with_decimal(self):
class PersonAuto(Document): class PersonAuto(Document):
@ -88,10 +89,11 @@ class TestCachedReferenceField(MongoDBTestCase):
s = SocialTest(group="dev", person=p) s = SocialTest(group="dev", person=p)
s.save() s.save()
self.assertEqual( assert SocialTest.objects._collection.find_one({"person.salary": 7000.00}) == {
SocialTest.objects._collection.find_one({"person.salary": 7000.00}), "_id": s.pk,
{"_id": s.pk, "group": s.group, "person": {"_id": p.pk, "salary": 7000.00}}, "group": s.group,
) "person": {"_id": p.pk, "salary": 7000.00},
}
def test_cached_reference_field_reference(self): def test_cached_reference_field_reference(self):
class Group(Document): class Group(Document):
@ -131,18 +133,15 @@ class TestCachedReferenceField(MongoDBTestCase):
s2 = SocialData(obs="testing 321", person=p3, tags=["tag3", "tag4"]) s2 = SocialData(obs="testing 321", person=p3, tags=["tag3", "tag4"])
s2.save() s2.save()
self.assertEqual( assert SocialData.objects._collection.find_one({"tags": "tag2"}) == {
SocialData.objects._collection.find_one({"tags": "tag2"}), "_id": s1.pk,
{ "obs": "testing 123",
"_id": s1.pk, "tags": ["tag1", "tag2"],
"obs": "testing 123", "person": {"_id": p1.pk, "group": g1.pk},
"tags": ["tag1", "tag2"], }
"person": {"_id": p1.pk, "group": g1.pk},
},
)
self.assertEqual(SocialData.objects(person__group=g2).count(), 1) assert SocialData.objects(person__group=g2).count() == 1
self.assertEqual(SocialData.objects(person__group=g2).first(), s2) assert SocialData.objects(person__group=g2).first() == s2
def test_cached_reference_field_push_with_fields(self): def test_cached_reference_field_push_with_fields(self):
class Product(Document): class Product(Document):
@ -157,26 +156,20 @@ class TestCachedReferenceField(MongoDBTestCase):
product1 = Product(name="abc").save() product1 = Product(name="abc").save()
product2 = Product(name="def").save() product2 = Product(name="def").save()
basket = Basket(products=[product1]).save() basket = Basket(products=[product1]).save()
self.assertEqual( assert Basket.objects._collection.find_one() == {
Basket.objects._collection.find_one(), "_id": basket.pk,
{ "products": [{"_id": product1.pk, "name": product1.name}],
"_id": basket.pk, }
"products": [{"_id": product1.pk, "name": product1.name}],
},
)
# push to list # push to list
basket.update(push__products=product2) basket.update(push__products=product2)
basket.reload() basket.reload()
self.assertEqual( assert Basket.objects._collection.find_one() == {
Basket.objects._collection.find_one(), "_id": basket.pk,
{ "products": [
"_id": basket.pk, {"_id": product1.pk, "name": product1.name},
"products": [ {"_id": product2.pk, "name": product2.name},
{"_id": product1.pk, "name": product1.name}, ],
{"_id": product2.pk, "name": product2.name}, }
],
},
)
def test_cached_reference_field_update_all(self): def test_cached_reference_field_update_all(self):
class Person(Document): class Person(Document):
@ -194,37 +187,31 @@ class TestCachedReferenceField(MongoDBTestCase):
a2.save() a2.save()
a2 = Person.objects.with_id(a2.id) a2 = Person.objects.with_id(a2.id)
self.assertEqual(a2.father.tp, a1.tp) assert a2.father.tp == a1.tp
self.assertEqual( assert dict(a2.to_mongo()) == {
dict(a2.to_mongo()), "_id": a2.pk,
{ "name": u"Wilson Junior",
"_id": a2.pk, "tp": u"pf",
"name": u"Wilson Junior", "father": {"_id": a1.pk, "tp": u"pj"},
"tp": u"pf", }
"father": {"_id": a1.pk, "tp": u"pj"},
},
)
self.assertEqual(Person.objects(father=a1)._query, {"father._id": a1.pk}) assert Person.objects(father=a1)._query == {"father._id": a1.pk}
self.assertEqual(Person.objects(father=a1).count(), 1) assert Person.objects(father=a1).count() == 1
Person.objects.update(set__tp="pf") Person.objects.update(set__tp="pf")
Person.father.sync_all() Person.father.sync_all()
a2.reload() a2.reload()
self.assertEqual( assert dict(a2.to_mongo()) == {
dict(a2.to_mongo()), "_id": a2.pk,
{ "name": u"Wilson Junior",
"_id": a2.pk, "tp": u"pf",
"name": u"Wilson Junior", "father": {"_id": a1.pk, "tp": u"pf"},
"tp": u"pf", }
"father": {"_id": a1.pk, "tp": u"pf"},
},
)
def test_cached_reference_fields_on_embedded_documents(self): def test_cached_reference_fields_on_embedded_documents(self):
with self.assertRaises(InvalidDocumentError): with pytest.raises(InvalidDocumentError):
class Test(Document): class Test(Document):
name = StringField() name = StringField()
@ -255,15 +242,12 @@ class TestCachedReferenceField(MongoDBTestCase):
a1.save() a1.save()
a2.reload() a2.reload()
self.assertEqual( assert dict(a2.to_mongo()) == {
dict(a2.to_mongo()), "_id": a2.pk,
{ "name": "Wilson Junior",
"_id": a2.pk, "tp": "pf",
"name": "Wilson Junior", "father": {"_id": a1.pk, "tp": "pf"},
"tp": "pf", }
"father": {"_id": a1.pk, "tp": "pf"},
},
)
def test_cached_reference_auto_sync_disabled(self): def test_cached_reference_auto_sync_disabled(self):
class Persone(Document): class Persone(Document):
@ -284,15 +268,12 @@ class TestCachedReferenceField(MongoDBTestCase):
a1.tp = "pf" a1.tp = "pf"
a1.save() a1.save()
self.assertEqual( assert Persone.objects._collection.find_one({"_id": a2.pk}) == {
Persone.objects._collection.find_one({"_id": a2.pk}), "_id": a2.pk,
{ "name": "Wilson Junior",
"_id": a2.pk, "tp": "pf",
"name": "Wilson Junior", "father": {"_id": a1.pk, "tp": "pj"},
"tp": "pf", }
"father": {"_id": a1.pk, "tp": "pj"},
},
)
def test_cached_reference_embedded_fields(self): def test_cached_reference_embedded_fields(self):
class Owner(EmbeddedDocument): class Owner(EmbeddedDocument):
@ -320,28 +301,29 @@ class TestCachedReferenceField(MongoDBTestCase):
o = Ocorrence(person="teste", animal=a) o = Ocorrence(person="teste", animal=a)
o.save() o.save()
self.assertEqual( assert dict(a.to_mongo(fields=["tag", "owner.tp"])) == {
dict(a.to_mongo(fields=["tag", "owner.tp"])), "_id": a.pk,
{"_id": a.pk, "tag": "heavy", "owner": {"t": "u"}}, "tag": "heavy",
) "owner": {"t": "u"},
self.assertEqual(o.to_mongo()["animal"]["tag"], "heavy") }
self.assertEqual(o.to_mongo()["animal"]["owner"]["t"], "u") assert o.to_mongo()["animal"]["tag"] == "heavy"
assert o.to_mongo()["animal"]["owner"]["t"] == "u"
# Check to_mongo with fields # Check to_mongo with fields
self.assertNotIn("animal", o.to_mongo(fields=["person"])) assert "animal" not in o.to_mongo(fields=["person"])
# counts # counts
Ocorrence(person="teste 2").save() Ocorrence(person="teste 2").save()
Ocorrence(person="teste 3").save() Ocorrence(person="teste 3").save()
count = Ocorrence.objects(animal__tag="heavy", animal__owner__tp="u").count() count = Ocorrence.objects(animal__tag="heavy", animal__owner__tp="u").count()
self.assertEqual(count, 1) assert count == 1
ocorrence = Ocorrence.objects( ocorrence = Ocorrence.objects(
animal__tag="heavy", animal__owner__tp="u" animal__tag="heavy", animal__owner__tp="u"
).first() ).first()
self.assertEqual(ocorrence.person, "teste") assert ocorrence.person == "teste"
self.assertIsInstance(ocorrence.animal, Animal) assert isinstance(ocorrence.animal, Animal)
def test_cached_reference_embedded_list_fields(self): def test_cached_reference_embedded_list_fields(self):
class Owner(EmbeddedDocument): class Owner(EmbeddedDocument):
@ -370,13 +352,14 @@ class TestCachedReferenceField(MongoDBTestCase):
o = Ocorrence(person="teste 2", animal=a) o = Ocorrence(person="teste 2", animal=a)
o.save() o.save()
self.assertEqual( assert dict(a.to_mongo(fields=["tag", "owner.tags"])) == {
dict(a.to_mongo(fields=["tag", "owner.tags"])), "_id": a.pk,
{"_id": a.pk, "tag": "heavy", "owner": {"tags": ["cool", "funny"]}}, "tag": "heavy",
) "owner": {"tags": ["cool", "funny"]},
}
self.assertEqual(o.to_mongo()["animal"]["tag"], "heavy") assert o.to_mongo()["animal"]["tag"] == "heavy"
self.assertEqual(o.to_mongo()["animal"]["owner"]["tags"], ["cool", "funny"]) assert o.to_mongo()["animal"]["owner"]["tags"] == ["cool", "funny"]
# counts # counts
Ocorrence(person="teste 2").save() Ocorrence(person="teste 2").save()
@ -385,10 +368,10 @@ class TestCachedReferenceField(MongoDBTestCase):
query = Ocorrence.objects( query = Ocorrence.objects(
animal__tag="heavy", animal__owner__tags="cool" animal__tag="heavy", animal__owner__tags="cool"
)._query )._query
self.assertEqual(query, {"animal.owner.tags": "cool", "animal.tag": "heavy"}) assert query == {"animal.owner.tags": "cool", "animal.tag": "heavy"}
ocorrence = Ocorrence.objects( ocorrence = Ocorrence.objects(
animal__tag="heavy", animal__owner__tags="cool" animal__tag="heavy", animal__owner__tags="cool"
).first() ).first()
self.assertEqual(ocorrence.person, "teste 2") assert ocorrence.person == "teste 2"
self.assertIsInstance(ocorrence.animal, Animal) assert isinstance(ocorrence.animal, Animal)

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime import datetime
import math
import itertools import itertools
import math
import re import re
from mongoengine import * from mongoengine import *
@ -28,7 +28,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1) assert log.date == d1
# Post UTC - microseconds are rounded (down) nearest millisecond - with # Post UTC - microseconds are rounded (down) nearest millisecond - with
# default datetimefields # default datetimefields
@ -36,7 +36,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1) assert log.date == d1
# Pre UTC dates microseconds below 1000 are dropped - with default # Pre UTC dates microseconds below 1000 are dropped - with default
# datetimefields # datetimefields
@ -44,7 +44,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1) assert log.date == d1
# Pre UTC microseconds above 1000 is wonky - with default datetimefields # Pre UTC microseconds above 1000 is wonky - with default datetimefields
# log.date has an invalid microsecond value so I can't construct # log.date has an invalid microsecond value so I can't construct
@ -54,9 +54,9 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1) assert log.date == d1
log1 = LogEntry.objects.get(date=d1) log1 = LogEntry.objects.get(date=d1)
self.assertEqual(log, log1) assert log == log1
# Test string padding # Test string padding
microsecond = map(int, [math.pow(10, x) for x in range(6)]) 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): for values in itertools.product([2014], mm, dd, hh, ii, ss, microsecond):
stored = LogEntry(date=datetime.datetime(*values)).to_mongo()["date"] 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) re.match("^\d{4},\d{2},\d{2},\d{2},\d{2},\d{2},\d{6}$", stored)
is not None is not None
) )
@ -73,7 +73,7 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()[ stored = LogEntry(date_with_dots=datetime.datetime(2014, 1, 1)).to_mongo()[
"date_with_dots" "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 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() log.save()
log1 = LogEntry.objects.get(date=d1) log1 = LogEntry.objects.get(date=d1)
self.assertEqual(log, log1) assert log == log1
# create extra 59 log entries for a total of 60 # create extra 59 log entries for a total of 60
for i in range(1951, 2010): for i in range(1951, 2010):
d = datetime.datetime(i, 1, 1, 0, 0, 1, 999) d = datetime.datetime(i, 1, 1, 0, 0, 1, 999)
LogEntry(date=d).save() LogEntry(date=d).save()
self.assertEqual(LogEntry.objects.count(), 60) assert LogEntry.objects.count() == 60
# Test ordering # Test ordering
logs = LogEntry.objects.order_by("date") logs = LogEntry.objects.order_by("date")
i = 0 i = 0
while i < 59: while i < 59:
self.assertTrue(logs[i].date <= logs[i + 1].date) assert logs[i].date <= logs[i + 1].date
i += 1 i += 1
logs = LogEntry.objects.order_by("-date") logs = LogEntry.objects.order_by("-date")
i = 0 i = 0
while i < 59: while i < 59:
self.assertTrue(logs[i].date >= logs[i + 1].date) assert logs[i].date >= logs[i + 1].date
i += 1 i += 1
# Test searching # Test searching
logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) 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)) logs = LogEntry.objects.filter(date__lte=datetime.datetime(1980, 1, 1))
self.assertEqual(logs.count(), 30) assert logs.count() == 30
logs = LogEntry.objects.filter( logs = LogEntry.objects.filter(
date__lte=datetime.datetime(2011, 1, 1), date__lte=datetime.datetime(2011, 1, 1),
date__gte=datetime.datetime(2000, 1, 1), date__gte=datetime.datetime(2000, 1, 1),
) )
self.assertEqual(logs.count(), 10) assert logs.count() == 10
LogEntry.drop_collection() LogEntry.drop_collection()
@ -137,17 +137,17 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
logs = list(LogEntry.objects.order_by("date")) logs = list(LogEntry.objects.order_by("date"))
for next_idx, log in enumerate(logs[:-1], start=1): for next_idx, log in enumerate(logs[:-1], start=1):
next_log = logs[next_idx] 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")) logs = list(LogEntry.objects.order_by("-date"))
for next_idx, log in enumerate(logs[:-1], start=1): for next_idx, log in enumerate(logs[:-1], start=1):
next_log = logs[next_idx] next_log = logs[next_idx]
self.assertTrue(log.date > next_log.date) assert log.date > next_log.date
logs = LogEntry.objects.filter( logs = LogEntry.objects.filter(
date__lte=datetime.datetime(2015, 1, 1, 0, 0, 0, 10000) 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): def test_no_default_value(self):
class Log(Document): class Log(Document):
@ -156,11 +156,11 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
Log.drop_collection() Log.drop_collection()
log = Log() log = Log()
self.assertIsNone(log.timestamp) assert log.timestamp is None
log.save() log.save()
fetched_log = Log.objects.with_id(log.id) 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): def test_default_static_value(self):
NOW = datetime.datetime.utcnow() NOW = datetime.datetime.utcnow()
@ -171,11 +171,11 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
Log.drop_collection() Log.drop_collection()
log = Log() log = Log()
self.assertEqual(log.timestamp, NOW) assert log.timestamp == NOW
log.save() log.save()
fetched_log = Log.objects.with_id(log.id) fetched_log = Log.objects.with_id(log.id)
self.assertEqual(fetched_log.timestamp, NOW) assert fetched_log.timestamp == NOW
def test_default_callable(self): def test_default_callable(self):
NOW = datetime.datetime.utcnow() NOW = datetime.datetime.utcnow()
@ -186,8 +186,8 @@ class ComplexDateTimeFieldTest(MongoDBTestCase):
Log.drop_collection() Log.drop_collection()
log = Log() log = Log()
self.assertGreaterEqual(log.timestamp, NOW) assert log.timestamp >= NOW
log.save() log.save()
fetched_log = Log.objects.with_id(log.id) fetched_log = Log.objects.with_id(log.id)
self.assertGreaterEqual(fetched_log.timestamp, NOW) assert fetched_log.timestamp >= NOW

View File

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime import datetime
import pytest
import six import six
try: try:
@ -8,7 +10,6 @@ except ImportError:
dateutil = None dateutil = None
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -23,7 +24,8 @@ class TestDateField(MongoDBTestCase):
dt = DateField() dt = DateField()
md = MyDoc(dt="") md = MyDoc(dt="")
self.assertRaises(ValidationError, md.save) with pytest.raises(ValidationError):
md.save()
def test_date_from_whitespace_string(self): def test_date_from_whitespace_string(self):
""" """
@ -35,7 +37,8 @@ class TestDateField(MongoDBTestCase):
dt = DateField() dt = DateField()
md = MyDoc(dt=" ") md = MyDoc(dt=" ")
self.assertRaises(ValidationError, md.save) with pytest.raises(ValidationError):
md.save()
def test_default_values_today(self): def test_default_values_today(self):
"""Ensure that default field values are used when creating """Ensure that default field values are used when creating
@ -47,9 +50,9 @@ class TestDateField(MongoDBTestCase):
person = Person() person = Person()
person.validate() person.validate()
self.assertEqual(person.day, person.day) assert person.day == person.day
self.assertEqual(person.day, datetime.date.today()) assert person.day == datetime.date.today()
self.assertEqual(person._data["day"], person.day) assert person._data["day"] == person.day
def test_date(self): def test_date(self):
"""Tests showing pymongo date fields """Tests showing pymongo date fields
@ -67,7 +70,7 @@ class TestDateField(MongoDBTestCase):
log.date = datetime.date.today() log.date = datetime.date.today()
log.save() log.save()
log.reload() 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) d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 999)
d2 = datetime.datetime(1970, 1, 1, 0, 0, 1) d2 = datetime.datetime(1970, 1, 1, 0, 0, 1)
@ -75,16 +78,16 @@ class TestDateField(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1.date()) assert log.date == d1.date()
self.assertEqual(log.date, d2.date()) assert log.date == d2.date()
d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999) d1 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9999)
d2 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9000) d2 = datetime.datetime(1970, 1, 1, 0, 0, 1, 9000)
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1.date()) assert log.date == d1.date()
self.assertEqual(log.date, d2.date()) assert log.date == d2.date()
if not six.PY3: if not six.PY3:
# Pre UTC dates microseconds below 1000 are dropped # Pre UTC dates microseconds below 1000 are dropped
@ -94,8 +97,8 @@ class TestDateField(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertEqual(log.date, d1.date()) assert log.date == d1.date()
self.assertEqual(log.date, d2.date()) assert log.date == d2.date()
def test_regular_usage(self): def test_regular_usage(self):
"""Tests for regular datetime fields""" """Tests for regular datetime fields"""
@ -113,35 +116,35 @@ class TestDateField(MongoDBTestCase):
for query in (d1, d1.isoformat(" ")): for query in (d1, d1.isoformat(" ")):
log1 = LogEntry.objects.get(date=query) log1 = LogEntry.objects.get(date=query)
self.assertEqual(log, log1) assert log == log1
if dateutil: if dateutil:
log1 = LogEntry.objects.get(date=d1.isoformat("T")) 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 # create additional 19 log entries for a total of 20
for i in range(1971, 1990): for i in range(1971, 1990):
d = datetime.datetime(i, 1, 1, 0, 0, 1) d = datetime.datetime(i, 1, 1, 0, 0, 1)
LogEntry(date=d).save() LogEntry(date=d).save()
self.assertEqual(LogEntry.objects.count(), 20) assert LogEntry.objects.count() == 20
# Test ordering # Test ordering
logs = LogEntry.objects.order_by("date") logs = LogEntry.objects.order_by("date")
i = 0 i = 0
while i < 19: while i < 19:
self.assertTrue(logs[i].date <= logs[i + 1].date) assert logs[i].date <= logs[i + 1].date
i += 1 i += 1
logs = LogEntry.objects.order_by("-date") logs = LogEntry.objects.order_by("-date")
i = 0 i = 0
while i < 19: while i < 19:
self.assertTrue(logs[i].date >= logs[i + 1].date) assert logs[i].date >= logs[i + 1].date
i += 1 i += 1
# Test searching # Test searching
logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1)) logs = LogEntry.objects.filter(date__gte=datetime.datetime(1980, 1, 1))
self.assertEqual(logs.count(), 10) assert logs.count() == 10
def test_validation(self): def test_validation(self):
"""Ensure that invalid values cannot be assigned to datetime """Ensure that invalid values cannot be assigned to datetime
@ -166,6 +169,8 @@ class TestDateField(MongoDBTestCase):
log.validate() log.validate()
log.time = -1 log.time = -1
self.assertRaises(ValidationError, log.validate) with pytest.raises(ValidationError):
log.validate()
log.time = "ABC" log.time = "ABC"
self.assertRaises(ValidationError, log.validate) with pytest.raises(ValidationError):
log.validate()

View File

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime as dt import datetime as dt
import pytest
import six import six
try: try:
@ -24,7 +26,8 @@ class TestDateTimeField(MongoDBTestCase):
dt = DateTimeField() dt = DateTimeField()
md = MyDoc(dt="") md = MyDoc(dt="")
self.assertRaises(ValidationError, md.save) with pytest.raises(ValidationError):
md.save()
def test_datetime_from_whitespace_string(self): def test_datetime_from_whitespace_string(self):
""" """
@ -36,7 +39,8 @@ class TestDateTimeField(MongoDBTestCase):
dt = DateTimeField() dt = DateTimeField()
md = MyDoc(dt=" ") md = MyDoc(dt=" ")
self.assertRaises(ValidationError, md.save) with pytest.raises(ValidationError):
md.save()
def test_default_value_utcnow(self): def test_default_value_utcnow(self):
"""Ensure that default field values are used when creating """Ensure that default field values are used when creating
@ -50,11 +54,9 @@ class TestDateTimeField(MongoDBTestCase):
person = Person() person = Person()
person.validate() person.validate()
person_created_t0 = person.created person_created_t0 = person.created
self.assertLess(person.created - utcnow, dt.timedelta(seconds=1)) assert person.created - utcnow < dt.timedelta(seconds=1)
self.assertEqual( assert person_created_t0 == person.created # make sure it does not change
person_created_t0, person.created assert person._data["created"] == person.created
) # make sure it does not change
self.assertEqual(person._data["created"], person.created)
def test_handling_microseconds(self): def test_handling_microseconds(self):
"""Tests showing pymongo datetime fields handling of microseconds. """Tests showing pymongo datetime fields handling of microseconds.
@ -74,7 +76,7 @@ class TestDateTimeField(MongoDBTestCase):
log.date = dt.date.today() log.date = dt.date.today()
log.save() log.save()
log.reload() 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 # Post UTC - microseconds are rounded (down) nearest millisecond and
# dropped # dropped
@ -84,8 +86,8 @@ class TestDateTimeField(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertNotEqual(log.date, d1) assert log.date != d1
self.assertEqual(log.date, d2) assert log.date == d2
# Post UTC - microseconds are rounded (down) nearest millisecond # Post UTC - microseconds are rounded (down) nearest millisecond
d1 = dt.datetime(1970, 1, 1, 0, 0, 1, 9999) d1 = dt.datetime(1970, 1, 1, 0, 0, 1, 9999)
@ -93,8 +95,8 @@ class TestDateTimeField(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertNotEqual(log.date, d1) assert log.date != d1
self.assertEqual(log.date, d2) assert log.date == d2
if not six.PY3: if not six.PY3:
# Pre UTC dates microseconds below 1000 are dropped # Pre UTC dates microseconds below 1000 are dropped
@ -104,8 +106,8 @@ class TestDateTimeField(MongoDBTestCase):
log.date = d1 log.date = d1
log.save() log.save()
log.reload() log.reload()
self.assertNotEqual(log.date, d1) assert log.date != d1
self.assertEqual(log.date, d2) assert log.date == d2
def test_regular_usage(self): def test_regular_usage(self):
"""Tests for regular datetime fields""" """Tests for regular datetime fields"""
@ -123,43 +125,43 @@ class TestDateTimeField(MongoDBTestCase):
for query in (d1, d1.isoformat(" ")): for query in (d1, d1.isoformat(" ")):
log1 = LogEntry.objects.get(date=query) log1 = LogEntry.objects.get(date=query)
self.assertEqual(log, log1) assert log == log1
if dateutil: if dateutil:
log1 = LogEntry.objects.get(date=d1.isoformat("T")) 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 # create additional 19 log entries for a total of 20
for i in range(1971, 1990): for i in range(1971, 1990):
d = dt.datetime(i, 1, 1, 0, 0, 1) d = dt.datetime(i, 1, 1, 0, 0, 1)
LogEntry(date=d).save() LogEntry(date=d).save()
self.assertEqual(LogEntry.objects.count(), 20) assert LogEntry.objects.count() == 20
# Test ordering # Test ordering
logs = LogEntry.objects.order_by("date") logs = LogEntry.objects.order_by("date")
i = 0 i = 0
while i < 19: while i < 19:
self.assertTrue(logs[i].date <= logs[i + 1].date) assert logs[i].date <= logs[i + 1].date
i += 1 i += 1
logs = LogEntry.objects.order_by("-date") logs = LogEntry.objects.order_by("-date")
i = 0 i = 0
while i < 19: while i < 19:
self.assertTrue(logs[i].date >= logs[i + 1].date) assert logs[i].date >= logs[i + 1].date
i += 1 i += 1
# Test searching # Test searching
logs = LogEntry.objects.filter(date__gte=dt.datetime(1980, 1, 1)) 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)) logs = LogEntry.objects.filter(date__lte=dt.datetime(1980, 1, 1))
self.assertEqual(logs.count(), 10) assert logs.count() == 10
logs = LogEntry.objects.filter( logs = LogEntry.objects.filter(
date__lte=dt.datetime(1980, 1, 1), date__gte=dt.datetime(1975, 1, 1) 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): def test_datetime_validation(self):
"""Ensure that invalid values cannot be assigned to datetime """Ensure that invalid values cannot be assigned to datetime
@ -187,15 +189,20 @@ class TestDateTimeField(MongoDBTestCase):
log.validate() log.validate()
log.time = -1 log.time = -1
self.assertRaises(ValidationError, log.validate) with pytest.raises(ValidationError):
log.validate()
log.time = "ABC" log.time = "ABC"
self.assertRaises(ValidationError, log.validate) with pytest.raises(ValidationError):
log.validate()
log.time = "2019-05-16 21:GARBAGE:12" 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" 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" 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): def test_parse_datetime_as_str(self):
class DTDoc(Document): class DTDoc(Document):
@ -206,15 +213,16 @@ class TestDateTimeField(MongoDBTestCase):
# make sure that passing a parsable datetime works # make sure that passing a parsable datetime works
dtd = DTDoc() dtd = DTDoc()
dtd.date = date_str dtd.date = date_str
self.assertIsInstance(dtd.date, six.string_types) assert isinstance(dtd.date, six.string_types)
dtd.save() dtd.save()
dtd.reload() dtd.reload()
self.assertIsInstance(dtd.date, dt.datetime) assert isinstance(dtd.date, dt.datetime)
self.assertEqual(str(dtd.date), date_str) assert str(dtd.date) == date_str
dtd.date = "January 1st, 9999999999" dtd.date = "January 1st, 9999999999"
self.assertRaises(ValidationError, dtd.validate) with pytest.raises(ValidationError):
dtd.validate()
class TestDateTimeTzAware(MongoDBTestCase): class TestDateTimeTzAware(MongoDBTestCase):
@ -235,4 +243,4 @@ class TestDateTimeTzAware(MongoDBTestCase):
log = LogEntry.objects.first() log = LogEntry.objects.first()
log.time = dt.datetime(2013, 1, 1, 0, 0, 0) log.time = dt.datetime(2013, 1, 1, 0, 0, 0)
self.assertEqual(["time"], log._changed_fields) assert ["time"] == log._changed_fields

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from decimal import Decimal from decimal import Decimal
from mongoengine import * import pytest
from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -18,21 +19,26 @@ class TestDecimalField(MongoDBTestCase):
Person(height=Decimal("1.89")).save() Person(height=Decimal("1.89")).save()
person = Person.objects.first() person = Person.objects.first()
self.assertEqual(person.height, Decimal("1.89")) assert person.height == Decimal("1.89")
person.height = "2.0" person.height = "2.0"
person.save() person.save()
person.height = 0.01 person.height = 0.01
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.height = Decimal("0.01") person.height = Decimal("0.01")
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.height = Decimal("4.0") person.height = Decimal("4.0")
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.height = "something invalid" person.height = "something invalid"
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person_2 = Person(height="something invalid") person_2 = Person(height="something invalid")
self.assertRaises(ValidationError, person_2.validate) with pytest.raises(ValidationError):
person_2.validate()
def test_comparison(self): def test_comparison(self):
class Person(Document): class Person(Document):
@ -45,11 +51,11 @@ class TestDecimalField(MongoDBTestCase):
Person(money=8).save() Person(money=8).save()
Person(money=10).save() Person(money=10).save()
self.assertEqual(2, Person.objects(money__gt=Decimal("7")).count()) assert 2 == Person.objects(money__gt=Decimal("7")).count()
self.assertEqual(2, Person.objects(money__gt=7).count()) assert 2 == Person.objects(money__gt=7).count()
self.assertEqual(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): def test_storage(self):
class Person(Document): class Person(Document):
@ -87,7 +93,7 @@ class TestDecimalField(MongoDBTestCase):
] ]
expected.extend(expected) expected.extend(expected)
actual = list(Person.objects.exclude("id").as_pymongo()) actual = list(Person.objects.exclude("id").as_pymongo())
self.assertEqual(expected, actual) assert expected == actual
# How it comes out locally # How it comes out locally
expected = [ expected = [
@ -101,4 +107,4 @@ class TestDecimalField(MongoDBTestCase):
expected.extend(expected) expected.extend(expected)
for field_name in ["float_value", "string_value"]: for field_name in ["float_value", "string_value"]:
actual = list(Person.objects().scalar(field_name)) actual = list(Person.objects().scalar(field_name))
self.assertEqual(expected, actual) assert expected == actual

View File

@ -1,6 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.base import BaseDict from mongoengine.base import BaseDict
from mongoengine.mongodb_support import MONGODB_36, get_mongodb_version
from tests.utils import MongoDBTestCase, get_as_pymongo from tests.utils import MongoDBTestCase, get_as_pymongo
@ -14,7 +17,7 @@ class TestDictField(MongoDBTestCase):
info = {"testkey": "testvalue"} info = {"testkey": "testvalue"}
post = BlogPost(info=info).save() 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): def test_general_things(self):
"""Ensure that dict types work as expected.""" """Ensure that dict types work as expected."""
@ -26,25 +29,42 @@ class TestDictField(MongoDBTestCase):
post = BlogPost() post = BlogPost()
post.info = "my post" post.info = "my post"
self.assertRaises(ValidationError, post.validate) with pytest.raises(ValidationError):
post.validate()
post.info = ["test", "test"] post.info = ["test", "test"]
self.assertRaises(ValidationError, post.validate) with pytest.raises(ValidationError):
post.validate()
post.info = {"$title": "test"} post.info = {"$title": "test"}
self.assertRaises(ValidationError, post.validate) with pytest.raises(ValidationError):
post.validate()
post.info = {"nested": {"$title": "test"}} post.info = {"nested": {"$title": "test"}}
self.assertRaises(ValidationError, post.validate) with pytest.raises(ValidationError):
post.validate()
post.info = {"the.title": "test"} post.info = {"$title.test": "test"}
self.assertRaises(ValidationError, post.validate) with pytest.raises(ValidationError):
post.validate()
post.info = {"nested": {"the.title": "test"}}
self.assertRaises(ValidationError, post.validate)
post.info = {1: "test"} 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.info = {"title": "test"}
post.save() post.save()
@ -61,33 +81,27 @@ class TestDictField(MongoDBTestCase):
post.info = {"details": {"test": 3}} post.info = {"details": {"test": 3}}
post.save() post.save()
self.assertEqual(BlogPost.objects.count(), 4) assert BlogPost.objects.count() == 4
self.assertEqual(BlogPost.objects.filter(info__title__exact="test").count(), 1) assert BlogPost.objects.filter(info__title__exact="test").count() == 1
self.assertEqual( assert BlogPost.objects.filter(info__details__test__exact="test").count() == 1
BlogPost.objects.filter(info__details__test__exact="test").count(), 1
)
post = BlogPost.objects.filter(info__title__exact="dollar_sign").first() 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 # Confirm handles non strings or non existing keys
self.assertEqual( assert BlogPost.objects.filter(info__details__test__exact=5).count() == 0
BlogPost.objects.filter(info__details__test__exact=5).count(), 0 assert BlogPost.objects.filter(info__made_up__test__exact="test").count() == 0
)
self.assertEqual(
BlogPost.objects.filter(info__made_up__test__exact="test").count(), 0
)
post = BlogPost.objects.create(info={"title": "original"}) post = BlogPost.objects.create(info={"title": "original"})
post.info.update({"title": "updated"}) post.info.update({"title": "updated"})
post.save() post.save()
post.reload() post.reload()
self.assertEqual("updated", post.info["title"]) assert "updated" == post.info["title"]
post.info.setdefault("authors", []) post.info.setdefault("authors", [])
post.save() post.save()
post.reload() post.reload()
self.assertEqual([], post.info["authors"]) assert [] == post.info["authors"]
def test_dictfield_dump_document(self): def test_dictfield_dump_document(self):
"""Ensure a DictField can handle another document's dump.""" """Ensure a DictField can handle another document's dump."""
@ -114,10 +128,8 @@ class TestDictField(MongoDBTestCase):
).save() ).save()
doc = Doc(field=to_embed.to_mongo().to_dict()) doc = Doc(field=to_embed.to_mongo().to_dict())
doc.save() doc.save()
self.assertIsInstance(doc.field, dict) assert isinstance(doc.field, dict)
self.assertEqual( assert doc.field == {"_id": 2, "recursive": {"_id": 1, "recursive": {}}}
doc.field, {"_id": 2, "recursive": {"_id": 1, "recursive": {}}}
)
# Same thing with a Document with a _cls field # Same thing with a Document with a _cls field
to_embed_recursive = ToEmbedChild(id=1).save() to_embed_recursive = ToEmbedChild(id=1).save()
to_embed_child = ToEmbedChild( to_embed_child = ToEmbedChild(
@ -125,7 +137,7 @@ class TestDictField(MongoDBTestCase):
).save() ).save()
doc = Doc(field=to_embed_child.to_mongo().to_dict()) doc = Doc(field=to_embed_child.to_mongo().to_dict())
doc.save() doc.save()
self.assertIsInstance(doc.field, dict) assert isinstance(doc.field, dict)
expected = { expected = {
"_id": 2, "_id": 2,
"_cls": "ToEmbedParent.ToEmbedChild", "_cls": "ToEmbedParent.ToEmbedChild",
@ -135,7 +147,7 @@ class TestDictField(MongoDBTestCase):
"recursive": {}, "recursive": {},
}, },
} }
self.assertEqual(doc.field, expected) assert doc.field == expected
def test_dictfield_strict(self): def test_dictfield_strict(self):
"""Ensure that dict field handles validation if provided a strict field type.""" """Ensure that dict field handles validation if provided a strict field type."""
@ -150,7 +162,7 @@ class TestDictField(MongoDBTestCase):
e.save() e.save()
# try creating an invalid mapping # try creating an invalid mapping
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
e.mapping["somestring"] = "abc" e.mapping["somestring"] = "abc"
e.save() e.save()
@ -184,22 +196,21 @@ class TestDictField(MongoDBTestCase):
e.save() e.save()
e2 = Simple.objects.get(id=e.id) e2 = Simple.objects.get(id=e.id)
self.assertIsInstance(e2.mapping["somestring"], StringSetting) assert isinstance(e2.mapping["somestring"], StringSetting)
self.assertIsInstance(e2.mapping["someint"], IntegerSetting) assert isinstance(e2.mapping["someint"], IntegerSetting)
# Test querying # Test querying
self.assertEqual(Simple.objects.filter(mapping__someint__value=42).count(), 1) assert Simple.objects.filter(mapping__someint__value=42).count() == 1
self.assertEqual( assert Simple.objects.filter(mapping__nested_dict__number=1).count() == 1
Simple.objects.filter(mapping__nested_dict__number=1).count(), 1 assert (
Simple.objects.filter(mapping__nested_dict__complex__value=42).count() == 1
) )
self.assertEqual( assert (
Simple.objects.filter(mapping__nested_dict__complex__value=42).count(), 1 Simple.objects.filter(mapping__nested_dict__list__0__value=42).count() == 1
) )
self.assertEqual( assert (
Simple.objects.filter(mapping__nested_dict__list__0__value=42).count(), 1 Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count()
) == 1
self.assertEqual(
Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count(), 1
) )
# Confirm can update # Confirm can update
@ -207,11 +218,13 @@ class TestDictField(MongoDBTestCase):
Simple.objects().update( Simple.objects().update(
set__mapping__nested_dict__list__1=StringSetting(value="Boo") set__mapping__nested_dict__list__1=StringSetting(value="Boo")
) )
self.assertEqual( assert (
Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count(), 0 Simple.objects.filter(mapping__nested_dict__list__1__value="foo").count()
== 0
) )
self.assertEqual( assert (
Simple.objects.filter(mapping__nested_dict__list__1__value="Boo").count(), 1 Simple.objects.filter(mapping__nested_dict__list__1__value="Boo").count()
== 1
) )
def test_push_dict(self): def test_push_dict(self):
@ -221,12 +234,12 @@ class TestDictField(MongoDBTestCase):
doc = MyModel(events=[{"a": 1}]).save() doc = MyModel(events=[{"a": 1}]).save()
raw_doc = get_as_pymongo(doc) raw_doc = get_as_pymongo(doc)
expected_raw_doc = {"_id": doc.id, "events": [{"a": 1}]} 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={}) MyModel.objects(id=doc.id).update(push__events={})
raw_doc = get_as_pymongo(doc) raw_doc = get_as_pymongo(doc)
expected_raw_doc = {"_id": doc.id, "events": [{"a": 1}, {}]} 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): def test_ensure_unique_default_instances(self):
"""Ensure that every field has it's own unique default instance.""" """Ensure that every field has it's own unique default instance."""
@ -239,8 +252,8 @@ class TestDictField(MongoDBTestCase):
d1.data["foo"] = "bar" d1.data["foo"] = "bar"
d1.data2["foo"] = "bar" d1.data2["foo"] = "bar"
d2 = D() d2 = D()
self.assertEqual(d2.data, {}) assert d2.data == {}
self.assertEqual(d2.data2, {}) assert d2.data2 == {}
def test_dict_field_invalid_dict_value(self): def test_dict_field_invalid_dict_value(self):
class DictFieldTest(Document): class DictFieldTest(Document):
@ -250,11 +263,13 @@ class TestDictField(MongoDBTestCase):
test = DictFieldTest(dictionary=None) test = DictFieldTest(dictionary=None)
test.dictionary # Just access to test getter test.dictionary # Just access to test getter
self.assertRaises(ValidationError, test.validate) with pytest.raises(ValidationError):
test.validate()
test = DictFieldTest(dictionary=False) test = DictFieldTest(dictionary=False)
test.dictionary # Just access to test getter 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): def test_dict_field_raises_validation_error_if_wrongly_assign_embedded_doc(self):
class DictFieldTest(Document): class DictFieldTest(Document):
@ -267,12 +282,12 @@ class TestDictField(MongoDBTestCase):
embed = Embedded(name="garbage") embed = Embedded(name="garbage")
doc = DictFieldTest(dictionary=embed) doc = DictFieldTest(dictionary=embed)
with self.assertRaises(ValidationError) as ctx_err: with pytest.raises(ValidationError) as exc_info:
doc.validate() doc.validate()
self.assertIn("'dictionary'", str(ctx_err.exception))
self.assertIn( error_msg = str(exc_info.value)
"Only dictionaries may be used in a DictField", str(ctx_err.exception) assert "'dictionary'" in error_msg
) assert "Only dictionaries may be used in a DictField" in error_msg
def test_atomic_update_dict_field(self): def test_atomic_update_dict_field(self):
"""Ensure that the entire DictField can be atomically updated.""" """Ensure that the entire DictField can be atomically updated."""
@ -287,11 +302,11 @@ class TestDictField(MongoDBTestCase):
e.save() e.save()
e.update(set__mapping={"ints": [3, 4]}) e.update(set__mapping={"ints": [3, 4]})
e.reload() e.reload()
self.assertEqual(BaseDict, type(e.mapping)) assert isinstance(e.mapping, BaseDict)
self.assertEqual({"ints": [3, 4]}, e.mapping) assert {"ints": [3, 4]} == e.mapping
# try creating an invalid mapping # try creating an invalid mapping
with self.assertRaises(ValueError): with pytest.raises(ValueError):
e.update(set__mapping={"somestrings": ["foo", "bar"]}) e.update(set__mapping={"somestrings": ["foo", "bar"]})
def test_dictfield_with_referencefield_complex_nesting_cases(self): def test_dictfield_with_referencefield_complex_nesting_cases(self):
@ -329,13 +344,13 @@ class TestDictField(MongoDBTestCase):
e.save() e.save()
s = Simple.objects.first() s = Simple.objects.first()
self.assertIsInstance(s.mapping0["someint"], Doc) assert isinstance(s.mapping0["someint"], Doc)
self.assertIsInstance(s.mapping1["someint"], Doc) assert isinstance(s.mapping1["someint"], Doc)
self.assertIsInstance(s.mapping2["someint"][0], Doc) assert isinstance(s.mapping2["someint"][0], Doc)
self.assertIsInstance(s.mapping3["someint"][0], Doc) assert isinstance(s.mapping3["someint"][0], Doc)
self.assertIsInstance(s.mapping4["someint"]["d"], Doc) assert isinstance(s.mapping4["someint"]["d"], Doc)
self.assertIsInstance(s.mapping5["someint"]["d"], Doc) assert isinstance(s.mapping5["someint"]["d"], Doc)
self.assertIsInstance(s.mapping6["someint"][0]["d"], Doc) assert isinstance(s.mapping6["someint"][0]["d"], Doc)
self.assertIsInstance(s.mapping7["someint"][0]["d"], Doc) assert isinstance(s.mapping7["someint"][0]["d"], Doc)
self.assertIsInstance(s.mapping8["someint"][0]["d"][0], Doc) assert isinstance(s.mapping8["someint"][0]["d"][0], Doc)
self.assertIsInstance(s.mapping9["someint"][0]["d"][0], Doc) assert isinstance(s.mapping9["someint"][0]["d"][0], Doc)

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys import sys
from unittest import SkipTest
import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -27,7 +27,8 @@ class TestEmailField(MongoDBTestCase):
user.validate() user.validate()
user = User(email="ross@example.com.") user = User(email="ross@example.com.")
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
# unicode domain # unicode domain
user = User(email=u"user@пример.рф") user = User(email=u"user@пример.рф")
@ -35,24 +36,22 @@ class TestEmailField(MongoDBTestCase):
# invalid unicode domain # invalid unicode domain
user = User(email=u"user@пример") user = User(email=u"user@пример")
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
# invalid data type # invalid data type
user = User(email=123) user = User(email=123)
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
def test_email_field_unicode_user(self): 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): class User(Document):
email = EmailField() email = EmailField()
# unicode user shouldn't validate by default... # unicode user shouldn't validate by default...
user = User(email=u"Dörte@Sörensen.example.com") 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 # ...but it should be fine with allow_utf8_user set to True
class User(Document): class User(Document):
@ -67,7 +66,8 @@ class TestEmailField(MongoDBTestCase):
# localhost domain shouldn't validate by default... # localhost domain shouldn't validate by default...
user = User(email="me@localhost") 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 # ...but it should be fine if it's whitelisted
class User(Document): class User(Document):
@ -82,9 +82,10 @@ class TestEmailField(MongoDBTestCase):
invalid_idn = ".google.com" invalid_idn = ".google.com"
user = User(email="me@%s" % invalid_idn) user = User(email="me@%s" % invalid_idn)
with self.assertRaises(ValidationError) as ctx_err:
with pytest.raises(ValidationError) as exc_info:
user.validate() 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): def test_email_field_ip_domain(self):
class User(Document): class User(Document):
@ -96,13 +97,16 @@ class TestEmailField(MongoDBTestCase):
# IP address as a domain shouldn't validate by default... # IP address as a domain shouldn't validate by default...
user = User(email=valid_ipv4) user = User(email=valid_ipv4)
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
user = User(email=valid_ipv6) user = User(email=valid_ipv6)
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
user = User(email=invalid_ip) 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 # ...but it should be fine with allow_ip_domain set to True
class User(Document): class User(Document):
@ -116,7 +120,8 @@ class TestEmailField(MongoDBTestCase):
# invalid IP should still fail validation # invalid IP should still fail validation
user = User(email=invalid_ip) user = User(email=invalid_ip)
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
def test_email_field_honors_regex(self): def test_email_field_honors_regex(self):
class User(Document): class User(Document):
@ -124,8 +129,9 @@ class TestEmailField(MongoDBTestCase):
# Fails regex validation # Fails regex validation
user = User(email="me@foo.com") user = User(email="me@foo.com")
self.assertRaises(ValidationError, user.validate) with pytest.raises(ValidationError):
user.validate()
# Passes regex validation # Passes regex validation
user = User(email="me@example.com") user = User(email="me@example.com")
self.assertIsNone(user.validate()) assert user.validate() is None

View File

@ -1,17 +1,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
from mongoengine import ( from mongoengine import (
Document, Document,
StringField,
ValidationError,
EmbeddedDocument, EmbeddedDocument,
EmbeddedDocumentField, EmbeddedDocumentField,
InvalidQueryError,
LookUpError,
IntField,
GenericEmbeddedDocumentField, GenericEmbeddedDocumentField,
IntField,
InvalidQueryError,
ListField, ListField,
EmbeddedDocumentListField, LookUpError,
ReferenceField, StringField,
ValidationError,
) )
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -23,13 +23,13 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
name = StringField() name = StringField()
field = EmbeddedDocumentField(MyDoc) field = EmbeddedDocumentField(MyDoc)
self.assertEqual(field.document_type_obj, MyDoc) assert field.document_type_obj == MyDoc
field2 = EmbeddedDocumentField("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): def test___init___throw_error_if_document_type_is_not_EmbeddedDocument(self):
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
EmbeddedDocumentField(dict) EmbeddedDocumentField(dict)
def test_document_type_throw_error_if_not_EmbeddedDocument_subclass(self): def test_document_type_throw_error_if_not_EmbeddedDocument_subclass(self):
@ -37,11 +37,11 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
name = StringField() name = StringField()
emb = EmbeddedDocumentField("MyDoc") emb = EmbeddedDocumentField("MyDoc")
with self.assertRaises(ValidationError) as ctx: with pytest.raises(ValidationError) as exc_info:
emb.document_type emb.document_type
self.assertIn( assert (
"Invalid embedded document class provided to an EmbeddedDocumentField", "Invalid embedded document class provided to an EmbeddedDocumentField"
str(ctx.exception), in str(exc_info.value)
) )
def test_embedded_document_field_only_allow_subclasses_of_embedded_document(self): def test_embedded_document_field_only_allow_subclasses_of_embedded_document(self):
@ -49,12 +49,12 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
class MyDoc(Document): class MyDoc(Document):
name = StringField() name = StringField()
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
class MyFailingDoc(Document): class MyFailingDoc(Document):
emb = EmbeddedDocumentField(MyDoc) emb = EmbeddedDocumentField(MyDoc)
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
class MyFailingdoc2(Document): class MyFailingdoc2(Document):
emb = EmbeddedDocumentField("MyDoc") emb = EmbeddedDocumentField("MyDoc")
@ -73,24 +73,24 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
p = Person(settings=AdminSettings(foo1="bar1", foo2="bar2"), name="John").save() p = Person(settings=AdminSettings(foo1="bar1", foo2="bar2"), name="John").save()
# Test non exiting attribute # Test non exiting attribute
with self.assertRaises(InvalidQueryError) as ctx_err: with pytest.raises(InvalidQueryError) as exc_info:
Person.objects(settings__notexist="bar").first() 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") Person.objects.only("settings.notexist")
# Test existing attribute # 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() only_p = Person.objects.only("settings.foo1").first()
self.assertEqual(only_p.settings.foo1, p.settings.foo1) assert only_p.settings.foo1 == p.settings.foo1
self.assertIsNone(only_p.settings.foo2) assert only_p.settings.foo2 is None
self.assertIsNone(only_p.name) assert only_p.name is None
exclude_p = Person.objects.exclude("settings.foo1").first() exclude_p = Person.objects.exclude("settings.foo1").first()
self.assertIsNone(exclude_p.settings.foo1) assert exclude_p.settings.foo1 is None
self.assertEqual(exclude_p.settings.foo2, p.settings.foo2) assert exclude_p.settings.foo2 == p.settings.foo2
self.assertEqual(exclude_p.name, p.name) assert exclude_p.name == p.name
def test_query_embedded_document_attribute_with_inheritance(self): def test_query_embedded_document_attribute_with_inheritance(self):
class BaseSettings(EmbeddedDocument): class BaseSettings(EmbeddedDocument):
@ -109,17 +109,17 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
p.save() p.save()
# Test non exiting attribute # Test non exiting attribute
with self.assertRaises(InvalidQueryError) as ctx_err: with pytest.raises(InvalidQueryError) as exc_info:
self.assertEqual(Person.objects(settings__notexist="bar").first().id, p.id) assert Person.objects(settings__notexist="bar").first().id == p.id
self.assertEqual(unicode(ctx_err.exception), u'Cannot resolve field "notexist"') assert unicode(exc_info.value) == u'Cannot resolve field "notexist"'
# Test existing attribute # Test existing attribute
self.assertEqual(Person.objects(settings__base_foo="basefoo").first().id, p.id) assert 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__sub_foo="subfoo").first().id == p.id
only_p = Person.objects.only("settings.base_foo", "settings._cls").first() only_p = Person.objects.only("settings.base_foo", "settings._cls").first()
self.assertEqual(only_p.settings.base_foo, "basefoo") assert only_p.settings.base_foo == "basefoo"
self.assertIsNone(only_p.settings.sub_foo) assert only_p.settings.sub_foo is None
def test_query_list_embedded_document_with_inheritance(self): def test_query_list_embedded_document_with_inheritance(self):
class Post(EmbeddedDocument): class Post(EmbeddedDocument):
@ -139,14 +139,14 @@ class TestEmbeddedDocumentField(MongoDBTestCase):
record_text = Record(posts=[TextPost(content="a", title="foo")]).save() record_text = Record(posts=[TextPost(content="a", title="foo")]).save()
records = list(Record.objects(posts__author=record_movie.posts[0].author)) records = list(Record.objects(posts__author=record_movie.posts[0].author))
self.assertEqual(len(records), 1) assert len(records) == 1
self.assertEqual(records[0].id, record_movie.id) assert records[0].id == record_movie.id
records = list(Record.objects(posts__content=record_text.posts[0].content)) records = list(Record.objects(posts__content=record_text.posts[0].content))
self.assertEqual(len(records), 1) assert len(records) == 1
self.assertEqual(records[0].id, record_text.id) 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): class TestGenericEmbeddedDocumentField(MongoDBTestCase):
@ -169,13 +169,13 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
person.save() person.save()
person = Person.objects.first() person = Person.objects.first()
self.assertIsInstance(person.like, Car) assert isinstance(person.like, Car)
person.like = Dish(food="arroz", number=15) person.like = Dish(food="arroz", number=15)
person.save() person.save()
person = Person.objects.first() person = Person.objects.first()
self.assertIsInstance(person.like, Dish) assert isinstance(person.like, Dish)
def test_generic_embedded_document_choices(self): def test_generic_embedded_document_choices(self):
"""Ensure you can limit GenericEmbeddedDocument choices.""" """Ensure you can limit GenericEmbeddedDocument choices."""
@ -195,13 +195,14 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
person = Person(name="Test User") person = Person(name="Test User")
person.like = Car(name="Fiat") person.like = Car(name="Fiat")
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.like = Dish(food="arroz", number=15) person.like = Dish(food="arroz", number=15)
person.save() person.save()
person = Person.objects.first() person = Person.objects.first()
self.assertIsInstance(person.like, Dish) assert isinstance(person.like, Dish)
def test_generic_list_embedded_document_choices(self): def test_generic_list_embedded_document_choices(self):
"""Ensure you can limit GenericEmbeddedDocument choices inside """Ensure you can limit GenericEmbeddedDocument choices inside
@ -223,13 +224,14 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
person = Person(name="Test User") person = Person(name="Test User")
person.likes = [Car(name="Fiat")] person.likes = [Car(name="Fiat")]
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.likes = [Dish(food="arroz", number=15)] person.likes = [Dish(food="arroz", number=15)]
person.save() person.save()
person = Person.objects.first() person = Person.objects.first()
self.assertIsInstance(person.likes[0], Dish) assert isinstance(person.likes[0], Dish)
def test_choices_validation_documents(self): def test_choices_validation_documents(self):
""" """
@ -265,7 +267,8 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
# Single Entry Failure # Single Entry Failure
post = BlogPost(comments=[ModeratorComments(author="mod1", message="message1")]) post = BlogPost(comments=[ModeratorComments(author="mod1", message="message1")])
self.assertRaises(ValidationError, post.save) with pytest.raises(ValidationError):
post.save()
# Mixed Entry Failure # Mixed Entry Failure
post = BlogPost( post = BlogPost(
@ -274,7 +277,8 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
UserComments(author="user2", message="message2"), UserComments(author="user2", message="message2"),
] ]
) )
self.assertRaises(ValidationError, post.save) with pytest.raises(ValidationError):
post.save()
def test_choices_validation_documents_inheritance(self): def test_choices_validation_documents_inheritance(self):
""" """
@ -313,16 +317,16 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
p2 = Person(settings=NonAdminSettings(foo2="bar2")).save() p2 = Person(settings=NonAdminSettings(foo2="bar2")).save()
# Test non exiting attribute # Test non exiting attribute
with self.assertRaises(InvalidQueryError) as ctx_err: with pytest.raises(InvalidQueryError) as exc_info:
Person.objects(settings__notexist="bar").first() 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") Person.objects.only("settings.notexist")
# Test existing attribute # Test existing attribute
self.assertEqual(Person.objects(settings__foo1="bar1").first().id, p1.id) assert Person.objects(settings__foo1="bar1").first().id == p1.id
self.assertEqual(Person.objects(settings__foo2="bar2").first().id, p2.id) assert Person.objects(settings__foo2="bar2").first().id == p2.id
def test_query_generic_embedded_document_attribute_with_inheritance(self): def test_query_generic_embedded_document_attribute_with_inheritance(self):
class BaseSettings(EmbeddedDocument): class BaseSettings(EmbeddedDocument):
@ -341,10 +345,10 @@ class TestGenericEmbeddedDocumentField(MongoDBTestCase):
p.save() p.save()
# Test non exiting attribute # Test non exiting attribute
with self.assertRaises(InvalidQueryError) as ctx_err: with pytest.raises(InvalidQueryError) as exc_info:
self.assertEqual(Person.objects(settings__notexist="bar").first().id, p.id) assert Person.objects(settings__notexist="bar").first().id == p.id
self.assertEqual(unicode(ctx_err.exception), u'Cannot resolve field "notexist"') assert unicode(exc_info.value) == u'Cannot resolve field "notexist"'
# Test existing attribute # Test existing attribute
self.assertEqual(Person.objects(settings__base_foo="basefoo").first().id, p.id) assert 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__sub_foo="subfoo").first().id == p.id

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ import tempfile
import unittest import unittest
import gridfs import gridfs
from nose.plugins.skip import SkipTest import pytest
import six import six
from mongoengine import * from mongoengine import *
@ -21,6 +21,8 @@ except ImportError:
from tests.utils import MongoDBTestCase 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_IMAGE_PATH = os.path.join(os.path.dirname(__file__), "mongoengine.png")
TEST_IMAGE2_PATH = os.path.join(os.path.dirname(__file__), "mongodb_leaf.png") TEST_IMAGE2_PATH = os.path.join(os.path.dirname(__file__), "mongodb_leaf.png")
@ -64,13 +66,13 @@ class TestFileField(MongoDBTestCase):
putfile.save() putfile.save()
result = PutFile.objects.first() result = PutFile.objects.first()
self.assertEqual(putfile, result) assert putfile == result
self.assertEqual( assert (
"%s" % result.the_file, "%s" % result.the_file
"<GridFSProxy: hello (%s)>" % result.the_file.grid_id, == "<GridFSProxy: hello (%s)>" % result.the_file.grid_id
) )
self.assertEqual(result.the_file.read(), text) assert result.the_file.read() == text
self.assertEqual(result.the_file.content_type, content_type) assert result.the_file.content_type == content_type
result.the_file.delete() # Remove file from GridFS result.the_file.delete() # Remove file from GridFS
PutFile.objects.delete() PutFile.objects.delete()
@ -85,9 +87,9 @@ class TestFileField(MongoDBTestCase):
putfile.save() putfile.save()
result = PutFile.objects.first() result = PutFile.objects.first()
self.assertEqual(putfile, result) assert putfile == result
self.assertEqual(result.the_file.read(), text) assert result.the_file.read() == text
self.assertEqual(result.the_file.content_type, content_type) assert result.the_file.content_type == content_type
result.the_file.delete() result.the_file.delete()
def test_file_fields_stream(self): def test_file_fields_stream(self):
@ -111,19 +113,19 @@ class TestFileField(MongoDBTestCase):
streamfile.save() streamfile.save()
result = StreamFile.objects.first() result = StreamFile.objects.first()
self.assertEqual(streamfile, result) assert streamfile == result
self.assertEqual(result.the_file.read(), text + more_text) assert result.the_file.read() == text + more_text
self.assertEqual(result.the_file.content_type, content_type) assert result.the_file.content_type == content_type
result.the_file.seek(0) result.the_file.seek(0)
self.assertEqual(result.the_file.tell(), 0) assert result.the_file.tell() == 0
self.assertEqual(result.the_file.read(len(text)), text) assert result.the_file.read(len(text)) == text
self.assertEqual(result.the_file.tell(), len(text)) assert result.the_file.tell() == len(text)
self.assertEqual(result.the_file.read(len(more_text)), more_text) assert result.the_file.read(len(more_text)) == more_text
self.assertEqual(result.the_file.tell(), len(text + more_text)) assert result.the_file.tell() == len(text + more_text)
result.the_file.delete() result.the_file.delete()
# Ensure deleted file returns None # 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): def test_file_fields_stream_after_none(self):
"""Ensure that a file field can be written to after it has been saved as """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!") text = six.b("Hello, World!")
more_text = six.b("Foo Bar") more_text = six.b("Foo Bar")
content_type = "text/plain"
streamfile = StreamFile() streamfile = StreamFile()
streamfile.save() streamfile.save()
@ -148,19 +149,19 @@ class TestFileField(MongoDBTestCase):
streamfile.save() streamfile.save()
result = StreamFile.objects.first() result = StreamFile.objects.first()
self.assertEqual(streamfile, result) assert streamfile == result
self.assertEqual(result.the_file.read(), text + more_text) assert result.the_file.read() == text + more_text
# self.assertEqual(result.the_file.content_type, content_type) # assert result.the_file.content_type == content_type
result.the_file.seek(0) result.the_file.seek(0)
self.assertEqual(result.the_file.tell(), 0) assert result.the_file.tell() == 0
self.assertEqual(result.the_file.read(len(text)), text) assert result.the_file.read(len(text)) == text
self.assertEqual(result.the_file.tell(), len(text)) assert result.the_file.tell() == len(text)
self.assertEqual(result.the_file.read(len(more_text)), more_text) assert result.the_file.read(len(more_text)) == more_text
self.assertEqual(result.the_file.tell(), len(text + more_text)) assert result.the_file.tell() == len(text + more_text)
result.the_file.delete() result.the_file.delete()
# Ensure deleted file returns None # 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): def test_file_fields_set(self):
class SetFile(Document): class SetFile(Document):
@ -176,16 +177,16 @@ class TestFileField(MongoDBTestCase):
setfile.save() setfile.save()
result = SetFile.objects.first() result = SetFile.objects.first()
self.assertEqual(setfile, result) assert setfile == result
self.assertEqual(result.the_file.read(), text) assert result.the_file.read() == text
# Try replacing file with new one # Try replacing file with new one
result.the_file.replace(more_text) result.the_file.replace(more_text)
result.save() result.save()
result = SetFile.objects.first() result = SetFile.objects.first()
self.assertEqual(setfile, result) assert setfile == result
self.assertEqual(result.the_file.read(), more_text) assert result.the_file.read() == more_text
result.the_file.delete() result.the_file.delete()
def test_file_field_no_default(self): 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 = GridDocument.objects.with_id(doc_a.id)
doc_b.the_file.replace(f, filename="doc_b") doc_b.the_file.replace(f, filename="doc_b")
doc_b.save() 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 # Test it matches
doc_c = GridDocument.objects.with_id(doc_b.id) 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 # Test with default
doc_d = GridDocument(the_file=six.b("")) doc_d = GridDocument(the_file=six.b(""))
doc_d.save() doc_d.save()
doc_e = GridDocument.objects.with_id(doc_d.id) 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.the_file.replace(f, filename="doc_e")
doc_e.save() doc_e.save()
doc_f = GridDocument.objects.with_id(doc_e.id) 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() db = GridDocument._get_db()
grid_fs = gridfs.GridFS(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): def test_file_uniqueness(self):
"""Ensure that each instance of a FileField is unique """Ensure that each instance of a FileField is unique
@ -246,8 +247,8 @@ class TestFileField(MongoDBTestCase):
test_file_dupe = TestFile() test_file_dupe = TestFile()
data = test_file_dupe.the_file.read() # Should be None data = test_file_dupe.the_file.read() # Should be None
self.assertNotEqual(test_file.name, test_file_dupe.name) assert test_file.name != test_file_dupe.name
self.assertNotEqual(test_file.the_file.read(), data) assert test_file.the_file.read() != data
TestFile.drop_collection() TestFile.drop_collection()
@ -268,8 +269,8 @@ class TestFileField(MongoDBTestCase):
marmot.save() marmot.save()
marmot = Animal.objects.get() marmot = Animal.objects.get()
self.assertEqual(marmot.photo.content_type, "image/jpeg") assert marmot.photo.content_type == "image/jpeg"
self.assertEqual(marmot.photo.foo, "bar") assert marmot.photo.foo == "bar"
def test_file_reassigning(self): def test_file_reassigning(self):
class TestFile(Document): class TestFile(Document):
@ -278,12 +279,12 @@ class TestFileField(MongoDBTestCase):
TestFile.drop_collection() TestFile.drop_collection()
test_file = TestFile(the_file=get_file(TEST_IMAGE_PATH)).save() 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 = TestFile.objects.first()
test_file.the_file = get_file(TEST_IMAGE2_PATH) test_file.the_file = get_file(TEST_IMAGE2_PATH)
test_file.save() 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): def test_file_boolean(self):
"""Ensure that a boolean test of a FileField indicates its presence """Ensure that a boolean test of a FileField indicates its presence
@ -295,13 +296,13 @@ class TestFileField(MongoDBTestCase):
TestFile.drop_collection() TestFile.drop_collection()
test_file = TestFile() 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.the_file.put(six.b("Hello, World!"), content_type="text/plain")
test_file.save() test_file.save()
self.assertTrue(bool(test_file.the_file)) assert bool(test_file.the_file)
test_file = TestFile.objects.first() 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): def test_file_cmp(self):
"""Test comparing against other types""" """Test comparing against other types"""
@ -310,7 +311,7 @@ class TestFileField(MongoDBTestCase):
the_file = FileField() the_file = FileField()
test_file = TestFile() 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): def test_file_disk_space(self):
""" Test disk space usage when we delete/replace a file """ """ Test disk space usage when we delete/replace a file """
@ -330,16 +331,16 @@ class TestFileField(MongoDBTestCase):
files = db.fs.files.find() files = db.fs.files.find()
chunks = db.fs.chunks.find() chunks = db.fs.chunks.find()
self.assertEqual(len(list(files)), 1) assert len(list(files)) == 1
self.assertEqual(len(list(chunks)), 1) assert len(list(chunks)) == 1
# Deleting the docoument should delete the files # Deleting the docoument should delete the files
testfile.delete() testfile.delete()
files = db.fs.files.find() files = db.fs.files.find()
chunks = db.fs.chunks.find() chunks = db.fs.chunks.find()
self.assertEqual(len(list(files)), 0) assert len(list(files)) == 0
self.assertEqual(len(list(chunks)), 0) assert len(list(chunks)) == 0
# Test case where we don't store a file in the first place # Test case where we don't store a file in the first place
testfile = TestFile() testfile = TestFile()
@ -347,15 +348,15 @@ class TestFileField(MongoDBTestCase):
files = db.fs.files.find() files = db.fs.files.find()
chunks = db.fs.chunks.find() chunks = db.fs.chunks.find()
self.assertEqual(len(list(files)), 0) assert len(list(files)) == 0
self.assertEqual(len(list(chunks)), 0) assert len(list(chunks)) == 0
testfile.delete() testfile.delete()
files = db.fs.files.find() files = db.fs.files.find()
chunks = db.fs.chunks.find() chunks = db.fs.chunks.find()
self.assertEqual(len(list(files)), 0) assert len(list(files)) == 0
self.assertEqual(len(list(chunks)), 0) assert len(list(chunks)) == 0
# Test case where we overwrite the file # Test case where we overwrite the file
testfile = TestFile() testfile = TestFile()
@ -368,20 +369,18 @@ class TestFileField(MongoDBTestCase):
files = db.fs.files.find() files = db.fs.files.find()
chunks = db.fs.chunks.find() chunks = db.fs.chunks.find()
self.assertEqual(len(list(files)), 1) assert len(list(files)) == 1
self.assertEqual(len(list(chunks)), 1) assert len(list(chunks)) == 1
testfile.delete() testfile.delete()
files = db.fs.files.find() files = db.fs.files.find()
chunks = db.fs.chunks.find() chunks = db.fs.chunks.find()
self.assertEqual(len(list(files)), 0) assert len(list(files)) == 0
self.assertEqual(len(list(chunks)), 0) assert len(list(chunks)) == 0
@require_pil
def test_image_field(self): def test_image_field(self):
if not HAS_PIL:
raise SkipTest("PIL not installed")
class TestImage(Document): class TestImage(Document):
image = ImageField() image = ImageField()
@ -396,9 +395,7 @@ class TestFileField(MongoDBTestCase):
t.image.put(f) t.image.put(f)
self.fail("Should have raised an invalidation error") self.fail("Should have raised an invalidation error")
except ValidationError as e: except ValidationError as e:
self.assertEqual( assert "%s" % e == "Invalid image: cannot identify image file %s" % f
"%s" % e, "Invalid image: cannot identify image file %s" % f
)
t = TestImage() t = TestImage()
t.image.put(get_file(TEST_IMAGE_PATH)) t.image.put(get_file(TEST_IMAGE_PATH))
@ -406,35 +403,31 @@ class TestFileField(MongoDBTestCase):
t = TestImage.objects.first() t = TestImage.objects.first()
self.assertEqual(t.image.format, "PNG") assert t.image.format == "PNG"
w, h = t.image.size w, h = t.image.size
self.assertEqual(w, 371) assert w == 371
self.assertEqual(h, 76) assert h == 76
t.image.delete() t.image.delete()
@require_pil
def test_image_field_reassigning(self): def test_image_field_reassigning(self):
if not HAS_PIL:
raise SkipTest("PIL not installed")
class TestFile(Document): class TestFile(Document):
the_file = ImageField() the_file = ImageField()
TestFile.drop_collection() TestFile.drop_collection()
test_file = TestFile(the_file=get_file(TEST_IMAGE_PATH)).save() 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 = TestFile.objects.first()
test_file.the_file = get_file(TEST_IMAGE2_PATH) test_file.the_file = get_file(TEST_IMAGE2_PATH)
test_file.save() 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): def test_image_field_resize(self):
if not HAS_PIL:
raise SkipTest("PIL not installed")
class TestImage(Document): class TestImage(Document):
image = ImageField(size=(185, 37)) image = ImageField(size=(185, 37))
@ -446,18 +439,16 @@ class TestFileField(MongoDBTestCase):
t = TestImage.objects.first() t = TestImage.objects.first()
self.assertEqual(t.image.format, "PNG") assert t.image.format == "PNG"
w, h = t.image.size w, h = t.image.size
self.assertEqual(w, 185) assert w == 185
self.assertEqual(h, 37) assert h == 37
t.image.delete() t.image.delete()
@require_pil
def test_image_field_resize_force(self): def test_image_field_resize_force(self):
if not HAS_PIL:
raise SkipTest("PIL not installed")
class TestImage(Document): class TestImage(Document):
image = ImageField(size=(185, 37, True)) image = ImageField(size=(185, 37, True))
@ -469,18 +460,16 @@ class TestFileField(MongoDBTestCase):
t = TestImage.objects.first() t = TestImage.objects.first()
self.assertEqual(t.image.format, "PNG") assert t.image.format == "PNG"
w, h = t.image.size w, h = t.image.size
self.assertEqual(w, 185) assert w == 185
self.assertEqual(h, 37) assert h == 37
t.image.delete() t.image.delete()
@require_pil
def test_image_field_thumbnail(self): def test_image_field_thumbnail(self):
if not HAS_PIL:
raise SkipTest("PIL not installed")
class TestImage(Document): class TestImage(Document):
image = ImageField(thumbnail_size=(92, 18)) image = ImageField(thumbnail_size=(92, 18))
@ -492,9 +481,9 @@ class TestFileField(MongoDBTestCase):
t = TestImage.objects.first() t = TestImage.objects.first()
self.assertEqual(t.image.thumbnail.format, "PNG") assert t.image.thumbnail.format == "PNG"
self.assertEqual(t.image.thumbnail.width, 92) assert t.image.thumbnail.width == 92
self.assertEqual(t.image.thumbnail.height, 18) assert t.image.thumbnail.height == 18
t.image.delete() t.image.delete()
@ -518,17 +507,17 @@ class TestFileField(MongoDBTestCase):
test_file.save() test_file.save()
data = get_db("test_files").macumba.files.find_one() 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() 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 = TestFile.objects.first()
test_file.the_file = six.b("HELLO, WORLD!") test_file.the_file = six.b("HELLO, WORLD!")
test_file.save() test_file.save()
test_file = TestFile.objects.first() 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): def test_copyable(self):
class PutFile(Document): class PutFile(Document):
@ -546,14 +535,11 @@ class TestFileField(MongoDBTestCase):
class TestFile(Document): class TestFile(Document):
name = StringField() name = StringField()
self.assertEqual(putfile, copy.copy(putfile)) assert putfile == copy.copy(putfile)
self.assertEqual(putfile, copy.deepcopy(putfile)) assert putfile == copy.deepcopy(putfile)
@require_pil
def test_get_image_by_grid_id(self): def test_get_image_by_grid_id(self):
if not HAS_PIL:
raise SkipTest("PIL not installed")
class TestImage(Document): class TestImage(Document):
image1 = ImageField() image1 = ImageField()
@ -569,9 +555,7 @@ class TestFileField(MongoDBTestCase):
test = TestImage.objects.first() test = TestImage.objects.first()
grid_id = test.image1.grid_id grid_id = test.image1.grid_id
self.assertEqual( assert 1 == TestImage.objects(Q(image1=grid_id) or Q(image2=grid_id)).count()
1, TestImage.objects(Q(image1=grid_id) or Q(image2=grid_id)).count()
)
def test_complex_field_filefield(self): def test_complex_field_filefield(self):
"""Ensure you can add meta data to file""" """Ensure you can add meta data to file"""
@ -593,9 +577,9 @@ class TestFileField(MongoDBTestCase):
marmot.save() marmot.save()
marmot = Animal.objects.get() marmot = Animal.objects.get()
self.assertEqual(marmot.photos[0].content_type, "image/jpeg") assert marmot.photos[0].content_type == "image/jpeg"
self.assertEqual(marmot.photos[0].foo, "bar") assert marmot.photos[0].foo == "bar"
self.assertEqual(marmot.photos[0].get().length, 8313) assert marmot.photos[0].get().length == 8313
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
import six import six
from mongoengine import * from mongoengine import *
@ -16,8 +17,8 @@ class TestFloatField(MongoDBTestCase):
TestDocument(float_fld=None).save() TestDocument(float_fld=None).save()
TestDocument(float_fld=1).save() TestDocument(float_fld=1).save()
self.assertEqual(1, TestDocument.objects(float_fld__ne=None).count()) assert 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=1).count()
def test_validation(self): def test_validation(self):
"""Ensure that invalid values cannot be assigned to float fields. """Ensure that invalid values cannot be assigned to float fields.
@ -34,16 +35,20 @@ class TestFloatField(MongoDBTestCase):
person.validate() person.validate()
person.height = "2.0" person.height = "2.0"
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.height = 0.01 person.height = 0.01
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.height = 4.0 person.height = 4.0
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person_2 = Person(height="something invalid") person_2 = Person(height="something invalid")
self.assertRaises(ValidationError, person_2.validate) with pytest.raises(ValidationError):
person_2.validate()
big_person = BigPerson() big_person = BigPerson()
@ -55,4 +60,5 @@ class TestFloatField(MongoDBTestCase):
big_person.validate() big_person.validate()
big_person.height = 2 ** 100000 # Too big for a float value big_person.height = 2 ** 100000 # Too big for a float value
self.assertRaises(ValidationError, big_person.validate) with pytest.raises(ValidationError):
big_person.validate()

View File

@ -11,7 +11,7 @@ class TestGeoField(MongoDBTestCase):
Cls(loc=loc).validate() Cls(loc=loc).validate()
self.fail("Should not validate the location {0}".format(loc)) self.fail("Should not validate the location {0}".format(loc))
except ValidationError as e: except ValidationError as e:
self.assertEqual(expected, e.to_dict()["loc"]) assert expected == e.to_dict()["loc"]
def test_geopoint_validation(self): def test_geopoint_validation(self):
class Location(Document): class Location(Document):
@ -299,7 +299,7 @@ class TestGeoField(MongoDBTestCase):
location = GeoPointField() location = GeoPointField()
geo_indicies = Event._geo_indices() geo_indicies = Event._geo_indices()
self.assertEqual(geo_indicies, [{"fields": [("location", "2d")]}]) assert geo_indicies == [{"fields": [("location", "2d")]}]
def test_geopoint_embedded_indexes(self): def test_geopoint_embedded_indexes(self):
"""Ensure that indexes are created automatically for GeoPointFields on """Ensure that indexes are created automatically for GeoPointFields on
@ -315,7 +315,7 @@ class TestGeoField(MongoDBTestCase):
venue = EmbeddedDocumentField(Venue) venue = EmbeddedDocumentField(Venue)
geo_indicies = Event._geo_indices() 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): def test_indexes_2dsphere(self):
"""Ensure that indexes are created automatically for GeoPointFields. """Ensure that indexes are created automatically for GeoPointFields.
@ -328,9 +328,9 @@ class TestGeoField(MongoDBTestCase):
polygon = PolygonField() polygon = PolygonField()
geo_indicies = Event._geo_indices() geo_indicies = Event._geo_indices()
self.assertIn({"fields": [("line", "2dsphere")]}, geo_indicies) assert {"fields": [("line", "2dsphere")]} in geo_indicies
self.assertIn({"fields": [("polygon", "2dsphere")]}, geo_indicies) assert {"fields": [("polygon", "2dsphere")]} in geo_indicies
self.assertIn({"fields": [("point", "2dsphere")]}, geo_indicies) assert {"fields": [("point", "2dsphere")]} in geo_indicies
def test_indexes_2dsphere_embedded(self): def test_indexes_2dsphere_embedded(self):
"""Ensure that indexes are created automatically for GeoPointFields. """Ensure that indexes are created automatically for GeoPointFields.
@ -347,9 +347,9 @@ class TestGeoField(MongoDBTestCase):
venue = EmbeddedDocumentField(Venue) venue = EmbeddedDocumentField(Venue)
geo_indicies = Event._geo_indices() geo_indicies = Event._geo_indices()
self.assertIn({"fields": [("venue.line", "2dsphere")]}, geo_indicies) assert {"fields": [("venue.line", "2dsphere")]} in geo_indicies
self.assertIn({"fields": [("venue.polygon", "2dsphere")]}, geo_indicies) assert {"fields": [("venue.polygon", "2dsphere")]} in geo_indicies
self.assertIn({"fields": [("venue.point", "2dsphere")]}, geo_indicies) assert {"fields": [("venue.point", "2dsphere")]} in geo_indicies
def test_geo_indexes_recursion(self): def test_geo_indexes_recursion(self):
class Location(Document): class Location(Document):
@ -365,12 +365,12 @@ class TestGeoField(MongoDBTestCase):
Parent(name="Berlin").save() Parent(name="Berlin").save()
info = Parent._get_collection().index_information() info = Parent._get_collection().index_information()
self.assertNotIn("location_2d", info) assert "location_2d" not in info
info = Location._get_collection().index_information() info = Location._get_collection().index_information()
self.assertIn("location_2d", info) assert "location_2d" in info
self.assertEqual(len(Parent._geo_indices()), 0) assert len(Parent._geo_indices()) == 0
self.assertEqual(len(Location._geo_indices()), 1) assert len(Location._geo_indices()) == 1
def test_geo_indexes_auto_index(self): def test_geo_indexes_auto_index(self):
@ -381,16 +381,16 @@ class TestGeoField(MongoDBTestCase):
meta = {"indexes": [[("location", "2dsphere"), ("datetime", 1)]]} meta = {"indexes": [[("location", "2dsphere"), ("datetime", 1)]]}
self.assertEqual([], Log._geo_indices()) assert [] == Log._geo_indices()
Log.drop_collection() Log.drop_collection()
Log.ensure_indexes() Log.ensure_indexes()
info = Log._get_collection().index_information() info = Log._get_collection().index_information()
self.assertEqual( assert info["location_2dsphere_datetime_1"]["key"] == [
info["location_2dsphere_datetime_1"]["key"], ("location", "2dsphere"),
[("location", "2dsphere"), ("datetime", 1)], ("datetime", 1),
) ]
# Test listing explicitly # Test listing explicitly
class Log(Document): class Log(Document):
@ -401,16 +401,16 @@ class TestGeoField(MongoDBTestCase):
"indexes": [{"fields": [("location", "2dsphere"), ("datetime", 1)]}] "indexes": [{"fields": [("location", "2dsphere"), ("datetime", 1)]}]
} }
self.assertEqual([], Log._geo_indices()) assert [] == Log._geo_indices()
Log.drop_collection() Log.drop_collection()
Log.ensure_indexes() Log.ensure_indexes()
info = Log._get_collection().index_information() info = Log._get_collection().index_information()
self.assertEqual( assert info["location_2dsphere_datetime_1"]["key"] == [
info["location_2dsphere_datetime_1"]["key"], ("location", "2dsphere"),
[("location", "2dsphere"), ("datetime", 1)], ("datetime", 1),
) ]
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -23,11 +25,14 @@ class TestIntField(MongoDBTestCase):
person.validate() person.validate()
person.age = -1 person.age = -1
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.age = 120 person.age = 120
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
person.age = "ten" person.age = "ten"
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
def test_ne_operator(self): def test_ne_operator(self):
class TestDocument(Document): class TestDocument(Document):
@ -38,5 +43,5 @@ class TestIntField(MongoDBTestCase):
TestDocument(int_fld=None).save() TestDocument(int_fld=None).save()
TestDocument(int_fld=1).save() TestDocument(int_fld=1).save()
self.assertEqual(1, TestDocument.objects(int_fld__ne=None).count()) assert 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=1).count()

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from bson import DBRef, ObjectId from bson import DBRef, ObjectId
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.base import LazyReference from mongoengine.base import LazyReference
@ -11,7 +12,8 @@ class TestLazyReferenceField(MongoDBTestCase):
def test_lazy_reference_config(self): def test_lazy_reference_config(self):
# Make sure ReferenceField only accepts a document class or a string # Make sure ReferenceField only accepts a document class or a string
# with a document class name. # with a document class name.
self.assertRaises(ValidationError, LazyReferenceField, EmbeddedDocument) with pytest.raises(ValidationError):
LazyReferenceField(EmbeddedDocument)
def test___repr__(self): def test___repr__(self):
class Animal(Document): class Animal(Document):
@ -25,7 +27,7 @@ class TestLazyReferenceField(MongoDBTestCase):
animal = Animal() animal = Animal()
oc = Ocurrence(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): def test___getattr___unknown_attr_raises_attribute_error(self):
class Animal(Document): class Animal(Document):
@ -39,7 +41,7 @@ class TestLazyReferenceField(MongoDBTestCase):
animal = Animal().save() animal = Animal().save()
oc = Ocurrence(animal=animal) oc = Ocurrence(animal=animal)
with self.assertRaises(AttributeError): with pytest.raises(AttributeError):
oc.animal.not_exist oc.animal.not_exist
def test_lazy_reference_simple(self): def test_lazy_reference_simple(self):
@ -57,19 +59,19 @@ class TestLazyReferenceField(MongoDBTestCase):
animal = Animal(name="Leopard", tag="heavy").save() animal = Animal(name="Leopard", tag="heavy").save()
Ocurrence(person="test", animal=animal).save() Ocurrence(person="test", animal=animal).save()
p = Ocurrence.objects.get() p = Ocurrence.objects.get()
self.assertIsInstance(p.animal, LazyReference) assert isinstance(p.animal, LazyReference)
fetched_animal = p.animal.fetch() fetched_animal = p.animal.fetch()
self.assertEqual(fetched_animal, animal) assert fetched_animal == animal
# `fetch` keep cache on referenced document by default... # `fetch` keep cache on referenced document by default...
animal.tag = "not so heavy" animal.tag = "not so heavy"
animal.save() animal.save()
double_fetch = p.animal.fetch() double_fetch = p.animal.fetch()
self.assertIs(fetched_animal, double_fetch) assert fetched_animal is double_fetch
self.assertEqual(double_fetch.tag, "heavy") assert double_fetch.tag == "heavy"
# ...unless specified otherwise # ...unless specified otherwise
fetch_force = p.animal.fetch(force=True) fetch_force = p.animal.fetch(force=True)
self.assertIsNot(fetch_force, fetched_animal) assert fetch_force is not fetched_animal
self.assertEqual(fetch_force.tag, "not so heavy") assert fetch_force.tag == "not so heavy"
def test_lazy_reference_fetch_invalid_ref(self): def test_lazy_reference_fetch_invalid_ref(self):
class Animal(Document): class Animal(Document):
@ -87,8 +89,8 @@ class TestLazyReferenceField(MongoDBTestCase):
Ocurrence(person="test", animal=animal).save() Ocurrence(person="test", animal=animal).save()
animal.delete() animal.delete()
p = Ocurrence.objects.get() p = Ocurrence.objects.get()
self.assertIsInstance(p.animal, LazyReference) assert isinstance(p.animal, LazyReference)
with self.assertRaises(DoesNotExist): with pytest.raises(DoesNotExist):
p.animal.fetch() p.animal.fetch()
def test_lazy_reference_set(self): def test_lazy_reference_set(self):
@ -122,7 +124,7 @@ class TestLazyReferenceField(MongoDBTestCase):
): ):
p = Ocurrence(person="test", animal=ref).save() p = Ocurrence(person="test", animal=ref).save()
p.reload() p.reload()
self.assertIsInstance(p.animal, LazyReference) assert isinstance(p.animal, LazyReference)
p.animal.fetch() p.animal.fetch()
def test_lazy_reference_bad_set(self): def test_lazy_reference_bad_set(self):
@ -149,7 +151,7 @@ class TestLazyReferenceField(MongoDBTestCase):
DBRef(baddoc._get_collection_name(), animal.pk), DBRef(baddoc._get_collection_name(), animal.pk),
LazyReference(BadDoc, animal.pk), LazyReference(BadDoc, animal.pk),
): ):
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
p = Ocurrence(person="test", animal=bad).save() p = Ocurrence(person="test", animal=bad).save()
def test_lazy_reference_query_conversion(self): def test_lazy_reference_query_conversion(self):
@ -179,14 +181,14 @@ class TestLazyReferenceField(MongoDBTestCase):
post2.save() post2.save()
post = BlogPost.objects(author=m1).first() post = BlogPost.objects(author=m1).first()
self.assertEqual(post.id, post1.id) assert post.id == post1.id
post = BlogPost.objects(author=m2).first() post = BlogPost.objects(author=m2).first()
self.assertEqual(post.id, post2.id) assert post.id == post2.id
# Same thing by passing a LazyReference instance # Same thing by passing a LazyReference instance
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first() 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): def test_lazy_reference_query_conversion_dbref(self):
"""Ensure that LazyReferenceFields can be queried using objects and values """Ensure that LazyReferenceFields can be queried using objects and values
@ -215,14 +217,14 @@ class TestLazyReferenceField(MongoDBTestCase):
post2.save() post2.save()
post = BlogPost.objects(author=m1).first() post = BlogPost.objects(author=m1).first()
self.assertEqual(post.id, post1.id) assert post.id == post1.id
post = BlogPost.objects(author=m2).first() post = BlogPost.objects(author=m2).first()
self.assertEqual(post.id, post2.id) assert post.id == post2.id
# Same thing by passing a LazyReference instance # Same thing by passing a LazyReference instance
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first() 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): def test_lazy_reference_passthrough(self):
class Animal(Document): class Animal(Document):
@ -239,20 +241,20 @@ class TestLazyReferenceField(MongoDBTestCase):
animal = Animal(name="Leopard", tag="heavy").save() animal = Animal(name="Leopard", tag="heavy").save()
Ocurrence(animal=animal, animal_passthrough=animal).save() Ocurrence(animal=animal, animal_passthrough=animal).save()
p = Ocurrence.objects.get() p = Ocurrence.objects.get()
self.assertIsInstance(p.animal, LazyReference) assert isinstance(p.animal, LazyReference)
with self.assertRaises(KeyError): with pytest.raises(KeyError):
p.animal["name"] p.animal["name"]
with self.assertRaises(AttributeError): with pytest.raises(AttributeError):
p.animal.name p.animal.name
self.assertEqual(p.animal.pk, animal.pk) assert p.animal.pk == animal.pk
self.assertEqual(p.animal_passthrough.name, "Leopard") assert p.animal_passthrough.name == "Leopard"
self.assertEqual(p.animal_passthrough["name"], "Leopard") assert p.animal_passthrough["name"] == "Leopard"
# Should not be able to access referenced document's methods # Should not be able to access referenced document's methods
with self.assertRaises(AttributeError): with pytest.raises(AttributeError):
p.animal.save p.animal.save
with self.assertRaises(KeyError): with pytest.raises(KeyError):
p.animal["save"] p.animal["save"]
def test_lazy_reference_not_set(self): def test_lazy_reference_not_set(self):
@ -269,7 +271,7 @@ class TestLazyReferenceField(MongoDBTestCase):
Ocurrence(person="foo").save() Ocurrence(person="foo").save()
p = Ocurrence.objects.get() p = Ocurrence.objects.get()
self.assertIs(p.animal, None) assert p.animal is None
def test_lazy_reference_equality(self): def test_lazy_reference_equality(self):
class Animal(Document): class Animal(Document):
@ -280,12 +282,12 @@ class TestLazyReferenceField(MongoDBTestCase):
animal = Animal(name="Leopard", tag="heavy").save() animal = Animal(name="Leopard", tag="heavy").save()
animalref = LazyReference(Animal, animal.pk) animalref = LazyReference(Animal, animal.pk)
self.assertEqual(animal, animalref) assert animal == animalref
self.assertEqual(animalref, animal) assert animalref == animal
other_animalref = LazyReference(Animal, ObjectId("54495ad94c934721ede76f90")) other_animalref = LazyReference(Animal, ObjectId("54495ad94c934721ede76f90"))
self.assertNotEqual(animal, other_animalref) assert animal != other_animalref
self.assertNotEqual(other_animalref, animal) assert other_animalref != animal
def test_lazy_reference_embedded(self): def test_lazy_reference_embedded(self):
class Animal(Document): class Animal(Document):
@ -308,12 +310,12 @@ class TestLazyReferenceField(MongoDBTestCase):
animal2 = Animal(name="cheeta").save() animal2 = Animal(name="cheeta").save()
def check_fields_type(occ): def check_fields_type(occ):
self.assertIsInstance(occ.direct, LazyReference) assert isinstance(occ.direct, LazyReference)
for elem in occ.in_list: for elem in occ.in_list:
self.assertIsInstance(elem, LazyReference) assert isinstance(elem, LazyReference)
self.assertIsInstance(occ.in_embedded.direct, LazyReference) assert isinstance(occ.in_embedded.direct, LazyReference)
for elem in occ.in_embedded.in_list: for elem in occ.in_embedded.in_list:
self.assertIsInstance(elem, LazyReference) assert isinstance(elem, LazyReference)
occ = Ocurrence( occ = Ocurrence(
in_list=[animal1, animal2], in_list=[animal1, animal2],
@ -346,19 +348,19 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
animal = Animal(name="Leopard", tag="heavy").save() animal = Animal(name="Leopard", tag="heavy").save()
Ocurrence(person="test", animal=animal).save() Ocurrence(person="test", animal=animal).save()
p = Ocurrence.objects.get() p = Ocurrence.objects.get()
self.assertIsInstance(p.animal, LazyReference) assert isinstance(p.animal, LazyReference)
fetched_animal = p.animal.fetch() fetched_animal = p.animal.fetch()
self.assertEqual(fetched_animal, animal) assert fetched_animal == animal
# `fetch` keep cache on referenced document by default... # `fetch` keep cache on referenced document by default...
animal.tag = "not so heavy" animal.tag = "not so heavy"
animal.save() animal.save()
double_fetch = p.animal.fetch() double_fetch = p.animal.fetch()
self.assertIs(fetched_animal, double_fetch) assert fetched_animal is double_fetch
self.assertEqual(double_fetch.tag, "heavy") assert double_fetch.tag == "heavy"
# ...unless specified otherwise # ...unless specified otherwise
fetch_force = p.animal.fetch(force=True) fetch_force = p.animal.fetch(force=True)
self.assertIsNot(fetch_force, fetched_animal) assert fetch_force is not fetched_animal
self.assertEqual(fetch_force.tag, "not so heavy") assert fetch_force.tag == "not so heavy"
def test_generic_lazy_reference_choices(self): def test_generic_lazy_reference_choices(self):
class Animal(Document): class Animal(Document):
@ -385,13 +387,13 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
occ_animal = Ocurrence(living_thing=animal, thing=animal).save() occ_animal = Ocurrence(living_thing=animal, thing=animal).save()
occ_vegetal = Ocurrence(living_thing=vegetal, thing=vegetal).save() occ_vegetal = Ocurrence(living_thing=vegetal, thing=vegetal).save()
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
Ocurrence(living_thing=mineral).save() Ocurrence(living_thing=mineral).save()
occ = Ocurrence.objects.get(living_thing=animal) occ = Ocurrence.objects.get(living_thing=animal)
self.assertEqual(occ, occ_animal) assert occ == occ_animal
self.assertIsInstance(occ.thing, LazyReference) assert isinstance(occ.thing, LazyReference)
self.assertIsInstance(occ.living_thing, LazyReference) assert isinstance(occ.living_thing, LazyReference)
occ.thing = vegetal occ.thing = vegetal
occ.living_thing = vegetal occ.living_thing = vegetal
@ -399,7 +401,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
occ.thing = mineral occ.thing = mineral
occ.living_thing = mineral occ.living_thing = mineral
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
occ.save() occ.save()
def test_generic_lazy_reference_set(self): def test_generic_lazy_reference_set(self):
@ -434,7 +436,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
): ):
p = Ocurrence(person="test", animal=ref).save() p = Ocurrence(person="test", animal=ref).save()
p.reload() p.reload()
self.assertIsInstance(p.animal, (LazyReference, Document)) assert isinstance(p.animal, (LazyReference, Document))
p.animal.fetch() p.animal.fetch()
def test_generic_lazy_reference_bad_set(self): def test_generic_lazy_reference_bad_set(self):
@ -455,7 +457,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
animal = Animal(name="Leopard", tag="heavy").save() animal = Animal(name="Leopard", tag="heavy").save()
baddoc = BadDoc().save() baddoc = BadDoc().save()
for bad in (42, "foo", baddoc, LazyReference(BadDoc, animal.pk)): 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() p = Ocurrence(person="test", animal=bad).save()
def test_generic_lazy_reference_query_conversion(self): def test_generic_lazy_reference_query_conversion(self):
@ -481,14 +483,14 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
post2.save() post2.save()
post = BlogPost.objects(author=m1).first() post = BlogPost.objects(author=m1).first()
self.assertEqual(post.id, post1.id) assert post.id == post1.id
post = BlogPost.objects(author=m2).first() post = BlogPost.objects(author=m2).first()
self.assertEqual(post.id, post2.id) assert post.id == post2.id
# Same thing by passing a LazyReference instance # Same thing by passing a LazyReference instance
post = BlogPost.objects(author=LazyReference(Member, m2.pk)).first() 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): def test_generic_lazy_reference_not_set(self):
class Animal(Document): class Animal(Document):
@ -504,7 +506,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
Ocurrence(person="foo").save() Ocurrence(person="foo").save()
p = Ocurrence.objects.get() 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): def test_generic_lazy_reference_accepts_string_instead_of_class(self):
class Animal(Document): class Animal(Document):
@ -521,7 +523,7 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
animal = Animal().save() animal = Animal().save()
Ocurrence(animal=animal).save() Ocurrence(animal=animal).save()
p = Ocurrence.objects.get() p = Ocurrence.objects.get()
self.assertEqual(p.animal, animal) assert p.animal == animal
def test_generic_lazy_reference_embedded(self): def test_generic_lazy_reference_embedded(self):
class Animal(Document): class Animal(Document):
@ -544,12 +546,12 @@ class TestGenericLazyReferenceField(MongoDBTestCase):
animal2 = Animal(name="cheeta").save() animal2 = Animal(name="cheeta").save()
def check_fields_type(occ): def check_fields_type(occ):
self.assertIsInstance(occ.direct, LazyReference) assert isinstance(occ.direct, LazyReference)
for elem in occ.in_list: for elem in occ.in_list:
self.assertIsInstance(elem, LazyReference) assert isinstance(elem, LazyReference)
self.assertIsInstance(occ.in_embedded.direct, LazyReference) assert isinstance(occ.in_embedded.direct, LazyReference)
for elem in occ.in_embedded.in_list: for elem in occ.in_embedded.in_list:
self.assertIsInstance(elem, LazyReference) assert isinstance(elem, LazyReference)
occ = Ocurrence( occ = Ocurrence(
in_list=[animal1, animal2], in_list=[animal1, animal2],

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
import six import six
try: try:
@ -24,10 +25,10 @@ class TestLongField(MongoDBTestCase):
doc = TestLongFieldConsideredAsInt64(some_long=42).save() doc = TestLongFieldConsideredAsInt64(some_long=42).save()
db = get_db() db = get_db()
self.assertIsInstance( assert isinstance(
db.test_long_field_considered_as_int64.find()[0]["some_long"], Int64 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): def test_long_validation(self):
"""Ensure that invalid values cannot be assigned to long fields. """Ensure that invalid values cannot be assigned to long fields.
@ -41,11 +42,14 @@ class TestLongField(MongoDBTestCase):
doc.validate() doc.validate()
doc.value = -1 doc.value = -1
self.assertRaises(ValidationError, doc.validate) with pytest.raises(ValidationError):
doc.validate()
doc.value = 120 doc.value = 120
self.assertRaises(ValidationError, doc.validate) with pytest.raises(ValidationError):
doc.validate()
doc.value = "ten" doc.value = "ten"
self.assertRaises(ValidationError, doc.validate) with pytest.raises(ValidationError):
doc.validate()
def test_long_ne_operator(self): def test_long_ne_operator(self):
class TestDocument(Document): class TestDocument(Document):
@ -56,4 +60,4 @@ class TestLongField(MongoDBTestCase):
TestDocument(long_fld=None).save() TestDocument(long_fld=None).save()
TestDocument(long_fld=1).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()

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime import datetime
from mongoengine import * import pytest
from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -19,11 +20,11 @@ class TestMapField(MongoDBTestCase):
e.mapping["someint"] = 1 e.mapping["someint"] = 1
e.save() e.save()
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
e.mapping["somestring"] = "abc" e.mapping["somestring"] = "abc"
e.save() e.save()
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
class NoDeclaredType(Document): class NoDeclaredType(Document):
mapping = MapField() mapping = MapField()
@ -51,10 +52,10 @@ class TestMapField(MongoDBTestCase):
e.save() e.save()
e2 = Extensible.objects.get(id=e.id) e2 = Extensible.objects.get(id=e.id)
self.assertIsInstance(e2.mapping["somestring"], StringSetting) assert isinstance(e2.mapping["somestring"], StringSetting)
self.assertIsInstance(e2.mapping["someint"], IntegerSetting) assert isinstance(e2.mapping["someint"], IntegerSetting)
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
e.mapping["someint"] = 123 e.mapping["someint"] = 123
e.save() e.save()
@ -74,9 +75,9 @@ class TestMapField(MongoDBTestCase):
Test.objects.update_one(inc__my_map__DICTIONARY_KEY__number=1) Test.objects.update_one(inc__my_map__DICTIONARY_KEY__number=1)
test = Test.objects.get() 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() 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): def test_mapfield_numerical_index(self):
"""Ensure that MapField accept numeric strings as indexes.""" """Ensure that MapField accept numeric strings as indexes."""
@ -116,13 +117,13 @@ class TestMapField(MongoDBTestCase):
actions={"friends": Action(operation="drink", object="beer")}, actions={"friends": Action(operation="drink", object="beer")},
).save() ).save()
self.assertEqual(1, Log.objects(visited__friends__exists=True).count()) assert 1 == Log.objects(visited__friends__exists=True).count()
self.assertEqual( assert (
1, 1
Log.objects( == Log.objects(
actions__friends__operation="drink", actions__friends__object="beer" actions__friends__operation="drink", actions__friends__object="beer"
).count(), ).count()
) )
def test_map_field_unicode(self): def test_map_field_unicode(self):
@ -139,7 +140,7 @@ class TestMapField(MongoDBTestCase):
tree.save() tree.save()
self.assertEqual( assert (
BlogPost.objects.get(id=tree.id).info_dict[u"éééé"].description, BlogPost.objects.get(id=tree.id).info_dict[u"éééé"].description
u"VALUE: éééé", == u"VALUE: éééé"
) )

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from bson import SON, DBRef from bson import DBRef, SON
import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -24,19 +24,22 @@ class TestReferenceField(MongoDBTestCase):
# Make sure ReferenceField only accepts a document class or a string # Make sure ReferenceField only accepts a document class or a string
# with a document class name. # with a document class name.
self.assertRaises(ValidationError, ReferenceField, EmbeddedDocument) with pytest.raises(ValidationError):
ReferenceField(EmbeddedDocument)
user = User(name="Test User") user = User(name="Test User")
# Ensure that the referenced object must have been saved # Ensure that the referenced object must have been saved
post1 = BlogPost(content="Chips and gravy taste good.") post1 = BlogPost(content="Chips and gravy taste good.")
post1.author = user post1.author = user
self.assertRaises(ValidationError, post1.save) with pytest.raises(ValidationError):
post1.save()
# Check that an invalid object type cannot be used # Check that an invalid object type cannot be used
post2 = BlogPost(content="Chips and chilli taste good.") post2 = BlogPost(content="Chips and chilli taste good.")
post1.author = post2 post1.author = post2
self.assertRaises(ValidationError, post1.validate) with pytest.raises(ValidationError):
post1.validate()
# Ensure ObjectID's are accepted as references # Ensure ObjectID's are accepted as references
user_object_id = user.pk user_object_id = user.pk
@ -52,22 +55,8 @@ class TestReferenceField(MongoDBTestCase):
# Make sure referencing a saved document of the *wrong* type fails # Make sure referencing a saved document of the *wrong* type fails
post2.save() post2.save()
post1.author = post2 post1.author = post2
self.assertRaises(ValidationError, post1.validate) with pytest.raises(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)
def test_dbref_reference_fields(self): def test_dbref_reference_fields(self):
"""Make sure storing references as bson.dbref.DBRef works.""" """Make sure storing references as bson.dbref.DBRef works."""
@ -81,13 +70,12 @@ class TestReferenceField(MongoDBTestCase):
p1 = Person(name="John").save() p1 = Person(name="John").save()
Person(name="Ross", parent=p1).save() Person(name="Ross", parent=p1).save()
self.assertEqual( assert Person._get_collection().find_one({"name": "Ross"})["parent"] == DBRef(
Person._get_collection().find_one({"name": "Ross"})["parent"], "person", p1.pk
DBRef("person", p1.pk),
) )
p = Person.objects.get(name="Ross") p = Person.objects.get(name="Ross")
self.assertEqual(p.parent, p1) assert p.parent == p1
def test_dbref_to_mongo(self): def test_dbref_to_mongo(self):
"""Make sure that calling to_mongo on a ReferenceField which """Make sure that calling to_mongo on a ReferenceField which
@ -100,9 +88,7 @@ class TestReferenceField(MongoDBTestCase):
parent = ReferenceField("self", dbref=False) parent = ReferenceField("self", dbref=False)
p = Person(name="Steve", parent=DBRef("person", "abcdefghijklmnop")) p = Person(name="Steve", parent=DBRef("person", "abcdefghijklmnop"))
self.assertEqual( assert p.to_mongo() == SON([("name", u"Steve"), ("parent", "abcdefghijklmnop")])
p.to_mongo(), SON([("name", u"Steve"), ("parent", "abcdefghijklmnop")])
)
def test_objectid_reference_fields(self): def test_objectid_reference_fields(self):
class Person(Document): class Person(Document):
@ -116,10 +102,10 @@ class TestReferenceField(MongoDBTestCase):
col = Person._get_collection() col = Person._get_collection()
data = col.find_one({"name": "Ross"}) data = col.find_one({"name": "Ross"})
self.assertEqual(data["parent"], p1.pk) assert data["parent"] == p1.pk
p = Person.objects.get(name="Ross") p = Person.objects.get(name="Ross")
self.assertEqual(p.parent, p1) assert p.parent == p1
def test_undefined_reference(self): def test_undefined_reference(self):
"""Ensure that ReferenceFields may reference undefined Documents. """Ensure that ReferenceFields may reference undefined Documents.
@ -144,14 +130,14 @@ class TestReferenceField(MongoDBTestCase):
me.save() me.save()
obj = Product.objects(company=ten_gen).first() obj = Product.objects(company=ten_gen).first()
self.assertEqual(obj, mongodb) assert obj == mongodb
self.assertEqual(obj.company, ten_gen) assert obj.company == ten_gen
obj = Product.objects(company=None).first() obj = Product.objects(company=None).first()
self.assertEqual(obj, me) assert obj == me
obj = Product.objects.get(company=None) obj = Product.objects.get(company=None)
self.assertEqual(obj, me) assert obj == me
def test_reference_query_conversion(self): def test_reference_query_conversion(self):
"""Ensure that ReferenceFields can be queried using objects and values """Ensure that ReferenceFields can be queried using objects and values
@ -180,10 +166,10 @@ class TestReferenceField(MongoDBTestCase):
post2.save() post2.save()
post = BlogPost.objects(author=m1).first() post = BlogPost.objects(author=m1).first()
self.assertEqual(post.id, post1.id) assert post.id == post1.id
post = BlogPost.objects(author=m2).first() post = BlogPost.objects(author=m2).first()
self.assertEqual(post.id, post2.id) assert post.id == post2.id
def test_reference_query_conversion_dbref(self): def test_reference_query_conversion_dbref(self):
"""Ensure that ReferenceFields can be queried using objects and values """Ensure that ReferenceFields can be queried using objects and values
@ -212,7 +198,7 @@ class TestReferenceField(MongoDBTestCase):
post2.save() post2.save()
post = BlogPost.objects(author=m1).first() post = BlogPost.objects(author=m1).first()
self.assertEqual(post.id, post1.id) assert post.id == post1.id
post = BlogPost.objects(author=m2).first() post = BlogPost.objects(author=m2).first()
self.assertEqual(post.id, post2.id) assert post.id == post2.id

View File

@ -18,17 +18,17 @@ class TestSequenceField(MongoDBTestCase):
Person(name="Person %s" % x).save() Person(name="Person %s" % x).save()
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) 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] 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"}) 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) Person.id.set_next_value(1000)
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) 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): def test_sequence_field_get_next_value(self):
class Person(Document): class Person(Document):
@ -41,10 +41,10 @@ class TestSequenceField(MongoDBTestCase):
for x in range(10): for x in range(10):
Person(name="Person %s" % x).save() 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.db["mongoengine.counters"].drop()
self.assertEqual(Person.id.get_next_value(), 1) assert Person.id.get_next_value() == 1
class Person(Document): class Person(Document):
id = SequenceField(primary_key=True, value_decorator=str) id = SequenceField(primary_key=True, value_decorator=str)
@ -56,10 +56,10 @@ class TestSequenceField(MongoDBTestCase):
for x in range(10): for x in range(10):
Person(name="Person %s" % x).save() 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.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): def test_sequence_field_sequence_name(self):
class Person(Document): class Person(Document):
@ -73,17 +73,17 @@ class TestSequenceField(MongoDBTestCase):
Person(name="Person %s" % x).save() Person(name="Person %s" % x).save()
c = self.db["mongoengine.counters"].find_one({"_id": "jelly.id"}) 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] 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"}) 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) Person.id.set_next_value(1000)
c = self.db["mongoengine.counters"].find_one({"_id": "jelly.id"}) 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): def test_multiple_sequence_fields(self):
class Person(Document): class Person(Document):
@ -98,24 +98,24 @@ class TestSequenceField(MongoDBTestCase):
Person(name="Person %s" % x).save() Person(name="Person %s" % x).save()
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) 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] 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] 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"}) 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) Person.id.set_next_value(1000)
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) 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) Person.counter.set_next_value(999)
c = self.db["mongoengine.counters"].find_one({"_id": "person.counter"}) 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): def test_sequence_fields_reload(self):
class Animal(Document): class Animal(Document):
@ -127,20 +127,20 @@ class TestSequenceField(MongoDBTestCase):
a = Animal(name="Boi").save() a = Animal(name="Boi").save()
self.assertEqual(a.counter, 1) assert a.counter == 1
a.reload() a.reload()
self.assertEqual(a.counter, 1) assert a.counter == 1
a.counter = None a.counter = None
self.assertEqual(a.counter, 2) assert a.counter == 2
a.save() a.save()
self.assertEqual(a.counter, 2) assert a.counter == 2
a = Animal.objects.first() a = Animal.objects.first()
self.assertEqual(a.counter, 2) assert a.counter == 2
a.reload() a.reload()
self.assertEqual(a.counter, 2) assert a.counter == 2
def test_multiple_sequence_fields_on_docs(self): def test_multiple_sequence_fields_on_docs(self):
class Animal(Document): class Animal(Document):
@ -160,22 +160,22 @@ class TestSequenceField(MongoDBTestCase):
Person(name="Person %s" % x).save() Person(name="Person %s" % x).save()
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) 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"}) 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] 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] 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"}) 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"}) 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): def test_sequence_field_value_decorator(self):
class Person(Document): class Person(Document):
@ -190,13 +190,13 @@ class TestSequenceField(MongoDBTestCase):
p.save() p.save()
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"}) 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] 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"}) 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): def test_embedded_sequence_field(self):
class Comment(EmbeddedDocument): class Comment(EmbeddedDocument):
@ -218,10 +218,10 @@ class TestSequenceField(MongoDBTestCase):
], ],
).save() ).save()
c = self.db["mongoengine.counters"].find_one({"_id": "comment.id"}) c = self.db["mongoengine.counters"].find_one({"_id": "comment.id"})
self.assertEqual(c["next"], 2) assert c["next"] == 2
post = Post.objects.first() post = Post.objects.first()
self.assertEqual(1, post.comments[0].id) assert 1 == post.comments[0].id
self.assertEqual(2, post.comments[1].id) assert 2 == post.comments[1].id
def test_inherited_sequencefield(self): def test_inherited_sequencefield(self):
class Base(Document): class Base(Document):
@ -241,16 +241,14 @@ class TestSequenceField(MongoDBTestCase):
foo = Foo(name="Foo") foo = Foo(name="Foo")
foo.save() foo.save()
self.assertTrue( assert "base.counter" in self.db["mongoengine.counters"].find().distinct("_id")
"base.counter" in self.db["mongoengine.counters"].find().distinct("_id") assert not (
)
self.assertFalse(
("foo.counter" or "bar.counter") ("foo.counter" or "bar.counter")
in self.db["mongoengine.counters"].find().distinct("_id") in self.db["mongoengine.counters"].find().distinct("_id")
) )
self.assertNotEqual(foo.counter, bar.counter) assert foo.counter != bar.counter
self.assertEqual(foo._fields["counter"].owner_document, Base) assert foo._fields["counter"].owner_document == Base
self.assertEqual(bar._fields["counter"].owner_document, Base) assert bar._fields["counter"].owner_document == Base
def test_no_inherited_sequencefield(self): def test_no_inherited_sequencefield(self):
class Base(Document): class Base(Document):
@ -269,13 +267,12 @@ class TestSequenceField(MongoDBTestCase):
foo = Foo(name="Foo") foo = Foo(name="Foo")
foo.save() foo.save()
self.assertFalse( assert not (
"base.counter" in self.db["mongoengine.counters"].find().distinct("_id") "base.counter" in self.db["mongoengine.counters"].find().distinct("_id")
) )
self.assertTrue( assert ("foo.counter" and "bar.counter") in self.db[
("foo.counter" and "bar.counter") "mongoengine.counters"
in self.db["mongoengine.counters"].find().distinct("_id") ].find().distinct("_id")
) assert foo.counter == bar.counter
self.assertEqual(foo.counter, bar.counter) assert foo._fields["counter"].owner_document == Foo
self.assertEqual(foo._fields["counter"].owner_document, Foo) assert bar._fields["counter"].owner_document == Bar
self.assertEqual(bar._fields["counter"].owner_document, Bar)

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@ -13,7 +15,8 @@ class TestURLField(MongoDBTestCase):
link = Link() link = Link()
link.url = "google" link.url = "google"
self.assertRaises(ValidationError, link.validate) with pytest.raises(ValidationError):
link.validate()
link.url = "http://www.google.com:8080" link.url = "http://www.google.com:8080"
link.validate() link.validate()
@ -29,11 +32,11 @@ class TestURLField(MongoDBTestCase):
# TODO fix URL validation - this *IS* a valid URL # TODO fix URL validation - this *IS* a valid URL
# For now we just want to make sure that the error message is correct # 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() link.validate()
self.assertEqual( assert (
unicode(ctx_err.exception), unicode(exc_info.value)
u"ValidationError (Link:None) (Invalid URL: http://\u043f\u0440\u0438\u0432\u0435\u0442.com: ['url'])", == u"ValidationError (Link:None) (Invalid URL: http://\u043f\u0440\u0438\u0432\u0435\u0442.com: ['url'])"
) )
def test_url_scheme_validation(self): def test_url_scheme_validation(self):
@ -48,7 +51,8 @@ class TestURLField(MongoDBTestCase):
link = Link() link = Link()
link.url = "ws://google.com" link.url = "ws://google.com"
self.assertRaises(ValidationError, link.validate) with pytest.raises(ValidationError):
link.validate()
scheme_link = SchemeLink() scheme_link = SchemeLink()
scheme_link.url = "ws://google.com" scheme_link.url = "ws://google.com"

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import uuid import uuid
from mongoengine import * import pytest
from mongoengine import *
from tests.utils import MongoDBTestCase, get_as_pymongo from tests.utils import MongoDBTestCase, get_as_pymongo
@ -14,9 +15,7 @@ class TestUUIDField(MongoDBTestCase):
def test_storage(self): def test_storage(self):
uid = uuid.uuid4() uid = uuid.uuid4()
person = Person(api_key=uid).save() person = Person(api_key=uid).save()
self.assertEqual( assert get_as_pymongo(person) == {"_id": person.id, "api_key": str(uid)}
get_as_pymongo(person), {"_id": person.id, "api_key": str(uid)}
)
def test_field_string(self): def test_field_string(self):
"""Test UUID fields storing as String """Test UUID fields storing as String
@ -25,8 +24,8 @@ class TestUUIDField(MongoDBTestCase):
uu = uuid.uuid4() uu = uuid.uuid4()
Person(api_key=uu).save() Person(api_key=uu).save()
self.assertEqual(1, Person.objects(api_key=uu).count()) assert 1 == Person.objects(api_key=uu).count()
self.assertEqual(uu, Person.objects.first().api_key) assert uu == Person.objects.first().api_key
person = Person() person = Person()
valid = (uuid.uuid4(), uuid.uuid1()) valid = (uuid.uuid4(), uuid.uuid1())
@ -40,7 +39,8 @@ class TestUUIDField(MongoDBTestCase):
) )
for api_key in invalid: for api_key in invalid:
person.api_key = api_key person.api_key = api_key
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()
def test_field_binary(self): def test_field_binary(self):
"""Test UUID fields storing as Binary object.""" """Test UUID fields storing as Binary object."""
@ -48,8 +48,8 @@ class TestUUIDField(MongoDBTestCase):
uu = uuid.uuid4() uu = uuid.uuid4()
Person(api_key=uu).save() Person(api_key=uu).save()
self.assertEqual(1, Person.objects(api_key=uu).count()) assert 1 == Person.objects(api_key=uu).count()
self.assertEqual(uu, Person.objects.first().api_key) assert uu == Person.objects.first().api_key
person = Person() person = Person()
valid = (uuid.uuid4(), uuid.uuid1()) valid = (uuid.uuid4(), uuid.uuid1())
@ -63,4 +63,5 @@ class TestUUIDField(MongoDBTestCase):
) )
for api_key in invalid: for api_key in invalid:
person.api_key = api_key person.api_key = api_key
self.assertRaises(ValidationError, person.validate) with pytest.raises(ValidationError):
person.validate()

View File

@ -42,11 +42,11 @@ class PickleSignalsTest(Document):
@classmethod @classmethod
def post_save(self, sender, document, created, **kwargs): def post_save(self, sender, document, created, **kwargs):
pickled = pickle.dumps(document) pickle.dumps(document)
@classmethod @classmethod
def post_delete(self, sender, document, **kwargs): def post_delete(self, sender, document, **kwargs):
pickled = pickle.dumps(document) pickle.dumps(document)
signals.post_save.connect(PickleSignalsTest.post_save, sender=PickleSignalsTest) signals.post_save.connect(PickleSignalsTest.post_save, sender=PickleSignalsTest)

View File

@ -1,67 +1,69 @@
import unittest import unittest
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.queryset import QueryFieldList from mongoengine.queryset import QueryFieldList
class TestQueryFieldList(unittest.TestCase): class TestQueryFieldList:
def test_empty(self): def test_empty(self):
q = QueryFieldList() q = QueryFieldList()
self.assertFalse(q) assert not q
q = QueryFieldList(always_include=["_cls"]) q = QueryFieldList(always_include=["_cls"])
self.assertFalse(q) assert not q
def test_include_include(self): def test_include_include(self):
q = QueryFieldList() q = QueryFieldList()
q += QueryFieldList( q += QueryFieldList(
fields=["a", "b"], value=QueryFieldList.ONLY, _only_called=True 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) 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): def test_include_exclude(self):
q = QueryFieldList() q = QueryFieldList()
q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.ONLY) 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) 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): def test_exclude_exclude(self):
q = QueryFieldList() q = QueryFieldList()
q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.EXCLUDE) 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) 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): def test_exclude_include(self):
q = QueryFieldList() q = QueryFieldList()
q += QueryFieldList(fields=["a", "b"], value=QueryFieldList.EXCLUDE) 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) 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): def test_always_include(self):
q = QueryFieldList(always_include=["x", "y"]) q = QueryFieldList(always_include=["x", "y"])
q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE) q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE)
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) 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): def test_reset(self):
q = QueryFieldList(always_include=["x", "y"]) q = QueryFieldList(always_include=["x", "y"])
q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE) q += QueryFieldList(fields=["a", "b", "x"], value=QueryFieldList.EXCLUDE)
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) 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() q.reset()
self.assertFalse(q) assert not q
q += QueryFieldList(fields=["b", "c"], value=QueryFieldList.ONLY) 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): def test_using_a_slice(self):
q = QueryFieldList() q = QueryFieldList()
q += QueryFieldList(fields=["a"], value={"$slice": 5}) 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): class TestOnlyExcludeAll(unittest.TestCase):
@ -90,25 +92,23 @@ class TestOnlyExcludeAll(unittest.TestCase):
only = ["b", "c"] only = ["b", "c"]
qs = MyDoc.objects.fields(**{i: 1 for i in include}) qs = MyDoc.objects.fields(**{i: 1 for i in include})
self.assertEqual( assert qs._loaded_fields.as_dict() == {"a": 1, "b": 1, "c": 1, "d": 1, "e": 1}
qs._loaded_fields.as_dict(), {"a": 1, "b": 1, "c": 1, "d": 1, "e": 1}
)
qs = qs.only(*only) 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) 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 = MyDoc.objects.fields(**{i: 1 for i in include})
qs = qs.exclude(*exclude) 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) 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 = MyDoc.objects.exclude(*exclude)
qs = qs.fields(**{i: 1 for i in include}) 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) 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): def test_slicing(self):
class MyDoc(Document): class MyDoc(Document):
@ -127,15 +127,16 @@ class TestOnlyExcludeAll(unittest.TestCase):
qs = qs.exclude(*exclude) qs = qs.exclude(*exclude)
qs = qs.only(*only) qs = qs.only(*only)
qs = qs.fields(slice__b=5) 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]) qs = qs.fields(slice__c=[5, 1])
self.assertEqual( assert qs._loaded_fields.as_dict() == {
qs._loaded_fields.as_dict(), {"b": {"$slice": 5}, "c": {"$slice": [5, 1]}} "b": {"$slice": 5},
) "c": {"$slice": [5, 1]},
}
qs = qs.exclude("c") 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): def test_mix_slice_with_other_fields(self):
class MyDoc(Document): class MyDoc(Document):
@ -144,7 +145,7 @@ class TestOnlyExcludeAll(unittest.TestCase):
c = ListField() c = ListField()
qs = MyDoc.objects.fields(a=1, b=0, slice__c=2) 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): def test_only(self):
"""Ensure that QuerySet.only only returns the requested fields. """Ensure that QuerySet.only only returns the requested fields.
@ -153,20 +154,20 @@ class TestOnlyExcludeAll(unittest.TestCase):
person.save() person.save()
obj = self.Person.objects.only("name").get() obj = self.Person.objects.only("name").get()
self.assertEqual(obj.name, person.name) assert obj.name == person.name
self.assertEqual(obj.age, None) assert obj.age is None
obj = self.Person.objects.only("age").get() obj = self.Person.objects.only("age").get()
self.assertEqual(obj.name, None) assert obj.name is None
self.assertEqual(obj.age, person.age) assert obj.age == person.age
obj = self.Person.objects.only("name", "age").get() obj = self.Person.objects.only("name", "age").get()
self.assertEqual(obj.name, person.name) assert obj.name == person.name
self.assertEqual(obj.age, person.age) assert obj.age == person.age
obj = self.Person.objects.only(*("id", "name")).get() obj = self.Person.objects.only(*("id", "name")).get()
self.assertEqual(obj.name, person.name) assert obj.name == person.name
self.assertEqual(obj.age, None) assert obj.age is None
# Check polymorphism still works # Check polymorphism still works
class Employee(self.Person): class Employee(self.Person):
@ -176,12 +177,12 @@ class TestOnlyExcludeAll(unittest.TestCase):
employee.save() employee.save()
obj = self.Person.objects(id=employee.id).only("age").get() 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 # Check field names are looked up properly
obj = Employee.objects(id=employee.id).only("salary").get() obj = Employee.objects(id=employee.id).only("salary").get()
self.assertEqual(obj.salary, employee.salary) assert obj.salary == employee.salary
self.assertEqual(obj.name, None) assert obj.name is None
def test_only_with_subfields(self): def test_only_with_subfields(self):
class User(EmbeddedDocument): class User(EmbeddedDocument):
@ -215,29 +216,29 @@ class TestOnlyExcludeAll(unittest.TestCase):
post.save() post.save()
obj = BlogPost.objects.only("author.name").get() obj = BlogPost.objects.only("author.name").get()
self.assertEqual(obj.content, None) assert obj.content is None
self.assertEqual(obj.author.email, None) assert obj.author.email is None
self.assertEqual(obj.author.name, "Test User") assert obj.author.name == "Test User"
self.assertEqual(obj.comments, []) assert obj.comments == []
obj = BlogPost.objects.only("various.test_dynamic.some").get() 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() obj = BlogPost.objects.only("content", "comments.title").get()
self.assertEqual(obj.content, "Had a good coffee today...") assert obj.content == "Had a good coffee today..."
self.assertEqual(obj.author, None) assert obj.author is None
self.assertEqual(obj.comments[0].title, "I aggree") assert obj.comments[0].title == "I aggree"
self.assertEqual(obj.comments[1].title, "Coffee") assert obj.comments[1].title == "Coffee"
self.assertEqual(obj.comments[0].text, None) assert obj.comments[0].text is None
self.assertEqual(obj.comments[1].text, None) assert obj.comments[1].text is None
obj = BlogPost.objects.only("comments").get() obj = BlogPost.objects.only("comments").get()
self.assertEqual(obj.content, None) assert obj.content is None
self.assertEqual(obj.author, None) assert obj.author is None
self.assertEqual(obj.comments[0].title, "I aggree") assert obj.comments[0].title == "I aggree"
self.assertEqual(obj.comments[1].title, "Coffee") assert obj.comments[1].title == "Coffee"
self.assertEqual(obj.comments[0].text, "Great post!") assert obj.comments[0].text == "Great post!"
self.assertEqual(obj.comments[1].text, "I hate coffee") assert obj.comments[1].text == "I hate coffee"
BlogPost.drop_collection() BlogPost.drop_collection()
@ -266,10 +267,10 @@ class TestOnlyExcludeAll(unittest.TestCase):
post.save() post.save()
obj = BlogPost.objects.exclude("author", "comments.text").get() obj = BlogPost.objects.exclude("author", "comments.text").get()
self.assertEqual(obj.author, None) assert obj.author is None
self.assertEqual(obj.content, "Had a good coffee today...") assert obj.content == "Had a good coffee today..."
self.assertEqual(obj.comments[0].title, "I aggree") assert obj.comments[0].title == "I aggree"
self.assertEqual(obj.comments[0].text, None) assert obj.comments[0].text is None
BlogPost.drop_collection() BlogPost.drop_collection()
@ -301,18 +302,18 @@ class TestOnlyExcludeAll(unittest.TestCase):
email.save() email.save()
obj = Email.objects.exclude("content_type").exclude("body").get() obj = Email.objects.exclude("content_type").exclude("body").get()
self.assertEqual(obj.sender, "me") assert obj.sender == "me"
self.assertEqual(obj.to, "you") assert obj.to == "you"
self.assertEqual(obj.subject, "From Russia with Love") assert obj.subject == "From Russia with Love"
self.assertEqual(obj.body, None) assert obj.body is None
self.assertEqual(obj.content_type, None) assert obj.content_type is None
obj = Email.objects.only("sender", "to").exclude("body", "sender").get() obj = Email.objects.only("sender", "to").exclude("body", "sender").get()
self.assertEqual(obj.sender, None) assert obj.sender is None
self.assertEqual(obj.to, "you") assert obj.to == "you"
self.assertEqual(obj.subject, None) assert obj.subject is None
self.assertEqual(obj.body, None) assert obj.body is None
self.assertEqual(obj.content_type, None) assert obj.content_type is None
obj = ( obj = (
Email.objects.exclude("attachments.content") Email.objects.exclude("attachments.content")
@ -320,13 +321,13 @@ class TestOnlyExcludeAll(unittest.TestCase):
.only("to", "attachments.name") .only("to", "attachments.name")
.get() .get()
) )
self.assertEqual(obj.attachments[0].name, "file1.doc") assert obj.attachments[0].name == "file1.doc"
self.assertEqual(obj.attachments[0].content, None) assert obj.attachments[0].content is None
self.assertEqual(obj.sender, None) assert obj.sender is None
self.assertEqual(obj.to, "you") assert obj.to == "you"
self.assertEqual(obj.subject, None) assert obj.subject is None
self.assertEqual(obj.body, None) assert obj.body is None
self.assertEqual(obj.content_type, None) assert obj.content_type is None
Email.drop_collection() Email.drop_collection()
@ -355,11 +356,11 @@ class TestOnlyExcludeAll(unittest.TestCase):
.all_fields() .all_fields()
.get() .get()
) )
self.assertEqual(obj.sender, "me") assert obj.sender == "me"
self.assertEqual(obj.to, "you") assert obj.to == "you"
self.assertEqual(obj.subject, "From Russia with Love") assert obj.subject == "From Russia with Love"
self.assertEqual(obj.body, "Hello!") assert obj.body == "Hello!"
self.assertEqual(obj.content_type, "text/plain") assert obj.content_type == "text/plain"
Email.drop_collection() Email.drop_collection()
@ -377,27 +378,27 @@ class TestOnlyExcludeAll(unittest.TestCase):
# first three # first three
numbers = Numbers.objects.fields(slice__n=3).get() numbers = Numbers.objects.fields(slice__n=3).get()
self.assertEqual(numbers.n, [0, 1, 2]) assert numbers.n == [0, 1, 2]
# last three # last three
numbers = Numbers.objects.fields(slice__n=-3).get() 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 # skip 2, limit 3
numbers = Numbers.objects.fields(slice__n=[2, 3]).get() 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 # skip to fifth from last, limit 4
numbers = Numbers.objects.fields(slice__n=[-5, 4]).get() 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 # skip to fifth from last, limit 10
numbers = Numbers.objects.fields(slice__n=[-5, 10]).get() 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 # skip to fifth from last, limit 10 dict method
numbers = Numbers.objects.fields(n={"$slice": [-5, 10]}).get() 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): def test_slicing_nested_fields(self):
"""Ensure that query slicing an embedded array works. """Ensure that query slicing an embedded array works.
@ -417,27 +418,27 @@ class TestOnlyExcludeAll(unittest.TestCase):
# first three # first three
numbers = Numbers.objects.fields(slice__embedded__n=3).get() 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 # last three
numbers = Numbers.objects.fields(slice__embedded__n=-3).get() 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 # skip 2, limit 3
numbers = Numbers.objects.fields(slice__embedded__n=[2, 3]).get() 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 # skip to fifth from last, limit 4
numbers = Numbers.objects.fields(slice__embedded__n=[-5, 4]).get() 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 # skip to fifth from last, limit 10
numbers = Numbers.objects.fields(slice__embedded__n=[-5, 10]).get() 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 # skip to fifth from last, limit 10 dict method
numbers = Numbers.objects.fields(embedded__n={"$slice": [-5, 10]}).get() 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): def test_exclude_from_subclasses_docs(self):
class Base(Document): class Base(Document):
@ -456,9 +457,10 @@ class TestOnlyExcludeAll(unittest.TestCase):
User(username="mongodb", password="secret").save() User(username="mongodb", password="secret").save()
user = Base.objects().exclude("password", "wibble").first() 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__": if __name__ == "__main__":

View File

@ -48,14 +48,14 @@ class TestGeoQueries(MongoDBTestCase):
# note that "near" will show the san francisco event, too, # note that "near" will show the san francisco event, too,
# although it sorts to last. # although it sorts to last.
events = self.Event.objects(location__near=[-87.67892, 41.9120459]) events = self.Event.objects(location__near=[-87.67892, 41.9120459])
self.assertEqual(events.count(), 3) assert events.count() == 3
self.assertEqual(list(events), [event1, event3, event2]) assert list(events) == [event1, event3, event2]
# ensure ordering is respected by "near" # ensure ordering is respected by "near"
events = self.Event.objects(location__near=[-87.67892, 41.9120459]) events = self.Event.objects(location__near=[-87.67892, 41.9120459])
events = events.order_by("-date") events = events.order_by("-date")
self.assertEqual(events.count(), 3) assert events.count() == 3
self.assertEqual(list(events), [event3, event1, event2]) assert list(events) == [event3, event1, event2]
def test_near_and_max_distance(self): def test_near_and_max_distance(self):
"""Ensure the "max_distance" operator works alongside the "near" """Ensure the "max_distance" operator works alongside the "near"
@ -66,8 +66,8 @@ class TestGeoQueries(MongoDBTestCase):
# find events within 10 degrees of san francisco # find events within 10 degrees of san francisco
point = [-122.415579, 37.7566023] point = [-122.415579, 37.7566023]
events = self.Event.objects(location__near=point, location__max_distance=10) events = self.Event.objects(location__near=point, location__max_distance=10)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0], event2) assert events[0] == event2
def test_near_and_min_distance(self): def test_near_and_min_distance(self):
"""Ensure the "min_distance" operator works alongside the "near" """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 # find events at least 10 degrees away of san francisco
point = [-122.415579, 37.7566023] point = [-122.415579, 37.7566023]
events = self.Event.objects(location__near=point, location__min_distance=10) 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): def test_within_distance(self):
"""Make sure the "within_distance" operator works.""" """Make sure the "within_distance" operator works."""
@ -87,29 +87,29 @@ class TestGeoQueries(MongoDBTestCase):
# find events within 5 degrees of pitchfork office, chicago # find events within 5 degrees of pitchfork office, chicago
point_and_distance = [[-87.67892, 41.9120459], 5] point_and_distance = [[-87.67892, 41.9120459], 5]
events = self.Event.objects(location__within_distance=point_and_distance) events = self.Event.objects(location__within_distance=point_and_distance)
self.assertEqual(events.count(), 2) assert events.count() == 2
events = list(events) events = list(events)
self.assertNotIn(event2, events) assert event2 not in events
self.assertIn(event1, events) assert event1 in events
self.assertIn(event3, events) assert event3 in events
# find events within 10 degrees of san francisco # find events within 10 degrees of san francisco
point_and_distance = [[-122.415579, 37.7566023], 10] point_and_distance = [[-122.415579, 37.7566023], 10]
events = self.Event.objects(location__within_distance=point_and_distance) events = self.Event.objects(location__within_distance=point_and_distance)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0], event2) assert events[0] == event2
# find events within 1 degree of greenpoint, broolyn, nyc, ny # find events within 1 degree of greenpoint, broolyn, nyc, ny
point_and_distance = [[-73.9509714, 40.7237134], 1] point_and_distance = [[-73.9509714, 40.7237134], 1]
events = self.Event.objects(location__within_distance=point_and_distance) 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" # ensure ordering is respected by "within_distance"
point_and_distance = [[-87.67892, 41.9120459], 10] point_and_distance = [[-87.67892, 41.9120459], 10]
events = self.Event.objects(location__within_distance=point_and_distance) events = self.Event.objects(location__within_distance=point_and_distance)
events = events.order_by("-date") events = events.order_by("-date")
self.assertEqual(events.count(), 2) assert events.count() == 2
self.assertEqual(events[0], event3) assert events[0] == event3
def test_within_box(self): def test_within_box(self):
"""Ensure the "within_box" operator works.""" """Ensure the "within_box" operator works."""
@ -118,8 +118,8 @@ class TestGeoQueries(MongoDBTestCase):
# check that within_box works # check that within_box works
box = [(-125.0, 35.0), (-100.0, 40.0)] box = [(-125.0, 35.0), (-100.0, 40.0)]
events = self.Event.objects(location__within_box=box) events = self.Event.objects(location__within_box=box)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0].id, event2.id) assert events[0].id == event2.id
def test_within_polygon(self): def test_within_polygon(self):
"""Ensure the "within_polygon" operator works.""" """Ensure the "within_polygon" operator works."""
@ -133,8 +133,8 @@ class TestGeoQueries(MongoDBTestCase):
(-87.656164, 41.898061), (-87.656164, 41.898061),
] ]
events = self.Event.objects(location__within_polygon=polygon) events = self.Event.objects(location__within_polygon=polygon)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0].id, event1.id) assert events[0].id == event1.id
polygon2 = [ polygon2 = [
(-1.742249, 54.033586), (-1.742249, 54.033586),
@ -142,7 +142,7 @@ class TestGeoQueries(MongoDBTestCase):
(-4.40094, 53.389881), (-4.40094, 53.389881),
] ]
events = self.Event.objects(location__within_polygon=polygon2) events = self.Event.objects(location__within_polygon=polygon2)
self.assertEqual(events.count(), 0) assert events.count() == 0
def test_2dsphere_near(self): def test_2dsphere_near(self):
"""Make sure the "near" operator works with a PointField, which """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, # note that "near" will show the san francisco event, too,
# although it sorts to last. # although it sorts to last.
events = self.Event.objects(location__near=[-87.67892, 41.9120459]) events = self.Event.objects(location__near=[-87.67892, 41.9120459])
self.assertEqual(events.count(), 3) assert events.count() == 3
self.assertEqual(list(events), [event1, event3, event2]) assert list(events) == [event1, event3, event2]
# ensure ordering is respected by "near" # ensure ordering is respected by "near"
events = self.Event.objects(location__near=[-87.67892, 41.9120459]) events = self.Event.objects(location__near=[-87.67892, 41.9120459])
events = events.order_by("-date") events = events.order_by("-date")
self.assertEqual(events.count(), 3) assert events.count() == 3
self.assertEqual(list(events), [event3, event1, event2]) assert list(events) == [event3, event1, event2]
def test_2dsphere_near_and_max_distance(self): def test_2dsphere_near_and_max_distance(self):
"""Ensure the "max_distance" operator works alongside the "near" """Ensure the "max_distance" operator works alongside the "near"
@ -172,21 +172,21 @@ class TestGeoQueries(MongoDBTestCase):
# find events within 10km of san francisco # find events within 10km of san francisco
point = [-122.415579, 37.7566023] point = [-122.415579, 37.7566023]
events = self.Event.objects(location__near=point, location__max_distance=10000) events = self.Event.objects(location__near=point, location__max_distance=10000)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0], event2) assert events[0] == event2
# find events within 1km of greenpoint, broolyn, nyc, ny # find events within 1km of greenpoint, broolyn, nyc, ny
events = self.Event.objects( events = self.Event.objects(
location__near=[-73.9509714, 40.7237134], location__max_distance=1000 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" # ensure ordering is respected by "near"
events = self.Event.objects( events = self.Event.objects(
location__near=[-87.67892, 41.9120459], location__max_distance=10000 location__near=[-87.67892, 41.9120459], location__max_distance=10000
).order_by("-date") ).order_by("-date")
self.assertEqual(events.count(), 2) assert events.count() == 2
self.assertEqual(events[0], event3) assert events[0] == event3
def test_2dsphere_geo_within_box(self): def test_2dsphere_geo_within_box(self):
"""Ensure the "geo_within_box" operator works with a 2dsphere """Ensure the "geo_within_box" operator works with a 2dsphere
@ -197,8 +197,8 @@ class TestGeoQueries(MongoDBTestCase):
# check that within_box works # check that within_box works
box = [(-125.0, 35.0), (-100.0, 40.0)] box = [(-125.0, 35.0), (-100.0, 40.0)]
events = self.Event.objects(location__geo_within_box=box) events = self.Event.objects(location__geo_within_box=box)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0].id, event2.id) assert events[0].id == event2.id
def test_2dsphere_geo_within_polygon(self): def test_2dsphere_geo_within_polygon(self):
"""Ensure the "geo_within_polygon" operator works with a """Ensure the "geo_within_polygon" operator works with a
@ -214,8 +214,8 @@ class TestGeoQueries(MongoDBTestCase):
(-87.656164, 41.898061), (-87.656164, 41.898061),
] ]
events = self.Event.objects(location__geo_within_polygon=polygon) events = self.Event.objects(location__geo_within_polygon=polygon)
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0].id, event1.id) assert events[0].id == event1.id
polygon2 = [ polygon2 = [
(-1.742249, 54.033586), (-1.742249, 54.033586),
@ -223,7 +223,7 @@ class TestGeoQueries(MongoDBTestCase):
(-4.40094, 53.389881), (-4.40094, 53.389881),
] ]
events = self.Event.objects(location__geo_within_polygon=polygon2) 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): def test_2dsphere_near_and_min_max_distance(self):
"""Ensure "min_distace" and "max_distance" operators work well """Ensure "min_distace" and "max_distance" operators work well
@ -237,15 +237,15 @@ class TestGeoQueries(MongoDBTestCase):
location__min_distance=1000, location__min_distance=1000,
location__max_distance=10000, location__max_distance=10000,
).order_by("-date") ).order_by("-date")
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0], event3) assert events[0] == event3
# ensure ordering is respected by "near" with "min_distance" # ensure ordering is respected by "near" with "min_distance"
events = self.Event.objects( events = self.Event.objects(
location__near=[-87.67892, 41.9120459], location__min_distance=10000 location__near=[-87.67892, 41.9120459], location__min_distance=10000
).order_by("-date") ).order_by("-date")
self.assertEqual(events.count(), 1) assert events.count() == 1
self.assertEqual(events[0], event2) assert events[0] == event2
def test_2dsphere_geo_within_center(self): def test_2dsphere_geo_within_center(self):
"""Make sure the "geo_within_center" operator works with a """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 # find events within 5 degrees of pitchfork office, chicago
point_and_distance = [[-87.67892, 41.9120459], 2] point_and_distance = [[-87.67892, 41.9120459], 2]
events = self.Event.objects(location__geo_within_center=point_and_distance) events = self.Event.objects(location__geo_within_center=point_and_distance)
self.assertEqual(events.count(), 2) assert events.count() == 2
events = list(events) events = list(events)
self.assertNotIn(event2, events) assert event2 not in events
self.assertIn(event1, events) assert event1 in events
self.assertIn(event3, events) assert event3 in events
def _test_embedded(self, point_field_class): def _test_embedded(self, point_field_class):
"""Helper test method ensuring given point field class works """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, # note that "near" will show the san francisco event, too,
# although it sorts to last. # although it sorts to last.
events = Event.objects(venue__location__near=[-87.67892, 41.9120459]) events = Event.objects(venue__location__near=[-87.67892, 41.9120459])
self.assertEqual(events.count(), 3) assert events.count() == 3
self.assertEqual(list(events), [event1, event3, event2]) assert list(events) == [event1, event3, event2]
def test_geo_spatial_embedded(self): def test_geo_spatial_embedded(self):
"""Make sure GeoPointField works properly in an embedded document.""" """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 # Finds both points because they are within 60 km of the reference
# point equidistant between them. # point equidistant between them.
points = Point.objects(location__near_sphere=[-122, 37.5]) points = Point.objects(location__near_sphere=[-122, 37.5])
self.assertEqual(points.count(), 2) assert points.count() == 2
# Same behavior for _within_spherical_distance # Same behavior for _within_spherical_distance
points = Point.objects( points = Point.objects(
location__within_spherical_distance=[[-122, 37.5], 60 / earth_radius] location__within_spherical_distance=[[-122, 37.5], 60 / earth_radius]
) )
self.assertEqual(points.count(), 2) assert points.count() == 2
points = Point.objects( points = Point.objects(
location__near_sphere=[-122, 37.5], location__max_distance=60 / earth_radius 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 # Test query works with max_distance, being farer from one point
points = Point.objects( points = Point.objects(
location__near_sphere=[-122, 37.8], location__max_distance=60 / earth_radius location__near_sphere=[-122, 37.8], location__max_distance=60 / earth_radius
) )
close_point = points.first() close_point = points.first()
self.assertEqual(points.count(), 1) assert points.count() == 1
# Test query works with min_distance, being farer from one point # Test query works with min_distance, being farer from one point
points = Point.objects( points = Point.objects(
location__near_sphere=[-122, 37.8], location__min_distance=60 / earth_radius 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() 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 # Finds both points, but orders the north point first because it's
# closer to the reference point to the north. # closer to the reference point to the north.
points = Point.objects(location__near_sphere=[-122, 38.5]) points = Point.objects(location__near_sphere=[-122, 38.5])
self.assertEqual(points.count(), 2) assert points.count() == 2
self.assertEqual(points[0].id, north_point.id) assert points[0].id == north_point.id
self.assertEqual(points[1].id, south_point.id) assert points[1].id == south_point.id
# Finds both points, but orders the south point first because it's # Finds both points, but orders the south point first because it's
# closer to the reference point to the south. # closer to the reference point to the south.
points = Point.objects(location__near_sphere=[-122, 36.5]) points = Point.objects(location__near_sphere=[-122, 36.5])
self.assertEqual(points.count(), 2) assert points.count() == 2
self.assertEqual(points[0].id, south_point.id) assert points[0].id == south_point.id
self.assertEqual(points[1].id, north_point.id) assert points[1].id == north_point.id
# Finds only one point because only the first point is within 60km of # Finds only one point because only the first point is within 60km of
# the reference point to the south. # the reference point to the south.
points = Point.objects( points = Point.objects(
location__within_spherical_distance=[[-122, 36.5], 60 / earth_radius] location__within_spherical_distance=[[-122, 36.5], 60 / earth_radius]
) )
self.assertEqual(points.count(), 1) assert points.count() == 1
self.assertEqual(points[0].id, south_point.id) assert points[0].id == south_point.id
def test_linestring(self): def test_linestring(self):
class Road(Document): class Road(Document):
@ -381,13 +381,13 @@ class TestGeoQueries(MongoDBTestCase):
# near # near
point = {"type": "Point", "coordinates": [40, 5]} point = {"type": "Point", "coordinates": [40, 5]}
roads = Road.objects.filter(line__near=point["coordinates"]).count() roads = Road.objects.filter(line__near=point["coordinates"]).count()
self.assertEqual(1, roads) assert 1 == roads
roads = Road.objects.filter(line__near=point).count() roads = Road.objects.filter(line__near=point).count()
self.assertEqual(1, roads) assert 1 == roads
roads = Road.objects.filter(line__near={"$geometry": point}).count() roads = Road.objects.filter(line__near={"$geometry": point}).count()
self.assertEqual(1, roads) assert 1 == roads
# Within # Within
polygon = { polygon = {
@ -395,37 +395,37 @@ class TestGeoQueries(MongoDBTestCase):
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
} }
roads = Road.objects.filter(line__geo_within=polygon["coordinates"]).count() 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() 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() roads = Road.objects.filter(line__geo_within={"$geometry": polygon}).count()
self.assertEqual(1, roads) assert 1 == roads
# Intersects # Intersects
line = {"type": "LineString", "coordinates": [[40, 5], [40, 6]]} line = {"type": "LineString", "coordinates": [[40, 5], [40, 6]]}
roads = Road.objects.filter(line__geo_intersects=line["coordinates"]).count() 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() 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() roads = Road.objects.filter(line__geo_intersects={"$geometry": line}).count()
self.assertEqual(1, roads) assert 1 == roads
polygon = { polygon = {
"type": "Polygon", "type": "Polygon",
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
} }
roads = Road.objects.filter(line__geo_intersects=polygon["coordinates"]).count() 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() 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() roads = Road.objects.filter(line__geo_intersects={"$geometry": polygon}).count()
self.assertEqual(1, roads) assert 1 == roads
def test_polygon(self): def test_polygon(self):
class Road(Document): class Road(Document):
@ -439,13 +439,13 @@ class TestGeoQueries(MongoDBTestCase):
# near # near
point = {"type": "Point", "coordinates": [40, 5]} point = {"type": "Point", "coordinates": [40, 5]}
roads = Road.objects.filter(poly__near=point["coordinates"]).count() roads = Road.objects.filter(poly__near=point["coordinates"]).count()
self.assertEqual(1, roads) assert 1 == roads
roads = Road.objects.filter(poly__near=point).count() roads = Road.objects.filter(poly__near=point).count()
self.assertEqual(1, roads) assert 1 == roads
roads = Road.objects.filter(poly__near={"$geometry": point}).count() roads = Road.objects.filter(poly__near={"$geometry": point}).count()
self.assertEqual(1, roads) assert 1 == roads
# Within # Within
polygon = { polygon = {
@ -453,37 +453,37 @@ class TestGeoQueries(MongoDBTestCase):
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
} }
roads = Road.objects.filter(poly__geo_within=polygon["coordinates"]).count() 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() 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() roads = Road.objects.filter(poly__geo_within={"$geometry": polygon}).count()
self.assertEqual(1, roads) assert 1 == roads
# Intersects # Intersects
line = {"type": "LineString", "coordinates": [[40, 5], [41, 6]]} line = {"type": "LineString", "coordinates": [[40, 5], [41, 6]]}
roads = Road.objects.filter(poly__geo_intersects=line["coordinates"]).count() 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() 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() roads = Road.objects.filter(poly__geo_intersects={"$geometry": line}).count()
self.assertEqual(1, roads) assert 1 == roads
polygon = { polygon = {
"type": "Polygon", "type": "Polygon",
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]], "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]],
} }
roads = Road.objects.filter(poly__geo_intersects=polygon["coordinates"]).count() 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() 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() roads = Road.objects.filter(poly__geo_intersects={"$geometry": polygon}).count()
self.assertEqual(1, roads) assert 1 == roads
def test_aspymongo_with_only(self): def test_aspymongo_with_only(self):
"""Ensure as_pymongo works with only""" """Ensure as_pymongo works with only"""
@ -495,13 +495,10 @@ class TestGeoQueries(MongoDBTestCase):
p = Place(location=[24.946861267089844, 60.16311983618494]) p = Place(location=[24.946861267089844, 60.16311983618494])
p.save() p.save()
qs = Place.objects().only("location") qs = Place.objects().only("location")
self.assertDictEqual( assert qs.as_pymongo()[0]["location"] == {
qs.as_pymongo()[0]["location"], u"type": u"Point",
{ u"coordinates": [24.946861267089844, 60.16311983618494],
u"type": u"Point", }
u"coordinates": [24.946861267089844, 60.16311983618494],
},
)
def test_2dsphere_point_sets_correctly(self): def test_2dsphere_point_sets_correctly(self):
class Location(Document): class Location(Document):
@ -511,11 +508,11 @@ class TestGeoQueries(MongoDBTestCase):
Location(loc=[1, 2]).save() Location(loc=[1, 2]).save()
loc = Location.objects.as_pymongo()[0] 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]) Location.objects.update(set__loc=[2, 1])
loc = Location.objects.as_pymongo()[0] 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): def test_2dsphere_linestring_sets_correctly(self):
class Location(Document): class Location(Document):
@ -525,15 +522,11 @@ class TestGeoQueries(MongoDBTestCase):
Location(line=[[1, 2], [2, 2]]).save() Location(line=[[1, 2], [2, 2]]).save()
loc = Location.objects.as_pymongo()[0] loc = Location.objects.as_pymongo()[0]
self.assertEqual( assert loc["line"] == {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}
loc["line"], {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}
)
Location.objects.update(set__line=[[2, 1], [1, 2]]) Location.objects.update(set__line=[[2, 1], [1, 2]])
loc = Location.objects.as_pymongo()[0] loc = Location.objects.as_pymongo()[0]
self.assertEqual( assert loc["line"] == {"type": "LineString", "coordinates": [[2, 1], [1, 2]]}
loc["line"], {"type": "LineString", "coordinates": [[2, 1], [1, 2]]}
)
def test_geojson_PolygonField(self): def test_geojson_PolygonField(self):
class Location(Document): class Location(Document):
@ -543,17 +536,17 @@ class TestGeoQueries(MongoDBTestCase):
Location(poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]]).save() Location(poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]]).save()
loc = Location.objects.as_pymongo()[0] loc = Location.objects.as_pymongo()[0]
self.assertEqual( assert loc["poly"] == {
loc["poly"], "type": "Polygon",
{"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]}, "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
) }
Location.objects.update(set__poly=[[[40, 4], [40, 6], [41, 6], [40, 4]]]) Location.objects.update(set__poly=[[[40, 4], [40, 6], [41, 6], [40, 4]]])
loc = Location.objects.as_pymongo()[0] loc = Location.objects.as_pymongo()[0]
self.assertEqual( assert loc["poly"] == {
loc["poly"], "type": "Polygon",
{"type": "Polygon", "coordinates": [[[40, 4], [40, 6], [41, 6], [40, 4]]]}, "coordinates": [[[40, 4], [40, 6], [41, 6], [40, 4]]],
) }
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -14,14 +14,14 @@ class TestFindAndModify(unittest.TestCase):
Doc.drop_collection() Doc.drop_collection()
def assertDbEqual(self, docs): 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): def test_modify(self):
Doc(id=0, value=0).save() Doc(id=0, value=0).save()
doc = Doc(id=1, value=1).save() doc = Doc(id=1, value=1).save()
old_doc = Doc.objects(id=1).modify(set__value=-1) 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}]) self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
def test_modify_with_new(self): 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) new_doc = Doc.objects(id=1).modify(set__value=-1, new=True)
doc.value = -1 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}]) self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
def test_modify_not_existing(self): def test_modify_not_existing(self):
Doc(id=0, value=0).save() 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}]) self.assertDbEqual([{"_id": 0, "value": 0}])
def test_modify_with_upsert(self): def test_modify_with_upsert(self):
Doc(id=0, value=0).save() Doc(id=0, value=0).save()
old_doc = Doc.objects(id=1).modify(set__value=1, upsert=True) 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}]) self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": 1}])
def test_modify_with_upsert_existing(self): def test_modify_with_upsert_existing(self):
@ -49,13 +49,13 @@ class TestFindAndModify(unittest.TestCase):
doc = Doc(id=1, value=1).save() doc = Doc(id=1, value=1).save()
old_doc = Doc.objects(id=1).modify(set__value=-1, upsert=True) 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}]) self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
def test_modify_with_upsert_with_new(self): def test_modify_with_upsert_with_new(self):
Doc(id=0, value=0).save() Doc(id=0, value=0).save()
new_doc = Doc.objects(id=1).modify(upsert=True, new=True, set__value=1) 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}]) self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": 1}])
def test_modify_with_remove(self): def test_modify_with_remove(self):
@ -63,12 +63,12 @@ class TestFindAndModify(unittest.TestCase):
doc = Doc(id=1, value=1).save() doc = Doc(id=1, value=1).save()
old_doc = Doc.objects(id=1).modify(remove=True) 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}]) self.assertDbEqual([{"_id": 0, "value": 0}])
def test_find_and_modify_with_remove_not_existing(self): def test_find_and_modify_with_remove_not_existing(self):
Doc(id=0, value=0).save() 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}]) self.assertDbEqual([{"_id": 0, "value": 0}])
def test_modify_with_order_by(self): def test_modify_with_order_by(self):
@ -78,7 +78,7 @@ class TestFindAndModify(unittest.TestCase):
doc = Doc(id=3, value=0).save() doc = Doc(id=3, value=0).save()
old_doc = Doc.objects().order_by("-id").modify(set__value=-1) 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( self.assertDbEqual(
[ [
{"_id": 0, "value": 3}, {"_id": 0, "value": 3},
@ -93,7 +93,7 @@ class TestFindAndModify(unittest.TestCase):
Doc(id=1, value=1).save() Doc(id=1, value=1).save()
old_doc = Doc.objects(id=1).only("id").modify(set__value=-1) 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}]) self.assertDbEqual([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
def test_modify_with_push(self): def test_modify_with_push(self):
@ -106,23 +106,23 @@ class TestFindAndModify(unittest.TestCase):
# Push a new tag via modify with new=False (default). # Push a new tag via modify with new=False (default).
BlogPost(id=blog.id).modify(push__tags="code") BlogPost(id=blog.id).modify(push__tags="code")
self.assertEqual(blog.tags, []) assert blog.tags == []
blog.reload() blog.reload()
self.assertEqual(blog.tags, ["code"]) assert blog.tags == ["code"]
# Push a new tag via modify with new=True. # Push a new tag via modify with new=True.
blog = BlogPost.objects(id=blog.id).modify(push__tags="java", 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. # Push a new tag with a positional argument.
blog = BlogPost.objects(id=blog.id).modify(push__tags__0="python", new=True) 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. # Push multiple new tags with a positional argument.
blog = BlogPost.objects(id=blog.id).modify( blog = BlogPost.objects(id=blog.id).modify(
push__tags__1=["go", "rust"], new=True 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__": if __name__ == "__main__":

View File

@ -37,13 +37,13 @@ class TestQuerysetPickable(MongoDBTestCase):
loadedQs = self._get_loaded(qs) loadedQs = self._get_loaded(qs)
self.assertEqual(qs.count(), loadedQs.count()) assert qs.count() == loadedQs.count()
# can update loadedQs # can update loadedQs
loadedQs.update(age=23) loadedQs.update(age=23)
# check # check
self.assertEqual(Person.objects.first().age, 23) assert Person.objects.first().age == 23
def test_pickle_support_filtration(self): def test_pickle_support_filtration(self):
Person.objects.create(name="Alice", age=22) Person.objects.create(name="Alice", age=22)
@ -51,9 +51,9 @@ class TestQuerysetPickable(MongoDBTestCase):
Person.objects.create(name="Bob", age=23) Person.objects.create(name="Bob", age=23)
qs = Person.objects.filter(age__gte=22) qs = Person.objects.filter(age__gte=22)
self.assertEqual(qs.count(), 2) assert qs.count() == 2
loaded = self._get_loaded(qs) loaded = self._get_loaded(qs)
self.assertEqual(loaded.count(), 2) assert loaded.count() == 2
self.assertEqual(loaded.filter(name="Bob").first().age, 23) assert loaded.filter(name="Bob").first().age == 23

File diff suppressed because it is too large Load Diff

View 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()

View File

@ -1,6 +1,7 @@
import unittest import unittest
from bson.son import SON from bson.son import SON
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.queryset import Q, transform from mongoengine.queryset import Q, transform
@ -13,23 +14,16 @@ class TestTransform(unittest.TestCase):
def test_transform_query(self): def test_transform_query(self):
"""Ensure that the _transform_query function operates correctly. """Ensure that the _transform_query function operates correctly.
""" """
self.assertEqual( assert transform.query(name="test", age=30) == {"name": "test", "age": 30}
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) == {
self.assertEqual(transform.query(age__lt=30), {"age": {"$lt": 30}}) "age": {"$gt": 20, "$lt": 50}
self.assertEqual( }
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}]
self.assertEqual( }
transform.query(age=20, age__gt=50), assert transform.query(friend__age__gte=30) == {"friend.age": {"$gte": 30}}
{"$and": [{"age": {"$gt": 50}}, {"age": 20}]}, assert transform.query(name__exists=True) == {"name": {"$exists": True}}
)
self.assertEqual(
transform.query(friend__age__gte=30), {"friend.age": {"$gte": 30}}
)
self.assertEqual(
transform.query(name__exists=True), {"name": {"$exists": True}}
)
def test_transform_update(self): def test_transform_update(self):
class LisDoc(Document): class LisDoc(Document):
@ -54,17 +48,17 @@ class TestTransform(unittest.TestCase):
("push", "$push"), ("push", "$push"),
): ):
update = transform.update(DicDoc, **{"%s__dictField__test" % k: doc}) 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 special cases
update = transform.update(DicDoc, unset__dictField__test=doc) 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) 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"]) 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): def test_transform_update_push(self):
"""Ensure the differences in behvaior between 'push' and 'push_all'""" """Ensure the differences in behvaior between 'push' and 'push_all'"""
@ -73,10 +67,10 @@ class TestTransform(unittest.TestCase):
tags = ListField(StringField()) tags = ListField(StringField())
update = transform.update(BlogPost, push__tags=["mongo", "db"]) 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"]) 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): def test_transform_update_no_operator_default_to_set(self):
"""Ensure the differences in behvaior between 'push' and 'push_all'""" """Ensure the differences in behvaior between 'push' and 'push_all'"""
@ -85,7 +79,7 @@ class TestTransform(unittest.TestCase):
tags = ListField(StringField()) tags = ListField(StringField())
update = transform.update(BlogPost, tags=["mongo", "db"]) 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): def test_query_field_name(self):
"""Ensure that the correct field name is used when querying. """Ensure that the correct field name is used when querying.
@ -106,18 +100,18 @@ class TestTransform(unittest.TestCase):
post = BlogPost(**data) post = BlogPost(**data)
post.save() post.save()
self.assertIn("postTitle", BlogPost.objects(title=data["title"])._query) assert "postTitle" in BlogPost.objects(title=data["title"])._query
self.assertFalse("title" in BlogPost.objects(title=data["title"])._query) assert not ("title" in BlogPost.objects(title=data["title"])._query)
self.assertEqual(BlogPost.objects(title=data["title"]).count(), 1) assert BlogPost.objects(title=data["title"]).count() == 1
self.assertIn("_id", BlogPost.objects(pk=post.id)._query) assert "_id" in BlogPost.objects(pk=post.id)._query
self.assertEqual(BlogPost.objects(pk=post.id).count(), 1) assert BlogPost.objects(pk=post.id).count() == 1
self.assertIn( assert (
"postComments.commentContent", "postComments.commentContent"
BlogPost.objects(comments__content="test")._query, 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() BlogPost.drop_collection()
@ -135,9 +129,9 @@ class TestTransform(unittest.TestCase):
post = BlogPost(**data) post = BlogPost(**data)
post.save() post.save()
self.assertIn("_id", BlogPost.objects(pk=data["title"])._query) assert "_id" in BlogPost.objects(pk=data["title"])._query
self.assertIn("_id", BlogPost.objects(title=data["title"])._query) assert "_id" in BlogPost.objects(title=data["title"])._query
self.assertEqual(BlogPost.objects(pk=data["title"]).count(), 1) assert BlogPost.objects(pk=data["title"]).count() == 1
BlogPost.drop_collection() BlogPost.drop_collection()
@ -163,7 +157,7 @@ class TestTransform(unittest.TestCase):
q2 = B.objects.filter(a__in=[a1, a2]) q2 = B.objects.filter(a__in=[a1, a2])
q2 = q2.filter(a=a1)._query q2 = q2.filter(a=a1)._query
self.assertEqual(q1, q2) assert q1 == q2
def test_raw_query_and_Q_objects(self): def test_raw_query_and_Q_objects(self):
""" """
@ -179,11 +173,11 @@ class TestTransform(unittest.TestCase):
meta = {"allow_inheritance": False} meta = {"allow_inheritance": False}
query = Foo.objects(__raw__={"$nor": [{"name": "bar"}]})._query 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}]} q1 = {"$or": [{"a": 1}, {"b": 1}]}
query = Foo.objects(Q(__raw__=q1) & Q(c=1))._query 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): def test_raw_and_merging(self):
class Doc(Document): class Doc(Document):
@ -200,51 +194,39 @@ class TestTransform(unittest.TestCase):
} }
)._query )._query
self.assertEqual( assert raw_query == {
raw_query, "deleted": False,
{ "scraped": "yes",
"deleted": False, "$nor": [{"views.extracted": "no"}, {"attachments.views.extracted": "no"}],
"scraped": "yes", }
"$nor": [
{"views.extracted": "no"},
{"attachments.views.extracted": "no"},
],
},
)
def test_geojson_PointField(self): def test_geojson_PointField(self):
class Location(Document): class Location(Document):
loc = PointField() loc = PointField()
update = transform.update(Location, set__loc=[1, 2]) update = transform.update(Location, set__loc=[1, 2])
self.assertEqual( assert update == {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}}
update, {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}}
)
update = transform.update( update = transform.update(
Location, set__loc={"type": "Point", "coordinates": [1, 2]} Location, set__loc={"type": "Point", "coordinates": [1, 2]}
) )
self.assertEqual( assert update == {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}}
update, {"$set": {"loc": {"type": "Point", "coordinates": [1, 2]}}}
)
def test_geojson_LineStringField(self): def test_geojson_LineStringField(self):
class Location(Document): class Location(Document):
line = LineStringField() line = LineStringField()
update = transform.update(Location, set__line=[[1, 2], [2, 2]]) update = transform.update(Location, set__line=[[1, 2], [2, 2]])
self.assertEqual( assert update == {
update, "$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}
{"$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}}, }
)
update = transform.update( update = transform.update(
Location, set__line={"type": "LineString", "coordinates": [[1, 2], [2, 2]]} Location, set__line={"type": "LineString", "coordinates": [[1, 2], [2, 2]]}
) )
self.assertEqual( assert update == {
update, "$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}
{"$set": {"line": {"type": "LineString", "coordinates": [[1, 2], [2, 2]]}}}, }
)
def test_geojson_PolygonField(self): def test_geojson_PolygonField(self):
class Location(Document): class Location(Document):
@ -253,17 +235,14 @@ class TestTransform(unittest.TestCase):
update = transform.update( update = transform.update(
Location, set__poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]] Location, set__poly=[[[40, 5], [40, 6], [41, 6], [40, 5]]]
) )
self.assertEqual( assert update == {
update, "$set": {
{ "poly": {
"$set": { "type": "Polygon",
"poly": { "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
"type": "Polygon",
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
}
} }
}, }
) }
update = transform.update( update = transform.update(
Location, Location,
@ -272,17 +251,14 @@ class TestTransform(unittest.TestCase):
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]], "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
}, },
) )
self.assertEqual( assert update == {
update, "$set": {
{ "poly": {
"$set": { "type": "Polygon",
"poly": { "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
"type": "Polygon",
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]],
}
} }
}, }
) }
def test_type(self): def test_type(self):
class Doc(Document): class Doc(Document):
@ -291,10 +267,10 @@ class TestTransform(unittest.TestCase):
Doc(df=True).save() Doc(df=True).save()
Doc(df=7).save() Doc(df=7).save()
Doc(df="df").save() Doc(df="df").save()
self.assertEqual(Doc.objects(df__type=1).count(), 0) # double assert Doc.objects(df__type=1).count() == 0 # double
self.assertEqual(Doc.objects(df__type=8).count(), 1) # bool assert Doc.objects(df__type=8).count() == 1 # bool
self.assertEqual(Doc.objects(df__type=2).count(), 1) # str assert Doc.objects(df__type=2).count() == 1 # str
self.assertEqual(Doc.objects(df__type=16).count(), 1) # int assert Doc.objects(df__type=16).count() == 1 # int
def test_last_field_name_like_operator(self): def test_last_field_name_like_operator(self):
class EmbeddedItem(EmbeddedDocument): class EmbeddedItem(EmbeddedDocument):
@ -309,12 +285,12 @@ class TestTransform(unittest.TestCase):
doc = Doc(item=EmbeddedItem(type="axe", name="Heroic axe")) doc = Doc(item=EmbeddedItem(type="axe", name="Heroic axe"))
doc.save() doc.save()
self.assertEqual(1, Doc.objects(item__type__="axe").count()) assert 1 == Doc.objects(item__type__="axe").count()
self.assertEqual(1, Doc.objects(item__name__="Heroic axe").count()) assert 1 == Doc.objects(item__name__="Heroic axe").count()
Doc.objects(id=doc.id).update(set__item__type__="sword") Doc.objects(id=doc.id).update(set__item__type__="sword")
self.assertEqual(1, Doc.objects(item__type__="sword").count()) assert 1 == Doc.objects(item__type__="sword").count()
self.assertEqual(0, Doc.objects(item__type__="axe").count()) assert 0 == Doc.objects(item__type__="axe").count()
def test_understandable_error_raised(self): def test_understandable_error_raised(self):
class Event(Document): class Event(Document):
@ -324,7 +300,7 @@ class TestTransform(unittest.TestCase):
box = [(35.0, -125.0), (40.0, -100.0)] box = [(35.0, -125.0), (40.0, -100.0)]
# I *meant* to execute location__within_box=box # I *meant* to execute location__within_box=box
events = Event.objects(location__within=box) events = Event.objects(location__within=box)
with self.assertRaises(InvalidQueryError): with pytest.raises(InvalidQueryError):
events.count() events.count()
def test_update_pull_for_list_fields(self): def test_update_pull_for_list_fields(self):
@ -347,24 +323,20 @@ class TestTransform(unittest.TestCase):
word = Word(word="abc", index=1) word = Word(word="abc", index=1)
update = transform.update(MainDoc, pull__content__text=word) update = transform.update(MainDoc, pull__content__text=word)
self.assertEqual( assert update == {
update, {"$pull": {"content.text": SON([("word", u"abc"), ("index", 1)])}} "$pull": {"content.text": SON([("word", u"abc"), ("index", 1)])}
) }
update = transform.update(MainDoc, pull__content__heading="xyz") 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"]) update = transform.update(MainDoc, pull__content__text__word__in=["foo", "bar"])
self.assertEqual( assert update == {"$pull": {"content.text": {"word": {"$in": ["foo", "bar"]}}}}
update, {"$pull": {"content.text": {"word": {"$in": ["foo", "bar"]}}}}
)
update = transform.update( update = transform.update(
MainDoc, pull__content__text__word__nin=["foo", "bar"] MainDoc, pull__content__text__word__nin=["foo", "bar"]
) )
self.assertEqual( assert update == {"$pull": {"content.text": {"word": {"$nin": ["foo", "bar"]}}}}
update, {"$pull": {"content.text": {"word": {"$nin": ["foo", "bar"]}}}}
)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -3,6 +3,7 @@ import re
import unittest import unittest
from bson import ObjectId from bson import ObjectId
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.errors import InvalidQueryError from mongoengine.errors import InvalidQueryError
@ -35,10 +36,10 @@ class TestQ(unittest.TestCase):
age = IntField() age = IntField()
query = {"$or": [{"age": {"$gte": 18}}, {"name": "test"}]} 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"} 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): def test_q_with_dbref(self):
"""Ensure Q objects handle DBRefs correctly""" """Ensure Q objects handle DBRefs correctly"""
@ -53,8 +54,8 @@ class TestQ(unittest.TestCase):
user = User.objects.create() user = User.objects.create()
Post.objects.create(created_user=user) Post.objects.create(created_user=user)
self.assertEqual(Post.objects.filter(created_user=user).count(), 1) assert Post.objects.filter(created_user=user).count() == 1
self.assertEqual(Post.objects.filter(Q(created_user=user)).count(), 1) assert Post.objects.filter(Q(created_user=user)).count() == 1
def test_and_combination(self): def test_and_combination(self):
"""Ensure that Q-objects correctly AND together. """Ensure that Q-objects correctly AND together.
@ -65,12 +66,10 @@ class TestQ(unittest.TestCase):
y = StringField() y = StringField()
query = (Q(x__lt=7) & Q(x__lt=3)).to_query(TestDoc) 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) query = (Q(y="a") & Q(x__lt=7) & Q(x__lt=3)).to_query(TestDoc)
self.assertEqual( assert query == {"$and": [{"y": "a"}, {"x": {"$lt": 7}}, {"x": {"$lt": 3}}]}
query, {"$and": [{"y": "a"}, {"x": {"$lt": 7}}, {"x": {"$lt": 3}}]}
)
# Check normal cases work without an error # Check normal cases work without an error
query = Q(x__lt=7) & Q(x__gt=3) query = Q(x__lt=7) & Q(x__gt=3)
@ -78,7 +77,7 @@ class TestQ(unittest.TestCase):
q1 = Q(x__lt=7) q1 = Q(x__lt=7)
q2 = Q(x__gt=3) q2 = Q(x__gt=3)
query = (q1 & q2).to_query(TestDoc) 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 # More complex nested example
query = Q(x__lt=100) & Q(y__ne="NotMyString") query = Q(x__lt=100) & Q(y__ne="NotMyString")
@ -87,7 +86,7 @@ class TestQ(unittest.TestCase):
"x": {"$lt": 100, "$gt": -100}, "x": {"$lt": 100, "$gt": -100},
"y": {"$ne": "NotMyString", "$in": ["a", "b", "c"]}, "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): def test_or_combination(self):
"""Ensure that Q-objects correctly OR together. """Ensure that Q-objects correctly OR together.
@ -99,7 +98,7 @@ class TestQ(unittest.TestCase):
q1 = Q(x__lt=3) q1 = Q(x__lt=3)
q2 = Q(x__gt=7) q2 = Q(x__gt=7)
query = (q1 | q2).to_query(TestDoc) 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): def test_and_or_combination(self):
"""Ensure that Q-objects handle ANDing ORed components. """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__gt=0) | Q(x__exists=False)
query &= Q(x__lt=100) query &= Q(x__lt=100)
self.assertEqual( assert query.to_query(TestDoc) == {
query.to_query(TestDoc), "$and": [
{ {"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]},
"$and": [ {"x": {"$lt": 100}},
{"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]}, ]
{"x": {"$lt": 100}}, }
]
},
)
q1 = Q(x__gt=0) | Q(x__exists=False) q1 = Q(x__gt=0) | Q(x__exists=False)
q2 = Q(x__lt=100) | Q(y=True) q2 = Q(x__lt=100) | Q(y=True)
@ -131,16 +127,13 @@ class TestQ(unittest.TestCase):
TestDoc(x=10).save() TestDoc(x=10).save()
TestDoc(y=True).save() TestDoc(y=True).save()
self.assertEqual( assert query == {
query, "$and": [
{ {"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]},
"$and": [ {"$or": [{"x": {"$lt": 100}}, {"y": True}]},
{"$or": [{"x": {"$gt": 0}}, {"x": {"$exists": False}}]}, ]
{"$or": [{"x": {"$lt": 100}}, {"y": True}]}, }
] assert 2 == TestDoc.objects(q1 & q2).count()
},
)
self.assertEqual(2, TestDoc.objects(q1 & q2).count())
def test_or_and_or_combination(self): def test_or_and_or_combination(self):
"""Ensure that Q-objects handle ORing ANDed ORed components. :) """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)) q2 = Q(x__lt=100) & (Q(y=False) | Q(y__exists=False))
query = (q1 | q2).to_query(TestDoc) query = (q1 | q2).to_query(TestDoc)
self.assertEqual( assert query == {
query, "$or": [
{ {
"$or": [ "$and": [
{ {"x": {"$gt": 0}},
"$and": [ {"$or": [{"y": True}, {"y": {"$exists": False}}]},
{"x": {"$gt": 0}}, ]
{"$or": [{"y": True}, {"y": {"$exists": False}}]}, },
] {
}, "$and": [
{ {"x": {"$lt": 100}},
"$and": [ {"$or": [{"y": False}, {"y": {"$exists": False}}]},
{"x": {"$lt": 100}}, ]
{"$or": [{"y": False}, {"y": {"$exists": False}}]}, },
] ]
}, }
] assert 2 == TestDoc.objects(q1 | q2).count()
},
)
self.assertEqual(2, TestDoc.objects(q1 | q2).count())
def test_multiple_occurence_in_field(self): def test_multiple_occurence_in_field(self):
class Test(Document): class Test(Document):
@ -192,8 +182,8 @@ class TestQ(unittest.TestCase):
q3 = q1 & q2 q3 = q1 & q2
query = q3.to_query(Test) query = q3.to_query(Test)
self.assertEqual(query["$and"][0], q1.to_query(Test)) assert query["$and"][0] == q1.to_query(Test)
self.assertEqual(query["$and"][1], q2.to_query(Test)) assert query["$and"][1] == q2.to_query(Test)
def test_q_clone(self): def test_q_clone(self):
class TestDoc(Document): class TestDoc(Document):
@ -207,15 +197,15 @@ class TestQ(unittest.TestCase):
# Check normal cases work without an error # Check normal cases work without an error
test = TestDoc.objects(Q(x__lt=7) & Q(x__gt=3)) test = TestDoc.objects(Q(x__lt=7) & Q(x__gt=3))
self.assertEqual(test.count(), 3) assert test.count() == 3
test2 = test.clone() test2 = test.clone()
self.assertEqual(test2.count(), 3) assert test2.count() == 3
self.assertNotEqual(test2, test) assert test2 != test
test3 = test2.filter(x=6) test3 = test2.filter(x=6)
self.assertEqual(test3.count(), 1) assert test3.count() == 1
self.assertEqual(test.count(), 3) assert test.count() == 3
def test_q(self): def test_q(self):
"""Ensure that Q objects may be used to query for documents. """Ensure that Q objects may be used to query for documents.
@ -252,19 +242,19 @@ class TestQ(unittest.TestCase):
# Check ObjectId lookup works # Check ObjectId lookup works
obj = BlogPost.objects(id=post1.id).first() obj = BlogPost.objects(id=post1.id).first()
self.assertEqual(obj, post1) assert obj == post1
# Check Q object combination with one does not exist # Check Q object combination with one does not exist
q = BlogPost.objects(Q(title="Test 5") | Q(published=True)) q = BlogPost.objects(Q(title="Test 5") | Q(published=True))
posts = [post.id for post in q] posts = [post.id for post in q]
published_posts = (post2, post3) 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)) q = BlogPost.objects(Q(title="Test 1") | Q(published=True))
posts = [post.id for post in q] posts = [post.id for post in q]
published_posts = (post1, post2, post3, post5, post6) 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 # Check Q object combination
date = datetime.datetime(2010, 1, 10) date = datetime.datetime(2010, 1, 10)
@ -272,9 +262,9 @@ class TestQ(unittest.TestCase):
posts = [post.id for post in q] posts = [post.id for post in q]
published_posts = (post1, post2, post3, post4) 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() BlogPost.drop_collection()
@ -284,15 +274,15 @@ class TestQ(unittest.TestCase):
self.Person(name="user3", age=30).save() self.Person(name="user3", age=30).save()
self.Person(name="user4", age=40).save() self.Person(name="user4", age=40).save()
self.assertEqual(self.Person.objects(Q(age__in=[20])).count(), 2) assert 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, 30])).count() == 3
# Test invalid query objs # Test invalid query objs
with self.assertRaises(InvalidQueryError): with pytest.raises(InvalidQueryError):
self.Person.objects("user1") self.Person.objects("user1")
# filter should fail, too # filter should fail, too
with self.assertRaises(InvalidQueryError): with pytest.raises(InvalidQueryError):
self.Person.objects.filter("user1") self.Person.objects.filter("user1")
def test_q_regex(self): def test_q_regex(self):
@ -302,31 +292,31 @@ class TestQ(unittest.TestCase):
person.save() person.save()
obj = self.Person.objects(Q(name=re.compile("^Gui"))).first() 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() 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() 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() 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() obj = self.Person.objects(Q(name__not=re.compile("^Gui"))).first()
self.assertEqual(obj, None) assert obj is None
def test_q_repr(self): def test_q_repr(self):
self.assertEqual(repr(Q()), "Q(**{})") assert repr(Q()) == "Q(**{})"
self.assertEqual(repr(Q(name="test")), "Q(**{'name': 'test'})") assert repr(Q(name="test")) == "Q(**{'name': 'test'})"
self.assertEqual( assert (
repr(Q(name="test") & Q(age__gte=18)), repr(Q(name="test") & Q(age__gte=18))
"(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))", == "(Q(**{'name': 'test'}) & Q(**{'age__gte': 18}))"
) )
self.assertEqual( assert (
repr(Q(name="test") | Q(age__gte=18)), repr(Q(name="test") | Q(age__gte=18))
"(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))", == "(Q(**{'name': 'test'}) | Q(**{'age__gte': 18}))"
) )
def test_q_lists(self): def test_q_lists(self):
@ -341,8 +331,8 @@ class TestQ(unittest.TestCase):
BlogPost(tags=["python", "mongo"]).save() BlogPost(tags=["python", "mongo"]).save()
BlogPost(tags=["python"]).save() BlogPost(tags=["python"]).save()
self.assertEqual(BlogPost.objects(Q(tags="mongo")).count(), 1) assert BlogPost.objects(Q(tags="mongo")).count() == 1
self.assertEqual(BlogPost.objects(Q(tags="python")).count(), 2) assert BlogPost.objects(Q(tags="python")).count() == 2
BlogPost.drop_collection() BlogPost.drop_collection()
@ -355,12 +345,12 @@ class TestQ(unittest.TestCase):
pk = ObjectId() pk = ObjectId()
User(email="example@example.com", pk=pk).save() User(email="example@example.com", pk=pk).save()
self.assertEqual( assert (
1, 1
User.objects.filter(Q(email="example@example.com") | Q(name="John Doe")) == User.objects.filter(Q(email="example@example.com") | Q(name="John Doe"))
.limit(2) .limit(2)
.filter(pk=pk) .filter(pk=pk)
.count(), .count()
) )
def test_chained_q_or_filtering(self): 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="c")]).save()
Item(postables=[Post(name="a"), Post(name="b"), Post(name="c")]).save() Item(postables=[Post(name="a"), Post(name="b"), Post(name="c")]).save()
self.assertEqual( assert (
Item.objects(Q(postables__name="a") & Q(postables__name="b")).count(), 2 Item.objects(Q(postables__name="a") & Q(postables__name="b")).count() == 2
) )
self.assertEqual( assert (
Item.objects.filter(postables__name="a") Item.objects.filter(postables__name="a").filter(postables__name="b").count()
.filter(postables__name="b") == 2
.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__": if __name__ == "__main__":
unittest.main() unittest.main()

9
tests/test_ci.py Normal file
View 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

View File

@ -1,14 +1,16 @@
import unittest import unittest
from mongoengine.common import _import_class import pytest
from mongoengine import Document from mongoengine import Document
from mongoengine.common import _import_class
class TestCommon(unittest.TestCase): class TestCommon:
def test__import_class(self): def test__import_class(self):
doc_cls = _import_class("Document") doc_cls = _import_class("Document")
self.assertIs(doc_cls, Document) assert doc_cls is Document
def test__import_class_raise_if_not_known(self): def test__import_class_raise_if_not_known(self):
with self.assertRaises(ValueError): with pytest.raises(ValueError):
_import_class("UnknownClass") _import_class("UnknownClass")

View File

@ -1,35 +1,32 @@
import datetime import datetime
from pymongo import MongoClient from bson.tz_util import utc
from pymongo.errors import OperationFailure, InvalidName import pymongo
from pymongo import ReadPreference
from mongoengine import Document from pymongo import MongoClient, ReadPreference
from pymongo.errors import InvalidName, OperationFailure
import pytest
try: try:
import unittest2 as unittest import unittest2 as unittest
except ImportError: except ImportError:
import unittest 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 import mongoengine.connection
from mongoengine import (
DateTimeField,
Document,
StringField,
connect,
disconnect_all,
register_connection,
)
from mongoengine.connection import ( from mongoengine.connection import (
ConnectionFailure, ConnectionFailure,
get_db,
get_connection,
disconnect,
DEFAULT_DATABASE_NAME, DEFAULT_DATABASE_NAME,
disconnect,
get_connection,
get_db,
) )
@ -37,6 +34,18 @@ def get_tz_awareness(connection):
return connection.codec_options.tz_aware 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): class ConnectionTest(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
@ -56,15 +65,15 @@ class ConnectionTest(unittest.TestCase):
connect("mongoenginetest") connect("mongoenginetest")
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
db = get_db() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "mongoenginetest") assert db.name == "mongoenginetest"
connect("mongoenginetest2", alias="testdb") connect("mongoenginetest2", alias="testdb")
conn = get_connection("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): def test_connect_disconnect_works_properly(self):
class History1(Document): class History1(Document):
@ -84,31 +93,27 @@ class ConnectionTest(unittest.TestCase):
h = History1(name="default").save() h = History1(name="default").save()
h1 = History2(name="db1").save() h1 = History2(name="db1").save()
self.assertEqual( assert list(History1.objects().as_pymongo()) == [
list(History1.objects().as_pymongo()), [{"_id": h.id, "name": "default"}] {"_id": h.id, "name": "default"}
) ]
self.assertEqual( assert list(History2.objects().as_pymongo()) == [{"_id": h1.id, "name": "db1"}]
list(History2.objects().as_pymongo()), [{"_id": h1.id, "name": "db1"}]
)
disconnect("db1") disconnect("db1")
disconnect("db2") disconnect("db2")
with self.assertRaises(ConnectionFailure): with pytest.raises(ConnectionFailure):
list(History1.objects().as_pymongo()) list(History1.objects().as_pymongo())
with self.assertRaises(ConnectionFailure): with pytest.raises(ConnectionFailure):
list(History2.objects().as_pymongo()) list(History2.objects().as_pymongo())
connect("db1", alias="db1") connect("db1", alias="db1")
connect("db2", alias="db2") connect("db2", alias="db2")
self.assertEqual( assert list(History1.objects().as_pymongo()) == [
list(History1.objects().as_pymongo()), [{"_id": h.id, "name": "default"}] {"_id": h.id, "name": "default"}
) ]
self.assertEqual( assert list(History2.objects().as_pymongo()) == [{"_id": h1.id, "name": "db1"}]
list(History2.objects().as_pymongo()), [{"_id": h1.id, "name": "db1"}]
)
def test_connect_different_documents_to_different_database(self): def test_connect_different_documents_to_different_database(self):
class History(Document): class History(Document):
@ -134,68 +139,64 @@ class ConnectionTest(unittest.TestCase):
h1 = History1(name="db1").save() h1 = History1(name="db1").save()
h2 = History2(name="db2").save() h2 = History2(name="db2").save()
self.assertEqual(History._collection.database.name, DEFAULT_DATABASE_NAME) assert History._collection.database.name == DEFAULT_DATABASE_NAME
self.assertEqual(History1._collection.database.name, "db1") assert History1._collection.database.name == "db1"
self.assertEqual(History2._collection.database.name, "db2") assert History2._collection.database.name == "db2"
self.assertEqual( assert list(History.objects().as_pymongo()) == [
list(History.objects().as_pymongo()), [{"_id": h.id, "name": "default"}] {"_id": h.id, "name": "default"}
) ]
self.assertEqual( assert list(History1.objects().as_pymongo()) == [{"_id": h1.id, "name": "db1"}]
list(History1.objects().as_pymongo()), [{"_id": h1.id, "name": "db1"}] assert list(History2.objects().as_pymongo()) == [{"_id": h2.id, "name": "db2"}]
)
self.assertEqual(
list(History2.objects().as_pymongo()), [{"_id": h2.id, "name": "db2"}]
)
def test_connect_fails_if_connect_2_times_with_default_alias(self): def test_connect_fails_if_connect_2_times_with_default_alias(self):
connect("mongoenginetest") connect("mongoenginetest")
with self.assertRaises(ConnectionFailure) as ctx_err: with pytest.raises(ConnectionFailure) as exc_info:
connect("mongoenginetest2") connect("mongoenginetest2")
self.assertEqual( assert (
"A different connection with alias `default` was already registered. Use disconnect() first", "A different connection with alias `default` was already registered. Use disconnect() first"
str(ctx_err.exception), == str(exc_info.value)
) )
def test_connect_fails_if_connect_2_times_with_custom_alias(self): def test_connect_fails_if_connect_2_times_with_custom_alias(self):
connect("mongoenginetest", alias="alias1") connect("mongoenginetest", alias="alias1")
with self.assertRaises(ConnectionFailure) as ctx_err: with pytest.raises(ConnectionFailure) as exc_info:
connect("mongoenginetest2", alias="alias1") connect("mongoenginetest2", alias="alias1")
self.assertEqual( assert (
"A different connection with alias `alias1` was already registered. Use disconnect() first", "A different connection with alias `alias1` was already registered. Use disconnect() first"
str(ctx_err.exception), == str(exc_info.value)
) )
def test_connect_fails_if_similar_connection_settings_arent_defined_the_same_way( def test_connect_fails_if_similar_connection_settings_arent_defined_the_same_way(
self self,
): ):
"""Intended to keep the detecton function simple but robust""" """Intended to keep the detecton function simple but robust"""
db_name = "mongoenginetest" db_name = "mongoenginetest"
db_alias = "alias1" db_alias = "alias1"
connect(db=db_name, alias=db_alias, host="localhost", port=27017) 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) connect(host="mongodb://localhost:27017/%s" % db_name, alias=db_alias)
def test_connect_passes_silently_connect_multiple_times_with_same_config(self): def test_connect_passes_silently_connect_multiple_times_with_same_config(self):
# test default connection to `test` # test default connection to `test`
connect() connect()
connect() connect()
self.assertEqual(len(mongoengine.connection._connections), 1) assert len(mongoengine.connection._connections) == 1
connect("test01", alias="test01") connect("test01", alias="test01")
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")
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): def test_connect_with_invalid_db_name(self):
"""Ensure that connect() method fails fast if db name is invalid """Ensure that connect() method fails fast if db name is invalid
""" """
with self.assertRaises(InvalidName): with pytest.raises(InvalidName):
connect("mongomock://localhost") connect("mongomock://localhost")
def test_connect_with_db_name_external(self): def test_connect_with_db_name_external(self):
@ -205,38 +206,34 @@ class ConnectionTest(unittest.TestCase):
connect("$external") connect("$external")
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
db = get_db() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "$external") assert db.name == "$external"
connect("$external", alias="testdb") connect("$external", alias="testdb")
conn = get_connection("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): def test_connect_with_invalid_db_name_type(self):
"""Ensure that connect() method fails fast if db name has invalid type """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"] non_string_db_name = ["e. g. list instead of a string"]
connect(non_string_db_name) connect(non_string_db_name)
@require_mongomock
def test_connect_in_mocking(self): def test_connect_in_mocking(self):
"""Ensure that the connect() method works properly in mocking. """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") connect("mongoenginetest", host="mongomock://localhost")
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect("mongoenginetest2", host="mongomock://localhost", alias="testdb2") connect("mongoenginetest2", host="mongomock://localhost", alias="testdb2")
conn = get_connection("testdb2") conn = get_connection("testdb2")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect( connect(
"mongoenginetest3", "mongoenginetest3",
@ -245,11 +242,11 @@ class ConnectionTest(unittest.TestCase):
alias="testdb3", alias="testdb3",
) )
conn = get_connection("testdb3") conn = get_connection("testdb3")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect("mongoenginetest4", is_mock=True, alias="testdb4") connect("mongoenginetest4", is_mock=True, alias="testdb4")
conn = get_connection("testdb4") conn = get_connection("testdb4")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect( connect(
host="mongodb://localhost:27017/mongoenginetest5", host="mongodb://localhost:27017/mongoenginetest5",
@ -257,11 +254,11 @@ class ConnectionTest(unittest.TestCase):
alias="testdb5", alias="testdb5",
) )
conn = get_connection("testdb5") conn = get_connection("testdb5")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect(host="mongomock://localhost:27017/mongoenginetest6", alias="testdb6") connect(host="mongomock://localhost:27017/mongoenginetest6", alias="testdb6")
conn = get_connection("testdb6") conn = get_connection("testdb6")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect( connect(
host="mongomock://localhost:27017/mongoenginetest7", host="mongomock://localhost:27017/mongoenginetest7",
@ -269,16 +266,12 @@ class ConnectionTest(unittest.TestCase):
alias="testdb7", alias="testdb7",
) )
conn = get_connection("testdb7") conn = get_connection("testdb7")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
@require_mongomock
def test_default_database_with_mocking(self): def test_default_database_with_mocking(self):
"""Ensure that the default database is correctly set when using mongomock. """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() disconnect_all()
class SomeDocument(Document): class SomeDocument(Document):
@ -288,37 +281,33 @@ class ConnectionTest(unittest.TestCase):
some_document = SomeDocument() some_document = SomeDocument()
# database won't exist until we save a document # database won't exist until we save a document
some_document.save() some_document.save()
self.assertEqual(conn.get_default_database().name, "mongoenginetest") assert conn.get_default_database().name == "mongoenginetest"
self.assertEqual(conn.database_names()[0], "mongoenginetest") assert conn.database_names()[0] == "mongoenginetest"
@require_mongomock
def test_connect_with_host_list(self): def test_connect_with_host_list(self):
"""Ensure that the connect() method works when host is a list """Ensure that the connect() method works when host is a list
Uses mongomock to test w/o needing multiple mongod/mongos processes 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"]) connect(host=["mongomock://localhost"])
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect(host=["mongodb://localhost"], is_mock=True, alias="testdb2") connect(host=["mongodb://localhost"], is_mock=True, alias="testdb2")
conn = get_connection("testdb2") conn = get_connection("testdb2")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect(host=["localhost"], is_mock=True, alias="testdb3") connect(host=["localhost"], is_mock=True, alias="testdb3")
conn = get_connection("testdb3") conn = get_connection("testdb3")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect( connect(
host=["mongomock://localhost:27017", "mongomock://localhost:27018"], host=["mongomock://localhost:27017", "mongomock://localhost:27018"],
alias="testdb4", alias="testdb4",
) )
conn = get_connection("testdb4") conn = get_connection("testdb4")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect( connect(
host=["mongodb://localhost:27017", "mongodb://localhost:27018"], host=["mongodb://localhost:27017", "mongodb://localhost:27018"],
@ -326,13 +315,13 @@ class ConnectionTest(unittest.TestCase):
alias="testdb5", alias="testdb5",
) )
conn = get_connection("testdb5") conn = get_connection("testdb5")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
connect( connect(
host=["localhost:27017", "localhost:27018"], is_mock=True, alias="testdb6" host=["localhost:27017", "localhost:27018"], is_mock=True, alias="testdb6"
) )
conn = get_connection("testdb6") conn = get_connection("testdb6")
self.assertIsInstance(conn, mongomock.MongoClient) assert isinstance(conn, mongomock.MongoClient)
def test_disconnect_cleans_globals(self): def test_disconnect_cleans_globals(self):
"""Ensure that the disconnect() method cleans the globals objects""" """Ensure that the disconnect() method cleans the globals objects"""
@ -342,20 +331,20 @@ class ConnectionTest(unittest.TestCase):
connect("mongoenginetest") connect("mongoenginetest")
self.assertEqual(len(connections), 1) assert len(connections) == 1
self.assertEqual(len(dbs), 0) assert len(dbs) == 0
self.assertEqual(len(connection_settings), 1) assert len(connection_settings) == 1
class TestDoc(Document): class TestDoc(Document):
pass pass
TestDoc.drop_collection() # triggers the db TestDoc.drop_collection() # triggers the db
self.assertEqual(len(dbs), 1) assert len(dbs) == 1
disconnect() disconnect()
self.assertEqual(len(connections), 0) assert len(connections) == 0
self.assertEqual(len(dbs), 0) assert len(dbs) == 0
self.assertEqual(len(connection_settings), 0) assert len(connection_settings) == 0
def test_disconnect_cleans_cached_collection_attribute_in_document(self): def test_disconnect_cleans_cached_collection_attribute_in_document(self):
"""Ensure that the disconnect() method works properly""" """Ensure that the disconnect() method works properly"""
@ -364,22 +353,20 @@ class ConnectionTest(unittest.TestCase):
class History(Document): class History(Document):
pass pass
self.assertIsNone(History._collection) assert History._collection is None
History.drop_collection() History.drop_collection()
History.objects.first() # will trigger the caching of _collection attribute History.objects.first() # will trigger the caching of _collection attribute
self.assertIsNotNone(History._collection) assert History._collection is not None
disconnect() 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() History.objects.first()
self.assertEqual( assert "You have not defined a default connection" == str(exc_info.value)
"You have not defined a default connection", str(ctx_err.exception)
)
def test_connect_disconnect_works_on_same_document(self): def test_connect_disconnect_works_on_same_document(self):
"""Ensure that the connect/disconnect works properly with a single Document""" """Ensure that the connect/disconnect works properly with a single Document"""
@ -401,7 +388,7 @@ class ConnectionTest(unittest.TestCase):
disconnect() disconnect()
# Make sure save doesnt work at this stage # Make sure save doesnt work at this stage
with self.assertRaises(ConnectionFailure): with pytest.raises(ConnectionFailure):
User(name="Wont work").save() User(name="Wont work").save()
# Save in db2 # Save in db2
@ -410,13 +397,13 @@ class ConnectionTest(unittest.TestCase):
disconnect() disconnect()
db1_users = list(client[db1].user.find()) 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()) 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): def test_disconnect_silently_pass_if_alias_does_not_exist(self):
connections = mongoengine.connection._connections connections = mongoengine.connection._connections
self.assertEqual(len(connections), 0) assert len(connections) == 0
disconnect(alias="not_exist") disconnect(alias="not_exist")
def test_disconnect_all(self): def test_disconnect_all(self):
@ -439,26 +426,26 @@ class ConnectionTest(unittest.TestCase):
History1.drop_collection() History1.drop_collection()
History1.objects.first() History1.objects.first()
self.assertIsNotNone(History._collection) assert History._collection is not None
self.assertIsNotNone(History1._collection) assert History1._collection is not None
self.assertEqual(len(connections), 2) assert len(connections) == 2
self.assertEqual(len(dbs), 2) assert len(dbs) == 2
self.assertEqual(len(connection_settings), 2) assert len(connection_settings) == 2
disconnect_all() disconnect_all()
self.assertIsNone(History._collection) assert History._collection is None
self.assertIsNone(History1._collection) assert History1._collection is None
self.assertEqual(len(connections), 0) assert len(connections) == 0
self.assertEqual(len(dbs), 0) assert len(dbs) == 0
self.assertEqual(len(connection_settings), 0) assert len(connection_settings) == 0
with self.assertRaises(ConnectionFailure): with pytest.raises(ConnectionFailure):
History.objects.first() History.objects.first()
with self.assertRaises(ConnectionFailure): with pytest.raises(ConnectionFailure):
History1.objects.first() History1.objects.first()
def test_disconnect_all_silently_pass_if_no_connection_exist(self): def test_disconnect_all_silently_pass_if_no_connection_exist(self):
@ -475,7 +462,7 @@ class ConnectionTest(unittest.TestCase):
expected_connection.server_info() expected_connection.server_info()
self.assertEqual(expected_connection, actual_connection) assert expected_connection == actual_connection
def test_connect_uri(self): def test_connect_uri(self):
"""Ensure that the connect() method works properly with URIs.""" """Ensure that the connect() method works properly with URIs."""
@ -492,11 +479,11 @@ class ConnectionTest(unittest.TestCase):
) )
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
db = get_db() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "mongoenginetest") assert db.name == "mongoenginetest"
c.admin.system.users.delete_many({}) c.admin.system.users.delete_many({})
c.mongoenginetest.system.users.delete_many({}) c.mongoenginetest.system.users.delete_many({})
@ -508,11 +495,11 @@ class ConnectionTest(unittest.TestCase):
connect("mongoenginetest", host="mongodb://localhost/") connect("mongoenginetest", host="mongodb://localhost/")
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
db = get_db() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "mongoenginetest") assert db.name == "mongoenginetest"
def test_connect_uri_default_db(self): def test_connect_uri_default_db(self):
"""Ensure connect() defaults to the right database name if """Ensure connect() defaults to the right database name if
@ -521,11 +508,11 @@ class ConnectionTest(unittest.TestCase):
connect(host="mongodb://localhost/") connect(host="mongodb://localhost/")
conn = get_connection() conn = get_connection()
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
db = get_db() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "test") assert db.name == "test"
def test_uri_without_credentials_doesnt_override_conn_settings(self): def test_uri_without_credentials_doesnt_override_conn_settings(self):
"""Ensure connect() uses the username & password params if the URI """Ensure connect() uses the username & password params if the URI
@ -538,7 +525,8 @@ class ConnectionTest(unittest.TestCase):
# OperationFailure means that mongoengine attempted authentication # OperationFailure means that mongoengine attempted authentication
# w/ the provided username/password and failed - that's the desired # w/ the provided username/password and failed - that's the desired
# behavior. If the MongoDB URI would override the credentials # 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): def test_connect_uri_with_authsource(self):
"""Ensure that the connect() method works well with `authSource` """Ensure that the connect() method works well with `authSource`
@ -556,7 +544,8 @@ class ConnectionTest(unittest.TestCase):
alias="test1", alias="test1",
host="mongodb://username2:password@localhost/mongoenginetest", 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" # Authentication succeeds with "authSource"
authd_conn = connect( authd_conn = connect(
@ -568,8 +557,8 @@ class ConnectionTest(unittest.TestCase):
), ),
) )
db = get_db("test2") db = get_db("test2")
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "mongoenginetest") assert db.name == "mongoenginetest"
# Clear all users # Clear all users
authd_conn.admin.system.users.delete_many({}) authd_conn.admin.system.users.delete_many({})
@ -579,13 +568,14 @@ class ConnectionTest(unittest.TestCase):
""" """
register_connection("testdb", "mongoenginetest2") register_connection("testdb", "mongoenginetest2")
self.assertRaises(ConnectionFailure, get_connection) with pytest.raises(ConnectionFailure):
get_connection()
conn = get_connection("testdb") conn = get_connection("testdb")
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
db = get_db("testdb") db = get_db("testdb")
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "mongoenginetest2") assert db.name == "mongoenginetest2"
def test_register_connection_defaults(self): def test_register_connection_defaults(self):
"""Ensure that defaults are used when the host and port are None. """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) register_connection("testdb", "mongoenginetest", host=None, port=None)
conn = get_connection("testdb") conn = get_connection("testdb")
self.assertIsInstance(conn, pymongo.mongo_client.MongoClient) assert isinstance(conn, pymongo.mongo_client.MongoClient)
def test_connection_kwargs(self): def test_connection_kwargs(self):
"""Ensure that connection kwargs get passed to pymongo.""" """Ensure that connection kwargs get passed to pymongo."""
connect("mongoenginetest", alias="t1", tz_aware=True) connect("mongoenginetest", alias="t1", tz_aware=True)
conn = get_connection("t1") conn = get_connection("t1")
self.assertTrue(get_tz_awareness(conn)) assert get_tz_awareness(conn)
connect("mongoenginetest2", alias="t2") connect("mongoenginetest2", alias="t2")
conn = get_connection("t2") conn = get_connection("t2")
self.assertFalse(get_tz_awareness(conn)) assert not get_tz_awareness(conn)
def test_connection_pool_via_kwarg(self): def test_connection_pool_via_kwarg(self):
"""Ensure we can specify a max connection pool size using """Ensure we can specify a max connection pool size using
@ -615,7 +605,7 @@ class ConnectionTest(unittest.TestCase):
conn = connect( conn = connect(
"mongoenginetest", alias="max_pool_size_via_kwarg", **pool_size_kwargs "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): def test_connection_pool_via_uri(self):
"""Ensure we can specify a max connection pool size using """Ensure we can specify a max connection pool size using
@ -625,16 +615,18 @@ class ConnectionTest(unittest.TestCase):
host="mongodb://localhost/test?maxpoolsize=100", host="mongodb://localhost/test?maxpoolsize=100",
alias="max_pool_size_via_uri", alias="max_pool_size_via_uri",
) )
self.assertEqual(conn.max_pool_size, 100) assert conn.max_pool_size == 100
def test_write_concern(self): def test_write_concern(self):
"""Ensure write concern can be specified in connect() via """Ensure write concern can be specified in connect() via
a kwarg or as part of the connection URI. a kwarg or as part of the connection URI.
""" """
conn1 = connect(alias="conn1", host="mongodb://localhost/testing?w=1&j=true") conn1 = connect(
conn2 = connect("testing", alias="conn2", w=1, j=True) alias="conn1", host="mongodb://localhost/testing?w=1&journal=true"
self.assertEqual(conn1.write_concern.document, {"w": 1, "j": True}) )
self.assertEqual(conn2.write_concern.document, {"w": 1, "j": 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): def test_connect_with_replicaset_via_uri(self):
"""Ensure connect() works when specifying a replicaSet via the """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") c = connect(host="mongodb://localhost/test?replicaSet=local-rs")
db = get_db() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "test") assert db.name == "test"
def test_connect_with_replicaset_via_kwargs(self): def test_connect_with_replicaset_via_kwargs(self):
"""Ensure connect() works when specifying a replicaSet via the """Ensure connect() works when specifying a replicaSet via the
connection kwargs connection kwargs
""" """
c = connect(replicaset="local-rs") 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() db = get_db()
self.assertIsInstance(db, pymongo.database.Database) assert isinstance(db, pymongo.database.Database)
self.assertEqual(db.name, "test") assert db.name == "test"
def test_connect_tz_aware(self): def test_connect_tz_aware(self):
connect("mongoenginetest", tz_aware=True) connect("mongoenginetest", tz_aware=True)
@ -666,13 +658,13 @@ class ConnectionTest(unittest.TestCase):
DateDoc(the_date=d).save() DateDoc(the_date=d).save()
date_doc = DateDoc.objects.first() 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): def test_read_preference_from_parse(self):
conn = connect( conn = connect(
host="mongodb://a1.vpc,a2.vpc,a3.vpc/prod?readPreference=secondaryPreferred" 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): def test_multiple_connection_settings(self):
connect("mongoenginetest", alias="t1", host="localhost") connect("mongoenginetest", alias="t1", host="localhost")
@ -680,27 +672,27 @@ class ConnectionTest(unittest.TestCase):
connect("mongoenginetest2", alias="t2", host="127.0.0.1") connect("mongoenginetest2", alias="t2", host="127.0.0.1")
mongo_connections = mongoengine.connection._connections mongo_connections = mongoengine.connection._connections
self.assertEqual(len(mongo_connections.items()), 2) assert len(mongo_connections.items()) == 2
self.assertIn("t1", mongo_connections.keys()) assert "t1" in mongo_connections.keys()
self.assertIn("t2", mongo_connections.keys()) assert "t2" in mongo_connections.keys()
# Handle PyMongo 3+ Async Connection # Handle PyMongo 3+ Async Connection
# Ensure we are connected, throws ServerSelectionTimeoutError otherwise. # Ensure we are connected, throws ServerSelectionTimeoutError otherwise.
# Purposely not catching exception to fail test if thrown. # Purposely not catching exception to fail test if thrown.
mongo_connections["t1"].server_info() mongo_connections["t1"].server_info()
mongo_connections["t2"].server_info() mongo_connections["t2"].server_info()
self.assertEqual(mongo_connections["t1"].address[0], "localhost") assert mongo_connections["t1"].address[0] == "localhost"
self.assertEqual(mongo_connections["t2"].address[0], "127.0.0.1") assert mongo_connections["t2"].address[0] == "127.0.0.1"
def test_connect_2_databases_uses_same_client_if_only_dbname_differs(self): def test_connect_2_databases_uses_same_client_if_only_dbname_differs(self):
c1 = connect(alias="testdb1", db="testdb1") c1 = connect(alias="testdb1", db="testdb1")
c2 = connect(alias="testdb2", db="testdb2") 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): def test_connect_2_databases_uses_different_client_if_different_parameters(self):
c1 = connect(alias="testdb1", db="testdb1", username="u1") c1 = connect(alias="testdb1", db="testdb1", username="u1")
c2 = connect(alias="testdb2", db="testdb2", username="u2") c2 = connect(alias="testdb2", db="testdb2", username="u2")
self.assertIsNot(c1, c2) assert c1 is not c2
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,18 +1,20 @@
import unittest import unittest
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.connection import get_db from mongoengine.connection import get_db
from mongoengine.context_managers import ( from mongoengine.context_managers import (
switch_db,
switch_collection,
no_sub_classes,
no_dereference, no_dereference,
no_sub_classes,
query_counter, query_counter,
switch_collection,
switch_db,
) )
from mongoengine.pymongo_support import count_documents from mongoengine.pymongo_support import count_documents
class ContextManagersTest(unittest.TestCase): class TestContextManagers:
def test_switch_db_context_manager(self): def test_switch_db_context_manager(self):
connect("mongoenginetest") connect("mongoenginetest")
register_connection("testdb-1", "mongoenginetest2") register_connection("testdb-1", "mongoenginetest2")
@ -23,20 +25,20 @@ class ContextManagersTest(unittest.TestCase):
Group.drop_collection() Group.drop_collection()
Group(name="hello - default").save() Group(name="hello - default").save()
self.assertEqual(1, Group.objects.count()) assert 1 == Group.objects.count()
with switch_db(Group, "testdb-1") as Group: with switch_db(Group, "testdb-1") as Group:
self.assertEqual(0, Group.objects.count()) assert 0 == Group.objects.count()
Group(name="hello").save() Group(name="hello").save()
self.assertEqual(1, Group.objects.count()) assert 1 == Group.objects.count()
Group.drop_collection() 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): def test_switch_collection_context_manager(self):
connect("mongoenginetest") connect("mongoenginetest")
@ -51,20 +53,20 @@ class ContextManagersTest(unittest.TestCase):
Group.drop_collection() # drops in group1 Group.drop_collection() # drops in group1
Group(name="hello - group").save() Group(name="hello - group").save()
self.assertEqual(1, Group.objects.count()) assert 1 == Group.objects.count()
with switch_collection(Group, "group1") as Group: with switch_collection(Group, "group1") as Group:
self.assertEqual(0, Group.objects.count()) assert 0 == Group.objects.count()
Group(name="hello - group1").save() Group(name="hello - group1").save()
self.assertEqual(1, Group.objects.count()) assert 1 == Group.objects.count()
Group.drop_collection() 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): def test_no_dereference_context_manager_object_id(self):
"""Ensure that DBRef items in ListFields aren't dereferenced. """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() Group(ref=user, members=User.objects, generic=user).save()
with no_dereference(Group) as NoDeRefGroup: with no_dereference(Group) as NoDeRefGroup:
self.assertTrue(Group._fields["members"]._auto_dereference) assert Group._fields["members"]._auto_dereference
self.assertFalse(NoDeRefGroup._fields["members"]._auto_dereference) assert not NoDeRefGroup._fields["members"]._auto_dereference
with no_dereference(Group) as Group: with no_dereference(Group) as Group:
group = Group.objects.first() group = Group.objects.first()
for m in group.members: for m in group.members:
self.assertNotIsInstance(m, User) assert not isinstance(m, User)
self.assertNotIsInstance(group.ref, User) assert not isinstance(group.ref, User)
self.assertNotIsInstance(group.generic, User) assert not isinstance(group.generic, User)
for m in group.members: for m in group.members:
self.assertIsInstance(m, User) assert isinstance(m, User)
self.assertIsInstance(group.ref, User) assert isinstance(group.ref, User)
self.assertIsInstance(group.generic, User) assert isinstance(group.generic, User)
def test_no_dereference_context_manager_dbref(self): def test_no_dereference_context_manager_dbref(self):
"""Ensure that DBRef items in ListFields aren't dereferenced. """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() Group(ref=user, members=User.objects, generic=user).save()
with no_dereference(Group) as NoDeRefGroup: with no_dereference(Group) as NoDeRefGroup:
self.assertTrue(Group._fields["members"]._auto_dereference) assert Group._fields["members"]._auto_dereference
self.assertFalse(NoDeRefGroup._fields["members"]._auto_dereference) assert not NoDeRefGroup._fields["members"]._auto_dereference
with no_dereference(Group) as Group: with no_dereference(Group) as Group:
group = Group.objects.first() group = Group.objects.first()
self.assertTrue(all([not isinstance(m, User) for m in group.members])) assert all([not isinstance(m, User) for m in group.members])
self.assertNotIsInstance(group.ref, User) assert not isinstance(group.ref, User)
self.assertNotIsInstance(group.generic, User) assert not isinstance(group.generic, User)
self.assertTrue(all([isinstance(m, User) for m in group.members])) assert all([isinstance(m, User) for m in group.members])
self.assertIsInstance(group.ref, User) assert isinstance(group.ref, User)
self.assertIsInstance(group.generic, User) assert isinstance(group.generic, User)
def test_no_sub_classes(self): def test_no_sub_classes(self):
class A(Document): class A(Document):
@ -159,32 +161,32 @@ class ContextManagersTest(unittest.TestCase):
B(x=30).save() B(x=30).save()
C(x=40).save() C(x=40).save()
self.assertEqual(A.objects.count(), 5) assert A.objects.count() == 5
self.assertEqual(B.objects.count(), 3) assert B.objects.count() == 3
self.assertEqual(C.objects.count(), 1) assert C.objects.count() == 1
with no_sub_classes(A): with no_sub_classes(A):
self.assertEqual(A.objects.count(), 2) assert A.objects.count() == 2
for obj in A.objects: for obj in A.objects:
self.assertEqual(obj.__class__, A) assert obj.__class__ == A
with no_sub_classes(B): with no_sub_classes(B):
self.assertEqual(B.objects.count(), 2) assert B.objects.count() == 2
for obj in B.objects: for obj in B.objects:
self.assertEqual(obj.__class__, B) assert obj.__class__ == B
with no_sub_classes(C): with no_sub_classes(C):
self.assertEqual(C.objects.count(), 1) assert C.objects.count() == 1
for obj in C.objects: for obj in C.objects:
self.assertEqual(obj.__class__, C) assert obj.__class__ == C
# Confirm context manager exit correctly # Confirm context manager exit correctly
self.assertEqual(A.objects.count(), 5) assert A.objects.count() == 5
self.assertEqual(B.objects.count(), 3) assert B.objects.count() == 3
self.assertEqual(C.objects.count(), 1) assert C.objects.count() == 1
def test_no_sub_classes_modification_to_document_class_are_temporary(self): def test_no_sub_classes_modification_to_document_class_are_temporary(self):
class A(Document): class A(Document):
@ -194,27 +196,26 @@ class ContextManagersTest(unittest.TestCase):
class B(A): class B(A):
z = IntField() z = IntField()
self.assertEqual(A._subclasses, ("A", "A.B")) assert A._subclasses == ("A", "A.B")
with no_sub_classes(A): with no_sub_classes(A):
self.assertEqual(A._subclasses, ("A",)) assert A._subclasses == ("A",)
self.assertEqual(A._subclasses, ("A", "A.B")) assert A._subclasses == ("A", "A.B")
self.assertEqual(B._subclasses, ("A.B",)) assert B._subclasses == ("A.B",)
with no_sub_classes(B): with no_sub_classes(B):
self.assertEqual(B._subclasses, ("A.B",)) assert B._subclasses == ("A.B",)
self.assertEqual(B._subclasses, ("A.B",)) assert B._subclasses == ("A.B",)
def test_no_subclass_context_manager_does_not_swallow_exception(self): def test_no_subclass_context_manager_does_not_swallow_exception(self):
class User(Document): class User(Document):
name = StringField() name = StringField()
with self.assertRaises(TypeError): with pytest.raises(TypeError):
with no_sub_classes(User): with no_sub_classes(User):
raise TypeError() raise TypeError()
def test_query_counter_does_not_swallow_exception(self): def test_query_counter_does_not_swallow_exception(self):
with pytest.raises(TypeError):
with self.assertRaises(TypeError):
with query_counter() as q: with query_counter() as q:
raise TypeError() raise TypeError()
@ -227,10 +228,10 @@ class ContextManagersTest(unittest.TestCase):
try: try:
NEW_LEVEL = 1 NEW_LEVEL = 1
db.set_profiling_level(NEW_LEVEL) db.set_profiling_level(NEW_LEVEL)
self.assertEqual(db.profiling_level(), NEW_LEVEL) assert db.profiling_level() == NEW_LEVEL
with query_counter() as q: with query_counter() as q:
self.assertEqual(db.profiling_level(), 2) assert db.profiling_level() == 2
self.assertEqual(db.profiling_level(), NEW_LEVEL) assert db.profiling_level() == NEW_LEVEL
except Exception: except Exception:
db.set_profiling_level( db.set_profiling_level(
initial_profiling_level initial_profiling_level
@ -255,33 +256,77 @@ class ContextManagersTest(unittest.TestCase):
counter = 0 counter = 0
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, counter) assert q == counter
self.assertEqual( assert q == counter # Ensures previous count query did not get counted
q, counter
) # Ensures previous count query did not get counted
for _ in range(10): for _ in range(10):
issue_1_insert_query() issue_1_insert_query()
counter += 1 counter += 1
self.assertEqual(q, counter) assert q == counter
for _ in range(4): for _ in range(4):
issue_1_find_query() issue_1_find_query()
counter += 1 counter += 1
self.assertEqual(q, counter) assert q == counter
for _ in range(3): for _ in range(3):
issue_1_count_query() issue_1_count_query()
counter += 1 counter += 1
self.assertEqual(q, counter) assert q == counter
self.assertEqual(int(q), counter) # test __int__ assert int(q) == counter # test __int__
self.assertEqual(repr(q), str(int(q))) # test __repr__ assert repr(q) == str(int(q)) # test __repr__
self.assertGreater(q, -1) # test __gt__ assert q > -1 # test __gt__
self.assertGreaterEqual(q, int(q)) # test __gte__ assert q >= int(q) # test __gte__
self.assertNotEqual(q, -1) assert q != -1
self.assertLess(q, 1000) assert q < 1000
self.assertLessEqual(q, int(q)) 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): def test_query_counter_counts_getmore_queries(self):
connect("mongoenginetest") connect("mongoenginetest")
@ -296,9 +341,9 @@ class ContextManagersTest(unittest.TestCase):
) # first batch of documents contains 101 documents ) # first batch of documents contains 101 documents
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
list(collection.find()) 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): def test_query_counter_ignores_particular_queries(self):
connect("mongoenginetest") connect("mongoenginetest")
@ -308,18 +353,18 @@ class ContextManagersTest(unittest.TestCase):
collection.insert_many([{"test": "garbage %s" % i} for i in range(10)]) collection.insert_many([{"test": "garbage %s" % i} for i in range(10)])
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
cursor = collection.find() 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 _ = 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 cursor.close() # issues a `killcursors` query that is ignored by the context
self.assertEqual(q, 1) assert q == 1
_ = ( _ = (
db.system.indexes.find_one() db.system.indexes.find_one()
) # queries on db.system.indexes are ignored as well ) # queries on db.system.indexes are ignored as well
self.assertEqual(q, 1) assert q == 1
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,8 +1,10 @@
import unittest import unittest
import pytest
from six import iterkeys from six import iterkeys
from mongoengine import Document from mongoengine import Document
from mongoengine.base.datastructures import StrictDict, BaseList, BaseDict from mongoengine.base.datastructures import BaseDict, BaseList, StrictDict
class DocumentStub(object): class DocumentStub(object):
@ -13,15 +15,15 @@ class DocumentStub(object):
self._changed_fields.append(key) self._changed_fields.append(key)
class TestBaseDict(unittest.TestCase): class TestBaseDict:
@staticmethod @staticmethod
def _get_basedict(dict_items): def _get_basedict(dict_items):
"""Get a BaseList bound to a fake document instance""" """Get a BaseList bound to a fake document instance"""
fake_doc = DocumentStub() fake_doc = DocumentStub()
base_list = BaseDict(dict_items, instance=None, name="my_name") base_list = BaseDict(dict_items, instance=None, name="my_name")
base_list._instance = ( base_list._instance = (
fake_doc fake_doc # hack to inject the mock, it does not work in the constructor
) # hack to inject the mock, it does not work in the constructor )
return base_list return base_list
def test___init___(self): def test___init___(self):
@ -31,48 +33,48 @@ class TestBaseDict(unittest.TestCase):
dict_items = {"k": "v"} dict_items = {"k": "v"}
doc = MyDoc() doc = MyDoc()
base_dict = BaseDict(dict_items, instance=doc, name="my_name") base_dict = BaseDict(dict_items, instance=doc, name="my_name")
self.assertIsInstance(base_dict._instance, Document) assert isinstance(base_dict._instance, Document)
self.assertEqual(base_dict._name, "my_name") assert base_dict._name == "my_name"
self.assertEqual(base_dict, dict_items) assert base_dict == dict_items
def test_setdefault_calls_mark_as_changed(self): def test_setdefault_calls_mark_as_changed(self):
base_dict = self._get_basedict({}) base_dict = self._get_basedict({})
base_dict.setdefault("k", "v") 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): def test_popitems_calls_mark_as_changed(self):
base_dict = self._get_basedict({"k": "v"}) base_dict = self._get_basedict({"k": "v"})
self.assertEqual(base_dict.popitem(), ("k", "v")) assert base_dict.popitem() == ("k", "v")
self.assertEqual(base_dict._instance._changed_fields, [base_dict._name]) assert base_dict._instance._changed_fields == [base_dict._name]
self.assertFalse(base_dict) assert not base_dict
def test_pop_calls_mark_as_changed(self): def test_pop_calls_mark_as_changed(self):
base_dict = self._get_basedict({"k": "v"}) base_dict = self._get_basedict({"k": "v"})
self.assertEqual(base_dict.pop("k"), "v") assert base_dict.pop("k") == "v"
self.assertEqual(base_dict._instance._changed_fields, [base_dict._name]) assert base_dict._instance._changed_fields == [base_dict._name]
self.assertFalse(base_dict) assert not base_dict
def test_pop_calls_does_not_mark_as_changed_when_it_fails(self): def test_pop_calls_does_not_mark_as_changed_when_it_fails(self):
base_dict = self._get_basedict({"k": "v"}) base_dict = self._get_basedict({"k": "v"})
with self.assertRaises(KeyError): with pytest.raises(KeyError):
base_dict.pop("X") 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): def test_clear_calls_mark_as_changed(self):
base_dict = self._get_basedict({"k": "v"}) base_dict = self._get_basedict({"k": "v"})
base_dict.clear() base_dict.clear()
self.assertEqual(base_dict._instance._changed_fields, ["my_name"]) assert base_dict._instance._changed_fields == ["my_name"]
self.assertEqual(base_dict, {}) assert base_dict == {}
def test___delitem___calls_mark_as_changed(self): def test___delitem___calls_mark_as_changed(self):
base_dict = self._get_basedict({"k": "v"}) base_dict = self._get_basedict({"k": "v"})
del base_dict["k"] del base_dict["k"]
self.assertEqual(base_dict._instance._changed_fields, ["my_name.k"]) assert base_dict._instance._changed_fields == ["my_name.k"]
self.assertEqual(base_dict, {}) assert base_dict == {}
def test___getitem____KeyError(self): def test___getitem____KeyError(self):
base_dict = self._get_basedict({}) base_dict = self._get_basedict({})
with self.assertRaises(KeyError): with pytest.raises(KeyError):
base_dict["new"] base_dict["new"]
def test___getitem____simple_value(self): def test___getitem____simple_value(self):
@ -82,62 +84,62 @@ class TestBaseDict(unittest.TestCase):
def test___getitem____sublist_gets_converted_to_BaseList(self): def test___getitem____sublist_gets_converted_to_BaseList(self):
base_dict = self._get_basedict({"k": [0, 1, 2]}) base_dict = self._get_basedict({"k": [0, 1, 2]})
sub_list = base_dict["k"] sub_list = base_dict["k"]
self.assertEqual(sub_list, [0, 1, 2]) assert sub_list == [0, 1, 2]
self.assertIsInstance(sub_list, BaseList) assert isinstance(sub_list, BaseList)
self.assertIs(sub_list._instance, base_dict._instance) assert sub_list._instance is base_dict._instance
self.assertEqual(sub_list._name, "my_name.k") assert sub_list._name == "my_name.k"
self.assertEqual(base_dict._instance._changed_fields, []) assert base_dict._instance._changed_fields == []
# Challenge mark_as_changed from sublist # Challenge mark_as_changed from sublist
sub_list[1] = None 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): def test___getitem____subdict_gets_converted_to_BaseDict(self):
base_dict = self._get_basedict({"k": {"subk": "subv"}}) base_dict = self._get_basedict({"k": {"subk": "subv"}})
sub_dict = base_dict["k"] sub_dict = base_dict["k"]
self.assertEqual(sub_dict, {"subk": "subv"}) assert sub_dict == {"subk": "subv"}
self.assertIsInstance(sub_dict, BaseDict) assert isinstance(sub_dict, BaseDict)
self.assertIs(sub_dict._instance, base_dict._instance) assert sub_dict._instance is base_dict._instance
self.assertEqual(sub_dict._name, "my_name.k") assert sub_dict._name == "my_name.k"
self.assertEqual(base_dict._instance._changed_fields, []) assert base_dict._instance._changed_fields == []
# Challenge mark_as_changed from subdict # Challenge mark_as_changed from subdict
sub_dict["subk"] = None 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): def test_get_sublist_gets_converted_to_BaseList_just_like__getitem__(self):
base_dict = self._get_basedict({"k": [0, 1, 2]}) base_dict = self._get_basedict({"k": [0, 1, 2]})
sub_list = base_dict.get("k") sub_list = base_dict.get("k")
self.assertEqual(sub_list, [0, 1, 2]) assert sub_list == [0, 1, 2]
self.assertIsInstance(sub_list, BaseList) assert isinstance(sub_list, BaseList)
def test_get_returns_the_same_as___getitem__(self): def test_get_returns_the_same_as___getitem__(self):
base_dict = self._get_basedict({"k": [0, 1, 2]}) base_dict = self._get_basedict({"k": [0, 1, 2]})
get_ = base_dict.get("k") get_ = base_dict.get("k")
getitem_ = base_dict["k"] getitem_ = base_dict["k"]
self.assertEqual(get_, getitem_) assert get_ == getitem_
def test_get_default(self): def test_get_default(self):
base_dict = self._get_basedict({}) base_dict = self._get_basedict({})
sentinel = object() sentinel = object()
self.assertEqual(base_dict.get("new"), None) assert base_dict.get("new") is None
self.assertIs(base_dict.get("new", sentinel), sentinel) assert base_dict.get("new", sentinel) is sentinel
def test___setitem___calls_mark_as_changed(self): def test___setitem___calls_mark_as_changed(self):
base_dict = self._get_basedict({}) base_dict = self._get_basedict({})
base_dict["k"] = "v" base_dict["k"] = "v"
self.assertEqual(base_dict._instance._changed_fields, ["my_name.k"]) assert base_dict._instance._changed_fields == ["my_name.k"]
self.assertEqual(base_dict, {"k": "v"}) assert base_dict == {"k": "v"}
def test_update_calls_mark_as_changed(self): def test_update_calls_mark_as_changed(self):
base_dict = self._get_basedict({}) base_dict = self._get_basedict({})
base_dict.update({"k": "v"}) 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): def test___setattr____not_tracked_by_changes(self):
base_dict = self._get_basedict({}) base_dict = self._get_basedict({})
base_dict.a_new_attr = "test" 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): def test___delattr____tracked_by_changes(self):
# This is probably a bug as __setattr__ is not tracked # 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 = self._get_basedict({})
base_dict.a_new_attr = "test" base_dict.a_new_attr = "test"
del base_dict.a_new_attr 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 @staticmethod
def _get_baselist(list_items): def _get_baselist(list_items):
"""Get a BaseList bound to a fake document instance""" """Get a BaseList bound to a fake document instance"""
fake_doc = DocumentStub() fake_doc = DocumentStub()
base_list = BaseList(list_items, instance=None, name="my_name") base_list = BaseList(list_items, instance=None, name="my_name")
base_list._instance = ( base_list._instance = (
fake_doc fake_doc # hack to inject the mock, it does not work in the constructor
) # hack to inject the mock, it does not work in the constructor )
return base_list return base_list
def test___init___(self): def test___init___(self):
@ -167,14 +169,14 @@ class TestBaseList(unittest.TestCase):
list_items = [True] list_items = [True]
doc = MyDoc() doc = MyDoc()
base_list = BaseList(list_items, instance=doc, name="my_name") base_list = BaseList(list_items, instance=doc, name="my_name")
self.assertIsInstance(base_list._instance, Document) assert isinstance(base_list._instance, Document)
self.assertEqual(base_list._name, "my_name") assert base_list._name == "my_name"
self.assertEqual(base_list, list_items) assert base_list == list_items
def test___iter__(self): def test___iter__(self):
values = [True, False, True, False] values = [True, False, True, False]
base_list = BaseList(values, instance=None, name="my_name") 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): def test___iter___allow_modification_while_iterating_withou_error(self):
# regular list allows for this, thus this subclass must comply to that # 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): def test_append_calls_mark_as_changed(self):
base_list = self._get_baselist([]) base_list = self._get_baselist([])
self.assertFalse(base_list._instance._changed_fields) assert not base_list._instance._changed_fields
base_list.append(True) 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): def test_subclass_append(self):
# Due to the way mark_as_changed_wrapper is implemented # 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): def test___getitem__using_simple_index(self):
base_list = self._get_baselist([0, 1, 2]) base_list = self._get_baselist([0, 1, 2])
self.assertEqual(base_list[0], 0) assert base_list[0] == 0
self.assertEqual(base_list[1], 1) assert base_list[1] == 1
self.assertEqual(base_list[-1], 2) assert base_list[-1] == 2
def test___getitem__using_slice(self): def test___getitem__using_slice(self):
base_list = self._get_baselist([0, 1, 2]) base_list = self._get_baselist([0, 1, 2])
self.assertEqual(base_list[1:3], [1, 2]) assert base_list[1:3] == [1, 2]
self.assertEqual(base_list[0:3:2], [0, 2]) assert base_list[0:3:2] == [0, 2]
def test___getitem___using_slice_returns_list(self): def test___getitem___using_slice_returns_list(self):
# Bug: using slice does not properly handles the instance # Bug: using slice does not properly handles the instance
# and mark_as_changed behaviour. # and mark_as_changed behaviour.
base_list = self._get_baselist([0, 1, 2]) base_list = self._get_baselist([0, 1, 2])
sliced = base_list[1:3] sliced = base_list[1:3]
self.assertEqual(sliced, [1, 2]) assert sliced == [1, 2]
self.assertIsInstance(sliced, list) assert isinstance(sliced, list)
self.assertEqual(base_list._instance._changed_fields, []) assert base_list._instance._changed_fields == []
def test___getitem__sublist_returns_BaseList_bound_to_instance(self): def test___getitem__sublist_returns_BaseList_bound_to_instance(self):
base_list = self._get_baselist([[1, 2], [3, 4]]) base_list = self._get_baselist([[1, 2], [3, 4]])
sub_list = base_list[0] sub_list = base_list[0]
self.assertEqual(sub_list, [1, 2]) assert sub_list == [1, 2]
self.assertIsInstance(sub_list, BaseList) assert isinstance(sub_list, BaseList)
self.assertIs(sub_list._instance, base_list._instance) assert sub_list._instance is base_list._instance
self.assertEqual(sub_list._name, "my_name.0") assert sub_list._name == "my_name.0"
self.assertEqual(base_list._instance._changed_fields, []) assert base_list._instance._changed_fields == []
# Challenge mark_as_changed from sublist # Challenge mark_as_changed from sublist
sub_list[1] = None 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): def test___getitem__subdict_returns_BaseList_bound_to_instance(self):
base_list = self._get_baselist([{"subk": "subv"}]) base_list = self._get_baselist([{"subk": "subv"}])
sub_dict = base_list[0] sub_dict = base_list[0]
self.assertEqual(sub_dict, {"subk": "subv"}) assert sub_dict == {"subk": "subv"}
self.assertIsInstance(sub_dict, BaseDict) assert isinstance(sub_dict, BaseDict)
self.assertIs(sub_dict._instance, base_list._instance) assert sub_dict._instance is base_list._instance
self.assertEqual(sub_dict._name, "my_name.0") assert sub_dict._name == "my_name.0"
self.assertEqual(base_list._instance._changed_fields, []) assert base_list._instance._changed_fields == []
# Challenge mark_as_changed from subdict # Challenge mark_as_changed from subdict
sub_dict["subk"] = None 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): def test_extend_calls_mark_as_changed(self):
base_list = self._get_baselist([]) base_list = self._get_baselist([])
base_list.extend([True]) 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): def test_insert_calls_mark_as_changed(self):
base_list = self._get_baselist([]) base_list = self._get_baselist([])
base_list.insert(0, True) 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): def test_remove_calls_mark_as_changed(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
base_list.remove(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): def test_remove_not_mark_as_changed_when_it_fails(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
with self.assertRaises(ValueError): with pytest.raises(ValueError):
base_list.remove(False) 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): def test_pop_calls_mark_as_changed(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
base_list.pop() 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): def test_reverse_calls_mark_as_changed(self):
base_list = self._get_baselist([True, False]) base_list = self._get_baselist([True, False])
base_list.reverse() 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): def test___delitem___calls_mark_as_changed(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
del base_list[0] 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): def test___setitem___calls_with_full_slice_mark_as_changed(self):
base_list = self._get_baselist([]) base_list = self._get_baselist([])
@ -286,8 +288,8 @@ class TestBaseList(unittest.TestCase):
0, 0,
1, 1,
] # Will use __setslice__ under py2 and __setitem__ under py3 ] # Will use __setslice__ under py2 and __setitem__ under py3
self.assertEqual(base_list._instance._changed_fields, ["my_name"]) assert base_list._instance._changed_fields == ["my_name"]
self.assertEqual(base_list, [0, 1]) assert base_list == [0, 1]
def test___setitem___calls_with_partial_slice_mark_as_changed(self): def test___setitem___calls_with_partial_slice_mark_as_changed(self):
base_list = self._get_baselist([0, 1, 2]) base_list = self._get_baselist([0, 1, 2])
@ -295,103 +297,103 @@ class TestBaseList(unittest.TestCase):
1, 1,
0, 0,
] # Will use __setslice__ under py2 and __setitem__ under py3 ] # Will use __setslice__ under py2 and __setitem__ under py3
self.assertEqual(base_list._instance._changed_fields, ["my_name"]) assert base_list._instance._changed_fields == ["my_name"]
self.assertEqual(base_list, [1, 0, 2]) assert base_list == [1, 0, 2]
def test___setitem___calls_with_step_slice_mark_as_changed(self): def test___setitem___calls_with_step_slice_mark_as_changed(self):
base_list = self._get_baselist([0, 1, 2]) base_list = self._get_baselist([0, 1, 2])
base_list[0:3:2] = [-1, -2] # uses __setitem__ in both py2 & 3 base_list[0:3:2] = [-1, -2] # uses __setitem__ in both py2 & 3
self.assertEqual(base_list._instance._changed_fields, ["my_name"]) assert base_list._instance._changed_fields == ["my_name"]
self.assertEqual(base_list, [-1, 1, -2]) assert base_list == [-1, 1, -2]
def test___setitem___with_slice(self): def test___setitem___with_slice(self):
base_list = self._get_baselist([0, 1, 2, 3, 4, 5]) base_list = self._get_baselist([0, 1, 2, 3, 4, 5])
base_list[0:6:2] = [None, None, None] base_list[0:6:2] = [None, None, None]
self.assertEqual(base_list._instance._changed_fields, ["my_name"]) assert base_list._instance._changed_fields == ["my_name"]
self.assertEqual(base_list, [None, 1, None, 3, None, 5]) assert base_list == [None, 1, None, 3, None, 5]
def test___setitem___item_0_calls_mark_as_changed(self): def test___setitem___item_0_calls_mark_as_changed(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
base_list[0] = False base_list[0] = False
self.assertEqual(base_list._instance._changed_fields, ["my_name"]) assert base_list._instance._changed_fields == ["my_name"]
self.assertEqual(base_list, [False]) assert base_list == [False]
def test___setitem___item_1_calls_mark_as_changed(self): def test___setitem___item_1_calls_mark_as_changed(self):
base_list = self._get_baselist([True, True]) base_list = self._get_baselist([True, True])
base_list[1] = False base_list[1] = False
self.assertEqual(base_list._instance._changed_fields, ["my_name.1"]) assert base_list._instance._changed_fields == ["my_name.1"]
self.assertEqual(base_list, [True, False]) assert base_list == [True, False]
def test___delslice___calls_mark_as_changed(self): def test___delslice___calls_mark_as_changed(self):
base_list = self._get_baselist([0, 1]) base_list = self._get_baselist([0, 1])
del base_list[0:1] del base_list[0:1]
self.assertEqual(base_list._instance._changed_fields, ["my_name"]) assert base_list._instance._changed_fields == ["my_name"]
self.assertEqual(base_list, [1]) assert base_list == [1]
def test___iadd___calls_mark_as_changed(self): def test___iadd___calls_mark_as_changed(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
base_list += [False] 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): def test___imul___calls_mark_as_changed(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
self.assertEqual(base_list._instance._changed_fields, []) assert base_list._instance._changed_fields == []
base_list *= 2 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): def test_sort_calls_not_marked_as_changed_when_it_fails(self):
base_list = self._get_baselist([True]) base_list = self._get_baselist([True])
with self.assertRaises(TypeError): with pytest.raises(TypeError):
base_list.sort(key=1) 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): def test_sort_calls_mark_as_changed(self):
base_list = self._get_baselist([True, False]) base_list = self._get_baselist([True, False])
base_list.sort() 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): def test_sort_calls_with_key(self):
base_list = self._get_baselist([1, 2, 11]) base_list = self._get_baselist([1, 2, 11])
base_list.sort(key=lambda i: str(i)) 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): class TestStrictDict(unittest.TestCase):
def strict_dict_class(self, *args, **kwargs):
return StrictDict.create(*args, **kwargs)
def setUp(self): def setUp(self):
self.dtype = self.strict_dict_class(("a", "b", "c")) 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): def test_init(self):
d = self.dtype(a=1, b=1, c=1) 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): def test_iterkeys(self):
d = self.dtype(a=1) d = self.dtype(a=1)
self.assertEqual(list(iterkeys(d)), ["a"]) assert list(iterkeys(d)) == ["a"]
def test_len(self): def test_len(self):
d = self.dtype(a=1) d = self.dtype(a=1)
self.assertEqual(len(d), 1) assert len(d) == 1
def test_pop(self): def test_pop(self):
d = self.dtype(a=1) d = self.dtype(a=1)
self.assertIn("a", d) assert "a" in d
d.pop("a") d.pop("a")
self.assertNotIn("a", d) assert "a" not in d
def test_repr(self): def test_repr(self):
d = self.dtype(a=1, b=2, c=3) 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 # make sure quotes are escaped properly
d = self.dtype(a='"', b="'", c="") 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): def test_init_fails_on_nonexisting_attrs(self):
with self.assertRaises(AttributeError): with pytest.raises(AttributeError):
self.dtype(a=1, b=2, d=3) self.dtype(a=1, b=2, d=3)
def test_eq(self): 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) 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) i = self.strict_dict_class(("a", "c", "b"))(a=1, b=1, c=2)
self.assertEqual(d, dd) assert d == dd
self.assertNotEqual(d, e) assert d != e
self.assertNotEqual(d, f) assert d != f
self.assertNotEqual(d, g) assert d != g
self.assertNotEqual(f, d) assert f != d
self.assertEqual(d, h) assert d == h
self.assertNotEqual(d, i) assert d != i
def test_setattr_getattr(self): def test_setattr_getattr(self):
d = self.dtype() d = self.dtype()
d.a = 1 d.a = 1
self.assertEqual(d.a, 1) assert d.a == 1
self.assertRaises(AttributeError, getattr, d, "b") with pytest.raises(AttributeError):
getattr(d, "b")
def test_setattr_raises_on_nonexisting_attr(self): def test_setattr_raises_on_nonexisting_attr(self):
d = self.dtype() d = self.dtype()
with self.assertRaises(AttributeError): with pytest.raises(AttributeError):
d.x = 1 d.x = 1
def test_setattr_getattr_special(self): def test_setattr_getattr_special(self):
d = self.strict_dict_class(["items"]) d = self.strict_dict_class(["items"])
d.items = 1 d.items = 1
self.assertEqual(d.items, 1) assert d.items == 1
def test_get(self): def test_get(self):
d = self.dtype(a=1) d = self.dtype(a=1)
self.assertEqual(d.get("a"), 1) assert d.get("a") == 1
self.assertEqual(d.get("b", "bla"), "bla") assert d.get("b", "bla") == "bla"
def test_items(self): def test_items(self):
d = self.dtype(a=1) d = self.dtype(a=1)
self.assertEqual(d.items(), [("a", 1)]) assert d.items() == [("a", 1)]
d = self.dtype(a=1, b=2) 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): def test_mappings_protocol(self):
d = self.dtype(a=1, b=2) d = self.dtype(a=1, b=2)
self.assertEqual(dict(d), {"a": 1, "b": 2}) assert dict(d) == {"a": 1, "b": 2}
self.assertEqual(dict(**d), {"a": 1, "b": 2}) assert dict(**d) == {"a": 1, "b": 2}
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -42,37 +42,37 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
len(group_obj._data["members"]) len(group_obj._data["members"])
self.assertEqual(q, 1) assert q == 1
len(group_obj.members) len(group_obj.members)
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 2) assert q == 2
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
User.drop_collection() User.drop_collection()
Group.drop_collection() Group.drop_collection()
@ -99,40 +99,40 @@ class FieldTest(unittest.TestCase):
group.reload() # Confirm reload works group.reload() # Confirm reload works
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
self.assertTrue(group_obj._data["members"]._dereferenced) assert group_obj._data["members"]._dereferenced
# verifies that no additional queries gets executed # verifies that no additional queries gets executed
# if we re-iterate over the ListField once it is # if we re-iterate over the ListField once it is
# dereferenced # dereferenced
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
self.assertTrue(group_obj._data["members"]._dereferenced) assert group_obj._data["members"]._dereferenced
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 2) assert q == 2
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
def test_list_item_dereference_orphan_dbref(self): def test_list_item_dereference_orphan_dbref(self):
"""Ensure that orphan DBRef items in ListFields are dereferenced. """Ensure that orphan DBRef items in ListFields are dereferenced.
@ -159,21 +159,21 @@ class FieldTest(unittest.TestCase):
# Group.members list is an orphan DBRef # Group.members list is an orphan DBRef
User.objects[0].delete() User.objects[0].delete()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
self.assertTrue(group_obj._data["members"]._dereferenced) assert group_obj._data["members"]._dereferenced
# verifies that no additional queries gets executed # verifies that no additional queries gets executed
# if we re-iterate over the ListField once it is # if we re-iterate over the ListField once it is
# dereferenced # dereferenced
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
self.assertTrue(group_obj._data["members"]._dereferenced) assert group_obj._data["members"]._dereferenced
User.drop_collection() User.drop_collection()
Group.drop_collection() Group.drop_collection()
@ -197,8 +197,8 @@ class FieldTest(unittest.TestCase):
Group(members=User.objects).save() Group(members=User.objects).save()
group = Group.objects.first() group = Group.objects.first()
self.assertEqual(Group._get_collection().find_one()["members"], [1]) assert Group._get_collection().find_one()["members"] == [1]
self.assertEqual(group.members, [user]) assert group.members == [user]
def test_handle_old_style_references(self): def test_handle_old_style_references(self):
"""Ensure that DBRef items in ListFields are dereferenced. """Ensure that DBRef items in ListFields are dereferenced.
@ -231,8 +231,8 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
group = Group.objects.first() group = Group.objects.first()
self.assertEqual(group.members[0].name, "user 1") assert group.members[0].name == "user 1"
self.assertEqual(group.members[-1].name, "String!") assert group.members[-1].name == "String!"
def test_migrate_references(self): def test_migrate_references(self):
"""Example of migrating ReferenceField storage """Example of migrating ReferenceField storage
@ -253,12 +253,12 @@ class FieldTest(unittest.TestCase):
group = Group(author=user, members=[user]).save() group = Group(author=user, members=[user]).save()
raw_data = Group._get_collection().find_one() raw_data = Group._get_collection().find_one()
self.assertIsInstance(raw_data["author"], DBRef) assert isinstance(raw_data["author"], DBRef)
self.assertIsInstance(raw_data["members"][0], DBRef) assert isinstance(raw_data["members"][0], DBRef)
group = Group.objects.first() group = Group.objects.first()
self.assertEqual(group.author, user) assert group.author == user
self.assertEqual(group.members, [user]) assert group.members == [user]
# Migrate the model definition # Migrate the model definition
class Group(Document): class Group(Document):
@ -273,12 +273,12 @@ class FieldTest(unittest.TestCase):
g.save() g.save()
group = Group.objects.first() group = Group.objects.first()
self.assertEqual(group.author, user) assert group.author == user
self.assertEqual(group.members, [user]) assert group.members == [user]
raw_data = Group._get_collection().find_one() raw_data = Group._get_collection().find_one()
self.assertIsInstance(raw_data["author"], ObjectId) assert isinstance(raw_data["author"], ObjectId)
self.assertIsInstance(raw_data["members"][0], ObjectId) assert isinstance(raw_data["members"][0], ObjectId)
def test_recursive_reference(self): def test_recursive_reference(self):
"""Ensure that ReferenceFields can reference their own documents. """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() Employee(name="Funky Gibbon", boss=bill, friends=friends).save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
peter = Employee.objects.with_id(peter.id) peter = Employee.objects.with_id(peter.id)
self.assertEqual(q, 1) assert q == 1
peter.boss peter.boss
self.assertEqual(q, 2) assert q == 2
peter.friends peter.friends
self.assertEqual(q, 3) assert q == 3
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
peter = Employee.objects.with_id(peter.id).select_related() peter = Employee.objects.with_id(peter.id).select_related()
self.assertEqual(q, 2) assert q == 2
self.assertEqual(peter.boss, bill) assert peter.boss == bill
self.assertEqual(q, 2) assert q == 2
self.assertEqual(peter.friends, friends) assert peter.friends == friends
self.assertEqual(q, 2) assert q == 2
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
employees = Employee.objects(boss=bill).select_related() employees = Employee.objects(boss=bill).select_related()
self.assertEqual(q, 2) assert q == 2
for employee in employees: for employee in employees:
self.assertEqual(employee.boss, bill) assert employee.boss == bill
self.assertEqual(q, 2) assert q == 2
self.assertEqual(employee.friends, friends) assert employee.friends == friends
self.assertEqual(q, 2) assert q == 2
def test_list_of_lists_of_references(self): def test_list_of_lists_of_references(self):
class User(Document): class User(Document):
@ -366,10 +366,10 @@ class FieldTest(unittest.TestCase):
u3 = User.objects.create(name="u3") u3 = User.objects.create(name="u3")
SimpleList.objects.create(users=[u1, u2, 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]]) 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): def test_circular_reference(self):
"""Ensure you can handle circular references """Ensure you can handle circular references
@ -403,9 +403,7 @@ class FieldTest(unittest.TestCase):
daughter.relations.append(self_rel) daughter.relations.append(self_rel)
daughter.save() daughter.save()
self.assertEqual( assert "[<Person: Mother>, <Person: Daughter>]" == "%s" % Person.objects()
"[<Person: Mother>, <Person: Daughter>]", "%s" % Person.objects()
)
def test_circular_reference_on_self(self): def test_circular_reference_on_self(self):
"""Ensure you can handle circular references """Ensure you can handle circular references
@ -432,9 +430,7 @@ class FieldTest(unittest.TestCase):
daughter.relations.append(daughter) daughter.relations.append(daughter)
daughter.save() daughter.save()
self.assertEqual( assert "[<Person: Mother>, <Person: Daughter>]" == "%s" % Person.objects()
"[<Person: Mother>, <Person: Daughter>]", "%s" % Person.objects()
)
def test_circular_tree_reference(self): def test_circular_tree_reference(self):
"""Ensure you can handle circular references with more than one level """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.other.name = "Anna's friends"
anna.save() anna.save()
self.assertEqual( assert (
"[<Person: Paul>, <Person: Maria>, <Person: Julia>, <Person: Anna>]", "[<Person: Paul>, <Person: Maria>, <Person: Julia>, <Person: Anna>]"
"%s" % Person.objects(), == "%s" % Person.objects()
) )
def test_generic_reference(self): def test_generic_reference(self):
@ -516,52 +512,52 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for m in group_obj.members: for m in group_obj.members:
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for m in group_obj.members: for m in group_obj.members:
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 4) assert q == 4
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for m in group_obj.members: 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): def test_generic_reference_orphan_dbref(self):
"""Ensure that generic orphan DBRef items in ListFields are dereferenced. """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 # an orphan DBRef in the GenericReference ListField
UserA.objects[0].delete() UserA.objects[0].delete()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
self.assertTrue(group_obj._data["members"]._dereferenced) assert group_obj._data["members"]._dereferenced
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
self.assertTrue(group_obj._data["members"]._dereferenced) assert group_obj._data["members"]._dereferenced
UserA.drop_collection() UserA.drop_collection()
UserB.drop_collection() UserB.drop_collection()
@ -660,52 +656,52 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for m in group_obj.members: for m in group_obj.members:
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for m in group_obj.members: for m in group_obj.members:
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 4) assert q == 4
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for m in group_obj.members: for m in group_obj.members:
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
UserA.drop_collection() UserA.drop_collection()
UserB.drop_collection() UserB.drop_collection()
@ -735,43 +731,43 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIsInstance(m, User) assert isinstance(m, User)
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIsInstance(m, User) assert isinstance(m, User)
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 2) assert q == 2
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIsInstance(m, User) assert isinstance(m, User)
User.drop_collection() User.drop_collection()
Group.drop_collection() Group.drop_collection()
@ -813,65 +809,65 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 4) assert q == 4
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
Group.objects.delete() Group.objects.delete()
Group().save() Group().save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 1) assert q == 1
self.assertEqual(group_obj.members, {}) assert group_obj.members == {}
UserA.drop_collection() UserA.drop_collection()
UserB.drop_collection() UserB.drop_collection()
@ -903,52 +899,52 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIsInstance(m, UserA) assert isinstance(m, UserA)
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIsInstance(m, UserA) assert isinstance(m, UserA)
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 2) assert q == 2
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 2) assert q == 2
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIsInstance(m, UserA) assert isinstance(m, UserA)
UserA.drop_collection() UserA.drop_collection()
Group.drop_collection() Group.drop_collection()
@ -990,64 +986,64 @@ class FieldTest(unittest.TestCase):
group.save() group.save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Document select_related # Document select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first().select_related() group_obj = Group.objects.first().select_related()
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
# Queryset select_related # Queryset select_related
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_objs = Group.objects.select_related() group_objs = Group.objects.select_related()
self.assertEqual(q, 4) assert q == 4
for group_obj in group_objs: for group_obj in group_objs:
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 4) assert q == 4
for k, m in iteritems(group_obj.members): for k, m in iteritems(group_obj.members):
self.assertIn("User", m.__class__.__name__) assert "User" in m.__class__.__name__
Group.objects.delete() Group.objects.delete()
Group().save() Group().save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
[m for m in group_obj.members] [m for m in group_obj.members]
self.assertEqual(q, 1) assert q == 1
UserA.drop_collection() UserA.drop_collection()
UserB.drop_collection() UserB.drop_collection()
@ -1075,8 +1071,8 @@ class FieldTest(unittest.TestCase):
root.save() root.save()
root = root.reload() root = root.reload()
self.assertEqual(root.children, [company]) assert root.children == [company]
self.assertEqual(company.parents, [root]) assert company.parents == [root]
def test_dict_in_dbref_instance(self): def test_dict_in_dbref_instance(self):
class Person(Document): class Person(Document):
@ -1102,8 +1098,8 @@ class FieldTest(unittest.TestCase):
room_101.save() room_101.save()
room = Room.objects.first().select_related() room = Room.objects.first().select_related()
self.assertEqual(room.staffs_with_position[0]["staff"], sarah) assert room.staffs_with_position[0]["staff"] == sarah
self.assertEqual(room.staffs_with_position[1]["staff"], bob) assert room.staffs_with_position[1]["staff"] == bob
def test_document_reload_no_inheritance(self): def test_document_reload_no_inheritance(self):
class Foo(Document): class Foo(Document):
@ -1133,8 +1129,8 @@ class FieldTest(unittest.TestCase):
foo.save() foo.save()
foo.reload() foo.reload()
self.assertEqual(type(foo.bar), Bar) assert type(foo.bar) == Bar
self.assertEqual(type(foo.baz), Baz) assert type(foo.baz) == Baz
def test_document_reload_reference_integrity(self): 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 = User.objects.get(id=1)
concurrent_change_user.name = "new-name" concurrent_change_user.name = "new-name"
concurrent_change_user.save() concurrent_change_user.save()
self.assertNotEqual(user.name, "new-name") assert user.name != "new-name"
msg = Message.objects.get(id=1) msg = Message.objects.get(id=1)
msg.reload() msg.reload()
self.assertEqual(msg.topic, topic) assert msg.topic == topic
self.assertEqual(msg.author, user) assert msg.author == user
self.assertEqual(msg.author.name, "new-name") assert msg.author.name == "new-name"
def test_list_lookup_not_checked_in_map(self): def test_list_lookup_not_checked_in_map(self):
"""Ensure we dereference list data correctly """Ensure we dereference list data correctly
@ -1194,8 +1190,8 @@ class FieldTest(unittest.TestCase):
Message(id=1, comments=[c1, c2]).save() Message(id=1, comments=[c1, c2]).save()
msg = Message.objects.get(id=1) msg = Message.objects.get(id=1)
self.assertEqual(0, msg.comments[0].id) assert 0 == msg.comments[0].id
self.assertEqual(1, msg.comments[1].id) assert 1 == msg.comments[1].id
def test_list_item_dereference_dref_false_save_doesnt_cause_extra_queries(self): def test_list_item_dereference_dref_false_save_doesnt_cause_extra_queries(self):
"""Ensure that DBRef items in ListFields are dereferenced. """Ensure that DBRef items in ListFields are dereferenced.
@ -1217,15 +1213,15 @@ class FieldTest(unittest.TestCase):
Group(name="Test", members=User.objects).save() Group(name="Test", members=User.objects).save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
group_obj.name = "new test" group_obj.name = "new test"
group_obj.save() group_obj.save()
self.assertEqual(q, 2) assert q == 2
def test_list_item_dereference_dref_true_save_doesnt_cause_extra_queries(self): def test_list_item_dereference_dref_true_save_doesnt_cause_extra_queries(self):
"""Ensure that DBRef items in ListFields are dereferenced. """Ensure that DBRef items in ListFields are dereferenced.
@ -1247,15 +1243,15 @@ class FieldTest(unittest.TestCase):
Group(name="Test", members=User.objects).save() Group(name="Test", members=User.objects).save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
group_obj.name = "new test" group_obj.name = "new test"
group_obj.save() group_obj.save()
self.assertEqual(q, 2) assert q == 2
def test_generic_reference_save_doesnt_cause_extra_queries(self): def test_generic_reference_save_doesnt_cause_extra_queries(self):
class UserA(Document): class UserA(Document):
@ -1287,15 +1283,15 @@ class FieldTest(unittest.TestCase):
Group(name="test", members=members).save() Group(name="test", members=members).save()
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
group_obj = Group.objects.first() group_obj = Group.objects.first()
self.assertEqual(q, 1) assert q == 1
group_obj.name = "new test" group_obj.name = "new test"
group_obj.save() group_obj.save()
self.assertEqual(q, 2) assert q == 2
def test_objectid_reference_across_databases(self): def test_objectid_reference_across_databases(self):
# mongoenginetest - Is default connection alias from setUp() # 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 # Can't use query_counter across databases - so test the _data object
book = Book.objects.first() book = Book.objects.first()
self.assertNotIsInstance(book._data["author"], User) assert not isinstance(book._data["author"], User)
book.select_related() book.select_related()
self.assertIsInstance(book._data["author"], User) assert isinstance(book._data["author"], User)
def test_non_ascii_pk(self): def test_non_ascii_pk(self):
""" """
@ -1346,7 +1342,7 @@ class FieldTest(unittest.TestCase):
BrandGroup(title="top_brands", brands=[brand1, brand2]).save() BrandGroup(title="top_brands", brands=[brand1, brand2]).save()
brand_groups = BrandGroup.objects().all() 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): def test_dereferencing_embedded_listfield_referencefield(self):
class Tag(Document): class Tag(Document):
@ -1370,7 +1366,7 @@ class FieldTest(unittest.TestCase):
Page(tags=[tag], posts=[post]).save() Page(tags=[tag], posts=[post]).save()
page = Page.objects.first() 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): def test_select_related_follows_embedded_referencefields(self):
class Song(Document): class Song(Document):
@ -1390,12 +1386,12 @@ class FieldTest(unittest.TestCase):
playlist = Playlist.objects.create(items=items) playlist = Playlist.objects.create(items=items)
with query_counter() as q: with query_counter() as q:
self.assertEqual(q, 0) assert q == 0
playlist = Playlist.objects.first().select_related() playlist = Playlist.objects.first().select_related()
songs = [item.song for item in playlist.items] songs = [item.song for item in playlist.items]
self.assertEqual(q, 2) assert q == 2
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,7 +1,6 @@
import unittest import unittest
from pymongo import ReadPreference from pymongo import MongoClient, ReadPreference
from pymongo import MongoClient
import mongoengine import mongoengine
from mongoengine.connection import ConnectionFailure from mongoengine.connection import ConnectionFailure
@ -25,21 +24,20 @@ class ConnectionTest(unittest.TestCase):
def test_replicaset_uri_passes_read_preference(self): def test_replicaset_uri_passes_read_preference(self):
"""Requires a replica set called "rs" on port 27017 """Requires a replica set called "rs" on port 27017
""" """
try: try:
conn = mongoengine.connect( conn = mongoengine.connect(
db="mongoenginetest", db="mongoenginetest",
host="mongodb://localhost/mongoenginetest?replicaSet=rs", host="mongodb://localhost/mongoenginetest?replicaSet=rs",
read_preference=READ_PREF, read_preference=READ_PREF,
) )
except ConnectionFailure as e: except ConnectionFailure:
return return
if not isinstance(conn, CONN_CLASS): if not isinstance(conn, CONN_CLASS):
# really??? # really???
return return
self.assertEqual(conn.read_preference, READ_PREF) assert conn.read_preference == READ_PREF
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -7,7 +7,7 @@ from mongoengine import signals
signal_output = [] signal_output = []
class SignalTests(unittest.TestCase): class TestSignal(unittest.TestCase):
""" """
Testing signals before/after saving and deleting. 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 # Note that there is a chance that the following assert fails in case
# some receivers (eventually created in other tests) # some receivers (eventually created in other tests)
# gets garbage collected (https://pythonhosted.org/blinker/#blinker.base.Signal.connect) # 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): def test_model_signals(self):
""" Model saves should throw some signals. """ """ Model saves should throw some signals. """
@ -267,97 +267,76 @@ class SignalTests(unittest.TestCase):
self.get_signal_output(lambda: None) # eliminate signal output self.get_signal_output(lambda: None) # eliminate signal output
a1 = self.Author.objects(name="Bill Shakespeare")[0] a1 = self.Author.objects(name="Bill Shakespeare")[0]
self.assertEqual( assert self.get_signal_output(create_author) == [
self.get_signal_output(create_author), "pre_init signal, Author",
[ {"name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = True",
{"name": "Bill Shakespeare"}, ]
"post_init signal, Bill Shakespeare, document._created = True",
],
)
a1 = self.Author(name="Bill Shakespeare") a1 = self.Author(name="Bill Shakespeare")
self.assertEqual( assert self.get_signal_output(a1.save) == [
self.get_signal_output(a1.save), "pre_save signal, Bill Shakespeare",
[ {},
"pre_save signal, Bill Shakespeare", "pre_save_post_validation signal, Bill Shakespeare",
{}, "Is created",
"pre_save_post_validation signal, Bill Shakespeare", {},
"Is created", "post_save signal, Bill Shakespeare",
{}, "post_save dirty keys, ['name']",
"post_save signal, Bill Shakespeare", "Is created",
"post_save dirty keys, ['name']", {},
"Is created", ]
{},
],
)
a1.reload() a1.reload()
a1.name = "William Shakespeare" a1.name = "William Shakespeare"
self.assertEqual( assert self.get_signal_output(a1.save) == [
self.get_signal_output(a1.save), "pre_save signal, William Shakespeare",
[ {},
"pre_save signal, William Shakespeare", "pre_save_post_validation signal, William Shakespeare",
{}, "Is updated",
"pre_save_post_validation signal, William Shakespeare", {},
"Is updated", "post_save signal, William Shakespeare",
{}, "post_save dirty keys, ['name']",
"post_save signal, William Shakespeare", "Is updated",
"post_save dirty keys, ['name']", {},
"Is updated", ]
{},
],
)
self.assertEqual( assert self.get_signal_output(a1.delete) == [
self.get_signal_output(a1.delete), "pre_delete signal, William Shakespeare",
[ {},
"pre_delete signal, William Shakespeare", "post_delete signal, William Shakespeare",
{}, {},
"post_delete signal, William Shakespeare", ]
{},
],
)
self.assertEqual( assert self.get_signal_output(load_existing_author) == [
self.get_signal_output(load_existing_author), "pre_init signal, Author",
[ {"id": 2, "name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = False",
{"id": 2, "name": "Bill Shakespeare"}, ]
"post_init signal, Bill Shakespeare, document._created = False",
],
)
self.assertEqual( assert self.get_signal_output(bulk_create_author_with_load) == [
self.get_signal_output(bulk_create_author_with_load), "pre_init signal, Author",
[ {"name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = True",
{"name": "Bill Shakespeare"}, "pre_bulk_insert signal, [<Author: 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"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = False",
{"id": 3, "name": "Bill Shakespeare"}, "post_bulk_insert signal, [<Author: Bill Shakespeare>]",
"post_init signal, Bill Shakespeare, document._created = False", "Is loaded",
"post_bulk_insert signal, [<Author: Bill Shakespeare>]", {},
"Is loaded", ]
{},
],
)
self.assertEqual( assert self.get_signal_output(bulk_create_author_without_load) == [
self.get_signal_output(bulk_create_author_without_load), "pre_init signal, Author",
[ {"name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = True",
{"name": "Bill Shakespeare"}, "pre_bulk_insert signal, [<Author: 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",
"post_bulk_insert signal, [<Author: Bill Shakespeare>]", {},
"Not loaded", ]
{},
],
)
def test_signal_kwargs(self): def test_signal_kwargs(self):
""" Make sure signal_kwargs is passed to signals calls. """ """ 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.save(signal_kwargs={"live": True, "die": False})
a.delete(signal_kwargs={"live": False, "die": True}) a.delete(signal_kwargs={"live": False, "die": True})
self.assertEqual( assert self.get_signal_output(live_and_let_die) == [
self.get_signal_output(live_and_let_die), "pre_init signal, Author",
[ {"name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = True",
{"name": "Bill Shakespeare"}, "pre_save signal, Bill Shakespeare",
"post_init signal, Bill Shakespeare, document._created = True", {"die": False, "live": True},
"pre_save signal, Bill Shakespeare", "pre_save_post_validation signal, Bill Shakespeare",
{"die": False, "live": True}, "Is created",
"pre_save_post_validation signal, Bill Shakespeare", {"die": False, "live": True},
"Is created", "post_save signal, Bill Shakespeare",
{"die": False, "live": True}, "post_save dirty keys, ['name']",
"post_save signal, Bill Shakespeare", "Is created",
"post_save dirty keys, ['name']", {"die": False, "live": True},
"Is created", "pre_delete signal, Bill Shakespeare",
{"die": False, "live": True}, {"die": True, "live": False},
"pre_delete signal, Bill Shakespeare", "post_delete signal, Bill Shakespeare",
{"die": True, "live": False}, {"die": True, "live": False},
"post_delete signal, Bill Shakespeare", ]
{"die": True, "live": False},
],
)
def bulk_create_author(): def bulk_create_author():
a1 = self.Author(name="Bill Shakespeare") a1 = self.Author(name="Bill Shakespeare")
self.Author.objects.insert([a1], signal_kwargs={"key": True}) self.Author.objects.insert([a1], signal_kwargs={"key": True})
self.assertEqual( assert self.get_signal_output(bulk_create_author) == [
self.get_signal_output(bulk_create_author), "pre_init signal, Author",
[ {"name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = True",
{"name": "Bill Shakespeare"}, "pre_bulk_insert signal, [<Author: Bill Shakespeare>]",
"post_init signal, Bill Shakespeare, document._created = True", {"key": True},
"pre_bulk_insert signal, [<Author: Bill Shakespeare>]", "pre_init signal, Author",
{"key": True}, {"id": 2, "name": "Bill Shakespeare"},
"pre_init signal, Author", "post_init signal, Bill Shakespeare, document._created = False",
{"id": 2, "name": "Bill Shakespeare"}, "post_bulk_insert signal, [<Author: Bill Shakespeare>]",
"post_init signal, Bill Shakespeare, document._created = False", "Is loaded",
"post_bulk_insert signal, [<Author: Bill Shakespeare>]", {"key": True},
"Is loaded", ]
{"key": True},
],
)
def test_queryset_delete_signals(self): def test_queryset_delete_signals(self):
""" Queryset delete should throw some signals. """ """ Queryset delete should throw some signals. """
self.Another(name="Bill Shakespeare").save() self.Another(name="Bill Shakespeare").save()
self.assertEqual( assert self.get_signal_output(self.Another.objects.delete) == [
self.get_signal_output(self.Another.objects.delete), "pre_delete signal, Bill Shakespeare",
[ {},
"pre_delete signal, Bill Shakespeare", "post_delete signal, Bill Shakespeare",
{}, {},
"post_delete signal, Bill Shakespeare", ]
{},
],
)
def test_signals_with_explicit_doc_ids(self): def test_signals_with_explicit_doc_ids(self):
""" Model saves must have a created flag the first time.""" """ Model saves must have a created flag the first time."""
ei = self.ExplicitId(id=123) ei = self.ExplicitId(id=123)
# post save must received the created flag, even if there's already # post save must received the created flag, even if there's already
# an object id present # 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 # 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): def test_signals_with_switch_collection(self):
ei = self.ExplicitId(id=123) ei = self.ExplicitId(id=123)
ei.switch_collection("explicit__1") 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") 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) 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) 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): def test_signals_with_switch_db(self):
connect("mongoenginetest") connect("mongoenginetest")
@ -451,14 +421,14 @@ class SignalTests(unittest.TestCase):
ei = self.ExplicitId(id=123) ei = self.ExplicitId(id=123)
ei.switch_db("testdb-1") 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") 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) 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) 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 test_signals_bulk_insert(self):
def bulk_set_active_post(): def bulk_set_active_post():
@ -470,16 +440,13 @@ class SignalTests(unittest.TestCase):
self.Post.objects.insert(posts) self.Post.objects.insert(posts)
results = self.get_signal_output(bulk_set_active_post) results = self.get_signal_output(bulk_set_active_post)
self.assertEqual( assert results == [
results, "pre_bulk_insert signal, [(<Post: Post 1>, {'active': False}), (<Post: Post 2>, {'active': False}), (<Post: Post 3>, {'active': False})]",
[ {},
"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",
"post_bulk_insert signal, [(<Post: Post 1>, {'active': True}), (<Post: Post 2>, {'active': True}), (<Post: Post 3>, {'active': True})]", {},
"Is loaded", ]
{},
],
)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,32 +1,34 @@
import unittest
import re import re
import unittest
import pytest
from mongoengine.base.utils import LazyRegexCompiler from mongoengine.base.utils import LazyRegexCompiler
signal_output = [] signal_output = []
class LazyRegexCompilerTest(unittest.TestCase): class TestLazyRegexCompiler:
def test_lazy_regex_compiler_verify_laziness_of_descriptor(self): def test_lazy_regex_compiler_verify_laziness_of_descriptor(self):
class UserEmail(object): class UserEmail(object):
EMAIL_REGEX = LazyRegexCompiler("@", flags=32) EMAIL_REGEX = LazyRegexCompiler("@", flags=32)
descriptor = UserEmail.__dict__["EMAIL_REGEX"] descriptor = UserEmail.__dict__["EMAIL_REGEX"]
self.assertIsNone(descriptor._compiled_regex) assert descriptor._compiled_regex is None
regex = UserEmail.EMAIL_REGEX regex = UserEmail.EMAIL_REGEX
self.assertEqual(regex, re.compile("@", flags=32)) assert regex == re.compile("@", flags=32)
self.assertEqual(regex.search("user@domain.com").group(), "@") assert regex.search("user@domain.com").group() == "@"
user_email = UserEmail() 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): def test_lazy_regex_compiler_verify_cannot_set_descriptor_on_instance(self):
class UserEmail(object): class UserEmail(object):
EMAIL_REGEX = LazyRegexCompiler("@") EMAIL_REGEX = LazyRegexCompiler("@")
user_email = UserEmail() user_email = UserEmail()
with self.assertRaises(AttributeError): with pytest.raises(AttributeError):
user_email.EMAIL_REGEX = re.compile("@") user_email.EMAIL_REGEX = re.compile("@")
def test_lazy_regex_compiler_verify_can_override_class_attr(self): def test_lazy_regex_compiler_verify_can_override_class_attr(self):
@ -34,6 +36,4 @@ class LazyRegexCompilerTest(unittest.TestCase):
EMAIL_REGEX = LazyRegexCompiler("@") EMAIL_REGEX = LazyRegexCompiler("@")
UserEmail.EMAIL_REGEX = re.compile("cookies") UserEmail.EMAIL_REGEX = re.compile("cookies")
self.assertEqual( assert UserEmail.EMAIL_REGEX.search("Cake & cookies").group() == "cookies"
UserEmail.EMAIL_REGEX.search("Cake & cookies").group(), "cookies"
)

View File

@ -1,10 +1,9 @@
import operator
import unittest import unittest
from nose.plugins.skip import SkipTest import pytest
from mongoengine import connect 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 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): def _decorated_with_ver_requirement(func, mongo_version_req, oper):
"""Return a MongoDB version requirement decorator. """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. MongoDB version doesn't match the provided version/operator.
For example, if you define a decorator like so: 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): if oper(mongodb_v, mongo_version_req):
return func(*args, **kwargs) return func(*args, **kwargs)
raise SkipTest( pretty_version = ".".join(str(n) for n in mongo_version_req)
"Needs MongoDB v{}+".format(".".join(str(n) for n in mongo_version_req)) pytest.skip("Needs MongoDB v{}+".format(pretty_version))
)
_inner.__name__ = func.__name__ _inner.__name__ = func.__name__
_inner.__doc__ = func.__doc__ _inner.__doc__ = func.__doc__

View File

@ -3,11 +3,11 @@ envlist = {py27,py35,pypy,pypy3}-{mg34,mg36, mg39}
[testenv] [testenv]
commands = commands =
python setup.py nosetests {posargs} python setup.py test {posargs}
deps = deps =
nose
mg34: pymongo>=3.4,<3.5 mg34: pymongo>=3.4,<3.5
mg36: pymongo>=3.6,<3.7 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 = setenv =
PYTHON_EGG_CACHE = {envdir}/python-eggs PYTHON_EGG_CACHE = {envdir}/python-eggs