source: orange/Orange/fixes/fix_orange_imports.py @ 9671:a7b056375472

Revision 9671:a7b056375472, 5.5 KB checked in by anze <anze.staric@…>, 2 years ago (diff)

Moved orange to Orange (part 2)

Line 
1""" This fixer changes old orange imports (imports of orange, orngSVM,
2orngClustering ...) to the corresponding package in the new hierarchy.
3It will also fix all occurrences of the module names in the script.
4
5For example it will replace this code::
6    import orange
7    learner = orange.SVMLearner(name='svm')
8
9with:
10    import Orange.core
11    learner = Orange.core.SVMLearner(name='svm')
12   
13.. note:: That this is possible only if the new package is a full
14    replacement for the old module (i.e. it exposes the same interface).
15    If this is not the case use the fix_changed_names fixer and list all
16    package content renames.
17   
18.. note:: This fixer runs last and should be used as a last resort. Use
19    fix_changed_names fixer for fine grain control of name mappings.
20 
21"""
22from lib2to3 import fixer_base
23from lib2to3 import fixer_util
24from lib2to3.fixer_util import Name, attr_chain
25
26from lib2to3.fixes import fix_imports
27
28import fix_changed_names
29
30NAMES_MAPPING = fix_changed_names.MAPPING
31   
32
33"""Fix incompatible imports and module references. Modified from the
34fix_imports fixer in lib2to3 by Collin Winter, Nick Edds. """
35
36# Local imports
37from lib2to3 import fixer_base
38from lib2to3.fixer_util import Name, attr_chain
39
40MAPPING = {"orange": "Orange.core",
41           "orngSVM": "Orange.classification.svm",
42           "orngSOM": "Orange.projection.som",
43           "orngBayes":"Orange.classification.bayes",
44           "orngNetwork":"Orange.network",
45           "orngMisc":"Orange.misc",
46           "orngEnsemble":"Orange.ensemble",
47           "orngCN2": "Orange.classification.rules",
48           "orngMDS": "Orange.projection.mds",
49           "orngStat": "Orange.evaluation.scoring",
50           "orngTree": "Orange.classification.tree",
51           "orngImpute": "Orange.feature.imputation",
52           "orngTest": "Orange.evaluation.testing",
53           "orngWrap": "Orange.optimization",
54           "orngClustering": "Orange.clustering",
55           "orngDisc": "Orange.feature.discretization",
56           "orngLookup": "Orange.classification.lookup",
57           "orngLinProj": "Orange.projection.linear",
58           "orngEnviron": "Orange.misc.environ",
59           }
60
61def alternates(members):
62    return "(" + "|".join(map(repr, members)) + ")"
63
64
65def build_pattern(mapping=MAPPING):
66    mod_list = ' | '.join(["module_name='%s'" % key for key in mapping])
67    bare_names = alternates(mapping.keys())
68
69    yield """name_import=import_name< 'import' ((%s) |
70               multiple_imports=dotted_as_names< any* (%s) any* >) >
71          """ % (mod_list, mod_list)
72    yield """import_from< 'from' (%s) 'import' ['(']
73              ( any | import_as_name< any 'as' any > |
74                import_as_names< any* >)  [')'] >
75          """ % mod_list
76    yield """import_name< 'import' (dotted_as_name< (%s) 'as' any > |
77               multiple_imports=dotted_as_names<
78                 any* dotted_as_name< (%s) 'as' any > any* >) >
79          """ % (mod_list, mod_list)
80
81    # Find usages of module members in code e.g. thread.foo(bar)
82    yield "power< bare_with_attr=(%s) trailer<'.' any > any* >" % bare_names
83
84
85class FixOrangeImports(fixer_base.BaseFix):
86    mapping = MAPPING
87
88    # We want to run this fixer late, so fix_import doesn't try to make stdlib
89    # renames into relative imports.
90    run_order = 6
91
92    def build_pattern(self):
93        return "|".join(build_pattern(self.mapping))
94
95    def compile_pattern(self):
96        # We override this, so MAPPING can be pragmatically altered and the
97        # changes will be reflected in PATTERN.
98        self.PATTERN = self.build_pattern()
99#        print self.PATTERN
100        super(FixOrangeImports, self).compile_pattern()
101#        print self.pattern
102
103    # Don't match the node if it's within another match.
104    def match(self, node):
105        match = super(FixOrangeImports, self).match
106        results = match(node)
107        if results:
108            # Module usage could be in the trailer of an attribute lookup, so we
109            # might have nested matches when "bare_with_attr" is present.
110            if "bare_with_attr" not in results and \
111                    any(match(obj) for obj in attr_chain(node, "parent")):
112                return False
113            return results
114        return False
115
116    def start_tree(self, tree, filename):
117        super(FixOrangeImports, self).start_tree(tree, filename)
118        self.replace = {}
119
120    def transform(self, node, results):
121        import_mod = results.get("module_name")
122        if import_mod:
123            mod_name = import_mod.value
124            new_name = unicode(self.mapping[mod_name])
125            import_mod.replace(Name(new_name, prefix=import_mod.prefix))
126            if "name_import" in results:
127                # If it's not a "from x import x, y" or "import x as y" import,
128                # marked its usage to be replaced.
129                self.replace[mod_name] = new_name
130            if "multiple_imports" in results:
131                # This is a nasty hack to fix multiple imports on a line (e.g.,
132                # "import StringIO, urlparse"). The problem is that I can't
133                # figure out an easy way to make a pattern recognize the keys of
134                # MAPPING randomly sprinkled in an import statement.
135                results = self.match(node)
136                if results:
137                    self.transform(node, results)
138        else:
139            # Replace usage of the module.
140            bare_name = results["bare_with_attr"][0]
141            new_name = self.replace.get(bare_name.value)
142            if new_name:
143                bare_name.replace(Name(new_name, prefix=bare_name.prefix))
Note: See TracBrowser for help on using the repository browser.