From 6caf44024293af135007b800505809c2ccc600b8 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 19 Aug 2009 16:48:34 +0200 Subject: [PATCH] extended exec() implementation, mostly copied from Py3.1 --- Cython/Compiler/Builtin.py | 40 +++++++++++++++++++++++++------------- tests/run/exectest.pyx | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index 5f85810a..6cc1a1fc 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -165,32 +165,42 @@ pyexec_utility_code = UtilityCode( proto = """ static PyObject* __Pyx_PyRun(PyObject*, PyObject*, PyObject*); """, -impl = """ +impl = ''' static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) { PyObject* result; PyObject* s = 0; char *code = 0; - if (!locals && !globals) { - globals = PyModule_GetDict(%s);""" % Naming.module_cname + """ + if (!globals || globals == Py_None) { + globals = PyModule_GetDict(%s);''' % Naming.module_cname + ''' if (!globals) goto bad; + } else if (!PyDict_Check(globals)) { + PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s", + globals->ob_type->tp_name); + goto bad; + } + if (!locals || locals == Py_None) { locals = globals; - } else if (!locals) { - locals = globals; - } else if (!globals) { - globals = locals; } + if (PyDict_GetItemString(globals, "__builtins__") == NULL) { PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins()); } - + if (PyCode_Check(o)) { + if (PyCode_GetNumFree((PyCodeObject *)o) > 0) { + PyErr_SetString(PyExc_TypeError, + "code object passed to exec() may not contain free variables"); + goto bad; + } result = PyEval_EvalCode((PyCodeObject *)o, globals, locals); - } - else { + } else { + PyCompilerFlags cf; + cf.cf_flags = 0; if (PyUnicode_Check(o)) { + cf.cf_flags = PyCF_SOURCE_IS_UTF8; s = PyUnicode_AsUTF8String(o); if (!s) goto bad; o = s; @@ -208,16 +218,20 @@ static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) { #else code = PyString_AS_STRING(o); #endif - result = PyRun_String(code, Py_file_input, globals, locals); + if (PyEval_MergeCompilerFlags(&cf)) { + result = PyRun_StringFlags(code, Py_file_input, globals, locals, &cf); + } else { + result = PyRun_String(code, Py_file_input, globals, locals); + } + Py_XDECREF(s); } - Py_XDECREF(s); return result; bad: Py_XDECREF(s); return 0; } -""") +''') intern_utility_code = UtilityCode( proto = """ diff --git a/tests/run/exectest.pyx b/tests/run/exectest.pyx index 2e297756..70a2a0d4 100644 --- a/tests/run/exectest.pyx +++ b/tests/run/exectest.pyx @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + __doc__ = u""" #>>> a #Traceback (most recent call last): @@ -43,6 +45,21 @@ __doc__ = u""" >>> list(add_iter()) [2, 3, 4, 5] +>>> d = {} +>>> test_encoding(d, None) +>>> print(d['b']) +üöä + +>>> d = {} +>>> test_encoding_unicode(d, None) +>>> print(d['b']) +üöä + +>>> d = dict(a=1, c=3) +>>> test_compile(d) +>>> d['b'] +4 + >>> # errors >>> d1, d2 = {}, {} @@ -76,3 +93,23 @@ def test(): yield x+1 """ % varref in d return d[u'test'] + +import sys + +def test_encoding(d1, d2): + if sys.version_info[0] >= 3: + s = "b = 'üöä'" + else: + s = "# -*- coding: utf-8 -*-" + "\n" + "b = u'üöä'" + exec s in d1, d2 + +def test_encoding_unicode(d1, d2): + if sys.version_info[0] >= 3: + s = u"b = 'üöä'" + else: + s = u"b = u'üöä'" + exec s in d1, d2 + +def test_compile(d): + c = compile(u"b = a+c", u"", u"exec") + exec c in d -- 2.26.2