[pypy-commit] pypy py3.5: Use ast.NameConstant instead of ast.Name for None/True/False
arigo
pypy.commits at gmail.com
Tue Sep 13 11:41:00 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r87081:19e8fc8dcfd0
Date: 2016-09-13 17:39 +0200
http://bitbucket.org/pypy/pypy/changeset/19e8fc8dcfd0/
Log: Use ast.NameConstant instead of ast.Name for None/True/False (that
class was not used so far)
diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -1194,9 +1194,19 @@
first_child = atom_node.get_child(0)
first_child_type = first_child.type
if first_child_type == tokens.NAME:
- name = self.new_identifier(first_child.get_value())
- return ast.Name(name, ast.Load, first_child.get_lineno(),
- first_child.get_column())
+ name = first_child.get_value()
+ if name == "None":
+ w_singleton = self.space.w_None
+ elif name == "True":
+ w_singleton = self.space.w_True
+ elif name == "False":
+ w_singleton = self.space.w_False
+ else:
+ name = self.new_identifier(name)
+ return ast.Name(name, ast.Load, first_child.get_lineno(),
+ first_child.get_column())
+ return ast.NameConstant(w_singleton, first_child.get_lineno(),
+ first_child.get_column())
elif first_child_type == tokens.STRING:
space = self.space
encoding = self.compile_info.encoding
diff --git a/pypy/interpreter/astcompiler/asthelpers.py b/pypy/interpreter/astcompiler/asthelpers.py
--- a/pypy/interpreter/astcompiler/asthelpers.py
+++ b/pypy/interpreter/astcompiler/asthelpers.py
@@ -22,15 +22,19 @@
class __extend__(ast.expr):
constant = False
+ _description = None
def as_node_list(self, space):
return None
def set_context(self, ctx):
+ d = self._description
+ if d is None:
+ d = "%r" % (self,)
if ctx == ast.Del:
- msg = "can't delete %s" % (self._description,)
+ msg = "can't delete %s" % (d,)
else:
- msg = "can't assign to %s" % (self._description,)
+ msg = "can't assign to %s" % (d,)
raise UnacceptableExpressionContext(self, msg)
@@ -174,3 +178,9 @@
_description = "Ellipsis"
constant = True
+
+
+class __extend__(ast.NameConstant):
+
+ _description = "name constant"
+ constant = True
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1271,6 +1271,10 @@
self.update_position(name.lineno)
self.name_op(name.id, name.ctx)
+ def visit_NameConstant(self, node):
+ self.update_position(node.lineno)
+ self.load_const(node.single)
+
def visit_keyword(self, keyword):
if keyword.arg is not None:
self.load_const(self.space.wrap(keyword.arg.decode('utf-8')))
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -67,6 +67,11 @@
def as_constant(self):
return self.obj
+class __extend__(ast.NameConstant):
+
+ def as_constant(self):
+ return self.single
+
class __extend__(ast.Index):
def as_constant(self):
return self.value.as_constant()
diff --git a/pypy/interpreter/astcompiler/test/test_validate.py b/pypy/interpreter/astcompiler/test/test_validate.py
--- a/pypy/interpreter/astcompiler/test/test_validate.py
+++ b/pypy/interpreter/astcompiler/test/test_validate.py
@@ -390,9 +390,21 @@
def test_tuple(self):
self._sequence(ast.Tuple)
+ def test_nameconstant(self):
+ node = ast.NameConstant("True", 0, 0)
+ self.expr(node, "singleton must be True, False, or None")
+
def test_stdlib_validates(self):
stdlib = os.path.join(os.path.dirname(ast.__file__), '../../../lib-python/3')
- tests = ["os.py", "test/test_grammar.py", "test/test_unpack_ex.py"]
+ if 1: # enable manually for a complete test
+ tests = [fn for fn in os.listdir(stdlib) if fn.endswith('.py')]
+ tests += ['test/'+fn for fn in os.listdir(stdlib+'/test')
+ if fn.endswith('.py')
+ and not fn.startswith('bad')]
+ tests.sort()
+ else:
+ tests = ["os.py", "test/test_grammar.py", "test/test_unpack_ex.py"]
+ #
for module in tests:
fn = os.path.join(stdlib, module)
print 'compiling', fn
diff --git a/pypy/interpreter/astcompiler/validate.py b/pypy/interpreter/astcompiler/validate.py
--- a/pypy/interpreter/astcompiler/validate.py
+++ b/pypy/interpreter/astcompiler/validate.py
@@ -1,6 +1,6 @@
"""A visitor to validate an AST object."""
-from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import oefmt
from pypy.interpreter.astcompiler import ast
from rpython.tool.pairtype import pair, pairtype
from pypy.interpreter.baseobjspace import W_Root
@@ -440,3 +440,10 @@
def visit_Index(self, node):
self._validate_expr(node.value)
+
+ def visit_NameConstant(self, node):
+ space = self.space
+ if (node.single is not space.w_None and
+ node.single is not space.w_True and
+ node.single is not space.w_False):
+ raise ValidationError("singleton must be True, False, or None")
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -689,10 +689,11 @@
except NameError:
pass
'''
- code = self.compiler.compile(snippet, '<tmp>', 'exec', 0)
+ e = py.test.raises(OperationError, self.compiler.compile,
+ snippet, '<tmp>', 'exec', 0)
+ ex = e.value
space = self.space
- w_d = space.newdict()
- space.exec_(code, w_d, w_d)
+ assert ex.match(space, space.w_SyntaxError)
def test_from_future_import(self):
source = """from __future__ import with_statement
More information about the pypy-commit
mailing list