ยปCore Development>Code coverage>Lib/lib2to3/fixes/fix_import.py

Python code coverage for Lib/lib2to3/fixes/fix_import.py

#countcontent
1n/a"""Fixer for import statements.
2n/aIf spam is being imported from the local directory, this import:
3n/a from spam import eggs
4n/aBecomes:
5n/a from .spam import eggs
6n/a
7n/aAnd this import:
8n/a import spam
9n/aBecomes:
10n/a from . import spam
11n/a"""
12n/a
13n/a# Local imports
14n/afrom .. import fixer_base
15n/afrom os.path import dirname, join, exists, sep
16n/afrom ..fixer_util import FromImport, syms, token
17n/a
18n/a
19n/adef traverse_imports(names):
20n/a """
21n/a Walks over all the names imported in a dotted_as_names node.
22n/a """
23n/a pending = [names]
24n/a while pending:
25n/a node = pending.pop()
26n/a if node.type == token.NAME:
27n/a yield node.value
28n/a elif node.type == syms.dotted_name:
29n/a yield "".join([ch.value for ch in node.children])
30n/a elif node.type == syms.dotted_as_name:
31n/a pending.append(node.children[0])
32n/a elif node.type == syms.dotted_as_names:
33n/a pending.extend(node.children[::-2])
34n/a else:
35n/a raise AssertionError("unknown node type")
36n/a
37n/a
38n/aclass FixImport(fixer_base.BaseFix):
39n/a BM_compatible = True
40n/a
41n/a PATTERN = """
42n/a import_from< 'from' imp=any 'import' ['('] any [')'] >
43n/a |
44n/a import_name< 'import' imp=any >
45n/a """
46n/a
47n/a def start_tree(self, tree, name):
48n/a super(FixImport, self).start_tree(tree, name)
49n/a self.skip = "absolute_import" in tree.future_features
50n/a
51n/a def transform(self, node, results):
52n/a if self.skip:
53n/a return
54n/a imp = results['imp']
55n/a
56n/a if node.type == syms.import_from:
57n/a # Some imps are top-level (eg: 'import ham')
58n/a # some are first level (eg: 'import ham.eggs')
59n/a # some are third level (eg: 'import ham.eggs as spam')
60n/a # Hence, the loop
61n/a while not hasattr(imp, 'value'):
62n/a imp = imp.children[0]
63n/a if self.probably_a_local_import(imp.value):
64n/a imp.value = "." + imp.value
65n/a imp.changed()
66n/a else:
67n/a have_local = False
68n/a have_absolute = False
69n/a for mod_name in traverse_imports(imp):
70n/a if self.probably_a_local_import(mod_name):
71n/a have_local = True
72n/a else:
73n/a have_absolute = True
74n/a if have_absolute:
75n/a if have_local:
76n/a # We won't handle both sibling and absolute imports in the
77n/a # same statement at the moment.
78n/a self.warning(node, "absolute and local imports together")
79n/a return
80n/a
81n/a new = FromImport(".", [imp])
82n/a new.prefix = node.prefix
83n/a return new
84n/a
85n/a def probably_a_local_import(self, imp_name):
86n/a if imp_name.startswith("."):
87n/a # Relative imports are certainly not local imports.
88n/a return False
89n/a imp_name = imp_name.split(".", 1)[0]
90n/a base_path = dirname(self.filename)
91n/a base_path = join(base_path, imp_name)
92n/a # If there is no __init__.py next to the file its not in a package
93n/a # so can't be a relative import.
94n/a if not exists(join(dirname(base_path), "__init__.py")):
95n/a return False
96n/a for ext in [".py", sep, ".pyc", ".so", ".sl", ".pyd"]:
97n/a if exists(base_path + ext):
98n/a return True
99n/a return False