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

This commit is contained in:
Bastien Gérard
2018-09-04 16:06:45 +02:00
11 changed files with 229 additions and 48 deletions

View File

@@ -104,6 +104,18 @@ def register_connection(alias, db=None, name=None, host=None, port=None,
conn_settings['authentication_source'] = uri_options['authsource']
if 'authmechanism' in uri_options:
conn_settings['authentication_mechanism'] = uri_options['authmechanism']
if IS_PYMONGO_3 and 'readpreference' in uri_options:
read_preferences = (
ReadPreference.NEAREST,
ReadPreference.PRIMARY,
ReadPreference.PRIMARY_PREFERRED,
ReadPreference.SECONDARY,
ReadPreference.SECONDARY_PREFERRED)
read_pf_mode = uri_options['readpreference'].lower()
for preference in read_preferences:
if preference.name.lower() == read_pf_mode:
conn_settings['read_preference'] = preference
break
else:
resolved_hosts.append(entity)
conn_settings['host'] = resolved_hosts

View File

@@ -145,18 +145,17 @@ class no_sub_classes(object):
:param cls: the class to turn querying sub classes on
"""
self.cls = cls
self.cls_initial_subclasses = None
def __enter__(self):
"""Change the objects default and _auto_dereference values."""
self.cls._all_subclasses = self.cls._subclasses
self.cls._subclasses = (self.cls,)
self.cls_initial_subclasses = self.cls._subclasses
self.cls._subclasses = (self.cls._class_name,)
return self.cls
def __exit__(self, t, value, traceback):
"""Reset the default and _auto_dereference values."""
self.cls._subclasses = self.cls._all_subclasses
delattr(self.cls, '_all_subclasses')
return self.cls
self.cls._subclasses = self.cls_initial_subclasses
class query_counter(object):
@@ -215,7 +214,7 @@ class query_counter(object):
"""Get the number of queries."""
ignore_query = {'ns': {'$ne': '%s.system.indexes' % self.db.name}}
count = self.db.system.profile.find(ignore_query).count() - self.counter
self.counter += 1
self.counter += 1 # Account for the query we just fired
return count

View File

@@ -364,7 +364,8 @@ class FloatField(BaseField):
class DecimalField(BaseField):
"""Fixed-point decimal number field.
"""Fixed-point decimal number field. Stores the value as a float by default unless `force_string` is used.
If using floats, beware of Decimal to float conversion (potential precision loss)
.. versionchanged:: 0.8
.. versionadded:: 0.3
@@ -375,7 +376,9 @@ class DecimalField(BaseField):
"""
:param min_value: Validation rule for the minimum acceptable value.
:param max_value: Validation rule for the maximum acceptable value.
:param force_string: Store as a string.
:param force_string: Store the value as a string (instead of a float).
Be aware that this affects query sorting and operation like lte, gte (as string comparison is applied)
and some query operator won't work (e.g: inc, dec)
:param precision: Number of decimal places to store.
:param rounding: The rounding rule from the python decimal library:
@@ -647,9 +650,17 @@ class EmbeddedDocumentField(BaseField):
def document_type(self):
if isinstance(self.document_type_obj, six.string_types):
if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT:
self.document_type_obj = self.owner_document
resolved_document_type = self.owner_document
else:
self.document_type_obj = get_document(self.document_type_obj)
resolved_document_type = get_document(self.document_type_obj)
if not issubclass(resolved_document_type, EmbeddedDocument):
# Due to the late resolution of the document_type
# There is a chance that it won't be an EmbeddedDocument (#1661)
self.error('Invalid embedded document class provided to an '
'EmbeddedDocumentField')
self.document_type_obj = resolved_document_type
return self.document_type_obj
def to_python(self, value):
@@ -1029,11 +1040,13 @@ class ReferenceField(BaseField):
.. code-block:: python
class Bar(Document):
content = StringField()
foo = ReferenceField('Foo')
class Org(Document):
owner = ReferenceField('User')
Foo.register_delete_rule(Bar, 'foo', NULLIFY)
class User(Document):
org = ReferenceField('Org', reverse_delete_rule=CASCADE)
User.register_delete_rule(Org, 'owner', DENY)
.. versionchanged:: 0.5 added `reverse_delete_rule`
"""

View File

@@ -147,7 +147,7 @@ def query(_doc_cls=None, **kwargs):
if op is None or key not in mongo_query:
mongo_query[key] = value
elif key in mongo_query:
if isinstance(mongo_query[key], dict):
if isinstance(mongo_query[key], dict) and isinstance(value, dict):
mongo_query[key].update(value)
# $max/minDistance needs to come last - convert to SON
value_dict = mongo_query[key]
@@ -201,30 +201,37 @@ def update(_doc_cls=None, **update):
format.
"""
mongo_update = {}
for key, value in update.items():
if key == '__raw__':
mongo_update.update(value)
continue
parts = key.split('__')
# if there is no operator, default to 'set'
if len(parts) < 3 and parts[0] not in UPDATE_OPERATORS:
parts.insert(0, 'set')
# Check for an operator and transform to mongo-style if there is
op = None
if parts[0] in UPDATE_OPERATORS:
op = parts.pop(0)
# Convert Pythonic names to Mongo equivalents
if op in ('push_all', 'pull_all'):
op = op.replace('_all', 'All')
elif op == 'dec':
operator_map = {
'push_all': 'pushAll',
'pull_all': 'pullAll',
'dec': 'inc',
'add_to_set': 'addToSet',
'set_on_insert': 'setOnInsert'
}
if op == 'dec':
# Support decrement by flipping a positive value's sign
# and using 'inc'
op = 'inc'
value = -value
elif op == 'add_to_set':
op = 'addToSet'
elif op == 'set_on_insert':
op = 'setOnInsert'
# If the operator doesn't found from operator map, the op value
# will stay unchanged
op = operator_map.get(op, op)
match = None
if parts[-1] in COMPARISON_OPERATORS:
@@ -291,6 +298,8 @@ def update(_doc_cls=None, **update):
value = field.prepare_query_value(op, value)
elif op == 'unset':
value = 1
elif op == 'inc':
value = field.prepare_query_value(op, value)
if match:
match = '$' + match