Skip to content

Commit c85b59d

Browse files
committed
Merge branch 'master' of github.com:MongoEngine/mongoengine into negative_indexes_in_list
2 parents c68e3e1 + 1170de1 commit c85b59d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+5038
-4830
lines changed

.travis.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ env:
3232
global:
3333
- MONGODB_3_4=3.4.17
3434
- MONGODB_3_6=3.6.12
35+
- PYMONGO_3_9=3.9
3536
- PYMONGO_3_6=3.6
3637
- PYMONGO_3_4=3.4
3738
matrix:
38-
- MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_6}
39+
- MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_9}
3940

4041
matrix:
4142

@@ -47,6 +48,8 @@ matrix:
4748
env: MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_4}
4849
- python: 3.7
4950
env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_6}
51+
- python: 3.7
52+
env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_9}
5053

5154

5255
install:
@@ -60,8 +63,8 @@ install:
6063
- pip install flake8 flake8-import-order
6164
- pip install tox # tox 3.11.0 has requirement virtualenv>=14.0.0
6265
- pip install virtualenv # virtualenv>=14.0.0 has dropped Python 3.2 support (and pypy3 is based on py32)
63-
# Install the tox venv.
64-
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -e test
66+
# tox dryrun to setup the tox venv (we run a mock test).
67+
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "-k=test_ci_placeholder"
6568
# Install black for Python v3.7 only.
6669
- if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then pip install black; fi
6770

@@ -73,13 +76,13 @@ before_script:
7376
- mongo --eval 'db.version();' # Make sure mongo is awake
7477

7578
script:
76-
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- --with-coverage
79+
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "--cov=mongoengine"
7780

7881
# For now only submit coveralls for Python v2.7. Python v3.x currently shows
7982
# 0% coverage. That's caused by 'use_2to3', which builds the py3-compatible
8083
# code in a separate dir and runs tests on that.
8184
after_success:
82-
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then coveralls --verbose; fi
85+
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then coveralls --verbose; else echo "coveralls only sent for py27"; fi
8386

8487
notifications:
8588
irc: irc.freenode.org#mongoengine

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,5 @@ that much better:
252252
* Paulo Amaral (https://github.com/pauloAmaral)
253253
* Gaurav Dadhania (https://github.com/GVRV)
254254
* Yurii Andrieiev (https://github.com/yandrieiev)
255+
* Filip Kucharczyk (https://github.com/Pacu2)
256+
* Eric Timmons (https://github.com/daewok)

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ General Guidelines
5454
should adapt to the breaking change in docs/upgrade.rst.
5555
- Write inline documentation for new classes and methods.
5656
- Write tests and make sure they pass (make sure you have a mongod
57-
running on the default port, then execute ``python setup.py nosetests``
57+
running on the default port, then execute ``python setup.py test``
5858
from the cmd line to run the test suite).
5959
- Ensure tests pass on all supported Python, PyMongo, and MongoDB versions.
6060
You can test various Python and PyMongo versions locally by executing

README.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ Some simple examples of what MongoEngine code looks like:
116116
Tests
117117
=====
118118
To run the test suite, ensure you are running a local instance of MongoDB on
119-
the standard port and have ``nose`` installed. Then, run ``python setup.py nosetests``.
119+
the standard port and have ``pytest`` installed. Then, run ``python setup.py test``
120+
or simply ``pytest``.
120121

121122
To run the test suite on every supported Python and PyMongo version, you can
122123
use ``tox``. You'll need to make sure you have each supported Python version
@@ -129,16 +130,14 @@ installed in your environment and then:
129130
# Run the test suites
130131
$ tox
131132
132-
If you wish to run a subset of tests, use the nosetests convention:
133+
If you wish to run a subset of tests, use the pytest convention:
133134

134135
.. code-block:: shell
135136
136137
# Run all the tests in a particular test file
137-
$ python setup.py nosetests --tests tests/fields/fields.py
138+
$ pytest tests/fields/test_fields.py
138139
# Run only particular test class in that file
139-
$ python setup.py nosetests --tests tests/fields/fields.py:FieldTest
140-
# Use the -s option if you want to print some debug statements or use pdb
141-
$ python setup.py nosetests --tests tests/fields/fields.py:FieldTest -s
140+
$ pytest tests/fields/test_fields.py::TestField
142141
143142
Community
144143
=========

docs/changelog.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Changelog
66
Development
77
===========
88
- (Fill this out as you fix issues and develop your features).
9+
- Documentation improvements:
10+
- Documented how `pymongo.monitoring` can be used to log all queries issued by MongoEngine to the driver.
911
- BREAKING CHANGE: ``class_check`` and ``read_preference`` keyword arguments are no longer available when filtering a ``QuerySet``. #2112
1012
- Instead of ``Doc.objects(foo=bar, read_preference=...)`` use ``Doc.objects(foo=bar).read_preference(...)``.
1113
- Instead of ``Doc.objects(foo=bar, class_check=False)`` use ``Doc.objects(foo=bar).clear_cls_query(...)``.
@@ -15,9 +17,18 @@ Development
1517
- If you catch/use ``MongoEngineConnectionError`` in your code, you'll have to rename it.
1618
- BREAKING CHANGE: Positional arguments when instantiating a document are no longer supported. #2103
1719
- From now on keyword arguments (e.g. ``Doc(field_name=value)``) are required.
20+
- 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
21+
- DEPRECATION: ``Q.empty`` & ``QNode.empty`` are marked as deprecated and will be removed in a next version of MongoEngine. #2210
22+
- Added ability to check if Q or QNode are empty by parsing them to bool.
23+
- Instead of ``Q(name="John").empty`` use ``not Q(name="John")``.
24+
- Improve error message related to InvalidDocumentError #2180
1825
- Fix updating/modifying/deleting/reloading a document that's sharded by a field with ``db_field`` specified. #2125
1926
- ``ListField`` now accepts an optional ``max_length`` parameter. #2110
27+
- Switch from nosetest to pytest as test runner #2114
2028
- The codebase is now formatted using ``black``. #2109
29+
- In bulk write insert, the detailed error message would raise in exception.
30+
- Added ability to compare Q and Q operations #2204
31+
- Added ability to use a db alias on query_counter #2194
2132

2233
Changes in 0.18.2
2334
=================

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
# All configuration values have a default; values that are commented out
1212
# serve to show the default.
1313

14-
import sys, os
14+
import os
15+
import sys
1516

1617
import sphinx_rtd_theme
1718

docs/faq.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
==========================
2+
Frequently Asked Questions
3+
==========================
4+
5+
Does MongoEngine support asynchronous drivers (Motor, TxMongo)?
6+
---------------------------------------------------------------
7+
8+
No, MongoEngine is exclusively based on PyMongo and isn't designed to support other driver.
9+
If this is a requirement for your project, check the alternative: `uMongo`_ and `MotorEngine`_.
10+
11+
.. _uMongo: https://umongo.readthedocs.io/
12+
.. _MotorEngine: https://motorengine.readthedocs.io/
13+

docs/guide/defining-documents.rst

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ Its value can take any of the following constants:
352352
Deletion is denied if there still exist references to the object being
353353
deleted.
354354
:const:`mongoengine.NULLIFY`
355-
Any object's fields still referring to the object being deleted are removed
355+
Any object's fields still referring to the object being deleted are set to None
356356
(using MongoDB's "unset" operation), effectively nullifying the relationship.
357357
:const:`mongoengine.CASCADE`
358358
Any object containing fields that are referring to the object being deleted
@@ -744,7 +744,7 @@ Document inheritance
744744

745745
To create a specialised type of a :class:`~mongoengine.Document` you have
746746
defined, you may subclass it and add any extra fields or methods you may need.
747-
As this is new class is not a direct subclass of
747+
As this new class is not a direct subclass of
748748
:class:`~mongoengine.Document`, it will not be stored in its own collection; it
749749
will use the same collection as its superclass uses. This allows for more
750750
convenient and efficient retrieval of related documents -- all you need do is
@@ -767,6 +767,27 @@ document.::
767767
Setting :attr:`allow_inheritance` to True should also be used in
768768
:class:`~mongoengine.EmbeddedDocument` class in case you need to subclass it
769769

770+
When it comes to querying using :attr:`.objects()`, querying `Page.objects()` will query
771+
both `Page` and `DatedPage` whereas querying `DatedPage` will only query the `DatedPage` documents.
772+
Behind the scenes, MongoEngine deals with inheritance by adding a :attr:`_cls` attribute that contains
773+
the class name in every documents. When a document is loaded, MongoEngine checks
774+
it's :attr:`_cls` attribute and use that class to construct the instance.::
775+
776+
Page(title='a funky title').save()
777+
DatedPage(title='another title', date=datetime.utcnow()).save()
778+
779+
print(Page.objects().count()) # 2
780+
print(DatedPage.objects().count()) # 1
781+
782+
# print documents in their native form
783+
# we remove 'id' to avoid polluting the output with unnecessary detail
784+
qs = Page.objects.exclude('id').as_pymongo()
785+
print(list(qs))
786+
# [
787+
# {'_cls': u 'Page', 'title': 'a funky title'},
788+
# {'_cls': u 'Page.DatedPage', 'title': u 'another title', 'date': datetime.datetime(2019, 12, 13, 20, 16, 59, 993000)}
789+
# ]
790+
770791
Working with existing data
771792
--------------------------
772793
As MongoEngine no longer defaults to needing :attr:`_cls`, you can quickly and

docs/guide/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ User Guide
1313
gridfs
1414
signals
1515
text-indexes
16+
logging-monitoring
1617
mongomock

docs/guide/logging-monitoring.rst

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
==================
2+
Logging/Monitoring
3+
==================
4+
5+
It is possible to use `pymongo.monitoring <https://api.mongodb.com/python/current/api/pymongo/monitoring.html>`_ to monitor
6+
the driver events (e.g: queries, connections, etc). This can be handy if you want to monitor the queries issued by
7+
MongoEngine to the driver.
8+
9+
To use `pymongo.monitoring` with MongoEngine, you need to make sure that you are registering the listeners
10+
**before** establishing the database connection (i.e calling `connect`):
11+
12+
The following snippet provides a basic logging of all command events:
13+
14+
.. code-block:: python
15+
16+
import logging
17+
from pymongo import monitoring
18+
from mongoengine import *
19+
20+
log = logging.getLogger()
21+
log.setLevel(logging.DEBUG)
22+
logging.basicConfig(level=logging.DEBUG)
23+
24+
25+
class CommandLogger(monitoring.CommandListener):
26+
27+
def started(self, event):
28+
log.debug("Command {0.command_name} with request id "
29+
"{0.request_id} started on server "
30+
"{0.connection_id}".format(event))
31+
32+
def succeeded(self, event):
33+
log.debug("Command {0.command_name} with request id "
34+
"{0.request_id} on server {0.connection_id} "
35+
"succeeded in {0.duration_micros} "
36+
"microseconds".format(event))
37+
38+
def failed(self, event):
39+
log.debug("Command {0.command_name} with request id "
40+
"{0.request_id} on server {0.connection_id} "
41+
"failed in {0.duration_micros} "
42+
"microseconds".format(event))
43+
44+
monitoring.register(CommandLogger())
45+
46+
47+
class Jedi(Document):
48+
name = StringField()
49+
50+
51+
connect()
52+
53+
54+
log.info('GO!')
55+
56+
log.info('Saving an item through MongoEngine...')
57+
Jedi(name='Obi-Wan Kenobii').save()
58+
59+
log.info('Querying through MongoEngine...')
60+
obiwan = Jedi.objects.first()
61+
62+
log.info('Updating through MongoEngine...')
63+
obiwan.name = 'Obi-Wan Kenobi'
64+
obiwan.save()
65+
66+
67+
Executing this prints the following output::
68+
69+
INFO:root:GO!
70+
INFO:root:Saving an item through MongoEngine...
71+
DEBUG:root:Command insert with request id 1681692777 started on server ('localhost', 27017)
72+
DEBUG:root:Command insert with request id 1681692777 on server ('localhost', 27017) succeeded in 562 microseconds
73+
INFO:root:Querying through MongoEngine...
74+
DEBUG:root:Command find with request id 1714636915 started on server ('localhost', 27017)
75+
DEBUG:root:Command find with request id 1714636915 on server ('localhost', 27017) succeeded in 341 microseconds
76+
INFO:root:Updating through MongoEngine...
77+
DEBUG:root:Command update with request id 1957747793 started on server ('localhost', 27017)
78+
DEBUG:root:Command update with request id 1957747793 on server ('localhost', 27017) succeeded in 455 microseconds
79+
80+
More details can of course be obtained by checking the `event` argument from the `CommandListener`.

0 commit comments

Comments
 (0)