Checking in the code for PEP 357.
This was mostly written by Travis Oliphant. I've inspected it all; Neal Norwitz and MvL have also looked at it (in an earlier incarnation).
This commit is contained in:
parent
9d7855076a
commit
38fff8c4e4
|
@ -346,6 +346,7 @@ determination.
|
||||||
either the sequence and mapping protocols, the sequence length is
|
either the sequence and mapping protocols, the sequence length is
|
||||||
returned. On error, \code{-1} is returned. This is the equivalent
|
returned. On error, \code{-1} is returned. This is the equivalent
|
||||||
to the Python expression \samp{len(\var{o})}.\bifuncindex{len}
|
to the Python expression \samp{len(\var{o})}.\bifuncindex{len}
|
||||||
|
\versionadded{2.5}
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
|
||||||
|
@ -689,6 +690,10 @@ determination.
|
||||||
\samp{float(\var{o})}.\bifuncindex{float}
|
\samp{float(\var{o})}.\bifuncindex{float}
|
||||||
\end{cfuncdesc}
|
\end{cfuncdesc}
|
||||||
|
|
||||||
|
\begin{cfuncdesc}{Py_ssize_t}{PyNumber_Index}{PyObject *o}
|
||||||
|
Returns the \var{o} converted to a Py_ssize_t integer on success, or
|
||||||
|
-1 with an exception raised on failure.
|
||||||
|
\end{cfuncdesc}
|
||||||
|
|
||||||
\section{Sequence Protocol \label{sequence}}
|
\section{Sequence Protocol \label{sequence}}
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,11 @@ effect. This is also known as ``true'' division.
|
||||||
Return the bitwise exclusive or of \var{a} and \var{b}.
|
Return the bitwise exclusive or of \var{a} and \var{b}.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
|
\begin{funcdesc}{index}{a}
|
||||||
|
\funcline{__index__}{a}
|
||||||
|
Return \var{a} converted to an integer. Equivalent to \var{a}\code{.__index__()}.
|
||||||
|
\versionadded{2.5}
|
||||||
|
\end{funcdesc}
|
||||||
|
|
||||||
Operations which work with sequences include:
|
Operations which work with sequences include:
|
||||||
|
|
||||||
|
|
|
@ -1978,6 +1978,13 @@ Called to implement the built-in functions
|
||||||
\function{hex()}\bifuncindex{hex}. Should return a string value.
|
\function{hex()}\bifuncindex{hex}. Should return a string value.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
|
\begin{methoddesc}[numeric object]{__index__}{self}
|
||||||
|
Called to implement operator.index(). Also called whenever Python
|
||||||
|
needs an integer object (such as in slicing). Must return an integer
|
||||||
|
(int or long).
|
||||||
|
\versionadded{2.5}
|
||||||
|
\end{methoddesc}
|
||||||
|
|
||||||
\begin{methoddesc}[numeric object]{__coerce__}{self, other}
|
\begin{methoddesc}[numeric object]{__coerce__}{self, other}
|
||||||
Called to implement ``mixed-mode'' numeric arithmetic. Should either
|
Called to implement ``mixed-mode'' numeric arithmetic. Should either
|
||||||
return a 2-tuple containing \var{self} and \var{other} converted to
|
return a 2-tuple containing \var{self} and \var{other} converted to
|
||||||
|
|
|
@ -748,6 +748,14 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
PyAPI_FUNC(Py_ssize_t) PyNumber_Index(PyObject *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the object converted to Py_ssize_t on success
|
||||||
|
or -1 with an error raised on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyNumber_Int(PyObject *o);
|
PyAPI_FUNC(PyObject *) PyNumber_Int(PyObject *o);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -206,6 +206,9 @@ typedef struct {
|
||||||
binaryfunc nb_true_divide;
|
binaryfunc nb_true_divide;
|
||||||
binaryfunc nb_inplace_floor_divide;
|
binaryfunc nb_inplace_floor_divide;
|
||||||
binaryfunc nb_inplace_true_divide;
|
binaryfunc nb_inplace_true_divide;
|
||||||
|
|
||||||
|
/* Added in release 2.5 */
|
||||||
|
lenfunc nb_index;
|
||||||
} PyNumberMethods;
|
} PyNumberMethods;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -503,13 +506,16 @@ given type object has a specified feature.
|
||||||
/* Objects support garbage collection (see objimp.h) */
|
/* Objects support garbage collection (see objimp.h) */
|
||||||
#define Py_TPFLAGS_HAVE_GC (1L<<14)
|
#define Py_TPFLAGS_HAVE_GC (1L<<14)
|
||||||
|
|
||||||
/* These two bits are preserved for Stackless Python, next after this is 16 */
|
/* These two bits are preserved for Stackless Python, next after this is 17 */
|
||||||
#ifdef STACKLESS
|
#ifdef STACKLESS
|
||||||
#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION (3L<<15)
|
#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION (3L<<15)
|
||||||
#else
|
#else
|
||||||
#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION 0
|
#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Objects support nb_index in PyNumberMethods */
|
||||||
|
#define Py_TPFLAGS_HAVE_INDEX (1L<<17)
|
||||||
|
|
||||||
#define Py_TPFLAGS_DEFAULT ( \
|
#define Py_TPFLAGS_DEFAULT ( \
|
||||||
Py_TPFLAGS_HAVE_GETCHARBUFFER | \
|
Py_TPFLAGS_HAVE_GETCHARBUFFER | \
|
||||||
Py_TPFLAGS_HAVE_SEQUENCE_IN | \
|
Py_TPFLAGS_HAVE_SEQUENCE_IN | \
|
||||||
|
@ -519,6 +525,7 @@ given type object has a specified feature.
|
||||||
Py_TPFLAGS_HAVE_ITER | \
|
Py_TPFLAGS_HAVE_ITER | \
|
||||||
Py_TPFLAGS_HAVE_CLASS | \
|
Py_TPFLAGS_HAVE_CLASS | \
|
||||||
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \
|
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \
|
||||||
|
Py_TPFLAGS_HAVE_INDEX | \
|
||||||
0)
|
0)
|
||||||
|
|
||||||
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
|
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
|
||||||
|
|
|
@ -1569,19 +1569,17 @@ array_repr(arrayobject *a)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
array_subscr(arrayobject* self, PyObject* item)
|
array_subscr(arrayobject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AS_LONG(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
if (i < 0)
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
i += self->ob_size;
|
if (i==-1 && PyErr_Occurred()) {
|
||||||
return array_item(self, i);
|
|
||||||
}
|
|
||||||
else if (PyLong_Check(item)) {
|
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i += self->ob_size;
|
i += self->ob_size;
|
||||||
return array_item(self, i);
|
return array_item(self, i);
|
||||||
|
@ -1626,15 +1624,10 @@ array_subscr(arrayobject* self, PyObject* item)
|
||||||
static int
|
static int
|
||||||
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AS_LONG(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
if (i < 0)
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
i += self->ob_size;
|
if (i==-1 && PyErr_Occurred())
|
||||||
return array_ass_item(self, i, value);
|
|
||||||
}
|
|
||||||
else if (PyLong_Check(item)) {
|
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i += self->ob_size;
|
i += self->ob_size;
|
||||||
|
|
|
@ -815,6 +815,8 @@ static PyTypeObject mmap_object_type = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
/* extract the map size from the given PyObject
|
/* extract the map size from the given PyObject
|
||||||
|
|
||||||
Returns -1 on error, with an appropriate Python exception raised. On
|
Returns -1 on error, with an appropriate Python exception raised. On
|
||||||
|
@ -822,26 +824,15 @@ static PyTypeObject mmap_object_type = {
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_GetMapSize(PyObject *o)
|
_GetMapSize(PyObject *o)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(o)) {
|
PyNumberMethods *nb = o->ob_type->tp_as_number;
|
||||||
long i = PyInt_AsLong(o);
|
if (nb != NULL && HASINDEX(o) && nb->nb_index != NULL) {
|
||||||
if (PyErr_Occurred())
|
Py_ssize_t i = nb->nb_index(o);
|
||||||
|
if (i==-1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
goto onnegoverflow;
|
goto onnegoverflow;
|
||||||
return i;
|
if (i==PY_SSIZE_T_MAX)
|
||||||
}
|
goto onposoverflow;
|
||||||
else if (PyLong_Check(o)) {
|
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(o);
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
/* yes negative overflow is mistaken for positive overflow
|
|
||||||
but not worth the trouble to check sign of 'i' */
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
|
||||||
goto onposoverflow;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (i < 0)
|
|
||||||
goto onnegoverflow;
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -130,6 +130,20 @@ op_ipow(PyObject *s, PyObject *a)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
op_index(PyObject *s, PyObject *a)
|
||||||
|
{
|
||||||
|
Py_ssize_t i;
|
||||||
|
PyObject *a1;
|
||||||
|
if (!PyArg_UnpackTuple(a,"index", 1, 1, &a1))
|
||||||
|
return NULL;
|
||||||
|
i = PyNumber_Index(a1);
|
||||||
|
if (i == -1 && PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return PyInt_FromSsize_t(i);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
is_(PyObject *s, PyObject *a)
|
is_(PyObject *s, PyObject *a)
|
||||||
{
|
{
|
||||||
|
@ -229,6 +243,7 @@ spam1o(isMappingType,
|
||||||
|
|
||||||
spam1(is_, "is_(a, b) -- Same as a is b.")
|
spam1(is_, "is_(a, b) -- Same as a is b.")
|
||||||
spam1(is_not, "is_not(a, b) -- Same as a is not b.")
|
spam1(is_not, "is_not(a, b) -- Same as a is not b.")
|
||||||
|
spam2(index, __index__, "index(a) -- Same as a.__index__()")
|
||||||
spam2(add,__add__, "add(a, b) -- Same as a + b.")
|
spam2(add,__add__, "add(a, b) -- Same as a + b.")
|
||||||
spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
|
spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
|
||||||
spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
|
spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
|
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
|
||||||
Py_TPFLAGS_CHECKTYPES)
|
Py_TPFLAGS_CHECKTYPES)
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
/* Shorthands to return certain errors */
|
/* Shorthands to return certain errors */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -119,10 +121,9 @@ PyObject_GetItem(PyObject *o, PyObject *key)
|
||||||
return m->mp_subscript(o, key);
|
return m->mp_subscript(o, key);
|
||||||
|
|
||||||
if (o->ob_type->tp_as_sequence) {
|
if (o->ob_type->tp_as_sequence) {
|
||||||
if (PyInt_Check(key))
|
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
||||||
return PySequence_GetItem(o, PyInt_AsLong(key));
|
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
||||||
else if (PyLong_Check(key)) {
|
Py_ssize_t key_value = nb->nb_index(key);
|
||||||
long key_value = PyLong_AsLong(key);
|
|
||||||
if (key_value == -1 && PyErr_Occurred())
|
if (key_value == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return PySequence_GetItem(o, key_value);
|
return PySequence_GetItem(o, key_value);
|
||||||
|
@ -148,10 +149,9 @@ PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
|
||||||
return m->mp_ass_subscript(o, key, value);
|
return m->mp_ass_subscript(o, key, value);
|
||||||
|
|
||||||
if (o->ob_type->tp_as_sequence) {
|
if (o->ob_type->tp_as_sequence) {
|
||||||
if (PyInt_Check(key))
|
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
||||||
return PySequence_SetItem(o, PyInt_AsLong(key), value);
|
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
||||||
else if (PyLong_Check(key)) {
|
Py_ssize_t key_value = nb->nb_index(key);
|
||||||
long key_value = PyLong_AsLong(key);
|
|
||||||
if (key_value == -1 && PyErr_Occurred())
|
if (key_value == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
return PySequence_SetItem(o, key_value, value);
|
return PySequence_SetItem(o, key_value, value);
|
||||||
|
@ -180,10 +180,9 @@ PyObject_DelItem(PyObject *o, PyObject *key)
|
||||||
return m->mp_ass_subscript(o, key, (PyObject*)NULL);
|
return m->mp_ass_subscript(o, key, (PyObject*)NULL);
|
||||||
|
|
||||||
if (o->ob_type->tp_as_sequence) {
|
if (o->ob_type->tp_as_sequence) {
|
||||||
if (PyInt_Check(key))
|
PyNumberMethods *nb = key->ob_type->tp_as_number;
|
||||||
return PySequence_DelItem(o, PyInt_AsLong(key));
|
if (nb != NULL && HASINDEX(key) && nb->nb_index != NULL) {
|
||||||
else if (PyLong_Check(key)) {
|
Py_ssize_t key_value = nb->nb_index(key);
|
||||||
long key_value = PyLong_AsLong(key);
|
|
||||||
if (key_value == -1 && PyErr_Occurred())
|
if (key_value == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
return PySequence_DelItem(o, key_value);
|
return PySequence_DelItem(o, key_value);
|
||||||
|
@ -647,12 +646,10 @@ PyNumber_Add(PyObject *v, PyObject *w)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
|
sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
|
||||||
{
|
{
|
||||||
long count;
|
Py_ssize_t count;
|
||||||
if (PyInt_Check(n)) {
|
PyNumberMethods *nb = n->ob_type->tp_as_number;
|
||||||
count = PyInt_AsLong(n);
|
if (nb != NULL && HASINDEX(n) && nb->nb_index != NULL) {
|
||||||
}
|
count = nb->nb_index(n);
|
||||||
else if (PyLong_Check(n)) {
|
|
||||||
count = PyLong_AsLong(n);
|
|
||||||
if (count == -1 && PyErr_Occurred())
|
if (count == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -660,32 +657,7 @@ sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
|
||||||
return type_error(
|
return type_error(
|
||||||
"can't multiply sequence by non-int");
|
"can't multiply sequence by non-int");
|
||||||
}
|
}
|
||||||
#if LONG_MAX != INT_MAX
|
return (*repeatfunc)(seq, count);
|
||||||
if (count > INT_MAX) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"sequence repeat count too large");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else if (count < INT_MIN)
|
|
||||||
count = INT_MIN;
|
|
||||||
/* XXX Why don't I either
|
|
||||||
|
|
||||||
- set count to -1 whenever it's negative (after all,
|
|
||||||
sequence repeat usually treats negative numbers
|
|
||||||
as zero(); or
|
|
||||||
|
|
||||||
- raise an exception when it's less than INT_MIN?
|
|
||||||
|
|
||||||
I'm thinking about a hypothetical use case where some
|
|
||||||
sequence type might use a negative value as a flag of
|
|
||||||
some kind. In those cases I don't want to break the
|
|
||||||
code by mapping all negative values to -1. But I also
|
|
||||||
don't want to break e.g. []*(-sys.maxint), which is
|
|
||||||
perfectly safe, returning []. As a compromise, I do
|
|
||||||
map out-of-range negative values.
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
return (*repeatfunc)(seq, (int)count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -960,6 +932,22 @@ int_from_string(const char *s, Py_ssize_t len)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return a Py_ssize_t integer from the object item */
|
||||||
|
Py_ssize_t
|
||||||
|
PyNumber_Index(PyObject *item)
|
||||||
|
{
|
||||||
|
Py_ssize_t value = -1;
|
||||||
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
|
value = nb->nb_index(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_IndexError,
|
||||||
|
"object cannot be interpreted as an index");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyNumber_Int(PyObject *o)
|
PyNumber_Int(PyObject *o)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1733,6 +1733,43 @@ instance_nonzero(PyInstanceObject *self)
|
||||||
return outcome > 0;
|
return outcome > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
instance_index(PyInstanceObject *self)
|
||||||
|
{
|
||||||
|
PyObject *func, *res;
|
||||||
|
Py_ssize_t outcome;
|
||||||
|
static PyObject *indexstr = NULL;
|
||||||
|
|
||||||
|
if (indexstr == NULL) {
|
||||||
|
indexstr = PyString_InternFromString("__index__");
|
||||||
|
if (indexstr == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((func = instance_getattr(self, indexstr)) == NULL) {
|
||||||
|
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
||||||
|
return -1;
|
||||||
|
PyErr_Clear();
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"object cannot be interpreted as an index");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
res = PyEval_CallObject(func, (PyObject *)NULL);
|
||||||
|
Py_DECREF(func);
|
||||||
|
if (res == NULL)
|
||||||
|
return -1;
|
||||||
|
if (PyInt_Check(res) || PyLong_Check(res)) {
|
||||||
|
outcome = res->ob_type->tp_as_number->nb_index(res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"__index__ must return an int or a long");
|
||||||
|
outcome = -1;
|
||||||
|
}
|
||||||
|
Py_DECREF(res);
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UNARY(instance_invert, "__invert__")
|
UNARY(instance_invert, "__invert__")
|
||||||
UNARY(instance_int, "__int__")
|
UNARY(instance_int, "__int__")
|
||||||
UNARY(instance_long, "__long__")
|
UNARY(instance_long, "__long__")
|
||||||
|
@ -2052,6 +2089,7 @@ static PyNumberMethods instance_as_number = {
|
||||||
(binaryfunc)instance_truediv, /* nb_true_divide */
|
(binaryfunc)instance_truediv, /* nb_true_divide */
|
||||||
(binaryfunc)instance_ifloordiv, /* nb_inplace_floor_divide */
|
(binaryfunc)instance_ifloordiv, /* nb_inplace_floor_divide */
|
||||||
(binaryfunc)instance_itruediv, /* nb_inplace_true_divide */
|
(binaryfunc)instance_itruediv, /* nb_inplace_true_divide */
|
||||||
|
(lenfunc)instance_index, /* nb_index */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyInstance_Type = {
|
PyTypeObject PyInstance_Type = {
|
||||||
|
|
|
@ -1069,6 +1069,7 @@ static PyNumberMethods int_as_number = {
|
||||||
int_true_divide, /* nb_true_divide */
|
int_true_divide, /* nb_true_divide */
|
||||||
0, /* nb_inplace_floor_divide */
|
0, /* nb_inplace_floor_divide */
|
||||||
0, /* nb_inplace_true_divide */
|
0, /* nb_inplace_true_divide */
|
||||||
|
(lenfunc)PyInt_AsSsize_t, /* nb_index */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyInt_Type = {
|
PyTypeObject PyInt_Type = {
|
||||||
|
|
|
@ -2452,11 +2452,14 @@ PyDoc_STRVAR(list_doc,
|
||||||
"list() -> new list\n"
|
"list() -> new list\n"
|
||||||
"list(sequence) -> new list initialized from sequence's items");
|
"list(sequence) -> new list initialized from sequence's items");
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
list_subscript(PyListObject* self, PyObject* item)
|
list_subscript(PyListObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item) || PyLong_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
@ -2503,14 +2506,9 @@ list_subscript(PyListObject* self, PyObject* item)
|
||||||
static int
|
static int
|
||||||
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AS_LONG(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
if (i < 0)
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
i += PyList_GET_SIZE(self);
|
|
||||||
return list_ass_item(self, i, value);
|
|
||||||
}
|
|
||||||
else if (PyLong_Check(item)) {
|
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
@ -241,12 +241,8 @@ PyLong_AsLong(PyObject *vv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a Py_ssize_t from a long int object.
|
static Py_ssize_t
|
||||||
Returns -1 and sets an error condition if overflow occurs. */
|
_long_as_ssize_t(PyObject *vv) {
|
||||||
|
|
||||||
Py_ssize_t
|
|
||||||
_PyLong_AsSsize_t(PyObject *vv)
|
|
||||||
{
|
|
||||||
register PyLongObject *v;
|
register PyLongObject *v;
|
||||||
size_t x, prev;
|
size_t x, prev;
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
|
@ -282,7 +278,45 @@ _PyLong_AsSsize_t(PyObject *vv)
|
||||||
overflow:
|
overflow:
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"long int too large to convert to int");
|
"long int too large to convert to int");
|
||||||
return -1;
|
if (sign > 0)
|
||||||
|
return PY_SSIZE_T_MAX;
|
||||||
|
else
|
||||||
|
return -PY_SSIZE_T_MAX-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a Py_ssize_t from a long int object.
|
||||||
|
Returns -1 and sets an error condition if overflow occurs. */
|
||||||
|
|
||||||
|
Py_ssize_t
|
||||||
|
_PyLong_AsSsize_t(PyObject *vv)
|
||||||
|
{
|
||||||
|
Py_ssize_t x;
|
||||||
|
|
||||||
|
x = _long_as_ssize_t(vv);
|
||||||
|
if (PyErr_Occurred()) return -1;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get a Py_ssize_t from a long int object.
|
||||||
|
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
|
||||||
|
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
|
||||||
|
Return 0 on error, 1 on success.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
long_index(PyObject *vv)
|
||||||
|
{
|
||||||
|
Py_ssize_t x;
|
||||||
|
|
||||||
|
x = _long_as_ssize_t(vv);
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
/* If overflow error, ignore the error */
|
||||||
|
if (x != -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a C unsigned long int from a long int object.
|
/* Get a C unsigned long int from a long int object.
|
||||||
|
@ -3131,6 +3165,7 @@ static PyNumberMethods long_as_number = {
|
||||||
long_true_divide, /* nb_true_divide */
|
long_true_divide, /* nb_true_divide */
|
||||||
0, /* nb_inplace_floor_divide */
|
0, /* nb_inplace_floor_divide */
|
||||||
0, /* nb_inplace_true_divide */
|
0, /* nb_inplace_true_divide */
|
||||||
|
(lenfunc)long_index, /* nb_index */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject PyLong_Type = {
|
PyTypeObject PyLong_Type = {
|
||||||
|
|
|
@ -1187,16 +1187,19 @@ string_hash(PyStringObject *a)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
string_subscript(PyStringObject* self, PyObject* item)
|
string_subscript(PyStringObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item) || PyLong_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i += PyString_GET_SIZE(self);
|
i += PyString_GET_SIZE(self);
|
||||||
return string_item(self,i);
|
return string_item(self, i);
|
||||||
}
|
}
|
||||||
else if (PySlice_Check(item)) {
|
else if (PySlice_Check(item)) {
|
||||||
Py_ssize_t start, stop, step, slicelength, cur, i;
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
||||||
|
|
|
@ -584,11 +584,14 @@ static PySequenceMethods tuple_as_sequence = {
|
||||||
(objobjproc)tuplecontains, /* sq_contains */
|
(objobjproc)tuplecontains, /* sq_contains */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
tuplesubscript(PyTupleObject* self, PyObject* item)
|
tuplesubscript(PyTupleObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item) || PyLong_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
@ -3051,6 +3051,9 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
|
||||||
COPYNUM(nb_inplace_true_divide);
|
COPYNUM(nb_inplace_true_divide);
|
||||||
COPYNUM(nb_inplace_floor_divide);
|
COPYNUM(nb_inplace_floor_divide);
|
||||||
}
|
}
|
||||||
|
if (base->tp_flags & Py_TPFLAGS_HAVE_INDEX) {
|
||||||
|
COPYNUM(nb_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) {
|
if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) {
|
||||||
|
@ -4344,6 +4347,44 @@ slot_nb_nonzero(PyObject *self)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
slot_nb_index(PyObject *self)
|
||||||
|
{
|
||||||
|
PyObject *func, *args;
|
||||||
|
static PyObject *index_str;
|
||||||
|
Py_ssize_t result = -1;
|
||||||
|
|
||||||
|
func = lookup_maybe(self, "__index__", &index_str);
|
||||||
|
if (func == NULL) {
|
||||||
|
if (!PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"object cannot be interpreted as an index");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
args = PyTuple_New(0);
|
||||||
|
if (args != NULL) {
|
||||||
|
PyObject *temp = PyObject_Call(func, args, NULL);
|
||||||
|
Py_DECREF(args);
|
||||||
|
if (temp != NULL) {
|
||||||
|
if (PyInt_Check(temp) || PyLong_Check(temp)) {
|
||||||
|
result =
|
||||||
|
temp->ob_type->tp_as_number->nb_index(temp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"__index__ must return an int or a long");
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
Py_DECREF(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_DECREF(func);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SLOT0(slot_nb_invert, "__invert__")
|
SLOT0(slot_nb_invert, "__invert__")
|
||||||
SLOT1BIN(slot_nb_lshift, nb_lshift, "__lshift__", "__rlshift__")
|
SLOT1BIN(slot_nb_lshift, nb_lshift, "__lshift__", "__rlshift__")
|
||||||
SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__")
|
SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__")
|
||||||
|
@ -5069,6 +5110,8 @@ static slotdef slotdefs[] = {
|
||||||
"oct(x)"),
|
"oct(x)"),
|
||||||
UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
|
UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
|
||||||
"hex(x)"),
|
"hex(x)"),
|
||||||
|
NBSLOT("__index__", nb_index, slot_nb_index, wrap_lenfunc,
|
||||||
|
"x[y:z] <==> x[y.__index__():z.__index__()]"),
|
||||||
IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
|
IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
|
||||||
wrap_binaryfunc, "+"),
|
wrap_binaryfunc, "+"),
|
||||||
IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,
|
IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,
|
||||||
|
|
|
@ -6460,11 +6460,14 @@ static PySequenceMethods unicode_as_sequence = {
|
||||||
(objobjproc)PyUnicode_Contains, /*sq_contains*/
|
(objobjproc)PyUnicode_Contains, /*sq_contains*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
unicode_subscript(PyUnicodeObject* self, PyObject* item)
|
unicode_subscript(PyUnicodeObject* self, PyObject* item)
|
||||||
{
|
{
|
||||||
if (PyInt_Check(item) || PyLong_Check(item)) {
|
PyNumberMethods *nb = item->ob_type->tp_as_number;
|
||||||
Py_ssize_t i = PyInt_AsSsize_t(item);
|
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
|
||||||
|
Py_ssize_t i = nb->nb_index(item);
|
||||||
if (i == -1 && PyErr_Occurred())
|
if (i == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
|
|
|
@ -3916,9 +3916,10 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract a slice index from a PyInt or PyLong, and store in *pi.
|
/* Extract a slice index from a PyInt or PyLong or an object with the
|
||||||
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
|
nb_index slot defined, and store in *pi.
|
||||||
and silently boost values less than -PY_SSIZE_T_MAX to 0.
|
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
|
||||||
|
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
|
||||||
Return 0 on error, 1 on success.
|
Return 0 on error, 1 on success.
|
||||||
*/
|
*/
|
||||||
/* Note: If v is NULL, return success without storing into *pi. This
|
/* Note: If v is NULL, return success without storing into *pi. This
|
||||||
|
@ -3932,46 +3933,18 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
|
||||||
Py_ssize_t x;
|
Py_ssize_t x;
|
||||||
if (PyInt_Check(v)) {
|
if (PyInt_Check(v)) {
|
||||||
x = PyInt_AsLong(v);
|
x = PyInt_AsLong(v);
|
||||||
} else if (PyLong_Check(v)) {
|
}
|
||||||
x = PyInt_AsSsize_t(v);
|
else if (v->ob_type->tp_as_number &&
|
||||||
if (x==-1 && PyErr_Occurred()) {
|
PyType_HasFeature(v->ob_type, Py_TPFLAGS_HAVE_INDEX)
|
||||||
PyObject *long_zero;
|
&& v->ob_type->tp_as_number->nb_index) {
|
||||||
int cmp;
|
x = v->ob_type->tp_as_number->nb_index(v);
|
||||||
|
if (x == -1 && PyErr_Occurred())
|
||||||
if (!PyErr_ExceptionMatches(
|
return 0;
|
||||||
PyExc_OverflowError)) {
|
}
|
||||||
/* It's not an overflow error, so just
|
else {
|
||||||
signal an error */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the OverflowError */
|
|
||||||
PyErr_Clear();
|
|
||||||
|
|
||||||
/* It's an overflow error, so we need to
|
|
||||||
check the sign of the long integer,
|
|
||||||
set the value to PY_SSIZE_T_MAX or
|
|
||||||
-PY_SSIZE_T_MAX, and clear the error. */
|
|
||||||
|
|
||||||
/* Create a long integer with a value of 0 */
|
|
||||||
long_zero = PyLong_FromLong(0L);
|
|
||||||
if (long_zero == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Check sign */
|
|
||||||
cmp = PyObject_RichCompareBool(v, long_zero,
|
|
||||||
Py_GT);
|
|
||||||
Py_DECREF(long_zero);
|
|
||||||
if (cmp < 0)
|
|
||||||
return 0;
|
|
||||||
else if (cmp)
|
|
||||||
x = PY_SSIZE_T_MAX;
|
|
||||||
else
|
|
||||||
x = -PY_SSIZE_T_MAX;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"slice indices must be integers or None");
|
"slice indices must be integers or "
|
||||||
|
"None or have an __index__ method");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*pi = x;
|
*pi = x;
|
||||||
|
@ -3979,8 +3952,11 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ISINT
|
#undef ISINDEX
|
||||||
#define ISINT(x) ((x) == NULL || PyInt_Check(x) || PyLong_Check(x))
|
#define ISINDEX(x) ((x) == NULL || PyInt_Check(x) || PyLong_Check(x) || \
|
||||||
|
((x)->ob_type->tp_as_number && \
|
||||||
|
PyType_HasFeature((x)->ob_type, Py_TPFLAGS_HAVE_INDEX) \
|
||||||
|
&& (x)->ob_type->tp_as_number->nb_index))
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
|
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
|
||||||
|
@ -3988,7 +3964,7 @@ apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
|
||||||
PyTypeObject *tp = u->ob_type;
|
PyTypeObject *tp = u->ob_type;
|
||||||
PySequenceMethods *sq = tp->tp_as_sequence;
|
PySequenceMethods *sq = tp->tp_as_sequence;
|
||||||
|
|
||||||
if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) {
|
if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
|
||||||
Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
|
Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
|
||||||
if (!_PyEval_SliceIndex(v, &ilow))
|
if (!_PyEval_SliceIndex(v, &ilow))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -4015,7 +3991,7 @@ assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
|
||||||
PyTypeObject *tp = u->ob_type;
|
PyTypeObject *tp = u->ob_type;
|
||||||
PySequenceMethods *sq = tp->tp_as_sequence;
|
PySequenceMethods *sq = tp->tp_as_sequence;
|
||||||
|
|
||||||
if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) {
|
if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
|
||||||
Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
|
Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
|
||||||
if (!_PyEval_SliceIndex(v, &ilow))
|
if (!_PyEval_SliceIndex(v, &ilow))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue