Compare commits

...

23 Commits

Author SHA1 Message Date
Bastien Gérard
04c26acdd6 Merge pull request #2513 from bagerard/prepare_release
Prepare release
2021-05-04 12:15:34 +02:00
Bastien Gerard
d0a15a8924 prepare changelog 2021-05-04 10:50:56 +02:00
Bastien Gerard
2215e2746b run latest autoformatter 2021-05-04 10:50:56 +02:00
Bastien Gerard
0e6bcbc030 update precommit 2021-05-04 10:50:56 +02:00
Bastien Gérard
232071f8f4 Merge pull request #2505 from deveil/patch-1
Typo correction
2021-04-23 20:45:33 +02:00
Bastien Gérard
fc0fb31d43 Merge pull request #2503 from bagerard/precommit_update
housekeeping - pre-commit autoupdate
2021-04-23 20:44:34 +02:00
deveil
1bd8cd803e Typo correction 2021-04-23 16:08:57 +02:00
Bastien Gerard
ef57a58155 housekeeping - pre-commit autoupdate 2021-04-22 10:18:15 +02:00
Bastien Gérard
9680259904 Merge pull request #2497 from bagerard/switch_to_isort
Switch to isort + add few pre-commit hooks
2021-03-31 14:11:23 +02:00
Bastien Gerard
49a4d23371 update hooks version 2021-03-29 22:04:07 +02:00
Bastien Gerard
b9d370c885 add standard hooks 2021-03-29 22:02:57 +02:00
Bastien Gerard
e5a2714baf update doc for isort 2021-03-29 21:55:34 +02:00
Bastien Gerard
ff596fcb7e replace flake8-import-order by isort 2021-03-29 21:50:22 +02:00
Bastien Gérard
f0fad6df19 Merge pull request #2485 from janste63/fix_2484
Test case and proposed solution for #2484
2021-03-29 20:52:53 +02:00
Jan Stein
da173cf0e2 Merge branch 'master' into fix_2484 2021-03-25 15:27:48 +01:00
Bastien Gérard
1669f0c5a4 Merge pull request #2489 from bagerard/fix_one_to_many_doc
Fix one-to-many example that is actually a many to many
2021-03-09 13:41:03 +01:00
Bastien Gérard
b045925efe Merge pull request #2481 from bagerard/improve_connect_doc
improve connect() doc and put more emphasis on URI string
2021-03-09 13:40:45 +01:00
Bastien Gerard
b3ce65453a Fix one-to-many example that is actually a many to many 2021-03-08 22:21:48 +01:00
Bastien Gerard
50d891cb7b more improvement to connect doc 2021-03-08 21:52:14 +01:00
Bastien Gerard
e31f9150d2 improve connect() doc and put more emphasis on URI string 2021-03-08 21:51:43 +01:00
Bastien Gérard
74ceb9703b Merge pull request #2488 from bagerard/add_lazy_loading_method_ease_profiling
Add _lazy_load_ref methods to make profiling easier
2021-03-08 19:18:54 +01:00
Bastien Gerard
58a3c6de03 Add _lazy_load_ref methods so that the impact of lazy loading surfaces when profiling 2021-03-08 00:14:53 +01:00
Jan Stein
8fd969aba9 Test case and proposed solution for #2484 2021-03-03 14:58:03 +01:00
57 changed files with 304 additions and 176 deletions

View File

@@ -140,4 +140,4 @@ jobs:
- name: publish pypi - name: publish pypi
uses: pypa/gh-action-pypi-publish@master uses: pypa/gh-action-pypi-publish@master
with: with:
password: ${{ secrets.pypi_token }} password: ${{ secrets.pypi_token }}

View File

@@ -1,17 +1,26 @@
fail_fast: false fail_fast: false
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: check-merge-conflict
- id: debug-statements
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: https://github.com/ambv/black - repo: https://github.com/ambv/black
rev: 20.8b1 rev: 21.4b2
hooks: hooks:
- id: black - id: black
- repo: https://gitlab.com/pycqa/flake8 - repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4 rev: 3.9.1
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies:
- flake8-import-order
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.7.4 rev: v2.14.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py36-plus] args: [--py36-plus]
- repo: https://github.com/pycqa/isort
rev: 5.8.0
hooks:
- id: isort

View File

@@ -259,3 +259,4 @@ that much better:
* Agustin Barto (https://github.com/abarto) * Agustin Barto (https://github.com/abarto)
* Stankiewicz Mateusz (https://github.com/mas15) * Stankiewicz Mateusz (https://github.com/mas15)
* Felix Schultheiß (https://github.com/felix-smashdocs) * Felix Schultheiß (https://github.com/felix-smashdocs)
* Jan Stein (https://github.com/janste63)

View File

@@ -35,8 +35,8 @@ Travis runs the tests against the main Python 3.x versions.
Style Guide Style Guide
----------- -----------
MongoEngine's codebase is formatted with `black <https://github.com/python/black>`_, other tools like MongoEngine's codebase is auto-formatted with `black <https://github.com/python/black>`_, imports are ordered with `isort <https://pycqa.github.io/isort/>`_
flake8 are also used. Those tools will run as part of the CI and will fail in case the code is not formatted properly. and other tools like flake8 are also used. Those tools will run as part of the CI and will fail in case the code is not formatted properly.
To install all development tools, simply run the following commands: To install all development tools, simply run the following commands:
@@ -58,6 +58,10 @@ To enable ``pre-commit`` simply run:
See the ``.pre-commit-config.yaml`` configuration file for more information See the ``.pre-commit-config.yaml`` configuration file for more information
on how it works. on how it works.
pre-commit will now run upon every commit and will reject anything that doesn't comply.
You can also run all the checks with ``pre-commit run -a``, this is what is used in the CI.
Testing Testing
------- -------

View File

@@ -31,7 +31,7 @@ myNoddys = noddy.find()
print("-" * 100) print("-" * 100)
print("PyMongo: Creating 10000 dictionaries.") print("PyMongo: Creating 10000 dictionaries.")
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
stmt = """ stmt = """
from pymongo import MongoClient, WriteConcern from pymongo import MongoClient, WriteConcern
@@ -54,7 +54,7 @@ myNoddys = noddy.find()
print("-" * 100) print("-" * 100)
print('PyMongo: Creating 10000 dictionaries (write_concern={"w": 0}).') print('PyMongo: Creating 10000 dictionaries (write_concern={"w": 0}).')
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
setup = """ setup = """
from pymongo import MongoClient from pymongo import MongoClient
@@ -84,7 +84,7 @@ myNoddys = Noddy.objects()
print("-" * 100) print("-" * 100)
print("MongoEngine: Creating 10000 dictionaries.") print("MongoEngine: Creating 10000 dictionaries.")
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
stmt = """ stmt = """
for i in range(10000): for i in range(10000):
@@ -102,7 +102,7 @@ myNoddys = Noddy.objects()
print("-" * 100) print("-" * 100)
print("MongoEngine: Creating 10000 dictionaries (using a single field assignment).") print("MongoEngine: Creating 10000 dictionaries (using a single field assignment).")
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
stmt = """ stmt = """
for i in range(10000): for i in range(10000):
@@ -118,7 +118,7 @@ myNoddys = Noddy.objects()
print("-" * 100) print("-" * 100)
print('MongoEngine: Creating 10000 dictionaries (write_concern={"w": 0}).') print('MongoEngine: Creating 10000 dictionaries (write_concern={"w": 0}).')
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
stmt = """ stmt = """
for i in range(10000): for i in range(10000):
@@ -136,7 +136,7 @@ myNoddys = Noddy.objects()
'MongoEngine: Creating 10000 dictionaries (write_concern={"w": 0}, validate=False).' 'MongoEngine: Creating 10000 dictionaries (write_concern={"w": 0}, validate=False).'
) )
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
stmt = """ stmt = """
for i in range(10000): for i in range(10000):
@@ -154,7 +154,7 @@ myNoddys = Noddy.objects()
'MongoEngine: Creating 10000 dictionaries (force_insert=True, write_concern={"w": 0}, validate=False).' 'MongoEngine: Creating 10000 dictionaries (force_insert=True, write_concern={"w": 0}, validate=False).'
) )
t = timeit.Timer(stmt=stmt, setup=setup) t = timeit.Timer(stmt=stmt, setup=setup)
print("{}s".format(t.timeit(1))) print(f"{t.timeit(1)}s")
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -8,8 +8,13 @@ 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.23.0 Changes in 0.23.1
=========== ===========
- Bug fix: ignore LazyReferenceFields when clearing _changed_fields #2484
- Improve connection doc #2481
Changes in 0.23.0
=================
- Bugfix: manually setting SequenceField in DynamicDocument doesn't increment the counter #2471 - Bugfix: manually setting SequenceField in DynamicDocument doesn't increment the counter #2471
- Add MongoDB 4.2 and 4.4 to CI - Add MongoDB 4.2 and 4.4 to CI
- Add support for allowDiskUse on querysets #2468 - Add support for allowDiskUse on querysets #2468

View File

