Skip to content

Provide __mypyc_attrs__ analogue for non-compiled mypy #12935

Closed
@devmessias

Description

@devmessias

Feature

mpyc_attrs provides a simple way to list all the attributes that can be related to SymbolTableNode, Nodes, etc.
If I understood correctly __mypyc_attrs__ is similar to _fields attribute on the python ast module.

In mypy, this attribute exists only in the compiled version and it's provided by allocate_class

create_mypyc_attrs_tuple(builder, builder.mapper.type_to_ir[cdef.info], cdef.line)],

Pitch

I'm trying to create something that can also be used to address the following issues

#4868
#12513

One example of use is this

import mypy.main as MAIN
import mypy.build as BUILD

from mypy.nodes import SymbolTableNode, Node, NodeVisitor
py_file = "src/script_name"

mod = py_file.replace("/", ".")

files, opt = MAIN.process_options([f"{py_file}.py"])
opt.preserve_asts = True
opt.fine_grained_incremental = True
result = BUILD.build(files, options=opt)
tree = result.graph[mod].tree
names = tree.names.keys()

def is_node(value):
    return isinstance(value, Node) or isinstance(value, SymbolTableNode)

class MyVisitor(NodeVisitor):
    def generic_visit(self, node):
        print(f'entering {node.__class__.__name__}')
        if hasattr(node, "line"):
            print(f"\t{node.line}")
        if hasattr(node, "column"):
            print(f"\t{node.column}")
            if node.column == -1:
                return
        if hasattr(node, "name"):
            print(f"\t{node.name}")
        if not hasattr(node, "__mypyc_attrs__"):
            return
        node_fields = zip(
            node.__mypyc_attrs__,
            [
                getattr(node, attr)
                for attr in node.__mypyc_attrs__
            ]
        )
        for attr, value in node_fields:
            if isinstance(value, list):
                for v in value:
                    if not is_node(v):
                        continue
                    self.generic_visit(v)
            if is_node(value):
                #self.visit(value)
                self.generic_visit(value)

for name in names:
    symbol_table_node = tree.names[name]
    if symbol_table_node is None:
        continue
    visitor = MyVisitor()
    visitor.generic_visit(symbol_table_node.node)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions