summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2012-03-06 20:33:24 (GMT)
committerBrett Cannon <brett@python.org>2012-03-06 20:33:24 (GMT)
commitf67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24 (patch)
treeceed84488164142e5884411566de19f66702c3e7 /Modules
parent0d4d410b2d6891520b1772a85f5ebdf926a0c77e (diff)
parent0119e4753eec50f671ee716af202b4a1ca28deef (diff)
downloadcpython-f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24.zip
cpython-f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24.tar.gz
cpython-f67e494ca8dfc72c0f812ed46c6a08ad3b9ddc24.tar.bz2
merge
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_elementtree.c250
-rw-r--r--Modules/_multiprocessing/win32_functions.c69
-rw-r--r--Modules/_pickle.c39
-rw-r--r--Modules/_testbuffer.c174
-rw-r--r--Modules/_testcapimodule.c19
-rw-r--r--Modules/mmapmodule.c28
-rw-r--r--Modules/signalmodule.c11
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) {