Example #1
0
def get_unused_import_aliases(tree, sc=None):
    """Get the import aliases that aren't used.

  Arguments:
    tree: (ast.AST) An ast to find imports in.
    sc: A scope.Scope representing tree (generated from scratch if not
    provided).

  Returns:
    A list of ast.alias representing imported aliases that aren't referenced in
    the given tree.
  """
    if sc is None:
        sc = scope.analyze(tree)
    unused_aliases = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.alias):
            str_name = node.asname if node.asname is not None else node.name
            if str_name in sc.names:
                name = sc.names[str_name]
                if not name.reads:
                    unused_aliases.add(node)
            else:
                # This happens because of https://github.com/google/pasta/issues/32
                logging.warning(
                    'Imported name %s not found in scope (perhaps it\'s '
                    'imported dynamically)', str_name)

    return unused_aliases
Example #2
0
 def test_rename_reads_noop(self):
     src = 'aaa.bbb.ccc()'
     t = ast.parse(src)
     sc = scope.analyze(t)
     rename._rename_reads(sc, t, 'aaa.bbb.ccc.ddd', 'xxx.yyy')
     rename._rename_reads(sc, t, 'bbb.aaa', 'xxx.yyy')
     self.checkAstsEqual(t, ast.parse(src))
Example #3
0
  def test_split_nested_imports(self):
    test_cases = (
        'def foo():\n  {import_stmt}\n',
        'class Foo(object):\n  {import_stmt}\n',
        'if foo:\n  {import_stmt}\nelse:\n  pass\n',
        'if foo:\n  pass\nelse:\n  {import_stmt}\n',
        'if foo:\n  pass\nelif bar:\n  {import_stmt}\n',
        'try:\n  {import_stmt}\nexcept:\n  pass\n',
        'try:\n  pass\nexcept:\n  {import_stmt}\n',
        'try:\n  pass\nfinally:\n  {import_stmt}\n',
        'for i in foo:\n  {import_stmt}\n',
        'for i in foo:\n  pass\nelse:\n  {import_stmt}\n',
        'while foo:\n  {import_stmt}\n',
    )

    for template in test_cases:
      try:
        src = template.format(import_stmt='import aaa, bbb, ccc')
        t = ast.parse(src)
        sc = scope.analyze(t)
        import_node = ast_utils.find_nodes_by_type(t, ast.Import)[0]
        import_utils.split_import(sc, import_node, import_node.names[1])

        split_import_nodes = ast_utils.find_nodes_by_type(t, ast.Import)
        self.assertEqual(1, len(t.body))
        self.assertEqual(2, len(split_import_nodes))
        self.assertEqual([alias.name for alias in split_import_nodes[0].names],
                         ['aaa', 'ccc'])
        self.assertEqual([alias.name for alias in split_import_nodes[1].names],
                         ['bbb'])
      except:
        self.fail('Failed while executing case:\n%s\nCaused by:\n%s' % 
                  (src, traceback.format_exc()))
Example #4
0
    def test_if_nested_imports(self):
        source = textwrap.dedent("""\
        if a:
          import aaa
        elif b:
          import bbb
        else:
          import ccc
        """)
        tree = ast.parse(source)
        nodes = tree.body

        node_aaa, node_bbb, node_ccc = ast_utils.find_nodes_by_type(
            tree, ast.alias)

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'bbb', 'ccc', 'a', 'b'})
        self.assertItemsEqual(s.external_references.keys(),
                              {'aaa', 'bbb', 'ccc'})

        self.assertEqual(s.names['aaa'].definition, node_aaa)
        self.assertEqual(s.names['bbb'].definition, node_bbb)
        self.assertEqual(s.names['ccc'].definition, node_ccc)

        self.assertIsNone(s.names['a'].definition)
        self.assertIsNone(s.names['b'].definition)

        for ref in {'aaa', 'bbb', 'ccc'}:
            self.assertEqual(s.names[ref].reads, [],
                             'Expected no reads for %s' % ref)
Example #5
0
    def test_import_attribute_references(self):
        source = textwrap.dedent("""\
        import aaa.bbb.ccc, ddd.eee
        aaa.x()
        aaa.bbb.y()
        aaa.bbb.ccc.z()
        """)
        tree = ast.parse(source)
        nodes = tree.body

        call1 = nodes[1].value.func.value
        call2 = nodes[2].value.func.value
        call3 = nodes[3].value.func.value

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'ddd'})
        self.assertItemsEqual(
            s.external_references.keys(),
            {'aaa', 'aaa.bbb', 'aaa.bbb.ccc', 'ddd', 'ddd.eee'})
        self.assertItemsEqual(s.names['aaa'].reads,
                              [call1, call2.value, call3.value.value])
        self.assertItemsEqual(s.names['aaa'].attrs['bbb'].reads,
                              [call2, call3.value])
        self.assertItemsEqual(s.names['aaa'].attrs['bbb'].attrs['ccc'].reads,
                              [call3])
Example #6
0
 def test_rename_reads_name(self):
     src = 'aaa.bbb()'
     t = pasta.ast_parse(src, py_ver)
     sc = scope.analyze(t, py_ver)
     self.assertTrue(rename._rename_reads(sc, t, 'aaa', 'xxx', py_ver))
     self.checkAstsEqual(t, pasta.ast_parse('xxx.bbb()', py_ver),
                         py_ver)
Example #7
0
    def test_top_level_imports(self):
        self.maxDiff = None
        source = textwrap.dedent("""\
        import aaa
        import bbb, ccc.ddd
        import aaa.bbb.ccc
        from eee import fff
        from ggg.hhh import iii, jjj
        """)
        tree = ast.parse(source)
        nodes = tree.body

        node_1_aaa = nodes[0].names[0]
        node_2_bbb = nodes[1].names[0]
        node_2_ccc = nodes[1].names[1]
        node_2_ccc_ddd = nodes[1].names[1]
        node_3_aaa_bbb_ccc = nodes[2].names[0]
        node_4_fff = nodes[3].names[0]
        node_5_iii = nodes[4].names[0]
        node_5_jjj = nodes[4].names[1]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(),
                              {'aaa', 'bbb', 'ccc', 'fff', 'iii', 'jjj'})
        self.assertItemsEqual(
            s.external_references.keys(), {
                'aaa', 'bbb', 'ccc', 'ccc.ddd', 'aaa.bbb', 'aaa.bbb.ccc',
                'eee', 'eee.fff', 'ggg', 'ggg.hhh', 'ggg.hhh.iii',
                'ggg.hhh.jjj'
            })
        self.assertItemsEqual(s.external_references['aaa'],
                              [s.names['aaa'].definition] +
                              s.names['aaa'].reads)
        self.assertItemsEqual(s.external_references['bbb'],
                              [s.names['bbb'].definition])
        self.assertItemsEqual(s.external_references['ccc.ddd'],
                              [s.names['ccc'].attrs['ddd'].definition])
        self.assertItemsEqual(
            s.external_references['aaa.bbb.ccc'],
            [s.names['aaa'].attrs['bbb'].attrs['ccc'].definition])
        self.assertItemsEqual(s.external_references['eee.fff'],
                              [s.names['fff'].definition])
        self.assertItemsEqual(s.external_references['ggg.hhh.iii'],
                              [s.names['iii'].definition])
        self.assertItemsEqual(s.external_references['ggg.hhh.jjj'],
                              [s.names['jjj'].definition])

        self.assertEqual(s.names['aaa'].definition, node_1_aaa)
        self.assertEqual(s.names['bbb'].definition, node_2_bbb)
        self.assertEqual(s.names['ccc'].definition, node_2_ccc)
        self.assertEqual(s.names['fff'].definition, node_4_fff)
        self.assertEqual(s.names['iii'].definition, node_5_iii)
        self.assertEqual(s.names['jjj'].definition, node_5_jjj)

        self.assertItemsEqual(s.names['aaa'].reads, [node_3_aaa_bbb_ccc])
        for ref in {'bbb', 'ccc', 'fff', 'iii', 'jjj'}:
            self.assertEqual(s.names[ref].reads, [],
                             'Expected no reads for %s' % ref)
