[Python-modules-commits] [importmagic] 01/02: New upstream version 0.1.7

Diane Trout diane at moszumanska.debian.org
Fri Aug 18 17:41:23 UTC 2017


This is an automated email from the git hooks/post-receive script.

diane pushed a commit to branch debian/master
in repository importmagic.

commit 71739ff479d964b41c776c1f49304b64dafe818d
Author: Diane Trout <diane at ghic.org>
Date:   Tue Aug 15 20:52:57 2017 -0700

    New upstream version 0.1.7
---
 CHANGES                                   |   18 +
 MANIFEST.in                               |    5 +
 PKG-INFO                                  |   11 +
 README.md                                 |   68 +
 importmagic.egg-info/PKG-INFO             |   11 +
 importmagic.egg-info/SOURCES.txt          |   22 +
 importmagic.egg-info/dependency_links.txt |    1 +
 importmagic.egg-info/requires.txt         |    1 +
 importmagic.egg-info/top_level.txt        |    1 +
 importmagic/__init__.py                   |   11 +
 importmagic/conftest.py                   |   12 +
 importmagic/importer.py                   |  342 +++
 importmagic/importer_test.py              |  430 ++++
 importmagic/index.py                      |  424 ++++
 importmagic/index_test.py                 |  116 +
 importmagic/six.py                        |  637 +++++
 importmagic/symbols.py                    |  400 +++
 importmagic/symbols_test.py               |  274 +++
 importmagic/test_index.json               |    1 +
 importmagic/util.py                       |   56 +
 pytest.ini                                |    3 +
 runtests.py                               | 3788 +++++++++++++++++++++++++++++
 setup.cfg                                 |    5 +
 setup.py                                  |   43 +
 24 files changed, 6680 insertions(+)

diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..a16ea9e
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,18 @@
+Changelog for importmagic
+-------------------------
+
+* 0.1.3 (11-02-2015)
+
+  - Do not choke on modules with non-UTF8 encoding on Python 3 (#13).
+
+* 0.1.2 (26-01-2015)
+
+  - Do not write to stdout, use logging, when parsing files fails.
+
+* 0.1.1 (24-01-2015)
+
+  - Do not treat multiple name references (`a == b`) as attributes (`a.b`).
+
+* 0.1.0 (20-01-2015)
+
+  - Initial release.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..9d9a936
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,5 @@
+include CHANGES
+include README.md
+include runtests.py
+include pytest.ini
+include importmagic/test_index.json
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..183a235
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,11 @@
+Metadata-Version: 1.1
+Name: importmagic
+Version: 0.1.7
+Summary: Python Import Magic - automagically add, remove and manage imports
+Home-page: http://github.com/alecthomas/importmagic
+Author: Alec Thomas
+Author-email: alec at swapoff.org
+License: BSD
+Download-URL: http://pypi.python.org/pypi/importmagic
+Description: See http://github.com/alecthomas/importmagic for details.
+Platform: any
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..66549ad
--- /dev/null
+++ b/README.md
@@ -0,0 +1,68 @@
+# Import Magic [![image](https://secure.travis-ci.org/alecthomas/importmagic.png?branch=master)](https://travis-ci.org/alecthomas/importmagic)
+
+The goal of this package is to be able to automatically manage imports in Python. To that end it can:
+
+- Build an index of all known symbols in all packages.
+- Find unresolved references in source, and resolve them against the index, effectively automating imports.
+- Automatically arrange imports according to PEP8.
+
+It was originally written for the Sublime Text 2 [Python Import Magic](https://github.com/alecthomas/SublimePythonImportMagic) plugin.
+
+## Example of use in Sublime Text 2 plugin
+
+![Example of Import Magic at work](importmagic.gif)
+
+
+## Using the library
+
+Build an index:
+
+```python
+index = importmagic.SymbolIndex()
+index.build_index(sys.path)
+with open('index.json') as fd:
+    index.serialize(fd)
+```
+
+Load an existing index:
+
+```python
+with open('index.json') as fd:
+    index = SymbolIndex.deserialize(fd)
+```
+
+Find unresolved and unreferenced symbols:
+
+```python
+scope = importmagic.Scope.from_source(python_source)
+unresolved, unreferenced = scope.find_unresolved_and_unreferenced_symbols()
+```
+
+Print new import block:
+
+```python
+start_line, end_line, import_block = importmagic.get_update(python_source, index, unresolved, unreferenced)
+```
+
+Update source code with new import blocks:
+
+```
+python_source = importmagic.update_imports(python_source, index, unresolved, unreferenced)
+```
+
+For more fine-grained control over what symbols are imported, the index can be queried directly:
+
+```python
+imports = importmagic.Imports(index, python_source)
+imports.remove(unreferenced)
+
+for symbol in unresolved:
+    for score, module, variable in index.symbol_scores(symbol):
+        if variable is None:
+            imports.add_import(module)
+        else:
+            imports.add_import_from(module, variable)
+        break
+
+python_source = imports.update_source()
+```
diff --git a/importmagic.egg-info/PKG-INFO b/importmagic.egg-info/PKG-INFO
new file mode 100644
index 0000000..183a235
--- /dev/null
+++ b/importmagic.egg-info/PKG-INFO
@@ -0,0 +1,11 @@
+Metadata-Version: 1.1
+Name: importmagic
+Version: 0.1.7
+Summary: Python Import Magic - automagically add, remove and manage imports
+Home-page: http://github.com/alecthomas/importmagic
+Author: Alec Thomas
+Author-email: alec at swapoff.org
+License: BSD
+Download-URL: http://pypi.python.org/pypi/importmagic
+Description: See http://github.com/alecthomas/importmagic for details.
+Platform: any
diff --git a/importmagic.egg-info/SOURCES.txt b/importmagic.egg-info/SOURCES.txt
new file mode 100644
index 0000000..8466ef2
--- /dev/null
+++ b/importmagic.egg-info/SOURCES.txt
@@ -0,0 +1,22 @@
+CHANGES
+MANIFEST.in
+README.md
+pytest.ini
+runtests.py
+setup.py
+importmagic/__init__.py
+importmagic/conftest.py
+importmagic/importer.py
+importmagic/importer_test.py
+importmagic/index.py
+importmagic/index_test.py
+importmagic/six.py
+importmagic/symbols.py
+importmagic/symbols_test.py
+importmagic/test_index.json
+importmagic/util.py
+importmagic.egg-info/PKG-INFO
+importmagic.egg-info/SOURCES.txt
+importmagic.egg-info/dependency_links.txt
+importmagic.egg-info/requires.txt
+importmagic.egg-info/top_level.txt
\ No newline at end of file
diff --git a/importmagic.egg-info/dependency_links.txt b/importmagic.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/importmagic.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/importmagic.egg-info/requires.txt b/importmagic.egg-info/requires.txt
new file mode 100644
index 0000000..fc94a18
--- /dev/null
+++ b/importmagic.egg-info/requires.txt
@@ -0,0 +1 @@
+setuptools >= 0.6b1
diff --git a/importmagic.egg-info/top_level.txt b/importmagic.egg-info/top_level.txt
new file mode 100644
index 0000000..0feb903
--- /dev/null
+++ b/importmagic.egg-info/top_level.txt
@@ -0,0 +1 @@
+importmagic
diff --git a/importmagic/__init__.py b/importmagic/__init__.py
new file mode 100644
index 0000000..bce354a
--- /dev/null
+++ b/importmagic/__init__.py
@@ -0,0 +1,11 @@
+"""Python Import Magic - automagically add, remove and manage imports
+
+This module just exports the main API of importmagic.
+"""
+
+__author__ = 'Alec Thomas <alec at swapoff.org>'
+__version__ = '0.1.7'
+
+from importmagic.importer import Import, Imports, get_update, update_imports
+from importmagic.index import SymbolIndex
+from importmagic.symbols import Scope
diff --git a/importmagic/conftest.py b/importmagic/conftest.py
new file mode 100644
index 0000000..c1c27c9
--- /dev/null
+++ b/importmagic/conftest.py
@@ -0,0 +1,12 @@
+import os
+
+import pytest
+
+from importmagic.index import SymbolIndex
+
+
+ at pytest.fixture(scope='session')
+def index(request):
+    dir = os.path.dirname(__file__)
+    with open(os.path.join(dir, 'test_index.json')) as fd:
+        return SymbolIndex.deserialize(fd)
diff --git a/importmagic/importer.py b/importmagic/importer.py
new file mode 100644
index 0000000..a2b5900
--- /dev/null
+++ b/importmagic/importer.py
@@ -0,0 +1,342 @@
+"""Imports new symbols."""
+
+import tokenize
+from collections import defaultdict
+
+from importmagic.six import StringIO
+
+
+class Iterator(object):
+    def __init__(self, tokens, start=None, end=None):
+        self._tokens = tokens
+        self._cursor = start or 0
+        self._end = end or len(self._tokens)
+
+    def rewind(self):
+        self._cursor -= 1
+
+    def next(self):
+        if not self:
+            return None, None
+        token = self._tokens[self._cursor]
+        index = self._cursor
+        self._cursor += 1
+        return index, token
+
+    def peek(self):
+        return self._tokens[self._cursor] if self else None
+
+    def until(self, type):
+        tokens = []
+        while self:
+            index, token = self.next()
+            tokens.append((index, token))
+            if type == token[0]:
+                break
+        return tokens
+
+    def __nonzero__(self):
+        return self._cursor < self._end
+    __bool__ = __nonzero__
+
+
+class Import(object):
+    def __init__(self, location, name, alias):
+        self.location = location
+        self.name = name
+        self.alias = alias
+
+    def __repr__(self):
+        return 'Import(location=%r, name=%r, alias=%r)' % \
+            (self.location, self.name, self.alias)
+
+    def __hash__(self):
+        return hash((self.location, self.name, self.alias))
+
+    def __eq__(self, other):
+        return self.location == other.location and self.name == other.name and self.alias == other.alias
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __lt__(self, other):
+        return self.location < other.location \
+            or self.name < other.name \
+            or (self.alias is not None and other.alias is not None and self.alias < other.alias)
+
+
+# See SymbolIndex.LOCATIONS for details.
+LOCATION_ORDER = 'FS3L'
+
+
+class Imports(object):
+
+    _style = {'multiline': 'parentheses',
+              'max_columns': 80,
+    }
+
+    def __init__(self, index, source):
+        self._imports = set()
+        self._imports_from = defaultdict(set)
+        self._imports_begin = self._imports_end = None
+        self._source = source
+        self._index = index
+        self._parse(source)
+
+    @classmethod
+    def set_style(cls, **kwargs):
+        cls._style.update(kwargs)
+
+    def add_import(self, name, alias=None):
+        location = LOCATION_ORDER.index(self._index.location_for(name))
+        self._imports.add(Import(location, name, alias))
+
+    def add_import_from(self, module, name, alias=None):
+        location = LOCATION_ORDER.index(self._index.location_for(module))
+        self._imports_from[module].add(Import(location, name, alias))
+
+    def remove(self, references):
+        for imp in list(self._imports):
+            if imp.name in references:
+                self._imports.remove(imp)
+        for name, imports in self._imports_from.items():
+            for imp in list(imports):
+                if imp.name in references:
+                    imports.remove(imp)
+
+    def get_update(self):
+        groups = []
+        for expected_location in range(len(LOCATION_ORDER)):
+            out = StringIO()
+            for imp in sorted(self._imports):
+                if expected_location != imp.location:
+                    continue
+                out.write('import {module}{alias}\n'.format(
+                    module=imp.name,
+                    alias=' as {alias}'.format(alias=imp.alias) if imp.alias else '',
+                ))
+
+            for module, imports in sorted(self._imports_from.items()):
+                imports = sorted(imports)
+                if not imports or expected_location != imports[0].location:
+                    continue
+                line = 'from {module} import '.format(module=module)
+                clauses = ['{name}{alias}'.format(
+                           name=i.name,
+                           alias=' as {alias}'.format(alias=i.alias) if i.alias else ''
+                           ) for i in imports]
+                clauses.reverse()
+                line_len = len(line)
+                line_pieces = []
+                paren_used = False
+                while clauses:
+                    clause = clauses.pop()
+                    next_len = line_len + len(clause) + 2
+                    if next_len > self._style['max_columns']:
+                        imported_items = ', '.join(line_pieces)
+                        if self._style['multiline'] == 'parentheses':
+                            line_tail = ',\n'
+                            if not paren_used:
+                                line += '('
+                                paren_used = True
+                            line_pieces.append('\n')
+                        else:
+                            # Use a backslash
+                            line_tail = ', \\\n'
+                        out.write(line + imported_items + line_tail)
+                        line = '    '
+                        line_len = len(line) + len(clause) + 2
+                        line_pieces = [clause]
+                    else:
+                        line_pieces.append(clause)
+                        line_len = next_len
+                line += ', '.join(line_pieces) + (')\n' if paren_used else '\n')
+                if line.strip():
+                    out.write(line)
+
+            text = out.getvalue()
+            if text:
+                groups.append(text)
+
+        start = self._tokens[self._imports_begin][2][0] - 1
+        end = self._tokens[min(len(self._tokens) - 1, self._imports_end)][2][0] - 1
+        if groups:
+            text = '\n'.join(groups) + '\n\n'
+        else:
+            text = ''
+        return start, end, text
+
+    def update_source(self):
+        start, end, text = self.get_update()
+        lines = self._source.splitlines()
+        lines[start:end] = text.splitlines()
+        return '\n'.join(lines) + '\n'
+
+    def _parse(self, source):
+        reader = StringIO(source)
+        # parse until EOF or TokenError (allows incomplete modules)
+        tokens = []
+        try:
+            tokens.extend(tokenize.generate_tokens(reader.readline))
+        except tokenize.TokenError:
+            # TokenError happens always at EOF, for unclosed strings or brackets.
+            # We don't care about that here, since we still can recover the whole
+            # source code.
+            pass
+        self._tokens = tokens
+        it = Iterator(self._tokens)
+        self._imports_begin, self._imports_end = self._find_import_range(it)
+        it = Iterator(self._tokens, start=self._imports_begin, end=self._imports_end)
+        self._parse_imports(it)
+
+    def _find_import_range(self, it):
+        ranges = self._find_import_ranges(it)
+        start, end = ranges[0][1:]
+        return start, end
+
+    def _find_import_ranges(self, it):
+        ranges = []
+        indentation = 0
+        explicit = False
+        size = 0
+        start = None
+        potential_end_index = -1
+
+        while it:
+            index, token = it.next()
+
+            if token[0] == tokenize.INDENT:
+                indentation += 1
+                continue
+            elif token[0] == tokenize.DEDENT:
+                indentation += 1
+                continue
+
+            if indentation:
+                continue
+
+            # Explicitly tell importmagic to manage the following block of imports
+            if token[1] == '# importmagic: manage':
+                ranges = []
+                start = index + 2  # Start managing imports after directive comment + newline.
+                explicit = True
+                continue
+            elif token[0] in (tokenize.STRING, tokenize.COMMENT):
+                # If a non-import statement follows, stop the range *before*
+                # this string or comment, in order to keep it out of the
+                # updated import block.
+                if potential_end_index == -1:
+                    potential_end_index = index
+                continue
+            elif token[0] in (tokenize.NEWLINE, tokenize.NL):
+                continue
+
+            if not ranges:
+                ranges.append((0, index, index))
+
+            # Accumulate imports
+            if token[1] in ('import', 'from'):
+                potential_end_index = -1
+                if start is None:
+                    start = index
+                size += 1
+                while it:
+                    token = it.peek()
+                    if token[0] == tokenize.NEWLINE or token[1] == ';':
+                        break
+                    index, _ = it.next()
+
+            # Terminate this import range
+            elif start is not None and token[1].strip():
+                if potential_end_index > -1:
+                    index = potential_end_index
+                    potential_end_index = -1
+                ranges.append((size, start, index))
+
+                start = None
+                size = 0
+                if explicit:
+                    break
+
+        if start is not None:
+            ranges.append((size, start, index))
+        ranges.sort(reverse=True)
+        return ranges
+
+    def _parse_imports(self, it):
+        while it:
+            index, token = it.next()
+
+            if token[1] not in ('import', 'from') and token[1].strip():
+                continue
+
+            type = token[1]
+            if type in ('import', 'from'):
+                tokens = it.until(tokenize.NEWLINE)
+                tokens = [t[1] for i, t in tokens
+                          if t[0] == tokenize.NAME or t[1] in ',.']
+                tokens.reverse()
+                self._parse_import(type, tokens)
+
+    def _parse_import(self, type, tokens):
+        module = None
+        if type == 'from':
+            module = ''
+            while tokens and tokens[-1] != 'import':
+                module += tokens.pop()
+            assert tokens.pop() == 'import'
+        while tokens:
+            name = ''
+            while True:
+                name += tokens.pop()
+                next = tokens.pop() if tokens else None
+                if next == '.':
+                    name += next
+                else:
+                    break
+
+            alias = None
+            if next == 'as':
+                alias = tokens.pop()
+                if alias == name:
+                    alias = None
+                next = tokens.pop() if tokens else None
+            if next == ',':
+                pass
+            if type == 'import':
+                self.add_import(name, alias=alias)
+            else:
+                self.add_import_from(module, name, alias=alias)
+
+    def __repr__(self):
+        return 'Imports(imports=%r, imports_from=%r)' % (self._imports, self._imports_from)
+
+
+def _process_imports(src, index, unresolved, unreferenced):
+    imports = Imports(index, src)
+    imports.remove(unreferenced)
+    for symbol in unresolved:
+        scores = index.symbol_scores(symbol)
+        if not scores:
+            continue
+        _, module, variable = scores[0]
+        # Direct module import: eg. os.path
+        if variable is None:
+            # sys.path              sys path          ->    import sys
+            # os.path.basename      os.path basename  ->    import os.path
+            imports.add_import(module)
+        else:
+            # basename              os.path basename   ->   from os.path import basename
+            # path.basename         os.path basename   ->   from os import path
+            imports.add_import_from(module, variable)
+    return imports
+
+
+def get_update(src, index, unresolved, unreferenced):
+    imports = _process_imports(src, index, unresolved, unreferenced)
+    return imports.get_update()
+
+
+def update_imports(src, index, unresolved, unreferenced):
+    imports = _process_imports(src, index, unresolved, unreferenced)
+    return imports.update_source()
diff --git a/importmagic/importer_test.py b/importmagic/importer_test.py
new file mode 100644
index 0000000..2885671
--- /dev/null
+++ b/importmagic/importer_test.py
@@ -0,0 +1,430 @@
+from __future__ import absolute_import
+
+from textwrap import dedent
+
+from importmagic.importer import Imports, get_update, update_imports
+from importmagic.symbols import Scope
+
+
+def test_get_update(index):
+    src = dedent("""
+         # header comment
+         import sys
+
+         print(os.unknown('/'))
+         """).strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    start_line, end_line, new_block = get_update(src, index, unresolved, unreferenced)
+    assert dedent("""\
+        import os
+
+
+        """).lstrip() == new_block
+
+
+def test_deep_import_of_unknown_symbol(index):
+    src = dedent("""
+         print(os.unknown('/'))
+         """).strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    assert unresolved == set(['os.unknown'])
+    new_src = update_imports(src, index, unresolved, unreferenced)
+    assert dedent("""
+        import os
+
+
+        print(os.unknown('/'))
+        """).strip() == new_src.strip()
+
+
+def test_import_future_preserved(index):
+    src = 'from __future__ import absolute_import'
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    assert not unresolved
+    assert not unreferenced
+    new_src = update_imports(src, index, unresolved, unreferenced).strip()
+    assert src == new_src
+
+
+def test_update_imports_inserts_initial_imports(index):
+    src = dedent("""
+        print(os.path.basename('sys/foo'))
+        print(sys.path[0])
+        print(basename('sys/foo'))
+        print(path.basename('sys/foo'))
+        """).strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    assert unresolved == set(['os.path.basename', 'sys.path', 'basename', 'path.basename'])
+    new_src = update_imports(src, index, unresolved, unreferenced)
+    assert dedent("""
+        import os.path
+        import sys
+        from os import path
+        from os.path import basename
+
+
+        print(os.path.basename('sys/foo'))
+        print(sys.path[0])
+        print(basename('sys/foo'))
+        print(path.basename('sys/foo'))
+        """).strip() == new_src.strip()
+
+
+def test_update_imports_inserts_imports(index):
+    src = dedent("""
+        import sys
+
+        print(os.path.basename("sys/foo"))
+        print(sys.path[0])
+        """).strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    assert unresolved == set(['os.path.basename'])
+    new_src = update_imports(src, index, unresolved, unreferenced)
+    assert dedent("""
+        import os.path
+        import sys
+
+
+        print(os.path.basename("sys/foo"))
+        print(sys.path[0])
+        """).strip() == new_src.strip()
+
+
+def test_update_imports_correctly_aliases(index):
+    src = dedent('''
+        print(basename('src/foo'))
+        ''').strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    assert unresolved == set(['basename'])
+    new_src = update_imports(src, index, unresolved, unreferenced)
+    assert dedent('''
+        from os.path import basename
+
+
+        print(basename('src/foo'))
+        ''').strip() == new_src.strip()
+
+
+def test_parse_imports(index):
+    src = dedent('''
+        import os, sys as sys
+        import sys as sys
+        from os.path import basename
+
+        from os import (
+            path,
+            posixpath
+            )
+
+        def main():
+            pass
+        ''').strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    new_src = update_imports(src, index, unresolved, unreferenced)
+    assert dedent(r'''
+        def main():
+            pass
+        ''').strip() == new_src.strip()
+
+
+def test_imports_inserted_after_preamble(index):
+    src = dedent('''
+        # Comment
+
+        """Docstring"""
+
+        def func(n):
+            print(basename(n))
+        ''').strip()
+    unresolved, unreferenced = Scope.from_source(src).find_unresolved_and_unreferenced_symbols()
+    new_src = update_imports(src, index, unresolved, unreferenced)
+    assert dedent('''
+        # Comment
+
+        """Docstring"""
+
+        from os.path import basename
+
+
+        def func(n):
+            print(basename(n))
+        ''').strip() == new_src.strip()
+
+
+def test_imports_dont_delete_trailing_comments(index):
+    src = dedent('''
+        import sys
+
+        # Some function
+        def func(n):
+            print(basename(n))
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols())
+    assert dedent('''
+        from os.path import basename
+
+
+        # Some function
+        def func(n):
+            print(basename(n))
+        ''').strip() == new_src.strip()
+
+
+def test_imports_dont_delete_imports_after_middle_comments(index):
+    src = dedent('''
+        import sys
+        # Some comment
+        import json
+
+        def func(n):
+            print(basename(n))
+            print(json)
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols())
+    assert dedent('''
+        import json
+        from os.path import basename
+
+
+        def func(n):
+            print(basename(n))
+            print(json)
+        ''').strip() == new_src.strip()
+
+
+def test_imports_removes_unused(index):
+    src = dedent('''
+        import sys
+
+        def func(n):
+            print(basename(n))
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols())
+    assert dedent('''
+        from os.path import basename
+
+
+        def func(n):
+            print(basename(n))
+        ''').strip() == new_src.strip()
+
+def test_imports_module_assignment(index):
+    src = dedent('''
+
+        def func(n):
+            sys.stderr = n
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols())
+    assert dedent('''
+        import sys
+
+
+        def func(n):
+            sys.stderr = n
+        ''').strip() == new_src.strip()
+
+def test_import_as_kept(index):
+    src = dedent('''
+        import time as taim
+
+
+        taim.sleep(0)
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols())
+    assert dedent('''
+        import time as taim
+
+
+        taim.sleep(0)
+        ''').strip() == new_src.strip()
+
+def test_from_import_as(index):
+    src = dedent('''
+        from clastic import MiddleWare as WebMiddleWare
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols())
+    assert src == new_src.strip()
+
+
+def test_importer_wrapping_escaped(index):
+    Imports.set_style(multiline='backslash', max_columns=80)
+    src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton
+        from waffle import stuff
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, stuff
+        ''').strip()
+    expected_src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, \\
+            Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton
+        from waffle import stuff
+
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, stuff
+        ''').strip()
+
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols()).strip()
+    assert expected_src == new_src
+
+def test_importer_wrapping_escaped_longer(index):
+    Imports.set_style(multiline='backslash', max_columns=80)
+    src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum
+        from waffle import stuff
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum, stuff
+        ''').strip()
+    expected_src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, \\
+            Module, Scope, ScopeDecorator, SequenceKey, bar, baz, cux, foo, imported, \\
+            inject, ipsum, lorem, more, provides, singleton, things
+        from waffle import stuff
+
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum, stuff
+        ''').strip()
+
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols()).strip()
+    assert expected_src == new_src
+
+def test_importer_wrapping_parentheses(index):
+    Imports.set_style(multiline='parentheses', max_columns=80)
+    src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton
+        from waffle import stuff
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, stuff
+        ''').strip()
+    expected_src = dedent('''
+        from injector import (Binder, Injector, InstanceProvider, Key, MappingKey,
+            Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton)
+        from waffle import stuff
+
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, stuff
+        ''').strip()
+
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols()).strip()
+    assert expected_src == new_src
+
+
+def test_importer_wrapping_parentheses_longer(index):
+    Imports.set_style(multiline='parentheses', max_columns=80)
+    src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum
+        from waffle import stuff
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum, stuff
+        ''').strip()
+    expected_src = dedent('''
+        from injector import (Binder, Injector, InstanceProvider, Key, MappingKey,
+            Module, Scope, ScopeDecorator, SequenceKey, bar, baz, cux, foo, imported,
+            inject, ipsum, lorem, more, provides, singleton, things)
+        from waffle import stuff
+
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum, stuff
+        ''').strip()
+
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols()).strip()
+    assert expected_src == new_src
+
+
+def test_importer_wrapping_colums(index):
+    Imports.set_style(multiline='parentheses', max_columns=120)
+    src = dedent('''
+        from injector import Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum
+        from waffle import stuff
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum, stuff
+        ''').strip()
+    expected_src = dedent('''
+        from injector import (Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey,
+            bar, baz, cux, foo, imported, inject, ipsum, lorem, more, provides, singleton, things)
+        from waffle import stuff
+
+
+        Binder, Injector, InstanceProvider, Key, MappingKey, Module, Scope, ScopeDecorator, SequenceKey, inject, provides, singleton, more, things, imported, foo, bar, baz, cux, lorem, ipsum, stuff
+        ''').strip()
+
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols()).strip()
+
+    assert expected_src == new_src
+
+
+def test_importer_directives_referenced(index):
+    src = dedent('''
+        from gevent.monkey import patch_all; patch_all()
+
+        # importmagic: manage
+        import re
+        import sys
+
+        print(os.path.basename('moo'))
+        ''').strip()
+    expected_src = dedent('''
+        from gevent.monkey import patch_all; patch_all()
+
+        # importmagic: manage
+        import os.path
+
+
+        print(os.path.basename('moo'))
+        ''').strip()
+    scope = Scope.from_source(src)
+    new_src = update_imports(src, index, *scope.find_unresolved_and_unreferenced_symbols()).strip()
... 5858 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/importmagic.git



More information about the Python-modules-commits mailing list