Mercurial > cpython-lru_cache-weakref
view Python/structmember.c @ 86436:76184b5339f2
Issue #18416: Have importlib.machinery.PathFinder treat '' as the cwd
and stop importlib.machinery.FileFinder treating '' as '.'.
Previous PathFinder transformed '' into '.' which led to __file__ for
modules imported from the cwd to always be relative paths. This meant
the values of the attribute were wrong as soon as the cwd changed.
This change now means that as long as the site module is run (which
makes all entries in sys.path absolute) then all values for __file__
will also be absolute unless it's for __main__ when specified by file
path in a relative way (modules imported by runpy will have an
absolute path).
Now that PathFinder is no longer treating '' as '.' it only makes
sense for FileFinder to stop doing so as well. Now no transformation
is performed for the directory given to the __init__ method.
Thanks to Madison May for the initial patch.
| author | Brett Cannon <brett@python.org> |
|---|---|
| date | Fri, 18 Oct 2013 11:39:04 -0400 |
| parents | afe55cd04119 |
| children |
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; addr += l->offset; if ((l->flags & READONLY)) { PyErr_SetString(PyExc_AttributeError, "readonly attribute"); return -1; } if (v == NULL) { if (l->type == T_OBJECT_EX) { /* Check if the attribute is set. */ if (*(PyObject **)addr == NULL) { PyErr_SetString(PyExc_AttributeError, l->name); return -1; } } else if (l->type != T_OBJECT) { PyErr_SetString(PyExc_TypeError, "can't delete numeric/char attribute"); return -1; } } 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 long)-1) && PyErr_Occurred()) { /* XXX: For compatibility, accept negative int values as well. */ PyErr_Clear(); ulong_val = PyLong_AsLong(v); if ((ulong_val == (unsigned long)-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 long)-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: { char *string; Py_ssize_t len; string = _PyUnicode_AsStringAndSize(v, &len); if (string == NULL || len != 1) { PyErr_BadArgument(); return -1; } *(char*)addr = string[0]; break; } case T_STRING: case T_STRING_INPLACE: PyErr_SetString(PyExc_TypeError, "readonly attribute"); return -1; #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; }
