def test_simple_assign(self) -> None: wrapper = MetadataWrapper(parse_module("a = b")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.STORE, "b": ExpressionContext.LOAD, }, ))
def test_with_as(self) -> None: wrapper = MetadataWrapper(parse_module("with a() as b:\n pass")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.LOAD, "b": ExpressionContext.STORE, }, ))
def test_except_as(self) -> None: wrapper = MetadataWrapper( parse_module("try: ...\nexcept Exception as ex:\n pass")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "Exception": ExpressionContext.LOAD, "ex": ExpressionContext.STORE, }, ))
def test_del_with_tuple(self) -> None: wrapper = MetadataWrapper(parse_module("del a, b")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.DEL, "b": ExpressionContext.DEL, }, tuple_to_context={("a", "b"): ExpressionContext.DEL}, ))
def test_starred_element_with_assign(self) -> None: wrapper = MetadataWrapper(parse_module("*a = b")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.LOAD, "b": ExpressionContext.LOAD, }, starred_element_to_context={"a": ExpressionContext.STORE}, ))
def test_del_with_subscript(self) -> None: wrapper = MetadataWrapper(parse_module("del a[b]")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.LOAD, "b": ExpressionContext.LOAD, }, subscript_to_context={"a": ExpressionContext.DEL}, ))
def test_accesses(self) -> None: m, scopes = get_scope_metadata_provider(""" foo = 'toplevel' fn1(foo) fn2(foo) def fn_def(): foo = 'shadow' fn3(foo) """) scope_of_module = scopes[m] self.assertIsInstance(scope_of_module, GlobalScope) global_foo_assignments = scope_of_module["foo"] self.assertEqual(len(global_foo_assignments), 1) foo_assignment = global_foo_assignments[0] self.assertEqual(len(foo_assignment.accesses), 2) fn1_call_arg = ensure_type( ensure_type( ensure_type(m.body[1], cst.SimpleStatementLine).body[0], cst.Expr).value, cst.Call, ).args[0] self.assertEqual(foo_assignment.accesses[0].node, fn1_call_arg.value) fn2_call_arg = ensure_type( ensure_type( ensure_type(m.body[2], cst.SimpleStatementLine).body[0], cst.Expr).value, cst.Call, ).args[0] self.assertEqual(foo_assignment.accesses[1].node, fn2_call_arg.value) func_body = ensure_type(m.body[3], cst.FunctionDef).body func_foo_statement = func_body.body[0] scope_of_func_statement = scopes[func_foo_statement] self.assertIsInstance(scope_of_func_statement, FunctionScope) func_foo_assignments = scope_of_func_statement["foo"] self.assertEqual(len(func_foo_assignments), 1) foo_assignment = func_foo_assignments[0] self.assertEqual(len(foo_assignment.accesses), 1) fn3_call_arg = ensure_type( ensure_type( ensure_type(func_body.body[1], cst.SimpleStatementLine).body[0], cst.Expr, ).value, cst.Call, ).args[0] self.assertEqual(foo_assignment.accesses[0].node, fn3_call_arg.value) wrapper = MetadataWrapper(cst.parse_module("from a import b\n")) wrapper.visit(DependentVisitor()) wrapper = MetadataWrapper( cst.parse_module("def a():\n from b import c\n\n")) wrapper.visit(DependentVisitor())
def test_list_with_assing(self) -> None: wrapper = MetadataWrapper(parse_module("[a] = [b]")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.STORE, "b": ExpressionContext.LOAD, }, list_to_context={ ("a", ): ExpressionContext.STORE, ("b", ): ExpressionContext.LOAD, }, ))
def test_assign_with_subscript(self) -> None: wrapper = MetadataWrapper(parse_module("a[b] = c[d]")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.LOAD, "b": ExpressionContext.LOAD, "c": ExpressionContext.LOAD, "d": ExpressionContext.LOAD, }, subscript_to_context={ "a": ExpressionContext.STORE, "c": ExpressionContext.LOAD, }, ))
def test_assign_to_attribute(self) -> None: wrapper = MetadataWrapper(parse_module("a.b = c.d")) wrapper.visit( DependentVisitor( test=self, name_to_context={ "a": ExpressionContext.LOAD, "b": ExpressionContext.STORE, "c": ExpressionContext.LOAD, "d": ExpressionContext.LOAD, }, attribute_to_context={ "b": ExpressionContext.STORE, "d": ExpressionContext.LOAD, }, ))
def test_visitor_provider(self) -> None: """ Sets 2 metadata entries for every node: SimpleProvider -> 1 DependentProvider - > 2 """ test = self class DependentVisitor(CSTTransformer): METADATA_DEPENDENCIES = (SyntacticPositionProvider,) def visit_Pass(self, node: cst.Pass) -> None: range = self.get_metadata(SyntacticPositionProvider, node) test.assertEqual(range, CodeRange((1, 0), (1, 4))) wrapper = MetadataWrapper(parse_module("pass")) wrapper.visit(DependentVisitor())
def visit(self: _ModuleSelfT, visitor: CSTVisitorT, use_compatible: bool = True) -> _ModuleSelfT: """ Returns the result of running a visitor over this module. :class:`Module` overrides the default visitor entry point to resolve metadata dependencies declared by 'visitor'. """ # TODO: remove compatibility hack if use_compatible: from libcst.metadata.wrapper import MetadataWrapper wrapper = MetadataWrapper(self) result = wrapper.visit(visitor) else: result = super(Module, self).visit(visitor) if isinstance(result, RemovalSentinel): return self.with_changes(body=(), header=(), footer=()) else: # is a Module return cast(_ModuleSelfT, result)
def test_simple_load(self) -> None: wrapper = MetadataWrapper(parse_module("a")) wrapper.visit( DependentVisitor(test=self, name_to_context={"a": ExpressionContext.LOAD}))
def test_invalid_type_for_context(self) -> None: wrapper = MetadataWrapper(parse_module("a()")) wrapper.visit( DependentVisitor(test=self, name_to_context={"a": ExpressionContext.LOAD}))