diff options
author | Brett Cannon <brett@python.org> | 2012-03-06 20:33:24 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2012-03-06 20:33:24 (GMT) |
commit | f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24 (patch) | |
tree | ceed84488164142e5884411566de19f66702c3e7 /Modules | |
parent | 0d4d410b2d6891520b1772a85f5ebdf926a0c77e (diff) | |
parent | 0119e4753eec50f671ee716af202b4a1ca28deef (diff) | |
download | cpython-f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24.zip cpython-f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24.tar.gz cpython-f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24.tar.bz2 |
merge
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_elementtree.c | 250 | ||||
-rw-r--r-- | Modules/_multiprocessing/win32_functions.c | 69 | ||||
-rw-r--r-- | Modules/_pickle.c | 39 | ||||
-rw-r--r-- | Modules/_testbuffer.c | 174 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 19 | ||||
-rw-r--r-- | Modules/mmapmodule.c | 28 | ||||
-rw-r--r-- | Modules/signalmodule.c | 11 |
7 files changed, 405 insertions, 185 deletions
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 78d8177..348fefc 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -191,7 +191,7 @@ list_join(PyObject* list) } /* -------------------------------------------------------------------- */ -/* the element type */ +/* the Element type */ typedef struct { @@ -236,10 +236,10 @@ static PyTypeObject Element_Type; #define Element_CheckExact(op) (Py_TYPE(op) == &Element_Type) /* -------------------------------------------------------------------- */ -/* element constructor and destructor */ +/* Element constructors and destructor */ LOCAL(int) -element_new_extra(ElementObject* self, PyObject* attrib) +create_extra(ElementObject* self, PyObject* attrib) { self->extra = PyObject_Malloc(sizeof(ElementObjectExtra)); if (!self->extra) @@ -259,7 +259,7 @@ element_new_extra(ElementObject* self, PyObject* attrib) } LOCAL(void) -element_dealloc_extra(ElementObject* self) +dealloc_extra(ElementObject* self) { int i; @@ -274,8 +274,11 @@ element_dealloc_extra(ElementObject* self) PyObject_Free(self->extra); } +/* Convenience internal function to create new Element objects with the given + * tag and attributes. +*/ LOCAL(PyObject*) -element_new(PyObject* tag, PyObject* attrib) +create_new_element(PyObject* tag, PyObject* attrib) { ElementObject* self; @@ -290,16 +293,10 @@ element_new(PyObject* tag, PyObject* attrib) self->extra = NULL; if (attrib != Py_None) { - - if (element_new_extra(self, attrib) < 0) { + if (create_extra(self, attrib) < 0) { PyObject_Del(self); return NULL; } - - self->extra->length = 0; - self->extra->allocated = STATIC_CHILDREN; - self->extra->children = self->extra->_children; - } Py_INCREF(tag); @@ -316,6 +313,86 @@ element_new(PyObject* tag, PyObject* attrib) return (PyObject*) self; } +static PyObject * +element_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + ElementObject *e = (ElementObject *)type->tp_alloc(type, 0); + if (e != NULL) { + Py_INCREF(Py_None); + e->tag = Py_None; + + Py_INCREF(Py_None); + e->text = Py_None; + + Py_INCREF(Py_None); + e->tail = Py_None; + + e->extra = NULL; + } + return (PyObject *)e; +} + +static int +element_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *tag; + PyObject *tmp; + PyObject *attrib = NULL; + ElementObject *self_elem; + + if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib)) + return -1; + + if (attrib || kwds) { + attrib = (attrib) ? PyDict_Copy(attrib) : PyDict_New(); + if (!attrib) + return -1; + if (kwds) + PyDict_Update(attrib, kwds); + } else { + Py_INCREF(Py_None); + attrib = Py_None; + } + + self_elem = (ElementObject *)self; + + /* Use None for empty dictionaries */ + if (PyDict_CheckExact(attrib) && PyDict_Size(attrib) == 0) { + Py_INCREF(Py_None); + attrib = Py_None; + } + + if (attrib != Py_None) { + if (create_extra(self_elem, attrib) < 0) { + PyObject_Del(self_elem); + return -1; + } + } + + /* If create_extra needed attrib, it took a reference to it, so we can + * release ours anyway. + */ + Py_DECREF(attrib); + + /* Replace the objects already pointed to by tag, text and tail. */ + tmp = self_elem->tag; + self_elem->tag = tag; + Py_INCREF(tag); + Py_DECREF(tmp); + + tmp = self_elem->text; + self_elem->text = Py_None; + Py_INCREF(Py_None); + Py_DECREF(JOIN_OBJ(tmp)); + + tmp = self_elem->tail; + self_elem->tail = Py_None; + Py_INCREF(Py_None); + Py_DECREF(JOIN_OBJ(tmp)); + + return 0; +} + LOCAL(int) element_resize(ElementObject* self, int extra) { @@ -326,7 +403,7 @@ element_resize(ElementObject* self, int extra) elements. set an exception and return -1 if allocation failed */ if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); size = self->extra->length + extra; @@ -444,35 +521,6 @@ element_get_tail(ElementObject* self) } static PyObject* -element(PyObject* self, PyObject* args, PyObject* kw) -{ - PyObject* elem; - - PyObject* tag; - PyObject* attrib = NULL; - if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, - &PyDict_Type, &attrib)) - return NULL; - - if (attrib || kw) { - attrib = (attrib) ? PyDict_Copy(attrib) : PyDict_New(); - if (!attrib) - return NULL; - if (kw) - PyDict_Update(attrib, kw); - } else { - Py_INCREF(Py_None); - attrib = Py_None; - } - - elem = element_new(tag, attrib); - - Py_DECREF(attrib); - - return elem; -} - -static PyObject* subelement(PyObject* self, PyObject* args, PyObject* kw) { PyObject* elem; @@ -496,7 +544,7 @@ subelement(PyObject* self, PyObject* args, PyObject* kw) attrib = Py_None; } - elem = element_new(tag, attrib); + elem = create_new_element(tag, attrib); Py_DECREF(attrib); @@ -512,7 +560,7 @@ static void element_dealloc(ElementObject* self) { if (self->extra) - element_dealloc_extra(self); + dealloc_extra(self); /* discard attributes */ Py_DECREF(self->tag); @@ -521,7 +569,7 @@ element_dealloc(ElementObject* self) RELEASE(sizeof(ElementObject), "destroy element"); - PyObject_Del(self); + Py_TYPE(self)->tp_free((PyObject *)self); } /* -------------------------------------------------------------------- */ @@ -547,7 +595,7 @@ element_clear(ElementObject* self, PyObject* args) return NULL; if (self->extra) { - element_dealloc_extra(self); + dealloc_extra(self); self->extra = NULL; } @@ -571,7 +619,7 @@ element_copy(ElementObject* self, PyObject* args) if (!PyArg_ParseTuple(args, ":__copy__")) return NULL; - element = (ElementObject*) element_new( + element = (ElementObject*) create_new_element( self->tag, (self->extra) ? self->extra->attrib : Py_None ); if (!element) @@ -634,7 +682,7 @@ element_deepcopy(ElementObject* self, PyObject* args) attrib = Py_None; } - element = (ElementObject*) element_new(tag, attrib); + element = (ElementObject*) create_new_element(tag, attrib); Py_DECREF(tag); Py_DECREF(attrib); @@ -1029,7 +1077,7 @@ element_insert(ElementObject* self, PyObject* args) return NULL; if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); if (index < 0) { index += self->extra->length; @@ -1100,7 +1148,7 @@ element_makeelement(PyObject* self, PyObject* args, PyObject* kw) if (!attrib) return NULL; - elem = element_new(tag, attrib); + elem = create_new_element(tag, attrib); Py_DECREF(attrib); @@ -1154,7 +1202,10 @@ element_remove(ElementObject* self, PyObject* args) static PyObject* element_repr(ElementObject* self) { - return PyUnicode_FromFormat("<Element %R at %p>", self->tag, self); + if (self->tag) + return PyUnicode_FromFormat("<Element %R at %p>", self->tag, self); + else + return PyUnicode_FromFormat("<Element at %p>", self); } static PyObject* @@ -1168,7 +1219,7 @@ element_set(ElementObject* self, PyObject* args) return NULL; if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); attrib = element_get_attrib(self); if (!attrib) @@ -1284,7 +1335,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) PyObject* seq = NULL; if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); if (PySlice_GetIndicesEx(item, self->extra->length, @@ -1448,7 +1499,7 @@ element_getattro(ElementObject* self, PyObject* nameobj) } else if (strcmp(name, "attrib") == 0) { PyErr_Clear(); if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); res = element_get_attrib(self); } @@ -1484,7 +1535,7 @@ element_setattr(ElementObject* self, const char* name, PyObject* value) Py_INCREF(self->tail); } else if (strcmp(name, "attrib") == 0) { if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); Py_DECREF(self->extra->attrib); self->extra->attrib = value; Py_INCREF(self->extra->attrib); @@ -1516,31 +1567,41 @@ static PyTypeObject Element_Type = { PyVarObject_HEAD_INIT(NULL, 0) "Element", sizeof(ElementObject), 0, /* methods */ - (destructor)element_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - (setattrfunc)element_setattr, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)element_repr, /* tp_repr */ - 0, /* tp_as_number */ - &element_as_sequence, /* tp_as_sequence */ - &element_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - (getattrofunc)element_getattro, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - element_methods, /* tp_methods */ - 0, /* tp_members */ + (destructor)element_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + (setattrfunc)element_setattr, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)element_repr, /* tp_repr */ + 0, /* tp_as_number */ + &element_as_sequence, /* tp_as_sequence */ + &element_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + (getattrofunc)element_getattro, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + element_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)element_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + element_new, /* tp_new */ + 0, /* tp_free */ }; /* ==================================================================== */ @@ -1638,13 +1699,6 @@ treebuilder_dealloc(TreeBuilderObject* self) /* handlers */ LOCAL(PyObject*) -treebuilder_handle_xml(TreeBuilderObject* self, PyObject* encoding, - PyObject* standalone) -{ - Py_RETURN_NONE; -} - -LOCAL(PyObject*) treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, PyObject* attrib) { @@ -1666,7 +1720,7 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, self->data = NULL; } - node = element_new(tag, attrib); + node = create_new_element(tag, attrib); if (!node) return NULL; @@ -1915,22 +1969,10 @@ treebuilder_start(TreeBuilderObject* self, PyObject* args) return treebuilder_handle_start(self, tag, attrib); } -static PyObject* -treebuilder_xml(TreeBuilderObject* self, PyObject* args) -{ - PyObject* encoding; - PyObject* standalone; - if (!PyArg_ParseTuple(args, "OO:xml", &encoding, &standalone)) - return NULL; - - return treebuilder_handle_xml(self, encoding, standalone); -} - static PyMethodDef treebuilder_methods[] = { {"data", (PyCFunction) treebuilder_data, METH_VARARGS}, {"start", (PyCFunction) treebuilder_start, METH_VARARGS}, {"end", (PyCFunction) treebuilder_end, METH_VARARGS}, - {"xml", (PyCFunction) treebuilder_xml, METH_VARARGS}, {"close", (PyCFunction) treebuilder_close, METH_VARARGS}, {NULL, NULL} }; @@ -1991,8 +2033,6 @@ typedef struct { PyObject* names; - PyObject* handle_xml; - PyObject* handle_start; PyObject* handle_data; PyObject* handle_end; @@ -2445,7 +2485,6 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw) Py_INCREF(target); self->target = target; - self->handle_xml = PyObject_GetAttrString(target, "xml"); self->handle_start = PyObject_GetAttrString(target, "start"); self->handle_data = PyObject_GetAttrString(target, "data"); self->handle_end = PyObject_GetAttrString(target, "end"); @@ -2501,7 +2540,6 @@ xmlparser_dealloc(XMLParserObject* self) Py_XDECREF(self->handle_end); Py_XDECREF(self->handle_data); Py_XDECREF(self->handle_start); - Py_XDECREF(self->handle_xml); Py_DECREF(self->target); Py_DECREF(self->entity); @@ -2801,7 +2839,6 @@ static PyTypeObject XMLParser_Type = { /* python module interface */ static PyMethodDef _functions[] = { - {"Element", (PyCFunction) element, METH_VARARGS|METH_KEYWORDS}, {"SubElement", (PyCFunction) subelement, METH_VARARGS|METH_KEYWORDS}, {"TreeBuilder", (PyCFunction) treebuilder, METH_VARARGS}, #if defined(USE_EXPAT) @@ -2911,5 +2948,8 @@ PyInit__elementtree(void) Py_INCREF(elementtree_parseerror_obj); PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); + Py_INCREF((PyObject *)&Element_Type); + PyModule_AddObject(m, "Element", (PyObject *)&Element_Type); + return m; } diff --git a/Modules/_multiprocessing/win32_functions.c b/Modules/_multiprocessing/win32_functions.c index 15aeeda..93c8fc9 100644 --- a/Modules/_multiprocessing/win32_functions.c +++ b/Modules/_multiprocessing/win32_functions.c @@ -60,16 +60,18 @@ typedef struct { static void overlapped_dealloc(OverlappedObject *self) { + DWORD bytes; int err = GetLastError(); if (self->pending) { - if (check_CancelIoEx()) - Py_CancelIoEx(self->handle, &self->overlapped); - else { - PyErr_SetString(PyExc_RuntimeError, - "I/O operations still in flight while destroying " - "Overlapped object, the process may crash"); - PyErr_WriteUnraisable(NULL); - } + /* make it a programming error to deallocate while operation + is pending, even if we can safely cancel it */ + if (check_CancelIoEx() && + Py_CancelIoEx(self->handle, &self->overlapped)) + GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE); + PyErr_SetString(PyExc_RuntimeError, + "I/O operations still in flight while destroying " + "Overlapped object, the process may crash"); + PyErr_WriteUnraisable(NULL); } CloseHandle(self->overlapped.hEvent); SetLastError(err); @@ -85,6 +87,7 @@ overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj) int wait; BOOL res; DWORD transferred = 0; + DWORD err; wait = PyObject_IsTrue(waitobj); if (wait < 0) @@ -94,23 +97,27 @@ overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj) wait != 0); Py_END_ALLOW_THREADS - if (!res) { - int err = GetLastError(); - if (err == ERROR_IO_INCOMPLETE) - Py_RETURN_NONE; - if (err != ERROR_MORE_DATA) { + err = res ? ERROR_SUCCESS : GetLastError(); + switch (err) { + case ERROR_SUCCESS: + case ERROR_MORE_DATA: + case ERROR_OPERATION_ABORTED: + self->completed = 1; + self->pending = 0; + break; + case ERROR_IO_INCOMPLETE: + break; + default: self->pending = 0; return PyErr_SetExcFromWindowsErr(PyExc_IOError, err); - } } - self->pending = 0; - self->completed = 1; - if (self->read_buffer) { + if (self->completed && self->read_buffer != NULL) { assert(PyBytes_CheckExact(self->read_buffer)); - if (_PyBytes_Resize(&self->read_buffer, transferred)) + if (transferred != PyBytes_GET_SIZE(self->read_buffer) && + _PyBytes_Resize(&self->read_buffer, transferred)) return NULL; } - return Py_BuildValue("lN", (long) transferred, PyBool_FromLong(res)); + return Py_BuildValue("II", (unsigned) transferred, (unsigned) err); } static PyObject * @@ -522,9 +529,10 @@ win32_WriteFile(PyObject *self, PyObject *args, PyObject *kwds) HANDLE handle; Py_buffer _buf, *buf; PyObject *bufobj; - int written; + DWORD written; BOOL ret; int use_overlapped = 0; + DWORD err; OverlappedObject *overlapped = NULL; static char *kwlist[] = {"handle", "buffer", "overlapped", NULL}; @@ -553,8 +561,9 @@ win32_WriteFile(PyObject *self, PyObject *args, PyObject *kwds) overlapped ? &overlapped->overlapped : NULL); Py_END_ALLOW_THREADS + err = ret ? 0 : GetLastError(); + if (overlapped) { - int err = GetLastError(); if (!ret) { if (err == ERROR_IO_PENDING) overlapped->pending = 1; @@ -563,13 +572,13 @@ win32_WriteFile(PyObject *self, PyObject *args, PyObject *kwds) return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); } } - return (PyObject *) overlapped; + return Py_BuildValue("NI", (PyObject *) overlapped, err); } PyBuffer_Release(buf); if (!ret) return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); - return PyLong_FromLong(written); + return Py_BuildValue("II", written, err); } static PyObject * @@ -581,6 +590,7 @@ win32_ReadFile(PyObject *self, PyObject *args, PyObject *kwds) PyObject *buf; BOOL ret; int use_overlapped = 0; + DWORD err; OverlappedObject *overlapped = NULL; static char *kwlist[] = {"handle", "size", "overlapped", NULL}; @@ -607,8 +617,9 @@ win32_ReadFile(PyObject *self, PyObject *args, PyObject *kwds) overlapped ? &overlapped->overlapped : NULL); Py_END_ALLOW_THREADS + err = ret ? 0 : GetLastError(); + if (overlapped) { - int err = GetLastError(); if (!ret) { if (err == ERROR_IO_PENDING) overlapped->pending = 1; @@ -617,16 +628,16 @@ win32_ReadFile(PyObject *self, PyObject *args, PyObject *kwds) return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); } } - return (PyObject *) overlapped; + return Py_BuildValue("NI", (PyObject *) overlapped, err); } - if (!ret && GetLastError() != ERROR_MORE_DATA) { + if (!ret && err != ERROR_MORE_DATA) { Py_DECREF(buf); return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0); } if (_PyBytes_Resize(&buf, nread)) return NULL; - return Py_BuildValue("NN", buf, PyBool_FromLong(ret)); + return Py_BuildValue("NI", buf, err); } static PyObject * @@ -783,7 +794,11 @@ create_win32_namespace(void) WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); WIN32_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE); + WIN32_CONSTANT(F_DWORD, ERROR_IO_PENDING); + WIN32_CONSTANT(F_DWORD, ERROR_MORE_DATA); + WIN32_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); WIN32_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); + WIN32_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED); WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); diff --git a/Modules/_pickle.c b/Modules/_pickle.c index a0c1029..2dc3a41 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -319,6 +319,7 @@ typedef struct PicklerObject { objects to support self-referential objects pickling. */ PyObject *pers_func; /* persistent_id() method, can be NULL */ + PyObject *dispatch_table; /* private dispatch_table, can be NULL */ PyObject *arg; PyObject *write; /* write() method of the output stream. */ @@ -764,6 +765,7 @@ _Pickler_New(void) return NULL; self->pers_func = NULL; + self->dispatch_table = NULL; self->arg = NULL; self->write = NULL; self->proto = 0; @@ -3176,17 +3178,24 @@ save(PicklerObject *self, PyObject *obj, int pers_save) /* XXX: This part needs some unit tests. */ /* Get a reduction callable, and call it. This may come from - * copyreg.dispatch_table, the object's __reduce_ex__ method, - * or the object's __reduce__ method. + * self.dispatch_table, copyreg.dispatch_table, the object's + * __reduce_ex__ method, or the object's __reduce__ method. */ - reduce_func = PyDict_GetItem(dispatch_table, (PyObject *)type); + if (self->dispatch_table == NULL) { + reduce_func = PyDict_GetItem(dispatch_table, (PyObject *)type); + /* PyDict_GetItem() unlike PyObject_GetItem() and + PyObject_GetAttr() returns a borrowed ref */ + Py_XINCREF(reduce_func); + } else { + reduce_func = PyObject_GetItem(self->dispatch_table, (PyObject *)type); + if (reduce_func == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_Clear(); + else + goto error; + } + } if (reduce_func != NULL) { - /* Here, the reference count of the reduce_func object returned by - PyDict_GetItem needs to be increased to be consistent with the one - returned by PyObject_GetAttr. This is allow us to blindly DECREF - reduce_func at the end of the save() routine. - */ - Py_INCREF(reduce_func); Py_INCREF(obj); reduce_value = _Pickler_FastCall(self, reduce_func, obj); } @@ -3359,6 +3368,7 @@ Pickler_dealloc(PicklerObject *self) Py_XDECREF(self->output_buffer); Py_XDECREF(self->write); Py_XDECREF(self->pers_func); + Py_XDECREF(self->dispatch_table); Py_XDECREF(self->arg); Py_XDECREF(self->fast_memo); @@ -3372,6 +3382,7 @@ Pickler_traverse(PicklerObject *self, visitproc visit, void *arg) { Py_VISIT(self->write); Py_VISIT(self->pers_func); + Py_VISIT(self->dispatch_table); Py_VISIT(self->arg); Py_VISIT(self->fast_memo); return 0; @@ -3383,6 +3394,7 @@ Pickler_clear(PicklerObject *self) Py_CLEAR(self->output_buffer); Py_CLEAR(self->write); Py_CLEAR(self->pers_func); + Py_CLEAR(self->dispatch_table); Py_CLEAR(self->arg); Py_CLEAR(self->fast_memo); @@ -3427,6 +3439,7 @@ Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds) PyObject *proto_obj = NULL; PyObject *fix_imports = Py_True; _Py_IDENTIFIER(persistent_id); + _Py_IDENTIFIER(dispatch_table); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO:Pickler", kwlist, &file, &proto_obj, &fix_imports)) @@ -3468,6 +3481,13 @@ Pickler_init(PicklerObject *self, PyObject *args, PyObject *kwds) if (self->pers_func == NULL) return -1; } + self->dispatch_table = NULL; + if (_PyObject_HasAttrId((PyObject *)self, &PyId_dispatch_table)) { + self->dispatch_table = _PyObject_GetAttrId((PyObject *)self, + &PyId_dispatch_table); + if (self->dispatch_table == NULL) + return -1; + } return 0; } @@ -3749,6 +3769,7 @@ Pickler_set_persid(PicklerObject *self, PyObject *value) static PyMemberDef Pickler_members[] = { {"bin", T_INT, offsetof(PicklerObject, bin)}, {"fast", T_INT, offsetof(PicklerObject, fast)}, + {"dispatch_table", T_OBJECT_EX, offsetof(PicklerObject, dispatch_table)}, {NULL} }; diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c index 39a7bcc..cc4aea8 100644 --- a/Modules/_testbuffer.c +++ b/Modules/_testbuffer.c @@ -44,23 +44,21 @@ static PyTypeObject NDArray_Type; #define ADJUST_PTR(ptr, suboffsets) \ (HAVE_PTR(suboffsets) ? *((char**)ptr) + suboffsets[0] : ptr) +/* Default: NumPy style (strides), read-only, no var-export, C-style layout */ +#define ND_DEFAULT 0x000 /* User configurable flags for the ndarray */ -#define ND_VAREXPORT 0x001 /* change layout while buffers are exported */ - +#define ND_VAREXPORT 0x001 /* change layout while buffers are exported */ /* User configurable flags for each base buffer */ -#define ND_WRITABLE 0x002 /* mark base buffer as writable */ -#define ND_FORTRAN 0x004 /* Fortran contiguous layout */ -#define ND_SCALAR 0x008 /* scalar: ndim = 0 */ -#define ND_PIL 0x010 /* convert to PIL-style array (suboffsets) */ -#define ND_GETBUF_FAIL 0x020 /* test issue 7385 */ - -/* Default: NumPy style (strides), read-only, no var-export, C-style layout */ -#define ND_DEFAULT 0x0 - +#define ND_WRITABLE 0x002 /* mark base buffer as writable */ +#define ND_FORTRAN 0x004 /* Fortran contiguous layout */ +#define ND_SCALAR 0x008 /* scalar: ndim = 0 */ +#define ND_PIL 0x010 /* convert to PIL-style array (suboffsets) */ +#define ND_REDIRECT 0x020 /* redirect buffer requests */ +#define ND_GETBUF_FAIL 0x040 /* trigger getbuffer failure */ +#define ND_GETBUF_UNDEFINED 0x080 /* undefined view.obj */ /* Internal flags for the base buffer */ -#define ND_C 0x040 /* C contiguous layout (default) */ -#define ND_OWN_ARRAYS 0x080 /* consumer owns arrays */ -#define ND_UNUSED 0x100 /* initializer */ +#define ND_C 0x100 /* C contiguous layout (default) */ +#define ND_OWN_ARRAYS 0x200 /* consumer owns arrays */ /* ndarray properties */ #define ND_IS_CONSUMER(nd) \ @@ -1290,7 +1288,7 @@ ndarray_init(PyObject *self, PyObject *args, PyObject *kwds) PyObject *strides = NULL; /* number of bytes to the next elt in each dim */ Py_ssize_t offset = 0; /* buffer offset */ PyObject *format = simple_format; /* struct module specifier: "B" */ - int flags = ND_UNUSED; /* base buffer and ndarray flags */ + int flags = ND_DEFAULT; /* base buffer and ndarray flags */ int getbuf = PyBUF_UNUSED; /* re-exporter: getbuffer request flags */ @@ -1302,10 +1300,10 @@ ndarray_init(PyObject *self, PyObject *args, PyObject *kwds) /* NDArrayObject is re-exporter */ if (PyObject_CheckBuffer(v) && shape == NULL) { if (strides || offset || format != simple_format || - flags != ND_UNUSED) { + !(flags == ND_DEFAULT || flags == ND_REDIRECT)) { PyErr_SetString(PyExc_TypeError, - "construction from exporter object only takes a single " - "additional getbuf argument"); + "construction from exporter object only takes 'obj', 'getbuf' " + "and 'flags' arguments"); return -1; } @@ -1315,6 +1313,7 @@ ndarray_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; init_flags(nd->head); + nd->head->flags |= flags; return 0; } @@ -1333,8 +1332,6 @@ ndarray_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; } - if (flags == ND_UNUSED) - flags = ND_DEFAULT; if (flags & ND_VAREXPORT) { nd->flags |= ND_VAREXPORT; flags &= ~ND_VAREXPORT; @@ -1357,7 +1354,7 @@ ndarray_push(PyObject *self, PyObject *args, PyObject *kwds) PyObject *strides = NULL; /* number of bytes to the next elt in each dim */ PyObject *format = simple_format; /* struct module specifier: "B" */ Py_ssize_t offset = 0; /* buffer offset */ - int flags = ND_UNUSED; /* base buffer flags */ + int flags = ND_DEFAULT; /* base buffer flags */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OnOi", kwlist, &items, &shape, &strides, &offset, &format, &flags)) @@ -1423,6 +1420,11 @@ ndarray_getbuf(NDArrayObject *self, Py_buffer *view, int flags) Py_buffer *base = &ndbuf->base; int baseflags = ndbuf->flags; + /* redirect mode */ + if (base->obj != NULL && (baseflags&ND_REDIRECT)) { + return PyObject_GetBuffer(base->obj, view, flags); + } + /* start with complete information */ *view = *base; view->obj = NULL; @@ -1445,6 +1447,8 @@ ndarray_getbuf(NDArrayObject *self, Py_buffer *view, int flags) if (baseflags & ND_GETBUF_FAIL) { PyErr_SetString(PyExc_BufferError, "ND_GETBUF_FAIL: forced test exception"); + if (baseflags & ND_GETBUF_UNDEFINED) + view->obj = (PyObject *)0x1; /* wrong but permitted in <= 3.2 */ return -1; } @@ -2598,6 +2602,126 @@ static PyTypeObject NDArray_Type = { ndarray_new, /* tp_new */ }; +/**************************************************************************/ +/* StaticArray Object */ +/**************************************************************************/ + +static PyTypeObject StaticArray_Type; + +typedef struct { + PyObject_HEAD + int legacy_mode; /* if true, use the view.obj==NULL hack */ +} StaticArrayObject; + +static char static_mem[12] = {0,1,2,3,4,5,6,7,8,9,10,11}; +static Py_ssize_t static_shape[1] = {12}; +static Py_ssize_t static_strides[1] = {1}; +static Py_buffer static_buffer = { + static_mem, /* buf */ + NULL, /* obj */ + 12, /* len */ + 1, /* itemsize */ + 1, /* readonly */ + 1, /* ndim */ + "B", /* format */ + static_shape, /* shape */ + static_strides, /* strides */ + NULL, /* suboffsets */ + NULL /* internal */ +}; + +static PyObject * +staticarray_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return (PyObject *)PyObject_New(StaticArrayObject, &StaticArray_Type); +} + +static int +staticarray_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + StaticArrayObject *a = (StaticArrayObject *)self; + static char *kwlist[] = { + "legacy_mode", NULL + }; + PyObject *legacy_mode = Py_False; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &legacy_mode)) + return -1; + + a->legacy_mode = (legacy_mode != Py_False); + return 0; +} + +static void +staticarray_dealloc(StaticArrayObject *self) +{ + PyObject_Del(self); +} + +/* Return a buffer for a PyBUF_FULL_RO request. Flags are not checked, + which makes this object a non-compliant exporter! */ +static int +staticarray_getbuf(StaticArrayObject *self, Py_buffer *view, int flags) +{ + *view = static_buffer; + + if (self->legacy_mode) { + view->obj = NULL; /* Don't use this in new code. */ + } + else { + view->obj = (PyObject *)self; + Py_INCREF(view->obj); + } + + return 0; +} + +static PyBufferProcs staticarray_as_buffer = { + (getbufferproc)staticarray_getbuf, /* bf_getbuffer */ + NULL, /* bf_releasebuffer */ +}; + +static PyTypeObject StaticArray_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "staticarray", /* Name of this type */ + sizeof(StaticArrayObject), /* Basic object size */ + 0, /* Item size for varobject */ + (destructor)staticarray_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + &staticarray_as_buffer, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + staticarray_init, /* tp_init */ + 0, /* tp_alloc */ + staticarray_new, /* tp_new */ +}; + static struct PyMethodDef _testbuffer_functions[] = { {"slice_indices", slice_indices, METH_VARARGS, NULL}, @@ -2630,10 +2754,14 @@ PyInit__testbuffer(void) if (m == NULL) return NULL; - Py_TYPE(&NDArray_Type)=&PyType_Type; + Py_TYPE(&NDArray_Type) = &PyType_Type; Py_INCREF(&NDArray_Type); PyModule_AddObject(m, "ndarray", (PyObject *)&NDArray_Type); + Py_TYPE(&StaticArray_Type) = &PyType_Type; + Py_INCREF(&StaticArray_Type); + PyModule_AddObject(m, "staticarray", (PyObject *)&StaticArray_Type); + structmodule = PyImport_ImportModule("struct"); if (structmodule == NULL) return NULL; @@ -2654,6 +2782,8 @@ PyInit__testbuffer(void) PyModule_AddIntConstant(m, "ND_SCALAR", ND_SCALAR); PyModule_AddIntConstant(m, "ND_PIL", ND_PIL); PyModule_AddIntConstant(m, "ND_GETBUF_FAIL", ND_GETBUF_FAIL); + PyModule_AddIntConstant(m, "ND_GETBUF_UNDEFINED", ND_GETBUF_UNDEFINED); + PyModule_AddIntConstant(m, "ND_REDIRECT", ND_REDIRECT); PyModule_AddIntConstant(m, "PyBUF_SIMPLE", PyBUF_SIMPLE); PyModule_AddIntConstant(m, "PyBUF_WRITABLE", PyBUF_WRITABLE); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 23a4d5ac..9294df3 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2323,6 +2323,24 @@ run_in_subinterp(PyObject *self, PyObject *args) return PyLong_FromLong(r); } +static PyObject * +test_pytime_object_to_timespec(PyObject *self, PyObject *args) +{ + PyObject *obj; + time_t sec; + long nsec; + if (!PyArg_ParseTuple(args, "O:pytime_object_to_timespec", &obj)) + return NULL; + if (_PyTime_ObjectToTimespec(obj, &sec, &nsec) == -1) + return NULL; +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + return Py_BuildValue("Ll", (PY_LONG_LONG)sec, nsec); +#else + assert(sizeof(time_t) <= sizeof(long)); + return Py_BuildValue("ll", (long)sec, nsec); +#endif +} + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -2412,6 +2430,7 @@ static PyMethodDef TestMethods[] = { METH_NOARGS}, {"crash_no_current_thread", (PyCFunction)crash_no_current_thread, METH_NOARGS}, {"run_in_subinterp", run_in_subinterp, METH_VARARGS}, + {"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index cf0b687..f52dce5 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -959,13 +959,13 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) } static PySequenceMethods mmap_as_sequence = { - (lenfunc)mmap_length, /*sq_length*/ - (binaryfunc)mmap_concat, /*sq_concat*/ - (ssizeargfunc)mmap_repeat, /*sq_repeat*/ - (ssizeargfunc)mmap_item, /*sq_item*/ - 0, /*sq_slice*/ - (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ + (lenfunc)mmap_length, /*sq_length*/ + (binaryfunc)mmap_concat, /*sq_concat*/ + (ssizeargfunc)mmap_repeat, /*sq_repeat*/ + (ssizeargfunc)mmap_item, /*sq_item*/ + 0, /*sq_slice*/ + (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/ + 0, /*sq_ass_slice*/ }; static PyMappingMethods mmap_as_mapping = { @@ -1027,7 +1027,7 @@ static PyTypeObject mmap_object_type = { PyObject_GenericGetAttr, /*tp_getattro*/ 0, /*tp_setattro*/ &mmap_as_buffer, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ mmap_doc, /*tp_doc*/ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -1043,10 +1043,10 @@ static PyTypeObject mmap_object_type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - 0, /* tp_init */ + 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ new_mmap_object, /* tp_new */ - PyObject_Del, /* tp_free */ + PyObject_Del, /* tp_free */ }; @@ -1097,8 +1097,8 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) int devzero = -1; int access = (int)ACCESS_DEFAULT; static char *keywords[] = {"fileno", "length", - "flags", "prot", - "access", "offset", NULL}; + "flags", "prot", + "access", "offset", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iii" _Py_PARSE_OFF_T, keywords, &fd, &map_size_obj, &flags, &prot, @@ -1260,8 +1260,8 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) int access = (access_mode)ACCESS_DEFAULT; DWORD flProtect, dwDesiredAccess; static char *keywords[] = { "fileno", "length", - "tagname", - "access", "offset", NULL }; + "tagname", + "access", "offset", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziL", keywords, &fileno, &map_size_obj, diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index e46f8cf..2eb7f29 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -783,16 +783,11 @@ signal_sigtimedwait(PyObject *self, PyObject *args) siginfo_t si; int err; - if (!PyArg_ParseTuple(args, "OO:sigtimedwait", &signals, &timeout)) + if (!PyArg_ParseTuple(args, "OO:sigtimedwait", + &signals, &timeout)) return NULL; - if (!PyTuple_Check(timeout) || PyTuple_Size(timeout) != 2) { - PyErr_SetString(PyExc_TypeError, - "sigtimedwait() arg 2 must be a tuple " - "(timeout_sec, timeout_nsec)"); - return NULL; - } else if (!PyArg_ParseTuple(timeout, "ll:sigtimedwait", - &(buf.tv_sec), &(buf.tv_nsec))) + if (_PyTime_ObjectToTimespec(timeout, &buf.tv_sec, &buf.tv_nsec) == -1) return NULL; if (buf.tv_sec < 0 || buf.tv_nsec < 0) { |