mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
add a replacement API for PyCObject, PyCapsule #5630
All stdlib modules with C-APIs now use this. Patch by Larry Hastings
This commit is contained in:
parent
c679fd8efc
commit
b173f7853e
37 changed files with 943 additions and 149 deletions
|
@ -1102,6 +1102,155 @@ test_string_to_double(PyObject *self) {
|
|||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if (error) {
|
||||
return raiseTestError("test_capsule", error);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
#undef FAIL
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
/* Profiling of integer performance */
|
||||
static void print_delta(int test, struct timeval *s, struct timeval *e)
|
||||
|
@ -1280,9 +1429,10 @@ static PyMethodDef TestMethods[] = {
|
|||
{"test_empty_argparse", (PyCFunction)test_empty_argparse,METH_NOARGS},
|
||||
{"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS},
|
||||
{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
|
||||
{"test_string_to_double", (PyCFunction)test_string_to_double, METH_NOARGS},
|
||||
{"test_with_docstring", (PyCFunction)test_with_docstring, METH_NOARGS,
|
||||
PyDoc_STR("This is a pretty normal docstring.")},
|
||||
{"test_string_to_double", (PyCFunction)test_string_to_double, METH_NOARGS},
|
||||
{"test_capsule", (PyCFunction)test_capsule, METH_NOARGS},
|
||||
|
||||
{"getargs_tuple", getargs_tuple, METH_VARARGS},
|
||||
{"getargs_keywords", (PyCFunction)getargs_keywords,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue