Instagram / LibCST

A concrete syntax tree parser and serializer library for Python that preserves many aspects of Python's abstract syntax tree
https://libcst.readthedocs.io/
Other
1.57k stars 192 forks source link

AttributeError: module 'libcst' has no attribute '_InverseOf' #1115

Open isVoid opened 8 months ago

isVoid commented 8 months ago

I'm attempting to visit the name nodes inside the import nodes using MatcherDecoratableTransformer. For each of node I'm visiting, I'd like to check against a list of items to skip the visit. I'm trying to use the following code to achieve this:

source = "import a, b, c, d"

import libcst as cst
import libcst.matchers as m

class InvertTransformer(m.MatcherDecoratableTransformer):
    @m.call_if_inside(m.Import(names=[m.ZeroOrMore(m.ImportAlias(name=m.Name()))]))
    @m.leave(~m.Name("c"))
    def update(self, original: cst.Name, updated: cst.Name) -> cst.Name:
        print(f"{updated.value=}")
        return updated

trans = InvertTransformer()
tree = cst.parse_module(source)
converted = tree.visit(trans)

An exception is thrown:

Traceback (most recent call last):
  File "do_not_match.py", line 15, in <module>
    trans = InvertTransformer()
            ^^^^^^^^^^^^^^^^^^^
  File "libcst/matchers/_visitors.py", line 482, in __init__
    _check_types(
  File "libcst/matchers/_visitors.py", line 227, in _check_types
    possible_match_classes = _get_possible_match_classes(matcher)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "libcst/matchers/_visitors.py", line 87, in _get_possible_match_classes
    return [getattr(cst, matcher.__class__.__name__)]
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'libcst' has no attribute '_InverseOf'

Comparing to using if m.matches(m.Name("b")): return updated inside the function body, which is the more preferred way to achieve the goal?