|
8 | 8 | from test.support.import_helper import import_fresh_module |
9 | 9 |
|
10 | 10 | import collections.abc |
11 | | -from collections import namedtuple, UserDict |
| 11 | +from collections import namedtuple, UserDict, OrderedDict |
12 | 12 | import copy |
13 | 13 | import _datetime |
14 | 14 | import gc |
@@ -1461,18 +1461,43 @@ def __eq__(self, other): |
1461 | 1461 | leaked = mp1 == Evil() |
1462 | 1462 | self.assertIs(type(leaked), dict) |
1463 | 1463 |
|
| 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 | + |
1464 | 1484 | def test_richcompare_evil(self): |
1465 | 1485 | # https://github.com/python/cpython/issues/152405 |
| 1486 | + key = "__mappingproxy_crash_key__" |
| 1487 | + |
1466 | 1488 | class Evil: |
1467 | 1489 | def __eq__(self, other): |
| 1490 | + other[key] = 1 |
1468 | 1491 | return other |
1469 | 1492 |
|
1470 | 1493 | # exposes the internals of `MappingProxyType` via richcompare: |
1471 | 1494 | leaked = vars(list) == Evil() |
1472 | 1495 | self.assertIs(type(leaked), dict) |
| 1496 | + self.assertIn(key, leaked) |
1473 | 1497 | name = "__mappingproxy_crash_probe__" |
1474 | 1498 | leaked[name] = lambda self: "probe" |
1475 | 1499 | self.assertIn(name, leaked) |
| 1500 | + self.assertNotHasAttr(list, key) |
1476 | 1501 | self.assertNotHasAttr(list, name) # it used to return `True` |
1477 | 1502 | del leaked[name] |
1478 | 1503 | self.assertNotIn(name, leaked) |
|
0 commit comments