def test_with_statement(self) -> None: m, scopes = get_scope_metadata_provider( """ import unittest.mock with unittest.mock.patch("something") as obj: obj.f1() unittest.mock """ ) import_ = ensure_type(m.body[0], cst.SimpleStatementLine).body[0] assignments = scopes[import_]["unittest"] self.assertEqual(len(assignments), 1) self.assertEqual(cast(Assignment, list(assignments)[0]).node, import_) with_ = ensure_type(m.body[1], cst.With) fn_call = with_.items[0].item self.assertEqual( scopes[fn_call].get_qualified_names_for(fn_call), { QualifiedName( name="unittest.mock.patch", source=QualifiedNameSource.IMPORT ) }, ) mock = ensure_type( ensure_type(m.body[2], cst.SimpleStatementLine).body[0], cst.Expr ).value self.assertEqual( scopes[fn_call].get_qualified_names_for(mock), {QualifiedName(name="unittest.mock", source=QualifiedNameSource.IMPORT)}, )
def test_multiple_assignments(self) -> None: m, scopes = get_scope_metadata_provider( """ if 1: from a import b as c elif 2: from d import e as c c() """ ) call = ensure_type( ensure_type(m.body[1], cst.SimpleStatementLine).body[0], cst.Expr ).value scope = scopes[call] self.assertIsInstance(scope, GlobalScope) self.assertEqual( scope.get_qualified_names_for(call), { QualifiedName(name="a.b", source=QualifiedNameSource.IMPORT), QualifiedName(name="d.e", source=QualifiedNameSource.IMPORT), }, ) self.assertEqual( scope.get_qualified_names_for("c"), { QualifiedName(name="a.b", source=QualifiedNameSource.IMPORT), QualifiedName(name="d.e", source=QualifiedNameSource.IMPORT), }, )
def visit_Module(self, node: cst.Module) -> bool: visitor = FullyQualifiedNameVisitor(self, self.module_name) node.visit(visitor) self.set_metadata( node, { QualifiedName(name=self.module_name, source=QualifiedNameSource.LOCAL) }, ) return True
def test_get_qualified_names_for_dotted_imports(self) -> None: m, scopes = get_scope_metadata_provider(""" import a.b.c a(a.b.d) """) call = ensure_type( ensure_type( ensure_type(m.body[1], cst.SimpleStatementLine).body[0], cst.Expr).value, cst.Call, ) module_scope = scopes[m] self.assertEqual( module_scope.get_qualified_names_for(call.func), {QualifiedName("a", QualifiedNameSource.IMPORT)}, ) self.assertEqual( module_scope.get_qualified_names_for(call.args[0].value), {QualifiedName("a.b.d", QualifiedNameSource.IMPORT)}, ) import_stmt = ensure_type( ensure_type(m.body[0], cst.SimpleStatementLine).body[0], cst.Import) a_b_c = ensure_type(import_stmt.names[0].name, cst.Attribute) a_b = ensure_type(a_b_c.value, cst.Attribute) a = a_b.value self.assertEqual( module_scope.get_qualified_names_for(a_b_c), {QualifiedName("a.b.c", QualifiedNameSource.IMPORT)}, ) self.assertEqual( module_scope.get_qualified_names_for(a_b), {QualifiedName("a.b", QualifiedNameSource.IMPORT)}, ) self.assertEqual( module_scope.get_qualified_names_for(a), {QualifiedName("a", QualifiedNameSource.IMPORT)}, )
def test_get_qualified_names_for_nested_cases(self) -> None: m, scopes = get_scope_metadata_provider( """ class A: def f1(self): def f2(): pass f2() def f3(self): class B(): ... B() def f4(): def f5(): class C: pass C() f5() """ ) cls_a = ensure_type(m.body[0], cst.ClassDef) func_f1 = ensure_type(cls_a.body.body[0], cst.FunctionDef) scope_of_cls_a = scopes[func_f1] self.assertIsInstance(scope_of_cls_a, ClassScope) self.assertEqual( scope_of_cls_a.get_qualified_names_for(func_f1), {QualifiedName("A.f1", QualifiedNameSource.LOCAL)}, ) func_f2_call = ensure_type( ensure_type(func_f1.body.body[1], cst.SimpleStatementLine).body[0], cst.Expr ).value scope_of_f1 = scopes[func_f2_call] self.assertIsInstance(scope_of_f1, FunctionScope) self.assertEqual( scope_of_f1.get_qualified_names_for(func_f2_call), {QualifiedName("A.f1.<locals>.f2", QualifiedNameSource.LOCAL)}, ) func_f3 = ensure_type(cls_a.body.body[1], cst.FunctionDef) call_b = ensure_type( ensure_type(func_f3.body.body[1], cst.SimpleStatementLine).body[0], cst.Expr ).value scope_of_f3 = scopes[call_b] self.assertIsInstance(scope_of_f3, FunctionScope) self.assertEqual( scope_of_f3.get_qualified_names_for(call_b), {QualifiedName("A.f3.<locals>.B", QualifiedNameSource.LOCAL)}, ) func_f4 = ensure_type(m.body[1], cst.FunctionDef) func_f5 = ensure_type(func_f4.body.body[0], cst.FunctionDef) scope_of_f4 = scopes[func_f5] self.assertIsInstance(scope_of_f4, FunctionScope) self.assertEqual( scope_of_f4.get_qualified_names_for(func_f5), {QualifiedName("f4.<locals>.f5", QualifiedNameSource.LOCAL)}, ) cls_c = func_f5.body.body[0] scope_of_f5 = scopes[cls_c] self.assertIsInstance(scope_of_f5, FunctionScope) self.assertEqual( scope_of_f5.get_qualified_names_for(cls_c), {QualifiedName("f4.<locals>.f5.<locals>.C", QualifiedNameSource.LOCAL)}, )
def test_get_qualified_names_for(self) -> None: m, scopes = get_scope_metadata_provider( """ from a.b import c class Cls: def f(self) -> "c": c() d = {} d['key'] = 0 def g(): pass g() """ ) cls = ensure_type(m.body[1], cst.ClassDef) f = ensure_type(cls.body.body[0], cst.FunctionDef) scope_of_module = scopes[m] self.assertEqual( scope_of_module.get_qualified_names_for( ensure_type(f.returns, cst.Annotation).annotation ), set(), "Get qualified name given a SimpleString type annotation is not supported", ) c_call = ensure_type( ensure_type(f.body.body[0], cst.SimpleStatementLine).body[0], cst.Expr ).value scope_of_f = scopes[c_call] self.assertIsInstance(scope_of_f, FunctionScope) self.assertEqual( scope_of_f.get_qualified_names_for(c_call), {QualifiedName("a.b.c", QualifiedNameSource.IMPORT)}, ) self.assertEqual( scope_of_f.get_qualified_names_for(c_call), {QualifiedName("a.b.c", QualifiedNameSource.IMPORT)}, ) g_call = ensure_type( ensure_type(m.body[3], cst.SimpleStatementLine).body[0], cst.Expr ).value self.assertIsInstance(scope_of_module, GlobalScope) self.assertEqual( scope_of_module.get_qualified_names_for(g_call), {QualifiedName("g", QualifiedNameSource.LOCAL)}, ) d_name = ( ensure_type( ensure_type(f.body.body[1], cst.SimpleStatementLine).body[0], cst.Assign ) .targets[0] .target ) self.assertEqual( scope_of_f.get_qualified_names_for(d_name), {QualifiedName("Cls.f.<locals>.d", QualifiedNameSource.LOCAL)}, ) d_subscript = ( ensure_type( ensure_type(f.body.body[2], cst.SimpleStatementLine).body[0], cst.Assign ) .targets[0] .target ) self.assertEqual( scope_of_f.get_qualified_names_for(d_subscript), {QualifiedName("Cls.f.<locals>.d", QualifiedNameSource.LOCAL)}, ) for builtin in ["map", "int", "dict"]: self.assertEqual( scope_of_f.get_qualified_names_for(cst.Name(value=builtin)), {QualifiedName(f"builtins.{builtin}", QualifiedNameSource.BUILTIN)}, f"Test builtin: {builtin}.", ) self.assertEqual( scope_of_module.get_qualified_names_for(cst.Name(value="d")), set(), "Test variable d in global scope.", )