Example #8
0
        def test_remove_full_importfrom(self):
            src = 'from m import a'
            tree = pasta.ast_parse(src, py_ver)
            sc = scope.analyze(tree, py_ver)

            a_node = tree.body[0].names[0]

            import_utils.remove_import_alias_node(sc, a_node, py_ver=py_ver)

            self.assertEqual(len(tree.body), 0)
  def test_remove_full_importfrom(self):
    src = "from m import a"
    tree = ast.parse(src)
    sc = scope.analyze(tree)

    a_node = tree.body[0].names[0]

    import_utils.remove_import_alias_node(sc, a_node)

    self.assertEqual(len(tree.body), 0)
  def test_split_imports_with_alias(self):
    src = 'import aaa as a, bbb as b, ccc as c\n'
    t = ast.parse(src)
    import_node = t.body[0]
    sc = scope.analyze(t)
    import_utils.split_import(sc, import_node, import_node.names[1])

    self.assertEqual(2, len(t.body))
    self.assertEqual([alias.name for alias in t.body[0].names], ['aaa', 'ccc'])
    self.assertEqual([alias.name for alias in t.body[1].names], ['bbb'])
    self.assertEqual(t.body[1].names[0].asname, 'b')
  def test_split_normal_import(self):
    src = 'import aaa, bbb, ccc\n'
    t = ast.parse(src)
    import_node = t.body[0]
    sc = scope.analyze(t)
    import_utils.split_import(sc, import_node, import_node.names[1])

    self.assertEqual(2, len(t.body))
    self.assertEqual(ast.Import, type(t.body[1]))
    self.assertEqual([alias.name for alias in t.body[0].names], ['aaa', 'ccc'])
    self.assertEqual([alias.name for alias in t.body[1].names], ['bbb'])
  def test_split_from_import(self):
    src = 'from aaa import bbb, ccc, ddd\n'
    t = ast.parse(src)
    import_node = t.body[0]
    sc = scope.analyze(t)
    import_utils.split_import(sc, import_node, import_node.names[1])

    self.assertEqual(2, len(t.body))
    self.assertEqual(ast.ImportFrom, type(t.body[1]))
    self.assertEqual(t.body[0].module, 'aaa')
    self.assertEqual(t.body[1].module, 'aaa')
    self.assertEqual([alias.name for alias in t.body[0].names], ['bbb', 'ddd'])
  def test_remove_just_alias_import_from(self):
    src = "from m import a, b"
    tree = ast.parse(src)
    sc = scope.analyze(tree)

    unused_b_node = tree.body[0].names[1]

    import_utils.remove_import_alias_node(sc, unused_b_node)

    self.assertEqual(len(tree.body), 1)
    self.assertEqual(type(tree.body[0]), ast.ImportFrom)
    self.assertEqual(len(tree.body[0].names), 1)
    self.assertEqual(tree.body[0].names[0].name, 'a')
Example #14
0
    def test_classdef_nested_imports(self):
        source = textwrap.dedent("""\
        class Foo():
          import aaa
        """)
        tree = ast.parse(source)
        nodes = tree.body

        node_aaa = nodes[0].body[0].names[0]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'Foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
  def test_split_imports_multiple(self):
    src = 'import aaa, bbb, ccc\n'
    t = ast.parse(src)
    import_node = t.body[0]
    alias_bbb = import_node.names[1]
    alias_ccc = import_node.names[2]
    sc = scope.analyze(t)
    import_utils.split_import(sc, import_node, alias_bbb)
    import_utils.split_import(sc, import_node, alias_ccc)

    self.assertEqual(3, len(t.body))
    self.assertEqual([alias.name for alias in t.body[0].names], ['aaa'])
    self.assertEqual([alias.name for alias in t.body[1].names], ['ccc'])
    self.assertEqual([alias.name for alias in t.body[2].names], ['bbb'])
Example #16
0
    def process(self, ast_tree):
        """
        Start to analyze the code.

        Args:
            ast_tree (AST): The root node of the source code.
        """
        self.__init__()
        self._root_scope = scope.analyze(ast_tree)
        self._pre_process()
        self.visit(ast_tree)
        if not self._network_classes:
            msg = "model definition not be found."
            raise ScriptNotSupport(msg)
Example #17
0
    def test_functiondef_nested_imports(self):
        source = textwrap.dedent("""\
        def foo(bar):
          import aaa
        """)
        tree = ast.parse(source)
        nodes = tree.body

        node_aaa = ast_utils.find_nodes_by_type(tree, ast.alias)[0]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
Example #18
0
 def test_rename_reads_type_annotation(self):
     src = textwrap.dedent("""\
     def foo(bar: 'aaa.bbb.ccc.Bar'):
       pass
     """)
     t = ast.parse(src)
     sc = scope.analyze(t)
     rename._rename_reads(sc, t, 'aaa.bbb', 'xxx.yyy')
     self.checkAstsEqual(
         t,
         ast.parse(
             textwrap.dedent("""\
     def foo(bar: 'xxx.yyy.ccc.Bar'):
       pass
     """)))
Example #19
0
        def test_remove_just_alias_import_from(self):
            src = 'from m import a, b'
            tree = pasta.ast_parse(src, py_ver)
            sc = scope.analyze(tree, py_ver)

            unused_b_node = tree.body[0].names[1]

            import_utils.remove_import_alias_node(sc,
                                                  unused_b_node,
                                                  py_ver=py_ver)

            self.assertEqual(len(tree.body), 1)
            self.assertEqual(type(tree.body[0]), pasta.ast(py_ver).ImportFrom)
            self.assertEqual(len(tree.body[0].names), 1)
            self.assertEqual(tree.body[0].names[0].name, 'a')
Example #20
0
    def test_forward_type_reference(self):
        source = textwrap.dedent("""\
        class A():
          def foo(self, a: 'A'): pass
        """)
        tree = ast.parse(source)
        nodes = tree.body

        classdef = nodes[0]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'A'})
        self.assertItemsEqual(s.names['A'].reads,
                              [classdef.body[0].args.args[1].annotation])
