diff options
author | Armin Rigo <arigo@tunes.org> | 2005-12-29 15:59:19 (GMT) |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2005-12-29 15:59:19 (GMT) |
commit | fd163f92cee2aa8189879bd43670782f4cfd2cf8 (patch) | |
tree | 9bd3785dde016396b17a006059c68b3e4b60023e /Objects/abstract.c | |
parent | c4308d5be64a622ee7be685c5eb05f90782711c1 (diff) | |
download | cpython-fd163f92cee2aa8189879bd43670782f4cfd2cf8.zip cpython-fd163f92cee2aa8189879bd43670782f4cfd2cf8.tar.gz cpython-fd163f92cee2aa8189879bd43670782f4cfd2cf8.tar.bz2 |
SF patch #1390657:
* set sq_repeat and sq_concat to NULL for user-defined new-style
classes, as a way to fix a number of related problems. See
test_descr.notimplemented()). One of these problems was fixed
in r25556 and r25557 but many more existed; this is a general
fix and thus reverts r25556-r25557.
* to avoid having PySequence_Repeat()/PySequence_Concat() failing
on user-defined classes, they now fall back to nb_add/nb_mul if
sq_concat/sq_repeat are not defined and the arguments appear to
be sequences.
* added tests.
Backport candidate.
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r-- | Objects/abstract.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 1f8feb5..6e070a9 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -635,14 +635,11 @@ PyNumber_Add(PyObject *v, PyObject *w) PyObject *result = binary_op1(v, w, NB_SLOT(nb_add)); if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; + Py_DECREF(result); if (m && m->sq_concat) { - Py_DECREF(result); - result = (*m->sq_concat)(v, w); + return (*m->sq_concat)(v, w); } - if (result == Py_NotImplemented) { - Py_DECREF(result); - return binop_type_error(v, w, "+"); - } + result = binop_type_error(v, w, "+"); } return result; } @@ -1144,6 +1141,15 @@ PySequence_Concat(PyObject *s, PyObject *o) if (m && m->sq_concat) return m->sq_concat(s, o); + /* Instances of user classes defining an __add__() method only + have an nb_add slot, not an sq_concat slot. So we fall back + to nb_add if both arguments appear to be sequences. */ + if (PySequence_Check(s) && PySequence_Check(o)) { + PyObject *result = binary_op1(s, o, NB_SLOT(nb_add)); + if (result != Py_NotImplemented) + return result; + Py_DECREF(result); + } return type_error("object can't be concatenated"); } @@ -1159,6 +1165,20 @@ PySequence_Repeat(PyObject *o, int count) if (m && m->sq_repeat) return m->sq_repeat(o, count); + /* Instances of user classes defining a __mul__() method only + have an nb_multiply slot, not an sq_repeat slot. so we fall back + to nb_multiply if o appears to be a sequence. */ + if (PySequence_Check(o)) { + PyObject *n, *result; + n = PyInt_FromLong(count); + if (n == NULL) + return NULL; + result = binary_op1(o, n, NB_SLOT(nb_multiply)); + Py_DECREF(n); + if (result != Py_NotImplemented) + return result; + Py_DECREF(result); + } return type_error("object can't be repeated"); } @@ -1176,6 +1196,13 @@ PySequence_InPlaceConcat(PyObject *s, PyObject *o) if (m && m->sq_concat) return m->sq_concat(s, o); + if (PySequence_Check(s) && PySequence_Check(o)) { + PyObject *result = binary_iop1(s, o, NB_SLOT(nb_inplace_add), + NB_SLOT(nb_add)); + if (result != Py_NotImplemented) + return result; + Py_DECREF(result); + } return type_error("object can't be concatenated"); } @@ -1193,6 +1220,18 @@ PySequence_InPlaceRepeat(PyObject *o, int count) if (m && m->sq_repeat) return m->sq_repeat(o, count); + if (PySequence_Check(o)) { + PyObject *n, *result; + n = PyInt_FromLong(count); + if (n == NULL) + return NULL; + result = binary_iop1(o, n, NB_SLOT(nb_inplace_multiply), + NB_SLOT(nb_multiply)); + Py_DECREF(n); + if (result != Py_NotImplemented) + return result; + Py_DECREF(result); + } return type_error("object can't be repeated"); } |