Skip to content

Commit f3c944a

Browse files
authored
Merge pull request #2724 from bagerard/update_operator_name_field
Clone - FIx for update on field with operator name
2 parents c4ef4d4 + 41689b8 commit f3c944a

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

.github/workflows/github-actions.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
# which runs pre-configured linter & autoformatter
3535
runs-on: ubuntu-latest
3636
steps:
37-
- uses: actions/checkout@v2
37+
- uses: actions/checkout@v3
3838
- uses: actions/setup-python@v4
3939
with:
4040
python-version: '3.9'
@@ -69,7 +69,7 @@ jobs:
6969
MONGODB: $MONGODB_5_0
7070
PYMONGO: $PYMONGO_4_3
7171
steps:
72-
- uses: actions/checkout@v2
72+
- uses: actions/checkout@v3
7373
- name: Set up Python ${{ matrix.python-version }}
7474
uses: actions/setup-python@v4
7575
with:
@@ -96,7 +96,7 @@ jobs:
9696
# to avoid that it breaks when new releases are being created
9797
runs-on: ubuntu-latest
9898
steps:
99-
- uses: actions/checkout@v2
99+
- uses: actions/checkout@v3
100100
- name: Set up Python ${{ matrix.python-version }}
101101
uses: actions/setup-python@v4
102102
with:

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Development
2020
it is not recommended to do so (DecimalField uses float/str to store the value, Decimal128Field uses Decimal128).
2121
- BREAKING CHANGE: When using ListField(EnumField) or DictField(EnumField), the values weren't always cast into the Enum (#2531)
2222
- BREAKING CHANGE (bugfix) Querying ObjectIdField or ComplexDateTimeField with None will no longer raise a ValidationError (#2681)
23+
- Allow updating a field that has an operator name e.g. "type" with .update(set__type="foo"). It was raising an error previously. #2595
2324

2425
Changes in 0.25.0
2526
=================

mongoengine/queryset/transform.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,24 @@ def update(_doc_cls=None, **update):
264264
op = operator_map.get(op, op)
265265

266266
match = None
267-
if parts[-1] in COMPARISON_OPERATORS:
268-
match = parts.pop()
269267

270-
# Allow to escape operator-like field name by __
271-
if len(parts) > 1 and parts[-1] == "":
272-
parts.pop()
268+
if len(parts) == 1:
269+
# typical update like set__field
270+
# but also allows to update a field named like a comparison operator
271+
# like set__type = "something" (without clashing with the 'type' operator)
272+
pass
273+
elif len(parts) > 1:
274+
# can be either an embedded field like set__foo__bar
275+
# or a comparison operator as in pull__foo__in
276+
if parts[-1] in COMPARISON_OPERATORS:
277+
match = parts.pop() # e.g. pop 'in' from pull__foo__in
278+
279+
# Allow to escape operator-like field name by __
280+
# e.g. in the case of an embedded foo.type field
281+
# Doc.objects().update(set__foo__type="bar")
282+
# see https://github.com/MongoEngine/mongoengine/pull/1351
283+
if parts[-1] == "":
284+
match = parts.pop() # e.g. pop last '__' from set__foo__type__
273285

274286
if _doc_cls:
275287
# Switch field names to proper names [set in Field(name='foo')]

tests/queryset/test_transform.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ class Doc(Document):
275275
assert Doc.objects(df__type=2).count() == 1 # str
276276
assert Doc.objects(df__type=16).count() == 1 # int
277277

278-
def test_last_field_name_like_operator(self):
278+
def test_embedded_field_name_like_operator(self):
279279
class EmbeddedItem(EmbeddedDocument):
280280
type = StringField()
281281
name = StringField()
@@ -295,6 +295,30 @@ class Doc(Document):
295295
assert 1 == Doc.objects(item__type__="sword").count()
296296
assert 0 == Doc.objects(item__type__="axe").count()
297297

298+
def test_regular_field_named_like_operator(self):
299+
class SimpleDoc(Document):
300+
size = StringField()
301+
type = StringField()
302+
303+
SimpleDoc.drop_collection()
304+
SimpleDoc(type="ok", size="ok").save()
305+
306+
qry = transform.query(SimpleDoc, type="testtype")
307+
assert qry == {"type": "testtype"}
308+
309+
assert SimpleDoc.objects(type="ok").count() == 1
310+
assert SimpleDoc.objects(size="ok").count() == 1
311+
312+
update = transform.update(SimpleDoc, set__type="testtype")
313+
assert update == {"$set": {"type": "testtype"}}
314+
315+
SimpleDoc.objects.update(set__type="testtype")
316+
SimpleDoc.objects.update(set__size="testsize")
317+
318+
s = SimpleDoc.objects.first()
319+
assert s.type == "testtype"
320+
assert s.size == "testsize"
321+
298322
def test_understandable_error_raised(self):
299323
class Event(Document):
300324
title = StringField()

0 commit comments

Comments
 (0)