Example #21
0
    def test_import_in_return_type(self):
        source = textwrap.dedent("""\
        import aaa
        def foo() -> aaa.Foo:
          pass
        """)
        tree = ast.parse(source)
        nodes = tree.body

        func = nodes[1]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads, [func.returns.value])
Example #22
0
    def test_import_masked_by_function_arg(self):
        source = textwrap.dedent("""\
        import aaa
        def foo(aaa=aaa):
          return aaa
        """)
        tree = ast.parse(source)
        nodes = tree.body

        argval = nodes[1].args.defaults[0]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads, [argval])
Example #23
0
    def test_import_in_argument_type(self):
        source = textwrap.dedent("""\
        import aaa
        def foo(bar: aaa.Bar):
          pass
        """)
        tree = ast.parse(source)
        nodes = tree.body

        func = nodes[1]

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads,
                              [func.args.args[0].annotation.value])
Example #24
0
    def test_import_in_decortator(self):
        source = textwrap.dedent("""\
        import aaa
        @aaa.wrapper
        def foo(aaa=1):
          pass
        """)
        tree = ast.parse(source)
        nodes = tree.body

        decorator = nodes[1].decorator_list[0].value

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads, [decorator])
Example #25
0
    def test_vararg_kwarg_references_in_function_body(self):
        source = textwrap.dedent("""\
        def aaa(bbb, *ccc, **ddd):
          ccc
          ddd
        eee(ccc, ddd)
        """)
        tree = ast.parse(source)
        funcdef, call = tree.body
        ccc_expr, ddd_expr = funcdef.body

        sc = scope.analyze(tree)

        func_scope = sc.lookup_scope(funcdef)
        self.assertIn('ccc', func_scope.names)
        self.assertItemsEqual(func_scope.names['ccc'].reads, [ccc_expr.value])
        self.assertIn('ddd', func_scope.names)
        self.assertItemsEqual(func_scope.names['ddd'].reads, [ddd_expr.value])
Example #26
0
    def test_import_masked_by_assign(self):
        source = textwrap.dedent("""\
        import aaa
        def foo():
          aaa = 123
          return aaa
        aaa
        """)
        tree = ast.parse(source)
        nodes = tree.body

        node_aaa = nodes[2].value

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads, [node_aaa])
Example #27
0
    def test_import_reads_in_functiondef(self):
        source = textwrap.dedent("""\
        import aaa
        @aaa.x
        def foo(bar):
          return aaa
        """)
        tree = ast.parse(source)
        nodes = tree.body

        return_value = nodes[1].body[0].value
        decorator = nodes[1].decorator_list[0].value

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads, [decorator, return_value])
Example #28
0
    def test_import_reads_in_classdef(self):
        source = textwrap.dedent("""\
        import aaa
        @aaa.x
        class Foo(aaa.Bar):
          pass
        """)
        tree = ast.parse(source)
        nodes = tree.body

        node_aaa = nodes[0].names[0]
        decorator = nodes[1].decorator_list[0].value
        base = nodes[1].bases[0].value

        s = scope.analyze(tree)

        self.assertItemsEqual(s.names.keys(), {'aaa', 'Foo'})
        self.assertItemsEqual(s.external_references.keys(), {'aaa'})
        self.assertItemsEqual(s.names['aaa'].reads, [decorator, base])
Example #29
0
    def test_multilevel_import_reads(self):
      source = textwrap.dedent("""\
          import aaa.bbb.ccc
          aaa.bbb.ccc.foo()
          """)
      tree = pasta.ast_parse(source, py_ver)
      nodes = tree.body

      node_ref = nodes[1].value.func.value

      s = scope.analyze(tree, py_ver)

      self.assertItemsEqual(s.names.keys(), {'aaa'})
      self.assertItemsEqual(s.external_references.keys(),
                            {'aaa', 'aaa.bbb', 'aaa.bbb.ccc'})
      self.assertItemsEqual(s.names['aaa'].reads, [node_ref.value.value])
      self.assertItemsEqual(s.names['aaa'].attrs['bbb'].reads, [node_ref.value])
      self.assertItemsEqual(s.names['aaa'].attrs['bbb'].attrs['ccc'].reads,
                            [node_ref])
Example #30
0
    def test_import_in_argument_type_string(self):
      source = textwrap.dedent("""\
          import aaa
          def foo(bar: 'aaa.Bar'):
            pass
          """)
      tree = pasta.ast_parse(source, py_ver)
      nodes = tree.body

      func = nodes[1]

      s = scope.analyze(tree, py_ver)

      self.assertItemsEqual(s.names.keys(), {'aaa', 'foo'})
      self.assertItemsEqual(s.external_references.keys(), {'aaa'})
      self.assertItemsEqual(s.names['aaa'].reads,
                            [func.args.args[0].annotation])
      self.assertItemsEqual(s.names['aaa'].lookup_name('Bar').reads,
                            [func.args.args[0].annotation])