Skip to content

ast.Assign need type_comment in Python3.8 #49

Description

@Aurelius84

In python3.8.5,I use gast to modify ast_node then convert back into ast bygast_to_ast. But the result is different with original ast.

It works in Python3.5 and Python2.7

The example code:

import ast
import gast
import textwrap
import unittest

def code_gast_ast(source):
    """
    Transform source_code into gast.Node and modify it,
    then back to ast.Node.
    """
    source = textwrap.dedent(source)
    root = gast.parse(source)
    new_root = GastNodeTransformer(root).apply()
    ast_root = gast.gast_to_ast(new_root)
    return ast.dump(ast_root)


def code_ast(source):
    """
    Transform source_code into ast.Node, then dump it.
    """
    source = textwrap.dedent(source)
    root = ast.parse(source)
    return ast.dump(root)


class GastNodeTransformer(gast.NodeTransformer):
    def __init__(self, root):
        self.root = root

    def apply(self):
        return self.generic_visit(self.root)

    def visit_Name(self, node):
        """
        Param in func is ast.Name in PY2, but ast.arg in PY3.
        It will be generally represented by gast.Name in gast.
        """
        if isinstance(node.ctx, gast.Param) and node.id != "self":
            node.id += '_new'

        return node

class TestPythonCompatibility(unittest.TestCase):
    def _check_compatibility(self, source, target):
        source_dump = code_gast_ast(source)
        target_dump = code_ast(target)
        self.assertEqual(source_dump, target_dump)

    def test_call(self):
        source = """
            y = foo(*arg)
        """
        target = """
            y = foo(*arg_new)
        """
        self._check_compatibility(source, target)

# source_dump  gast-> ast
# Module(body=[Assign(targets=[Name(id='y', ctx=Store())], value=Call(func=Name(id='foo', ctx=Load()), args=[Starred(value=Name(id='arg_new', ctx=Load()), ctx=Load())], keywords=[]))], type_ignores=[])

# target_dump ast
# Module(body=[Assign(targets=[Name(id='y', ctx=Store())], value=Call(func=Name(id='foo', ctx=Load()), args=[Starred(value=Name(id='arg_new', ctx=Load()), ctx=Load())], keywords=[]), type_comment=None)], type_ignores=[])

After I modified the defination in gast.py, it works in python3.8

from

('Assign', (('targets', 'value',),
                ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
                (stmt,))),

into

('Assign', (('targets', 'value','type_comment'),
                ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',),
                (stmt,))),

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions