bpo-36917: Add default implementation of ast.NodeVisitor.visit_Constant(). (GH-15490)
It emits a deprecation warning and calls corresponding method visit_Num(), visit_Str(), etc.
This commit is contained in:
parent
44cd86bbdd
commit
c3ea41e9bf
|
@ -275,6 +275,13 @@ and classes for traversing abstract syntax trees:
|
||||||
during traversal. For this a special visitor exists
|
during traversal. For this a special visitor exists
|
||||||
(:class:`NodeTransformer`) that allows modifications.
|
(:class:`NodeTransformer`) that allows modifications.
|
||||||
|
|
||||||
|
.. deprecated:: 3.8
|
||||||
|
|
||||||
|
Methods :meth:`visit_Num`, :meth:`visit_Str`, :meth:`visit_Bytes`,
|
||||||
|
:meth:`visit_NameConstant` and :meth:`visit_Ellipsis` are deprecated
|
||||||
|
now and will not be called in future Python versions. Add the
|
||||||
|
:meth:`visit_Constant` method to handle all constant nodes.
|
||||||
|
|
||||||
|
|
||||||
.. class:: NodeTransformer()
|
.. class:: NodeTransformer()
|
||||||
|
|
||||||
|
|
|
@ -1360,6 +1360,13 @@ Deprecated
|
||||||
versions. :class:`~ast.Constant` should be used instead.
|
versions. :class:`~ast.Constant` should be used instead.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`32892`.)
|
(Contributed by Serhiy Storchaka in :issue:`32892`.)
|
||||||
|
|
||||||
|
* :class:`ast.NodeVisitor` methods ``visit_Num()``, ``visit_Str()``,
|
||||||
|
``visit_Bytes()``, ``visit_NameConstant()`` and ``visit_Ellipsis()`` are
|
||||||
|
deprecated now and will not be called in future Python versions.
|
||||||
|
Add the :meth:`~ast.NodeVisitor.visit_Constant` method to handle all
|
||||||
|
constant nodes.
|
||||||
|
(Contributed by Serhiy Storchaka in :issue:`36917`.)
|
||||||
|
|
||||||
* The following functions and methods are deprecated in the :mod:`gettext`
|
* The following functions and methods are deprecated in the :mod:`gettext`
|
||||||
module: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`,
|
module: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`,
|
||||||
:func:`~gettext.lngettext` and :func:`~gettext.ldngettext`.
|
:func:`~gettext.lngettext` and :func:`~gettext.ldngettext`.
|
||||||
|
|
31
Lib/ast.py
31
Lib/ast.py
|
@ -360,6 +360,27 @@ class NodeVisitor(object):
|
||||||
elif isinstance(value, AST):
|
elif isinstance(value, AST):
|
||||||
self.visit(value)
|
self.visit(value)
|
||||||
|
|
||||||
|
def visit_Constant(self, node):
|
||||||
|
value = node.value
|
||||||
|
type_name = _const_node_type_names.get(type(value))
|
||||||
|
if type_name is None:
|
||||||
|
for cls, name in _const_node_type_names.items():
|
||||||
|
if isinstance(value, cls):
|
||||||
|
type_name = name
|
||||||
|
break
|
||||||
|
if type_name is not None:
|
||||||
|
method = 'visit_' + type_name
|
||||||
|
try:
|
||||||
|
visitor = getattr(self, method)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
import warnings
|
||||||
|
warnings.warn(f"{method} is deprecated; add visit_Constant",
|
||||||
|
DeprecationWarning, 2)
|
||||||
|
return visitor(node)
|
||||||
|
return self.generic_visit(node)
|
||||||
|
|
||||||
|
|
||||||
class NodeTransformer(NodeVisitor):
|
class NodeTransformer(NodeVisitor):
|
||||||
"""
|
"""
|
||||||
|
@ -487,3 +508,13 @@ _const_types = {
|
||||||
_const_types_not = {
|
_const_types_not = {
|
||||||
Num: (bool,),
|
Num: (bool,),
|
||||||
}
|
}
|
||||||
|
_const_node_type_names = {
|
||||||
|
bool: 'NameConstant', # should be before int
|
||||||
|
type(None): 'NameConstant',
|
||||||
|
int: 'Num',
|
||||||
|
float: 'Num',
|
||||||
|
complex: 'Num',
|
||||||
|
str: 'Str',
|
||||||
|
bytes: 'Bytes',
|
||||||
|
type(...): 'Ellipsis',
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import dis
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
import weakref
|
import weakref
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
|
@ -1662,6 +1663,56 @@ class EndPositionTests(unittest.TestCase):
|
||||||
self.assertEqual(ast.get_source_segment(s, cdef.body[0], padded=True), s_method)
|
self.assertEqual(ast.get_source_segment(s, cdef.body[0], padded=True), s_method)
|
||||||
|
|
||||||
|
|
||||||
|
class NodeVisitorTests(unittest.TestCase):
|
||||||
|
def test_old_constant_nodes(self):
|
||||||
|
class Visitor(ast.NodeVisitor):
|
||||||
|
def visit_Num(self, node):
|
||||||
|
log.append((node.lineno, 'Num', node.n))
|
||||||
|
def visit_Str(self, node):
|
||||||
|
log.append((node.lineno, 'Str', node.s))
|
||||||
|
def visit_Bytes(self, node):
|
||||||
|
log.append((node.lineno, 'Bytes', node.s))
|
||||||
|
def visit_NameConstant(self, node):
|
||||||
|
log.append((node.lineno, 'NameConstant', node.value))
|
||||||
|
def visit_Ellipsis(self, node):
|
||||||
|
log.append((node.lineno, 'Ellipsis', ...))
|
||||||
|
mod = ast.parse(dedent('''\
|
||||||
|
i = 42
|
||||||
|
f = 4.25
|
||||||
|
c = 4.25j
|
||||||
|
s = 'string'
|
||||||
|
b = b'bytes'
|
||||||
|
t = True
|
||||||
|
n = None
|
||||||
|
e = ...
|
||||||
|
'''))
|
||||||
|
visitor = Visitor()
|
||||||
|
log = []
|
||||||
|
with warnings.catch_warnings(record=True) as wlog:
|
||||||
|
warnings.filterwarnings('always', '', DeprecationWarning)
|
||||||
|
visitor.visit(mod)
|
||||||
|
self.assertEqual(log, [
|
||||||
|
(1, 'Num', 42),
|
||||||
|
(2, 'Num', 4.25),
|
||||||
|
(3, 'Num', 4.25j),
|
||||||
|
(4, 'Str', 'string'),
|
||||||
|
(5, 'Bytes', b'bytes'),
|
||||||
|
(6, 'NameConstant', True),
|
||||||
|
(7, 'NameConstant', None),
|
||||||
|
(8, 'Ellipsis', ...),
|
||||||
|
])
|
||||||
|
self.assertEqual([str(w.message) for w in wlog], [
|
||||||
|
'visit_Num is deprecated; add visit_Constant',
|
||||||
|
'visit_Num is deprecated; add visit_Constant',
|
||||||
|
'visit_Num is deprecated; add visit_Constant',
|
||||||
|
'visit_Str is deprecated; add visit_Constant',
|
||||||
|
'visit_Bytes is deprecated; add visit_Constant',
|
||||||
|
'visit_NameConstant is deprecated; add visit_Constant',
|
||||||
|
'visit_NameConstant is deprecated; add visit_Constant',
|
||||||
|
'visit_Ellipsis is deprecated; add visit_Constant',
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if __name__ != '__main__':
|
if __name__ != '__main__':
|
||||||
return
|
return
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Add default implementation of the :meth:`ast.NodeVisitor.visit_Constant`
|
||||||
|
method which emits a deprecation warning and calls corresponding methody
|
||||||
|
``visit_Num()``, ``visit_Str()``, etc.
|
Loading…
Reference in New Issue