Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d3f41fe

Browse files
committed
merge 3.3 (#17610)
2 parents 49e835b + 6395241 commit d3f41fe

2 files changed

Lines changed: 101 additions & 112 deletions

File tree

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Core and Builtins
1313
- Issue #17357: Add missing verbosity messages for -v/-vv that were lost during
1414
the importlib transition.
1515

16+
- Issue #17610: Don't rely on non-standard behavior of the C qsort() function.
17+
1618
- Issue #17323: The "[X refs, Y blocks]" printed by debug builds has been
1719
disabled by default. It can be re-enabled with the `-X showrefcount` option.
1820

Objects/typeobject.c

Lines changed: 99 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -5658,15 +5658,16 @@ slot_tp_del(PyObject *self)
56585658
}
56595659

56605660

5661-
/* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
5662-
functions. The offsets here are relative to the 'PyHeapTypeObject'
5663-
structure, which incorporates the additional structures used for numbers,
5664-
sequences and mappings.
5665-
Note that multiple names may map to the same slot (e.g. __eq__,
5666-
__ne__ etc. all map to tp_richcompare) and one name may map to multiple
5667-
slots (e.g. __str__ affects tp_str as well as tp_repr). The table is
5668-
terminated with an all-zero entry. (This table is further initialized and
5669-
sorted in init_slotdefs() below.) */
5661+
/*
5662+
Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper functions.
5663+
5664+
The table is ordered by offsets relative to the 'PyHeapTypeObject' structure,
5665+
which incorporates the additional structures used for numbers, sequences and
5666+
mappings. Note that multiple names may map to the same slot (e.g. __eq__,
5667+
__ne__ etc. all map to tp_richcompare) and one name may map to multiple slots
5668+
(e.g. __str__ affects tp_str as well as tp_repr). The table is terminated with
5669+
an all-zero entry. (This table is further initialized in init_slotdefs().)
5670+
*/
56705671

56715672
typedef struct wrapperbase slotdef;
56725673

@@ -5716,43 +5717,53 @@ typedef struct wrapperbase slotdef;
57165717
"x." NAME "(y) <==> " DOC)
57175718

57185719
static slotdef slotdefs[] = {
5719-
SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
5720-
"x.__len__() <==> len(x)"),
5721-
/* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
5722-
The logic in abstract.c always falls back to nb_add/nb_multiply in
5723-
this case. Defining both the nb_* and the sq_* slots to call the
5724-
user-defined methods has unexpected side-effects, as shown by
5725-
test_descr.notimplemented() */
5726-
SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
5727-
"x.__add__(y) <==> x+y"),
5728-
SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc,
5729-
"x.__mul__(n) <==> x*n"),
5730-
SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc,
5731-
"x.__rmul__(n) <==> n*x"),
5732-
SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
5733-
"x.__getitem__(y) <==> x[y]"),
5734-
SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem,
5735-
"x.__setitem__(i, y) <==> x[i]=y"),
5736-
SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem,
5737-
"x.__delitem__(y) <==> del x[y]"),
5738-
SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc,
5739-
"x.__contains__(y) <==> y in x"),
5740-
SQSLOT("__iadd__", sq_inplace_concat, NULL,
5741-
wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"),
5742-
SQSLOT("__imul__", sq_inplace_repeat, NULL,
5743-
wrap_indexargfunc, "x.__imul__(y) <==> x*=y"),
5744-
5745-
MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc,
5746-
"x.__len__() <==> len(x)"),
5747-
MPSLOT("__getitem__", mp_subscript, slot_mp_subscript,
5748-
wrap_binaryfunc,
5749-
"x.__getitem__(y) <==> x[y]"),
5750-
MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript,
5751-
wrap_objobjargproc,
5752-
"x.__setitem__(i, y) <==> x[i]=y"),
5753-
MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript,
5754-
wrap_delitem,
5755-
"x.__delitem__(y) <==> del x[y]"),
5720+
TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),
5721+
TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
5722+
TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
5723+
TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
5724+
TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc,
5725+
"x.__repr__() <==> repr(x)"),
5726+
TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc,
5727+
"x.__hash__() <==> hash(x)"),
5728+
FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call,
5729+
"x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS),
5730+
TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc,
5731+
"x.__str__() <==> str(x)"),
5732+
TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,
5733+
wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"),
5734+
TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),
5735+
TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,
5736+
"x.__setattr__('name', value) <==> x.name = value"),
5737+
TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr,
5738+
"x.__delattr__('name') <==> del x.name"),
5739+
TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt,
5740+
"x.__lt__(y) <==> x<y"),
5741+
TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le,
5742+
"x.__le__(y) <==> x<=y"),
5743+
TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq,
5744+
"x.__eq__(y) <==> x==y"),
5745+
TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne,
5746+
"x.__ne__(y) <==> x!=y"),
5747+
TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt,
5748+
"x.__gt__(y) <==> x>y"),
5749+
TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge,
5750+
"x.__ge__(y) <==> x>=y"),
5751+
TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc,
5752+
"x.__iter__() <==> iter(x)"),
5753+
TPSLOT("__next__", tp_iternext, slot_tp_iternext, wrap_next,
5754+
"x.__next__() <==> next(x)"),
5755+
TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get,
5756+
"descr.__get__(obj[, type]) -> value"),
5757+
TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set,
5758+
"descr.__set__(obj, value)"),
5759+
TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set,
5760+
wrap_descr_delete, "descr.__delete__(obj)"),
5761+
FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init,
5762+
"x.__init__(...) initializes x; "
5763+
"see help(type(x)) for signature",
5764+
PyWrapperFlag_KEYWORDS),
5765+
TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),
5766+
TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""),
57565767

57575768
BINSLOT("__add__", nb_add, slot_nb_add,
57585769
"+"),
@@ -5799,8 +5810,6 @@ static slotdef slotdefs[] = {
57995810
"int(x)"),
58005811
UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc,
58015812
"float(x)"),
5802-
NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
5803-
"x[y:z] <==> x[y.__index__():z.__index__()]"),
58045813
IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
58055814
wrap_binaryfunc, "+="),
58065815
IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,
@@ -5829,54 +5838,47 @@ static slotdef slotdefs[] = {
58295838
slot_nb_inplace_floor_divide, wrap_binaryfunc, "//"),
58305839
IBSLOT("__itruediv__", nb_inplace_true_divide,
58315840
slot_nb_inplace_true_divide, wrap_binaryfunc, "/"),
5841+
NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
5842+
"x[y:z] <==> x[y.__index__():z.__index__()]"),
5843+
5844+
MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc,
5845+
"x.__len__() <==> len(x)"),
5846+
MPSLOT("__getitem__", mp_subscript, slot_mp_subscript,
5847+
wrap_binaryfunc,
5848+
"x.__getitem__(y) <==> x[y]"),
5849+
MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript,
5850+
wrap_objobjargproc,
5851+
"x.__setitem__(i, y) <==> x[i]=y"),
5852+
MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript,
5853+
wrap_delitem,
5854+
"x.__delitem__(y) <==> del x[y]"),
5855+
5856+
SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
5857+
"x.__len__() <==> len(x)"),
5858+
/* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
5859+
The logic in abstract.c always falls back to nb_add/nb_multiply in
5860+
this case. Defining both the nb_* and the sq_* slots to call the
5861+
user-defined methods has unexpected side-effects, as shown by
5862+
test_descr.notimplemented() */
5863+
SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
5864+
"x.__add__(y) <==> x+y"),
5865+
SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc,
5866+
"x.__mul__(n) <==> x*n"),
5867+
SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc,
5868+
"x.__rmul__(n) <==> n*x"),
5869+
SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
5870+
"x.__getitem__(y) <==> x[y]"),
5871+
SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem,
5872+
"x.__setitem__(i, y) <==> x[i]=y"),
5873+
SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem,
5874+
"x.__delitem__(y) <==> del x[y]"),
5875+
SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc,
5876+
"x.__contains__(y) <==> y in x"),
5877+
SQSLOT("__iadd__", sq_inplace_concat, NULL,
5878+
wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"),
5879+
SQSLOT("__imul__", sq_inplace_repeat, NULL,
5880+
wrap_indexargfunc, "x.__imul__(y) <==> x*=y"),
58325881

5833-
TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc,
5834-
"x.__str__() <==> str(x)"),
5835-
TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc,
5836-
"x.__repr__() <==> repr(x)"),
5837-
TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc,
5838-
"x.__hash__() <==> hash(x)"),
5839-
FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call,
5840-
"x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS),
5841-
TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,
5842-
wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"),
5843-
TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),
5844-
TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),
5845-
TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
5846-
TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,
5847-
"x.__setattr__('name', value) <==> x.name = value"),
5848-
TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
5849-
TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr,
5850-
"x.__delattr__('name') <==> del x.name"),
5851-
TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
5852-
TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt,
5853-
"x.__lt__(y) <==> x<y"),
5854-
TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le,
5855-
"x.__le__(y) <==> x<=y"),
5856-
TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq,
5857-
"x.__eq__(y) <==> x==y"),
5858-
TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne,
5859-
"x.__ne__(y) <==> x!=y"),
5860-
TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt,
5861-
"x.__gt__(y) <==> x>y"),
5862-
TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge,
5863-
"x.__ge__(y) <==> x>=y"),
5864-
TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc,
5865-
"x.__iter__() <==> iter(x)"),
5866-
TPSLOT("__next__", tp_iternext, slot_tp_iternext, wrap_next,
5867-
"x.__next__() <==> next(x)"),
5868-
TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get,
5869-
"descr.__get__(obj[, type]) -> value"),
5870-
TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set,
5871-
"descr.__set__(obj, value)"),
5872-
TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set,
5873-
wrap_descr_delete, "descr.__delete__(obj)"),
5874-
FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init,
5875-
"x.__init__(...) initializes x; "
5876-
"see help(type(x)) for signature",
5877-
PyWrapperFlag_KEYWORDS),
5878-
TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),
5879-
TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""),
58805882
{NULL}
58815883
};
58825884

@@ -6057,21 +6059,6 @@ update_slots_callback(PyTypeObject *type, void *data)
60576059
return 0;
60586060
}
60596061

6060-
/* Comparison function for qsort() to compare slotdefs by their offset, and
6061-
for equal offset by their address (to force a stable sort). */
6062-
static int
6063-
slotdef_cmp(const void *aa, const void *bb)
6064-
{
6065-
const slotdef *a = (const slotdef *)aa, *b = (const slotdef *)bb;
6066-
int c = a->offset - b->offset;
6067-
if (c != 0)
6068-
return c;
6069-
else
6070-
/* Cannot use a-b, as this gives off_t,
6071-
which may lose precision when converted to int. */
6072-
return (a > b) ? 1 : (a < b) ? -1 : 0;
6073-
}
6074-
60756062
/* Initialize the slotdefs table by adding interned string objects for the
60766063
names and sorting the entries. */
60776064
static void
@@ -6083,12 +6070,12 @@ init_slotdefs(void)
60836070
if (initialized)
60846071
return;
60856072
for (p = slotdefs; p->name; p++) {
6073+
/* Slots must be ordered by their offset in the PyHeapTypeObject. */
6074+
assert(!p[1].name || p->offset <= p[1].offset);
60866075
p->name_strobj = PyUnicode_InternFromString(p->name);
60876076
if (!p->name_strobj)
60886077
Py_FatalError("Out of memory interning slotdef names");
60896078
}
6090-
qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef),
6091-
slotdef_cmp);
60926079
initialized = 1;
60936080
}
60946081

0 commit comments

Comments
 (0)