File: astutils.py

package info (click to toggle)
stsci.distutils 0.3.7-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 364 kB
  • sloc: python: 1,835; makefile: 132; ansic: 23
file content (106 lines) | stat: -rw-r--r-- 3,423 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""AST Visitors

Currently only uses one for collecting a list of import statements.
Unfortunately two versions of this have to be implemented: One for 2.6 and up
and a different version for 2.5.
"""


import os
import sys

from distutils import log

try:
    import ast # Python >= 2.6

    def walk(filename, visitor):
        """Generate an AST for the given filename and walk over it using
        the given visitor instance.
        """

        filename = os.path.abspath(filename)

        try:
            tree = ast.parse(open(filename, 'r').read())
        except SyntaxError:
            if sys.version_info[0] < 3:
                e = sys.exc_info()[1]
                log.warn('SyntaxError while parsing file %s: %s' %
                         (filename, str(e)))
                return
            # We're probably in Python 3 and looking at a file intended for
            # Python 2.  Otherwise there's an unintended SyntaxError in the
            # file, so there are bigger problems anyways
            try:
                import lib2to3.refactor

                tool = StringRefactoringTool(
                    lib2to3.refactor.get_fixers_from_package('lib2to3.fixes'))
                tool.refactor_file(filename, write=True)
                tree = ast.parse(tool.refactored[filename])
            except ImportError:
                # Without 2to3 we can't do much more.
                # TODO: Issue a warning?
                return

        visitor.visit(tree)


    class ImportVisitor(ast.NodeVisitor):
        def __init__(self):
            self.imports = set()
            self.importfroms = set()

        def visit_Import(self, node):
            for name in node.names:
                self.imports.add((name.name, name.asname))

        def visit_ImportFrom(self, node):
            for name in node.names:
                self.importfroms.add((node.module, name.name, name.asname))

except ImportError:
    import compiler

    def walk(filename, visitor):
        tree = compiler.parseFile(filename)
        compiler.walk(tree, visitor)

    class ImportVisitor(compiler.visitor.ASTVisitor):
        def __init__(self):
            self.imports = set()
            self.importfroms = set()

        def visitImport(self, node):
            for name in node.names:
                self.imports.add(name)

        def visitFrom(self, node):
            for name in node.names:
                self.importfroms.add((node.modname, name[0], name[1]))


if sys.version_info[0] >= 3:
    try:
        import lib2to3.refactor

        class StringRefactoringTool(lib2to3.refactor.RefactoringTool):
            """A RefactoringTool that saves refactored files as strings in the
            self.refactored dict rather than outputting to actual files.

            This is used in case we're running in Python 3 and need to refactor
            a file before parsing its syntax tree.
            """

            def __init__(self, fixer_names, options=None, explicit=None):
                super(StringRefactoringTool, self).__init__(fixer_names,
                                                            options,
                                                            explicit)
                self.refactored = {}

            def write_file(self, new_text, filename, old_text, encoding=None):
                self.refactored[filename] = new_text

    except ImportError:
        pass