bpo-32892: Use ast.Constant instead of specific constant AST types. (GH-9445)

This commit is contained in:
Serhiy Storchaka 2018-09-27 17:42:37 +03:00 committed by GitHub
parent a94ee12c26
commit 3f22811fef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 337 additions and 678 deletions

View File

@ -78,8 +78,8 @@ Node classes
node = ast.UnaryOp() node = ast.UnaryOp()
node.op = ast.USub() node.op = ast.USub()
node.operand = ast.Num() node.operand = ast.Constant()
node.operand.n = 5 node.operand.value = 5
node.operand.lineno = 0 node.operand.lineno = 0
node.operand.col_offset = 0 node.operand.col_offset = 0
node.lineno = 0 node.lineno = 0
@ -87,9 +87,16 @@ Node classes
or the more compact :: or the more compact ::
node = ast.UnaryOp(ast.USub(), ast.Num(5, lineno=0, col_offset=0), node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
lineno=0, col_offset=0) lineno=0, col_offset=0)
.. deprecated:: 3.8
Class :class:`ast.Constant` is now used for all constants. Old classes
:class:`ast.Num`, :class:`ast.Str`, :class:`ast.Bytes`,
:class:`ast.NameConstant` and :class:`ast.Ellipsis` are still available,
but they will be removed in future Python releases.
.. _abstract-grammar: .. _abstract-grammar:
@ -239,7 +246,7 @@ and classes for traversing abstract syntax trees:
def visit_Name(self, node): def visit_Name(self, node):
return copy_location(Subscript( return copy_location(Subscript(
value=Name(id='data', ctx=Load()), value=Name(id='data', ctx=Load()),
slice=Index(value=Str(s=node.id)), slice=Index(value=Constant(value=node.id)),
ctx=node.ctx ctx=node.ctx
), node) ), node)

View File

@ -262,6 +262,11 @@ Deprecated
(Contributed by Berker Peksag in :issue:`9372`.) (Contributed by Berker Peksag in :issue:`9372`.)
* :mod:`ast` classes ``Num``, ``Str``, ``Bytes``, ``NameConstant`` and
``Ellipsis`` are considered deprecated and will be removed in future Python
versions. :class:`~ast.Constant` should be used instead.
(Contributed by Serhiy Storchaka in :issue:`32892`.)
Removed Removed
======= =======

36
Include/Python-ast.h generated
View File

@ -208,11 +208,10 @@ enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8, IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11, SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11,
Await_kind=12, Yield_kind=13, YieldFrom_kind=14, Await_kind=12, Yield_kind=13, YieldFrom_kind=14,
Compare_kind=15, Call_kind=16, Num_kind=17, Str_kind=18, Compare_kind=15, Call_kind=16, FormattedValue_kind=17,
FormattedValue_kind=19, JoinedStr_kind=20, Bytes_kind=21, JoinedStr_kind=18, Constant_kind=19, Attribute_kind=20,
NameConstant_kind=22, Ellipsis_kind=23, Constant_kind=24, Subscript_kind=21, Starred_kind=22, Name_kind=23,
Attribute_kind=25, Subscript_kind=26, Starred_kind=27, List_kind=24, Tuple_kind=25};
Name_kind=28, List_kind=29, Tuple_kind=30};
struct _expr { struct _expr {
enum _expr_kind kind; enum _expr_kind kind;
union { union {
@ -297,14 +296,6 @@ struct _expr {
asdl_seq *keywords; asdl_seq *keywords;
} Call; } Call;
struct {
object n;
} Num;
struct {
string s;
} Str;
struct { struct {
expr_ty value; expr_ty value;
int conversion; int conversion;
@ -315,14 +306,6 @@ struct _expr {
asdl_seq *values; asdl_seq *values;
} JoinedStr; } JoinedStr;
struct {
bytes s;
} Bytes;
struct {
singleton value;
} NameConstant;
struct { struct {
constant value; constant value;
} Constant; } Constant;
@ -566,23 +549,12 @@ expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators,
#define Call(a0, a1, a2, a3, a4, a5) _Py_Call(a0, a1, a2, a3, a4, a5) #define Call(a0, a1, a2, a3, a4, a5) _Py_Call(a0, a1, a2, a3, a4, a5)
expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int
lineno, int col_offset, PyArena *arena); lineno, int col_offset, PyArena *arena);
#define Num(a0, a1, a2, a3) _Py_Num(a0, a1, a2, a3)
expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena);
#define Str(a0, a1, a2, a3) _Py_Str(a0, a1, a2, a3)
expr_ty _Py_Str(string s, int lineno, int col_offset, PyArena *arena);
#define FormattedValue(a0, a1, a2, a3, a4, a5) _Py_FormattedValue(a0, a1, a2, a3, a4, a5) #define FormattedValue(a0, a1, a2, a3, a4, a5) _Py_FormattedValue(a0, a1, a2, a3, a4, a5)
expr_ty _Py_FormattedValue(expr_ty value, int conversion, expr_ty format_spec, expr_ty _Py_FormattedValue(expr_ty value, int conversion, expr_ty format_spec,
int lineno, int col_offset, PyArena *arena); int lineno, int col_offset, PyArena *arena);
#define JoinedStr(a0, a1, a2, a3) _Py_JoinedStr(a0, a1, a2, a3) #define JoinedStr(a0, a1, a2, a3) _Py_JoinedStr(a0, a1, a2, a3)
expr_ty _Py_JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena expr_ty _Py_JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena
*arena); *arena);
#define Bytes(a0, a1, a2, a3) _Py_Bytes(a0, a1, a2, a3)
expr_ty _Py_Bytes(bytes s, int lineno, int col_offset, PyArena *arena);
#define NameConstant(a0, a1, a2, a3) _Py_NameConstant(a0, a1, a2, a3)
expr_ty _Py_NameConstant(singleton value, int lineno, int col_offset, PyArena
*arena);
#define Ellipsis(a0, a1, a2) _Py_Ellipsis(a0, a1, a2)
expr_ty _Py_Ellipsis(int lineno, int col_offset, PyArena *arena);
#define Constant(a0, a1, a2, a3) _Py_Constant(a0, a1, a2, a3) #define Constant(a0, a1, a2, a3) _Py_Constant(a0, a1, a2, a3)
expr_ty _Py_Constant(constant value, int lineno, int col_offset, PyArena expr_ty _Py_Constant(constant value, int lineno, int col_offset, PyArena
*arena); *arena);

View File

@ -48,10 +48,8 @@ def literal_eval(node_or_string):
node_or_string = node_or_string.body node_or_string = node_or_string.body
def _convert_num(node): def _convert_num(node):
if isinstance(node, Constant): if isinstance(node, Constant):
if isinstance(node.value, (int, float, complex)): if type(node.value) in (int, float, complex):
return node.value return node.value
elif isinstance(node, Num):
return node.n
raise ValueError('malformed node or string: ' + repr(node)) raise ValueError('malformed node or string: ' + repr(node))
def _convert_signed_num(node): def _convert_signed_num(node):
if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)): if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)):
@ -64,10 +62,6 @@ def literal_eval(node_or_string):
def _convert(node): def _convert(node):
if isinstance(node, Constant): if isinstance(node, Constant):
return node.value return node.value
elif isinstance(node, (Str, Bytes)):
return node.s
elif isinstance(node, Num):
return node.n
elif isinstance(node, Tuple): elif isinstance(node, Tuple):
return tuple(map(_convert, node.elts)) return tuple(map(_convert, node.elts))
elif isinstance(node, List): elif isinstance(node, List):
@ -77,8 +71,6 @@ def literal_eval(node_or_string):
elif isinstance(node, Dict): elif isinstance(node, Dict):
return dict(zip(map(_convert, node.keys), return dict(zip(map(_convert, node.keys),
map(_convert, node.values))) map(_convert, node.values)))
elif isinstance(node, NameConstant):
return node.value
elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)): elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
left = _convert_signed_num(node.left) left = _convert_signed_num(node.left)
right = _convert_num(node.right) right = _convert_num(node.right)
@ -329,3 +321,66 @@ class NodeTransformer(NodeVisitor):
else: else:
setattr(node, field, new_node) setattr(node, field, new_node)
return node return node
# The following code is for backward compatibility.
# It will be removed in future.
def _getter(self):
return self.value
def _setter(self, value):
self.value = value
Constant.n = property(_getter, _setter)
Constant.s = property(_getter, _setter)
class _ABC(type):
def __instancecheck__(cls, inst):
if not isinstance(inst, Constant):
return False
if cls in _const_types:
try:
value = inst.value
except AttributeError:
return False
else:
return type(value) in _const_types[cls]
return type.__instancecheck__(cls, inst)
def _new(cls, *args, **kwargs):
if cls in _const_types:
return Constant(*args, **kwargs)
return Constant.__new__(cls, *args, **kwargs)
class Num(Constant, metaclass=_ABC):
_fields = ('n',)
__new__ = _new
class Str(Constant, metaclass=_ABC):
_fields = ('s',)
__new__ = _new
class Bytes(Constant, metaclass=_ABC):
_fields = ('s',)
__new__ = _new
class NameConstant(Constant, metaclass=_ABC):
__new__ = _new
class Ellipsis(Constant, metaclass=_ABC):
_fields = ()
def __new__(cls, *args, **kwargs):
if cls is Ellipsis:
return Constant(..., *args, **kwargs)
return Constant.__new__(cls, *args, **kwargs)
_const_types = {
Num: (int, float, complex),
Str: (str,),
Bytes: (bytes,),
NameConstant: (type(None), bool),
Ellipsis: (type(...),),
}

View File

@ -2005,14 +2005,8 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True):
except NameError: except NameError:
raise RuntimeError() raise RuntimeError()
if isinstance(value, str): if isinstance(value, (str, int, float, bytes, bool, type(None))):
return ast.Str(value) return ast.Constant(value)
if isinstance(value, (int, float)):
return ast.Num(value)
if isinstance(value, bytes):
return ast.Bytes(value)
if value in (True, False, None):
return ast.NameConstant(value)
raise RuntimeError() raise RuntimeError()
class RewriteSymbolics(ast.NodeTransformer): class RewriteSymbolics(ast.NodeTransformer):

View File

@ -300,12 +300,16 @@ class AST_Tests(unittest.TestCase):
def test_classattrs(self): def test_classattrs(self):
x = ast.Num() x = ast.Num()
self.assertEqual(x._fields, ('n',)) self.assertEqual(x._fields, ('value',))
with self.assertRaises(AttributeError):
x.value
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
x.n x.n
x = ast.Num(42) x = ast.Num(42)
self.assertEqual(x.value, 42)
self.assertEqual(x.n, 42) self.assertEqual(x.n, 42)
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
@ -319,12 +323,102 @@ class AST_Tests(unittest.TestCase):
x = ast.Num(42, lineno=0) x = ast.Num(42, lineno=0)
self.assertEqual(x.lineno, 0) self.assertEqual(x.lineno, 0)
self.assertEqual(x._fields, ('n',)) self.assertEqual(x._fields, ('value',))
self.assertEqual(x.value, 42)
self.assertEqual(x.n, 42) self.assertEqual(x.n, 42)
self.assertRaises(TypeError, ast.Num, 1, 2) self.assertRaises(TypeError, ast.Num, 1, 2)
self.assertRaises(TypeError, ast.Num, 1, 2, lineno=0) self.assertRaises(TypeError, ast.Num, 1, 2, lineno=0)
self.assertEqual(ast.Num(42).n, 42)
self.assertEqual(ast.Num(4.25).n, 4.25)
self.assertEqual(ast.Num(4.25j).n, 4.25j)
self.assertEqual(ast.Str('42').s, '42')
self.assertEqual(ast.Bytes(b'42').s, b'42')
self.assertIs(ast.NameConstant(True).value, True)
self.assertIs(ast.NameConstant(False).value, False)
self.assertIs(ast.NameConstant(None).value, None)
self.assertEqual(ast.Constant(42).value, 42)
self.assertEqual(ast.Constant(4.25).value, 4.25)
self.assertEqual(ast.Constant(4.25j).value, 4.25j)
self.assertEqual(ast.Constant('42').value, '42')
self.assertEqual(ast.Constant(b'42').value, b'42')
self.assertIs(ast.Constant(True).value, True)
self.assertIs(ast.Constant(False).value, False)
self.assertIs(ast.Constant(None).value, None)
self.assertIs(ast.Constant(...).value, ...)
def test_realtype(self):
self.assertEqual(type(ast.Num(42)), ast.Constant)
self.assertEqual(type(ast.Num(4.25)), ast.Constant)
self.assertEqual(type(ast.Num(4.25j)), ast.Constant)
self.assertEqual(type(ast.Str('42')), ast.Constant)
self.assertEqual(type(ast.Bytes(b'42')), ast.Constant)
self.assertEqual(type(ast.NameConstant(True)), ast.Constant)
self.assertEqual(type(ast.NameConstant(False)), ast.Constant)
self.assertEqual(type(ast.NameConstant(None)), ast.Constant)
self.assertEqual(type(ast.Ellipsis()), ast.Constant)
def test_isinstance(self):
self.assertTrue(isinstance(ast.Num(42), ast.Num))
self.assertTrue(isinstance(ast.Num(4.2), ast.Num))
self.assertTrue(isinstance(ast.Num(4.2j), ast.Num))
self.assertTrue(isinstance(ast.Str('42'), ast.Str))
self.assertTrue(isinstance(ast.Bytes(b'42'), ast.Bytes))
self.assertTrue(isinstance(ast.NameConstant(True), ast.NameConstant))
self.assertTrue(isinstance(ast.NameConstant(False), ast.NameConstant))
self.assertTrue(isinstance(ast.NameConstant(None), ast.NameConstant))
self.assertTrue(isinstance(ast.Ellipsis(), ast.Ellipsis))
self.assertTrue(isinstance(ast.Constant(42), ast.Num))
self.assertTrue(isinstance(ast.Constant(4.2), ast.Num))
self.assertTrue(isinstance(ast.Constant(4.2j), ast.Num))
self.assertTrue(isinstance(ast.Constant('42'), ast.Str))
self.assertTrue(isinstance(ast.Constant(b'42'), ast.Bytes))
self.assertTrue(isinstance(ast.Constant(True), ast.NameConstant))
self.assertTrue(isinstance(ast.Constant(False), ast.NameConstant))
self.assertTrue(isinstance(ast.Constant(None), ast.NameConstant))
self.assertTrue(isinstance(ast.Constant(...), ast.Ellipsis))
self.assertFalse(isinstance(ast.Str('42'), ast.Num))
self.assertFalse(isinstance(ast.Num(42), ast.Str))
self.assertFalse(isinstance(ast.Str('42'), ast.Bytes))
self.assertFalse(isinstance(ast.Num(42), ast.NameConstant))
self.assertFalse(isinstance(ast.Num(42), ast.Ellipsis))
self.assertFalse(isinstance(ast.Constant('42'), ast.Num))
self.assertFalse(isinstance(ast.Constant(42), ast.Str))
self.assertFalse(isinstance(ast.Constant('42'), ast.Bytes))
self.assertFalse(isinstance(ast.Constant(42), ast.NameConstant))
self.assertFalse(isinstance(ast.Constant(42), ast.Ellipsis))
self.assertFalse(isinstance(ast.Constant(), ast.Num))
self.assertFalse(isinstance(ast.Constant(), ast.Str))
self.assertFalse(isinstance(ast.Constant(), ast.Bytes))
self.assertFalse(isinstance(ast.Constant(), ast.NameConstant))
self.assertFalse(isinstance(ast.Constant(), ast.Ellipsis))
def test_subclasses(self):
class N(ast.Num):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.z = 'spam'
class N2(ast.Num):
pass
n = N(42)
self.assertEqual(n.n, 42)
self.assertEqual(n.z, 'spam')
self.assertEqual(type(n), N)
self.assertTrue(isinstance(n, N))
self.assertTrue(isinstance(n, ast.Num))
self.assertFalse(isinstance(n, N2))
self.assertFalse(isinstance(ast.Num(42), N))
n = N(n=42)
self.assertEqual(n.n, 42)
self.assertEqual(type(n), N)
def test_module(self): def test_module(self):
body = [ast.Num(42)] body = [ast.Num(42)]
x = ast.Module(body) x = ast.Module(body)
@ -446,17 +540,17 @@ class ASTHelpers_Test(unittest.TestCase):
node = ast.parse('spam(eggs, "and cheese")') node = ast.parse('spam(eggs, "and cheese")')
self.assertEqual(ast.dump(node), self.assertEqual(ast.dump(node),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), "
"args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], " "args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')], "
"keywords=[]))])" "keywords=[]))])"
) )
self.assertEqual(ast.dump(node, annotate_fields=False), self.assertEqual(ast.dump(node, annotate_fields=False),
"Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), "
"Str('and cheese')], []))])" "Constant('and cheese')], []))])"
) )
self.assertEqual(ast.dump(node, include_attributes=True), self.assertEqual(ast.dump(node, include_attributes=True),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), "
"lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), " "lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), "
"lineno=1, col_offset=5), Str(s='and cheese', lineno=1, " "lineno=1, col_offset=5), Constant(value='and cheese', lineno=1, "
"col_offset=11)], keywords=[], " "col_offset=11)], keywords=[], "
"lineno=1, col_offset=0), lineno=1, col_offset=0)])" "lineno=1, col_offset=0), lineno=1, col_offset=0)])"
) )
@ -465,8 +559,8 @@ class ASTHelpers_Test(unittest.TestCase):
src = ast.parse('1 + 1', mode='eval') src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right) src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True), self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), ' 'Expression(body=BinOp(left=Constant(value=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, ' 'op=Add(), right=Constant(value=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))' 'col_offset=0))'
) )
@ -477,11 +571,11 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(src, ast.fix_missing_locations(src)) self.assertEqual(src, ast.fix_missing_locations(src))
self.assertEqual(ast.dump(src, include_attributes=True), self.assertEqual(ast.dump(src, include_attributes=True),
"Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), " "Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), "
"lineno=1, col_offset=0), args=[Str(s='spam', lineno=1, " "lineno=1, col_offset=0), args=[Constant(value='spam', lineno=1, "
"col_offset=6)], keywords=[], " "col_offset=6)], keywords=[], "
"lineno=1, col_offset=0), lineno=1, col_offset=0), " "lineno=1, col_offset=0), lineno=1, col_offset=0), "
"Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, " "Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, "
"col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], " "col_offset=0), args=[Constant(value='eggs', lineno=1, col_offset=0)], "
"keywords=[], lineno=1, " "keywords=[], lineno=1, "
"col_offset=0), lineno=1, col_offset=0)])" "col_offset=0), lineno=1, col_offset=0)])"
) )
@ -490,16 +584,16 @@ class ASTHelpers_Test(unittest.TestCase):
src = ast.parse('1 + 1', mode='eval') src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src) self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True), self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), ' 'Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, ' 'op=Add(), right=Constant(value=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))' 'col_offset=0))'
) )
# issue10869: do not increment lineno of root twice # issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval') src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body) self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True), self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), ' 'Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, ' 'op=Add(), right=Constant(value=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))' 'col_offset=0))'
) )
@ -514,10 +608,10 @@ class ASTHelpers_Test(unittest.TestCase):
self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4) self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4)
iterator = ast.iter_child_nodes(node.body) iterator = ast.iter_child_nodes(node.body)
self.assertEqual(next(iterator).id, 'spam') self.assertEqual(next(iterator).id, 'spam')
self.assertEqual(next(iterator).n, 23) self.assertEqual(next(iterator).value, 23)
self.assertEqual(next(iterator).n, 42) self.assertEqual(next(iterator).value, 42)
self.assertEqual(ast.dump(next(iterator)), self.assertEqual(ast.dump(next(iterator)),
"keyword(arg='eggs', value=Str(s='leek'))" "keyword(arg='eggs', value=Constant(value='leek'))"
) )
def test_get_docstring(self): def test_get_docstring(self):
@ -627,9 +721,11 @@ class ASTValidatorTests(unittest.TestCase):
def mod(self, mod, msg=None, mode="exec", *, exc=ValueError): def mod(self, mod, msg=None, mode="exec", *, exc=ValueError):
mod.lineno = mod.col_offset = 0 mod.lineno = mod.col_offset = 0
ast.fix_missing_locations(mod) ast.fix_missing_locations(mod)
with self.assertRaises(exc) as cm: if msg is None:
compile(mod, "<test>", mode) compile(mod, "<test>", mode)
if msg is not None: else:
with self.assertRaises(exc) as cm:
compile(mod, "<test>", mode)
self.assertIn(msg, str(cm.exception)) self.assertIn(msg, str(cm.exception))
def expr(self, node, msg=None, *, exc=ValueError): def expr(self, node, msg=None, *, exc=ValueError):
@ -927,9 +1023,9 @@ class ASTValidatorTests(unittest.TestCase):
comp = ast.Compare(left, [ast.In()], [ast.Num(4), ast.Num(5)]) comp = ast.Compare(left, [ast.In()], [ast.Num(4), ast.Num(5)])
self.expr(comp, "different number of comparators and operands") self.expr(comp, "different number of comparators and operands")
comp = ast.Compare(ast.Num("blah"), [ast.In()], [left]) comp = ast.Compare(ast.Num("blah"), [ast.In()], [left])
self.expr(comp, "non-numeric", exc=TypeError) self.expr(comp)
comp = ast.Compare(left, [ast.In()], [ast.Num("blah")]) comp = ast.Compare(left, [ast.In()], [ast.Num("blah")])
self.expr(comp, "non-numeric", exc=TypeError) self.expr(comp)
def test_call(self): def test_call(self):
func = ast.Name("x", ast.Load()) func = ast.Name("x", ast.Load())
@ -950,8 +1046,10 @@ class ASTValidatorTests(unittest.TestCase):
pass pass
class subcomplex(complex): class subcomplex(complex):
pass pass
for obj in "0", "hello", subint(), subfloat(), subcomplex(): for obj in "0", "hello":
self.expr(ast.Num(obj), "non-numeric", exc=TypeError) self.expr(ast.Num(obj))
for obj in subint(), subfloat(), subcomplex():
self.expr(ast.Num(obj), "invalid type", exc=TypeError)
def test_attribute(self): def test_attribute(self):
attr = ast.Attribute(ast.Name("x", ast.Store()), "y", ast.Load()) attr = ast.Attribute(ast.Name("x", ast.Store()), "y", ast.Load())
@ -993,7 +1091,7 @@ class ASTValidatorTests(unittest.TestCase):
self._sequence(ast.Tuple) self._sequence(ast.Tuple)
def test_nameconstant(self): def test_nameconstant(self):
self.expr(ast.NameConstant(4), "singleton must be True, False, or None") self.expr(ast.NameConstant(4))
def test_stdlib_validates(self): def test_stdlib_validates(self):
stdlib = os.path.dirname(ast.__file__) stdlib = os.path.dirname(ast.__file__)
@ -1140,35 +1238,35 @@ def main():
#### EVERYTHING BELOW IS GENERATED ##### #### EVERYTHING BELOW IS GENERATED #####
exec_results = [ exec_results = [
('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))]), ('Module', [('Expr', (1, 0), ('Constant', (1, 0), None))]),
('Module', [('Expr', (1, 0), ('Str', (1, 0), 'module docstring'))]), ('Module', [('Expr', (1, 0), ('Constant', (1, 0), 'module docstring'))]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (1, 9), ('Str', (1, 9), 'function docstring'))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (1, 9), ('Constant', (1, 9), 'function docstring'))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Constant', (1, 8), 0)]), [('Pass', (1, 12))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Str', (1, 58), 'doc for f()'))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Constant', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Constant', (1, 11), 1), ('Constant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Constant', (1, 58), 'doc for f()'))], [], None)]),
('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]), ('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]),
('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Str', (1, 9), 'docstring for class C'))], [])]), ('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Constant', (1, 9), 'docstring for class C'))], [])]),
('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])]), ('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Constant', (1, 15), 1))], [], None)]),
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]),
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Constant', (1, 4), 1))]),
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]), ('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Constant', (1, 5), 1))]),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]),
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]), ('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]),
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]), ('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]),
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)]), ('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Constant', (1, 16), 'string')], []), None)]),
('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]),
('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]), ('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),
('Module', [('Import', (1, 0), [('alias', 'sys', None)])]), ('Module', [('Import', (1, 0), [('alias', 'sys', None)])]),
('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]), ('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]),
('Module', [('Global', (1, 0), ['v'])]), ('Module', [('Global', (1, 0), ['v'])]),
('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))]), ('Module', [('Expr', (1, 0), ('Constant', (1, 0), 1))]),
('Module', [('Pass', (1, 0))]), ('Module', [('Pass', (1, 0))]),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])]), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])]),
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])]), ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])]),
@ -1181,40 +1279,40 @@ exec_results = [
('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))]), ('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))]),
('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))]), ('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))]),
('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))]), ('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))]),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Str', (2, 1), 'async function')), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None)]), ('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Constant', (2, 1), 'async function')), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None)]),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 1), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None)]), ('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 1), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Constant', (2, 19), 1))], [('Expr', (3, 7), ('Constant', (3, 7), 2))])], [], None)]),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 1), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None)]), ('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 1), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Constant', (2, 20), 1))])], [], None)]),
('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))]), ('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Constant', (1, 10), 2)], [('Dict', (1, 3), [('Constant', (1, 4), 1)], [('Constant', (1, 6), 2)]), ('Constant', (1, 12), 3)]))]),
('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))]), ('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Constant', (1, 3), 1), ('Constant', (1, 6), 2)]), ('Load',)), ('Constant', (1, 10), 3)]))]),
('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None)]), ('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None)]),
] ]
single_results = [ single_results = [
('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Constant', (1, 0), 1), ('Add',), ('Constant', (1, 2), 2)))]),
] ]
eval_results = [ eval_results = [
('Expression', ('NameConstant', (1, 0), None)), ('Expression', ('Constant', (1, 0), None)),
('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])), ('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])),
('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))), ('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))),
('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))), ('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))),
('Expression', ('Lambda', (1, 0), ('arguments', [], None, [], [], None, []), ('NameConstant', (1, 7), None))), ('Expression', ('Lambda', (1, 0), ('arguments', [], None, [], [], None, []), ('Constant', (1, 7), None))),
('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])), ('Expression', ('Dict', (1, 0), [('Constant', (1, 2), 1)], [('Constant', (1, 4), 2)])),
('Expression', ('Dict', (1, 0), [], [])), ('Expression', ('Dict', (1, 0), [], [])),
('Expression', ('Set', (1, 0), [('NameConstant', (1, 1), None)])), ('Expression', ('Set', (1, 0), [('Constant', (1, 1), None)])),
('Expression', ('Dict', (1, 0), [('Num', (2, 6), 1)], [('Num', (4, 10), 2)])), ('Expression', ('Dict', (1, 0), [('Constant', (2, 6), 1)], [('Constant', (4, 10), 2)])),
('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))], 0)])), ('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))], 0)])),
('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))], 0)])), ('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))], 0)])),
('Expression', ('Compare', (1, 0), ('Num', (1, 0), 1), [('Lt',), ('Lt',)], [('Num', (1, 4), 2), ('Num', (1, 8), 3)])), ('Expression', ('Compare', (1, 0), ('Constant', (1, 0), 1), [('Lt',), ('Lt',)], [('Constant', (1, 4), 2), ('Constant', (1, 8), 3)])),
('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Num', (1, 2), 1), ('Num', (1, 4), 2), ('Starred', (1, 10), ('Name', (1, 11), 'd', ('Load',)), ('Load',))], [('keyword', 'c', ('Num', (1, 8), 3)), ('keyword', None, ('Name', (1, 15), 'e', ('Load',)))])), ('Expression', ('Call', (1, 0), ('Name', (1, 0), 'f', ('Load',)), [('Constant', (1, 2), 1), ('Constant', (1, 4), 2), ('Starred', (1, 10), ('Name', (1, 11), 'd', ('Load',)), ('Load',))], [('keyword', 'c', ('Constant', (1, 8), 3)), ('keyword', None, ('Name', (1, 15), 'e', ('Load',)))])),
('Expression', ('Num', (1, 0), 10)), ('Expression', ('Constant', (1, 0), 10)),
('Expression', ('Str', (1, 0), 'string')), ('Expression', ('Constant', (1, 0), 'string')),
('Expression', ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',))), ('Expression', ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',))),
('Expression', ('Subscript', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Slice', ('Name', (1, 2), 'b', ('Load',)), ('Name', (1, 4), 'c', ('Load',)), None), ('Load',))), ('Expression', ('Subscript', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Slice', ('Name', (1, 2), 'b', ('Load',)), ('Name', (1, 4), 'c', ('Load',)), None), ('Load',))),
('Expression', ('Name', (1, 0), 'v', ('Load',))), ('Expression', ('Name', (1, 0), 'v', ('Load',))),
('Expression', ('List', (1, 0), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), ('Expression', ('List', (1, 0), [('Constant', (1, 1), 1), ('Constant', (1, 3), 2), ('Constant', (1, 5), 3)], ('Load',))),
('Expression', ('List', (1, 0), [], ('Load',))), ('Expression', ('List', (1, 0), [], ('Load',))),
('Expression', ('Tuple', (1, 0), [('Num', (1, 0), 1), ('Num', (1, 2), 2), ('Num', (1, 4), 3)], ('Load',))), ('Expression', ('Tuple', (1, 0), [('Constant', (1, 0), 1), ('Constant', (1, 2), 2), ('Constant', (1, 4), 3)], ('Load',))),
('Expression', ('Tuple', (1, 1), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), ('Expression', ('Tuple', (1, 1), [('Constant', (1, 1), 1), ('Constant', (1, 3), 2), ('Constant', (1, 5), 3)], ('Load',))),
('Expression', ('Tuple', (1, 0), [], ('Load',))), ('Expression', ('Tuple', (1, 0), [], ('Load',))),
('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Num', (1, 12), 1), ('Num', (1, 14), 2), None), ('Load',))], [])), ('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Constant', (1, 12), 1), ('Constant', (1, 14), 2), None), ('Load',))], [])),
] ]
main() main()

View File

@ -116,9 +116,11 @@ f'eggs {a * x()} spam {b + y()}'"""
self.assertEqual(type(t.body[1]), ast.Expr) self.assertEqual(type(t.body[1]), ast.Expr)
self.assertEqual(type(t.body[1].value), ast.JoinedStr) self.assertEqual(type(t.body[1].value), ast.JoinedStr)
self.assertEqual(len(t.body[1].value.values), 4) self.assertEqual(len(t.body[1].value.values), 4)
self.assertEqual(type(t.body[1].value.values[0]), ast.Str) self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[0].value), str)
self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[2]), ast.Str) self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[2].value), str)
self.assertEqual(type(t.body[1].value.values[3]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[3]), ast.FormattedValue)
self.assertEqual(t.body[1].lineno, 3) self.assertEqual(t.body[1].lineno, 3)
self.assertEqual(t.body[1].value.lineno, 3) self.assertEqual(t.body[1].value.lineno, 3)
@ -183,9 +185,11 @@ f'{a * f"-{x()}-"}'"""
self.assertEqual(binop.right.col_offset, 7) self.assertEqual(binop.right.col_offset, 7)
# check the nested call location # check the nested call location
self.assertEqual(len(binop.right.values), 3) self.assertEqual(len(binop.right.values), 3)
self.assertEqual(type(binop.right.values[0]), ast.Str) self.assertEqual(type(binop.right.values[0]), ast.Constant)
self.assertEqual(type(binop.right.values[0].value), str)
self.assertEqual(type(binop.right.values[1]), ast.FormattedValue) self.assertEqual(type(binop.right.values[1]), ast.FormattedValue)
self.assertEqual(type(binop.right.values[2]), ast.Str) self.assertEqual(type(binop.right.values[2]), ast.Constant)
self.assertEqual(type(binop.right.values[2].value), str)
self.assertEqual(binop.right.values[0].lineno, 3) self.assertEqual(binop.right.values[0].lineno, 3)
self.assertEqual(binop.right.values[1].lineno, 3) self.assertEqual(binop.right.values[1].lineno, 3)
self.assertEqual(binop.right.values[2].lineno, 3) self.assertEqual(binop.right.values[2].lineno, 3)
@ -215,9 +219,11 @@ f'{a * x()} {a * x()} {a * x()}'
self.assertEqual(type(t.body[1].value), ast.JoinedStr) self.assertEqual(type(t.body[1].value), ast.JoinedStr)
self.assertEqual(len(t.body[1].value.values), 5) self.assertEqual(len(t.body[1].value.values), 5)
self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[1]), ast.Str) self.assertEqual(type(t.body[1].value.values[1]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[1].value), str)
self.assertEqual(type(t.body[1].value.values[2]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[2]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[3]), ast.Str) self.assertEqual(type(t.body[1].value.values[3]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[3].value), str)
self.assertEqual(type(t.body[1].value.values[4]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[4]), ast.FormattedValue)
self.assertEqual(t.body[1].lineno, 3) self.assertEqual(t.body[1].lineno, 3)
self.assertEqual(t.body[1].value.lineno, 3) self.assertEqual(t.body[1].value.lineno, 3)
@ -287,9 +293,11 @@ non-important content
self.assertEqual(type(t.body[1]), ast.Expr) self.assertEqual(type(t.body[1]), ast.Expr)
self.assertEqual(type(t.body[1].value), ast.JoinedStr) self.assertEqual(type(t.body[1].value), ast.JoinedStr)
self.assertEqual(len(t.body[1].value.values), 3) self.assertEqual(len(t.body[1].value.values), 3)
self.assertEqual(type(t.body[1].value.values[0]), ast.Str) self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[0].value), str)
self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[2]), ast.Str) self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[2].value), str)
# NOTE: the following invalid behavior is described in bpo-16806. # NOTE: the following invalid behavior is described in bpo-16806.
# - line number should be the *first* line (3), not the *last* (8) # - line number should be the *first* line (3), not the *last* (8)
# - column offset should not be -1 # - column offset should not be -1

