Skip to content

Commit 829b303

Browse files
committed
remove long-warned deprecations (in prevision of 1.0)
1 parent 3305136 commit 829b303

File tree

10 files changed

+55
-76
lines changed

10 files changed

+55
-76
lines changed

docs/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ Changelog
77
Development
88
===========
99
- (Fill this out as you fix issues and develop your features).
10+
- 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
11+
- Further to the deprecation warning, remove `full_response` from `QuerySet.modify` as it wasn't supported with Pymongo 3+
12+
- Fixed stacklevel of many warnings (to point places emitting the warning more accurately)
1013

1114
Changes in 0.29.0
1215
=================

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
@@ -204,6 +204,7 @@ def _get_connection_settings(
204204
"older drivers in those languages. This will be changed to "
205205
"'unspecified' in a future release.",
206206
DeprecationWarning,
207+
stacklevel=3,
207208
)
208209
kwargs["uuidRepresentation"] = "pythonLegacy"
209210

mongoengine/queryset/base.py

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,6 @@ def update_one(
671671
def modify(
672672
self,
673673
upsert=False,
674-
full_response=False,
675674
remove=False,
676675
new=False,
677676
array_filters=None,
@@ -683,15 +682,7 @@ def modify(
683682
parameter. If no documents match the query and `upsert` is false,
684683
returns ``None``. If upserting and `new` is false, returns ``None``.
685684
686-
If the full_response parameter is ``True``, the return value will be
687-
the entire response object from the server, including the 'ok' and
688-
'lastErrorObject' fields, rather than just the modified document.
689-
This is useful mainly because the 'lastErrorObject' document holds
690-
information about the command's execution.
691-
692685
:param upsert: insert if document doesn't exist (default ``False``)
693-
:param full_response: return the entire response object from the
694-
server (default ``False``, not available for PyMongo 3+)
695686
:param remove: remove rather than updating (default ``False``)
696687
:param new: return updated rather than original document
697688
(default ``False``)
@@ -715,9 +706,6 @@ def modify(
715706
sort = queryset._ordering
716707

717708
try:
718-
if full_response:
719-
msg = "With PyMongo 3+, it is not possible anymore to get the full response."
720-
warnings.warn(msg, DeprecationWarning)
721709
if remove:
722710
result = queryset._collection.find_one_and_delete(
723711
query, sort=sort, **self._cursor_args
@@ -741,12 +729,8 @@ def modify(
741729
except pymongo.errors.OperationFailure as err:
742730
raise OperationError("Update failed (%s)" % err)
743731

744-
if full_response:
745-
if result["value"] is not None:
746-
result["value"] = self._document._from_son(result["value"])
747-
else:
748-
if result is not None:
749-
result = self._document._from_son(result)
732+
if result is not None:
733+
result = self._document._from_son(result)
750734

751735
return result
752736

@@ -1215,7 +1199,7 @@ def snapshot(self, enabled):
12151199
:param enabled: whether or not snapshot mode is enabled
12161200
"""
12171201
msg = "snapshot is deprecated as it has no impact when using PyMongo 3+."
1218-
warnings.warn(msg, DeprecationWarning)
1202+
warnings.warn(msg, DeprecationWarning, stacklevel=2)
12191203
queryset = self.clone()
12201204
queryset._snapshot = enabled
12211205
return queryset
@@ -1324,6 +1308,7 @@ def to_json(self, *args, **kwargs):
13241308
"representation to use. This will be changed to "
13251309
"uuid_representation=UNSPECIFIED in a future release.",
13261310
DeprecationWarning,
1311+
stacklevel=2,
13271312
)
13281313
kwargs["json_options"] = LEGACY_JSON_OPTIONS
13291314
return json_util.dumps(self.as_pymongo(), *args, **kwargs)
@@ -1333,24 +1318,18 @@ def from_json(self, json_data):
13331318
son_data = json_util.loads(json_data)
13341319
return [self._document._from_son(data) for data in son_data]
13351320

1336-
def aggregate(self, pipeline, *suppl_pipeline, **kwargs):
1321+
def aggregate(self, pipeline, **kwargs):
13371322
"""Perform an aggregate function based on your queryset params
13381323
13391324
:param pipeline: list of aggregation commands,
13401325
see: https://www.mongodb.com/docs/manual/core/aggregation-pipeline/
1341-
:param suppl_pipeline: unpacked list of pipeline (added to support deprecation of the old interface)
1342-
parameter will be removed shortly
13431326
:param kwargs: (optional) kwargs dictionary to be passed to pymongo's aggregate call
13441327
See https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.aggregate
13451328
"""
1346-
using_deprecated_interface = isinstance(pipeline, dict) or bool(suppl_pipeline)
1347-
user_pipeline = [pipeline] if isinstance(pipeline, dict) else list(pipeline)
1348-
1349-
if using_deprecated_interface:
1350-
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"
1351-
warnings.warn(msg, DeprecationWarning)
1352-
1353-
user_pipeline += suppl_pipeline
1329+
if not isinstance(pipeline, (tuple, list)):
1330+
raise TypeError(
1331+
f"Starting from 1.0 release pipeline must be a list/tuple, received: {type(pipeline)}"
1332+
)
13541333

13551334
initial_pipeline = []
13561335
if self._none or self._empty:
@@ -1373,7 +1352,7 @@ def aggregate(self, pipeline, *suppl_pipeline, **kwargs):
13731352
if self._skip is not None:
13741353
initial_pipeline.append({"$skip": self._skip})
13751354

1376-
final_pipeline = initial_pipeline + user_pipeline
1355+
final_pipeline = initial_pipeline + pipeline
13771356

13781357
collection = self._collection
13791358
if self._read_preference is not None or self._read_concern is not None:
@@ -1679,7 +1658,7 @@ def _cursor_args(self):
16791658
# TODO: evaluate similar possibilities using modifiers
16801659
if self._snapshot:
16811660
msg = "The snapshot option is not anymore available with PyMongo 3+"
1682-
warnings.warn(msg, DeprecationWarning)
1661+
warnings.warn(msg, DeprecationWarning, stacklevel=3)
16831662

16841663
cursor_args = {}
16851664
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 *
@@ -215,7 +215,7 @@ class Person(Document):
215215

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

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

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

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

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

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

251244
def test_queryset_aggregation_geonear_aggregation_on_pointfield(self):
252245
"""test ensures that $geonear can be used as a 1-stage pipeline and that
@@ -271,7 +264,7 @@ class Aggr(Document):
271264
}
272265
}
273266
]
274-
assert list(Aggr.objects.aggregate(*pipeline)) == [
267+
assert list(Aggr.objects.aggregate(pipeline)) == [
275268
{"_id": agg1.id, "c": 0.0, "name": "X"},
276269
{"_id": agg2.id, "c": 0.0, "name": "Y"},
277270
]

tests/test_connection.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,11 @@ def test_multiple_connection_settings(self):
648648
mongo_connections["t1"].server_info()
649649
mongo_connections["t2"].server_info()
650650
assert mongo_connections["t1"].address[0] == "localhost"
651-
assert mongo_connections["t2"].address[0] == "127.0.0.1"
651+
652+
assert mongo_connections["t2"].address[0] in (
653+
"localhost",
654+
"127.0.0.1",
655+
) # depends on db setting
652656

653657
def test_connect_2_databases_uses_same_client_if_only_dbname_differs(self):
654658
c1 = connect(alias="testdb1", db="testdb1")

tests/test_context_managers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class TestableThread(Thread):
2828
REF: https://gist.github.com/sbrugman/59b3535ebcd5aa0e2598293cfa58b6ab
2929
"""
3030

31+
__test__ = False
32+
3133
def __init__(self, *args, **kwargs):
3234
super().__init__(*args, **kwargs)
3335
self.exc = None

0 commit comments

Comments
 (0)