Skip to content

Commit b3c26a7

Browse files
authored
PYTHON-1316 Remove eval, system_js, and SystemJS (#542)
1 parent 55eef0e commit b3c26a7

File tree

5 files changed

+23
-158
lines changed

5 files changed

+23
-158
lines changed

doc/api/pymongo/database.rst

-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,3 @@
2727
.. autoattribute:: read_preference
2828
.. autoattribute:: write_concern
2929
.. autoattribute:: read_concern
30-
31-
32-
.. autoclass:: pymongo.database.SystemJS
33-
:members:

doc/changelog.rst

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Breaking Changes in 4.0
1515
.......................
1616

1717
- Removed support for Python 2.7, 3.4, and 3.5. Python 3.6+ is now required.
18+
- Removed :meth:`~pymongo.database.Database.eval`,
19+
:data:`~pymongo.database.Database.system_js` and
20+
:class:`~pymongo.database.SystemJS`.
1821
- Removed :mod:`~pymongo.thread_util`.
1922

2023
Notable improvements

doc/migrate-to-pymongo4.rst

+20-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ PyMongo 4 Migration Guide
77

88
from pymongo import MongoClient, ReadPreference
99
client = MongoClient()
10-
collection = client.my_database.my_collection
10+
database = client.my_database
11+
collection = database.my_collection
1112

1213
PyMongo 4.0 brings a number of improvements as well as some backward breaking
1314
changes. This guide provides a roadmap for migrating an existing application
@@ -51,3 +52,21 @@ Warnings can also be changed to errors::
5152

5253
Removed features with no migration path
5354
---------------------------------------
55+
56+
Database.eval, Database.system_js, and SystemJS are removed
57+
...........................................................
58+
59+
Removed :meth:`~pymongo.database.Database.eval`,
60+
:data:`~pymongo.database.Database.system_js` and
61+
:class:`~pymongo.database.SystemJS`. The eval command was deprecated in
62+
MongoDB 3.0 and removed in MongoDB 4.2. There is no replacement for eval with
63+
MongoDB 4.2+.
64+
65+
However, on MongoDB <= 4.0, code like this::
66+
67+
>>> result = database.eval('function (x) {return x;}', 3)
68+
69+
can be changed to this::
70+
71+
>>> from bson.code import Code
72+
>>> result = database.command('eval', Code('function (x) {return x;}'), args=[3]).get('retval')

pymongo/database.py

-82
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,6 @@ def method_overwritten(instance, method):
145145
if method_overwritten(manipulator, "transform_outgoing"):
146146
self.__outgoing_manipulators.insert(0, manipulator)
147147

148-
@property
149-
def system_js(self):
150-
"""**DEPRECATED**: :class:`SystemJS` helper for this :class:`Database`.
151-
152-
See the documentation for :class:`SystemJS` for more details.
153-
"""
154-
return SystemJS(self)
155-
156148
@property
157149
def client(self):
158150
"""The client instance for this :class:`Database`."""
@@ -1547,77 +1539,3 @@ def dereference(self, dbref, session=None, **kwargs):
15471539
self.__name))
15481540
return self[dbref.collection].find_one(
15491541
{"_id": dbref.id}, session=session, **kwargs)
1550-
1551-
def eval(self, code, *args):
1552-
"""**DEPRECATED**: Evaluate a JavaScript expression in MongoDB.
1553-
1554-
:Parameters:
1555-
- `code`: string representation of JavaScript code to be
1556-
evaluated
1557-
- `args` (optional): additional positional arguments are
1558-
passed to the `code` being evaluated
1559-
1560-
.. warning:: the eval command is deprecated in MongoDB 3.0 and
1561-
will be removed in a future server version.
1562-
"""
1563-
warnings.warn("Database.eval() is deprecated",
1564-
DeprecationWarning, stacklevel=2)
1565-
1566-
if not isinstance(code, Code):
1567-
code = Code(code)
1568-
1569-
result = self.command("$eval", code, args=args)
1570-
return result.get("retval", None)
1571-
1572-
def __call__(self, *args, **kwargs):
1573-
"""This is only here so that some API misusages are easier to debug.
1574-
"""
1575-
raise TypeError("'Database' object is not callable. If you meant to "
1576-
"call the '%s' method on a '%s' object it is "
1577-
"failing because no such method exists." % (
1578-
self.__name, self.__client.__class__.__name__))
1579-
1580-
1581-
class SystemJS(object):
1582-
"""**DEPRECATED**: Helper class for dealing with stored JavaScript.
1583-
"""
1584-
1585-
def __init__(self, database):
1586-
"""**DEPRECATED**: Get a system js helper for the database `database`.
1587-
1588-
SystemJS will be removed in PyMongo 4.0.
1589-
"""
1590-
warnings.warn("SystemJS is deprecated",
1591-
DeprecationWarning, stacklevel=2)
1592-
1593-
if not database.write_concern.acknowledged:
1594-
database = database.client.get_database(
1595-
database.name, write_concern=DEFAULT_WRITE_CONCERN)
1596-
# can't just assign it since we've overridden __setattr__
1597-
object.__setattr__(self, "_db", database)
1598-
1599-
def __setattr__(self, name, code):
1600-
self._db.system.js.replace_one(
1601-
{"_id": name}, {"_id": name, "value": Code(code)}, True)
1602-
1603-
def __setitem__(self, name, code):
1604-
self.__setattr__(name, code)
1605-
1606-
def __delattr__(self, name):
1607-
self._db.system.js.delete_one({"_id": name})
1608-
1609-
def __delitem__(self, name):
1610-
self.__delattr__(name)
1611-
1612-
def __getattr__(self, name):
1613-
return lambda *args: self._db.eval(Code("function() { "
1614-
"return this[name].apply("
1615-
"this, arguments); }",
1616-
scope={'name': name}), *args)
1617-
1618-
def __getitem__(self, name):
1619-
return self.__getattr__(name)
1620-
1621-
def list(self):
1622-
"""Get a list of the names of the functions stored in this database."""
1623-
return [x["_id"] for x in self._db.system.js.find(projection=["_id"])]

test/test_database.py

-71
Original file line numberDiff line numberDiff line change
@@ -806,35 +806,6 @@ def test_deref_kwargs(self):
806806
db.dereference(DBRef("test", 4),
807807
projection={"_id": False}))
808808

809-
@client_context.require_no_auth
810-
@client_context.require_version_max(4, 1, 0)
811-
def test_eval(self):
812-
db = self.client.pymongo_test
813-
db.test.drop()
814-
815-
with ignore_deprecations():
816-
self.assertRaises(TypeError, db.eval, None)
817-
self.assertRaises(TypeError, db.eval, 5)
818-
self.assertRaises(TypeError, db.eval, [])
819-
820-
self.assertEqual(3, db.eval("function (x) {return x;}", 3))
821-
self.assertEqual(3, db.eval(u"function (x) {return x;}", 3))
822-
823-
self.assertEqual(None,
824-
db.eval("function (x) {db.test.save({y:x});}", 5))
825-
self.assertEqual(db.test.find_one()["y"], 5)
826-
827-
self.assertEqual(5, db.eval("function (x, y) {return x + y;}", 2, 3))
828-
self.assertEqual(5, db.eval("function () {return 5;}"))
829-
self.assertEqual(5, db.eval("2 + 3;"))
830-
831-
self.assertEqual(5, db.eval(Code("2 + 3;")))
832-
self.assertRaises(OperationFailure, db.eval, Code("return i;"))
833-
self.assertEqual(2, db.eval(Code("return i;", {"i": 2})))
834-
self.assertEqual(5, db.eval(Code("i + 3;", {"i": 2})))
835-
836-
self.assertRaises(OperationFailure, db.eval, "5 ++ 5;")
837-
838809
# TODO some of these tests belong in the collection level testing.
839810
def test_insert_find_one(self):
840811
db = self.client.pymongo_test
@@ -910,48 +881,6 @@ def test_delete(self):
910881
db.test.delete_many({})
911882
self.assertFalse(db.test.find_one())
912883

913-
@client_context.require_no_auth
914-
@client_context.require_version_max(4, 1, 0)
915-
def test_system_js(self):
916-
db = self.client.pymongo_test
917-
db.system.js.delete_many({})
918-
919-
self.assertEqual(0, db.system.js.count_documents({}))
920-
db.system_js.add = "function(a, b) { return a + b; }"
921-
self.assertEqual('add', db.system.js.find_one()['_id'])
922-
self.assertEqual(1, db.system.js.count_documents({}))
923-
self.assertEqual(6, db.system_js.add(1, 5))
924-
del db.system_js.add
925-
self.assertEqual(0, db.system.js.count_documents({}))
926-
927-
db.system_js['add'] = "function(a, b) { return a + b; }"
928-
self.assertEqual('add', db.system.js.find_one()['_id'])
929-
self.assertEqual(1, db.system.js.count_documents({}))
930-
self.assertEqual(6, db.system_js['add'](1, 5))
931-
del db.system_js['add']
932-
self.assertEqual(0, db.system.js.count_documents({}))
933-
self.assertRaises(OperationFailure, db.system_js.add, 1, 5)
934-
935-
# TODO right now CodeWScope doesn't work w/ system js
936-
# db.system_js.scope = Code("return hello;", {"hello": 8})
937-
# self.assertEqual(8, db.system_js.scope())
938-
939-
self.assertRaises(OperationFailure, db.system_js.non_existant)
940-
941-
def test_system_js_list(self):
942-
db = self.client.pymongo_test
943-
db.system.js.delete_many({})
944-
self.assertEqual([], db.system_js.list())
945-
946-
db.system_js.foo = "function() { return 'blah'; }"
947-
self.assertEqual(["foo"], db.system_js.list())
948-
949-
db.system_js.bar = "function() { return 'baz'; }"
950-
self.assertEqual(set(["foo", "bar"]), set(db.system_js.list()))
951-
952-
del db.system_js.foo
953-
self.assertEqual(["bar"], db.system_js.list())
954-
955884
def test_command_response_without_ok(self):
956885
# Sometimes (SERVER-10891) the server's response to a badly-formatted
957886
# command document will have no 'ok' field. We should raise

0 commit comments

Comments
 (0)