bpo-34822: Simplify AST for subscription. by serhiy-storchaka · Pull Request #9605 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 30 additions & 37 deletions Doc/library/ast.rst
2 changes: 2 additions & 0 deletions Doc/tools/susp-ignored.csv
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ howto/pyporting,,::,Programming Language :: Python :: 3
howto/regex,,::,
howto/regex,,:foo,(?:foo)
howto/urllib2,,:password,"""joe:password@example.com"""
library/ast,,:upper,lower:upper
library/ast,,:step,lower:upper:step
library/audioop,,:ipos,"# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],"
library/bisect,32,:hi,all(val >= x for val in a[i:hi])
library/bisect,42,:hi,all(val > x for val in a[i:hi])
Expand Down
12 changes: 12 additions & 0 deletions Doc/whatsnew/3.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,12 @@ Deprecated

(Contributed by Victor Stinner in :issue:`39353`.)

* :mod:`ast` classes ``Index`` and ``ExtSlice`` are considered deprecated
and will be removed in future Python versions. ``value`` itself should be
used instead of ``Index(value)``. ``Tuple(slices, Load())`` should be
used instead of ``ExtSlice(slices)``.
(Contributed by Serhiy Storchaka in :issue:`32892`.)


Removed
=======
Expand Down Expand Up @@ -645,6 +651,12 @@ Changes in the Python API
since the *buffering* parameter has been removed.
(Contributed by Victor Stinner in :issue:`39357`.)

* Simplified AST for subscription. Simple indices will be represented by
their value, extended slices will be represented as tuples.
``Index(value)`` will return a ``value`` itself, ``ExtSlice(slices)``
will return ``Tuple(slices, Load())``.
(Contributed by Serhiy Storchaka in :issue:`34822`.)


CPython bytecode changes
------------------------
Expand Down
41 changes: 11 additions & 30 deletions Include/Python-ast.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 15 additions & 19 deletions Lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ class RewriteName(NodeTransformer):
def visit_Name(self, node):
return copy_location(Subscript(
value=Name(id='data', ctx=Load()),
slice=Index(value=Str(s=node.id)),
slice=Constant(value=node.id),
ctx=node.ctx
), node)

Expand Down Expand Up @@ -546,6 +546,7 @@ def __new__(cls, *args, **kwargs):
_const_types_not = {
Num: (bool,),
}

_const_node_type_names = {
bool: 'NameConstant', # should be before int
type(None): 'NameConstant',
Expand All @@ -557,6 +558,15 @@ def __new__(cls, *args, **kwargs):
type(...): 'Ellipsis',
}

class Index(AST):
def __new__(cls, value, *args, **kwargs):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there ever any additional positional args? (I presume kwargs could be lineno etc.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No!

return value

class ExtSlice(AST):
def __new__(cls, dims=(), *args, **kwargs):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not make dims a mandatory argument, like value for Index?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Index without value cannot work. This change breaks the following code

node = Index()
node.value = Constant(1)

but we cannot keep it working. We should have something to return from Index().

On other side, ExtSlice with empty dims is invalid, and the following legal code

node = ExtSlice()
node.dims.append(Ellipsis())

will be broken because Tuple has the elts filed instead of dims. We can add an alias dims in Tuple to make the above example working. Should we? If not, than making dims a required parameter will not break anything that is not broken.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.S. There is a test (test_field_attr_existence) which tests that all node classes are callable without arguments (Index is an exception now). Should we make ExtSlice an exception too?

return Tuple(list(dims), Load(), *args, **kwargs)


# Large float and imaginary literals get turned into infinities in the AST.
# We unparse those infinities to INFSTR.
_INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
Expand Down Expand Up @@ -1261,15 +1271,13 @@ def visit_Subscript(self, node):
self.set_precedence(_Precedence.ATOM, node.value)
self.traverse(node.value)
with self.delimit("[", "]"):
if (isinstance(node.slice, Index)
and isinstance(node.slice.value, Tuple)
and node.slice.value.elts):
if len(node.slice.value.elts) == 1:
elt = node.slice.value.elts[0]
if isinstance(node.slice, Tuple) and node.slice.elts:
if len(node.slice.elts) == 1:
elt = node.slice.elts[0]
self.traverse(elt)
self.write(",")
else:
self.interleave(lambda: self.write(", "), self.traverse, node.slice.value.elts)
self.interleave(lambda: self.write(", "), self.traverse, node.slice.elts)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing you'll get a merge conflict here if GH-17892 is merged first (which I think it should be).

else:
self.traverse(node.slice)

Expand All @@ -1281,10 +1289,6 @@ def visit_Starred(self, node):
def visit_Ellipsis(self, node):
self.write("...")

def visit_Index(self, node):
self.set_precedence(_Precedence.TUPLE, node.value)
self.traverse(node.value)

def visit_Slice(self, node):
if node.lower:
self.traverse(node.lower)
Expand All @@ -1295,14 +1299,6 @@ def visit_Slice(self, node):
self.write(":")
self.traverse(node.step)

def visit_ExtSlice(self, node):
if len(node.dims) == 1:
elt = node.dims[0]
self.traverse(elt)
self.write(",")
else:
self.interleave(lambda: self.write(", "), self.traverse, node.dims)

def visit_arg(self, node):
self.write(node.arg)
if node.annotation:
Expand Down
24 changes: 14 additions & 10 deletions Lib/test/test_ast.py
Loading