From: Stefan Behnel <scoder@users.berlios.de>
Date: Wed, 19 Aug 2009 14:48:34 +0000 (+0200)
Subject: extended exec() implementation, mostly copied from Py3.1
X-Git-Tag: 0.12.alpha0~224^2~2
X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=6caf44024293af135007b800505809c2ccc600b8;p=cython.git

extended exec() implementation, mostly copied from Py3.1
---

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"<string>", u"exec")
+    exec c in d