[Python-checkins] python/dist/src/Objects typeobject.c,2.151,2.152
gvanrossum@users.sourceforge.net
gvanrossum@users.sourceforge.net
Thu, 13 Jun 2002 12:17:51 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv11967/Objects
Modified Files:
typeobject.c
Log Message:
Hopefully this addresses the remaining issues of SF bugs 459235 and
473985. Through a subtle rearrangement of some members in the etype
struct (!), mapping methods are now preferred over sequence methods,
which is necessary to support str.__getitem__("hello", slice(4)) etc.
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.151
retrieving revision 2.152
diff -C2 -d -r2.151 -r2.152
*** typeobject.c 10 Jun 2002 15:29:03 -0000 2.151
--- typeobject.c 13 Jun 2002 19:17:45 -0000 2.152
***************
*** 9,16 ****
/* XXX Should we publish this in a header file? */
typedef struct {
PyTypeObject type;
PyNumberMethods as_number;
- PySequenceMethods as_sequence;
PyMappingMethods as_mapping;
PyBufferProcs as_buffer;
PyObject *name, *slots;
--- 9,22 ----
/* XXX Should we publish this in a header file? */
typedef struct {
+ /* Note: there's a dependency on the order of these members
+ in slotptr() below. */
PyTypeObject type;
PyNumberMethods as_number;
PyMappingMethods as_mapping;
+ PySequenceMethods as_sequence; /* as_sequence comes after as_mapping,
+ so that the mapping wins when both
+ the mapping and the sequence define
+ a given operator (e.g. __getitem__).
+ see add_operators() below. */
PyBufferProcs as_buffer;
PyObject *name, *slots;
***************
*** 3871,3884 ****
char *ptr;
assert(offset >= 0);
assert(offset < offsetof(etype, as_buffer));
! if (offset >= offsetof(etype, as_mapping)) {
! ptr = (void *)type->tp_as_mapping;
! offset -= offsetof(etype, as_mapping);
! }
! else if (offset >= offsetof(etype, as_sequence)) {
ptr = (void *)type->tp_as_sequence;
offset -= offsetof(etype, as_sequence);
}
else if (offset >= offsetof(etype, as_number)) {
ptr = (void *)type->tp_as_number;
--- 3877,3891 ----
char *ptr;
+ /* Note: this depends on the order of the members of etype! */
assert(offset >= 0);
assert(offset < offsetof(etype, as_buffer));
! if (offset >= offsetof(etype, as_sequence)) {
ptr = (void *)type->tp_as_sequence;
offset -= offsetof(etype, as_sequence);
}
+ else if (offset >= offsetof(etype, as_mapping)) {
+ ptr = (void *)type->tp_as_mapping;
+ offset -= offsetof(etype, as_mapping);
+ }
else if (offset >= offsetof(etype, as_number)) {
ptr = (void *)type->tp_as_number;
***************
*** 4114,4135 ****
/* 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 corresponding descriptors are added in the type's tp_dict
! dictionary under the appropriate name (like __repr__). Some
! function slots cause more than one descriptor to be added (for
! example, the nb_add slot adds both __add__ and __radd__
! descriptors) and some function slots compete for the same
! descriptor (for example both sq_item and mp_subscript generate a
! __getitem__ descriptor). This only adds new descriptors and
! doesn't overwrite entries in tp_dict that were previously
! defined. The descriptors contain a reference to the C function
! they must call, so that it's safe if they are copied into a
! subtype's __dict__ and the subtype has a different C function in
! its slot -- calling the method defined by the descriptor will call
! the C function that was used to create it, rather than the C
! function present in the slot when it is called. (This is important
! because a subtype may have a C function in the slot that calls the
! method from the dictionary, and we want to avoid infinite recursion
! here.) */
static int
--- 4121,4150 ----
/* 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
! corresponding descriptors are added in the type's tp_dict dictionary
! under the appropriate name (like __repr__). Some function slots
! cause more than one descriptor to be added (for example, the nb_add
! slot adds both __add__ and __radd__ descriptors) and some function
! slots compete for the same descriptor (for example both sq_item and
! mp_subscript generate a __getitem__ descriptor).
!
! In the latter case, the first slotdef entry encoutered wins. Since
! slotdef entries are sorted by the offset of the slot in the etype
! struct, this gives us some control over disambiguating between
! competing slots: the members of struct etype are listed from most
! general to least general, so the most general slot is preferred. In
! particular, because as_mapping comes before as_sequence, for a type
! that defines both mp_subscript and sq_item, mp_subscript wins.
!
! This only adds new descriptors and doesn't overwrite entries in
! tp_dict that were previously defined. The descriptors contain a
! reference to the C function they must call, so that it's safe if they
! are copied into a subtype's __dict__ and the subtype has a different
! C function in its slot -- calling the method defined by the
! descriptor will call the C function that was used to create it,
! rather than the C function present in the slot when it is called.
! (This is important because a subtype may have a C function in the
! slot that calls the method from the dictionary, and we want to avoid
! infinite recursion here.) */
static int