Skip to content

Commit

Permalink
Fix #19, only run linters that are selected
Browse files Browse the repository at this point in the history
  • Loading branch information
mschwager committed Feb 19, 2020
1 parent ea3be23 commit 0a17f23
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- Cache namespace results and minimize kwarg checks by grouping similar rules - ~500% speed up ([#18](https://github.com/dlint-py/dlint/issues/18))
- Only run linters that are selected - speed up depends on number of linters seleted ([#19](https://github.com/dlint-py/dlint/issues/19))

### Fixed
- The `--print-dlint-linters` flag on Windows ([#17](https://github.com/dlint-py/dlint/issues/17))
Expand Down
19 changes: 17 additions & 2 deletions dlint/extension.py
Expand Up @@ -13,12 +13,15 @@
import optparse
import sys

from flake8 import style_guide

import dlint


class Flake8Extension(object):
name = dlint.__name__
version = dlint.__version__
options = None

def __init__(self, tree, filename):
self.tree = tree
Expand All @@ -44,7 +47,7 @@ def add_options(cls, parser):
def parse_options(cls, options):
if options.print_dlint_linters:
code_prefix_len = 7
linters = Flake8Extension.get_linter_classes()
linters = cls.get_linter_classes()
output_lines = [
"{} {} {}".format(l._code, l.__name__, l._error_tmpl[code_prefix_len:])
for l in sorted(linters, key=lambda li: li._code)
Expand All @@ -53,6 +56,8 @@ def parse_options(cls, options):
EX_OK = 0
sys.exit(EX_OK)

cls.options = options

@classmethod
def get_plugin_linter_classes(cls):
module_prefix = 'dlint_plugin_'
Expand All @@ -74,7 +79,17 @@ def get_plugin_linter_classes(cls):

@classmethod
def get_linter_classes(cls):
return dlint.linters.ALL + tuple(cls.get_plugin_linter_classes())
linter_classes = dlint.linters.ALL + tuple(cls.get_plugin_linter_classes())

if cls.options:
engine = style_guide.DecisionEngine(cls.options)
selected = style_guide.Decision.Selected
linter_classes = tuple(
linter_class for linter_class in linter_classes
if engine.decision_for(linter_class._code) is selected
)

return linter_classes

def run(self):
linter_instances = [l() for l in self.get_linter_classes()]
Expand Down
78 changes: 78 additions & 0 deletions tests/test_extension.py
Expand Up @@ -7,6 +7,8 @@
unicode_literals,
)

import argparse
import contextlib
import os
import sys
import unittest
Expand All @@ -31,6 +33,30 @@
import extension # noqa: E402


def create_options(**kwargs):
kwargs.setdefault("select", [])
kwargs.setdefault("extended_default_select", ["DUO"])
kwargs.setdefault("ignore", [])
kwargs.setdefault("extend_ignore", [])
kwargs.setdefault("disable_noqa", False)
kwargs.setdefault("enable_extensions", [])

return argparse.Namespace(**kwargs)


@contextlib.contextmanager
def extension_with_options(options):
# Flake8 requires an extension's options to be set as a class
# variable. We have to ensure options are reset back to None after the
# extension is used or all class instances will retain the set options.
ext = extension.Flake8Extension
ext.options = options
try:
yield ext
finally:
ext.options = None


class TestFlake8Extension(base.BaseTest):

def test_flake8_extension_empty(self):
Expand Down Expand Up @@ -67,6 +93,58 @@ def test_flake8_extension_basic(self):

assert result == expected

def test_flake8_extension_get_linter_classes_select(self):
options = create_options(select=["DUO101"])

with extension_with_options(options) as ext:
result = ext.get_linter_classes()

expected = (extension.dlint.linters.YieldReturnStatementLinter,)

assert result == expected

def test_flake8_extension_get_linter_classes_extended_default_select(self):
options = create_options(extended_default_select=["DUO101"])

with extension_with_options(options) as ext:
result = ext.get_linter_classes()

expected = (extension.dlint.linters.YieldReturnStatementLinter,)

assert result == expected

def test_flake8_extension_get_linter_classes_ignore(self):
options = create_options(ignore=["DUO101"])

with extension_with_options(options) as ext:
result = ext.get_linter_classes()

expected = list(extension.dlint.linters.ALL)
expected.remove(extension.dlint.linters.YieldReturnStatementLinter)
expected = tuple(expected)

assert result == expected

def test_flake8_extension_get_linter_classes_extend_ignore(self):
options = create_options(extend_ignore=["DUO101"])

with extension_with_options(options) as ext:
result = ext.get_linter_classes()

expected = list(extension.dlint.linters.ALL)
expected.remove(extension.dlint.linters.YieldReturnStatementLinter)
expected = tuple(expected)

assert result == expected

def test_flake8_extension_get_linter_classes_missing_options(self):
ext = extension.Flake8Extension

result = ext.get_linter_classes()
expected = extension.dlint.linters.ALL

assert result == expected


if __name__ == "__main__":
unittest.main()

0 comments on commit 0a17f23

Please sign in to comment.