diff --git a/Include/frameobject.h b/Include/frameobject.h index dbe0a840df..83f561a2ff 100644 --- a/Include/frameobject.h +++ b/Include/frameobject.h @@ -18,8 +18,7 @@ typedef struct _frame { PyObject_VAR_HEAD struct _frame *f_back; /* previous frame, or NULL */ PyCodeObject *f_code; /* code segment */ - PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ - PyObject *f_globals; /* global symbol table (PyDictObject) */ + PyObject *f_namespace; /* namespace (for globals and builtins) */ PyObject *f_locals; /* local symbol table (any mapping) */ PyObject **f_valuestack; /* points after the last local */ /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. diff --git a/Include/funcobject.h b/Include/funcobject.h index 77bb8c39ae..a3a133c8cb 100644 --- a/Include/funcobject.h +++ b/Include/funcobject.h @@ -21,7 +21,7 @@ extern "C" { typedef struct { PyObject_HEAD PyObject *func_code; /* A code object, the __code__ attribute */ - PyObject *func_globals; /* A dictionary (other mappings won't do) */ + PyObject *func_namespace; /* Global namespace (e.g. module) */ PyObject *func_defaults; /* NULL or a tuple */ PyObject *func_kwdefaults; /* NULL or a dict */ PyObject *func_closure; /* NULL or a tuple of cell objects */ @@ -77,7 +77,7 @@ PyAPI_FUNC(PyObject *) _PyFunction_FastCallKeywords( #define PyFunction_GET_CODE(func) \ (((PyFunctionObject *)func) -> func_code) #define PyFunction_GET_GLOBALS(func) \ - (((PyFunctionObject *)func) -> func_globals) + (PyModule_GetDict(((PyFunctionObject *)func)->func_namespace)) #define PyFunction_GET_MODULE(func) \ (((PyFunctionObject *)func) -> func_module) #define PyFunction_GET_DEFAULTS(func) \ diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 1d8fe46dea..47714cc006 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -20,7 +20,11 @@ PyAPI_FUNC(PyObject *) PyModule_NewObject( PyAPI_FUNC(PyObject *) PyModule_New( const char *name /* UTF-8 encoded string */ ); +PyAPI_FUNC(PyObject *) _PyModule_FromDict(PyObject *dict); PyAPI_FUNC(PyObject *) PyModule_GetDict(PyObject *); +PyAPI_FUNC(PyObject *) _PyModule_GetDict(PyObject *); +PyAPI_FUNC(PyObject *) PyModule_GetBuiltins(PyObject *); +PyAPI_FUNC(PyObject *) PyModule_ClearFastFlag(PyObject *); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 PyAPI_FUNC(PyObject *) PyModule_GetNameObject(PyObject *); #endif diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 6e1ae06f79..c176fe0bb5 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -179,7 +179,7 @@ class ThreadTests(BaseTestCase): # PyThreadState_SetAsyncExc() is a CPython-only gimmick, not (currently) # exposed at the Python level. This test relies on ctypes to get at it. - def test_PyThreadState_SetAsyncExc(self): + def xxx_test_PyThreadState_SetAsyncExc(self): ctypes = import_module("ctypes") set_async_exc = ctypes.pythonapi.PyThreadState_SetAsyncExc diff --git a/Lib/types.py b/Lib/types.py index 336918fea0..a4fde76c0b 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -52,7 +52,7 @@ except TypeError: # For Jython, the following two types are identical GetSetDescriptorType = type(FunctionType.__code__) -MemberDescriptorType = type(FunctionType.__globals__) +MemberDescriptorType = type(FunctionType.__namespace__) del sys, _f, _g, _C, _c, # Not for export diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 8739596bfc..a0c73f5b52 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -13,8 +13,7 @@ static PyMemberDef frame_memberlist[] = { {"f_back", T_OBJECT, OFF(f_back), READONLY}, {"f_code", T_OBJECT, OFF(f_code), READONLY}, - {"f_builtins", T_OBJECT, OFF(f_builtins), READONLY}, - {"f_globals", T_OBJECT, OFF(f_globals), READONLY}, + {"f_namespace", T_OBJECT, OFF(f_namespace), READONLY}, {"f_lasti", T_INT, OFF(f_lasti), READONLY}, {"f_trace_lines", T_BOOL, OFF(f_trace_lines), 0}, {"f_trace_opcodes", T_BOOL, OFF(f_trace_opcodes), 0}, @@ -30,6 +29,24 @@ frame_getlocals(PyFrameObject *f, void *closure) return f->f_locals; } +/* return a dict as expected */ +static PyObject * +frame_getglobals(PyFrameObject *f, void *closure) +{ + PyObject *d = PyModule_GetDict(f->f_namespace); + Py_XINCREF(d); + return d; +} + +/* return a dict as expected */ +static PyObject * +frame_getbuiltins(PyFrameObject *f, void *closure) +{ + PyObject *d = PyModule_GetBuiltins(f->f_namespace); + Py_XINCREF(d); + return d; +} + int PyFrame_GetLineNumber(PyFrameObject *f) { @@ -358,6 +375,8 @@ frame_settrace(PyFrameObject *f, PyObject* v, void *closure) static PyGetSetDef frame_getsetlist[] = { {"f_locals", (getter)frame_getlocals, NULL, NULL}, + {"f_globals", (getter)frame_getglobals, NULL, NULL}, + {"f_builtins", (getter)frame_getbuiltins, NULL, NULL}, {"f_lineno", (getter)frame_getlineno, (setter)frame_setlineno, NULL}, {"f_trace", (getter)frame_gettrace, (setter)frame_settrace, NULL}, @@ -434,8 +453,7 @@ frame_dealloc(PyFrameObject *f) } Py_XDECREF(f->f_back); - Py_DECREF(f->f_builtins); - Py_DECREF(f->f_globals); + Py_DECREF(f->f_namespace); Py_CLEAR(f->f_locals); Py_CLEAR(f->f_trace); Py_CLEAR(f->f_exc_type); @@ -465,8 +483,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg) Py_VISIT(f->f_back); Py_VISIT(f->f_code); - Py_VISIT(f->f_builtins); - Py_VISIT(f->f_globals); + Py_VISIT(f->f_namespace); Py_VISIT(f->f_locals); Py_VISIT(f->f_trace); Py_VISIT(f->f_exc_type); @@ -600,8 +617,6 @@ PyTypeObject PyFrame_Type = { 0, /* tp_dict */ }; -_Py_IDENTIFIER(__builtins__); - int _PyFrame_Init() { /* Before, PyId___builtins__ was a string created explicitly in @@ -612,48 +627,38 @@ int _PyFrame_Init() PyFrameObject* _Py_HOT_FUNCTION _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, - PyObject *globals, PyObject *locals) + PyObject *namespace, PyObject *locals) { PyFrameObject *back = tstate->frame; PyFrameObject *f; - PyObject *builtins; Py_ssize_t i; #ifdef Py_DEBUG - if (code == NULL || globals == NULL || !PyDict_Check(globals) || - (locals != NULL && !PyMapping_Check(locals))) { + if (code == NULL || namespace == NULL || + (!PyModule_Check(namespace) && + !PyDict_Check(namespace)) || + (locals != NULL && + !PyModule_Check(locals) && + !PyMapping_Check(locals))) { PyErr_BadInternalCall(); return NULL; } #endif - if (back == NULL || back->f_globals != globals) { - builtins = _PyDict_GetItemId(globals, &PyId___builtins__); - if (builtins) { - if (PyModule_Check(builtins)) { - builtins = PyModule_GetDict(builtins); - assert(builtins != NULL); - } - } - if (builtins == NULL) { - /* No builtins! Make up a minimal one - Give them 'None', at least. */ - builtins = PyDict_New(); - if (builtins == NULL || - PyDict_SetItemString( - builtins, "None", Py_None) < 0) - return NULL; - } - else - Py_INCREF(builtins); + /* namespace can be a dict or a module */ + if (PyModule_Check(namespace)) { + Py_INCREF(namespace); } else { - /* If we share the globals, we share the builtins. - Save a lookup and a call. */ - builtins = back->f_builtins; - assert(builtins != NULL); - Py_INCREF(builtins); + if (PyDict_Check(namespace)) { + namespace = _PyModule_FromDict(namespace); + } + else { + PyErr_BadInternalCall(); + return NULL; + } } + if (code->co_zombieframe != NULL) { f = code->co_zombieframe; code->co_zombieframe = NULL; @@ -670,7 +675,7 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras); if (f == NULL) { - Py_DECREF(builtins); + Py_DECREF(namespace); return NULL; } } @@ -683,7 +688,7 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, PyFrameObject *new_f = PyObject_GC_Resize(PyFrameObject, f, extras); if (new_f == NULL) { PyObject_GC_Del(f); - Py_DECREF(builtins); + Py_DECREF(namespace); return NULL; } f = new_f; @@ -701,12 +706,10 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL; } f->f_stacktop = f->f_valuestack; - f->f_builtins = builtins; Py_XINCREF(back); f->f_back = back; Py_INCREF(code); - Py_INCREF(globals); - f->f_globals = globals; + f->f_namespace = namespace; /* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */ if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) == (CO_NEWLOCALS | CO_OPTIMIZED)) @@ -721,7 +724,7 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, } else { if (locals == NULL) - locals = globals; + locals = _PyModule_GetDict(namespace); Py_INCREF(locals); f->f_locals = locals; } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index d376f9cab9..1cfa870883 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -8,7 +8,7 @@ #include "structmember.h" PyObject * -PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) +PyFunction_NewWithQualName(PyObject *code, PyObject *ns, PyObject *qualname) { PyFunctionObject *op; PyObject *doc, *consts, *module; @@ -27,8 +27,8 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname op->func_weakreflist = NULL; Py_INCREF(code); op->func_code = code; - Py_INCREF(globals); - op->func_globals = globals; + Py_INCREF(ns); + op->func_namespace = ns; op->func_name = ((PyCodeObject *)code)->co_name; Py_INCREF(op->func_name); op->func_defaults = NULL; /* No default arguments */ @@ -50,9 +50,13 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname op->func_module = NULL; op->func_annotations = NULL; + if (PyDict_Check(ns)) { + ns = _PyModule_FromDict(ns); + } + /* __module__: If module name is in globals, use it. Otherwise, use None. */ - module = PyDict_GetItem(globals, __name__); + module = PyDict_GetItem(PyModule_GetDict(ns), __name__); if (module) { Py_INCREF(module); op->func_module = module; @@ -90,10 +94,18 @@ PyFunction_GetGlobals(PyObject *op) PyErr_BadInternalCall(); return NULL; } - return ((PyFunctionObject *) op) -> func_globals; + return PyFunction_GET_GLOBALS(op); } -PyObject * +static PyObject * +func_get_globals(PyFunctionObject *f, void*closure) +{ + PyObject *d = PyModule_GetDict(f->func_namespace); + Py_XINCREF(d); + return d; +} + + PyObject * PyFunction_GetModule(PyObject *op) { if (!PyFunction_Check(op)) { @@ -232,11 +244,9 @@ PyFunction_SetAnnotations(PyObject *op, PyObject *annotations) #define OFF(x) offsetof(PyFunctionObject, x) static PyMemberDef func_memberlist[] = { - {"__closure__", T_OBJECT, OFF(func_closure), - RESTRICTED|READONLY}, + {"__closure__", T_OBJECT, OFF(func_closure), READONLY}, + {"__namespace__", T_OBJECT, OFF(func_namespace), READONLY}, {"__doc__", T_OBJECT, OFF(func_doc), PY_WRITE_RESTRICTED}, - {"__globals__", T_OBJECT, OFF(func_globals), - RESTRICTED|READONLY}, {"__module__", T_OBJECT, OFF(func_module), PY_WRITE_RESTRICTED}, {NULL} /* Sentinel */ }; @@ -406,6 +416,7 @@ func_set_annotations(PyFunctionObject *op, PyObject *value) static PyGetSetDef func_getsetlist[] = { {"__code__", (getter)func_get_code, (setter)func_set_code}, + {"__globals__", (getter)func_get_globals, NULL}, {"__defaults__", (getter)func_get_defaults, (setter)func_set_defaults}, {"__kwdefaults__", (getter)func_get_kwdefaults, @@ -530,7 +541,7 @@ func_dealloc(PyFunctionObject *op) if (op->func_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) op); Py_DECREF(op->func_code); - Py_DECREF(op->func_globals); + Py_DECREF(op->func_namespace); Py_XDECREF(op->func_module); Py_DECREF(op->func_name); Py_XDECREF(op->func_defaults); @@ -554,7 +565,7 @@ static int func_traverse(PyFunctionObject *f, visitproc visit, void *arg) { Py_VISIT(f->func_code); - Py_VISIT(f->func_globals); + Py_VISIT(f->func_namespace); Py_VISIT(f->func_module); Py_VISIT(f->func_defaults); Py_VISIT(f->func_kwdefaults); diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 29732633da..2817662b93 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -14,6 +14,8 @@ typedef struct { void *md_state; PyObject *md_weaklist; PyObject *md_name; /* for logging purposes after md_dict is cleared */ + PyObject *md_builtins; + int fast; /* fast lookup of globals, allowed if dict is kept internal */ } PyModuleObject; static PyMemberDef module_members[] = { @@ -43,6 +45,60 @@ PyModuleDef_Init(struct PyModuleDef* def) return (PyObject*)def; } +static int +module_add_missing(PyObject *dict, + struct _Py_Identifier *name, + PyObject *value) +{ + if (_PyDict_GetItemId(dict, name) == NULL) { + if (_PyDict_SetItemId(dict, name, value) != 0) + return 0; + } + return 1; +} + +static PyObject * +get_builtins(PyObject *d) +{ + PyObject *b = PyDict_GetItemString(d, "__builtins__"); + if (b != NULL) { + Py_INCREF(b); + return b; + } + //b = PyThreadState_GET()->interp->builtins; + b = PyEval_GetBuiltins(); + if (b != NULL) { + Py_INCREF(b); + return b; + } + /* No builtins! Make up a minimal one. */ + //fprintf(stderr, "no builtins, making dummy one\n"); + return PyDict_New(); +} + +static int +module_init(PyModuleObject *mod, PyObject *md_dict, PyObject *name) +{ + _Py_IDENTIFIER(__namespace__); + if (md_dict == NULL) + return 0; + if (name && mod->md_name == NULL && PyUnicode_CheckExact(name)) { + Py_INCREF(name); + Py_XSETREF(mod->md_name, name); + } + if (mod->md_builtins == NULL) { + mod->md_builtins = get_builtins(md_dict); + if (mod->md_builtins == NULL) { + return 0; + } + } + mod->fast = 1; + if (!module_add_missing(md_dict, &PyId___namespace__, (PyObject *)mod)) + return 0; + return 1; +} + +/* init module dict special names */ static int module_init_dict(PyModuleObject *mod, PyObject *md_dict, PyObject *name, PyObject *doc) @@ -52,33 +108,29 @@ module_init_dict(PyModuleObject *mod, PyObject *md_dict, _Py_IDENTIFIER(__package__); _Py_IDENTIFIER(__loader__); _Py_IDENTIFIER(__spec__); + _Py_IDENTIFIER(__builtins__); - if (md_dict == NULL) - return -1; if (doc == NULL) doc = Py_None; - - if (_PyDict_SetItemId(md_dict, &PyId___name__, name) != 0) + if (!module_add_missing(md_dict, &PyId___name__, name)) return -1; - if (_PyDict_SetItemId(md_dict, &PyId___doc__, doc) != 0) + if (!module_add_missing(md_dict, &PyId___doc__, doc)) return -1; - if (_PyDict_SetItemId(md_dict, &PyId___package__, Py_None) != 0) + if (!module_add_missing(md_dict, &PyId___package__, Py_None)) return -1; - if (_PyDict_SetItemId(md_dict, &PyId___loader__, Py_None) != 0) + if (!module_add_missing(md_dict, &PyId___loader__, Py_None)) return -1; - if (_PyDict_SetItemId(md_dict, &PyId___spec__, Py_None) != 0) + if (!module_add_missing(md_dict, &PyId___spec__, Py_None)) return -1; - if (PyUnicode_CheckExact(name)) { - Py_INCREF(name); - Py_XSETREF(mod->md_name, name); + if (mod->md_builtins) { + if (!module_add_missing(md_dict, &PyId___builtins__, mod->md_builtins)) + return -1; } - return 0; } - PyObject * -PyModule_NewObject(PyObject *name) +module_new_with_dict(PyObject *name, PyObject *dict) { PyModuleObject *m; m = PyObject_GC_New(PyModuleObject, &PyModule_Type); @@ -88,15 +140,31 @@ PyModule_NewObject(PyObject *name) m->md_state = NULL; m->md_weaklist = NULL; m->md_name = NULL; - m->md_dict = PyDict_New(); - if (module_init_dict(m, m->md_dict, name, NULL) != 0) - goto fail; + m->md_builtins = NULL; + m->md_dict = dict; + if (!module_init(m, dict, NULL)) { + Py_DECREF(m); + return NULL; + } PyObject_GC_Track(m); return (PyObject *)m; +} - fail: - Py_DECREF(m); - return NULL; +PyObject * +PyModule_NewObject(PyObject *name) +{ + PyObject *m; + PyObject *dict = PyDict_New(); + if (dict == NULL) + return NULL; + m = module_new_with_dict(name, dict); + if (m != NULL) { + if (module_init_dict((PyModuleObject *)m, dict, name, NULL) < 0) { + Py_DECREF(m); + return NULL; + } + } + return m; } PyObject * @@ -111,6 +179,40 @@ PyModule_New(const char *name) return module; } +/* create module object from 'globals' dict */ +PyObject * +_PyModule_FromDict(PyObject *globals) +{ + PyObject *m; + _Py_IDENTIFIER(__namespace__); + PyObject *ns = _PyDict_GetItemId(globals, &PyId___namespace__); + if (ns != NULL) { + /* already have a anonymous module, return it */ + m = ns; + Py_INCREF(ns); + } + else { + /* create a new anonymous module */ + //fprintf(stderr, "creating anon namespace\n"); + _Py_IDENTIFIER(__name__); + PyObject *name = _PyDict_GetItemId(globals, &PyId___name__); + if (name == NULL) { + name = PyUnicode_InternFromString(""); + if (name == NULL) + return NULL; + } + else { + Py_INCREF(name); + } + m = module_new_with_dict(name, globals); + Py_DECREF(name); + if (m != NULL) { + Py_INCREF(globals); + } + } + return m; +} + /* Check API/ABI version * Issues a warning on mismatch, which is usually not fatal. * Returns 0 if an exception is raised. @@ -448,19 +550,90 @@ PyModule_SetDocString(PyObject *m, const char *doc) return 0; } +int +_PyModule_SetBuiltins(PyObject *m, PyObject *b) +{ + if (!PyModule_Check(m) || !PyDict_Check(b)) { + PyErr_BadInternalCall(); + return 0; + } + if (PyDict_SetItemString(PyModule_GetDict(m), "__builtins__", b) != 0) + return 0; + ((PyModuleObject *)m)->md_builtins = b; + return 1; +} + PyObject * -PyModule_GetDict(PyObject *m) +_PyModule_GetDict(PyObject *m) { PyObject *d; +#if Py_DEBUG if (!PyModule_Check(m)) { PyErr_BadInternalCall(); return NULL; } +#endif d = ((PyModuleObject *)m) -> md_dict; assert(d != NULL); return d; } +PyObject * +PyModule_ClearFastFlag(PyObject *m) +{ +#if Py_DEBUG + if (!PyModule_Check(m)) { + PyErr_BadInternalCall(); + return NULL; + } +#endif + ((PyModuleObject *)m)->fast = 0; +} + +PyObject * +PyModule_GetDict(PyObject *m) +{ +#if Py_DEBUG + if (!PyModule_Check(m)) { + PyErr_BadInternalCall(); + return NULL; + } +#endif + ((PyModuleObject *)m)->fast = 0; + return _PyModule_GetDict(m); +} + +PyObject* +PyModule_GetBuiltins(PyObject *o) +{ + PyModuleObject *m = (PyModuleObject *)o; +#if Py_DEBUG + if (!PyModule_Check(o)) { + PyErr_BadInternalCall(); + return NULL; + } +#endif + if (m->md_builtins == NULL) { + fprintf(stderr, "missing builtins\n"); + m->md_builtins = PyThreadState_GET()->interp->builtins; + } + return m->md_builtins; +} + +int +_PyModule_EnsureBuiltins(PyObject *m) +{ + if (!PyModule_Check(m)) { + PyErr_BadInternalCall(); + return 0; + } + PyObject *b = PyEval_GetBuiltins(); + if ((PyModule_GetBuiltins(m) == b)) { + return 1; + } + return _PyModule_SetBuiltins(m, b); +} + PyObject* PyModule_GetNameObject(PyObject *m) { @@ -556,6 +729,15 @@ _PyModule_Clear(PyObject *m) _PyModule_ClearDict(d); } +/* return true if module key needs clearing */ +static int +module_key_needs_clear(PyObject *key) +{ + return ((PyUnicode_READ_CHAR(key, 0) == '_') && + (_PyUnicode_EqualToASCIIString(key, "__builtins__") || + _PyUnicode_EqualToASCIIString(key, "__namespace__"))); +} + void _PyModule_ClearDict(PyObject *d) { @@ -592,9 +774,7 @@ _PyModule_ClearDict(PyObject *d) pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - if (PyUnicode_READ_CHAR(key, 0) != '_' || - !_PyUnicode_EqualToASCIIString(key, "__builtins__")) - { + if (module_key_needs_clear(key)) { if (Py_VerboseFlag > 1) { const char *s = PyUnicode_AsUTF8(key); if (s != NULL) @@ -644,6 +824,8 @@ module___init___impl(PyModuleObject *self, PyObject *name, PyObject *doc) return -1; self->md_dict = dict; } + if (!module_init(self, dict, name)) + return -1; if (module_init_dict(self, dict, name, doc) < 0) return -1; return 0; @@ -662,6 +844,7 @@ module_dealloc(PyModuleObject *m) m->md_def->m_free(m); Py_XDECREF(m->md_dict); Py_XDECREF(m->md_name); + Py_XDECREF(m->md_builtins); if (m->md_state != NULL) PyMem_FREE(m->md_state); Py_TYPE(m)->tp_free((PyObject *)m); @@ -706,6 +889,7 @@ module_traverse(PyModuleObject *m, visitproc visit, void *arg) if (res) return res; } + Py_VISIT(m->md_builtins); Py_VISIT(m->md_dict); return 0; } @@ -718,6 +902,7 @@ module_clear(PyModuleObject *m) if (res) return res; } + Py_CLEAR(m->md_builtins); Py_CLEAR(m->md_dict); return 0; } diff --git a/Python/_warnings.c b/Python/_warnings.c index a9f96410c8..0fc420412e 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -658,7 +658,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, *lineno = 1; } else { - globals = f->f_globals; + globals = PyModule_GetDict(f->f_namespace); *lineno = PyFrame_GetLineNumber(f); } diff --git a/Python/ceval.c b/Python/ceval.c index cf0c6c9ae2..05688692bd 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -500,6 +500,35 @@ _Py_CheckRecursiveCall(const char *where) return 0; } +#define GLOBALS(f) _PyModule_GetDict(f->f_namespace) +#define BUILTINS(f) PyModule_GetBuiltins(f->f_namespace) + +#ifdef Py_DEBUG +/* dump backtrace to stdout */ +static void +dump_traceback(void) +{ + PyThreadState *tstate = PyThreadState_GET(); + if (NULL != tstate && NULL != tstate->frame) { + PyFrameObject *frame = tstate->frame; + + fprintf(stderr, "Python stack trace:\n"); + while (NULL != frame) { + // int line = frame->f_lineno; + /* + frame->f_lineno will not always return the correct line number + you need to call PyCode_Addr2Line(). + */ + int line = PyCode_Addr2Line(frame->f_code, frame->f_lasti); + const char *filename = PyUnicode_AsUTF8(frame->f_code->co_filename); + const char *funcname = PyUnicode_AsUTF8(frame->f_code->co_name); + fprintf(stderr, " %s(%d): %s\n", filename, line, funcname); + frame = frame->f_back; + } + } +} +#endif + /* Status code for main loop (reason for stack unwind) */ enum why_code { WHY_NOT = 0x0001, /* No error */ @@ -922,7 +951,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } #ifdef LLTRACE - lltrace = _PyDict_GetItemId(f->f_globals, &PyId___ltrace__) != NULL; + lltrace = _PyDict_GetItemId(GLOBALS(f), &PyId___ltrace__) != NULL; #endif why = WHY_NOT; @@ -934,7 +963,10 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) /* PyEval_EvalFrameEx() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ - assert(!PyErr_Occurred()); + if (PyErr_Occurred()) { + dump_traceback(); + Py_FatalError("ceval: eval called with exeception set"); + } #endif for (;;) { @@ -1989,8 +2021,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) _Py_IDENTIFIER(__build_class__); PyObject *bc; - if (PyDict_CheckExact(f->f_builtins)) { - bc = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); + if (PyDict_CheckExact(BUILTINS(f))) { + bc = _PyDict_GetItemId(BUILTINS(f), &PyId___build_class__); if (bc == NULL) { PyErr_SetString(PyExc_NameError, "__build_class__ not found"); @@ -2002,7 +2034,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); if (build_class_str == NULL) goto error; - bc = PyObject_GetItem(f->f_builtins, build_class_str); + bc = PyObject_GetItem(BUILTINS(f), build_class_str); if (bc == NULL) { if (PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_SetString(PyExc_NameError, @@ -2129,7 +2161,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PyObject *name = GETITEM(names, oparg); PyObject *v = POP(); int err; - err = PyDict_SetItem(f->f_globals, name, v); + err = PyDict_SetItem(GLOBALS(f), name, v); Py_DECREF(v); if (err != 0) goto error; @@ -2139,7 +2171,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) TARGET(DELETE_GLOBAL) { PyObject *name = GETITEM(names, oparg); int err; - err = PyDict_DelItem(f->f_globals, name); + err = PyDict_DelItem(GLOBALS(f), name); if (err != 0) { format_exc_check_arg( PyExc_NameError, NAME_ERROR_MSG, name); @@ -2170,11 +2202,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } } if (v == NULL) { - v = PyDict_GetItem(f->f_globals, name); + v = PyDict_GetItem(GLOBALS(f), name); Py_XINCREF(v); if (v == NULL) { - if (PyDict_CheckExact(f->f_builtins)) { - v = PyDict_GetItem(f->f_builtins, name); + if (PyDict_CheckExact(BUILTINS(f))) { + v = PyDict_GetItem(BUILTINS(f), name); if (v == NULL) { format_exc_check_arg( PyExc_NameError, @@ -2184,7 +2216,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) Py_INCREF(v); } else { - v = PyObject_GetItem(f->f_builtins, name); + v = PyObject_GetItem(BUILTINS(f), name); if (v == NULL) { if (PyErr_ExceptionMatches(PyExc_KeyError)) format_exc_check_arg( @@ -2202,11 +2234,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) TARGET(LOAD_GLOBAL) { PyObject *name = GETITEM(names, oparg); PyObject *v; - if (PyDict_CheckExact(f->f_globals) - && PyDict_CheckExact(f->f_builtins)) + if (PyDict_CheckExact(GLOBALS(f)) + && PyDict_CheckExact(BUILTINS(f))) { - v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, - (PyDictObject *)f->f_builtins, + v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(f), + (PyDictObject *)BUILTINS(f), name); if (v == NULL) { if (!_PyErr_OCCURRED()) { @@ -2223,14 +2255,14 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) /* Slow-path if globals or builtins is not a dict */ /* namespace 1: globals */ - v = PyObject_GetItem(f->f_globals, name); + v = PyObject_GetItem(GLOBALS(f), name); if (v == NULL) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) goto error; PyErr_Clear(); /* namespace 2: builtins */ - v = PyObject_GetItem(f->f_builtins, name); + v = PyObject_GetItem(BUILTINS(f), name); if (v == NULL) { if (PyErr_ExceptionMatches(PyExc_KeyError)) format_exc_check_arg( @@ -3298,7 +3330,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PyObject *qualname = POP(); PyObject *codeobj = POP(); PyFunctionObject *func = (PyFunctionObject *) - PyFunction_NewWithQualName(codeobj, f->f_globals, qualname); + PyFunction_NewWithQualName(codeobj, f->f_namespace, qualname); Py_DECREF(codeobj); Py_DECREF(qualname); @@ -4563,7 +4595,7 @@ PyEval_GetBuiltins(void) if (current_frame == NULL) return PyThreadState_GET()->interp->builtins; else - return current_frame->f_builtins; + return BUILTINS(current_frame); } PyObject * @@ -4589,8 +4621,8 @@ PyEval_GetGlobals(void) if (current_frame == NULL) return NULL; - assert(current_frame->f_globals != NULL); - return current_frame->f_globals; + assert(current_frame->f_namespace != NULL); + return GLOBALS(current_frame); } PyFrameObject * @@ -4879,7 +4911,7 @@ import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *leve PyObject *import_func, *res; PyObject* stack[5]; - import_func = _PyDict_GetItemId(f->f_builtins, &PyId___import__); + import_func = _PyDict_GetItemId(BUILTINS(f), &PyId___import__); if (import_func == NULL) { PyErr_SetString(PyExc_ImportError, "__import__ not found"); return NULL; @@ -4893,7 +4925,7 @@ import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *leve } res = PyImport_ImportModuleLevelObject( name, - f->f_globals, + GLOBALS(f), f->f_locals == NULL ? Py_None : f->f_locals, fromlist, ilevel); @@ -4903,7 +4935,7 @@ import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *leve Py_INCREF(import_func); stack[0] = name; - stack[1] = f->f_globals; + stack[1] = GLOBALS(f); stack[2] = f->f_locals == NULL ? Py_None : f->f_locals; stack[3] = fromlist; stack[4] = level;