diff options
Diffstat (limited to 'Objects/abstract.c')
| -rw-r--r-- | Objects/abstract.c | 101 |
1 files changed, 80 insertions, 21 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 9ed3f92..d7dde91 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -260,8 +260,7 @@ PyObject_AsCharBuffer(PyObject *obj, pb = obj->ob_type->tp_as_buffer; if (pb == NULL || pb->bf_getbuffer == NULL) { PyErr_SetString(PyExc_TypeError, - "expected bytes, bytearray " - "or buffer compatible object"); + "expected a bytes-like object"); return -1; } if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1; @@ -306,7 +305,7 @@ int PyObject_AsReadBuffer(PyObject *obj, if (pb == NULL || pb->bf_getbuffer == NULL) { PyErr_SetString(PyExc_TypeError, - "expected an object with a buffer interface"); + "expected a bytes-like object"); return -1; } @@ -336,7 +335,7 @@ int PyObject_AsWriteBuffer(PyObject *obj, pb->bf_getbuffer == NULL || ((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) { PyErr_SetString(PyExc_TypeError, - "expected an object with a writable buffer interface"); + "expected a writable bytes-like object"); return -1; } @@ -355,7 +354,7 @@ PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { if (!PyObject_CheckBuffer(obj)) { PyErr_Format(PyExc_TypeError, - "'%.100s' does not support the buffer interface", + "a bytes-like object is required, not '%.100s'", Py_TYPE(obj)->tp_name); return -1; } @@ -368,16 +367,35 @@ _IsFortranContiguous(const Py_buffer *view) Py_ssize_t sd, dim; int i; - if (view->ndim == 0) return 1; - if (view->strides == NULL) return (view->ndim == 1); + /* 1) len = product(shape) * itemsize + 2) itemsize > 0 + 3) len = 0 <==> exists i: shape[i] = 0 */ + if (view->len == 0) return 1; + if (view->strides == NULL) { /* C-contiguous by definition */ + /* Trivially F-contiguous */ + if (view->ndim <= 1) return 1; + + /* ndim > 1 implies shape != NULL */ + assert(view->shape != NULL); + + /* Effectively 1-d */ + sd = 0; + for (i=0; i<view->ndim; i++) { + if (view->shape[i] > 1) sd += 1; + } + return sd <= 1; + } + + /* strides != NULL implies both of these */ + assert(view->ndim > 0); + assert(view->shape != NULL); sd = view->itemsize; - if (view->ndim == 1) return (view->shape[0] == 1 || - sd == view->strides[0]); for (i=0; i<view->ndim; i++) { dim = view->shape[i]; - if (dim == 0) return 1; - if (view->strides[i] != sd) return 0; + if (dim > 1 && view->strides[i] != sd) { + return 0; + } sd *= dim; } return 1; @@ -389,16 +407,22 @@ _IsCContiguous(const Py_buffer *view) Py_ssize_t sd, dim; int i; - if (view->ndim == 0) return 1; - if (view->strides == NULL) return 1; + /* 1) len = product(shape) * itemsize + 2) itemsize > 0 + 3) len = 0 <==> exists i: shape[i] = 0 */ + if (view->len == 0) return 1; + if (view->strides == NULL) return 1; /* C-contiguous by definition */ + + /* strides != NULL implies both of these */ + assert(view->ndim > 0); + assert(view->shape != NULL); sd = view->itemsize; - if (view->ndim == 1) return (view->shape[0] == 1 || - sd == view->strides[0]); for (i=view->ndim-1; i>=0; i--) { dim = view->shape[i]; - if (dim == 0) return 1; - if (view->strides[i] != sd) return 0; + if (dim > 1 && view->strides[i] != sd) { + return 0; + } sd *= dim; } return 1; @@ -530,8 +554,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src) if (!PyObject_CheckBuffer(dest) || !PyObject_CheckBuffer(src)) { PyErr_SetString(PyExc_TypeError, - "both destination and source must have the "\ - "buffer interface"); + "both destination and source must be "\ + "bytes-like objects"); return -1; } @@ -687,8 +711,9 @@ PyObject_Format(PyObject *obj, PyObject *format_spec) Py_DECREF(meth); if (result && !PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "__format__ method did not return string"); + PyErr_Format(PyExc_TypeError, + "__format__ must return a str, not %.200s", + Py_TYPE(result)->tp_name); Py_DECREF(result); result = NULL; goto done; @@ -932,6 +957,12 @@ PyNumber_Multiply(PyObject *v, PyObject *w) } PyObject * +PyNumber_MatrixMultiply(PyObject *v, PyObject *w) +{ + return binary_op(v, w, NB_SLOT(nb_matrix_multiply), "@"); +} + +PyObject * PyNumber_FloorDivide(PyObject *v, PyObject *w) { return binary_op(v, w, NB_SLOT(nb_floor_divide), "//"); @@ -1012,6 +1043,7 @@ INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=") INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=") INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=") INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=") +INPLACE_BINOP(PyNumber_InMatrixMultiply, nb_inplace_matrix_multiply, nb_matrix_multiply, "@=") PyObject * PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w) @@ -1078,6 +1110,13 @@ PyNumber_InPlaceMultiply(PyObject *v, PyObject *w) } PyObject * +PyNumber_InPlaceMatrixMultiply(PyObject *v, PyObject *w) +{ + return binary_iop(v, w, NB_SLOT(nb_inplace_matrix_multiply), + NB_SLOT(nb_matrix_multiply), "@="); +} + +PyObject * PyNumber_InPlaceRemainder(PyObject *v, PyObject *w) { return binary_iop(v, w, NB_SLOT(nb_inplace_remainder), @@ -2060,6 +2099,11 @@ PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { ternaryfunc call; + /* PyObject_Call() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller looses its exception */ + assert(!PyErr_Occurred()); + if ((call = func->ob_type->tp_call) != NULL) { PyObject *result; if (Py_EnterRecursiveCall(" while calling a Python object")) @@ -2519,6 +2563,11 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) if (Py_TYPE(inst) == (PyTypeObject *)cls) return 1; + /* We know what type's __instancecheck__ does. */ + if (PyType_CheckExact(cls)) { + return recursive_isinstance(inst, cls); + } + if (PyTuple_Check(cls)) { Py_ssize_t i; Py_ssize_t n; @@ -2557,6 +2606,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) } else if (PyErr_Occurred()) return -1; + /* Probably never reached anymore. */ return recursive_isinstance(inst, cls); } @@ -2584,6 +2634,14 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls) _Py_IDENTIFIER(__subclasscheck__); PyObject *checker; + /* We know what type's __subclasscheck__ does. */ + if (PyType_CheckExact(cls)) { + /* Quick test for an exact match */ + if (derived == cls) + return 1; + return recursive_issubclass(derived, cls); + } + if (PyTuple_Check(cls)) { Py_ssize_t i; Py_ssize_t n; @@ -2622,6 +2680,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls) } else if (PyErr_Occurred()) return -1; + /* Probably never reached anymore. */ return recursive_issubclass(derived, cls); } |
