aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Objects
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-08-17 21:51:59 +0300
committershadchin <shadchin@yandex-team.com>2024-08-17 22:04:51 +0300
commitee9edbd8878888bafcd0eeb3b528f3ec4311560b (patch)
treed54d8138e50a446904f10a2092719be86af011b7 /contrib/tools/python3/Objects
parent72cbe4bad58add0912623ba51351ff1db8587249 (diff)
downloadydb-ee9edbd8878888bafcd0eeb3b528f3ec4311560b.tar.gz
Update Python 3 to 3.12.5
https://docs.python.org/release/3.12.5/whatsnew/changelog.html#python-3-12-5-final de86cdeacd3a8653b9ec36e87975886fafcf6dc2
Diffstat (limited to 'contrib/tools/python3/Objects')
-rw-r--r--contrib/tools/python3/Objects/clinic/floatobject.c.h6
-rw-r--r--contrib/tools/python3/Objects/descrobject.c19
-rw-r--r--contrib/tools/python3/Objects/dictobject.c21
-rw-r--r--contrib/tools/python3/Objects/exceptions.c2
-rw-r--r--contrib/tools/python3/Objects/floatobject.c10
-rw-r--r--contrib/tools/python3/Objects/genericaliasobject.c4
-rw-r--r--contrib/tools/python3/Objects/genobject.c6
-rw-r--r--contrib/tools/python3/Objects/listobject.c54
-rw-r--r--contrib/tools/python3/Objects/longobject.c70
-rw-r--r--contrib/tools/python3/Objects/memoryobject.c2
-rw-r--r--contrib/tools/python3/Objects/tupleobject.c2
-rw-r--r--contrib/tools/python3/Objects/typeobject.c103
12 files changed, 231 insertions, 68 deletions
diff --git a/contrib/tools/python3/Objects/clinic/floatobject.c.h b/contrib/tools/python3/Objects/clinic/floatobject.c.h
index a99fd74e4b..ed166538af 100644
--- a/contrib/tools/python3/Objects/clinic/floatobject.c.h
+++ b/contrib/tools/python3/Objects/clinic/floatobject.c.h
@@ -201,7 +201,7 @@ PyDoc_STRVAR(float_new__doc__,
"float(x=0, /)\n"
"--\n"
"\n"
-"Convert a string or number to a floating point number, if possible.");
+"Convert a string or number to a floating-point number, if possible.");
static PyObject *
float_new_impl(PyTypeObject *type, PyObject *x);
@@ -260,7 +260,7 @@ PyDoc_STRVAR(float___getformat____doc__,
"It exists mainly to be used in Python\'s test suite.\n"
"\n"
"This function returns whichever of \'unknown\', \'IEEE, big-endian\' or \'IEEE,\n"
-"little-endian\' best describes the format of floating point numbers used by the\n"
+"little-endian\' best describes the format of floating-point numbers used by the\n"
"C type named by typestr.");
#define FLOAT___GETFORMAT___METHODDEF \
@@ -325,4 +325,4 @@ float___format__(PyObject *self, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=ea329577074911b9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=e6e3f5f833b37eba input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/Objects/descrobject.c b/contrib/tools/python3/Objects/descrobject.c
index 55c0491cfd..7a3a1f0640 100644
--- a/contrib/tools/python3/Objects/descrobject.c
+++ b/contrib/tools/python3/Objects/descrobject.c
@@ -1788,22 +1788,9 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
/* if no docstring given and the getter has one, use that one */
else if (fget != NULL) {
int rc = _PyObject_LookupAttr(fget, &_Py_ID(__doc__), &prop_doc);
- if (rc <= 0) {
+ if (rc < 0) {
return rc;
}
- if (!Py_IS_TYPE(self, &PyProperty_Type) &&
- prop_doc != NULL && prop_doc != Py_None) {
- // This oddity preserves the long existing behavior of surfacing
- // an AttributeError when using a dict-less (__slots__) property
- // subclass as a decorator on a getter method with a docstring.
- // See PropertySubclassTest.test_slots_docstring_copy_exception.
- int err = PyObject_SetAttr(
- (PyObject *)self, &_Py_ID(__doc__), prop_doc);
- if (err < 0) {
- Py_DECREF(prop_doc); // release our new reference.
- return -1;
- }
- }
if (prop_doc == Py_None) {
prop_doc = NULL;
Py_DECREF(Py_None);
@@ -1831,7 +1818,9 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
Py_DECREF(prop_doc);
if (err < 0) {
assert(PyErr_Occurred());
- if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (!self->getter_doc &&
+ PyErr_ExceptionMatches(PyExc_AttributeError))
+ {
PyErr_Clear();
// https://github.com/python/cpython/issues/98963#issuecomment-1574413319
// Python silently dropped this doc assignment through 3.11.
diff --git a/contrib/tools/python3/Objects/dictobject.c b/contrib/tools/python3/Objects/dictobject.c
index 254cd9ad2f..a99f32a9c8 100644
--- a/contrib/tools/python3/Objects/dictobject.c
+++ b/contrib/tools/python3/Objects/dictobject.c
@@ -1251,10 +1251,6 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
MAINTAIN_TRACKING(mp, key, value);
if (ix == DKIX_EMPTY) {
- uint64_t new_version = _PyDict_NotifyEvent(
- interp, PyDict_EVENT_ADDED, mp, key, value);
- /* Insert into new slot. */
- mp->ma_keys->dk_version = 0;
assert(old_value == NULL);
if (mp->ma_keys->dk_usable <= 0) {
/* Need to resize. */
@@ -1262,6 +1258,11 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
goto Fail;
}
+ uint64_t new_version = _PyDict_NotifyEvent(
+ interp, PyDict_EVENT_ADDED, mp, key, value);
+ /* Insert into new slot. */
+ mp->ma_keys->dk_version = 0;
+
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
@@ -1335,9 +1336,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
{
assert(mp->ma_keys == Py_EMPTY_KEYS);
- uint64_t new_version = _PyDict_NotifyEvent(
- interp, PyDict_EVENT_ADDED, mp, key, value);
-
int unicode = PyUnicode_CheckExact(key);
PyDictKeysObject *newkeys = new_keys_object(
interp, PyDict_LOG_MINSIZE, unicode);
@@ -1346,6 +1344,9 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
Py_DECREF(value);
return -1;
}
+ uint64_t new_version = _PyDict_NotifyEvent(
+ interp, PyDict_EVENT_ADDED, mp, key, value);
+
/* We don't decref Py_EMPTY_KEYS here because it is immortal. */
mp->ma_keys = newkeys;
mp->ma_values = NULL;
@@ -3324,15 +3325,15 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
return NULL;
if (ix == DKIX_EMPTY) {
- uint64_t new_version = _PyDict_NotifyEvent(
- interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
- mp->ma_keys->dk_version = 0;
value = defaultobj;
if (mp->ma_keys->dk_usable <= 0) {
if (insertion_resize(interp, mp, 1) < 0) {
return NULL;
}
}
+ uint64_t new_version = _PyDict_NotifyEvent(
+ interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
+ mp->ma_keys->dk_version = 0;
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
if (DK_IS_UNICODE(mp->ma_keys)) {
diff --git a/contrib/tools/python3/Objects/exceptions.c b/contrib/tools/python3/Objects/exceptions.c
index e3217c922e..4f2153b193 100644
--- a/contrib/tools/python3/Objects/exceptions.c
+++ b/contrib/tools/python3/Objects/exceptions.c
@@ -3254,7 +3254,7 @@ SimpleExtendsException(PyExc_Exception, ArithmeticError,
* FloatingPointError extends ArithmeticError
*/
SimpleExtendsException(PyExc_ArithmeticError, FloatingPointError,
- "Floating point operation failed.");
+ "Floating-point operation failed.");
/*
diff --git a/contrib/tools/python3/Objects/floatobject.c b/contrib/tools/python3/Objects/floatobject.c
index 7a882bfd88..92d40e8aca 100644
--- a/contrib/tools/python3/Objects/floatobject.c
+++ b/contrib/tools/python3/Objects/floatobject.c
@@ -1644,12 +1644,12 @@ float.__new__ as float_new
x: object(c_default="NULL") = 0
/
-Convert a string or number to a floating point number, if possible.
+Convert a string or number to a floating-point number, if possible.
[clinic start generated code]*/
static PyObject *
float_new_impl(PyTypeObject *type, PyObject *x)
-/*[clinic end generated code: output=ccf1e8dc460ba6ba input=f43661b7de03e9d8]*/
+/*[clinic end generated code: output=ccf1e8dc460ba6ba input=55909f888aa0c8a6]*/
{
if (type != &PyFloat_Type) {
if (x == NULL) {
@@ -1745,13 +1745,13 @@ You probably don't want to use this function.
It exists mainly to be used in Python's test suite.
This function returns whichever of 'unknown', 'IEEE, big-endian' or 'IEEE,
-little-endian' best describes the format of floating point numbers used by the
+little-endian' best describes the format of floating-point numbers used by the
C type named by typestr.
[clinic start generated code]*/
static PyObject *
float___getformat___impl(PyTypeObject *type, const char *typestr)
-/*[clinic end generated code: output=2bfb987228cc9628 input=d5a52600f835ad67]*/
+/*[clinic end generated code: output=2bfb987228cc9628 input=90d5e246409a246e]*/
{
float_format_type r;
@@ -1937,7 +1937,7 @@ _init_global_state(void)
float_format_type detected_double_format, detected_float_format;
/* We attempt to determine if this machine is using IEEE
- floating point formats by peering at the bits of some
+ floating-point formats by peering at the bits of some
carefully chosen values. If it looks like we are on an
IEEE platform, the float packing/unpacking routines can
just copy bits, if not they resort to arithmetic & shifts
diff --git a/contrib/tools/python3/Objects/genericaliasobject.c b/contrib/tools/python3/Objects/genericaliasobject.c
index 117b4e8dfb..7f89e68340 100644
--- a/contrib/tools/python3/Objects/genericaliasobject.c
+++ b/contrib/tools/python3/Objects/genericaliasobject.c
@@ -564,6 +564,10 @@ ga_getitem(PyObject *self, PyObject *item)
}
PyObject *res = Py_GenericAlias(alias->origin, newargs);
+ if (res == NULL) {
+ Py_DECREF(newargs);
+ return NULL;
+ }
((gaobject *)res)->starred = alias->starred;
Py_DECREF(newargs);
diff --git a/contrib/tools/python3/Objects/genobject.c b/contrib/tools/python3/Objects/genobject.c
index dc034a4b72..474abe1094 100644
--- a/contrib/tools/python3/Objects/genobject.c
+++ b/contrib/tools/python3/Objects/genobject.c
@@ -374,6 +374,7 @@ static PyObject *
gen_close(PyGenObject *gen, PyObject *args)
{
PyObject *retval;
+ PyObject *yf = _PyGen_yf(gen);
int err = 0;
if (gen->gi_frame_state == FRAME_CREATED) {
@@ -383,7 +384,6 @@ gen_close(PyGenObject *gen, PyObject *args)
if (gen->gi_frame_state >= FRAME_COMPLETED) {
Py_RETURN_NONE;
}
- PyObject *yf = _PyGen_yf(gen);
if (yf) {
PyFrameState state = gen->gi_frame_state;
gen->gi_frame_state = FRAME_EXECUTING;
@@ -396,14 +396,12 @@ gen_close(PyGenObject *gen, PyObject *args)
* YIELD_VALUE if the debugger has changed the lineno. */
if (err == 0 && is_yield(frame->prev_instr)) {
assert(is_resume(frame->prev_instr + 1));
- int exception_handler_depth = frame->prev_instr[0].op.arg;
+ int exception_handler_depth = frame->prev_instr[0].op.code;
assert(exception_handler_depth > 0);
/* We can safely ignore the outermost try block
* as it automatically generated to handle
* StopIteration. */
if (exception_handler_depth == 1) {
- gen->gi_frame_state = FRAME_COMPLETED;
- _PyFrame_ClearLocals((_PyInterpreterFrame *)gen->gi_iframe);
Py_RETURN_NONE;
}
}
diff --git a/contrib/tools/python3/Objects/listobject.c b/contrib/tools/python3/Objects/listobject.c
index f59abe2e64..d017f34b94 100644
--- a/contrib/tools/python3/Objects/listobject.c
+++ b/contrib/tools/python3/Objects/listobject.c
@@ -2759,7 +2759,14 @@ list_richcompare(PyObject *v, PyObject *w, int op)
}
/* Compare the final item again using the proper operator */
- return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
+ PyObject *vitem = vl->ob_item[i];
+ PyObject *witem = wl->ob_item[i];
+ Py_INCREF(vitem);
+ Py_INCREF(witem);
+ PyObject *result = PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
+ Py_DECREF(vitem);
+ Py_DECREF(witem);
+ return result;
}
/*[clinic input]
@@ -2928,6 +2935,23 @@ list_subscript(PyListObject* self, PyObject* item)
}
}
+static Py_ssize_t
+adjust_slice_indexes(PyListObject *lst,
+ Py_ssize_t *start, Py_ssize_t *stop,
+ Py_ssize_t step)
+{
+ Py_ssize_t slicelength = PySlice_AdjustIndices(Py_SIZE(lst), start, stop,
+ step);
+
+ /* Make sure s[5:2] = [..] inserts at the right place:
+ before 5, not before 2. */
+ if ((step < 0 && *start < *stop) ||
+ (step > 0 && *start > *stop))
+ *stop = *start;
+
+ return slicelength;
+}
+
static int
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
{
@@ -2940,22 +2964,11 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
return list_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
+ Py_ssize_t start, stop, step;
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
- slicelength = PySlice_AdjustIndices(Py_SIZE(self), &start, &stop,
- step);
-
- if (step == 1)
- return list_ass_slice(self, start, stop, value);
-
- /* Make sure s[5:2] = [..] inserts at the right place:
- before 5, not before 2. */
- if ((step < 0 && start < stop) ||
- (step > 0 && start > stop))
- stop = start;
if (value == NULL) {
/* delete slice */
@@ -2964,6 +2977,12 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
Py_ssize_t i;
int res;
+ Py_ssize_t slicelength = adjust_slice_indexes(self, &start, &stop,
+ step);
+
+ if (step == 1)
+ return list_ass_slice(self, start, stop, value);
+
if (slicelength <= 0)
return 0;
@@ -3039,6 +3058,15 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
if (!seq)
return -1;
+ Py_ssize_t slicelength = adjust_slice_indexes(self, &start, &stop,
+ step);
+
+ if (step == 1) {
+ int res = list_ass_slice(self, start, stop, seq);
+ Py_DECREF(seq);
+ return res;
+ }
+
if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
PyErr_Format(PyExc_ValueError,
"attempt to assign sequence of "
diff --git a/contrib/tools/python3/Objects/longobject.c b/contrib/tools/python3/Objects/longobject.c
index c72e1643c9..c366034fe4 100644
--- a/contrib/tools/python3/Objects/longobject.c
+++ b/contrib/tools/python3/Objects/longobject.c
@@ -484,11 +484,18 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
do_decref = 1;
}
if (_PyLong_IsCompact(v)) {
-#if SIZEOF_LONG < SIZEOF_VOID_P
- intptr_t tmp = _PyLong_CompactValue(v);
- res = (long)tmp;
- if (res != tmp) {
- *overflow = tmp < 0 ? -1 : 1;
+#if SIZEOF_LONG < SIZEOF_SIZE_T
+ Py_ssize_t tmp = _PyLong_CompactValue(v);
+ if (tmp < LONG_MIN) {
+ *overflow = -1;
+ res = -1;
+ }
+ else if (tmp > LONG_MAX) {
+ *overflow = 1;
+ res = -1;
+ }
+ else {
+ res = (long)tmp;
}
#else
res = _PyLong_CompactValue(v);
@@ -633,14 +640,15 @@ PyLong_AsUnsignedLong(PyObject *vv)
v = (PyLongObject *)vv;
if (_PyLong_IsNonNegativeCompact(v)) {
-#if SIZEOF_LONG < SIZEOF_VOID_P
- intptr_t tmp = _PyLong_CompactValue(v);
+#if SIZEOF_LONG < SIZEOF_SIZE_T
+ size_t tmp = (size_t)_PyLong_CompactValue(v);
unsigned long res = (unsigned long)tmp;
if (res != tmp) {
goto overflow;
}
+ return res;
#else
- return _PyLong_CompactValue(v);
+ return (unsigned long)(size_t)_PyLong_CompactValue(v);
#endif
}
if (_PyLong_IsNegative(v)) {
@@ -686,7 +694,7 @@ PyLong_AsSize_t(PyObject *vv)
v = (PyLongObject *)vv;
if (_PyLong_IsNonNegativeCompact(v)) {
- return _PyLong_CompactValue(v);
+ return (size_t)_PyLong_CompactValue(v);
}
if (_PyLong_IsNegative(v)) {
PyErr_SetString(PyExc_OverflowError,
@@ -723,7 +731,11 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
}
v = (PyLongObject *)vv;
if (_PyLong_IsCompact(v)) {
- return (unsigned long)_PyLong_CompactValue(v);
+#if SIZEOF_LONG < SIZEOF_SIZE_T
+ return (unsigned long)(size_t)_PyLong_CompactValue(v);
+#else
+ return (unsigned long)(long)_PyLong_CompactValue(v);
+#endif
}
i = _PyLong_DigitCount(v);
int sign = _PyLong_NonCompactSign(v);
@@ -1267,7 +1279,18 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
v = (PyLongObject*)vv;
if (_PyLong_IsNonNegativeCompact(v)) {
res = 0;
- bytes = _PyLong_CompactValue(v);
+#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
+ size_t tmp = (size_t)_PyLong_CompactValue(v);
+ bytes = (unsigned long long)tmp;
+ if (bytes != tmp) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert "
+ "to C unsigned long long");
+ res = -1;
+ }
+#else
+ bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
+#endif
}
else {
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
@@ -1298,7 +1321,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
}
v = (PyLongObject *)vv;
if (_PyLong_IsCompact(v)) {
- return (unsigned long long)(signed long long)_PyLong_CompactValue(v);
+#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
+ return (unsigned long long)(size_t)_PyLong_CompactValue(v);
+#else
+ return (unsigned long long)(long long)_PyLong_CompactValue(v);
+#endif
}
i = _PyLong_DigitCount(v);
sign = _PyLong_NonCompactSign(v);
@@ -1370,7 +1397,22 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
do_decref = 1;
}
if (_PyLong_IsCompact(v)) {
+#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
+ Py_ssize_t tmp = _PyLong_CompactValue(v);
+ if (tmp < LLONG_MIN) {
+ *overflow = -1;
+ res = -1;
+ }
+ else if (tmp > LLONG_MAX) {
+ *overflow = 1;
+ res = -1;
+ }
+ else {
+ res = (long long)tmp;
+ }
+#else
res = _PyLong_CompactValue(v);
+#endif
}
else {
i = _PyLong_DigitCount(v);
@@ -3308,7 +3350,7 @@ long_hash(PyLongObject *v)
int sign;
if (_PyLong_IsCompact(v)) {
- x = _PyLong_CompactValue(v);
+ x = (Py_uhash_t)_PyLong_CompactValue(v);
if (x == (Py_uhash_t)-1) {
x = (Py_uhash_t)-2;
}
@@ -6209,7 +6251,7 @@ PyDoc_STRVAR(long_doc,
int(x, base=10) -> integer\n\
\n\
Convert a number or string to an integer, or return 0 if no arguments\n\
-are given. If x is a number, return x.__int__(). For floating point\n\
+are given. If x is a number, return x.__int__(). For floating-point\n\
numbers, this truncates towards zero.\n\
\n\
If x is not a number or if base is given, then x must be a string,\n\
diff --git a/contrib/tools/python3/Objects/memoryobject.c b/contrib/tools/python3/Objects/memoryobject.c
index b0168044d9..3c88859acc 100644
--- a/contrib/tools/python3/Objects/memoryobject.c
+++ b/contrib/tools/python3/Objects/memoryobject.c
@@ -264,7 +264,7 @@ PyTypeObject _PyManagedBuffer_Type = {
/* Assumptions: ndim >= 1. The macro tests for a corner case that should
perhaps be explicitly forbidden in the PEP. */
#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
- (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
+ (view->suboffsets && view->suboffsets[view->ndim-1] >= 0)
static inline int
last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
diff --git a/contrib/tools/python3/Objects/tupleobject.c b/contrib/tools/python3/Objects/tupleobject.c
index 991edcc866..918654fae8 100644
--- a/contrib/tools/python3/Objects/tupleobject.c
+++ b/contrib/tools/python3/Objects/tupleobject.c
@@ -1139,7 +1139,7 @@ maybe_freelist_pop(Py_ssize_t size)
return NULL;
}
assert(size > 0);
- if (size < PyTuple_MAXSAVESIZE) {
+ if (size <= PyTuple_MAXSAVESIZE) {
Py_ssize_t index = size - 1;
PyTupleObject *op = STATE.free_list[index];
if (op != NULL) {
diff --git a/contrib/tools/python3/Objects/typeobject.c b/contrib/tools/python3/Objects/typeobject.c
index 7ebc7a9804..1cac4b8b0f 100644
--- a/contrib/tools/python3/Objects/typeobject.c
+++ b/contrib/tools/python3/Objects/typeobject.c
@@ -116,6 +116,7 @@ static_builtin_index_clear(PyTypeObject *self)
self->tp_subclasses = NULL;
}
+
static inline static_builtin_state *
static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
{
@@ -5720,7 +5721,6 @@ differs:
static int
object_set_class(PyObject *self, PyObject *value, void *closure)
{
- PyTypeObject *oldto = Py_TYPE(self);
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
@@ -5740,6 +5740,8 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
return -1;
}
+ PyTypeObject *oldto = Py_TYPE(self);
+
/* In versions of CPython prior to 3.5, the code in
compatible_for_assignment was not set up to correctly check for memory
layout / slot / etc. compatibility for non-HEAPTYPE classes, so we just
@@ -7595,6 +7597,7 @@ _PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
if (res < 0) {
static_builtin_state_clear(interp, self);
}
+
return res;
}
@@ -10087,6 +10090,84 @@ recurse_down_subclasses(PyTypeObject *type, PyObject *attr_name,
return 0;
}
+static int
+expect_manually_inherited(PyTypeObject *type, void **slot)
+{
+ PyObject *typeobj = (PyObject *)type;
+ if (slot == (void *)&type->tp_init) {
+ /* This is a best-effort list of builtin exception types
+ that have their own tp_init function. */
+ if (typeobj != PyExc_BaseException
+ && typeobj != PyExc_BaseExceptionGroup
+ && typeobj != PyExc_ImportError
+ && typeobj != PyExc_NameError
+ && typeobj != PyExc_OSError
+ && typeobj != PyExc_StopIteration
+ && typeobj != PyExc_SyntaxError
+ && typeobj != PyExc_UnicodeDecodeError
+ && typeobj != PyExc_UnicodeEncodeError
+
+ && type != &PyBool_Type
+ && type != &PyBytes_Type
+ && type != &PyMemoryView_Type
+ && type != &PyComplex_Type
+ && type != &PyEnum_Type
+ && type != &PyFilter_Type
+ && type != &PyFloat_Type
+ && type != &PyFrozenSet_Type
+ && type != &PyLong_Type
+ && type != &PyMap_Type
+ && type != &PyRange_Type
+ && type != &PyReversed_Type
+ && type != &PySlice_Type
+ && type != &PyTuple_Type
+ && type != &PyUnicode_Type
+ && type != &PyZip_Type)
+
+ {
+ return 1;
+ }
+ }
+ else if (slot == (void *)&type->tp_str) {
+ /* This is a best-effort list of builtin exception types
+ that have their own tp_str function. */
+ if (typeobj == PyExc_AttributeError || typeobj == PyExc_NameError) {
+ return 1;
+ }
+ }
+ else if (slot == (void *)&type->tp_getattr
+ || slot == (void *)&type->tp_getattro)
+ {
+ /* This is a best-effort list of builtin types
+ that have their own tp_getattr function. */
+ if (typeobj == PyExc_BaseException
+ || type == &PyByteArray_Type
+ || type == &PyBytes_Type
+ || type == &PyComplex_Type
+ || type == &PyDict_Type
+ || type == &PyEnum_Type
+ || type == &PyFilter_Type
+ || type == &PyLong_Type
+ || type == &PyList_Type
+ || type == &PyMap_Type
+ || type == &PyMemoryView_Type
+ || type == &PyProperty_Type
+ || type == &PyRange_Type
+ || type == &PyReversed_Type
+ || type == &PySet_Type
+ || type == &PySlice_Type
+ || type == &PySuper_Type
+ || type == &PyTuple_Type
+ || type == &PyZip_Type)
+ {
+ return 1;
+ }
+ }
+
+ /* It must be inherited (see type_ready_inherit()).. */
+ return 0;
+}
+
/* This function is called by PyType_Ready() to populate the type's
dictionary with method descriptors for function slots. For each
function slot (like tp_repr) that's defined in the type, one or more
@@ -10131,6 +10212,26 @@ add_operators(PyTypeObject *type)
ptr = slotptr(type, p->offset);
if (!ptr || !*ptr)
continue;
+ if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN
+ && type->tp_base != NULL)
+ {
+ /* Also ignore when the type slot has been inherited. */
+ void **ptr_base = slotptr(type->tp_base, p->offset);
+ if (ptr_base && *ptr == *ptr_base) {
+ /* Ideally we would always ignore any manually inherited
+ slots, Which would mean inheriting the slot wrapper
+ using normal attribute lookup rather than keeping
+ a distinct copy. However, that would introduce
+ a slight change in behavior that could break
+ existing code.
+
+ In the meantime, look the other way when the definition
+ explicitly inherits the slot. */
+ if (!expect_manually_inherited(type, ptr)) {
+ continue;
+ }
+ }
+ }
int r = PyDict_Contains(dict, p->name_strobj);
if (r > 0)
continue;