with self.assertRaisesRegex(NotImplementedError, "BAR"):
B().foo
+ def test_gh146587(self):
+ # See https://github.com/python/cpython/issues/146587
+
+ class A:
+ def __radd__(self, other): ...
+
+ class B(tuple): ...
+
+ self.assertIsNone(() + A())
+ self.assertIsNone(B() + A())
+
+ from typing import NamedTuple
+
+ class T(NamedTuple):
+ x: int
+
+ class A:
+ def __init__(self, *args):
+ self.lst = list(args)
+ def __radd__(self, other):
+ return A(*self.lst, other)
+
+ self.assertEqual(((1,)+A()).lst, [(1,)])
+ self.assertEqual((T(x=1)+A()).lst, [T(x=1)])
+
class DictProxyTests(unittest.TestCase):
def setUp(self):
/* Stores the number of times where slotdefs has elements with same name.
This counter precalculated by _PyType_InitSlotDefs() when the main
interpreter starts. */
-static uint8_t slotdefs_name_counts[Py_ARRAY_LENGTH(slotdefs)];
+static uint8_t slotdefs_dups[Py_ARRAY_LENGTH(slotdefs)][1 + MAX_EQUIV];
/* Given a type pointer and an offset gotten from a slotdef entry, return a
pointer to the actual slot. This is not quite the same as simply adding
((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) {
void **tptr;
size_t index = (p - slotdefs);
- if (slotdefs_name_counts[index] == 1) {
- tptr = slotptr(type, p->offset);
+ if (slotdefs_dups[index][0] > 1) {
+ tptr = NULL;
+ for (size_t i = 1; i <= slotdefs_dups[index][0]; i++) {
+ pytype_slotdef *q = &slotdefs[slotdefs_dups[index][i]];
+ void **qptr = slotptr(type, q->offset);
+ if (qptr == NULL || *qptr == NULL)
+ continue;
+ if (tptr != NULL) {
+ tptr = NULL;
+ break;
+ }
+ tptr = qptr;
+ }
}
else {
- tptr = NULL;
+ tptr = slotptr(type, offset);
}
if (tptr == NULL || tptr == ptr)
Py_CLEAR(bytearray);
}
- memset(slotdefs_name_counts, 0, sizeof(slotdefs_name_counts));
+ memset(slotdefs_dups, -1, sizeof(slotdefs_dups));
Py_ssize_t pos = 0;
PyObject *key = NULL;
uint8_t n = data[0];
for (uint8_t i = 0; i < n; i++) {
uint8_t idx = data[i + 1];
- slotdefs_name_counts[idx] = n;
+ memcpy(&slotdefs_dups[idx], data, sizeof(uint8_t) * (n + 1));
}
}
Objects/typeobject.c - name_op -
Objects/typeobject.c - slotdefs -
# It initialized only once when main interpeter starts
-Objects/typeobject.c - slotdefs_name_counts -
+Objects/typeobject.c - slotdefs_dups -
Objects/unicodeobject.c - stripfuncnames -
Objects/unicodeobject.c - utf7_category -
Objects/unicodeobject.c unicode_decode_call_errorhandler_wchar argparse -