summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorLarry Hastings <larry@hastings.org>2010-03-25 00:54:54 (GMT)
committerLarry Hastings <larry@hastings.org>2010-03-25 00:54:54 (GMT)
commit402b73fb8d54ec2b24b52fdd77d389d903fa6c44 (patch)
treeced928b7f7dce754142742e485ed8e836fbc9486 /Modules
parent53ff86ea5f0ed27f5eb5b966faf59dac298d6672 (diff)
downloadcpython-402b73fb8d54ec2b24b52fdd77d389d903fa6c44.zip
cpython-402b73fb8d54ec2b24b52fdd77d389d903fa6c44.tar.gz
cpython-402b73fb8d54ec2b24b52fdd77d389d903fa6c44.tar.bz2
Backported PyCapsule from 3.1, and converted most uses of
CObject to PyCapsule.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/callproc.c23
-rw-r--r--Modules/_ctypes/cfield.c7
-rw-r--r--Modules/_ctypes/ctypes.h34
-rw-r--r--Modules/_cursesmodule.c6
-rw-r--r--Modules/_elementtree.c2
-rw-r--r--Modules/_testcapimodule.c152
-rw-r--r--Modules/cStringIO.c4
-rw-r--r--Modules/cjkcodecs/cjkcodecs.h10
-rw-r--r--Modules/cjkcodecs/multibytecodec.c4
-rw-r--r--Modules/cjkcodecs/multibytecodec.h3
-rw-r--r--Modules/datetimemodule.c9
-rw-r--r--Modules/pyexpat.c4
-rw-r--r--Modules/socketmodule.c2
-rw-r--r--Modules/socketmodule.h24
-rw-r--r--Modules/unicodedata.c2
15 files changed, 240 insertions, 46 deletions
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index cf17e3a..8e0b6a0 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -83,6 +83,13 @@
#define DONT_USE_SEH
#endif
+
+#define CTYPES_CAPSULE_ERROROBJ "_ctypes/callproc.c error object"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_ERROROBJ)
+
+#define CTYPES_CAPSULE_WCHAR_T "_ctypes/callproc.c wchar_t buffer from unicode"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T)
+
/*
ctypes maintains thread-local storage that has space for two error numbers:
private copies of the system 'errno' value and, on Windows, the system error code
@@ -134,14 +141,22 @@ _ctypes_get_errobj(int **pspace)
return NULL;
}
errobj = PyDict_GetItem(dict, error_object_name);
- if (errobj)
+ if (errobj) {
+#ifdef CTYPES_USING_CAPSULE
+ if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_ERROROBJ)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "ctypes.error_object is an invalid capsule");
+ return NULL;
+ }
+#endif /* CTYPES_USING_CAPSULE */
Py_INCREF(errobj);
+ }
else {
void *space = PyMem_Malloc(sizeof(int) * 2);
if (space == NULL)
return NULL;
memset(space, 0, sizeof(int) * 2);
- errobj = PyCObject_FromVoidPtr(space, PyMem_Free);
+ errobj = CAPSULE_NEW(space, CTYPES_CAPSULE_ERROROBJ);
if (errobj == NULL)
return NULL;
if (-1 == PyDict_SetItem(dict, error_object_name,
@@ -150,7 +165,7 @@ _ctypes_get_errobj(int **pspace)
return NULL;
}
}
- *pspace = (int *)PyCObject_AsVoidPtr(errobj);
+ *pspace = (int *)CAPSULE_DEREFERENCE(errobj, CTYPES_CAPSULE_ERROROBJ);
return errobj;
}
@@ -670,7 +685,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
return -1;
}
memset(pa->value.p, 0, size);
- pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free);
+ pa->keep = CAPSULE_NEW(pa->value.p, CTYPES_CAPSULE_WCHAR_T);
if (!pa->keep) {
PyMem_Free(pa->value.p);
return -1;
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index bf247bc..d7fc5d2 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -10,6 +10,11 @@
#endif
#include "ctypes.h"
+
+#define CTYPES_CAPSULE_WCHAR_T "_ctypes/cfield.c wchar_t buffer from unicode"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T)
+
+
/******************************************************************/
/*
PyCField_Type
@@ -1457,7 +1462,7 @@ Z_set(void *ptr, PyObject *value, Py_ssize_t size)
return PyErr_NoMemory();
}
memset(buffer, 0, size);
- keep = PyCObject_FromVoidPtr(buffer, PyMem_Free);
+ keep = CAPSULE_NEW(buffer, CTYPES_CAPSULE_WCHAR_T);
if (!keep) {
Py_DECREF(value);
PyMem_Free(buffer);
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index 1003614..718ee52 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -445,6 +445,40 @@ PyObject *_ctypes_get_errobj(int **pspace);
extern PyObject *ComError;
#endif
+#if PY_VERSION_HEX >= 0x020700A4
+/* Use PyCapsule for 2.7 */
+
+#define CTYPES_USING_CAPSULE
+
+#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name) \
+static void capsule_destructor_ ## name(PyObject *ptr) \
+{ \
+ void *p = PyCapsule_GetPointer(ptr, name); \
+ if (p) { \
+ PyMem_Free(p); \
+ } \
+} \
+
+#define CAPSULE_NEW(pointer, name) \
+ (PyCapsule_New(pointer, name, capsule_destructor_ ## name))
+
+#define CAPSULE_DEREFERENCE(capsule, name) \
+ (PyCapsule_GetPointer(capsule, name))
+
+#else /* PY_VERSION_HEX >= 0x020700A4 */
+/* Use CObject for 2.6 and before */
+
+#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name)
+
+#define CAPSULE_NEW(pointer, name) \
+ (PyCObject_FromVoidPtr(pointer, PyMem_Free))
+
+#define CAPSULE_DEREFERENCE(capsule, name) \
+ (PyCObject_AsVoidPtr(capsule))
+
+#endif /* PY_VERSION_HEX >= 0x020700A4 */
+
+
/*
Local Variables:
compile-command: "python setup.py -q build install --home ~"
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 430ab17..3f95cef 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -172,7 +172,7 @@ static int initialisedcolors = FALSE;
/*
* Check the return code from a curses function and return None
* or raise an exception as appropriate. These are exported using the
- * CObject API.
+ * capsule API.
*/
static PyObject *
@@ -2745,8 +2745,8 @@ init_curses(void)
return;
ModDict = d; /* For PyCurses_InitScr to use later */
- /* Add a CObject for the C API */
- c_api_object = PyCObject_FromVoidPtr((void *)PyCurses_API, NULL);
+ /* Add a capsule for the C API */
+ c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, NULL);
PyDict_SetItemString(d, "_C_API", c_api_object);
Py_DECREF(c_api_object);
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 0aa1ebb..4311ba2 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -3059,7 +3059,7 @@ init_elementtree(void)
#if defined(USE_PYEXPAT_CAPI)
/* link against pyexpat, if possible */
- expat_capi = PyCObject_Import("pyexpat", "expat_CAPI");
+ expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
if (expat_capi) {
/* check that it's usable */
if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 6bc6da2..023e62e 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1428,6 +1428,157 @@ test_string_from_format(PyObject *self, PyObject *args)
#undef CHECK_1_FORMAT
}
+/* Coverage testing of capsule objects. */
+
+static const char *capsule_name = "capsule name";
+static char *capsule_pointer = "capsule pointer";
+static char *capsule_context = "capsule context";
+static const char *capsule_error = NULL;
+static int
+capsule_destructor_call_count = 0;
+
+static void
+capsule_destructor(PyObject *o) {
+ capsule_destructor_call_count++;
+ if (PyCapsule_GetContext(o) != capsule_context) {
+ capsule_error = "context did not match in destructor!";
+ } else if (PyCapsule_GetDestructor(o) != capsule_destructor) {
+ capsule_error = "destructor did not match in destructor! (woah!)";
+ } else if (PyCapsule_GetName(o) != capsule_name) {
+ capsule_error = "name did not match in destructor!";
+ } else if (PyCapsule_GetPointer(o, capsule_name) != capsule_pointer) {
+ capsule_error = "pointer did not match in destructor!";
+ }
+}
+
+typedef struct {
+ char *name;
+ char *module;
+ char *attribute;
+} known_capsule;
+
+static PyObject *
+test_capsule(PyObject *self, PyObject *args)
+{
+ PyObject *object;
+ const char *error = NULL;
+ void *pointer;
+ void *pointer2;
+ known_capsule known_capsules[] = {
+ #define KNOWN_CAPSULE(module, name) { module "." name, module, name }
+ KNOWN_CAPSULE("_socket", "CAPI"),
+ KNOWN_CAPSULE("_curses", "_C_API"),
+ KNOWN_CAPSULE("datetime", "datetime_CAPI"),
+ { NULL, NULL },
+ };
+ known_capsule *known = &known_capsules[0];
+
+#define FAIL(x) { error = (x); goto exit; }
+
+#define CHECK_DESTRUCTOR \
+ if (capsule_error) { \
+ FAIL(capsule_error); \
+ } \
+ else if (!capsule_destructor_call_count) { \
+ FAIL("destructor not called!"); \
+ } \
+ capsule_destructor_call_count = 0; \
+
+ object = PyCapsule_New(capsule_pointer, capsule_name, capsule_destructor);
+ PyCapsule_SetContext(object, capsule_context);
+ capsule_destructor(object);
+ CHECK_DESTRUCTOR;
+ Py_DECREF(object);
+ CHECK_DESTRUCTOR;
+
+ object = PyCapsule_New(known, "ignored", NULL);
+ PyCapsule_SetPointer(object, capsule_pointer);
+ PyCapsule_SetName(object, capsule_name);
+ PyCapsule_SetDestructor(object, capsule_destructor);
+ PyCapsule_SetContext(object, capsule_context);
+ capsule_destructor(object);
+ CHECK_DESTRUCTOR;
+ /* intentionally access using the wrong name */
+ pointer2 = PyCapsule_GetPointer(object, "the wrong name");
+ if (!PyErr_Occurred()) {
+ FAIL("PyCapsule_GetPointer should have failed but did not!");
+ }
+ PyErr_Clear();
+ if (pointer2) {
+ if (pointer2 == capsule_pointer) {
+ FAIL("PyCapsule_GetPointer should not have"
+ " returned the internal pointer!");
+ } else {
+ FAIL("PyCapsule_GetPointer should have "
+ "returned NULL pointer but did not!");
+ }
+ }
+ PyCapsule_SetDestructor(object, NULL);
+ Py_DECREF(object);
+ if (capsule_destructor_call_count) {
+ FAIL("destructor called when it should not have been!");
+ }
+
+ for (known = &known_capsules[0]; known->module != NULL; known++) {
+ /* yeah, ordinarily I wouldn't do this either,
+ but it's fine for this test harness.
+ */
+ static char buffer[256];
+#undef FAIL
+#define FAIL(x) \
+ { \
+ sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \
+ x, known->module, known->attribute); \
+ error = buffer; \
+ goto exit; \
+ } \
+
+ PyObject *module = PyImport_ImportModule(known->module);
+ if (module) {
+ pointer = PyCapsule_Import(known->name, 0);
+ if (!pointer) {
+ Py_DECREF(module);
+ FAIL("PyCapsule_GetPointer returned NULL unexpectedly!");
+ }
+ object = PyObject_GetAttrString(module, known->attribute);
+ if (!object) {
+ Py_DECREF(module);
+ return NULL;
+ }
+ pointer2 = PyCapsule_GetPointer(object,
+ "weebles wobble but they don't fall down");
+ if (!PyErr_Occurred()) {
+ Py_DECREF(object);
+ Py_DECREF(module);
+ FAIL("PyCapsule_GetPointer should have failed but did not!");
+ }
+ PyErr_Clear();
+ if (pointer2) {
+ Py_DECREF(module);
+ Py_DECREF(object);
+ if (pointer2 == pointer) {
+ FAIL("PyCapsule_GetPointer should not have"
+ " returned its internal pointer!");
+ } else {
+ FAIL("PyCapsule_GetPointer should have"
+ " returned NULL pointer but did not!");
+ }
+ }
+ Py_DECREF(object);
+ Py_DECREF(module);
+ }
+ else
+ PyErr_Clear();
+ }
+
+ exit:
+ if (error) {
+ return raiseTestError("test_capsule", error);
+ }
+ Py_RETURN_NONE;
+#undef FAIL
+}
+
/* This is here to provide a docstring for test_descr. */
static PyObject *
test_with_docstring(PyObject *self)
@@ -1539,6 +1690,7 @@ static PyMethodDef TestMethods[] = {
{"_test_thread_state", test_thread_state, METH_VARARGS},
{"_pending_threadfunc", pending_threadfunc, METH_VARARGS},
#endif
+ {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS},
{"traceback_print", traceback_print, METH_VARARGS},
{"code_newempty", code_newempty, METH_VARARGS},
{"make_exception_with_doc", (PyCFunction)make_exception_with_doc,
diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c
index 237d8c2..80588bf 100644
--- a/Modules/cStringIO.c
+++ b/Modules/cStringIO.c
@@ -761,8 +761,8 @@ initcStringIO(void) {
Py_TYPE(&Otype)=&PyType_Type;
if (PyType_Ready(&Otype) < 0) return;
if (PyType_Ready(&Itype) < 0) return;
- PyDict_SetItemString(d,"cStringIO_CAPI",
- v = PyCObject_FromVoidPtr(&CAPI,NULL));
+ v = PyCapsule_New(&CAPI, PycStringIO_CAPSULE_NAME, NULL);
+ PyDict_SetItemString(d,"cStringIO_CAPI", v);
Py_XDECREF(v);
/* Export Types */
diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h
index 4005bcf..236c3fe 100644
--- a/Modules/cjkcodecs/cjkcodecs.h
+++ b/Modules/cjkcodecs/cjkcodecs.h
@@ -282,7 +282,7 @@ getcodec(PyObject *self, PyObject *encoding)
return NULL;
}
- codecobj = PyCObject_FromVoidPtr((void *)codec, NULL);
+ codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL);
if (codecobj == NULL)
return NULL;
@@ -307,7 +307,7 @@ register_maps(PyObject *module)
int r;
strcpy(mhname + sizeof("__map_") - 1, h->charset);
r = PyModule_AddObject(module, mhname,
- PyCObject_FromVoidPtr((void *)h, NULL));
+ PyCapsule_New((void *)h, PyMultibyteCodec_CAPSULE_NAME, NULL));
if (r == -1)
return -1;
}
@@ -362,14 +362,14 @@ importmap(const char *modname, const char *symbol,
o = PyObject_GetAttrString(mod, (char*)symbol);
if (o == NULL)
goto errorexit;
- else if (!PyCObject_Check(o)) {
+ else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
PyErr_SetString(PyExc_ValueError,
- "map data must be a CObject.");
+ "map data must be a Capsule.");
goto errorexit;
}
else {
struct dbcs_map *map;
- map = PyCObject_AsVoidPtr(o);
+ map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
if (encmap != NULL)
*encmap = map->encmap;
if (decmap != NULL)
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index 5fb5ec0..794774b 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -1774,12 +1774,12 @@ __create_codec(PyObject *ignore, PyObject *arg)
MultibyteCodecObject *self;
MultibyteCodec *codec;
- if (!PyCObject_Check(arg)) {
+ if (!PyCapsule_IsValid(arg, PyMultibyteCodec_CAPSULE_NAME)) {
PyErr_SetString(PyExc_ValueError, "argument type invalid");
return NULL;
}
- codec = PyCObject_AsVoidPtr(arg);
+ codec = PyCapsule_GetPointer(arg, PyMultibyteCodec_CAPSULE_NAME);
if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
return NULL;
diff --git a/Modules/cjkcodecs/multibytecodec.h b/Modules/cjkcodecs/multibytecodec.h
index 22ea5d4..71c02cc 100644
--- a/Modules/cjkcodecs/multibytecodec.h
+++ b/Modules/cjkcodecs/multibytecodec.h
@@ -132,6 +132,9 @@ typedef struct {
#define MBENC_FLUSH 0x0001 /* encode all characters encodable */
#define MBENC_MAX MBENC_FLUSH
+#define PyMultibyteCodec_CAPSULE_NAME "multibytecodec.__map_*"
+
+
#ifdef __cplusplus
}
#endif
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index 7b9e271..3f1eb57 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -4856,11 +4856,10 @@ initdatetime(void)
Py_INCREF(&PyDateTime_TZInfoType);
PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
- x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC,
- NULL);
- if (x == NULL)
- return;
- PyModule_AddObject(m, "datetime_CAPI", x);
+ x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
+ if (x == NULL)
+ return NULL;
+ PyModule_AddObject(m, "datetime_CAPI", x);
/* A 4-year cycle has an extra leap day over what we'd get from
* pasting together 4 single years.
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index 47ef186..d428c66 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -2053,8 +2053,8 @@ MODULE_INITFUNC(void)
capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
capi.SetUserData = XML_SetUserData;
- /* export as cobject */
- capi_object = PyCObject_FromVoidPtr(&capi, NULL);
+ /* export using capsule */
+ capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL);
if (capi_object)
PyModule_AddObject(m, "expat_CAPI", capi_object);
}
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index fbd0239..d44a691 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -4496,7 +4496,7 @@ init_socket(void)
/* Export C API */
if (PyModule_AddObject(m, PySocket_CAPI_NAME,
- PyCObject_FromVoidPtr((void *)&PySocketModuleAPI, NULL)
+ PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL)
) != 0)
return;
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index ef8d0fc..48f230e 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -78,6 +78,7 @@ extern "C" {
/* Python module and C API name */
#define PySocket_MODULE_NAME "_socket"
#define PySocket_CAPI_NAME "CAPI"
+#define PySocket_CAPSULE_NAME (PySocket_MODULE_NAME "." PySocket_CAPI_NAME)
/* Abstract the socket file descriptor type */
#ifdef MS_WINDOWS
@@ -142,12 +143,12 @@ typedef struct {
the _socket module. Since cross-DLL linking introduces a lot of
problems on many platforms, the "trick" is to wrap the
C API of a module in a struct which then gets exported to
- other modules via a PyCObject.
+ other modules via a PyCapsule.
The code in socketmodule.c defines this struct (which currently
only contains the type object reference, but could very
well also include other C APIs needed by other modules)
- and exports it as PyCObject via the module dictionary
+ and exports it as PyCapsule via the module dictionary
under the name "CAPI".
Other modules can now include the socketmodule.h file
@@ -226,33 +227,18 @@ PySocketModule_APIObject PySocketModule;
static
int PySocketModule_ImportModuleAndAPI(void)
{
- PyObject *mod = 0, *v = 0;
- char *apimodule = PySocket_MODULE_NAME;
- char *apiname = PySocket_CAPI_NAME;
void *api;
- DPRINTF("Importing the %s C API...\n", apimodule);
- mod = PyImport_ImportModuleNoBlock(apimodule);
- if (mod == NULL)
- goto onError;
- DPRINTF(" %s package found\n", apimodule);
- v = PyObject_GetAttrString(mod, apiname);
- if (v == NULL)
- goto onError;
- Py_DECREF(mod);
- DPRINTF(" API object %s found\n", apiname);
- api = PyCObject_AsVoidPtr(v);
+ DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME);
+ api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1);
if (api == NULL)
goto onError;
- Py_DECREF(v);
memcpy(&PySocketModule, api, sizeof(PySocketModule));
DPRINTF(" API object loaded and initialized.\n");
return 0;
onError:
DPRINTF(" not found.\n");
- Py_XDECREF(mod);
- Py_XDECREF(v);
return -1;
}
diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c
index 552dae5..ede57cb 100644
--- a/Modules/unicodedata.c
+++ b/Modules/unicodedata.c
@@ -1261,7 +1261,7 @@ initunicodedata(void)
PyModule_AddObject(m, "ucd_3_2_0", v);
/* Export C API */
- v = PyCObject_FromVoidPtr((void *) &hashAPI, NULL);
+ v = PyCapsule_New((void *)&hashAPI, PyUnicodeData_CAPSULE_NAME, NULL);
if (v != NULL)
PyModule_AddObject(m, "ucnhash_CAPI", v);
}