Skip to content

Commit aa84617

Browse files
committed
Fix CI
1 parent fb78a8a commit aa84617

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

Lib/test/test_types.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from test.support.import_helper import import_fresh_module
99

1010
import collections.abc
11-
from collections import namedtuple, UserDict
11+
from collections import namedtuple, UserDict, OrderedDict
1212
import copy
1313
import _datetime
1414
import gc
@@ -1461,18 +1461,43 @@ def __eq__(self, other):
14611461
leaked = mp1 == Evil()
14621462
self.assertIs(type(leaked), dict)
14631463

1464+
def test_richcompare_odict(self):
1465+
od1 = OrderedDict(x=1, y=2)
1466+
od1_2 = OrderedDict(x=1, y=2)
1467+
od2 = OrderedDict(y=2, x=1)
1468+
self.assertNotEqual(od1, od2)
1469+
self.assertEqual(od1, od1_2)
1470+
1471+
self.assertEqual(self.mappingproxy(od1), self.mappingproxy(od1_2))
1472+
self.assertEqual(self.mappingproxy(od1), od1_2)
1473+
self.assertNotEqual(self.mappingproxy(od1), self.mappingproxy(od2))
1474+
self.assertNotEqual(self.mappingproxy(od1), od2)
1475+
self.assertEqual(
1476+
self.mappingproxy(od1),
1477+
self.mappingproxy({'x': 1, 'y': 2}),
1478+
)
1479+
self.assertEqual(
1480+
self.mappingproxy(od1),
1481+
{'x': 1, 'y': 2},
1482+
)
1483+
14641484
def test_richcompare_evil(self):
14651485
# https://github.com/python/cpython/issues/152405
1486+
key = "__mappingproxy_crash_key__"
1487+
14661488
class Evil:
14671489
def __eq__(self, other):
1490+
other[key] = 1
14681491
return other
14691492

14701493
# exposes the internals of `MappingProxyType` via richcompare:
14711494
leaked = vars(list) == Evil()
14721495
self.assertIs(type(leaked), dict)
1496+
self.assertIn(key, leaked)
14731497
name = "__mappingproxy_crash_probe__"
14741498
leaked[name] = lambda self: "probe"
14751499
self.assertIn(name, leaked)
1500+
self.assertNotHasAttr(list, key)
14761501
self.assertNotHasAttr(list, name) # it used to return `True`
14771502
del leaked[name]
14781503
self.assertNotIn(name, leaked)

Objects/descrobject.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,8 +1234,13 @@ mappingproxy_richcompare(PyObject *self, PyObject *w, int op)
12341234
{
12351235
if (op == Py_EQ || op == Py_NE) {
12361236
mappingproxyobject *v = (mappingproxyobject *)self;
1237-
// Common path optimization:
1238-
if (PyDict_CheckExact(w)) {
1237+
// Common path optimizations, where we can expose the real mapping:
1238+
if (
1239+
PyAnyDict_CheckExact(w)
1240+
|| PyODict_CheckExact(w)
1241+
|| Py_TYPE(w) == &PyDictProxy_Type
1242+
) {
1243+
fprintf(stderr, "optimized %s richcompare\n", Py_TYPE(w)->tp_name);
12391244
return PyObject_RichCompare(v->mapping, w, op);
12401245
}
12411246
// We can't expose the `v->mapping` itself, so we create a dict copy:

0 commit comments

Comments
 (0)