View File

@ -230,7 +230,7 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq("lukasz.langa.pl") eq("lukasz.langa.pl")
eq("call.me(maybe)") eq("call.me(maybe)")
eq("1 .real") eq("1 .real")
eq("1.0 .real") eq("1.0.real")
eq("....__class__") eq("....__class__")
eq("list[str]") eq("list[str]")
eq("dict[str, int]") eq("dict[str, int]")

View File

@ -144,7 +144,8 @@ class PyclbrTest(TestCase):
def test_easy(self): def test_easy(self):
self.checkModule('pyclbr') self.checkModule('pyclbr')
self.checkModule('ast') # XXX: Metaclasses are not supported
# self.checkModule('ast')
self.checkModule('doctest', ignore=("TestResults", "_SpoofOut", self.checkModule('doctest', ignore=("TestResults", "_SpoofOut",
"DocTestCase", '_DocTestSuite')) "DocTestCase", '_DocTestSuite'))
self.checkModule('difflib', ignore=("Match",)) self.checkModule('difflib', ignore=("Match",))

View File

@ -0,0 +1,4 @@
The parser now represents all constants as :class:`ast.Constant` instead of
using specific constant AST types (``Num``, ``Str``, ``Bytes``,
``NameConstant`` and ``Ellipsis``). These classes are considered deprecated
and will be removed in future Python versions.

View File

@ -1,8 +1,5 @@
-- ASDL's 7 builtin types are: -- ASDL's 5 builtin types are:
-- identifier, int, string, bytes, object, singleton, constant -- identifier, int, string, object, constant
--
-- singleton: None, True or False
-- constant can be None, whereas None means "no value" for object.
module Python module Python
{ {
@ -75,13 +72,8 @@ module Python
-- x < 4 < 3 and (x < 4) < 3 -- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators) | Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords) | Call(expr func, expr* args, keyword* keywords)
| Num(object n) -- a number as a PyObject.
| Str(string s) -- need to specify raw, unicode, etc?
| FormattedValue(expr value, int? conversion, expr? format_spec) | FormattedValue(expr value, int? conversion, expr? format_spec)
| JoinedStr(expr* values) | JoinedStr(expr* values)
| Bytes(bytes s)
| NameConstant(singleton value)
| Ellipsis
| Constant(constant value) | Constant(constant value)
-- the following expression can appear in assignment context -- the following expression can appear in assignment context

View File