@@ -5,7 +5,7 @@ Connecting to MongoDB
===================== =====================
Connections in MongoEngine are registered globally and are identified with aliases. Connections in MongoEngine are registered globally and are identified with aliases.
If no `alias` is provided during the connection, it will use "default" as alias. If no ``alias`` is provided during the connection, it will use "default" as alias.
To connect to a running instance of :program:`mongod`, use the :func:`~mongoengine.connect` To connect to a running instance of :program:`mongod`, use the :func:`~mongoengine.connect`
function. The first argument is the name of the database to connect to:: function. The first argument is the name of the database to connect to::
@@ -14,27 +14,66 @@ function. The first argument is the name of the database to connect to::
connect('project1') connect('project1')
By default, MongoEngine assumes that the :program:`mongod` instance is running By default, MongoEngine assumes that the :program:`mongod` instance is running
on **localhost** on port **27017**. If MongoDB is running elsewhere, you should on **localhost** on port **27017**.
provide the :attr:`host` and :attr:`port` arguments to
:func:`~mongoengine.connect`::
connect('project1', host='192.168.1.35', port=12345) If MongoDB is running elsewhere, you need to provide details on how to connect. There are two ways of
doing this. Using a connection string in URI format (**this is the preferred method**) or individual attributes
provided as keyword arguments.
Connect with URI string
=======================
When using a connection string in URI format you should specify the connection details
as the :attr:`host` to :func:`~mongoengine.connect`. In a web application context for instance, the URI
is typically read from the config file::
connect(host="mongodb://127.0.0.1:27017/my_db")
If the database requires authentication, you can specify it in the
URI. As each database can have its own users configured, you need to tell MongoDB
where to look for the user you are working with, that's what the ``?authSource=admin`` bit
of the MongoDB connection string is for::
# Connects to 'my_db' database by authenticating
# with given credentials against the 'admin' database (by default as authSource isn't provided)
connect(host="mongodb://my_user:my_password@127.0.0.1:27017/my_db")
# Equivalent to previous connection but explicitly states that
# it should use admin as the authentication source database
connect(host="mongodb://my_user:my_password@hostname:port/my_db?authSource=admin")
# Connects to 'my_db' database by authenticating
# with given credentials against that same database
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/>`_::
connect(host="mongodb://my_user:my_password@127.0.0.1:27017/my_db?authSource=admin&ssl=true&replicaSet=globaldb")
.. note:: URI containing SRV records (e.g "mongodb+srv://server.example.com/") can be used as well
Connect with keyword attributes
===============================
The second option for specifying the connection details is to provide the information as keyword
attributes to :func:`~mongoengine.connect`::
connect('my_db', host='127.0.0.1', port=27017)
If the database requires authentication, :attr:`username`, :attr:`password` If the database requires authentication, :attr:`username`, :attr:`password`
and :attr:`authentication_source` arguments should be provided:: and :attr:`authentication_source` arguments should be provided::
connect('project1', username='webapp', password='pwd123', authentication_source='admin') connect('my_db', username='my_user', password='my_password', authentication_source='admin')
URI style connections are also supported -- just supply the URI as The set of attributes that :func:`~mongoengine.connect` recognizes includes but is not limited to:
the :attr:`host` to :attr:`host`, :attr:`port`, :attr:`read_preference`, :attr:`username`, :attr:`password`, :attr:`authentication_source`, :attr:`authentication_mechanism`,
:func:`~mongoengine.connect`:: :attr:`replicaset`, :attr:`tls`, etc. Most of the parameters accepted by `pymongo.MongoClient <https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient>`_
can be used with :func:`~mongoengine.connect` and will simply be forwarded when instantiating the `pymongo.MongoClient`.
connect('project1', host='mongodb://localhost/database_name')
.. note:: URI containing SRV records (e.g mongodb+srv://server.example.com/) can be used as well as the :attr:`host`
.. note:: Database, username and password from URI string overrides .. note:: Database, username and password from URI string overrides
corresponding parameters in :func:`~mongoengine.connect`: :: corresponding parameters in :func:`~mongoengine.connect`, this should
obviously be avoided: ::
connect( connect(
db='test', db='test',
@@ -43,28 +82,19 @@ the :attr:`host` to
host='mongodb://admin:qwerty@localhost/production' host='mongodb://admin:qwerty@localhost/production'
) )
will establish connection to ``production`` database using will establish connection to ``production`` database using ``admin`` username and ``qwerty`` password.
``admin`` username and ``12345`` password.
.. note:: Calling :func:`~mongoengine.connect` without argument will establish .. note:: Calling :func:`~mongoengine.connect` without argument will establish
a connection to the "test" database by default a connection to the "test" database by default
Replica Sets Read Preferences
============ ================
MongoEngine supports connecting to replica sets:: As stated above, Read preferences are supported through the connection but also via individual
from mongoengine import connect
# Regular connect
connect('dbname', replicaset='rs-name')
# MongoDB URI-style connect
connect(host='mongodb://localhost/dbname?replicaSet=rs-name')
Read preferences are supported through the connection or via individual
queries by passing the read_preference :: queries by passing the read_preference ::
from pymongo import ReadPreference
Bar.objects().read_preference(ReadPreference.PRIMARY) Bar.objects().read_preference(ReadPreference.PRIMARY)
Bar.objects(read_preference=ReadPreference.PRIMARY) Bar.objects(read_preference=ReadPreference.PRIMARY)

View File

@@ -290,12 +290,12 @@ as the constructor's argument::
content = StringField() content = StringField()
.. _one-to-many-with-listfields: .. _many-to-many-with-listfields:
One to Many with ListFields Many to Many with ListFields
''''''''''''''''''''''''''' '''''''''''''''''''''''''''
If you are implementing a one to many relationship via a list of references, 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 then the references are stored as DBRefs and to query you need to pass an
instance of the object to the query:: instance of the object to the query::

View File

@@ -35,7 +35,7 @@ existing ``User`` model with a `default=True`. Thus you simply update the ``User
class User(Document): class User(Document):
name = StringField(required=True) name = StringField(required=True)
enabled = BooleaField(default=True) enabled = BooleanField(default=True)
Without applying any migration, we now reload an object from the database into the ``User`` class Without applying any migration, we now reload an object from the database into the ``User`` class
and checks its `enabled` attribute: and checks its `enabled` attribute:

View File

@@ -120,4 +120,3 @@ the validation and cleaning of a document when you call :meth:`~mongoengine.docu
Person(age=1000).save(validate=False) Person(age=1000).save(validate=False)
person = Person.objects.first() person = Person.objects.first()
assert person.age == 1000 assert person.age == 1000

View File

@@ -1,10 +1,12 @@
# Import submodules so that we can expose their __all__ # Import submodules so that we can expose their __all__
from mongoengine import connection from mongoengine import (
from mongoengine import document connection,
from mongoengine import errors document,
from mongoengine import fields errors,
from mongoengine import queryset fields,
from mongoengine import signals queryset,
signals,
)
# Import everything from each submodule so that it can be accessed via # Import everything from each submodule so that it can be accessed via
# mongoengine, e.g. instead of `from mongoengine.connection import connect`, # mongoengine, e.g. instead of `from mongoengine.connection import connect`,
@@ -17,7 +19,6 @@ from mongoengine.fields import * # noqa: F401
from mongoengine.queryset import * # noqa: F401 from mongoengine.queryset import * # noqa: F401
from mongoengine.signals import * # noqa: F401 from mongoengine.signals import * # noqa: F401
__all__ = ( __all__ = (
list(document.__all__) list(document.__all__)
+ list(fields.__all__) + list(fields.__all__)
@@ -28,7 +29,7 @@ __all__ = (
) )
VERSION = (0, 23, 0) VERSION = (0, 23, 1)
def get_version(): def get_version():

View File

@@ -1,10 +1,9 @@
import copy import copy
import numbers import numbers
from functools import partial from functools import partial
from bson import DBRef, ObjectId, SON, json_util
import pymongo import pymongo
from bson import SON, DBRef, ObjectId, json_util
from mongoengine import signals from mongoengine import signals
from mongoengine.base.common import get_document from mongoengine.base.common import get_document
@@ -615,7 +614,9 @@ class BaseDocument:
def _get_changed_fields(self): def _get_changed_fields(self):
"""Return a list of all fields that have explicitly been changed.""" """Return a list of all fields that have explicitly been changed."""
EmbeddedDocument = _import_class("EmbeddedDocument") EmbeddedDocument = _import_class("EmbeddedDocument")
LazyReferenceField = _import_class("LazyReferenceField")
ReferenceField = _import_class("ReferenceField") ReferenceField = _import_class("ReferenceField")
GenericLazyReferenceField = _import_class("GenericLazyReferenceField")
GenericReferenceField = _import_class("GenericReferenceField") GenericReferenceField = _import_class("GenericReferenceField")
SortedListField = _import_class("SortedListField") SortedListField = _import_class("SortedListField")
@@ -641,7 +642,13 @@ class BaseDocument:
changed_fields += [f"{key}{k}" for k in changed if k] changed_fields += [f"{key}{k}" for k in changed if k]
elif isinstance(data, (list, tuple, dict)): elif isinstance(data, (list, tuple, dict)):
if hasattr(field, "field") and isinstance( if hasattr(field, "field") and isinstance(
field.field, (ReferenceField, GenericReferenceField) field.field,
(
LazyReferenceField,
ReferenceField,
GenericLazyReferenceField,
GenericReferenceField,
),
): ):
continue continue
elif isinstance(field, SortedListField) and field._ordering: elif isinstance(field, SortedListField) and field._ordering:

View File

@@ -1,11 +1,15 @@
import operator import operator
import weakref import weakref
from bson import DBRef, ObjectId, SON
import pymongo import pymongo
from bson import SON, DBRef, ObjectId
from mongoengine.base.common import UPDATE_OPERATORS from mongoengine.base.common import UPDATE_OPERATORS
from mongoengine.base.datastructures import BaseDict, BaseList, EmbeddedDocumentList from mongoengine.base.datastructures import (
BaseDict,
BaseList,
EmbeddedDocumentList,
)
from mongoengine.common import _import_class from mongoengine.common import _import_class
from mongoengine.errors import DeprecatedError, ValidationError from mongoengine.errors import DeprecatedError, ValidationError
@@ -267,6 +271,17 @@ class ComplexBaseField(BaseField):
self.field = field self.field = field
super().__init__(**kwargs) super().__init__(**kwargs)
@staticmethod
def _lazy_load_refs(instance, name, ref_values, *, max_depth):
_dereference = _import_class("DeReference")()
documents = _dereference(
ref_values,
max_depth=max_depth,
instance=instance,
name=name,
)
return documents
def __get__(self, instance, owner): def __get__(self, instance, owner):
"""Descriptor to automatically dereference references.""" """Descriptor to automatically dereference references."""
if instance is None: if instance is None:
@@ -284,19 +299,15 @@ class ComplexBaseField(BaseField):
or isinstance(self.field, (GenericReferenceField, ReferenceField)) or isinstance(self.field, (GenericReferenceField, ReferenceField))
) )
_dereference = _import_class("DeReference")()
if ( if (
instance._initialised instance._initialised
and dereference and dereference
and instance._data.get(self.name) and instance._data.get(self.name)
and not getattr(instance._data[self.name], "_dereferenced", False) and not getattr(instance._data[self.name], "_dereferenced", False)
): ):
instance._data[self.name] = _dereference( ref_values = instance._data.get(self.name)
instance._data.get(self.name), instance._data[self.name] = self._lazy_load_refs(
max_depth=1, ref_values=ref_values, instance=instance, name=self.name, max_depth=1
instance=instance,
name=self.name,
) )
if hasattr(instance._data[self.name], "_dereferenced"): if hasattr(instance._data[self.name], "_dereferenced"):
instance._data[self.name]._dereferenced = True instance._data[self.name]._dereferenced = True
@@ -322,7 +333,9 @@ class ComplexBaseField(BaseField):
and isinstance(value, (BaseList, BaseDict)) and isinstance(value, (BaseList, BaseDict))
and not value._dereferenced and not value._dereferenced
): ):
value = _dereference(value, max_depth=1, instance=instance, name=self.name) value = self._lazy_load_refs(
ref_values=value, instance=instance, name=self.name, max_depth=1
)
value._dereferenced = True value._dereferenced = True
instance._data[self.name] = value instance._data[self.name] = value

View File

@@ -2,7 +2,11 @@ import itertools
import warnings import warnings
from mongoengine.base.common import _document_registry from mongoengine.base.common import _document_registry
from mongoengine.base.fields import BaseField, ComplexBaseField, ObjectIdField from mongoengine.base.fields import (
BaseField,
ComplexBaseField,
ObjectIdField,
)
from mongoengine.common import _import_class from mongoengine.common import _import_class
from mongoengine.errors import InvalidDocumentError from mongoengine.errors import InvalidDocumentError
from mongoengine.queryset import ( from mongoengine.queryset import (
@@ -12,7 +16,6 @@ from mongoengine.queryset import (
QuerySetManager, QuerySetManager,
) )
__all__ = ("DocumentMetaclass", "TopLevelDocumentMetaclass") __all__ = ("DocumentMetaclass", "TopLevelDocumentMetaclass")

View File

@@ -217,8 +217,8 @@ def register_connection(
def disconnect(alias=DEFAULT_CONNECTION_NAME): def disconnect(alias=DEFAULT_CONNECTION_NAME):
"""Close the connection with a given alias.""" """Close the connection with a given alias."""
from mongoengine.base.common import _get_documents_by_db
from mongoengine import Document from mongoengine import Document
from mongoengine.base.common import _get_documents_by_db
if alias in _connections: if alias in _connections:
get_connection(alias=alias).close() get_connection(alias=alias).close()

View File

@@ -1,4 +1,4 @@
from bson import DBRef, SON from bson import SON, DBRef
from mongoengine.base import ( from mongoengine.base import (
BaseDict, BaseDict,
@@ -10,7 +10,12 @@ from mongoengine.base import (
from mongoengine.base.datastructures import LazyReference from mongoengine.base.datastructures import LazyReference
from mongoengine.connection import get_db from mongoengine.connection import get_db
from mongoengine.document import Document, EmbeddedDocument from mongoengine.document import Document, EmbeddedDocument
from mongoengine.fields import DictField, ListField, MapField, ReferenceField from mongoengine.fields import (
DictField,
ListField,
MapField,
ReferenceField,
)
from mongoengine.queryset import QuerySet from mongoengine.queryset import QuerySet

View File

@@ -1,7 +1,7 @@
import re import re
from bson.dbref import DBRef
import pymongo import pymongo
from bson.dbref import DBRef
from pymongo.read_preferences import ReadPreference from pymongo.read_preferences import ReadPreference
from mongoengine import signals from mongoengine import signals
@@ -16,14 +16,23 @@ from mongoengine.base import (
) )
from mongoengine.common import _import_class 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.context_managers import set_write_concern, switch_collection, switch_db from mongoengine.context_managers import (
set_write_concern,
switch_collection,
switch_db,
)
from mongoengine.errors import ( from mongoengine.errors import (
InvalidDocumentError, InvalidDocumentError,
InvalidQueryError, InvalidQueryError,
SaveConditionError, SaveConditionError,
) )
from mongoengine.pymongo_support import list_collection_names from mongoengine.pymongo_support import list_collection_names
from mongoengine.queryset import NotUniqueError, OperationError, QuerySet, transform from mongoengine.queryset import (
NotUniqueError,
OperationError,
QuerySet,
transform,
)
__all__ = ( __all__ = (
"Document", "Document",
@@ -323,7 +332,7 @@ class Document(BaseDocument, metaclass=TopLevelDocumentMetaclass):
_refs=None, _refs=None,
save_condition=None, save_condition=None,
signal_kwargs=None, signal_kwargs=None,
**kwargs **kwargs,
): ):
"""Save the :class:`~mongoengine.Document` to the database. If the """Save the :class:`~mongoengine.Document` to the database. If the
document already exists, it will be updated, otherwise it will be document already exists, it will be updated, otherwise it will be
@@ -554,7 +563,7 @@ class Document(BaseDocument, metaclass=TopLevelDocumentMetaclass):
if not getattr(ref, "_changed_fields", True): if not getattr(ref, "_changed_fields", True):
continue continue
ref_id = "{},{}".format(ref.__class__.__name__, str(ref._data)) ref_id = f"{ref.__class__.__name__},{str(ref._data)}"
if ref and ref_id not in _refs: if ref and ref_id not in _refs:
_refs.append(ref_id) _refs.append(ref_id)
kwargs["_refs"] = _refs kwargs["_refs"] = _refs

View File

@@ -1,6 +1,5 @@
from collections import defaultdict from collections import defaultdict
__all__ = ( __all__ = (
"NotRegistered", "NotRegistered",
"InvalidDocumentError", "InvalidDocumentError",

View File

@@ -9,10 +9,10 @@ import uuid
from io import BytesIO from io import BytesIO
from operator import itemgetter from operator import itemgetter
from bson import Binary, DBRef, ObjectId, SON
from bson.int64 import Int64
import gridfs import gridfs
import pymongo import pymongo
from bson import SON, Binary, DBRef, ObjectId
from bson.int64 import Int64
from pymongo import ReturnDocument from pymongo import ReturnDocument
try: try:
@@ -22,7 +22,6 @@ except ImportError:
else: else:
import dateutil.parser import dateutil.parser
from mongoengine.base import ( from mongoengine.base import (
BaseDocument, BaseDocument,
BaseField, BaseField,
@@ -36,7 +35,11 @@ from mongoengine.base.utils import LazyRegexCompiler
from mongoengine.common import _import_class 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.queryset import DO_NOTHING from mongoengine.queryset import DO_NOTHING
from mongoengine.queryset.base import BaseQuerySet from mongoengine.queryset.base import BaseQuerySet
from mongoengine.queryset.transform import STRING_OPERATORS from mongoengine.queryset.transform import STRING_OPERATORS
@@ -915,7 +918,7 @@ class ListField(ComplexBaseField):
"""A list field that wraps a standard field, allowing multiple instances """A list field that wraps a standard field, allowing multiple instances
of the field to be used as a list in the database. of the field to be used as a list in the database.
If using with ReferenceFields see: :ref:`one-to-many-with-listfields` If using with ReferenceFields see: :ref:`many-to-many-with-listfields`
.. note:: .. note::
Required means it cannot be empty - as the default for ListFields is [] Required means it cannot be empty - as the default for ListFields is []
@@ -1194,6 +1197,14 @@ class ReferenceField(BaseField):
self.document_type_obj = get_document(self.document_type_obj) self.document_type_obj = get_document(self.document_type_obj)
return self.document_type_obj return self.document_type_obj
@staticmethod
def _lazy_load_ref(ref_cls, dbref):
dereferenced_son = ref_cls._get_db().dereference(dbref)
if dereferenced_son is None:
raise DoesNotExist(f"Trying to dereference unknown document {dbref}")
return ref_cls._from_son(dereferenced_son)
def __get__(self, instance, owner): def __get__(self, instance, owner):
"""Descriptor to allow lazy dereferencing.""" """Descriptor to allow lazy dereferencing."""
if instance is None: if instance is None:
@@ -1201,20 +1212,17 @@ class ReferenceField(BaseField):
return self return self
# Get value from document instance if available # Get value from document instance if available
value = instance._data.get(self.name) ref_value = instance._data.get(self.name)
auto_dereference = instance._fields[self.name]._auto_dereference auto_dereference = instance._fields[self.name]._auto_dereference
# Dereference DBRefs # Dereference DBRefs
if auto_dereference and isinstance(value, DBRef): if auto_dereference and isinstance(ref_value, DBRef):
if hasattr(value, "cls"): if hasattr(ref_value, "cls"):
# Dereference using the class type specified in the reference # Dereference using the class type specified in the reference
cls = get_document(value.cls) cls = get_document(ref_value.cls)
else: else:
cls = self.document_type cls = self.document_type
dereferenced = cls._get_db().dereference(value)
if dereferenced is None: instance._data[self.name] = self._lazy_load_ref(cls, ref_value)
raise DoesNotExist("Trying to dereference unknown document %s" % value)
else:
instance._data[self.name] = cls._from_son(dereferenced)
return super().__get__(instance, owner) return super().__get__(instance, owner)
@@ -1353,6 +1361,14 @@ class CachedReferenceField(BaseField):
self.document_type_obj = get_document(self.document_type_obj) self.document_type_obj = get_document(self.document_type_obj)
return self.document_type_obj return self.document_type_obj
@staticmethod
def _lazy_load_ref(ref_cls, dbref):
dereferenced_son = ref_cls._get_db().dereference(dbref)
if dereferenced_son is None:
raise DoesNotExist(f"Trying to dereference unknown document {dbref}")
return ref_cls._from_son(dereferenced_son)
def __get__(self, instance, owner): def __get__(self, instance, owner):
if instance is None: if instance is None:
# Document class being used rather than a document object # Document class being used rather than a document object
@@ -1364,11 +1380,7 @@ class CachedReferenceField(BaseField):
# Dereference DBRefs # Dereference DBRefs
if auto_dereference and isinstance(value, DBRef): if auto_dereference and isinstance(value, DBRef):
dereferenced = self.document_type._get_db().dereference(value) instance._data[self.name] = self._lazy_load_ref(self.document_type, value)
if dereferenced is None:
raise DoesNotExist("Trying to dereference unknown document %s" % value)
else:
instance._data[self.name] = self.document_type._from_son(dereferenced)
return super().__get__(instance, owner) return super().__get__(instance, owner)
@@ -1493,6 +1505,14 @@ class GenericReferenceField(BaseField):
value = value._class_name value = value._class_name
super()._validate_choices(value) super()._validate_choices(value)
@staticmethod
def _lazy_load_ref(ref_cls, dbref):
dereferenced_son = ref_cls._get_db().dereference(dbref)
if dereferenced_son is None:
raise DoesNotExist(f"Trying to dereference unknown document {dbref}")
return ref_cls._from_son(dereferenced_son)
def __get__(self, instance, owner): def __get__(self, instance, owner):
if instance is None: if instance is None:
return self return self
@@ -1500,12 +1520,9 @@ class GenericReferenceField(BaseField):
value = instance._data.get(self.name) value = instance._data.get(self.name)
auto_dereference = instance._fields[self.name]._auto_dereference auto_dereference = instance._fields[self.name]._auto_dereference
if auto_dereference and isinstance(value, (dict, SON)): if auto_dereference and isinstance(value, dict):
dereferenced = self.dereference(value) doc_cls = get_document(value["_cls"])
if dereferenced is None: instance._data[self.name] = self._lazy_load_ref(doc_cls, value["_ref"])
raise DoesNotExist("Trying to dereference unknown document %s" % value)
else:
instance._data[self.name] = dereferenced
return super().__get__(instance, owner) return super().__get__(instance, owner)
@@ -1524,14 +1541,6 @@ class GenericReferenceField(BaseField):
" saved to the database" " saved to the database"
) )
def dereference(self, value):
doc_cls = get_document(value["_cls"])
reference = value["_ref"]
doc = doc_cls._get_db().dereference(reference)
if doc is not None:
doc = doc_cls._from_son(doc)
return doc
def to_mongo(self, document): def to_mongo(self, document):
if document is None: if document is None:
return None return None

View File

@@ -3,7 +3,6 @@ Helper functions, constants, and types to aid with MongoDB version support
""" """
from mongoengine.connection import get_connection from mongoengine.connection import get_connection
# Constant that can be used to compare the version retrieved with # Constant that can be used to compare the version retrieved with
# get_mongodb_version() # get_mongodb_version()
MONGODB_34 = (3, 4) MONGODB_34 = (3, 4)

View File

@@ -2,13 +2,12 @@ import copy
import itertools import itertools
import re import re
import warnings import warnings
from collections.abc import Mapping from collections.abc import Mapping
from bson import SON, json_util
from bson.code import Code
import pymongo import pymongo
import pymongo.errors import pymongo.errors
from bson import SON, json_util
from bson.code import Code
from pymongo.collection import ReturnDocument from pymongo.collection import ReturnDocument
from pymongo.common import validate_read_preference from pymongo.common import validate_read_preference
from pymongo.read_concern import ReadConcern from pymongo.read_concern import ReadConcern
@@ -34,7 +33,6 @@ from mongoengine.queryset import transform
from mongoengine.queryset.field_list import QueryFieldList from mongoengine.queryset.field_list import QueryFieldList
from mongoengine.queryset.visitor import Q, QNode from mongoengine.queryset.visitor import Q, QNode
__all__ = ("BaseQuerySet", "DO_NOTHING", "NULLIFY", "CASCADE", "DENY", "PULL") __all__ = ("BaseQuerySet", "DO_NOTHING", "NULLIFY", "CASCADE", "DENY", "PULL")
# Delete rules # Delete rules

View File

@@ -1,4 +1,5 @@
from functools import partial from functools import partial
from mongoengine.queryset.queryset import QuerySet from mongoengine.queryset.queryset import QuerySet
__all__ = ("queryset_manager", "QuerySetManager") __all__ = ("queryset_manager", "QuerySetManager")

View File

@@ -1,11 +1,11 @@
from mongoengine.errors import OperationError from mongoengine.errors import OperationError
from mongoengine.queryset.base import ( from mongoengine.queryset.base import (
BaseQuerySet,
CASCADE, CASCADE,
DENY, DENY,
DO_NOTHING, DO_NOTHING,
NULLIFY, NULLIFY,
PULL, PULL,
BaseQuerySet,
) )
__all__ = ( __all__ = (

View File

@@ -1,8 +1,8 @@
from collections import defaultdict from collections import defaultdict
from bson import ObjectId, SON
from bson.dbref import DBRef
import pymongo import pymongo
from bson import SON, ObjectId
from bson.dbref import DBRef
from mongoengine.base import UPDATE_OPERATORS from mongoengine.base import UPDATE_OPERATORS
from mongoengine.common import _import_class from mongoengine.common import _import_class

View File

@@ -1,6 +1,5 @@
black black
flake8 flake8
flake8-import-order
pre-commit pre-commit
pytest pytest
ipdb ipdb

View File

@@ -2,9 +2,17 @@
ignore=E501,F403,F405,I201,I202,W504,W605,W503,B007 ignore=E501,F403,F405,I201,I202,W504,W605,W503,B007
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
[tool:pytest] [tool:pytest]
# Limits the discovery to tests directory # Limits the discovery to tests directory
# avoids that it runs for instance the benchmark # avoids that it runs for instance the benchmark
testpaths = tests testpaths = tests
[isort]
known_first_party = mongoengine,tests
default_section = THIRDPARTY
multi_line_output = 3
include_trailing_comma = True
combine_as_imports = True
line_length = 70
ensure_newline_before_comments = 1

View File

@@ -53,8 +53,8 @@ class PyTest(TestCommand):
def run_tests(self): def run_tests(self):
# import here, cause outside the eggs aren't loaded # import here, cause outside the eggs aren't loaded
from pkg_resources import _namespace_packages
import pytest import pytest
from pkg_resources import _namespace_packages
# Purge modules under test from sys.modules. The test loader will # Purge modules under test from sys.modules. The test loader will
# re-import them from the build location. Required when 2to3 is used # re-import them from the build location. Required when 2to3 is used

View File

@@ -177,7 +177,7 @@ class TestClassMethods(unittest.TestCase):
assert BlogPostWithCustomField.compare_indexes() == {"missing": [], "extra": []} assert 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"""
class Doc(Document): class Doc(Document):
a = StringField() a = StringField()

View File

@@ -1,6 +1,7 @@
import unittest import unittest
from bson import SON from bson import SON
from mongoengine import * from mongoengine import *
from mongoengine.pymongo_support import list_collection_names from mongoengine.pymongo_support import list_collection_names
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,13 +1,16 @@
import unittest import unittest
from datetime import datetime from datetime import datetime
import pytest
from pymongo.collation import Collation from pymongo.collation import Collation
from pymongo.errors import OperationFailure from pymongo.errors import OperationFailure
import pytest
from mongoengine import * from mongoengine import *
from mongoengine.connection import get_db from mongoengine.connection import get_db
from mongoengine.mongodb_support import MONGODB_42, get_mongodb_version from mongoengine.mongodb_support import (
MONGODB_42,
get_mongodb_version,
)
class TestIndexes(unittest.TestCase): class TestIndexes(unittest.TestCase):

View File

@@ -6,9 +6,9 @@ import weakref
from datetime import datetime from datetime import datetime
import bson import bson
import pytest
from bson import DBRef, ObjectId from bson import DBRef, ObjectId
from pymongo.errors import DuplicateKeyError from pymongo.errors import DuplicateKeyError
import pytest
from mongoengine import * from mongoengine import *
from mongoengine import signals from mongoengine import signals
@@ -23,7 +23,11 @@ from mongoengine.errors import (
NotUniqueError, NotUniqueError,
SaveConditionError, SaveConditionError,
) )
from mongoengine.mongodb_support import MONGODB_34, MONGODB_36, get_mongodb_version from mongoengine.mongodb_support import (
MONGODB_34,
MONGODB_36,
get_mongodb_version,
)
from mongoengine.pymongo_support import list_collection_names from mongoengine.pymongo_support import list_collection_names
from mongoengine.queryset import NULLIFY, Q from mongoengine.queryset import NULLIFY, Q
from tests import fixtures from tests import fixtures

View File

@@ -1,7 +1,7 @@
import unittest import unittest
import uuid import uuid
from datetime import datetime from datetime import datetime
from bson import ObjectId from bson import ObjectId
from mongoengine import * from mongoengine import *

View File

@@ -1,7 +1,7 @@
import uuid import uuid
from bson import Binary
import pytest import pytest
from bson import Binary
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -6,7 +6,6 @@ import re
import pytest import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -9,7 +9,6 @@ except ImportError:
from mongoengine import * from mongoengine import *
from mongoengine import connection from mongoengine import connection
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,10 +1,12 @@
from bson import InvalidDocument
import pytest import pytest
from bson import InvalidDocument
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 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

View File

@@ -12,7 +12,6 @@ from mongoengine import (
StringField, StringField,
ValidationError, ValidationError,
) )
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,7 +1,7 @@
from enum import Enum from enum import Enum
from bson import InvalidDocument
import pytest import pytest
from bson import InvalidDocument
from mongoengine import Document, EnumField, ValidationError from mongoengine import Document, EnumField, ValidationError
from tests.utils import MongoDBTestCase, get_as_pymongo from tests.utils import MongoDBTestCase, get_as_pymongo

View File

@@ -1,8 +1,8 @@
import datetime import datetime
import unittest import unittest
from bson import DBRef, ObjectId, SON
import pytest import pytest
from bson import SON, DBRef, ObjectId
from mongoengine import ( from mongoengine import (
BooleanField, BooleanField,
@@ -34,9 +34,12 @@ from mongoengine import (
StringField, StringField,
ValidationError, ValidationError,
) )
from mongoengine.base import BaseField, EmbeddedDocumentList, _document_registry from mongoengine.base import (
BaseField,
EmbeddedDocumentList,
_document_registry,
)
from mongoengine.errors import DeprecatedError from mongoengine.errors import DeprecatedError
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -308,7 +308,7 @@ class TestFileField(MongoDBTestCase):
assert test_file.the_file not in [{"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"""
class TestFile(Document): class TestFile(Document):
the_file = FileField() the_file = FileField()

View File

@@ -1,7 +1,6 @@
import pytest import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,7 +1,6 @@
import pytest import pytest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,10 +1,9 @@
from bson import DBRef, ObjectId
import pytest import pytest
from bson import DBRef, ObjectId
from mongoengine import * from mongoengine import *
from mongoengine.base import LazyReference from mongoengine.base import LazyReference
from mongoengine.context_managers import query_counter from mongoengine.context_managers import query_counter
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase
@@ -375,6 +374,26 @@ class TestLazyReferenceField(MongoDBTestCase):
assert isinstance(ref.author, LazyReference) assert isinstance(ref.author, LazyReference)
assert isinstance(ref.author.id, ObjectId) assert isinstance(ref.author.id, ObjectId)
def test_lazy_reference_in_list_with_changed_element(self):
class Animal(Document):
name = StringField()
tag = StringField()
class Ocurrence(Document):
in_list = ListField(LazyReferenceField(Animal))
Animal.drop_collection()
Ocurrence.drop_collection()
animal1 = Animal(name="doggo").save()
animal1.tag = "blue"
occ = Ocurrence(in_list=[animal1]).save()
animal1.save()
assert isinstance(occ.in_list[0], LazyReference)
assert occ.in_list[0].pk == animal1.pk
class TestGenericLazyReferenceField(MongoDBTestCase): class TestGenericLazyReferenceField(MongoDBTestCase):
def test_generic_lazy_reference_simple(self): def test_generic_lazy_reference_simple(self):

View File

@@ -1,9 +1,8 @@
from bson.int64 import Int64
import pytest import pytest
from bson.int64 import Int64
from mongoengine import * from mongoengine import *
from mongoengine.connection import get_db from mongoengine.connection import get_db
from tests.utils import MongoDBTestCase, get_as_pymongo from tests.utils import MongoDBTestCase, get_as_pymongo

View File

@@ -1,5 +1,5 @@
from bson import DBRef, SON
import pytest import pytest
from bson import SON, DBRef
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,5 +1,4 @@
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -2,7 +2,6 @@ import datetime
import unittest import unittest
from mongoengine import * from mongoengine import *
from tests.utils import MongoDBTestCase from tests.utils import MongoDBTestCase

View File

@@ -1,6 +1,12 @@
import unittest import unittest
from mongoengine import Document, IntField, ListField, StringField, connect from mongoengine import (
Document,
IntField,
ListField,
StringField,
connect,
)
class Doc(Document): class Doc(Document):

View File

@@ -3,17 +3,20 @@ import unittest
import uuid import uuid
from decimal import Decimal from decimal import Decimal
from bson import DBRef, ObjectId
import pymongo import pymongo
import pytest
from bson import DBRef, ObjectId
from pymongo.read_preferences import ReadPreference from pymongo.read_preferences import ReadPreference
from pymongo.results import UpdateResult from pymongo.results import UpdateResult
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 query_counter, switch_db from mongoengine.context_managers import query_counter, switch_db
from mongoengine.errors import InvalidQueryError from mongoengine.errors import InvalidQueryError
from mongoengine.mongodb_support import MONGODB_36, get_mongodb_version from mongoengine.mongodb_support import (
MONGODB_36,
get_mongodb_version,
)
from mongoengine.queryset import ( from mongoengine.queryset import (
DoesNotExist, DoesNotExist,
MultipleObjectsReturned, MultipleObjectsReturned,

View File

@@ -1,7 +1,7 @@
import unittest import unittest
from bson.son import SON
import pytest import pytest
from bson.son import SON
from mongoengine import * from mongoengine import *
from mongoengine.queryset import Q, transform from mongoengine.queryset import Q, transform

View File

@@ -2,8 +2,8 @@ import datetime
import re import re
import unittest import unittest
from bson import ObjectId
import pytest import pytest
from bson import ObjectId
from mongoengine import * from mongoengine import *
from mongoengine.errors import InvalidQueryError from mongoengine.errors import InvalidQueryError

View File

@@ -1,11 +1,11 @@
import datetime import datetime
import unittest import unittest
from bson.tz_util import utc
import pymongo import pymongo
import pytest
from bson.tz_util import utc
from pymongo import MongoClient, ReadPreference from pymongo import MongoClient, ReadPreference
from pymongo.errors import InvalidName, OperationFailure from pymongo.errors import InvalidName, OperationFailure
import pytest
import mongoengine.connection import mongoengine.connection
from mongoengine import ( from mongoengine import (
@@ -17,8 +17,8 @@ from mongoengine import (
register_connection, register_connection,
) )
from mongoengine.connection import ( from mongoengine.connection import (
ConnectionFailure,
DEFAULT_DATABASE_NAME, DEFAULT_DATABASE_NAME,
ConnectionFailure,
disconnect, disconnect,
get_connection, get_connection,
get_db, get_db,

View File

@@ -3,15 +3,9 @@ import unittest
import pytest import pytest
import mongoengine.connection import mongoengine.connection
from mongoengine import ( from mongoengine import Document, StringField, connect, disconnect_all
Document,
StringField,
connect,
disconnect_all,
)
from mongoengine.connection import get_connection from mongoengine.connection import get_connection
try: try:
import mongomock import mongomock

View File

@@ -3,7 +3,11 @@ import unittest
import pytest import pytest
from mongoengine import Document from mongoengine import Document
from mongoengine.base.datastructures import BaseDict, BaseList, StrictDict from mongoengine.base.datastructures import (
BaseDict,
BaseList,
StrictDict,
)
class DocumentStub: class DocumentStub:

View File

@@ -5,7 +5,6 @@ from pymongo import MongoClient, ReadPreference
import mongoengine import mongoengine
from mongoengine.connection import ConnectionFailure from mongoengine.connection import ConnectionFailure
CONN_CLASS = MongoClient CONN_CLASS = MongoClient
READ_PREF = ReadPreference.SECONDARY READ_PREF = ReadPreference.SECONDARY

View File

@@ -249,7 +249,7 @@ class TestSignal(unittest.TestCase):
assert 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."""
def create_author(): def create_author():
self.Author(name="Bill Shakespeare") self.Author(name="Bill Shakespeare")
@@ -340,7 +340,7 @@ class TestSignal(unittest.TestCase):
] ]
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."""
def live_and_let_die(): def live_and_let_die():
a = self.Author(name="Bill Shakespeare") a = self.Author(name="Bill Shakespeare")
@@ -385,7 +385,7 @@ class TestSignal(unittest.TestCase):
] ]
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()
assert self.get_signal_output(self.Another.objects.delete) == [ assert self.get_signal_output(self.Another.objects.delete) == [
@@ -396,7 +396,7 @@ class TestSignal(unittest.TestCase):
] ]
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

View File

@@ -7,7 +7,6 @@ from mongoengine import connect
from mongoengine.connection import disconnect_all, get_db from mongoengine.connection import disconnect_all, get_db
from mongoengine.mongodb_support import get_mongodb_version from mongoengine.mongodb_support import get_mongodb_version
MONGO_TEST_DB = "mongoenginetest" # standard name for the test database MONGO_TEST_DB = "mongoenginetest" # standard name for the test database