Mercurial > cpython-lru_cache-weakref
view Python/structmember.c @ 36683:da2a1049215d legacy-trunk
Patch 1413181, by Gabriel Becedillas.
PyThreadState_Delete(): if the auto-GIL-state machinery knows about
the thread state, forget it (since the thread state is being deleted,
continuing to remember it can't help, but can hurt if another thread
happens to get created with the same thread id).
I'll backport to 2.4 next.
| author | Tim Peters <tim.peters@gmail.com> |
|---|---|
| date | Mon, 27 Feb 2006 17:15:31 +0000 |
| parents | e9a10f74cf88 |
| children | 8bc4a7e5fef8 |
line wrap: on
line source
/* Map C struct members to Python object attributes */ #include "Python.h" #include "structmember.h" static PyObject * listmembers(struct memberlist *mlist) { int i, n; PyObject *v; for (n = 0; mlist[n].name != NULL; n++) ; v = PyList_New(n); if (v != NULL) { for (i = 0; i < n; i++) PyList_SetItem(v, i, PyString_FromString(mlist[i].name)); if (PyErr_Occurred()) { Py_DECREF(v); v = NULL; } else { PyList_Sort(v); } } return v; } PyObject * PyMember_Get(const char *addr, struct memberlist *mlist, const char *name) { struct memberlist *l; if (strcmp(name, "__members__") == 0) return listmembers(mlist); for (l = mlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) { PyMemberDef copy; copy.name = l->name; copy.type = l->type; copy.offset = l->offset; copy.flags = l->flags; copy.doc = NULL; return PyMember_GetOne(addr, ©); } } PyErr_SetString(PyExc_AttributeError, name); return NULL; } PyObject * PyMember_GetOne(const char *addr, PyMemberDef *l) { PyObject *v; if ((l->flags & READ_RESTRICTED) && PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); return NULL; } addr += l->offset; switch (l->type) { case T_BYTE: v = PyInt_FromLong( (long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80)); break; case T_UBYTE: v = PyInt_FromLong((long) *(char*)addr & 0xff); break; case T_SHORT: v = PyInt_FromLong((long) *(short*)addr); break; case T_USHORT: v = PyInt_FromLong((long) *(unsigned short*)addr); break; case T_INT: v = PyInt_FromLong((long) *(int*)addr); break; case T_UINT: v = PyInt_FromLong((long) *(unsigned int*)addr); break; case T_LONG: v = PyInt_FromLong(*(long*)addr); break; case T_ULONG: v = PyLong_FromDouble((double) *(unsigned long*)addr); break; case T_FLOAT: v = PyFloat_FromDouble((double)*(float*)addr); break; case T_DOUBLE: v = PyFloat_FromDouble(*(double*)addr); break; case T_STRING: if (*(char**)addr == NULL) { Py_INCREF(Py_None); v = Py_None; } else v = PyString_FromString(*(char**)addr); break; case T_STRING_INPLACE: v = PyString_FromString((char*)addr); break; case T_CHAR: v = PyString_FromStringAndSize((char*)addr, 1); break; case T_OBJECT: v = *(PyObject **)addr; if (v == NULL) v = Py_None; Py_INCREF(v); break; case T_OBJECT_EX: v = *(PyObject **)addr; if (v == NULL) PyErr_SetString(PyExc_AttributeError, l->name); Py_XINCREF(v); break; #ifdef HAVE_LONG_LONG case T_LONGLONG: v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr); break; case T_ULONGLONG: v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr); break; #endif /* HAVE_LONG_LONG */ default: PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); v = NULL; } return v; } int PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v) { struct memberlist *l; for (l = mlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) { PyMemberDef copy; copy.name = l->name; copy.type = l->type; copy.offset = l->offset; copy.flags = l->flags; copy.doc = NULL; return PyMember_SetOne(addr, ©, v); } } PyErr_SetString(PyExc_AttributeError, name); return -1; } int PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) { PyObject *oldv; if ((l->flags & READONLY) || l->type == T_STRING) { PyErr_SetString(PyExc_TypeError, "readonly attribute"); return -1; } if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); return -1; } if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) { PyErr_SetString(PyExc_TypeError, "can't delete numeric/char attribute"); return -1; } addr += l->offset; switch (l->type) { case T_BYTE: case T_UBYTE: if (!PyInt_Check(v)) { PyErr_BadArgument(); return -1; } *(char*)addr = (char) PyInt_AsLong(v); break; case T_SHORT: case T_USHORT: if (!PyInt_Check(v)) { PyErr_BadArgument(); return -1; } *(short*)addr = (short) PyInt_AsLong(v); break; case T_UINT: case T_INT: if (!PyInt_Check(v)) { PyErr_BadArgument(); return -1; } *(int*)addr = (int) PyInt_AsLong(v); break; case T_LONG: if (!PyInt_Check(v)) { PyErr_BadArgument(); return -1; } *(long*)addr = PyInt_AsLong(v); break; case T_ULONG: if (PyInt_Check(v)) *(long*)addr = PyInt_AsLong(v); else if (PyLong_Check(v)) *(long*)addr = PyLong_AsLong(v); else { PyErr_BadArgument(); return -1; } break; case T_FLOAT: if (PyInt_Check(v)) *(float*)addr = (float) PyInt_AsLong(v); else if (PyFloat_Check(v)) *(float*)addr = (float) PyFloat_AsDouble(v); else { PyErr_BadArgument(); return -1; } break; case T_DOUBLE: if (PyInt_Check(v)) *(double*)addr = (double) PyInt_AsLong(v); else if (PyFloat_Check(v)) *(double*)addr = PyFloat_AsDouble(v); else { PyErr_BadArgument(); return -1; } break; case T_OBJECT: case T_OBJECT_EX: Py_XINCREF(v); oldv = *(PyObject **)addr; *(PyObject **)addr = v; Py_XDECREF(oldv); break; case T_CHAR: if (PyString_Check(v) && PyString_Size(v) == 1) { *(char*)addr = PyString_AsString(v)[0]; } else { PyErr_BadArgument(); return -1; } break; #ifdef HAVE_LONG_LONG case T_LONGLONG: if (!PyLong_Check(v)) { PyErr_BadArgument(); return -1; } else { *(PY_LONG_LONG*)addr = PyLong_AsLongLong(v); if ((*addr == -1) && PyErr_Occurred()) { return -1; } } break; case T_ULONGLONG: if (!PyLong_Check(v)) { PyErr_BadArgument(); return -1; } else { *(unsigned PY_LONG_LONG*)addr = PyLong_AsUnsignedLongLong(v); if ((*addr == -1) && PyErr_Occurred()) { return -1; } } break; #endif /* HAVE_LONG_LONG */ default: PyErr_Format(PyExc_SystemError, "bad memberdescr type for %s", l->name); return -1; } return 0; }