@ -855,17 +855,6 @@ static PyObject* ast2obj_int(long b)
/* Conversion Python -> AST */ /* Conversion Python -> AST */
static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
{
if (obj != Py_None && obj != Py_True && obj != Py_False) {
PyErr_SetString(PyExc_ValueError,
"AST singleton must be True, False, or None");
return 1;
}
*out = obj;
return 0;
}
static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
{ {
if (obj == Py_None) if (obj == Py_None)
@ -883,13 +872,11 @@ static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena)
{ {
if (obj) { if (PyArena_AddPyObject(arena, obj) < 0) {
if (PyArena_AddPyObject(arena, obj) < 0) { *out = NULL;
*out = NULL; return -1;
return -1;
}
Py_INCREF(obj);
} }
Py_INCREF(obj);
*out = obj; *out = obj;
return 0; return 0;
} }
@ -903,24 +890,6 @@ static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
return obj2ast_object(obj, out, arena); return obj2ast_object(obj, out, arena);
} }
static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST string must be of type str");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
{ {
int i; int i;

312
Python/Python-ast.c generated
View File

@ -284,16 +284,6 @@ static char *Call_fields[]={
"args", "args",
"keywords", "keywords",
}; };
static PyTypeObject *Num_type;
_Py_IDENTIFIER(n);
static char *Num_fields[]={
"n",
};
static PyTypeObject *Str_type;
_Py_IDENTIFIER(s);
static char *Str_fields[]={
"s",
};
static PyTypeObject *FormattedValue_type; static PyTypeObject *FormattedValue_type;
_Py_IDENTIFIER(conversion); _Py_IDENTIFIER(conversion);
_Py_IDENTIFIER(format_spec); _Py_IDENTIFIER(format_spec);
@ -306,15 +296,6 @@ static PyTypeObject *JoinedStr_type;
static char *JoinedStr_fields[]={ static char *JoinedStr_fields[]={
"values", "values",
}; };
static PyTypeObject *Bytes_type;
static char *Bytes_fields[]={
"s",
};
static PyTypeObject *NameConstant_type;
static char *NameConstant_fields[]={
"value",
};
static PyTypeObject *Ellipsis_type;
static PyTypeObject *Constant_type; static PyTypeObject *Constant_type;
static char *Constant_fields[]={ static char *Constant_fields[]={
"value", "value",
@ -736,17 +717,6 @@ static PyObject* ast2obj_int(long b)
/* Conversion Python -> AST */ /* Conversion Python -> AST */
static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
{
if (obj != Py_None && obj != Py_True && obj != Py_False) {
PyErr_SetString(PyExc_ValueError,
"AST singleton must be True, False, or None");
return 1;
}
*out = obj;
return 0;
}
static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
{ {
if (obj == Py_None) if (obj == Py_None)
@ -764,13 +734,11 @@ static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena)
{ {
if (obj) { if (PyArena_AddPyObject(arena, obj) < 0) {
if (PyArena_AddPyObject(arena, obj) < 0) { *out = NULL;
*out = NULL; return -1;
return -1;
}
Py_INCREF(obj);
} }
Py_INCREF(obj);
*out = obj; *out = obj;
return 0; return 0;
} }
@ -784,24 +752,6 @@ static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
return obj2ast_object(obj, out, arena); return obj2ast_object(obj, out, arena);
} }
static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST string must be of type str");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
{ {
int i; int i;
@ -943,22 +893,11 @@ static int init_types(void)
if (!Compare_type) return 0; if (!Compare_type) return 0;
Call_type = make_type("Call", expr_type, Call_fields, 3); Call_type = make_type("Call", expr_type, Call_fields, 3);
if (!Call_type) return 0; if (!Call_type) return 0;
Num_type = make_type("Num", expr_type, Num_fields, 1);
if (!Num_type) return 0;
Str_type = make_type("Str", expr_type, Str_fields, 1);
if (!Str_type) return 0;
FormattedValue_type = make_type("FormattedValue", expr_type, FormattedValue_type = make_type("FormattedValue", expr_type,
FormattedValue_fields, 3); FormattedValue_fields, 3);
if (!FormattedValue_type) return 0; if (!FormattedValue_type) return 0;
JoinedStr_type = make_type("JoinedStr", expr_type, JoinedStr_fields, 1); JoinedStr_type = make_type("JoinedStr", expr_type, JoinedStr_fields, 1);
if (!JoinedStr_type) return 0; if (!JoinedStr_type) return 0;
Bytes_type = make_type("Bytes", expr_type, Bytes_fields, 1);
if (!Bytes_type) return 0;
NameConstant_type = make_type("NameConstant", expr_type,
NameConstant_fields, 1);
if (!NameConstant_type) return 0;
Ellipsis_type = make_type("Ellipsis", expr_type, NULL, 0);
if (!Ellipsis_type) return 0;
Constant_type = make_type("Constant", expr_type, Constant_fields, 1); Constant_type = make_type("Constant", expr_type, Constant_fields, 1);
if (!Constant_type) return 0; if (!Constant_type) return 0;
Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3); Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3);
@ -2089,44 +2028,6 @@ Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int lineno, int
return p; return p;
} }
expr_ty
Num(object n, int lineno, int col_offset, PyArena *arena)
{
expr_ty p;
if (!n) {
PyErr_SetString(PyExc_ValueError,
"field n is required for Num");
return NULL;
}
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = Num_kind;
p->v.Num.n = n;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
expr_ty
Str(string s, int lineno, int col_offset, PyArena *arena)
{
expr_ty p;
if (!s) {
PyErr_SetString(PyExc_ValueError,
"field s is required for Str");
return NULL;
}
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = Str_kind;
p->v.Str.s = s;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
expr_ty expr_ty
FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int lineno, FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int lineno,
int col_offset, PyArena *arena) int col_offset, PyArena *arena)
@ -2163,57 +2064,6 @@ JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena *arena)
return p; return p;
} }
expr_ty
Bytes(bytes s, int lineno, int col_offset, PyArena *arena)
{
expr_ty p;
if (!s) {
PyErr_SetString(PyExc_ValueError,
"field s is required for Bytes");
return NULL;
}
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = Bytes_kind;
p->v.Bytes.s = s;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
expr_ty
NameConstant(singleton value, int lineno, int col_offset, PyArena *arena)
{
expr_ty p;
if (!value) {
PyErr_SetString(PyExc_ValueError,
"field value is required for NameConstant");
return NULL;
}
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = NameConstant_kind;
p->v.NameConstant.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
expr_ty
Ellipsis(int lineno, int col_offset, PyArena *arena)
{
expr_ty p;
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = Ellipsis_kind;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
expr_ty expr_ty
Constant(constant value, int lineno, int col_offset, PyArena *arena) Constant(constant value, int lineno, int col_offset, PyArena *arena)
{ {
@ -3289,24 +3139,6 @@ ast2obj_expr(void* _o)
goto failed; goto failed;
Py_DECREF(value); Py_DECREF(value);
break; break;
case Num_kind:
result = PyType_GenericNew(Num_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_object(o->v.Num.n);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_n, value) == -1)
goto failed;
Py_DECREF(value);
break;
case Str_kind:
result = PyType_GenericNew(Str_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_string(o->v.Str.s);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_s, value) == -1)
goto failed;
Py_DECREF(value);
break;
case FormattedValue_kind: case FormattedValue_kind:
result = PyType_GenericNew(FormattedValue_type, NULL, NULL); result = PyType_GenericNew(FormattedValue_type, NULL, NULL);
if (!result) goto failed; if (!result) goto failed;
@ -3335,28 +3167,6 @@ ast2obj_expr(void* _o)
goto failed; goto failed;
Py_DECREF(value); Py_DECREF(value);
break; break;
case Bytes_kind:
result = PyType_GenericNew(Bytes_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_bytes(o->v.Bytes.s);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_s, value) == -1)
goto failed;
Py_DECREF(value);
break;
case NameConstant_kind:
result = PyType_GenericNew(NameConstant_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_singleton(o->v.NameConstant.value);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
goto failed;
Py_DECREF(value);
break;
case Ellipsis_kind:
result = PyType_GenericNew(Ellipsis_type, NULL, NULL);
if (!result) goto failed;
break;
case Constant_kind: case Constant_kind:
result = PyType_GenericNew(Constant_type, NULL, NULL); result = PyType_GenericNew(Constant_type, NULL, NULL);
if (!result) goto failed; if (!result) goto failed;
@ -6606,54 +6416,6 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (*out == NULL) goto failed; if (*out == NULL) goto failed;
return 0; return 0;
} }
isinstance = PyObject_IsInstance(obj, (PyObject*)Num_type);
if (isinstance == -1) {
return 1;
}
if (isinstance) {
object n;
if (_PyObject_LookupAttrId(obj, &PyId_n, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
PyErr_SetString(PyExc_TypeError, "required field \"n\" missing from Num");
return 1;
}
else {
int res;
res = obj2ast_object(tmp, &n, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = Num(n, lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)Str_type);
if (isinstance == -1) {
return 1;
}
if (isinstance) {
string s;
if (_PyObject_LookupAttrId(obj, &PyId_s, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
PyErr_SetString(PyExc_TypeError, "required field \"s\" missing from Str");
return 1;
}
else {
int res;
res = obj2ast_string(tmp, &s, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = Str(s, lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)FormattedValue_type); isinstance = PyObject_IsInstance(obj, (PyObject*)FormattedValue_type);
if (isinstance == -1) { if (isinstance == -1) {
return 1; return 1;
@ -6748,64 +6510,6 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
if (*out == NULL) goto failed; if (*out == NULL) goto failed;
return 0; return 0;
} }
isinstance = PyObject_IsInstance(obj, (PyObject*)Bytes_type);
if (isinstance == -1) {
return 1;
}
if (isinstance) {
bytes s;
if (_PyObject_LookupAttrId(obj, &PyId_s, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
PyErr_SetString(PyExc_TypeError, "required field \"s\" missing from Bytes");
return 1;
}
else {
int res;
res = obj2ast_bytes(tmp, &s, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = Bytes(s, lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)NameConstant_type);
if (isinstance == -1) {
return 1;
}
if (isinstance) {
singleton value;
if (_PyObject_LookupAttrId(obj, &PyId_value, &tmp) < 0) {
return 1;
}
if (tmp == NULL) {
PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from NameConstant");
return 1;
}
else {
int res;
res = obj2ast_singleton(tmp, &value, arena);
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = NameConstant(value, lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)Ellipsis_type);
if (isinstance == -1) {
return 1;
}
if (isinstance) {
*out = Ellipsis(lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
isinstance = PyObject_IsInstance(obj, (PyObject*)Constant_type); isinstance = PyObject_IsInstance(obj, (PyObject*)Constant_type);
if (isinstance == -1) { if (isinstance == -1) {
return 1; return 1;
@ -8244,18 +7948,10 @@ PyInit__ast(void)
if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0) return if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0) return
NULL; NULL;
if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return NULL; if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return NULL;
if (PyDict_SetItemString(d, "Num", (PyObject*)Num_type) < 0) return NULL;
if (PyDict_SetItemString(d, "Str", (PyObject*)Str_type) < 0) return NULL;
if (PyDict_SetItemString(d, "FormattedValue", if (PyDict_SetItemString(d, "FormattedValue",
(PyObject*)FormattedValue_type) < 0) return NULL; (PyObject*)FormattedValue_type) < 0) return NULL;
if (PyDict_SetItemString(d, "JoinedStr", (PyObject*)JoinedStr_type) < 0) if (PyDict_SetItemString(d, "JoinedStr", (PyObject*)JoinedStr_type) < 0)
return NULL; return NULL;
if (PyDict_SetItemString(d, "Bytes", (PyObject*)Bytes_type) < 0) return
NULL;
if (PyDict_SetItemString(d, "NameConstant", (PyObject*)NameConstant_type) <
0) return NULL;
if (PyDict_SetItemString(d, "Ellipsis", (PyObject*)Ellipsis_type) < 0)
return NULL;
if (PyDict_SetItemString(d, "Constant", (PyObject*)Constant_type) < 0) if (PyDict_SetItemString(d, "Constant", (PyObject*)Constant_type) < 0)
return NULL; return NULL;
if (PyDict_SetItemString(d, "Attribute", (PyObject*)Attribute_type) < 0) if (PyDict_SetItemString(d, "Attribute", (PyObject*)Attribute_type) < 0)

View File

@ -295,23 +295,6 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
return 0; return 0;
} }
return 1; return 1;
case Num_kind: {
PyObject *n = exp->v.Num.n;
if (!PyLong_CheckExact(n) && !PyFloat_CheckExact(n) &&
!PyComplex_CheckExact(n)) {
PyErr_SetString(PyExc_TypeError, "non-numeric type in Num");
return 0;
}
return 1;
}
case Str_kind: {
PyObject *s = exp->v.Str.s;
if (!PyUnicode_CheckExact(s)) {
PyErr_SetString(PyExc_TypeError, "non-string type in Str");
return 0;
}
return 1;
}
case JoinedStr_kind: case JoinedStr_kind:
return validate_exprs(exp->v.JoinedStr.values, Load, 0); return validate_exprs(exp->v.JoinedStr.values, Load, 0);
case FormattedValue_kind: case FormattedValue_kind:
@ -320,14 +303,6 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
if (exp->v.FormattedValue.format_spec) if (exp->v.FormattedValue.format_spec)
return validate_expr(exp->v.FormattedValue.format_spec, Load); return validate_expr(exp->v.FormattedValue.format_spec, Load);
return 1; return 1;
case Bytes_kind: {
PyObject *b = exp->v.Bytes.s;
if (!PyBytes_CheckExact(b)) {
PyErr_SetString(PyExc_TypeError, "non-bytes type in Bytes");
return 0;
}
return 1;
}
case Attribute_kind: case Attribute_kind:
return validate_expr(exp->v.Attribute.value, Load); return validate_expr(exp->v.Attribute.value, Load);
case Subscript_kind: case Subscript_kind:
@ -339,10 +314,8 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
return validate_exprs(exp->v.List.elts, ctx, 0); return validate_exprs(exp->v.List.elts, ctx, 0);
case Tuple_kind: case Tuple_kind:
return validate_exprs(exp->v.Tuple.elts, ctx, 0); return validate_exprs(exp->v.Tuple.elts, ctx, 0);
/* These last cases don't have any checking. */ /* This last case doesn't have any checking. */
case Name_kind: case Name_kind:
case NameConstant_kind:
case Ellipsis_kind:
return 1; return 1;
default: default:
PyErr_SetString(PyExc_SystemError, "unexpected expression"); PyErr_SetString(PyExc_SystemError, "unexpected expression");
@ -1040,19 +1013,23 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
break; break;
case Dict_kind: case Dict_kind:
case Set_kind: case Set_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case JoinedStr_kind: case JoinedStr_kind:
case FormattedValue_kind: case FormattedValue_kind:
expr_name = "literal"; expr_name = "literal";
break; break;
case NameConstant_kind: case Constant_kind: {
expr_name = "keyword"; PyObject *value = e->v.Constant.value;
break; if (value == Py_None || value == Py_False || value == Py_True) {
case Ellipsis_kind: expr_name = "keyword";
expr_name = "Ellipsis"; }
else if (value == Py_Ellipsis) {
expr_name = "Ellipsis";
}
else {
expr_name = "literal";
}
break; break;
}
case Compare_kind: case Compare_kind:
expr_name = "comparison"; expr_name = "comparison";
break; break;
@ -2091,11 +2068,11 @@ ast_for_atom(struct compiling *c, const node *n)
size_t len = strlen(s); size_t len = strlen(s);
if (len >= 4 && len <= 5) { if (len >= 4 && len <= 5) {
if (!strcmp(s, "None")) if (!strcmp(s, "None"))
return NameConstant(Py_None, LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_None, LINENO(n), n->n_col_offset, c->c_arena);
if (!strcmp(s, "True")) if (!strcmp(s, "True"))
return NameConstant(Py_True, LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_True, LINENO(n), n->n_col_offset, c->c_arena);
if (!strcmp(s, "False")) if (!strcmp(s, "False"))
return NameConstant(Py_False, LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_False, LINENO(n), n->n_col_offset, c->c_arena);
} }
name = new_identifier(s, c); name = new_identifier(s, c);
if (!name) if (!name)
@ -2144,10 +2121,10 @@ ast_for_atom(struct compiling *c, const node *n)
Py_DECREF(pynum); Py_DECREF(pynum);
return NULL; return NULL;
} }
return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); return Constant(pynum, LINENO(n), n->n_col_offset, c->c_arena);
} }
case ELLIPSIS: /* Ellipsis */ case ELLIPSIS: /* Ellipsis */
return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_Ellipsis, LINENO(n), n->n_col_offset, c->c_arena);
case LPAR: /* some parenthesized expressions */ case LPAR: /* some parenthesized expressions */
ch = CHILD(n, 1); ch = CHILD(n, 1);
@ -4751,7 +4728,7 @@ typedef struct {
expr_ty's, and then after that start dynamically allocating, expr_ty's, and then after that start dynamically allocating,
doubling the number allocated each time. Note that the f-string doubling the number allocated each time. Note that the f-string
f'{0}a{1}' contains 3 expr_ty's: 2 FormattedValue's, and one f'{0}a{1}' contains 3 expr_ty's: 2 FormattedValue's, and one
Str for the literal 'a'. So you add expr_ty's about twice as Constant for the literal 'a'. So you add expr_ty's about twice as
fast as you add exressions in an f-string. */ fast as you add exressions in an f-string. */
Py_ssize_t allocated; /* Number we've allocated. */ Py_ssize_t allocated; /* Number we've allocated. */
@ -4903,7 +4880,7 @@ FstringParser_Dealloc(FstringParser *state)
ExprList_Dealloc(&state->expr_list); ExprList_Dealloc(&state->expr_list);
} }
/* Make a Str node, but decref the PyUnicode object being added. */ /* Make a Constant node, but decref the PyUnicode object being added. */
static expr_ty static expr_ty
make_str_node_and_del(PyObject **str, struct compiling *c, const node* n) make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
{ {
@ -4914,7 +4891,7 @@ make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
Py_DECREF(s); Py_DECREF(s);
return NULL; return NULL;
} }
return Str(s, LINENO(n), n->n_col_offset, c->c_arena); return Constant(s, LINENO(n), n->n_col_offset, c->c_arena);
} }
/* Add a non-f-string (that is, a regular literal string). str is /* Add a non-f-string (that is, a regular literal string). str is
@ -5002,11 +4979,11 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str,
break; break;
/* We know we have an expression. Convert any existing string /* We know we have an expression. Convert any existing string
to a Str node. */ to a Constant node. */
if (!state->last_str) { if (!state->last_str) {
/* Do nothing. No previous literal. */ /* Do nothing. No previous literal. */
} else { } else {
/* Convert the existing last_str literal to a Str node. */ /* Convert the existing last_str literal to a Constant node. */
expr_ty str = make_str_node_and_del(&state->last_str, c, n); expr_ty str = make_str_node_and_del(&state->last_str, c, n);
if (!str || ExprList_Append(&state->expr_list, str) < 0) if (!str || ExprList_Append(&state->expr_list, str) < 0)
return -1; return -1;
@ -5033,7 +5010,7 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str,
} }
/* Convert the partial state reflected in last_str and expr_list to an /* Convert the partial state reflected in last_str and expr_list to an
expr_ty. The expr_ty can be a Str, or a JoinedStr. */ expr_ty. The expr_ty can be a Constant, or a JoinedStr. */
static expr_ty static expr_ty
FstringParser_Finish(FstringParser *state, struct compiling *c, FstringParser_Finish(FstringParser *state, struct compiling *c,
const node *n) const node *n)
@ -5055,7 +5032,7 @@ FstringParser_Finish(FstringParser *state, struct compiling *c,
return make_str_node_and_del(&state->last_str, c, n); return make_str_node_and_del(&state->last_str, c, n);
} }
/* Create a Str node out of last_str, if needed. It will be the /* Create a Constant node out of last_str, if needed. It will be the
last node in our expression list. */ last node in our expression list. */
if (state->last_str) { if (state->last_str) {
expr_ty str = make_str_node_and_del(&state->last_str, c, n); expr_ty str = make_str_node_and_del(&state->last_str, c, n);
@ -5206,9 +5183,9 @@ parsestr(struct compiling *c, const node *n, int *bytesmode, int *rawmode,
/* Accepts a STRING+ atom, and produces an expr_ty node. Run through /* Accepts a STRING+ atom, and produces an expr_ty node. Run through
each STRING atom, and process it as needed. For bytes, just each STRING atom, and process it as needed. For bytes, just
concatenate them together, and the result will be a Bytes node. For concatenate them together, and the result will be a Constant node. For
normal strings and f-strings, concatenate them together. The result normal strings and f-strings, concatenate them together. The result
will be a Str node if there were no f-strings; a FormattedValue will be a Constant node if there were no f-strings; a FormattedValue
node if there's just an f-string (with no leading or trailing node if there's just an f-string (with no leading or trailing
literals), or a JoinedStr node if there are multiple f-strings or literals), or a JoinedStr node if there are multiple f-strings or
any literals involved. */ any literals involved. */
@ -5279,7 +5256,7 @@ parsestrplus(struct compiling *c, const node *n)
/* Just return the bytes object and we're done. */ /* Just return the bytes object and we're done. */
if (PyArena_AddPyObject(c->c_arena, bytes_str) < 0) if (PyArena_AddPyObject(c->c_arena, bytes_str) < 0)
goto error; goto error;
return Bytes(bytes_str, LINENO(n), n->n_col_offset, c->c_arena); return Constant(bytes_str, LINENO(n), n->n_col_offset, c->c_arena);
} }
/* We're not a bytes string, bytes_str should never have been set. */ /* We're not a bytes string, bytes_str should never have been set. */
@ -5304,9 +5281,6 @@ _PyAST_GetDocString(asdl_seq *body)
return NULL; return NULL;
} }
expr_ty e = st->v.Expr.value; expr_ty e = st->v.Expr.value;
if (e->kind == Str_kind) {
return e->v.Str.s;
}
if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) { if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) {
return e->v.Constant.value; return e->v.Constant.value;
} }

View File

@ -5,47 +5,6 @@
#include "ast.h" #include "ast.h"
/* TODO: is_const and get_const_value are copied from Python/compile.c.
It should be deduped in the future. Maybe, we can include this file
from compile.c?
*/
static int
is_const(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
case NameConstant_kind:
return 1;
default:
return 0;
}
}
static PyObject *
get_const_value(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
return e->v.Constant.value;
case Num_kind:
return e->v.Num.n;
case Str_kind:
return e->v.Str.s;
case Bytes_kind:
return e->v.Bytes.s;
case Ellipsis_kind:
return Py_Ellipsis;
case NameConstant_kind:
return e->v.NameConstant.value;
default:
Py_UNREACHABLE();
}
}
static int static int
make_const(expr_ty node, PyObject *val, PyArena *arena) make_const(expr_ty node, PyObject *val, PyArena *arena)
{ {
@ -81,7 +40,7 @@ fold_unaryop(expr_ty node, PyArena *arena, int optimize)
{ {
expr_ty arg = node->v.UnaryOp.operand; expr_ty arg = node->v.UnaryOp.operand;
if (!is_const(arg)) { if (arg->kind != Constant_kind) {
/* Fold not into comparison */ /* Fold not into comparison */
if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind && if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
asdl_seq_LEN(arg->v.Compare.ops) == 1) { asdl_seq_LEN(arg->v.Compare.ops) == 1) {
@ -123,7 +82,7 @@ fold_unaryop(expr_ty node, PyArena *arena, int optimize)
[UAdd] = PyNumber_Positive, [UAdd] = PyNumber_Positive,
[USub] = PyNumber_Negative, [USub] = PyNumber_Negative,
}; };
PyObject *newval = ops[node->v.UnaryOp.op](get_const_value(arg)); PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
return make_const(node, newval, arena); return make_const(node, newval, arena);
} }
@ -259,12 +218,12 @@ fold_binop(expr_ty node, PyArena *arena, int optimize)
expr_ty lhs, rhs; expr_ty lhs, rhs;
lhs = node->v.BinOp.left; lhs = node->v.BinOp.left;
rhs = node->v.BinOp.right; rhs = node->v.BinOp.right;
if (!is_const(lhs) || !is_const(rhs)) { if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
return 1; return 1;
} }
PyObject *lv = get_const_value(lhs); PyObject *lv = lhs->v.Constant.value;
PyObject *rv = get_const_value(rhs); PyObject *rv = rhs->v.Constant.value;
PyObject *newval; PyObject *newval;
switch (node->v.BinOp.op) { switch (node->v.BinOp.op) {
@ -316,7 +275,7 @@ make_const_tuple(asdl_seq *elts)
{ {
for (int i = 0; i < asdl_seq_LEN(elts); i++) { for (int i = 0; i < asdl_seq_LEN(elts); i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i); expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
if (!is_const(e)) { if (e->kind != Constant_kind) {
return NULL; return NULL;
} }
} }
@ -328,7 +287,7 @@ make_const_tuple(asdl_seq *elts)
for (int i = 0; i < asdl_seq_LEN(elts); i++) { for (int i = 0; i < asdl_seq_LEN(elts); i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i); expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
PyObject *v = get_const_value(e); PyObject *v = e->v.Constant.value;
Py_INCREF(v); Py_INCREF(v);
PyTuple_SET_ITEM(newval, i, v); PyTuple_SET_ITEM(newval, i, v);
} }
@ -357,16 +316,16 @@ fold_subscr(expr_ty node, PyArena *arena, int optimize)
arg = node->v.Subscript.value; arg = node->v.Subscript.value;
slice = node->v.Subscript.slice; slice = node->v.Subscript.slice;
if (node->v.Subscript.ctx != Load || if (node->v.Subscript.ctx != Load ||
!is_const(arg) || arg->kind != Constant_kind ||
/* TODO: handle other types of slices */ /* TODO: handle other types of slices */
slice->kind != Index_kind || slice->kind != Index_kind ||
!is_const(slice->v.Index.value)) slice->v.Index.value->kind != Constant_kind)
{ {
return 1; return 1;
} }
idx = slice->v.Index.value; idx = slice->v.Index.value;
newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx)); newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
return make_const(node, newval, arena); return make_const(node, newval, arena);
} }

View File

@ -567,8 +567,6 @@ append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
switch (e->kind) { switch (e->kind) {
case Constant_kind: case Constant_kind:
return append_fstring_unicode(writer, e->v.Constant.value); return append_fstring_unicode(writer, e->v.Constant.value);
case Str_kind:
return append_fstring_unicode(writer, e->v.Str.s);
case JoinedStr_kind: case JoinedStr_kind:
return append_joinedstr(writer, e, is_format_spec); return append_joinedstr(writer, e, is_format_spec);
case FormattedValue_kind: case FormattedValue_kind:
@ -690,13 +688,12 @@ static int
append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
{ {
const char *period; const char *period;
APPEND_EXPR(e->v.Attribute.value, PR_ATOM); expr_ty v = e->v.Attribute.value;
APPEND_EXPR(v, PR_ATOM);
/* Special case: integers require a space for attribute access to be /* Special case: integers require a space for attribute access to be
unambiguous. Floats and complex numbers don't but work with it, too. */ unambiguous. */
if (e->v.Attribute.value->kind == Num_kind || if (v->kind == Constant_kind && PyLong_CheckExact(v->v.Constant.value)) {
e->v.Attribute.value->kind == Constant_kind)
{
period = " ."; period = " .";
} }
else { else {
@ -841,21 +838,14 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
case Call_kind: case Call_kind:
return append_ast_call(writer, e); return append_ast_call(writer, e);
case Constant_kind: case Constant_kind:
if (e->v.Constant.value == Py_Ellipsis) {
APPEND_STR_FINISH("...");
}
return append_repr(writer, e->v.Constant.value); return append_repr(writer, e->v.Constant.value);
case Num_kind:
return append_repr(writer, e->v.Num.n);
case Str_kind:
return append_repr(writer, e->v.Str.s);
case JoinedStr_kind: case JoinedStr_kind:
return append_joinedstr(writer, e, false); return append_joinedstr(writer, e, false);
case FormattedValue_kind: case FormattedValue_kind:
return append_formattedvalue(writer, e, false); return append_formattedvalue(writer, e, false);
case Bytes_kind:
return append_repr(writer, e->v.Bytes.s);
case Ellipsis_kind:
APPEND_STR_FINISH("...");
case NameConstant_kind:
return append_repr(writer, e->v.NameConstant.value);
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */
case Attribute_kind: case Attribute_kind:
return append_ast_attribute(writer, e); return append_ast_attribute(writer, e);

View File

@ -1398,43 +1398,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
} \ } \
} }
static int
is_const(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
case NameConstant_kind:
return 1;
default:
return 0;
}
}
static PyObject *
get_const_value(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
return e->v.Constant.value;
case Num_kind:
return e->v.Num.n;
case Str_kind:
return e->v.Str.s;
case Bytes_kind:
return e->v.Bytes.s;
case Ellipsis_kind:
return Py_Ellipsis;
case NameConstant_kind:
return e->v.NameConstant.value;
default:
Py_UNREACHABLE();
}
}
/* Search if variable annotations are present statically in a block. */ /* Search if variable annotations are present statically in a block. */
static int static int
@ -2568,7 +2531,7 @@ static int
compiler_return(struct compiler *c, stmt_ty s) compiler_return(struct compiler *c, stmt_ty s)
{ {
int preserve_tos = ((s->v.Return.value != NULL) && int preserve_tos = ((s->v.Return.value != NULL) &&
!is_const(s->v.Return.value)); (s->v.Return.value->kind != Constant_kind));
if (c->u->u_ste->ste_type != FunctionBlock) if (c->u->u_ste->ste_type != FunctionBlock)
return compiler_error(c, "'return' outside function"); return compiler_error(c, "'return' outside function");
if (s->v.Return.value != NULL && if (s->v.Return.value != NULL &&
@ -3054,7 +3017,7 @@ compiler_visit_stmt_expr(struct compiler *c, expr_ty value)
return 1; return 1;
} }
if (is_const(value)) { if (value->kind == Constant_kind) {
/* ignore constant statement */ /* ignore constant statement */
return 1; return 1;
} }
@ -3502,7 +3465,7 @@ are_all_items_const(asdl_seq *seq, Py_ssize_t begin, Py_ssize_t end)
Py_ssize_t i; Py_ssize_t i;
for (i = begin; i < end; i++) { for (i = begin; i < end; i++) {
expr_ty key = (expr_ty)asdl_seq_GET(seq, i); expr_ty key = (expr_ty)asdl_seq_GET(seq, i);
if (key == NULL || !is_const(key)) if (key == NULL || key->kind != Constant_kind)
return 0; return 0;
} }
return 1; return 1;
@ -3522,7 +3485,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end
return 0; return 0;
} }
for (i = begin; i < end; i++) { for (i = begin; i < end; i++) {
key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); key = ((expr_ty)asdl_seq_GET(e->v.Dict.keys, i))->v.Constant.value;
Py_INCREF(key); Py_INCREF(key);
PyTuple_SET_ITEM(keys, i - begin, key); PyTuple_SET_ITEM(keys, i - begin, key);
} }
@ -4244,8 +4207,8 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
static int static int
expr_constant(expr_ty e) expr_constant(expr_ty e)
{ {
if (is_const(e)) { if (e->kind == Constant_kind) {
return PyObject_IsTrue(get_const_value(e)); return PyObject_IsTrue(e->v.Constant.value);
} }
return -1; return -1;
} }
@ -4505,25 +4468,10 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
case Constant_kind: case Constant_kind:
ADDOP_LOAD_CONST(c, e->v.Constant.value); ADDOP_LOAD_CONST(c, e->v.Constant.value);
break; break;
case Num_kind:
ADDOP_LOAD_CONST(c, e->v.Num.n);
break;
case Str_kind:
ADDOP_LOAD_CONST(c, e->v.Str.s);
break;
case JoinedStr_kind: case JoinedStr_kind:
return compiler_joined_str(c, e); return compiler_joined_str(c, e);
case FormattedValue_kind: case FormattedValue_kind:
return compiler_formatted_value(c, e); return compiler_formatted_value(c, e);
case Bytes_kind:
ADDOP_LOAD_CONST(c, e->v.Bytes.s);
break;
case Ellipsis_kind:
ADDOP_LOAD_CONST(c, Py_Ellipsis);
break;
case NameConstant_kind:
ADDOP_LOAD_CONST(c, e->v.NameConstant.value);
break;
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */
case Attribute_kind: case Attribute_kind:
if (e->v.Attribute.ctx != AugStore) if (e->v.Attribute.ctx != AugStore)

View File

@ -1461,11 +1461,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
VISIT_SEQ(st, expr, e->v.JoinedStr.values); VISIT_SEQ(st, expr, e->v.JoinedStr.values);
break; break;
case Constant_kind: case Constant_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
case NameConstant_kind:
/* Nothing to do here. */ /* Nothing to do here. */
break; break;
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */

View File

@ -3840,9 +3840,6 @@ class DSLParser:
# "starred": "a = [1, 2, 3]; *a" # "starred": "a = [1, 2, 3]; *a"
visit_Starred = bad_node visit_Starred = bad_node
# allow ellipsis, for now
# visit_Ellipsis = bad_node
blacklist = DetectBadNodes() blacklist = DetectBadNodes()
blacklist.visit(module) blacklist.visit(module)
bad = blacklist.bad bad = blacklist.bad
@ -3868,10 +3865,15 @@ class DSLParser:
py_default = 'None' py_default = 'None'
c_default = "NULL" c_default = "NULL"
elif (isinstance(expr, ast.BinOp) or elif (isinstance(expr, ast.BinOp) or
(isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))): (isinstance(expr, ast.UnaryOp) and
not (isinstance(expr.operand, ast.Num) or
(hasattr(ast, 'Constant') and
isinstance(expr.operand, ast.Constant) and
type(expr.operand.value) in (int, float, complex)))
)):
c_default = kwargs.get("c_default") c_default = kwargs.get("c_default")
if not (isinstance(c_default, str) and c_default): if not (isinstance(c_default, str) and c_default):
fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.") fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default." + ast.dump(expr))
py_default = default py_default = default
value = unknown value = unknown
elif isinstance(expr, ast.Attribute): elif isinstance(expr, ast.Attribute):
@ -3946,6 +3948,11 @@ class DSLParser:
self.function.parameters[parameter_name] = p self.function.parameters[parameter_name] = p
def parse_converter(self, annotation): def parse_converter(self, annotation):
if (hasattr(ast, 'Constant') and
isinstance(annotation, ast.Constant) and
type(annotation.value) is str):
return annotation.value, True, {}
if isinstance(annotation, ast.Str): if isinstance(annotation, ast.Str):
return annotation.s, True, {} return annotation.s, True, {}

View File

@ -329,12 +329,6 @@ class Unparser:
self.leave() self.leave()
# expr # expr
def _Bytes(self, t):
self.write(repr(t.s))
def _Str(self, tree):
self.write(repr(tree.s))
def _JoinedStr(self, t): def _JoinedStr(self, t):
self.write("f") self.write("f")
string = io.StringIO() string = io.StringIO()
@ -352,10 +346,6 @@ class Unparser:
meth = getattr(self, "_fstring_" + type(value).__name__) meth = getattr(self, "_fstring_" + type(value).__name__)
meth(value, write) meth(value, write)
def _fstring_Str(self, t, write):
value = t.s.replace("{", "{{").replace("}", "}}")
write(value)
def _fstring_Constant(self, t, write): def _fstring_Constant(self, t, write):
assert isinstance(t.value, str) assert isinstance(t.value, str)
value = t.value.replace("{", "{{").replace("}", "}}") value = t.value.replace("{", "{{").replace("}", "}}")
@ -384,6 +374,7 @@ class Unparser:
def _write_constant(self, value): def _write_constant(self, value):
if isinstance(value, (float, complex)): if isinstance(value, (float, complex)):
# Substitute overflowing decimal literal for AST infinities.
self.write(repr(value).replace("inf", INFSTR)) self.write(repr(value).replace("inf", INFSTR))
else: else:
self.write(repr(value)) self.write(repr(value))
@ -398,16 +389,11 @@ class Unparser:
else: else:
interleave(lambda: self.write(", "), self._write_constant, value) interleave(lambda: self.write(", "), self._write_constant, value)
self.write(")") self.write(")")
elif value is ...:
self.write("...")
else: else:
self._write_constant(t.value) self._write_constant(t.value)
def _NameConstant(self, t):
self.write(repr(t.value))
def _Num(self, t):
# Substitute overflowing decimal literal for AST infinities.
self.write(repr(t.n).replace("inf", INFSTR))
def _List(self, t): def _List(self, t):
self.write("[") self.write("[")
interleave(lambda: self.write(", "), self.dispatch, t.elts) interleave(lambda: self.write(", "), self.dispatch, t.elts)
@ -539,8 +525,7 @@ class Unparser:
# Special case: 3.__abs__() is a syntax error, so if t.value # Special case: 3.__abs__() is a syntax error, so if t.value
# is an integer literal then we need to either parenthesize # is an integer literal then we need to either parenthesize
# it or add an extra space to get 3 .__abs__(). # it or add an extra space to get 3 .__abs__().
if ((isinstance(t.value, ast.Num) and isinstance(t.value.n, int)) if isinstance(t.value, ast.Constant) and isinstance(t.value.value, int):
or (isinstance(t.value, ast.Constant) and isinstance(t.value.value, int))):
self.write(" ") self.write(" ")
self.write(".") self.write(".")
self.write(t.attr) self.write(t.attr)