Skip to content

Commit f0c34e6

Browse files
committed
Merge branch 'master' of github.com:MongoEngine/mongoengine
2 parents 6db2525 + 090e6e1 commit f0c34e6

38 files changed

+492
-172
lines changed

.github/workflows/github-actions.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ jobs:
115115
runs-on: ubuntu-latest
116116
needs: [linting, test, build_doc_dryrun]
117117
steps:
118-
- uses: actions/checkout@master
118+
- uses: actions/checkout@v3
119119
- uses: actions/setup-python@v4
120120
with:
121121
python-version: 3.9
@@ -130,7 +130,7 @@ jobs:
130130
needs: [linting, test, build_doc_dryrun, build-dryrun]
131131
if: github.event_name == 'create' && startsWith(github.ref, 'refs/tags/v')
132132
steps:
133-
- uses: actions/checkout@master
133+
- uses: actions/checkout@v3
134134
- name: Set up Python 3.9
135135
uses: actions/setup-python@v4
136136
with:
@@ -143,6 +143,6 @@ jobs:
143143
pip install wheel
144144
python setup.py sdist bdist_wheel
145145
- name: publish pypi
146-
uses: pypa/gh-action-pypi-publish@master
146+
uses: pypa/gh-action-pypi-publish@release/v1
147147
with:
148148
password: ${{ secrets.pypi_token }}

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ repos:
88
- id: trailing-whitespace
99
- id: end-of-file-fixer
1010
- repo: https://github.com/ambv/black
11-
rev: 22.12.0
11+
rev: 23.1.0
1212
hooks:
1313
- id: black
1414
- repo: https://github.com/pycqa/flake8
@@ -23,6 +23,6 @@ repos:
2323
- id: pyupgrade
2424
args: [--py36-plus]
2525
- repo: https://github.com/pycqa/isort
26-
rev: 5.11.4
26+
rev: 5.12.0
2727
hooks:
2828
- id: isort

docs/changelog.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ Changelog
77
Development
88
===========
99
- (Fill this out as you fix issues and develop your features).
10+
- Fix for uuidRepresentation not read when provided in URI #2741
11+
12+
Changes in 0.27.0
13+
=================
14+
- Update uuidRepresentation warnings with "unspecified" as the future default (instead of 'standard' previously advertised) #2739
15+
- Added `mongo_client_class` optional parameter to connect() to allow to use an alternative mongo client than pymongo.MongoClient.
16+
Typically to support mock mongo libraries like mongomock, montydb, mongita #2729
17+
- BREAKING CHANGE: connecting MongoEngine with mongomock should now use the new `mongo_client_class`
18+
For more info, check https://docs.mongoengine.org/guide/mongomock.html
19+
- Fix DictField that always gets marked as changed #2606
20+
- fix for Queryset.none() that has no effect on update/aggregate / first #2669
21+
22+
Changes in 0.26.0
23+
=================
1024
- BREAKING CHANGE: Improved the performance of :meth:`~mongoengine.Document.save()`
1125
by removing the call to :meth:`~mongoengine.Document.ensure_indexes` unless
1226
``meta['auto_create_index_on_save']`` is set to True. With the default settings, Document indexes
@@ -19,6 +33,8 @@ Development
1933
Although it could work to switch an existing DecimalField to Decimal128Field without applying a migration script,
2034
it is not recommended to do so (DecimalField uses float/str to store the value, Decimal128Field uses Decimal128).
2135
- BREAKING CHANGE: When using ListField(EnumField) or DictField(EnumField), the values weren't always cast into the Enum (#2531)
36+
- BREAKING CHANGE (bugfix) Querying ObjectIdField or ComplexDateTimeField with None no longer raise a ValidationError (#2681)
37+
- Allow updating a field that has an operator name e.g. "type" with .update(set__type="foo"). It was raising an error previously. #2595
2238

2339
Changes in 0.25.0
2440
=================

docs/guide/mongomock.rst

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
1-
==============================
1+
=========================
22
Use mongomock for testing
3-
==============================
3+
=========================
44

5-
`mongomock <https://github.com/vmalloc/mongomock/>`_ is a package to do just
6-
what the name implies, mocking a mongo database.
5+
Although we recommend running your tests against a regular MongoDB server, it is sometimes useful to plug
6+
MongoEngine to alternative implementations (mongomock, montydb, mongita, etc).
7+
8+
`mongomock <https://github.com/vmalloc/mongomock/>`_ is historically the one suggested for MongoEngine and is
9+
a package to do just what the name implies, mocking a mongo database.
710

811
To use with mongoengine, simply specify mongomock when connecting with
912
mongoengine:
1013

1114
.. code-block:: python
1215
13-
connect('mongoenginetest', host='mongomock://localhost')
16+
import mongomock
17+
18+
connect('mongoenginetest', host='mongodb://localhost', mongo_client_class=mongomock.MongoClient)
1419
conn = get_connection()
1520
1621
or with an alias:
1722

1823
.. code-block:: python
1924
20-
connect('mongoenginetest', host='mongomock://localhost', alias='testdb')
25+
connect('mongoenginetest', host='mongodb://localhost', mongo_client_class=mongomock.MongoClient, alias='testdb')
2126
conn = get_connection('testdb')
2227
2328
Example of test file:
@@ -34,7 +39,7 @@ Example of test file:
3439
3540
@classmethod
3641
def setUpClass(cls):
37-
connect('mongoenginetest', host='mongomock://localhost')
42+
connect('mongoenginetest', host='mongodb://localhost', mongo_client_class=mongomock.MongoClient)
3843
3944
@classmethod
4045
def tearDownClass(cls):

docs/guide/querying.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ you could use the following query::
196196

197197
Page.objects(tags__0='db')
198198

199+
The string queries operators can be used as well for querying a list field, e.g.::
200+
201+
Page.objects(tags__iexact='db')
202+
199203
If you only want to fetch part of a list eg: you want to paginate a list, then
200204
the `slice` operator is required::
201205

mongoengine/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
)
3030

3131

32-
VERSION = (0, 25, 0)
32+
VERSION = (0, 27, 0)
3333

3434

3535
def get_version():

mongoengine/base/datastructures.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ def mark_key_as_changed_wrapper(parent_method):
3131

3232
def wrapper(self, key, *args, **kwargs):
3333
# Can't use super() in the decorator.
34-
result = parent_method(self, key, *args, **kwargs)
35-
self._mark_as_changed(key)
36-
return result
34+
if not args or key not in self or self[key] != args[0]:
35+
self._mark_as_changed(key)
36+
return parent_method(self, key, *args, **kwargs)
3737

3838
return wrapper
3939

mongoengine/base/document.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ def __delattr__(self, *args, **kwargs):
161161
def __setattr__(self, name, value):
162162
# Handle dynamic data only if an initialised dynamic document
163163
if self._dynamic and not self._dynamic_lock:
164-
165164
if name not in self._fields_ordered and not name.startswith("_"):
166165
DynamicField = _import_class("DynamicField")
167166
field = DynamicField(db_field=name, null=True)
@@ -372,7 +371,7 @@ def to_mongo(self, use_db_field=True, fields=None):
372371
value = field.generate()
373372
self._data[field_name] = value
374373

375-
if (value is not None) or (field.null):
374+
if value is not None or field.null:
376375
if use_db_field:
377376
data[field.db_field] = value
378377
else:
@@ -451,7 +450,8 @@ def to_json(self, *args, **kwargs):
451450
"No 'json_options' are specified! Falling back to "
452451
"LEGACY_JSON_OPTIONS with uuid_representation=PYTHON_LEGACY. "
453452
"For use with other MongoDB drivers specify the UUID "
454-
"representation to use.",
453+
"representation to use. This will be changed to "
454+
"uuid_representation=UNSPECIFIED in a future release.",
455455
DeprecationWarning,
456456
)
457457
kwargs["json_options"] = LEGACY_JSON_OPTIONS
@@ -481,7 +481,8 @@ def from_json(cls, json_data, created=False, **kwargs):
481481
"No 'json_options' are specified! Falling back to "
482482
"LEGACY_JSON_OPTIONS with uuid_representation=PYTHON_LEGACY. "
483483
"For use with other MongoDB drivers specify the UUID "
484-
"representation to use.",
484+
"representation to use. This will be changed to "
485+
"uuid_representation=UNSPECIFIED in a future release.",
485486
DeprecationWarning,
486487
)
487488
kwargs["json_options"] = LEGACY_JSON_OPTIONS
@@ -517,9 +518,6 @@ def __expand_dynamic_values(self, name, value):
517518

518519
def _mark_as_changed(self, key):
519520
"""Mark a key as explicitly changed by the user."""
520-
if not key:
521-
return
522-
523521
if not hasattr(self, "_changed_fields"):
524522
return
525523

mongoengine/base/fields.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ def __init__(
5252
:param required: If the field is required. Whether it has to have a
5353
value or not. Defaults to False.
5454
:param default: (optional) The default value for this field if no value
55-
has been set (or if the value has been unset). It can be a
55+
has been set, if the value is set to None or has been unset. It can be a
5656
callable.
57-
:param unique: Is the field value unique or not. Defaults to False.
57+
:param unique: Is the field value unique or not (Creates an index). Defaults to False.
5858
:param unique_with: (optional) The other field this field should be
59-
unique with.
60-
:param primary_key: Mark this field as the primary key. Defaults to False.
59+
unique with (Creates an index).
60+
:param primary_key: Mark this field as the primary key ((Creates an index)). Defaults to False.
6161
:param validation: (optional) A callable to validate the value of the
6262
field. The callable takes the value as parameter and should raise
6363
a ValidationError if validation fails
6464
:param choices: (optional) The valid choices
65-
:param null: (optional) If the field value can be null. If no and there is a default value
66-
then the default value is set
65+
:param null: (optional) If the field value can be null when a default exist. If not set, the default value
66+
will be used in case a field with a default value is set to None. Defaults to False.
6767
:param sparse: (optional) `sparse=True` combined with `unique=True` and `required=False`
68-
means that uniqueness won't be enforced for `None` values
68+
means that uniqueness won't be enforced for `None` values (Creates an index). Defaults to False.
6969
:param **kwargs: (optional) Arbitrary indirection-free metadata for
7070
this field can be supplied as additional keyword arguments and
7171
accessed as attributes of the field. Must not conflict with any
@@ -521,14 +521,17 @@ def to_python(self, value):
521521
return value
522522

523523
def to_mongo(self, value):
524-
if not isinstance(value, ObjectId):
525-
try:
526-
return ObjectId(str(value))
527-
except Exception as e:
528-
self.error(str(e))
529-
return value
524+
if isinstance(value, ObjectId):
525+
return value
526+
527+
try:
528+
return ObjectId(str(value))
529+
except Exception as e:
530+
self.error(str(e))
530531

531532
def prepare_query_value(self, op, value):
533+
if value is None:
534+
return value
532535
return self.to_mongo(value)
533536

534537
def validate(self, value):

mongoengine/base/metaclasses.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ def __new__(mcs, name, bases, attrs):
178178
f.owner_document = new_class
179179
delete_rule = getattr(f, "reverse_delete_rule", DO_NOTHING)
180180
if isinstance(f, CachedReferenceField):
181-
182181
if issubclass(new_class, EmbeddedDocument):
183182
raise InvalidDocumentError(
184183
"CachedReferenceFields is not allowed in EmbeddedDocuments"

0 commit comments

Comments
 (0)