summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalvo 'LtWorf' Tomaselli <ltworf@debian.org>2024-10-15 01:01:58 +0200
committergit-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com>2024-10-15 04:44:20 +0000
commit926b939d3582f54b9730b4b33f5e14431970cf7c (patch)
treeacb2ba80db9cb979c8fc9fee40cd9ce6e03726d1
parent78ab29bd8d914f4c96246eaa0cc836644117d3be (diff)
Imported using git-ubuntu import.
Notes
Notes: * Team upload * New upstream release * Fix autopkgtest * Require the new pymongo
-rw-r--r--AUTHORS1
-rw-r--r--PKG-INFO29
-rw-r--r--README.rst22
-rw-r--r--debian/changelog9
-rw-r--r--debian/control4
-rw-r--r--debian/tests/test-mongoengine3
-rw-r--r--docs/Makefile34
-rw-r--r--docs/apireference.rst1
-rw-r--r--docs/changelog.rst20
-rw-r--r--docs/django.rst15
-rw-r--r--docs/faq.rst4
-rw-r--r--docs/guide/connecting.rst2
-rw-r--r--docs/guide/defining-documents.rst28
-rw-r--r--docs/guide/gridfs.rst2
-rw-r--r--docs/guide/installing.rst4
-rw-r--r--docs/guide/migration.rst2
-rw-r--r--docs/guide/mongomock.rst2
-rw-r--r--docs/guide/querying.rst8
-rw-r--r--docs/index.rst16
-rw-r--r--docs/requirements.txt10
-rw-r--r--mongoengine.egg-info/PKG-INFO29
-rw-r--r--mongoengine.egg-info/requires.txt7
-rw-r--r--mongoengine/__init__.py2
-rw-r--r--mongoengine/base/datastructures.py10
-rw-r--r--mongoengine/base/document.py15
-rw-r--r--mongoengine/base/fields.py52
-rw-r--r--mongoengine/connection.py6
-rw-r--r--mongoengine/context_managers.py48
-rw-r--r--mongoengine/document.py23
-rw-r--r--mongoengine/fields.py32
-rw-r--r--mongoengine/mongodb_support.py1
-rw-r--r--mongoengine/pymongo_support.py1
-rw-r--r--mongoengine/queryset/base.py33
-rw-r--r--mongoengine/signals.py6
-rw-r--r--setup.py101
35 files changed, 301 insertions, 281 deletions
diff --git a/AUTHORS b/AUTHORS
index 40508b5..0a50af7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -264,3 +264,4 @@ that much better:
* oleksandr-l5 (https://github.com/oleksandr-l5)
* Ido Shraga (https://github.com/idoshr)
* Terence Honles (https://github.com/terencehonles)
+ * Sean Bermejo (https://github.com/seanbermejo)
diff --git a/PKG-INFO b/PKG-INFO
index b83bf81..3daf721 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
Metadata-Version: 2.1
Name: mongoengine
-Version: 0.28.2
+Version: 0.29.1
Summary: MongoEngine is a Python Object-Document Mapper for working with MongoDB.
Home-page: http://mongoengine.org/
Author: Harry Marr
Author-email: harry.marr@gmail.com
-Maintainer: Stefan Wojcik
-Maintainer-email: wojcikstefan@gmail.com
+Maintainer: Bastien Gerard
+Maintainer-email: bast.gerard@gmail.com
License: MIT
Download-URL: https://github.com/MongoEngine/mongoengine/tarball/master
Platform: any
@@ -24,6 +24,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
+Provides-Extra: test
License-File: LICENSE
License-File: AUTHORS
@@ -33,7 +34,7 @@ MongoEngine
:Info: MongoEngine is an ORM-like layer on top of PyMongo.
:Repository: https://github.com/MongoEngine/mongoengine
:Author: Harry Marr (http://github.com/hmarr)
-:Maintainer: Stefan Wójcik (http://github.com/wojcikstefan)
+:Maintainer: Bastien Gerard (http://github.com/bagerard)
.. image:: https://travis-ci.org/MongoEngine/mongoengine.svg?branch=master
:target: https://travis-ci.org/MongoEngine/mongoengine
@@ -50,6 +51,10 @@ MongoEngine
.. image:: https://img.shields.io/pypi/v/mongoengine.svg
:target: https://pypi.python.org/pypi/mongoengine
+
+.. image:: https://readthedocs.org/projects/mongoengine-odm/badge/?version=latest
+ :target: https://readthedocs.org/projects/mongoengine-odm/builds/
+
About
=====
MongoEngine is a Python Object-Document Mapper for working with MongoDB.
@@ -73,7 +78,7 @@ You may also have `setuptools <http://peak.telecommunity.com/DevCenter/setuptool
and thus you can use ``easy_install -U mongoengine``. Another option is
`pipenv <https://docs.pipenv.org/>`_. You can then use ``pipenv install mongoengine``
to both create the virtual environment and install the package. Otherwise, you can
-download the source from `GitHub <http://github.com/MongoEngine/mongoengine>`_ and
+download the source from `GitHub <https://github.com/MongoEngine/mongoengine>`_ and
run ``python setup.py install``.
The support for Python2 was dropped with MongoEngine 0.20.0
@@ -91,7 +96,7 @@ If you utilize a ``DateTimeField``, you might also use a more flexible date pars
If you need to use an ``ImageField`` or ``ImageGridFsProxy``:
-- Pillow>=2.0.0
+- Pillow>=7.0.0
If you need to use signals:
@@ -154,8 +159,7 @@ Some simple examples of what MongoEngine code looks like:
Tests
=====
To run the test suite, ensure you are running a local instance of MongoDB on
-the standard port and have ``pytest`` installed. Then, run ``python setup.py test``
-or simply ``pytest``.
+the standard port and have ``pytest`` installed. Then, run ``pytest tests/``.
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
@@ -168,15 +172,6 @@ installed in your environment and then:
# Run the test suites
$ tox
-If you wish to run a subset of tests, use the pytest convention:
-
-.. code-block:: shell
-
- # Run all the tests in a particular test file
- $ pytest tests/fields/test_fields.py
- # Run only particular test class in that file
- $ pytest tests/fields/test_fields.py::TestField
-
Community
=========
- `MongoEngine Users mailing list
diff --git a/README.rst b/README.rst
index 64e43b6..d7cf6d3 100644
--- a/README.rst
+++ b/README.rst
@@ -4,7 +4,7 @@ MongoEngine
:Info: MongoEngine is an ORM-like layer on top of PyMongo.
:Repository: https://github.com/MongoEngine/mongoengine
:Author: Harry Marr (http://github.com/hmarr)
-:Maintainer: Stefan Wójcik (http://github.com/wojcikstefan)
+:Maintainer: Bastien Gerard (http://github.com/bagerard)
.. image:: https://travis-ci.org/MongoEngine/mongoengine.svg?branch=master
:target: https://travis-ci.org/MongoEngine/mongoengine
@@ -21,6 +21,10 @@ MongoEngine
.. image:: https://img.shields.io/pypi/v/mongoengine.svg
:target: https://pypi.python.org/pypi/mongoengine
+
+.. image:: https://readthedocs.org/projects/mongoengine-odm/badge/?version=latest
+ :target: https://readthedocs.org/projects/mongoengine-odm/builds/
+
About
=====
MongoEngine is a Python Object-Document Mapper for working with MongoDB.
@@ -44,7 +48,7 @@ You may also have `setuptools <http://peak.telecommunity.com/DevCenter/setuptool
and thus you can use ``easy_install -U mongoengine``. Another option is
`pipenv <https://docs.pipenv.org/>`_. You can then use ``pipenv install mongoengine``
to both create the virtual environment and install the package. Otherwise, you can
-download the source from `GitHub <http://github.com/MongoEngine/mongoengine>`_ and
+download the source from `GitHub <https://github.com/MongoEngine/mongoengine>`_ and
run ``python setup.py install``.
The support for Python2 was dropped with MongoEngine 0.20.0
@@ -62,7 +66,7 @@ If you utilize a ``DateTimeField``, you might also use a more flexible date pars
If you need to use an ``ImageField`` or ``ImageGridFsProxy``:
-- Pillow>=2.0.0
+- Pillow>=7.0.0
If you need to use signals:
@@ -125,8 +129,7 @@ Some simple examples of what MongoEngine code looks like:
Tests
=====
To run the test suite, ensure you are running a local instance of MongoDB on
-the standard port and have ``pytest`` installed. Then, run ``python setup.py test``
-or simply ``pytest``.
+the standard port and have ``pytest`` installed. Then, run ``pytest tests/``.
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
@@ -139,15 +142,6 @@ installed in your environment and then:
# Run the test suites
$ tox
-If you wish to run a subset of tests, use the pytest convention:
-
-.. code-block:: shell
-
- # Run all the tests in a particular test file
- $ pytest tests/fields/test_fields.py
- # Run only particular test class in that file
- $ pytest tests/fields/test_fields.py::TestField
-
Community
=========
- `MongoEngine Users mailing list
diff --git a/debian/changelog b/debian/changelog
index b4536a7..3bf2f72 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+python-mongoengine (0.29.1-1) unstable; urgency=high
+
+ * Team upload
+ * New upstream release
+ * Fix autopkgtest
+ * Require the new pymongo
+
+ -- Salvo 'LtWorf' Tomaselli <ltworf@debian.org> Tue, 15 Oct 2024 01:01:58 +0200
+
python-mongoengine (0.28.2-1) unstable; urgency=medium
* Team upload
diff --git a/debian/control b/debian/control
index b1f149a..9762b31 100644
--- a/debian/control
+++ b/debian/control
@@ -11,7 +11,7 @@ Build-Depends:
python3-coverage,
python3-gridfs,
python3-pillow,
- python3-pymongo,
+ python3-pymongo (>= 4.10.1-2),
python3-setuptools,
python3-sphinx,
python3-sphinx-rtd-theme,
@@ -26,7 +26,7 @@ Package: python3-mongoengine
Architecture: all
Depends:
python3-gridfs,
- python3-pymongo,
+ python3-pymongo (>= 4.10.1-2),
${misc:Depends},
${python3:Depends},
Suggests:
diff --git a/debian/tests/test-mongoengine b/debian/tests/test-mongoengine
index 7d8f0b7..7d425fa 100644
--- a/debian/tests/test-mongoengine
+++ b/debian/tests/test-mongoengine
@@ -7,11 +7,12 @@ cd "${AUTOPKGTEST_TMP}"
cat <<EOF > test_mongo.py
from mongoengine import *
import pymongo
+import pymongo.database
connect('mongo_test')
conn = get_connection()
-assert isinstance(conn, pymongo.mongo_client.MongoClient)
+assert isinstance(conn, pymongo.MongoClient)
db = get_db()
assert isinstance(db, pymongo.database.Database)
diff --git a/docs/Makefile b/docs/Makefile
index 301b44f..68149fe 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -16,13 +16,10 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
help:
@echo "Please use \`make <target>' where <target> is one of"
+ @echo " html-readthedocs to simulate an html-build for readthedocs"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@@ -40,47 +37,20 @@ html:
html-readthedocs:
$(SPHINXBUILD) -T -E -b readthedocs $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
+ @echo "Open in browser: file://`realpath $(BUILDDIR)/html/index.html`"
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MongoEngine.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MongoEngine.qhc"
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
- "run these through (pdf)latex."
-
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
diff --git a/docs/apireference.rst b/docs/apireference.rst
index dbcb3b8..5cc8a29 100644
--- a/docs/apireference.rst
+++ b/docs/apireference.rst
@@ -80,6 +80,7 @@ Fields
.. autoclass:: mongoengine.fields.LongField
.. autoclass:: mongoengine.fields.FloatField
.. autoclass:: mongoengine.fields.DecimalField
+.. autoclass:: mongoengine.fields.Decimal128Field
.. autoclass:: mongoengine.fields.BooleanField
.. autoclass:: mongoengine.fields.DateTimeField
.. autoclass:: mongoengine.fields.ComplexDateTimeField
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 81a0ce6..0f5ce06 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -8,6 +8,26 @@ Development
===========
- (Fill this out as you fix issues and develop your features).
+
+Changes in 0.29.1
+=================
+- Add support for freshly released pymongo 4.9 #2849
+
+Changes in 0.29.0
+=================
+- Fix weakref in EmbeddedDocumentListField (causing brief mem leak in certain circumstances) #2827
+- Fix pillow deprecation warning related with LANCZOS filter #2824
+- Allow gt/gte/lt/lte/ne operators to be used with a list as value on ListField #2813
+- Switch tox to use pytest instead of legacy `python setup.py test` #2804
+- Add support for timeseries collection #2661
+- Add support in tests for MongoDB 7.0, pymongo 4.7 and pymongo 4.8 in the CI #2826
+- Add support for `array_filters` in Queryset.modify #2811
+- Integrate a docker-compose setup for local testing #2555
+- improve ReferenceField wrong usage detection
+- Fix no_dereference thread-safetyness #2830
+- BREAKING CHANGE: max_length in ListField is now keyword only on ListField signature
+- BREAKING CHANGE: Force `field` argument of ListField/DictField to be a field instance (e.g ListField(StringField()) instead of ListField(StringField)
+
Changes in 0.28.2
=================
- Fix typing import incompatible with Pymongo 3.7 #2802
diff --git a/docs/django.rst b/docs/django.rst
index d43a205..b9986f8 100644
--- a/docs/django.rst
+++ b/docs/django.rst
@@ -3,17 +3,4 @@ Django Support
==============
.. note:: Django support has been split from the main MongoEngine
- repository. The *legacy* Django extension may be found bundled with the
- 0.9 release of MongoEngine.
-
-
-
-Help Wanted!
-------------
-
-The MongoEngine team is looking for help contributing and maintaining a new
-Django extension for MongoEngine! If you have Django experience and would like
-to help contribute to the project, please get in touch on the
-`mailing list <http://groups.google.com/group/mongoengine-users>`_ or by
-simply contributing on
-`GitHub <https://github.com/MongoEngine/django-mongoengine>`_.
+ repository.
diff --git a/docs/faq.rst b/docs/faq.rst
index 49c7302..1c05df7 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -8,5 +8,5 @@ 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/
+.. _uMongo: https://umongo.readthedocs.io/en/latest/
+.. _MotorEngine: https://motorengine.readthedocs.io/en/latest/
diff --git a/docs/guide/connecting.rst b/docs/guide/connecting.rst
index 2cbdb44..78d59f8 100644
--- a/docs/guide/connecting.rst
+++ b/docs/guide/connecting.rst
@@ -47,7 +47,7 @@ of the MongoDB connection string is for::
connect(host="mongodb://my_user:my_password@127.0.0.1:27017/my_db?authSource=my_db")
The URI string can also be used to configure advanced parameters like ssl, replicaSet, etc. For more
-information or example about URI string, you can refer to the `official doc <https://docs.mongodb.com/manual/reference/connection-string/>`_::
+information or example about URI string, you can refer to the `official doc <https://www.mongodb.com/docs/manual/reference/connection-string/>`_::
connect(host="mongodb://my_user:my_password@127.0.0.1:27017/my_db?authSource=admin&ssl=true&replicaSet=globaldb")
diff --git a/docs/guide/defining-documents.rst b/docs/guide/defining-documents.rst
index df749ee..cc59a8c 100644
--- a/docs/guide/defining-documents.rst
+++ b/docs/guide/defining-documents.rst
@@ -29,7 +29,7 @@ documents are serialized based on their field order.
.. _dynamic-document-schemas:
-Dynamic document schemas
+Dynamic Document Schemas
========================
One of the benefits of MongoDB is dynamic schemas for a collection, whilst data
should be planned and organised (after all explicit is better than implicit!)
@@ -260,7 +260,7 @@ document class as the first argument::
comment2 = Comment(content='Nice article!')
page = Page(comments=[comment1, comment2])
-Embedded documents can also leverage the flexibility of :ref:`dynamic-document-schemas:`
+Embedded documents can also leverage the flexibility of :ref:`dynamic-document-schemas`
by inheriting :class:`~mongoengine.DynamicEmbeddedDocument`.
Dictionary Fields
@@ -325,7 +325,7 @@ as the constructor's argument::
.. _many-to-many-with-listfields:
Many to Many with ListFields
-'''''''''''''''''''''''''''
+''''''''''''''''''''''''''''
If you are implementing a many to many relationship via a list of references,
then the references are stored as DBRefs and to query you need to pass an
@@ -491,6 +491,26 @@ The following example shows a :class:`Log` document that will be limited to
ip_address = StringField()
meta = {'max_documents': 1000, 'max_size': 2000000}
+Timeseries collections
+----------------------
+A :class:`~mongoengine.Document` may use a **Timeseries Collection** by specifying
+:attr:`timeseries` in the :attr:`meta` dictionary. Timeseries collection were added
+in MongoDB 5.0 (`doc <https://www.mongodb.com/docs/v5.3/core/timeseries-collections/>`_).
+The following example shows a Document class with a basic setup::
+
+ class SensorData(Document):
+ timestamp = DateTimeField(required=True)
+ temperature = FloatField()
+
+ meta = {
+ "timeseries": {
+ "timeField": "timestamp",
+ "metaField": "temperature",
+ "granularity": "seconds",
+ "expireAfterSeconds": 5,
+ },
+ }
+
.. defining-indexes_
Indexes
@@ -579,7 +599,7 @@ There are a few top level defaults for all indexes that can be set::
:attr:`index_opts` (Optional)
- Set any default index options - see the `full options list <https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex>`_
+ Set any default index options - see the `full options list <https://www.mongodb.com/docs/manual/reference/method/db.collection.createIndex/>`_
:attr:`index_background` (Optional)
Set the default value for if an index should be indexed in the background
diff --git a/docs/guide/gridfs.rst b/docs/guide/gridfs.rst
index e6c097f..4d1b483 100644
--- a/docs/guide/gridfs.rst
+++ b/docs/guide/gridfs.rst
@@ -9,7 +9,7 @@ GridFS support comes in the form of the :class:`~mongoengine.fields.FileField` f
object. This field acts as a file-like object and provides a couple of
different ways of inserting and retrieving data. Arbitrary metadata such as
content type can also be stored alongside the files. The object returned when accessing a
-FileField is a proxy to `Pymongo's GridFS <https://api.mongodb.com/python/current/examples/gridfs.html#gridfs-example>`_
+FileField is a proxy to `Pymongo's GridFS <https://pymongo.readthedocs.io/en/stable/examples/gridfs.html#gridfs-example>`_
In the following example, a document is created to store details about animals, including a photo::
class Animal(Document):
diff --git a/docs/guide/installing.rst b/docs/guide/installing.rst
index 2c962ad..efdb46f 100644
--- a/docs/guide/installing.rst
+++ b/docs/guide/installing.rst
@@ -2,7 +2,7 @@
Installing MongoEngine
======================
-To use MongoEngine, you will need to download `MongoDB <http://mongodb.com/>`_
+To use MongoEngine, you will need to download `MongoDB <https://www.mongodb.com/>`_
and ensure it is running in an accessible location. You will also need
`PyMongo <http://api.mongodb.org/python>`_ to use MongoEngine, but if you
install MongoEngine using setuptools, then the dependencies will be handled for
@@ -22,7 +22,7 @@ Alternatively, if you don't have setuptools installed, `download it from PyPi
$ python setup.py install
To use the bleeding-edge version of MongoEngine, you can get the source from
-`GitHub <http://github.com/mongoengine/mongoengine/>`_ and install it as above:
+`GitHub <https://github.com/MongoEngine/mongoengine/>`_ and install it as above:
.. code-block:: console
diff --git a/docs/guide/migration.rst b/docs/guide/migration.rst
index ed982ef..116910e 100644
--- a/docs/guide/migration.rst
+++ b/docs/guide/migration.rst
@@ -262,7 +262,7 @@ If you would remove the 'name' field or its index, you would have to call:
User._get_collection().drop_index('name_1')
.. note:: When adding new fields or new indexes, MongoEngine will take care of creating them
- (unless `auto_create_index` is disabled) ::
+ (unless `auto_create_index` is disabled)
Recommendations
===============
diff --git a/docs/guide/mongomock.rst b/docs/guide/mongomock.rst
index d923205..024fda1 100644
--- a/docs/guide/mongomock.rst
+++ b/docs/guide/mongomock.rst
@@ -5,7 +5,7 @@ Use mongomock for testing
Although we recommend running your tests against a regular MongoDB server, it is sometimes useful to plug
MongoEngine to alternative implementations (mongomock, montydb, mongita, etc).
-`mongomock <https://github.com/vmalloc/mongomock/>`_ is historically the one suggested for MongoEngine and is
+`mongomock <https://github.com/mongomock/mongomock>`_ is historically the one suggested for MongoEngine and is
a package to do just what the name implies, mocking a mongo database.
To use with mongoengine, simply specify mongomock when connecting with
diff --git a/docs/guide/querying.rst b/docs/guide/querying.rst
index d5ac70b..d347806 100644
--- a/docs/guide/querying.rst
+++ b/docs/guide/querying.rst
@@ -241,7 +241,7 @@ Update with Aggregation Pipeline
It is possible to provide a raw :mod:`PyMongo` aggregation update parameter, which will
be integrated directly into the update. This is done by using ``__raw__`` keyword argument to the update method
and provide the pipeline as a list
-`Update with Aggregation Pipeline <https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#update-with-aggregation->`_
+`Update with Aggregation Pipeline <https://www.mongodb.com/docs/manual/reference/method/db.collection.updateMany/#update-with-aggregation->`_
::
# 'tags' field is set to 'coding is fun'
@@ -257,7 +257,7 @@ Update with Array Operator
It is possible to update specific value in array by use array_filters (arrayFilters) operator.
This is done by using ``__raw__`` keyword argument to the update method and provide the arrayFilters as a list.
-`Update with Array Operator <https://www.mongodb.com/docs/manual/reference/operator/update/positional-filtered->`_
+`Update with Array Operator <https://www.mongodb.com/docs/manual/reference/operator/update/positional-filtered/>`_
::
# assuming an initial 'tags' field == ['test1', 'test2', 'test3']
@@ -447,7 +447,7 @@ would be generating "tag-clouds"::
MongoDB aggregation API
-----------------------
-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>`_
+If you need to run aggregation pipelines, MongoEngine provides an entry point to `Pymongo's aggregation framework <https://pymongo.readthedocs.io/en/stable/examples/aggregation.html#aggregation-framework>`_
through :meth:`~mongoengine.queryset.QuerySet.aggregate`. Check out Pymongo's documentation for the syntax and pipeline.
An example of its use would be::
@@ -661,7 +661,7 @@ to push values with index::
.. note::
Currently only top level lists are handled, future versions of mongodb /
pymongo plan to support nested positional operators. See `The $ positional
- operator <https://docs.mongodb.com/manual/tutorial/update-documents/#Updating-The%24positionaloperator>`_.
+ operator <https://www.mongodb.com/docs/manual/tutorial/update-documents/#Updating-The%24positionaloperator>`_.
Server-side javascript execution
================================
diff --git a/docs/index.rst b/docs/index.rst
index a42ff85..e550760 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -20,9 +20,6 @@ MongoDB. To install it, simply run
:doc:`apireference`
The complete API documentation --- the innards of documents, querysets and fields.
-:doc:`upgrade`
- How to upgrade MongoEngine.
-
:doc:`faq`
Frequently Asked Questions
@@ -33,7 +30,7 @@ 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>`_.
+For further details, please refer to the `readme <https://github.com/MongoEngine/mongoengine>`_.
Community
---------
@@ -47,22 +44,18 @@ Contributing
**Yes please!** We are always looking for contributions, additions and improvements.
-The source is available on `GitHub <http://github.com/MongoEngine/mongoengine>`_
+The source is available on `GitHub <https://github.com/MongoEngine/mongoengine>`_
and contributions are always encouraged. Contributions can be as simple as
minor tweaks to this documentation, the website or the core.
To contribute, fork the project on
-`GitHub <http://github.com/MongoEngine/mongoengine>`_ and send a
+`GitHub <https://github.com/MongoEngine/mongoengine>`_ and send a
pull request.
Changes
-------
-See the :doc:`changelog` for a full list of changes to MongoEngine and
-:doc:`upgrade` for upgrade information.
-
-.. note:: Always read and test the `upgrade <upgrade>`_ documentation before
- putting updates live in production **;)**
+See the :doc:`changelog` for a full list of changes to MongoEngine.
Offline Reading
---------------
@@ -81,7 +74,6 @@ formats for offline reading.
guide/index
apireference
changelog
- upgrade
faq
django
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 4ecb012..4d4be82 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,5 +1,5 @@
-Sphinx==3.3.0
-sphinx-rtd-theme==0.5.0
-readthedocs-sphinx-ext==2.1.1
-docutils==0.17.1
-Jinja2<3.1
+Sphinx==7.4.7
+sphinx-rtd-theme==2.1.0rc2
+readthedocs-sphinx-ext==2.2.5
+docutils==0.20.1
+Jinja2==3.1.4
diff --git a/mongoengine.egg-info/PKG-INFO b/mongoengine.egg-info/PKG-INFO
index b83bf81..3daf721 100644
--- a/mongoengine.egg-info/PKG-INFO
+++ b/mongoengine.egg-info/PKG-INFO
@@ -1,12 +1,12 @@
Metadata-Version: 2.1
Name: mongoengine
-Version: 0.28.2
+Version: 0.29.1
Summary: MongoEngine is a Python Object-Document Mapper for working with MongoDB.
Home-page: http://mongoengine.org/
Author: Harry Marr
Author-email: harry.marr@gmail.com
-Maintainer: Stefan Wojcik
-Maintainer-email: wojcikstefan@gmail.com
+Maintainer: Bastien Gerard
+Maintainer-email: bast.gerard@gmail.com
License: MIT
Download-URL: https://github.com/MongoEngine/mongoengine/tarball/master
Platform: any
@@ -24,6 +24,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
+Provides-Extra: test
License-File: LICENSE
License-File: AUTHORS
@@ -33,7 +34,7 @@ MongoEngine
:Info: MongoEngine is an ORM-like layer on top of PyMongo.
:Repository: https://github.com/MongoEngine/mongoengine
:Author: Harry Marr (http://github.com/hmarr)
-:Maintainer: Stefan Wójcik (http://github.com/wojcikstefan)
+:Maintainer: Bastien Gerard (http://github.com/bagerard)
.. image:: https://travis-ci.org/MongoEngine/mongoengine.svg?branch=master
:target: https://travis-ci.org/MongoEngine/mongoengine
@@ -50,6 +51,10 @@ MongoEngine
.. image:: https://img.shields.io/pypi/v/mongoengine.svg
:target: https://pypi.python.org/pypi/mongoengine
+
+.. image:: https://readthedocs.org/projects/mongoengine-odm/badge/?version=latest
+ :target: https://readthedocs.org/projects/mongoengine-odm/builds/
+
About
=====
MongoEngine is a Python Object-Document Mapper for working with MongoDB.
@@ -73,7 +78,7 @@ You may also have `setuptools <http://peak.telecommunity.com/DevCenter/setuptool
and thus you can use ``easy_install -U mongoengine``. Another option is
`pipenv <https://docs.pipenv.org/>`_. You can then use ``pipenv install mongoengine``
to both create the virtual environment and install the package. Otherwise, you can
-download the source from `GitHub <http://github.com/MongoEngine/mongoengine>`_ and
+download the source from `GitHub <https://github.com/MongoEngine/mongoengine>`_ and
run ``python setup.py install``.
The support for Python2 was dropped with MongoEngine 0.20.0
@@ -91,7 +96,7 @@ If you utilize a ``DateTimeField``, you might also use a more flexible date pars
If you need to use an ``ImageField`` or ``ImageGridFsProxy``:
-- Pillow>=2.0.0
+- Pillow>=7.0.0
If you need to use signals:
@@ -154,8 +159,7 @@ Some simple examples of what MongoEngine code looks like:
Tests
=====
To run the test suite, ensure you are running a local instance of MongoDB on
-the standard port and have ``pytest`` installed. Then, run ``python setup.py test``
-or simply ``pytest``.
+the standard port and have ``pytest`` installed. Then, run ``pytest tests/``.
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
@@ -168,15 +172,6 @@ installed in your environment and then:
# Run the test suites
$ tox
-If you wish to run a subset of tests, use the pytest convention:
-
-.. code-block:: shell
-
- # Run all the tests in a particular test file
- $ pytest tests/fields/test_fields.py
- # Run only particular test class in that file
- $ pytest tests/fields/test_fields.py::TestField
-
Community
=========
- `MongoEngine Users mailing list
diff --git a/mongoengine.egg-info/requires.txt b/mongoengine.egg-info/requires.txt
index dd5d096..49dbae9 100644
--- a/mongoengine.egg-info/requires.txt
+++ b/mongoengine.egg-info/requires.txt
@@ -1 +1,8 @@
pymongo<5.0,>=3.4
+
+[test]
+pytest
+pytest-cov
+coverage
+blinker
+Pillow>=7.0.0
diff --git a/mongoengine/__init__.py b/mongoengine/__init__.py
index 799dad6..f74e30a 100644
--- a/mongoengine/__init__.py
+++ b/mongoengine/__init__.py
@@ -29,7 +29,7 @@ __all__ = (
)
-VERSION = (0, 28, 2)
+VERSION = (0, 29, 1)
def get_version():
diff --git a/mongoengine/base/datastructures.py b/mongoengine/base/datastructures.py
index a3561b8..a175cd1 100644
--- a/mongoengine/base/datastructures.py
+++ b/mongoengine/base/datastructures.py
@@ -113,7 +113,11 @@ class BaseList(list):
BaseDocument = _import_class("BaseDocument")
if isinstance(instance, BaseDocument):
- self._instance = weakref.proxy(instance)
+ if isinstance(instance, weakref.ProxyTypes):
+ self._instance = instance
+ else:
+ self._instance = weakref.proxy(instance)
+
self._name = name
super().__init__(list_items)
@@ -186,10 +190,6 @@ class BaseList(list):
class EmbeddedDocumentList(BaseList):
- def __init__(self, list_items, instance, name):
- super().__init__(list_items, instance, name)
- self._instance = instance
-
@classmethod
def __match_all(cls, embedded_doc, kwargs):
"""Return True if a given embedded doc matches all the filter
diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py
index 194b24e..379f5e8 100644
--- a/mongoengine/base/document.py
+++ b/mongoengine/base/document.py
@@ -202,6 +202,8 @@ class BaseDocument:
and self__created
and name == self._meta.get("id_field")
):
+ # When setting the ID field of an instance already instantiated and that was user-created (i.e not saved in db yet)
+ # Typically this is when calling .save()
super().__setattr__("_created", False)
super().__setattr__(name, value)
@@ -459,13 +461,13 @@ class BaseDocument:
@classmethod
def from_json(cls, json_data, created=False, **kwargs):
- """Converts json data to a Document instance
+ """Converts json data to a Document instance.
- :param str json_data: The json data to load into the Document
+ :param str json_data: The json data to load into the Document.
:param bool created: Boolean defining whether to consider the newly
instantiated document as brand new or as persisted already:
* If True, consider the document as brand new, no matter what data
- it's loaded with (i.e. even if an ID is loaded).
+ it's loaded with (i.e., even if an ID is loaded).
* If False and an ID is NOT provided, consider the document as
brand new.
* If False and an ID is provided, assume that the object has
@@ -804,10 +806,15 @@ class BaseDocument:
fields = cls._fields
if not _auto_dereference:
+ # if auto_deref is turned off, we copy the fields so
+ # we can mutate the auto_dereference of the fields
fields = copy.deepcopy(fields)
+ # Apply field-name / db-field conversion
for field_name, field in fields.items():
- field._auto_dereference = _auto_dereference
+ field.set_auto_dereferencing(
+ _auto_dereference
+ ) # align the field's auto-dereferencing with the document's
if field.db_field in data:
value = data[field.db_field]
try:
diff --git a/mongoengine/base/fields.py b/mongoengine/base/fields.py
index 037e916..cead144 100644
--- a/mongoengine/base/fields.py
+++ b/mongoengine/base/fields.py
@@ -1,4 +1,6 @@
+import contextlib
import operator
+import threading
import weakref
import pymongo
@@ -16,6 +18,19 @@ from mongoengine.errors import DeprecatedError, ValidationError
__all__ = ("BaseField", "ComplexBaseField", "ObjectIdField", "GeoJsonBaseField")
+@contextlib.contextmanager
+def _no_dereference_for_fields(*fields):
+ """Context manager for temporarily disabling a Field's auto-dereferencing
+ (meant to be used from no_dereference context manager)"""
+ try:
+ for field in fields:
+ field._incr_no_dereference_context()
+ yield None
+ finally:
+ for field in fields:
+ field._decr_no_dereference_context()
+
+
class BaseField:
"""A base class for fields in a MongoDB document. Instances of this class
may be added to subclasses of `Document` to define a document's schema.
@@ -24,7 +39,7 @@ class BaseField:
name = None # set in TopLevelDocumentMetaclass
_geo_index = False
_auto_gen = False # Call `generate` to generate a value
- _auto_dereference = True
+ _thread_local_storage = threading.local()
# These track each time a Field instance is created. Used to retain order.
# The auto_creation_counter is used for fields that MongoEngine implicitly
@@ -85,6 +100,8 @@ class BaseField:
self.sparse = sparse
self._owner_document = None
+ self.__auto_dereference = True
+
# Make sure db_field is a string (if it's explicitly defined).
if self.db_field is not None and not isinstance(self.db_field, str):
raise TypeError("db_field should be a string.")
@@ -120,6 +137,33 @@ class BaseField:
self.creation_counter = BaseField.creation_counter
BaseField.creation_counter += 1
+ def set_auto_dereferencing(self, value):
+ self.__auto_dereference = value
+
+ @property
+ def _no_dereference_context_local(self):
+ if not hasattr(self._thread_local_storage, "no_dereference_context"):
+ self._thread_local_storage.no_dereference_context = 0
+ return self._thread_local_storage.no_dereference_context
+
+ @property
+ def _no_dereference_context_is_set(self):
+ return self._no_dereference_context_local > 0
+
+ def _incr_no_dereference_context(self):
+ self._thread_local_storage.no_dereference_context = (
+ self._no_dereference_context_local + 1
+ )
+
+ def _decr_no_dereference_context(self):
+ self._thread_local_storage.no_dereference_context = (
+ self._no_dereference_context_local - 1
+ )
+
+ @property
+ def _auto_dereference(self):
+ return self.__auto_dereference and not self._no_dereference_context_is_set
+
def __get__(self, instance, owner):
"""Descriptor for retrieving a value from a field in a document."""
if instance is None:
@@ -268,6 +312,10 @@ class ComplexBaseField(BaseField):
"""
def __init__(self, field=None, **kwargs):
+ if field is not None and not isinstance(field, BaseField):
+ raise TypeError(
+ f"field argument must be a Field instance (e.g {self.__class__.__name__}(StringField()))"
+ )
self.field = field
super().__init__(**kwargs)
@@ -375,7 +423,7 @@ class ComplexBaseField(BaseField):
return value
if self.field:
- self.field._auto_dereference = self._auto_dereference
+ self.field.set_auto_dereferencing(self._auto_dereference)
value_dict = {
key: self.field.to_python(item) for key, item in value.items()
}
diff --git a/mongoengine/connection.py b/mongoengine/connection.py
index 42a7943..2f07b83 100644
--- a/mongoengine/connection.py
+++ b/mongoengine/connection.py
@@ -2,7 +2,11 @@ import warnings
from pymongo import MongoClient, ReadPreference, uri_parser
from pymongo.common import _UUID_REPRESENTATIONS
-from pymongo.database import _check_name
+
+try:
+ from pymongo.database_shared import _check_name
+except ImportError:
+ from pymongo.database import _check_name
# DriverInfo was added in PyMongo 3.7.
try:
diff --git a/mongoengine/context_managers.py b/mongoengine/context_managers.py
index f16753e..6b987dd 100644
--- a/mongoengine/context_managers.py
+++ b/mongoengine/context_managers.py
@@ -1,9 +1,11 @@
+import contextlib
import threading
from contextlib import contextmanager
from pymongo.read_concern import ReadConcern
from pymongo.write_concern import WriteConcern
+from mongoengine.base.fields import _no_dereference_for_fields
from mongoengine.common import _import_class
from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_db
from mongoengine.pymongo_support import count_documents
@@ -22,6 +24,7 @@ __all__ = (
class MyThreadLocals(threading.local):
def __init__(self):
+ # {DocCls: count} keeping track of classes with an active no_dereference context
self.no_dereferencing_class = {}
@@ -126,46 +129,37 @@ class switch_collection:
self.cls._get_collection_name = self.ori_get_collection_name
-class no_dereference:
+@contextlib.contextmanager
+def no_dereference(cls):
"""no_dereference context manager.
Turns off all dereferencing in Documents for the duration of the context
manager::
with no_dereference(Group):
- Group.objects.find()
+ Group.objects()
"""
-
- def __init__(self, cls):
- """Construct the no_dereference context manager.
-
- :param cls: the class to turn dereferencing off on
- """
- self.cls = cls
+ try:
+ cls = cls
ReferenceField = _import_class("ReferenceField")
GenericReferenceField = _import_class("GenericReferenceField")
ComplexBaseField = _import_class("ComplexBaseField")
- self.deref_fields = [
- k
- for k, v in self.cls._fields.items()
- if isinstance(v, (ReferenceField, GenericReferenceField, ComplexBaseField))
+ deref_fields = [
+ field
+ for name, field in cls._fields.items()
+ if isinstance(
+ field, (ReferenceField, GenericReferenceField, ComplexBaseField)
+ )
]
- def __enter__(self):
- """Change the objects default and _auto_dereference values."""
- _register_no_dereferencing_for_class(self.cls)
-
- for field in self.deref_fields:
- self.cls._fields[field]._auto_dereference = False
-
- def __exit__(self, t, value, traceback):
- """Reset the default and _auto_dereference values."""
- _unregister_no_dereferencing_for_class(self.cls)
+ _register_no_dereferencing_for_class(cls)
- for field in self.deref_fields:
- self.cls._fields[field]._auto_dereference = True
+ with _no_dereference_for_fields(*deref_fields):
+ yield None
+ finally:
+ _unregister_no_dereferencing_for_class(cls)
class no_sub_classes:
@@ -180,7 +174,7 @@ class no_sub_classes:
def __init__(self, cls):
"""Construct the no_sub_classes context manager.
- :param cls: the class to turn querying sub classes on
+ :param cls: the class to turn querying subclasses on
"""
self.cls = cls
self.cls_initial_subclasses = None
@@ -221,7 +215,7 @@ class query_counter:
Be aware that:
- - Iterating over large amount of documents (>101) makes pymongo issue `getmore` queries to fetch the next batch of documents (https://docs.mongodb.com/manual/tutorial/iterate-a-cursor/#cursor-batches)
+ - Iterating over large amount of documents (>101) makes pymongo issue `getmore` queries to fetch the next batch of documents (https://www.mongodb.com/docs/manual/tutorial/iterate-a-cursor/#cursor-batches)
- Some queries are ignored by default by the counter (killcursors, db.system.indexes)
"""
diff --git a/mongoengine/document.py b/mongoengine/document.py
index 3fddec3..ad166c9 100644
--- a/mongoengine/document.py
+++ b/mongoengine/document.py
@@ -220,6 +220,8 @@ class Document(BaseDocument, metaclass=TopLevelDocumentMetaclass):
# Get the collection, either capped or regular.
if cls._meta.get("max_size") or cls._meta.get("max_documents"):
cls._collection = cls._get_capped_collection()
+ elif cls._meta.get("timeseries"):
+ cls._collection = cls._get_timeseries_collection()
else:
db = cls._get_db()
collection_name = cls._get_collection_name()
@@ -271,6 +273,27 @@ class Document(BaseDocument, metaclass=TopLevelDocumentMetaclass):
return db.create_collection(collection_name, **opts)
+ @classmethod
+ def _get_timeseries_collection(cls):
+ """Create a new or get an existing timeseries PyMongo collection."""
+ db = cls._get_db()
+ collection_name = cls._get_collection_name()
+ timeseries_opts = cls._meta.get("timeseries")
+
+ if collection_name in list_collection_names(
+ db, include_system_collections=True
+ ):
+ collection = db[collection_name]
+ collection.options()
+ return collection
+
+ opts = {"expireAfterSeconds": timeseries_opts.pop("expireAfterSeconds", None)}
+ return db.create_collection(
+ name=collection_name,
+ timeseries=timeseries_opts,
+ **opts,
+ )
+
def to_mongo(self, *args, **kwargs):
data = super().to_mongo(*args, **kwargs)
diff --git a/mongoengine/fields.py b/mongoengine/fields.py
index 40469bf..a5ebba2 100644
--- a/mongoengine/fields.py
+++ b/mongoengine/fields.py
@@ -6,6 +6,7 @@ import re
import socket
import time
import uuid
+from inspect import isclass
from io import BytesIO
from operator import itemgetter
@@ -48,8 +49,12 @@ from mongoengine.queryset.transform import STRING_OPERATORS
try:
from PIL import Image, ImageOps
- LANCZOS = Image.LANCZOS if hasattr(Image, "LANCZOS") else Image.ANTIALIAS
+ if hasattr(Image, "Resampling"):
+ LANCZOS = Image.Resampling.LANCZOS
+ else:
+ LANCZOS = Image.LANCZOS
except ImportError:
+ # pillow is optional so may not be installed
Image = None
ImageOps = None
@@ -707,7 +712,6 @@ class EmbeddedDocumentField(BaseField):
"""
def __init__(self, document_type, **kwargs):
- # XXX ValidationError raised outside of the "validate" method.
if not (
isinstance(document_type, str)
or issubclass(document_type, EmbeddedDocument)
@@ -910,9 +914,9 @@ class ListField(ComplexBaseField):
Required means it cannot be empty - as the default for ListFields is []
"""
- def __init__(self, field=None, max_length=None, **kwargs):
+ def __init__(self, field=None, *, max_length=None, **kwargs):
self.max_length = max_length
- kwargs.setdefault("default", lambda: [])
+ kwargs.setdefault("default", list)
super().__init__(field=field, **kwargs)
def __get__(self, instance, owner):
@@ -951,11 +955,11 @@ class ListField(ComplexBaseField):
if self.field:
# If the value is iterable and it's not a string nor a
# BaseDocument, call prepare_query_value for each of its items.
+ is_iter = hasattr(value, "__iter__")
+ eligible_iter = is_iter and not isinstance(value, (str, BaseDocument))
if (
- op in ("set", "unset", None)
- and hasattr(value, "__iter__")
- and not isinstance(value, str)
- and not isinstance(value, BaseDocument)
+ op in ("set", "unset", "gt", "gte", "lt", "lte", "ne", None)
+ and eligible_iter
):
return [self.field.prepare_query_value(op, v) for v in value]
@@ -1035,10 +1039,9 @@ class DictField(ComplexBaseField):
"""
def __init__(self, field=None, *args, **kwargs):
- self._auto_dereference = False
-
- kwargs.setdefault("default", lambda: {})
+ kwargs.setdefault("default", dict)
super().__init__(*args, field=field, **kwargs)
+ self.set_auto_dereferencing(False)
def validate(self, value):
"""Make sure that a list of valid fields is being used."""
@@ -1151,8 +1154,9 @@ class ReferenceField(BaseField):
:class:`~pymongo.dbref.DBRef`, regardless of the value of `dbref`.
"""
# XXX ValidationError raised outside of the "validate" method.
- if not isinstance(document_type, str) and not issubclass(
- document_type, Document
+ if not (
+ isinstance(document_type, str)
+ or (isclass(document_type) and issubclass(document_type, Document))
):
self.error(
"Argument to ReferenceField constructor must be a "
@@ -2065,7 +2069,7 @@ class ImageField(FileField):
class SequenceField(BaseField):
"""Provides a sequential counter see:
- https://docs.mongodb.com/manual/reference/method/ObjectId/#ObjectIDs-SequenceNumbers
+ https://www.mongodb.com/docs/manual/reference/method/ObjectId/#ObjectIDs-SequenceNumbers
.. note::
diff --git a/mongoengine/mongodb_support.py b/mongoengine/mongodb_support.py
index 23c538d..f15a72c 100644
--- a/mongoengine/mongodb_support.py
+++ b/mongoengine/mongodb_support.py
@@ -1,6 +1,7 @@
"""
Helper functions, constants, and types to aid with MongoDB version support
"""
+
from mongoengine.connection import get_connection
# Constant that can be used to compare the version retrieved with
diff --git a/mongoengine/pymongo_support.py b/mongoengine/pymongo_support.py
index 7aa5567..674a9b6 100644
--- a/mongoengine/pymongo_support.py
+++ b/mongoengine/pymongo_support.py
@@ -1,6 +1,7 @@
"""
Helper functions, constants, and types to aid with PyMongo support.
"""
+
import pymongo
from bson import binary, json_util
from pymongo.errors import OperationFailure
diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py
index 3ce3cb3..068374f 100644
--- a/mongoengine/queryset/base.py
+++ b/mongoengine/queryset/base.py
@@ -405,7 +405,7 @@ class BaseQuerySet:
getting the count
"""
# mimic the fact that setting .limit(0) in pymongo sets no limit
- # https://docs.mongodb.com/manual/reference/method/cursor.limit/#zero-value
+ # https://www.mongodb.com/docs/manual/reference/method/cursor.limit/#zero-value
if (
self._limit == 0
and with_limit_and_skip is False
@@ -634,7 +634,14 @@ class BaseQuerySet:
document = self._document.objects.with_id(atomic_update.upserted_id)
return document
- def update_one(self, upsert=False, write_concern=None, full_result=False, **update):
+ def update_one(
+ self,
+ upsert=False,
+ write_concern=None,
+ full_result=False,
+ array_filters=None,
+ **update,
+ ):
"""Perform an atomic update on the fields of the first document
matched by the query.
@@ -647,6 +654,7 @@ class BaseQuerySet:
will force an fsync on the primary server.
:param full_result: Return the associated ``pymongo.UpdateResult`` rather than just the number
updated items
+ :param array_filters: A list of filters specifying which array elements an update should apply.
:param update: Django-style update keyword arguments
full_result
:returns the number of updated documents (unless ``full_result`` is True)
@@ -656,11 +664,18 @@ class BaseQuerySet:
multi=False,
write_concern=write_concern,
full_result=full_result,
+ array_filters=array_filters,
**update,
)
def modify(
- self, upsert=False, full_response=False, remove=False, new=False, **update
+ self,
+ upsert=False,
+ full_response=False,
+ remove=False,
+ new=False,
+ array_filters=None,
+ **update,
):
"""Update and return the updated document.
@@ -680,6 +695,7 @@ class BaseQuerySet:
:param remove: remove rather than updating (default ``False``)
:param new: return updated rather than original document
(default ``False``)
+ :param array_filters: A list of filters specifying which array elements an update should apply.
:param update: Django-style update keyword arguments
"""
@@ -717,6 +733,7 @@ class BaseQuerySet:
upsert=upsert,
sort=sort,
return_document=return_doc,
+ array_filters=array_filters,
**self._cursor_args,
)
except pymongo.errors.DuplicateKeyError as err:
@@ -946,7 +963,7 @@ class BaseQuerySet:
"""Limit the number of documents returned in a single batch (each
batch requires a round trip to the server).
- See http://api.mongodb.com/python/current/api/pymongo/cursor.html#pymongo.cursor.Cursor.batch_size
+ See https://pymongo.readthedocs.io/en/stable/api/pymongo/cursor.html#pymongo.cursor.Cursor
for details.
:param size: desired size of each batch.
@@ -1180,7 +1197,7 @@ class BaseQuerySet:
def comment(self, text):
"""Add a comment to the query.
- See https://docs.mongodb.com/manual/reference/method/cursor.comment/#cursor.comment
+ See https://www.mongodb.com/docs/manual/reference/method/cursor.comment/
for details.
"""
return self._chainable_method("comment", text)
@@ -1324,7 +1341,7 @@ class BaseQuerySet:
: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
+ See https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.aggregate
"""
using_deprecated_interface = isinstance(pipeline, dict) or bool(suppl_pipeline)
user_pipeline = [pipeline] if isinstance(pipeline, dict) else list(pipeline)
@@ -1347,7 +1364,7 @@ class BaseQuerySet:
initial_pipeline.append({"$sort": dict(self._ordering)})
if self._limit is not None:
- # As per MongoDB Documentation (https://docs.mongodb.com/manual/reference/operator/aggregation/limit/),
+ # As per MongoDB Documentation (https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit/),
# keeping limit stage right after sort stage is more efficient. But this leads to wrong set of documents
# for a skip stage that might succeed these. So we need to maintain more documents in memory in such a
# case (https://stackoverflow.com/a/24161461).
@@ -1384,7 +1401,7 @@ class BaseQuerySet:
:class:`~bson.code.Code` or string
:param output: output collection name, if set to 'inline' will return
the results inline. This can also be a dictionary containing output options
- see: http://docs.mongodb.org/manual/reference/command/mapReduce/#dbcmd.mapReduce
+ see: https://www.mongodb.com/docs/manual/reference/command/mapReduce/#mongodb-dbcommand-dbcmd.mapReduce
:param finalize_f: finalize function, an optional function that
performs any post-reduction processing.
:param scope: values to insert into map/reduce global scope. Optional.
diff --git a/mongoengine/signals.py b/mongoengine/signals.py
index 582b533..940209a 100644
--- a/mongoengine/signals.py
+++ b/mongoengine/signals.py
@@ -38,9 +38,9 @@ except ImportError:
)
send = lambda *a, **kw: None # noqa
- connect = (
- disconnect
- ) = has_receivers_for = receivers_for = temporarily_connected_to = _fail
+ connect = disconnect = has_receivers_for = receivers_for = (
+ temporarily_connected_to
+ ) = _fail
del _fail
diff --git a/setup.py b/setup.py
index aebabc4..a629d5b 100644
--- a/setup.py
+++ b/setup.py
@@ -1,15 +1,6 @@
import os
-import sys
-from pkg_resources import normalize_path
from setuptools import find_packages, setup
-from setuptools.command.test import test as TestCommand
-
-# Hack to silence atexit traceback in newer python versions
-try:
- import multiprocessing # noqa: F401
-except ImportError:
- pass
DESCRIPTION = "MongoEngine is a Python Object-Document Mapper for working with MongoDB."
@@ -27,62 +18,6 @@ def get_version(version_tuple):
return ".".join(map(str, version_tuple))
-class PyTest(TestCommand):
- """Will force pytest to search for tests inside the build directory
- for 2to3 converted code (used by tox), instead of the current directory.
- Required as long as we need 2to3
-
- Known Limitation: https://tox.readthedocs.io/en/latest/example/pytest.html#known-issues-and-limitations
- Source: https://www.hackzine.org/python-testing-with-pytest-and-2to3-plus-tox-and-travis-ci.html
- """
-
- # https://pytest.readthedocs.io/en/2.7.3/goodpractises.html#integration-with-setuptools-test-commands
- # Allows to provide pytest command argument through the test runner command `python setup.py test`
- # e.g: `python setup.py test -a "-k=test"`
- # This only works for 1 argument though
- user_options = [("pytest-args=", "a", "Arguments to pass to py.test")]
-
- def initialize_options(self):
- TestCommand.initialize_options(self)
- self.pytest_args = ""
-
- def finalize_options(self):
- TestCommand.finalize_options(self)
- self.test_args = ["tests"]
- self.test_suite = True
-
- def run_tests(self):
- # import here, cause outside the eggs aren't loaded
- import pytest
- from pkg_resources import _namespace_packages
-
- # Purge modules under test from sys.modules. The test loader will
- # re-import them from the build location. Required when 2to3 is used
- # with namespace packages.
- if sys.version_info >= (3,) and getattr(self.distribution, "use_2to3", False):
- module = self.test_args[-1].split(".")[0]
- if module in _namespace_packages:
- del_modules = []
- if module in sys.modules:
- del_modules.append(module)
- module += "."
- for name in sys.modules:
- if name.startswith(module):
- del_modules.append(name)
- map(sys.modules.__delitem__, del_modules)
-
- # Run on the build directory for 2to3-built code
- # This will prevent the old 2.x code from being found
- # by py.test discovery mechanism, that apparently
- # ignores sys.path..
- ei_cmd = self.get_finalized_command("egg_info")
- self.test_args = [normalize_path(ei_cmd.egg_base)]
-
- cmd_args = self.test_args + ([self.pytest_args] if self.pytest_args else [])
- errno = pytest.main(cmd_args)
- sys.exit(errno)
-
-
# Dirty hack to get version number from monogengine/__init__.py - we can't
# import it as it depends on PyMongo and PyMongo isn't installed until this
# file is read
@@ -107,30 +42,22 @@ CLASSIFIERS = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
-extra_opts = {
- "packages": find_packages(exclude=["tests", "tests.*"]),
- "tests_require": [
- "pytest",
- "pytest-cov",
- "coverage",
- "blinker",
- "Pillow>=7.0.0",
- ],
-}
-
-if "test" in sys.argv:
- extra_opts["packages"] = find_packages()
- extra_opts["package_data"] = {
- "tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"]
- }
+install_require = ["pymongo>=3.4,<5.0"]
+tests_require = [
+ "pytest",
+ "pytest-cov",
+ "coverage",
+ "blinker",
+ "Pillow>=7.0.0",
+]
setup(
name="mongoengine",
version=VERSION,
author="Harry Marr",
author_email="harry.marr@gmail.com",
- maintainer="Stefan Wojcik",
- maintainer_email="wojcikstefan@gmail.com",
+ maintainer="Bastien Gerard",
+ maintainer_email="bast.gerard@gmail.com",
url="http://mongoengine.org/",
download_url="https://github.com/MongoEngine/mongoengine/tarball/master",
license="MIT",
@@ -140,7 +67,9 @@ setup(
platforms=["any"],
classifiers=CLASSIFIERS,
python_requires=">=3.7",
- install_requires=["pymongo>=3.4,<5.0"],
- cmdclass={"test": PyTest},
- **extra_opts
+ install_requires=install_require,
+ extras_require={
+ "test": tests_require,
+ },
+ packages=find_packages(exclude=["tests", "tests.*"]),
)