Mercurial > cpython-lru_cache-weakref
view Python/structmember.c @ 45774:058fbfb985ae
Merged revisions 61404-61407 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r61404 | raymond.hettinger | 2008-03-15 21:02:04 +0100 (Sat, 15 Mar 2008) | 17 lines
Removed Exact/Inexact after discussion with Yasskin.
Unlike Scheme where exactness is implemented as taints, the Python
implementation associated exactness with data types. This created
inheritance issues (making an exact subclass of floats would result
in the subclass having both an explicit Exact registration and an
inherited Inexact registration). This was a problem for the
decimal module which was designed to span both exact and inexact
arithmetic. There was also a question of use cases and no examples
were found where ABCs for exactness could be used to improve code.
One other issue was having separate tags for both the affirmative
and negative cases. This is at odds with the approach taken
elsewhere in the Python (i.e. we don't have an ABC both Hashable
and Unhashable).
........
r61405 | raymond.hettinger | 2008-03-15 21:37:50 +0100 (Sat, 15 Mar 2008) | 1 line
Zap one more use of Exact/Inexact.
........
r61406 | neal.norwitz | 2008-03-15 23:03:18 +0100 (Sat, 15 Mar 2008) | 9 lines
Add a warning for code like:
assert (0, 'message')
An empty tuple does not create a warning. While questionable usage:
assert (), 'message'
should not display a warning. Tested manually.
The warning message could be improved. Feel free to update it.
........
r61407 | neal.norwitz | 2008-03-15 23:36:01 +0100 (Sat, 15 Mar 2008) | 1 line
Handle memory allocation failure. Found by Adam Olsen
........
| author | Christian Heimes <christian@cheimes.de> |
|---|---|
| date | Sun, 16 Mar 2008 00:32:36 +0000 |
| parents | fefaa0e66fdd |
| children | ea594306ea85 |
line wrap: on
line source
/* Map C struct members to Python object attributes */ #include "Python.h" #include "structmember.h" PyObject * PyMember_GetOne(const char *addr, PyMemberDef *l) { PyObject *v; addr += l->offset; switch (l->type) { case T_BOOL: v = PyBool_FromLong(*(char*)addr); break; case T_BYTE: v = PyLong_FromLong(*(char*)addr); break; case T_UBYTE: v = PyLong_FromUnsignedLong(*(unsigned char*)addr); break; case T_SHORT: v = PyLong_FromLong(*(short*)addr); break; case T_USHORT: v = PyLong_FromUnsignedLong(*(unsigned short*)addr); break; case T_INT: v = PyLong_FromLong(*(int*)addr); break; case T_UINT: v = PyLong_FromUnsignedLong(*(unsigned int*)addr); break; case T_LONG: v = PyLong_FromLong(*(long*)addr); break; case T_ULONG: v = PyLong_FromUnsignedLong(*(unsigned long*)addr); break; case T_PYSSIZET: v = PyLong_FromSsize_t(*(Py_ssize_t*)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 = PyUnicode_FromString(*(char**)addr); break; case T_STRING_INPLACE: v = PyUnicode_FromString((char*)addr); break; case T_CHAR: v = PyUnicode_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 */ case T_NONE: v = Py_None; Py_INCREF(v); break; default: PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); v = NULL; } return v; } #define WARN(msg) \ do { \ if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \ return -1; \ } while (0) int PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) { PyObject *oldv; if ((l->flags & READONLY) || l->type == T_STRING) { PyErr_SetString(PyExc_AttributeError, "readonly 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_BOOL:{ if (!PyBool_Check(v)) { PyErr_SetString(PyExc_TypeError, "attribute value type must be bool"); return -1; } if (v == Py_True) *(char*)addr = (char) 1; else *(char*)addr = (char) 0; break; } case T_BYTE:{ long long_val = PyLong_AsLong(v); if ((long_val == -1) && PyErr_Occurred()) return -1; *(char*)addr = (char)long_val; /* XXX: For compatibility, only warn about truncations for now. */ if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN)) WARN("Truncation of value to char"); break; } case T_UBYTE:{ long long_val = PyLong_AsLong(v); if ((long_val == -1) && PyErr_Occurred()) return -1; *(unsigned char*)addr = (unsigned char)long_val; if ((long_val > UCHAR_MAX) || (long_val < 0)) WARN("Truncation of value to unsigned char"); break; } case T_SHORT:{ long long_val = PyLong_AsLong(v); if ((long_val == -1) && PyErr_Occurred()) return -1; *(short*)addr = (short)long_val; if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN)) WARN("Truncation of value to short"); break; } case T_USHORT:{ long long_val = PyLong_AsLong(v); if ((long_val == -1) && PyErr_Occurred()) return -1; *(unsigned short*)addr = (unsigned short)long_val; if ((long_val > USHRT_MAX) || (long_val < 0)) WARN("Truncation of value to unsigned short"); break; } case T_INT:{ long long_val = PyLong_AsLong(v); if ((long_val == -1) && PyErr_Occurred()) return -1; *(int *)addr = (int)long_val; if ((long_val > INT_MAX) || (long_val < INT_MIN)) WARN("Truncation of value to int"); break; } case T_UINT:{ unsigned long ulong_val = PyLong_AsUnsignedLong(v); if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) { /* XXX: For compatibility, accept negative int values as well. */ PyErr_Clear(); ulong_val = PyLong_AsLong(v); if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) return -1; *(unsigned int *)addr = (unsigned int)ulong_val; WARN("Writing negative value into unsigned field"); } else *(unsigned int *)addr = (unsigned int)ulong_val; if (ulong_val > UINT_MAX) WARN("Truncation of value to unsigned int"); break; } case T_LONG:{ *(long*)addr = PyLong_AsLong(v); if ((*(long*)addr == -1) && PyErr_Occurred()) return -1; break; } case T_ULONG:{ *(unsigned long*)addr = PyLong_AsUnsignedLong(v); if ((*(unsigned long*)addr == (unsigned long)-1) && PyErr_Occurred()) { /* XXX: For compatibility, accept negative int values as well. */ PyErr_Clear(); *(unsigned long*)addr = PyLong_AsLong(v); if ((*(unsigned long*)addr == (unsigned int)-1) && PyErr_Occurred()) return -1; WARN("Writing negative value into unsigned field"); } break; } case T_PYSSIZET:{ *(Py_ssize_t*)addr = PyLong_AsSsize_t(v); if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1) && PyErr_Occurred()) return -1; break; } case T_FLOAT:{ double double_val = PyFloat_AsDouble(v); if ((double_val == -1) && PyErr_Occurred()) return -1; *(float*)addr = (float)double_val; break; } case T_DOUBLE: *(double*)addr = PyFloat_AsDouble(v); if ((*(double*)addr == -1) && PyErr_Occurred()) 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 (PyUnicode_Check(v) && PyUnicode_GetSize(v) == 1) { *(char*)addr = PyUnicode_AsString(v)[0]; } else { PyErr_BadArgument(); return -1; } break; #ifdef HAVE_LONG_LONG case T_LONGLONG:{ PY_LONG_LONG value; *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v); if ((value == -1) && PyErr_Occurred()) return -1; break; } case T_ULONGLONG:{ unsigned PY_LONG_LONG value; /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong doesn't ??? */ if (PyLong_Check(v)) *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v); else *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v); if ((value == (unsigned PY_LONG_LONG)-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; }
