Commit f2bfd54d authored by Georg Brandl's avatar Georg Brandl

Properly check for consistency with the third argument of

compile() when compiling an AST node.
parent ea13dc62
...@@ -501,5 +501,5 @@ keyword_ty _Py_keyword(identifier arg, expr_ty value, PyArena *arena); ...@@ -501,5 +501,5 @@ keyword_ty _Py_keyword(identifier arg, expr_ty value, PyArena *arena);
alias_ty _Py_alias(identifier name, identifier asname, PyArena *arena); alias_ty _Py_alias(identifier name, identifier asname, PyArena *arena);
PyObject* PyAST_mod2obj(mod_ty t); PyObject* PyAST_mod2obj(mod_ty t);
mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena); mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode);
int PyAST_Check(PyObject* obj); int PyAST_Check(PyObject* obj);
...@@ -441,6 +441,20 @@ if 1: ...@@ -441,6 +441,20 @@ if 1:
self.assert_(type(ast) == _ast.Module) self.assert_(type(ast) == _ast.Module)
co2 = compile(ast, '%s3' % fname, 'exec') co2 = compile(ast, '%s3' % fname, 'exec')
self.assertEqual(co1, co2) self.assertEqual(co1, co2)
# the code object's filename comes from the second compilation step
self.assertEqual(co2.co_filename, '%s3' % fname)
# raise exception when node type doesn't match with compile mode
co1 = compile('print 1', '<string>', 'exec', _ast.PyCF_ONLY_AST)
self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
# raise exception when node type is no start node
self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
# raise exception when node has invalid children
ast = _ast.Module()
ast.body = [_ast.BoolOp()]
self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
def test_main(): def test_main():
......
...@@ -954,13 +954,20 @@ PyObject* PyAST_mod2obj(mod_ty t) ...@@ -954,13 +954,20 @@ PyObject* PyAST_mod2obj(mod_ty t)
return ast2obj_mod(t); return ast2obj_mod(t);
} }
mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena) /* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode)
{ {
mod_ty res; mod_ty res;
PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type,
(PyObject*)Interactive_type};
char *req_name[] = {"Module", "Expression", "Interactive"};
assert(0 <= mode && mode <= 2);
init_types(); init_types();
if (!PyObject_IsInstance(ast, (PyObject*)mod_type)) {
PyErr_SetString(PyExc_TypeError, "expected either Module, Interactive " if (!PyObject_IsInstance(ast, req_type[mode])) {
"or Expression node"); PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
req_name[mode], Py_TYPE(ast)->tp_name);
return NULL; return NULL;
} }
if (obj2ast_mod(ast, &res, arena) != 0) if (obj2ast_mod(ast, &res, arena) != 0)
...@@ -1016,7 +1023,7 @@ def main(srcfile): ...@@ -1016,7 +1023,7 @@ def main(srcfile):
) )
c.visit(mod) c.visit(mod)
print >>f, "PyObject* PyAST_mod2obj(mod_ty t);" print >>f, "PyObject* PyAST_mod2obj(mod_ty t);"
print >>f, "mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena);" print >>f, "mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode);"
print >>f, "int PyAST_Check(PyObject* obj);" print >>f, "int PyAST_Check(PyObject* obj);"
f.close() f.close()
......
...@@ -5944,13 +5944,20 @@ PyObject* PyAST_mod2obj(mod_ty t) ...@@ -5944,13 +5944,20 @@ PyObject* PyAST_mod2obj(mod_ty t)
return ast2obj_mod(t); return ast2obj_mod(t);
} }
mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena) /* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */
mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode)
{ {
mod_ty res; mod_ty res;
PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type,
(PyObject*)Interactive_type};
char *req_name[] = {"Module", "Expression", "Interactive"};
assert(0 <= mode && mode <= 2);
init_types(); init_types();
if (!PyObject_IsInstance(ast, (PyObject*)mod_type)) {
PyErr_SetString(PyExc_TypeError, "expected either Module, Interactive " if (!PyObject_IsInstance(ast, req_type[mode])) {
"or Expression node"); PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s",
req_name[mode], Py_TYPE(ast)->tp_name);
return NULL; return NULL;
} }
if (obj2ast_mod(ast, &res, arena) != 0) if (obj2ast_mod(ast, &res, arena) != 0)
......
...@@ -466,7 +466,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -466,7 +466,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
char *str; char *str;
char *filename; char *filename;
char *startstr; char *startstr;
int start; int mode = -1;
int dont_inherit = 0; int dont_inherit = 0;
int supplied_flags = 0; int supplied_flags = 0;
PyCompilerFlags cf; PyCompilerFlags cf;
...@@ -474,6 +474,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -474,6 +474,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
Py_ssize_t length; Py_ssize_t length;
static char *kwlist[] = {"source", "filename", "mode", "flags", static char *kwlist[] = {"source", "filename", "mode", "flags",
"dont_inherit", NULL}; "dont_inherit", NULL};
int start[] = {Py_file_input, Py_eval_input, Py_single_input};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile",
kwlist, &cmd, &filename, &startstr, kwlist, &cmd, &filename, &startstr,
...@@ -495,6 +496,18 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -495,6 +496,18 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
PyEval_MergeCompilerFlags(&cf); PyEval_MergeCompilerFlags(&cf);
} }
if (strcmp(startstr, "exec") == 0)
mode = 0;
else if (strcmp(startstr, "eval") == 0)
mode = 1;
else if (strcmp(startstr, "single") == 0)
mode = 2;
else {
PyErr_SetString(PyExc_ValueError,
"compile() arg 3 must be 'exec', 'eval' or 'single'");
return NULL;
}
if (PyAST_Check(cmd)) { if (PyAST_Check(cmd)) {
if (supplied_flags & PyCF_ONLY_AST) { if (supplied_flags & PyCF_ONLY_AST) {
Py_INCREF(cmd); Py_INCREF(cmd);
...@@ -505,7 +518,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -505,7 +518,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
mod_ty mod; mod_ty mod;
arena = PyArena_New(); arena = PyArena_New();
mod = PyAST_obj2mod(cmd, arena); mod = PyAST_obj2mod(cmd, arena, mode);
if (mod == NULL) { if (mod == NULL) {
PyArena_Free(arena); PyArena_Free(arena);
return NULL; return NULL;
...@@ -526,19 +539,6 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -526,19 +539,6 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
cf.cf_flags |= PyCF_SOURCE_IS_UTF8; cf.cf_flags |= PyCF_SOURCE_IS_UTF8;
} }
#endif #endif
/* XXX: is it possible to pass start to the PyAST_ branch? */
if (strcmp(startstr, "exec") == 0)
start = Py_file_input;
else if (strcmp(startstr, "eval") == 0)
start = Py_eval_input;
else if (strcmp(startstr, "single") == 0)
start = Py_single_input;
else {
PyErr_SetString(PyExc_ValueError,
"compile() arg 3 must be 'exec'"
"or 'eval' or 'single'");
goto cleanup;
}
if (PyObject_AsReadBuffer(cmd, (const void **)&str, &length)) if (PyObject_AsReadBuffer(cmd, (const void **)&str, &length))
goto cleanup; goto cleanup;
...@@ -547,7 +547,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -547,7 +547,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
"compile() expected string without null bytes"); "compile() expected string without null bytes");
goto cleanup; goto cleanup;
} }
result = Py_CompileStringFlags(str, filename, start, &cf); result = Py_CompileStringFlags(str, filename, start[mode], &cf);
cleanup: cleanup:
Py_XDECREF(tmp); Py_XDECREF(tmp);
return result; return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment