Пример #1
0
    def check_order(self):
        if not self.tree or not self.lines:
            self.load_file()

        try:
            style_entry_point = self.options['import_order_style']
        except KeyError:
            style_entry_point = lookup_entry_point(DEFAULT_IMPORT_ORDER_STYLE)
        style_cls = style_entry_point.load()

        if style_cls.accepts_application_package_names:
            visitor = self.visitor_class(
                self.options.get('application_import_names', []),
                self.options.get('application_package_names', []),
            )
        else:
            visitor = self.visitor_class(
                self.options.get('application_import_names', []),
                [],
            )
        visitor.visit(self.tree)

        imports = []
        for import_ in visitor.imports:
            if not pycodestyle.noqa(self.lines[import_.lineno - 1]):
                imports.append(import_)

        style = style_cls(imports)

        for error in style.check():
            yield self.error(error)
Пример #2
0
    def run(self, path, **meta):
        self.filename = path
        self.tree = None
        meta.setdefault('import_order_style', DEFAULT_IMPORT_ORDER_STYLE)
        meta['import_order_style'] = lookup_entry_point(
            meta['import_order_style'])
        self.options = meta

        for error in self.check_order():
            yield error
Пример #3
0
    def run(self, path, **meta):
        self.filename = path
        self.ast_tree = None
        meta.setdefault('import_order_style', DEFAULT_IMPORT_ORDER_STYLE)
        meta['import_order_style'] = lookup_entry_point(
            meta['import_order_style']
        )
        self.options = meta

        for error in self.check_order():
            yield error
Пример #4
0
    def parse_options(cls, options):
        def get_names(it):
            if not isinstance(it, list):
                it = it.split(',')
            return [item.strip() for item in it if item and item.strip()]

        names = get_names(options.application_import_names)
        packages = get_names(options.application_package_names)
        style_entry_point = lookup_entry_point(options.import_order_style)

        cls.options = {
            'application_import_names': names,
            'application_package_names': packages,
            'import_order_style': style_entry_point,
        }
Пример #5
0
 def assert_error_codes(self, expected_error_codes, filename, code):
     try:
         tree = ast.parse(code, filename or '<stdin>')
     except TypeError as e:
         raise TypeError('{0!s}\ncode = {1!r}\nfilename = {2!r}'.format(
             e, code, filename))
     checker = ImportOrderChecker(filename, tree)
     checker.lines = code.splitlines(True)
     checker.options = {
         'application_import_names': ['spoqa', 'tests'],
         'import_order_style': lookup_entry_point('spoqa'),
     }
     actual_error_codes = frozenset(error.code
                                    for error in checker.check_order())
     self.assertEquals(frozenset(expected_error_codes), actual_error_codes)
    def assert_error_codes(self, expected_error_codes, filename, code):
        tree = ast.parse(code, filename or '<stdin>')

        checker = ImportOrderChecker(filename, tree)
        checker.lines = code.splitlines(True)
        checker.options = {
            'application_import_names': ['myapp', 'tests'],
            'import_order_style': lookup_entry_point('fuzeman'),
        }

        errors = list(checker.check_order())

        self.assertEquals(
            frozenset(expected_error_codes),
            frozenset(error.code for error in errors)
        )
Пример #7
0
def _load_test_cases():
    base_path = os.path.dirname(__file__)
    test_cases = []
    test_case_path = os.path.join(base_path, 'test_cases')
    wildcard_path = os.path.join(test_case_path, '*.py')

    for filename in glob.glob(wildcard_path):
        fullpath = os.path.join(test_case_path, filename)
        with open(fullpath) as file_:
            data = file_.read()
        styles = data.splitlines()[0].lstrip('#').strip().split()
        codes = _extract_expected_errors(data)
        tree = ast.parse(data, fullpath)
        for style_name in styles:
            style_entry_point = lookup_entry_point(style_name)
            test_cases.append((filename, tree, style_entry_point, codes))

    return test_cases
Пример #8
0
    def parse_options(cls, options):
        optdict = {}

        names = options.application_import_names
        if not isinstance(names, list):
            names = options.application_import_names.split(",")

        pkg_names = options.application_package_names
        if not isinstance(pkg_names, list):
            pkg_names = options.application_package_names.split(",")

        style_entry_point = lookup_entry_point(options.import_order_style)

        optdict = dict(
            application_import_names=[n.strip() for n in names],
            application_package_names=[p.strip() for p in pkg_names],
            import_order_style=style_entry_point,
        )

        cls.options = optdict
    def parse_options(cls, options):
        optdict = {}

        names = options.application_import_names
        if not isinstance(names, list):
            names = options.application_import_names.split(",")

        pkg_names = options.application_package_names
        if not isinstance(pkg_names, list):
            pkg_names = options.application_package_names.split(",")

        style_entry_point = lookup_entry_point(options.import_order_style)

        optdict = dict(
            application_import_names=[n.strip() for n in names],
            application_package_names=[p.strip() for p in pkg_names],
            import_order_style=style_entry_point,
        )

        cls.options = optdict
Пример #10
0
def _load_test_cases():
    base_path = os.path.dirname(__file__)
    test_cases = []
    test_case_path = os.path.join(base_path, 'test_cases')
    wildcard_path = os.path.join(test_case_path, '*.py')

    for filename in glob.glob(wildcard_path):
        # The namespace.py test only works with Python3
        if filename.endswith('namespace.py') and sys.version_info.major < 3:
            continue
        fullpath = os.path.join(test_case_path, filename)
        with open(fullpath) as file_:
            data = file_.read()
        styles = data.splitlines()[0].lstrip('#').strip().split()
        codes = _extract_expected_errors(data)
        tree = ast.parse(data, fullpath)
        for style_name in styles:
            style_entry_point = lookup_entry_point(style_name)
            test_cases.append((filename, tree, style_entry_point, codes))

    return test_cases
Пример #11
0
    def check_order(self):
        if not self.tree or not self.lines:
            self.load_file()

        try:
            style_entry_point = self.options['import_order_style']
        except KeyError:
            style_entry_point = lookup_entry_point(DEFAULT_IMPORT_ORDER_STYLE)
        style_cls = style_entry_point.load()

        if style_cls.accepts_application_package_names:
            visitor = self.visitor_class(
                self.options.get('application_import_names', []),
                self.options.get('application_package_names', []),
            )
        else:
            visitor = self.visitor_class(
                self.options.get('application_import_names', []),
                [],
            )
        visitor.visit(self.tree)

        newlines = [
            NewLine(lineno)  # Lines are ordinal, no zero line
            for lineno, line in enumerate(self.lines, start=1)
            if BLANK_LINE_RE.match(line)
        ]
        # Replace the below with heapq merge, when Python2 is dropped.
        combined = sorted(
            chain(newlines, visitor.imports),
            key=lambda element: element.lineno,
        )
        style = style_cls(combined)

        for error in style.check():
            if not self.error_is_ignored(error):
                yield self.error(error)
Пример #12
0
    def check_order(self):
        if not self.tree or not self.lines:
            self.load_file()

        try:
            style_entry_point = self.options['import_order_style']
        except KeyError:
            style_entry_point = lookup_entry_point(DEFAULT_IMPORT_ORDER_STYLE)
        style_cls = style_entry_point.load()

        if style_cls.accepts_application_package_names:
            visitor = self.visitor_class(
                self.options.get('application_import_names', []),
                self.options.get('application_package_names', []),
            )
        else:
            visitor = self.visitor_class(
                self.options.get('application_import_names', []),
                [],
            )
        visitor.visit(self.tree)

        newlines = [
            NewLine(lineno)  # Lines are ordinal, no zero line
            for lineno, line in enumerate(self.lines, start=1)
            if BLANK_LINE_RE.match(line)
        ]
        # Replace the below with heapq merge, when Python2 is dropped.
        combined = sorted(
            chain(newlines, visitor.imports),
            key=lambda element: element.lineno,
        )
        style = style_cls(combined)

        for error in style.check():
            if not self.error_is_ignored(error):
                yield self.error(error)
Пример #13
0
import ast
import os
from os.path import dirname, join
import re
from flake8_import_order.checker import ImportOrderChecker
from flake8_import_order.styles import lookup_entry_point
import pytest

DATA_DIR = join(dirname(__file__), "data")

ERROR_RGX = re.compile("# ((?:I[0-9]{3} ?)+) ?.*$")

style_entry_point = lookup_entry_point("jwodder")

options = {
    "application_import_names": [
        "flake8_import_order",
        "namespace.package_b",
        "tests",
    ],
    "application_package_names": ["localpackage"],
    "import_order_style": style_entry_point,
}


@pytest.mark.parametrize("pyfile", os.listdir(DATA_DIR))
def test_jwodder_style(pyfile):
    pypath = join(DATA_DIR, pyfile)
    with open(pypath) as fp:
        data = fp.read()
    expected = []
Пример #14
0
def test_unknown_style():
    with pytest.raises(LookupError):
        lookup_entry_point('Unknown')
Пример #15
0
def _rewrite_source(options, filename, source_lines):

    keep_threshhold = options.heuristic_unused
    expand_stars = options.expand_stars
    style_entry_point = lookup_entry_point(options.style)
    style = style_entry_point.load()

    stats = {
        "starttime": time.time(),
        "names_from_star": 0,
        "star_imports_removed": 0,
        "removed_imports": 0,
    }

    # parse the code.  get the imports and a collection of line numbers
    # we definitely don't want to discard
    imports, _, lines_with_code = _parse_toplevel_imports(
        options, filename, source_lines
    )

    original_imports = len(imports)
    if imports:
        imports_start_on = imports[0].lineno
    else:
        imports_start_on = 0

    # assemble a set of line numbers that will not be copied to the
    # output.  E.g. lines where import statements occurred, or the
    # extra lines they take up which we figure out by looking at the
    # "gap" between statements
    import_gap_lines = _get_import_discard_lines(
        filename, source_lines, imports, lines_with_code
    )

    # flatten imports into single import per line and rewrite
    # full source
    if not options.multi_imports:
        imports = list(
            _dedupe_single_imports(
                _as_single_imports(imports, stats, expand_stars=expand_stars),
                stats,
            )
        )

    on_source_lines = _write_source(
        source_lines, imports, [],
        import_gap_lines, imports_start_on,
        style
    )
    # now parse again.  Because pyflakes won't tell us about unused
    # imports that are not the first import, we had to flatten first.
    imports, warnings, lines_with_code = _parse_toplevel_imports(
        options, filename, on_source_lines, drill_for_warnings=True
    )

    # now remove unused names from the imports
    # if number of imports is greater than keep_threshold% of the total
    # lines of code, don't remove names, assume this is like a
    # package file
    if not lines_with_code:
        stats["import_proportion"] = import_proportion = 0
    else:
        stats["import_proportion"] = import_proportion = (
            (
                len(imports)
                + stats["star_imports_removed"]
                - stats["names_from_star"]
            )
            / float(len(lines_with_code))
        ) * 100

    if keep_threshhold is None or import_proportion < keep_threshhold:
        _remove_unused_names(imports, warnings, stats)

    stats["import_line_delta"] = len(imports) - original_imports

    sorted_imports, nosort_imports = sort_imports(style, imports, options)

    rewritten = _write_source(
        source_lines,
        sorted_imports,
        nosort_imports,
        import_gap_lines,
        imports_start_on,
        style
    )

    differ = list(difflib.Differ().compare(source_lines, rewritten))

    stats["added"] = len([l for l in differ if l.startswith("+ ")])
    stats["removed"] = len([l for l in differ if l.startswith("- ")])
    stats["is_changed"] = bool(stats["added"] or stats["removed"])
    stats["totaltime"] = time.time() - stats["starttime"]
    return rewritten, stats