diff options
| author | maxim-yurchuk <[email protected]> | 2024-10-09 12:29:46 +0300 | 
|---|---|---|
| committer | maxim-yurchuk <[email protected]> | 2024-10-09 13:14:22 +0300 | 
| commit | 9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80 (patch) | |
| tree | a8fb3181d5947c0d78cf402aa56e686130179049 /contrib/tools/python3/Lib/lib2to3/fixes/fix_import.py | |
| parent | a44b779cd359f06c3ebbef4ec98c6b38609d9d85 (diff) | |
publishFullContrib: true for ydb
<HIDDEN_URL>
commit_hash:c82a80ac4594723cebf2c7387dec9c60217f603e
Diffstat (limited to 'contrib/tools/python3/Lib/lib2to3/fixes/fix_import.py')
| -rw-r--r-- | contrib/tools/python3/Lib/lib2to3/fixes/fix_import.py | 99 | 
1 files changed, 99 insertions, 0 deletions
diff --git a/contrib/tools/python3/Lib/lib2to3/fixes/fix_import.py b/contrib/tools/python3/Lib/lib2to3/fixes/fix_import.py new file mode 100644 index 00000000000..734ca294699 --- /dev/null +++ b/contrib/tools/python3/Lib/lib2to3/fixes/fix_import.py @@ -0,0 +1,99 @@ +"""Fixer for import statements. +If spam is being imported from the local directory, this import: +    from spam import eggs +Becomes: +    from .spam import eggs + +And this import: +    import spam +Becomes: +    from . import spam +""" + +# Local imports +from .. import fixer_base +from os.path import dirname, join, exists, sep +from ..fixer_util import FromImport, syms, token + + +def traverse_imports(names): +    """ +    Walks over all the names imported in a dotted_as_names node. +    """ +    pending = [names] +    while pending: +        node = pending.pop() +        if node.type == token.NAME: +            yield node.value +        elif node.type == syms.dotted_name: +            yield "".join([ch.value for ch in node.children]) +        elif node.type == syms.dotted_as_name: +            pending.append(node.children[0]) +        elif node.type == syms.dotted_as_names: +            pending.extend(node.children[::-2]) +        else: +            raise AssertionError("unknown node type") + + +class FixImport(fixer_base.BaseFix): +    BM_compatible = True + +    PATTERN = """ +    import_from< 'from' imp=any 'import' ['('] any [')'] > +    | +    import_name< 'import' imp=any > +    """ + +    def start_tree(self, tree, name): +        super(FixImport, self).start_tree(tree, name) +        self.skip = "absolute_import" in tree.future_features + +    def transform(self, node, results): +        if self.skip: +            return +        imp = results['imp'] + +        if node.type == syms.import_from: +            # Some imps are top-level (eg: 'import ham') +            # some are first level (eg: 'import ham.eggs') +            # some are third level (eg: 'import ham.eggs as spam') +            # Hence, the loop +            while not hasattr(imp, 'value'): +                imp = imp.children[0] +            if self.probably_a_local_import(imp.value): +                imp.value = "." + imp.value +                imp.changed() +        else: +            have_local = False +            have_absolute = False +            for mod_name in traverse_imports(imp): +                if self.probably_a_local_import(mod_name): +                    have_local = True +                else: +                    have_absolute = True +            if have_absolute: +                if have_local: +                    # We won't handle both sibling and absolute imports in the +                    # same statement at the moment. +                    self.warning(node, "absolute and local imports together") +                return + +            new = FromImport(".", [imp]) +            new.prefix = node.prefix +            return new + +    def probably_a_local_import(self, imp_name): +        if imp_name.startswith("."): +            # Relative imports are certainly not local imports. +            return False +        imp_name = imp_name.split(".", 1)[0] +        base_path = dirname(self.filename) +        base_path = join(base_path, imp_name) +        # If there is no __init__.py next to the file its not in a package +        # so can't be a relative import. +        if not exists(join(dirname(base_path), "__init__.py")): +            return False +        for ext in [".py", sep, ".pyc", ".so", ".sl", ".pyd"]: +            if exists(base_path + ext): +                return True +        return False  | 
