Skip to content

Commit fd9955c

Browse files
authored
Merge pull request #2837 from bagerard/remove_deprecated_warnings
remove long-warned deprecations (in prevision of 1.0)
2 parents 0dcb09f + 9b7d774 commit fd9955c

File tree

8 files changed

+48
-75
lines changed

8 files changed

+48
-75
lines changed

docs/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ Development
1212
- make sure to read https://www.mongodb.com/docs/manual/core/transactions-in-applications/#callback-api-vs-core-api
1313
- run_in_transaction context manager relies on Pymongo coreAPI, it will retry automatically in case of `UnknownTransactionCommitResult` but not `TransientTransactionError` exceptions
1414
- Using .count() in a transaction will always use Collection.count_document (as estimated_document_count is not supported in transactions)
15+
- Further to the deprecation warning, remove ability to use an unpacked list to `Queryset.aggregate(*pipeline)`, a plain list must be provided instead `Queryset.aggregate(pipeline)`, as it's closer to pymongo interface
16+
- Further to the deprecation warning, remove `full_response` from `QuerySet.modify` as it wasn't supported with Pymongo 3+
17+
- Fixed stacklevel of many warnings (to point places emitting the warning more accurately)
1518

1619
Changes in 0.29.0
1720
=================

mongoengine/base/document.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ def to_json(self, *args, **kwargs):
455455
"representation to use. This will be changed to "
456456
"uuid_representation=UNSPECIFIED in a future release.",
457457
DeprecationWarning,
458+
stacklevel=2,
458459
)
459460
kwargs["json_options"] = LEGACY_JSON_OPTIONS
460461
return json_util.dumps(self.to_mongo(use_db_field), *args, **kwargs)
@@ -486,6 +487,7 @@ def from_json(cls, json_data, created=False, **kwargs):
486487
"representation to use. This will be changed to "
487488
"uuid_representation=UNSPECIFIED in a future release.",
488489
DeprecationWarning,
490+
stacklevel=2,
489491
)
490492
kwargs["json_options"] = LEGACY_JSON_OPTIONS
491493
return cls._from_son(json_util.loads(json_data, **kwargs), created=created)

mongoengine/base/metaclasses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def __new__(mcs, name, bases, attrs):
307307
and not parent_doc_cls._meta.get("abstract", True)
308308
):
309309
msg = "Trying to set a collection on a subclass (%s)" % name
310-
warnings.warn(msg, SyntaxWarning)
310+
warnings.warn(msg, SyntaxWarning, stacklevel=2)
311311
del attrs["_meta"]["collection"]
312312

313313
# Ensure abstract documents have abstract bases

mongoengine/connection.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ def _get_connection_settings(
211211
"older drivers in those languages. This will be changed to "
212212
"'unspecified' in a future release.",
213213
DeprecationWarning,
214+
stacklevel=3,
214215
)
215216
kwargs["uuidRepresentation"] = "pythonLegacy"
216217

mongoengine/queryset/base.py

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,6 @@ def update_one(
675675
def modify(
676676
self,
677677
upsert=False,
678-
full_response=False,
679678
remove=False,
680679
new=False,
681680
array_filters=None,
@@ -687,15 +686,7 @@ def modify(
687686
parameter. If no documents match the query and `upsert` is false,
688687
returns ``None``. If upserting and `new` is false, returns ``None``.
689688
690-
If the full_response parameter is ``True``, the return value will be
691-
the entire response object from the server, including the 'ok' and
692-
'lastErrorObject' fields, rather than just the modified document.
693-
This is useful mainly because the 'lastErrorObject' document holds
694-
information about the command's execution.
695-
696689
:param upsert: insert if document doesn't exist (default ``False``)
697-
:param full_response: return the entire response object from the
698-
server (default ``False``, not available for PyMongo 3+)
699690
:param remove: remove rather than updating (default ``False``)
700691
:param new: return updated rather than original document
701692
(default ``False``)
@@ -719,9 +710,6 @@ def modify(
719710
sort = queryset._ordering
720711

721712
try:
722-
if full_response:
723-
msg = "With PyMongo 3+, it is not possible anymore to get the full response."
724-
warnings.warn(msg, DeprecationWarning)
725713
if remove:
726714
result = queryset._collection.find_one_and_delete(
727715
query, sort=sort, session=_get_session(), **self._cursor_args
@@ -746,12 +734,8 @@ def modify(
746734
except pymongo.errors.OperationFailure as err:
747735
raise OperationError("Update failed (%s)" % err)
748736

749-
if full_response:
750-
if result["value"] is not None:
751-
result["value"] = self._document._from_son(result["value"])
752-
else:
753-
if result is not None:
754-
result = self._document._from_son(result)
737+
if result is not None:
738+
result = self._document._from_son(result)
755739

756740
return result
757741

@@ -1222,7 +1206,7 @@ def snapshot(self, enabled):
12221206
:param enabled: whether or not snapshot mode is enabled
12231207
"""
12241208
msg = "snapshot is deprecated as it has no impact when using PyMongo 3+."
1225-
warnings.warn(msg, DeprecationWarning)
1209+
warnings.warn(msg, DeprecationWarning, stacklevel=2)
12261210
queryset = self.clone()
12271211
queryset._snapshot = enabled
12281212
return queryset
@@ -1331,6 +1315,7 @@ def to_json(self, *args, **kwargs):
13311315
"representation to use. This will be changed to "
13321316
"uuid_representation=UNSPECIFIED in a future release.",
13331317
DeprecationWarning,
1318+
stacklevel=2,
13341319
)
13351320
kwargs["json_options"] = LEGACY_JSON_OPTIONS
13361321
return json_util.dumps(self.as_pymongo(), *args, **kwargs)
@@ -1340,24 +1325,18 @@ def from_json(self, json_data):
13401325
son_data = json_util.loads(json_data)
13411326
return [self._document._from_son(data) for data in son_data]
13421327

1343-
def aggregate(self, pipeline, *suppl_pipeline, **kwargs):
1328+
def aggregate(self, pipeline, **kwargs):
13441329
"""Perform an aggregate function based on your queryset params
13451330
13461331
:param pipeline: list of aggregation commands,
13471332
see: https://www.mongodb.com/docs/manual/core/aggregation-pipeline/
1348-
:param suppl_pipeline: unpacked list of pipeline (added to support deprecation of the old interface)
1349-
parameter will be removed shortly
13501333
:param kwargs: (optional) kwargs dictionary to be passed to pymongo's aggregate call
13511334
See https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.aggregate
13521335
"""
1353-
using_deprecated_interface = isinstance(pipeline, dict) or bool(suppl_pipeline)
1354-
user_pipeline = [pipeline] if isinstance(pipeline, dict) else list(pipeline)
1355-
1356-
if using_deprecated_interface:
1357-
msg = "Calling .aggregate() with un unpacked list (*pipeline) is deprecated, it will soon change and will expect a list (similar to pymongo.Collection.aggregate interface), see documentation"
1358-
warnings.warn(msg, DeprecationWarning)
1359-
1360-
user_pipeline += suppl_pipeline
1336+
if not isinstance(pipeline, (tuple, list)):
1337+
raise TypeError(
1338+
f"Starting from 1.0 release pipeline must be a list/tuple, received: {type(pipeline)}"
1339+
)
13611340

13621341
initial_pipeline = []
13631342
if self._none or self._empty:
@@ -1380,7 +1359,7 @@ def aggregate(self, pipeline, *suppl_pipeline, **kwargs):
13801359
if self._skip is not None:
13811360
initial_pipeline.append({"$skip": self._skip})
13821361

1383-
final_pipeline = initial_pipeline + user_pipeline
1362+
final_pipeline = initial_pipeline + pipeline
13841363

13851364
collection = self._collection
13861365
if self._read_preference is not None or self._read_concern is not None:
@@ -1693,7 +1672,7 @@ def _cursor_args(self):
16931672
# TODO: evaluate similar possibilities using modifiers
16941673
if self._snapshot:
16951674
msg = "The snapshot option is not anymore available with PyMongo 3+"
1696-
warnings.warn(msg, DeprecationWarning)
1675+
warnings.warn(msg, DeprecationWarning, stacklevel=3)
16971676

16981677
cursor_args = {}
16991678
if not self._timeout:

tests/queryset/test_modify.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import unittest
22

3-
import pytest
4-
53
from mongoengine import (
64
Document,
75
IntField,
@@ -32,13 +30,6 @@ def test_modify(self):
3230
assert old_doc.to_json() == doc.to_json()
3331
self._assert_db_equal([{"_id": 0, "value": 0}, {"_id": 1, "value": -1}])
3432

35-
def test_modify_full_response_raise_value_error_for_recent_mongo(self):
36-
Doc(id=0, value=0).save()
37-
Doc(id=1, value=1).save()
38-
39-
with pytest.raises(ValueError):
40-
Doc.objects(id=1).modify(set__value=-1, full_response=True)
41-
4233
def test_modify_with_new(self):
4334
Doc(id=0, value=0).save()
4435
doc = Doc(id=1, value=1).save()

tests/queryset/test_queryset.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,7 @@ class A(Document):
474474

475475
A.drop_collection()
476476

477-
for i in range(100):
478-
A.objects.create(s=str(i))
477+
A.objects.insert([A(s=str(i)) for i in range(100)], load_bulk=True)
479478

480479
# test iterating over the result set
481480
cnt = 0
@@ -1283,8 +1282,7 @@ def __repr__(self):
12831282

12841283
Doc.drop_collection()
12851284

1286-
for i in range(1000):
1287-
Doc(number=i).save()
1285+
Doc.objects.insert([Doc(number=i) for i in range(1000)], load_bulk=True)
12881286

12891287
docs = Doc.objects.order_by("number")
12901288

@@ -5438,8 +5436,9 @@ class Person(Document):
54385436
name = StringField()
54395437

54405438
Person.drop_collection()
5441-
for i in range(100):
5442-
Person(name="No: %s" % i).save()
5439+
5440+
persons = [Person(name="No: %s" % i) for i in range(100)]
5441+
Person.objects.insert(persons, load_bulk=True)
54435442

54445443
with query_counter() as q:
54455444
assert q == 0
@@ -5469,8 +5468,9 @@ class Person(Document):
54695468
name = StringField()
54705469

54715470
Person.drop_collection()
5472-
for i in range(100):
5473-
Person(name="No: %s" % i).save()
5471+
5472+
persons = [Person(name="No: %s" % i) for i in range(100)]
5473+
Person.objects.insert(persons, load_bulk=True)
54745474

54755475
with query_counter() as q:
54765476
assert q == 0
@@ -5537,17 +5537,20 @@ def __unicode__(self):
55375537
assert 1 == len(users._result_cache)
55385538

55395539
def test_no_cache(self):
5540-
"""Ensure you can add meta data to file"""
5540+
"""Ensure you can add metadata to file"""
55415541

55425542
class Noddy(Document):
55435543
fields = DictField()
55445544

55455545
Noddy.drop_collection()
5546+
5547+
noddies = []
55465548
for i in range(100):
55475549
noddy = Noddy()
55485550
for j in range(20):
55495551
noddy.fields["key" + str(j)] = "value " + str(j)
5550-
noddy.save()
5552+
noddies.append(noddy)
5553+
Noddy.objects.insert(noddies, load_bulk=True)
55515554

55525555
docs = Noddy.objects.no_cache()
55535556

@@ -5766,8 +5769,9 @@ class Person(Document):
57665769
name = StringField()
57675770

57685771
Person.drop_collection()
5769-
for i in range(100):
5770-
Person(name="No: %s" % i).save()
5772+
5773+
persons = [Person(name="No: %s" % i) for i in range(100)]
5774+
Person.objects.insert(persons, load_bulk=True)
57715775

57725776
with query_counter() as q:
57735777
if Person.objects:

tests/queryset/test_queryset_aggregation.py

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
2-
import warnings
32

3+
import pytest
44
from pymongo.read_preferences import ReadPreference
55

66
from mongoengine import *
@@ -216,7 +216,7 @@ class Person(Document):
216216

217217
assert list(data) == [{"_id": p3.pk, "name": "SANDRA MARA"}]
218218

219-
def test_queryset_aggregation_deprecated_interface(self):
219+
def test_queryset_aggregation_old_interface_not_working(self):
220220
class Person(Document):
221221
name = StringField()
222222

@@ -227,27 +227,20 @@ class Person(Document):
227227
p3 = Person(name="Sandra Mara")
228228
Person.objects.insert([p1, p2, p3])
229229

230-
pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}]
231-
232-
# Make sure a warning is emitted
233-
with warnings.catch_warnings():
234-
warnings.simplefilter("error", DeprecationWarning)
235-
with self.assertRaises(DeprecationWarning):
236-
Person.objects.order_by("name").limit(2).aggregate(*pipeline)
230+
_1_step_pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}]
237231

238-
# Make sure old interface works as expected with a 1-step pipeline
239-
data = Person.objects.order_by("name").limit(2).aggregate(*pipeline)
232+
# Make sure old interface raises an error as we changed it >= 1.0
233+
with pytest.raises(TypeError, match="pipeline must be a list/tuple"):
234+
Person.objects.order_by("name").limit(2).aggregate(*_1_step_pipeline)
240235

241-
assert list(data) == [
242-
{"_id": p1.pk, "name": "ISABELLA LUANNA"},
243-
{"_id": p3.pk, "name": "SANDRA MARA"},
236+
_2_step_pipeline = [
237+
{"$project": {"name": {"$toUpper": "$name"}}},
238+
{"$limit": 1},
244239
]
245-
246-
# Make sure old interface works as expected with a 2-steps pipeline
247-
pipeline = [{"$project": {"name": {"$toUpper": "$name"}}}, {"$limit": 1}]
248-
data = Person.objects.order_by("name").limit(2).aggregate(*pipeline)
249-
250-
assert list(data) == [{"_id": p1.pk, "name": "ISABELLA LUANNA"}]
240+
with pytest.raises(
241+
TypeError, match="takes 2 positional arguments but 3 were given"
242+
):
243+
Person.objects.order_by("name").limit(2).aggregate(*_2_step_pipeline)
251244

252245
def test_queryset_aggregation_geonear_aggregation_on_pointfield(self):
253246
"""test ensures that $geonear can be used as a 1-stage pipeline and that
@@ -272,7 +265,7 @@ class Aggr(Document):
272265
}
273266
}
274267
]
275-
assert list(Aggr.objects.aggregate(*pipeline)) == [
268+
assert list(Aggr.objects.aggregate(pipeline)) == [
276269
{"_id": agg1.id, "c": 0.0, "name": "X"},
277270
{"_id": agg2.id, "c": 0.0, "name": "Y"},
278271
]

0 commit comments

Comments
 (0)