make sure the parser flags and passed onto the compiler
This fixes "from __future__ import unicode_literals" in an exec statment See #4225
This commit is contained in:
parent
44a90c95ce
commit
dcee09d920
|
@ -106,6 +106,11 @@ class FutureTest(unittest.TestCase):
|
|||
test_support.unload("test.test_future5")
|
||||
from test import test_future5
|
||||
|
||||
def test_unicode_literals_exec(self):
|
||||
scope = {}
|
||||
exec "from __future__ import unicode_literals; x = ''" in scope
|
||||
self.assertTrue(isinstance(scope["x"], unicode))
|
||||
|
||||
|
||||
def test_main():
|
||||
test_support.run_unittest(FutureTest)
|
||||
|
|
|
@ -25,6 +25,15 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
|
|||
def check_expr(self, s):
|
||||
self.roundtrip(parser.expr, s)
|
||||
|
||||
def test_flags_passed(self):
|
||||
# The unicode literals flags has to be passed from the paser to AST
|
||||
# generation.
|
||||
suite = parser.suite("from __future__ import unicode_literals; x = ''")
|
||||
code = suite.compile()
|
||||
scope = {}
|
||||
exec code in scope
|
||||
self.assertTrue(isinstance(scope["x"], unicode))
|
||||
|
||||
def check_suite(self, s):
|
||||
self.roundtrip(parser.suite, s)
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #4225: ``from __future__ import unicode_literals`` didn't work in an
|
||||
exec statement.
|
||||
|
||||
- Issue #4176: Fixed a crash when pickling an object which ``__reduce__``
|
||||
method does not return iterators for the 4th and 5th items.
|
||||
|
||||
|
|
|
@ -26,12 +26,20 @@
|
|||
*/
|
||||
|
||||
#include "Python.h" /* general Python API */
|
||||
#include "Python-ast.h" /* mod_ty */
|
||||
#include "graminit.h" /* symbols defined in the grammar */
|
||||
#include "node.h" /* internal parser structure */
|
||||
#include "errcode.h" /* error codes for PyNode_*() */
|
||||
#include "token.h" /* token definitions */
|
||||
#include "grammar.h"
|
||||
#include "parsetok.h"
|
||||
/* ISTERMINAL() / ISNONTERMINAL() */
|
||||
#include "compile.h" /* PyNode_Compile() */
|
||||
#include "compile.h"
|
||||
#undef Yield
|
||||
#include "ast.h"
|
||||
#include "pyarena.h"
|
||||
|
||||
extern grammar _PyParser_Grammar; /* From graminit.c */
|
||||
|
||||
#ifdef lint
|
||||
#include <note.h>
|
||||
|
@ -156,6 +164,7 @@ typedef struct {
|
|||
PyObject_HEAD /* standard object header */
|
||||
node* st_node; /* the node* returned by the parser */
|
||||
int st_type; /* EXPR or SUITE ? */
|
||||
PyCompilerFlags st_flags; /* Parser and compiler flags */
|
||||
} PyST_Object;
|
||||
|
||||
|
||||
|
@ -260,6 +269,7 @@ parser_newstobject(node *st, int type)
|
|||
if (o != 0) {
|
||||
o->st_node = st;
|
||||
o->st_type = type;
|
||||
o->st_flags.cf_flags = 0;
|
||||
}
|
||||
else {
|
||||
PyNode_Free(st);
|
||||
|
@ -394,6 +404,8 @@ static PyObject*
|
|||
parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject* res = 0;
|
||||
PyArena* arena;
|
||||
mod_ty mod;
|
||||
char* str = "<syntax-tree>";
|
||||
int ok;
|
||||
|
||||
|
@ -406,8 +418,16 @@ parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw)
|
|||
ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1],
|
||||
&str);
|
||||
|
||||
if (ok)
|
||||
res = (PyObject *)PyNode_Compile(self->st_node, str);
|
||||
if (ok) {
|
||||
arena = PyArena_New();
|
||||
if (arena) {
|
||||
mod = PyAST_FromNode(self->st_node, &(self->st_flags), str, arena);
|
||||
if (mod) {
|
||||
res = (PyObject *)PyAST_Compile(mod, str, &(self->st_flags), arena);
|
||||
}
|
||||
PyArena_Free(arena);
|
||||
}
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
@ -523,16 +543,25 @@ parser_do_parse(PyObject *args, PyObject *kw, char *argspec, int type)
|
|||
{
|
||||
char* string = 0;
|
||||
PyObject* res = 0;
|
||||
int flags = 0;
|
||||
perrdetail err;
|
||||
|
||||
static char *keywords[] = {"source", NULL};
|
||||
|
||||
if (PyArg_ParseTupleAndKeywords(args, kw, argspec, keywords, &string)) {
|
||||
node* n = PyParser_SimpleParseString(string,
|
||||
(type == PyST_EXPR)
|
||||
? eval_input : file_input);
|
||||
node* n = PyParser_ParseStringFlagsFilenameEx(string, NULL,
|
||||
&_PyParser_Grammar,
|
||||
(type == PyST_EXPR)
|
||||
? eval_input : file_input,
|
||||
&err, &flags);
|
||||
|
||||
if (n)
|
||||
if (n) {
|
||||
res = parser_newstobject(n, type);
|
||||
if (res)
|
||||
((PyST_Object *)res)->st_flags.cf_flags = flags & PyCF_MASK;
|
||||
}
|
||||
else
|
||||
PyParser_SetError(&err);
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
|
|
@ -1417,16 +1417,19 @@ PyParser_ASTFromString(const char *s, const char *filename, int start,
|
|||
PyCompilerFlags *flags, PyArena *arena)
|
||||
{
|
||||
mod_ty mod;
|
||||
PyCompilerFlags localflags;
|
||||
perrdetail err;
|
||||
int iflags = PARSER_FLAGS(flags);
|
||||
|
||||
node *n = PyParser_ParseStringFlagsFilenameEx(s, filename,
|
||||
&_PyParser_Grammar, start, &err,
|
||||
&iflags);
|
||||
if (flags == NULL) {
|
||||
localflags.cf_flags = 0;
|
||||
flags = &localflags;
|
||||
}
|
||||
if (n) {
|
||||
if (flags) {
|
||||
flags->cf_flags |= iflags & PyCF_MASK;
|
||||
}
|
||||
flags->cf_flags |= iflags & PyCF_MASK;
|
||||
mod = PyAST_FromNode(n, flags, filename, arena);
|
||||
PyNode_Free(n);
|
||||
return mod;
|
||||
|
@ -1443,15 +1446,18 @@ PyParser_ASTFromFile(FILE *fp, const char *filename, int start, char *ps1,
|
|||
PyArena *arena)
|
||||
{
|
||||
mod_ty mod;
|
||||
PyCompilerFlags localflags;
|
||||
perrdetail err;
|
||||
int iflags = PARSER_FLAGS(flags);
|
||||
|
||||
node *n = PyParser_ParseFileFlagsEx(fp, filename, &_PyParser_Grammar,
|
||||
start, ps1, ps2, &err, &iflags);
|
||||
if (flags == NULL) {
|
||||
localflags.cf_flags = 0;
|
||||
flags = &localflags;
|
||||
}
|
||||
if (n) {
|
||||
if (flags) {
|
||||
flags->cf_flags |= iflags & PyCF_MASK;
|
||||
}
|
||||
flags->cf_flags |= iflags & PyCF_MASK;
|
||||
mod = PyAST_FromNode(n, flags, filename, arena);
|
||||
PyNode_Free(n);
|
||||
return mod;
|
||||
|
|
Loading…
Reference in New Issue