extended exec() implementation, mostly copied from Py3.1
authorStefan Behnel <scoder@users.berlios.de>
Wed, 19 Aug 2009 14:48:34 +0000 (16:48 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Wed, 19 Aug 2009 14:48:34 +0000 (16:48 +0200)
Cython/Compiler/Builtin.py
tests/run/exectest.pyx

index 5f85810a43e4f29b57ff8f05111671c63580ab22..6cc1a1fca3ef104add653eefc33d51d4066f277d 100644 (file)
@@ -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 = """
index 2e297756a8f4e089dbfb7c0f89d59f710eb00a96..70a2a0d4c1d98199a7253e4bb86f81e4fe75f121 100644 (file)
@@ -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