From be88d2639694da77d07a9075231a0bea2b8df3f5 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 27 Dec 2018 16:55:15 -0800 Subject: [PATCH] Remove unused and broken flake8.listen plugin type --- docs/source/internal/plugin_handling.rst | 40 +----- .../registering-plugins.rst | 5 +- src/flake8/main/application.py | 31 +---- src/flake8/plugins/_trie.py | 95 -------------- src/flake8/plugins/manager.py | 33 +---- src/flake8/plugins/notifier.py | 46 ------- src/flake8/style_guide.py | 15 +-- tests/unit/test_notifier.py | 54 -------- tests/unit/test_plugin_type_manager.py | 28 ---- tests/unit/test_style_guide.py | 75 +---------- tests/unit/test_trie.py | 122 ------------------ 11 files changed, 19 insertions(+), 525 deletions(-) delete mode 100644 src/flake8/plugins/_trie.py delete mode 100644 src/flake8/plugins/notifier.py delete mode 100644 tests/unit/test_notifier.py delete mode 100644 tests/unit/test_trie.py diff --git a/docs/source/internal/plugin_handling.rst b/docs/source/internal/plugin_handling.rst index 9af3182..faf3996 100644 --- a/docs/source/internal/plugin_handling.rst +++ b/docs/source/internal/plugin_handling.rst @@ -4,15 +4,13 @@ Plugin Handling Plugin Management ----------------- -|Flake8| 3.0 added support for two other plugins besides those which define +|Flake8| 3.0 added support for other plugins besides those which define new checks. It now supports: - extra checks - alternative report formatters -- listeners to auto-correct violations of checks - To facilitate this, |Flake8| needed a more mature way of managing plugins. Thus, we developed the |PluginManager| which accepts a namespace and will load the plugins for that namespace. A |PluginManager| creates and manages many @@ -38,12 +36,10 @@ the |PTM| will subclass it and specify the ``namespace``, e.g., This provides a few extra methods via the |PluginManager|'s ``map`` method. -Finally, we create three classes of plugins: +Finally, we create two classes of plugins: - :class:`~flake8.plugins.manager.Checkers` -- :class:`~flake8.plugins.manager.Listeners` - - :class:`~flake8.plugins.manager.ReportFormatters` These are used to interact with each of the types of plugins individually. @@ -53,29 +49,6 @@ These are used to interact with each of the types of plugins individually. Our inspiration for our plugin handling comes from the author's extensive experience with ``stevedore``. -Notifying Listener Plugins --------------------------- - -One of the interesting challenges with allowing plugins to be notified each -time an error or warning is emitted by a checker is finding listeners quickly -and efficiently. It makes sense to allow a listener to listen for a certain -class of warnings or just a specific warning. Hence, we need to allow all -plugins that listen to a specific warning or class to be notified. For -example, someone might register a listener for ``E1`` and another for ``E111`` -if ``E111`` is triggered by the code, both listeners should be notified. -If ``E112`` is returned, then only ``E1`` (and any other listeners) would be -notified. - -To implement this goal, we needed an object to store listeners in that would -allow for efficient look up - a Trie (or Prefix Tree). Given that none of the -existing packages on PyPI allowed for storing data on each node of the trie, -it was left up to write our own as :class:`~flake8.plugins._trie.Trie`. On -top of that we layer our :class:`~flake8.plugins.notifier.Notifier` class. - -Now when |Flake8| receives an error or warning, we can easily call the -:meth:`~flake8.plugins.notifier.Notifier.notify` method and let plugins act on -that knowledge. - Default Plugins --------------- @@ -103,7 +76,7 @@ API Documentation .. autoclass:: flake8.plugins.manager.PluginManager :members: - :special-members: __init__, __contains__, __getitem__ + :special-members: __init__ .. autoclass:: flake8.plugins.manager.Plugin :members: @@ -115,15 +88,8 @@ API Documentation .. autoclass:: flake8.plugins.manager.Checkers :members: -.. autoclass:: flake8.plugins.manager.Listeners - :members: build_notifier - .. autoclass:: flake8.plugins.manager.ReportFormatters -.. autoclass:: flake8.plugins.notifier.Notifier - -.. autoclass:: flake8.plugins._trie.Trie - .. |PluginManager| replace:: :class:`~flake8.plugins.manager.PluginManager` .. |Plugin| replace:: :class:`~flake8.plugins.manager.Plugin` .. |PTM| replace:: :class:`~flake8.plugins.manager.PluginTypeManager` diff --git a/docs/source/plugin-development/registering-plugins.rst b/docs/source/plugin-development/registering-plugins.rst index 39c3083..6d901d7 100644 --- a/docs/source/plugin-development/registering-plugins.rst +++ b/docs/source/plugin-development/registering-plugins.rst @@ -86,13 +86,10 @@ grouping of entry-points that flake8 should look in. - ``flake8.extension`` -- ``flake8.listen`` - - ``flake8.report`` If your plugin is one that adds checks to |Flake8|, you will use -``flake8.extension``. If your plugin automatically fixes errors in code, you -will use ``flake8.listen``. Finally, if your plugin performs extra report +``flake8.extension``. If your plugin performs extra report handling (formatting, filtering, etc.) it will use ``flake8.report``. If our ``ExamplePlugin`` is something that adds checks, our code would look diff --git a/src/flake8/main/application.py b/src/flake8/main/application.py index 86d7fd4..ae33b13 100644 --- a/src/flake8/main/application.py +++ b/src/flake8/main/application.py @@ -57,14 +57,10 @@ class Application(object): self.local_plugins = None #: The instance of :class:`flake8.plugins.manager.Checkers` self.check_plugins = None - #: The instance of :class:`flake8.plugins.manager.Listeners` - self.listening_plugins = None #: The instance of :class:`flake8.plugins.manager.ReportFormatters` self.formatting_plugins = None #: The user-selected formatter from :attr:`formatting_plugins` self.formatter = None - #: The :class:`flake8.plugins.notifier.Notifier` for listening plugins - self.listener_trie = None #: The :class:`flake8.style_guide.StyleGuideManager` built from the #: user's options self.guide = None @@ -166,11 +162,11 @@ class Application(object): # type: () -> NoneType """Find and load the plugins for this application. - If :attr:`check_plugins`, :attr:`listening_plugins`, or - :attr:`formatting_plugins` are ``None`` then this method will update - them with the appropriate plugin manager instance. Given the expense - of finding plugins (via :mod:`entrypoints`) we want this to be - idempotent and so only update those attributes if they are ``None``. + If :attr:`check_plugins`, or :attr:`formatting_plugins` are ``None`` + then this method will update them with the appropriate plugin manager + instance. Given the expense of finding plugins (via :mod:`entrypoints`) + we want this to be idempotent and so only update those attributes if + they are ``None``. """ if self.local_plugins is None: self.local_plugins = config.get_local_plugins( @@ -186,16 +182,12 @@ class Application(object): self.local_plugins.extension ) - if self.listening_plugins is None: - self.listening_plugins = plugin_manager.Listeners() - if self.formatting_plugins is None: self.formatting_plugins = plugin_manager.ReportFormatters( self.local_plugins.report ) self.check_plugins.load_plugins() - self.listening_plugins.load_plugins() self.formatting_plugins.load_plugins() def register_plugin_options(self): @@ -203,7 +195,6 @@ class Application(object): """Register options provided by plugins to our option manager.""" self.check_plugins.register_options(self.option_manager) self.check_plugins.register_plugin_versions(self.option_manager) - self.listening_plugins.register_options(self.option_manager) self.formatting_plugins.register_options(self.option_manager) def parse_configuration_and_cli(self, argv=None): @@ -229,9 +220,6 @@ class Application(object): self.check_plugins.provide_options( self.option_manager, self.options, self.args ) - self.listening_plugins.provide_options( - self.option_manager, self.options, self.args - ) self.formatting_plugins.provide_options( self.option_manager, self.options, self.args ) @@ -264,18 +252,12 @@ class Application(object): self.formatter = formatter_class(self.options) - def make_notifier(self): - # type: () -> NoneType - """Initialize our listener Notifier.""" - if self.listener_trie is None: - self.listener_trie = self.listening_plugins.build_notifier() - def make_guide(self): # type: () -> NoneType """Initialize our StyleGuide.""" if self.guide is None: self.guide = style_guide.StyleGuideManager( - self.options, self.listener_trie, self.formatter + self.options, self.formatter ) if self.running_against_diff: @@ -373,7 +355,6 @@ class Application(object): self.register_plugin_options() self.parse_configuration_and_cli(argv) self.make_formatter() - self.make_notifier() self.make_guide() self.make_file_checker_manager() diff --git a/src/flake8/plugins/_trie.py b/src/flake8/plugins/_trie.py deleted file mode 100644 index 9a50b45..0000000 --- a/src/flake8/plugins/_trie.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Independent implementation of a Trie tree.""" - -__all__ = ("Trie", "TrieNode") - - -def _iterate_stringlike_objects(string): - for i in range(len(string)): - yield string[i : i + 1] - - -class Trie(object): - """The object that manages the trie nodes.""" - - def __init__(self): - """Initialize an empty trie.""" - self.root = TrieNode(None, None) - - def add(self, path, node_data): - """Add the node data to the path described.""" - node = self.root - for prefix in _iterate_stringlike_objects(path): - child = node.find_prefix(prefix) - if child is None: - child = node.add_child(prefix, []) - node = child - node.data.append(node_data) - - def find(self, path): - """Find a node based on the path provided.""" - node = self.root - for prefix in _iterate_stringlike_objects(path): - child = node.find_prefix(prefix) - if child is None: - return None - node = child - return node - - def traverse(self): - """Traverse this tree. - - This performs a depth-first pre-order traversal of children in this - tree. It returns the results consistently by first sorting the - children based on their prefix and then traversing them in - alphabetical order. - """ - return self.root.traverse() - - -class TrieNode(object): - """The majority of the implementation details of a Trie.""" - - def __init__(self, prefix, data, children=None): - """Initialize a TrieNode with data and children.""" - self.children = children or {} - self.data = data - self.prefix = prefix - - def __repr__(self): - """Generate an easy to read representation of the node.""" - return "TrieNode(prefix={0}, data={1})".format(self.prefix, self.data) - - def find_prefix(self, prefix): - """Find the prefix in the children of this node. - - :returns: A child matching the prefix or None. - :rtype: :class:`~TrieNode` or None - """ - return self.children.get(prefix, None) - - def add_child(self, prefix, data, children=None): - """Create and add a new child node. - - :returns: The newly created node - :rtype: :class:`~TrieNode` - """ - new_node = TrieNode(prefix, data, children) - self.children[prefix] = new_node - return new_node - - def traverse(self): - """Traverse children of this node. - - This performs a depth-first pre-order traversal of the remaining - children in this sub-tree. It returns the results consistently by - first sorting the children based on their prefix and then traversing - them in alphabetical order. - """ - if not self.children: - return - - for prefix in sorted(self.children): - child = self.children[prefix] - yield child - for child in child.traverse(): - yield child diff --git a/src/flake8/plugins/manager.py b/src/flake8/plugins/manager.py index 411e02f..045cfd7 100644 --- a/src/flake8/plugins/manager.py +++ b/src/flake8/plugins/manager.py @@ -6,7 +6,6 @@ import entrypoints from flake8 import exceptions from flake8 import utils -from flake8.plugins import notifier if sys.version_info >= (3, 3): import collections.abc as collections_abc @@ -15,13 +14,7 @@ else: LOG = logging.getLogger(__name__) -__all__ = ( - "Checkers", - "Listeners", - "Plugin", - "PluginManager", - "ReportFormatters", -) +__all__ = ("Checkers", "Plugin", "PluginManager", "ReportFormatters") NO_GROUP_FOUND = object() @@ -444,24 +437,6 @@ class PluginTypeManager(object): list(self.manager.map(call_provide_options)) -class NotifierBuilderMixin(object): # pylint: disable=too-few-public-methods - """Mixin class that builds a Notifier from a PluginManager.""" - - def build_notifier(self): - """Build a Notifier for our Listeners. - - :returns: - Object to notify our listeners of certain error codes and - warnings. - :rtype: - :class:`~flake8.notifier.Notifier` - """ - notifier_trie = notifier.Notifier() - for name in self.names: - notifier_trie.register_listener(name, self.manager[name]) - return notifier_trie - - class Checkers(PluginTypeManager): """All of the checkers registered through entry-points or config.""" @@ -542,12 +517,6 @@ class Checkers(PluginTypeManager): return plugins -class Listeners(PluginTypeManager, NotifierBuilderMixin): - """All of the listeners registered through entry-points or config.""" - - namespace = "flake8.listen" - - class ReportFormatters(PluginTypeManager): """All of the report formatters registered through entry-points/config.""" diff --git a/src/flake8/plugins/notifier.py b/src/flake8/plugins/notifier.py deleted file mode 100644 index 9efccd4..0000000 --- a/src/flake8/plugins/notifier.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Implementation of the class that registers and notifies listeners.""" -from flake8.plugins import _trie - - -class Notifier(object): - """Object that tracks and notifies listener objects.""" - - def __init__(self): - """Initialize an empty notifier object.""" - self.listeners = _trie.Trie() - - def listeners_for(self, error_code): - """Retrieve listeners for an error_code. - - There may be listeners registered for E1, E100, E101, E110, E112, and - E126. To get all the listeners for one of E100, E101, E110, E112, or - E126 you would also need to incorporate the listeners for E1 (since - they're all in the same class). - - Example usage: - - .. code-block:: python - - from flake8 import notifier - - n = notifier.Notifier() - # register listeners - for listener in n.listeners_for('W102'): - listener.notify(...) - """ - path = error_code - while path: - node = self.listeners.find(path) - listeners = getattr(node, "data", []) - for listener in listeners: - yield listener - path = path[:-1] - - def notify(self, error_code, *args, **kwargs): - """Notify all listeners for the specified error code.""" - for listener in self.listeners_for(error_code): - listener.notify(error_code, *args, **kwargs) - - def register_listener(self, error_code, listener): - """Register a listener for a specific error_code.""" - self.listeners.add(error_code, listener) diff --git a/src/flake8/style_guide.py b/src/flake8/style_guide.py index 46f72fc..56fa832 100644 --- a/src/flake8/style_guide.py +++ b/src/flake8/style_guide.py @@ -325,19 +325,18 @@ class DecisionEngine(object): class StyleGuideManager(object): """Manage multiple style guides for a single run.""" - def __init__(self, options, listener_trie, formatter, decider=None): + def __init__(self, options, formatter, decider=None): """Initialize our StyleGuide. .. todo:: Add parameter documentation. """ self.options = options - self.listener = listener_trie self.formatter = formatter self.stats = statistics.Statistics() self.decider = decider or DecisionEngine(options) self.style_guides = [] self.default_style_guide = StyleGuide( - options, listener_trie, formatter, decider=decider + options, formatter, decider=decider ) self.style_guides = list( itertools.chain( @@ -435,15 +434,12 @@ class StyleGuideManager(object): class StyleGuide(object): """Manage a Flake8 user's style guide.""" - def __init__( - self, options, listener_trie, formatter, filename=None, decider=None - ): + def __init__(self, options, formatter, filename=None, decider=None): """Initialize our StyleGuide. .. todo:: Add parameter documentation. """ self.options = options - self.listener = listener_trie self.formatter = formatter self.stats = statistics.Statistics() self.decider = decider or DecisionEngine(options) @@ -461,9 +457,7 @@ class StyleGuide(object): filename = filename or self.filename options = copy.deepcopy(self.options) options.ignore.extend(extend_ignore_with or []) - return StyleGuide( - options, self.listener, self.formatter, filename=filename - ) + return StyleGuide(options, self.formatter, filename=filename) @contextlib.contextmanager def processing_file(self, filename): @@ -565,7 +559,6 @@ class StyleGuide(object): ): self.formatter.handle(error) self.stats.record(error) - self.listener.notify(error.code, error) return 1 return 0 diff --git a/tests/unit/test_notifier.py b/tests/unit/test_notifier.py deleted file mode 100644 index 208d406..0000000 --- a/tests/unit/test_notifier.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Unit tests for the Notifier object.""" -import pytest - -from flake8.plugins import notifier - - -class _Listener(object): - def __init__(self, error_code): - self.error_code = error_code - self.was_notified = False - - def notify(self, error_code, *args, **kwargs): - assert error_code.startswith(self.error_code) - self.was_notified = True - - -class TestNotifier(object): - """Notifier unit tests.""" - - @pytest.fixture(autouse=True) - def setup(self): - """Set up each TestNotifier instance.""" - self.notifier = notifier.Notifier() - self.listener_map = {} - - def add_listener(error_code): - listener = _Listener(error_code) - self.listener_map[error_code] = listener - self.notifier.register_listener(error_code, listener) - - for i in range(10): - add_listener('E{0}'.format(i)) - for j in range(30): - add_listener('E{0}{1:02d}'.format(i, j)) - - def test_notify(self): - """Show that we notify a specific error code.""" - self.notifier.notify('E111', 'extra', 'args') - assert self.listener_map['E111'].was_notified is True - assert self.listener_map['E1'].was_notified is True - - @pytest.mark.parametrize('code', ['W123', 'W12', 'W1', 'W']) - def test_no_listeners_for(self, code): - """Show that we return an empty list of listeners.""" - assert list(self.notifier.listeners_for(code)) == [] - - @pytest.mark.parametrize('code,expected', [ - ('E101', ['E101', 'E1']), - ('E211', ['E211', 'E2']), - ]) - def test_listeners_for(self, code, expected): - """Verify that we retrieve the correct listeners.""" - assert ([l.error_code - for l in self.notifier.listeners_for(code)] == expected) diff --git a/tests/unit/test_plugin_type_manager.py b/tests/unit/test_plugin_type_manager.py index 18058d4..e1392a4 100644 --- a/tests/unit/test_plugin_type_manager.py +++ b/tests/unit/test_plugin_type_manager.py @@ -203,31 +203,3 @@ def test_proxies_getitem_to_managers_plugins_dict(PluginManager): # noqa: N803 for i in range(8): key = 'T10%i' % i assert type_mgr[key] is plugins[key] - - -class FakePluginTypeManager(manager.NotifierBuilderMixin): - """Provide an easy way to test the NotifierBuilderMixin.""" - - def __init__(self, manager): - """Initialize with our fake manager.""" - self.names = sorted(manager) - self.manager = manager - - -@pytest.fixture -def notifier_builder(): - """Create a fake plugin type manager.""" - return FakePluginTypeManager(manager={ - 'T100': object(), - 'T101': object(), - 'T110': object(), - }) - - -def test_build_notifier(notifier_builder): - """Verify we properly build a Notifier object.""" - notifier = notifier_builder.build_notifier() - for name in ('T100', 'T101', 'T110'): - assert list(notifier.listeners_for(name)) == [ - notifier_builder.manager[name] - ] diff --git a/tests/unit/test_style_guide.py b/tests/unit/test_style_guide.py index c4ef5ef..a1740a7 100644 --- a/tests/unit/test_style_guide.py +++ b/tests/unit/test_style_guide.py @@ -7,7 +7,6 @@ import pytest from flake8 import style_guide from flake8 import utils from flake8.formatting import base -from flake8.plugins import notifier def create_options(**kwargs): @@ -22,35 +21,10 @@ def create_options(**kwargs): return optparse.Values(kwargs) -@pytest.mark.parametrize('select_list,ignore_list,error_code', [ - (['E111', 'E121'], [], 'E111'), - (['E111', 'E121'], [], 'E121'), - (['E11', 'E121'], ['E1'], 'E112'), - (['E41'], ['E2', 'E12', 'E4'], 'E410'), -]) -def test_handle_error_notifies_listeners(select_list, ignore_list, error_code): - """Verify that error codes notify the listener trie appropriately.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) - formatter = mock.create_autospec(base.BaseFormatter, instance=True) - guide = style_guide.StyleGuide(create_options(select=select_list, - ignore=ignore_list), - listener_trie=listener_trie, - formatter=formatter) - - with mock.patch('linecache.getline', return_value=''): - guide.handle_error(error_code, 'stdin', 1, 0, 'error found') - error = style_guide.Violation( - error_code, 'stdin', 1, 1, 'error found', None) - listener_trie.notify.assert_called_once_with(error_code, error) - formatter.handle.assert_called_once_with(error) - - def test_handle_error_does_not_raise_type_errors(): """Verify that we handle our inputs better.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True) guide = style_guide.StyleGuide(create_options(select=['T111'], ignore=[]), - listener_trie=listener_trie, formatter=formatter) assert 1 == guide.handle_error( @@ -58,41 +32,11 @@ def test_handle_error_does_not_raise_type_errors(): ) -@pytest.mark.parametrize('select_list,ignore_list,error_code', [ - (['E111', 'E121'], [], 'E122'), - (['E11', 'E12'], [], 'E132'), - (['E2', 'E12'], [], 'E321'), - (['E2', 'E12'], [], 'E410'), - (['E111', 'E121'], ['E2'], 'E122'), - (['E11', 'E12'], ['E13'], 'E132'), - (['E1', 'E3'], ['E32'], 'E321'), - (['E4'], ['E2', 'E12', 'E41'], 'E410'), - (['E111', 'E121'], [], 'E112'), -]) -def test_handle_error_does_not_notify_listeners(select_list, ignore_list, - error_code): - """Verify that error codes notify the listener trie appropriately.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) - formatter = mock.create_autospec(base.BaseFormatter, instance=True) - guide = style_guide.StyleGuide(create_options(select=select_list, - ignore=ignore_list), - listener_trie=listener_trie, - formatter=formatter) - - with mock.patch('linecache.getline', return_value=''): - guide.handle_error(error_code, 'stdin', 1, 1, 'error found') - assert listener_trie.notify.called is False - assert formatter.handle.called is False - - def test_style_guide_manager(): """Verify how the StyleGuideManager creates a default style guide.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True) options = create_options() - guide = style_guide.StyleGuideManager(options, - listener_trie=listener_trie, - formatter=formatter) + guide = style_guide.StyleGuideManager(options, formatter=formatter) assert guide.default_style_guide.options is options assert len(guide.style_guides) == 1 @@ -114,11 +58,9 @@ PER_FILE_IGNORES_UNPARSED = [ ]) def test_style_guide_applies_to(style_guide_file, filename, expected): """Verify that we match a file to its style guide.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True) options = create_options() guide = style_guide.StyleGuide(options, - listener_trie=listener_trie, formatter=formatter, filename=style_guide_file) assert guide.applies_to(filename) is expected @@ -126,12 +68,9 @@ def test_style_guide_applies_to(style_guide_file, filename, expected): def test_style_guide_manager_pre_file_ignores_parsing(): """Verify how the StyleGuideManager creates a default style guide.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True) options = create_options(per_file_ignores=PER_FILE_IGNORES_UNPARSED) - guide = style_guide.StyleGuideManager(options, - listener_trie=listener_trie, - formatter=formatter) + guide = style_guide.StyleGuideManager(options, formatter=formatter) assert len(guide.style_guides) == 5 assert list(map(utils.normalize_path, ["first_file.py", "second_file.py", "third_file.py", @@ -150,14 +89,11 @@ def test_style_guide_manager_pre_file_ignores_parsing(): def test_style_guide_manager_pre_file_ignores(ignores, violation, filename, handle_error_return): """Verify how the StyleGuideManager creates a default style guide.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True) options = create_options(ignore=ignores, select=['E', 'F', 'W'], per_file_ignores=PER_FILE_IGNORES_UNPARSED) - guide = style_guide.StyleGuideManager(options, - listener_trie=listener_trie, - formatter=formatter) + guide = style_guide.StyleGuideManager(options, formatter=formatter) assert (guide.handle_error(violation, filename, 1, 1, "Fake text") == handle_error_return) @@ -172,12 +108,9 @@ def test_style_guide_manager_pre_file_ignores(ignores, violation, filename, ]) def test_style_guide_manager_style_guide_for(filename, expected): """Verify the style guide selection function.""" - listener_trie = mock.create_autospec(notifier.Notifier, instance=True) formatter = mock.create_autospec(base.BaseFormatter, instance=True) options = create_options(per_file_ignores=PER_FILE_IGNORES_UNPARSED) - guide = style_guide.StyleGuideManager(options, - listener_trie=listener_trie, - formatter=formatter) + guide = style_guide.StyleGuideManager(options, formatter=formatter) file_guide = guide.style_guide_for(filename) assert file_guide.filename == expected diff --git a/tests/unit/test_trie.py b/tests/unit/test_trie.py deleted file mode 100644 index 2f08a37..0000000 --- a/tests/unit/test_trie.py +++ /dev/null @@ -1,122 +0,0 @@ -"""Unit test for the _trie module.""" -from flake8.plugins import _trie as trie - - -class TestTrie(object): - """Collection of tests for the Trie class.""" - - def test_traverse_without_data(self): - """Verify the behaviour when traversing an empty Trie.""" - tree = trie.Trie() - assert list(tree.traverse()) == [] - - def test_traverse_with_data(self): - """Verify that traversal of our Trie is depth-first and pre-order.""" - tree = trie.Trie() - tree.add('A', 'A') - tree.add('a', 'a') - tree.add('AB', 'B') - tree.add('Ab', 'b') - tree.add('AbC', 'C') - tree.add('Abc', 'c') - # The trie tree here should look something like - # - # - # / \ - # A a - # / | - # B b - # / \ - # C c - # - # And the traversal should look like: - # - # A B b C c a - expected_order = ['A', 'B', 'b', 'C', 'c', 'a'] - for expected, actual_node in zip(expected_order, tree.traverse()): - assert actual_node.prefix == expected - - def test_find(self): - """Exercise the Trie.find method.""" - tree = trie.Trie() - tree.add('A', 'A') - tree.add('a', 'a') - tree.add('AB', 'AB') - tree.add('Ab', 'Ab') - tree.add('AbC', 'AbC') - tree.add('Abc', 'Abc') - - assert tree.find('AB').data == ['AB'] - assert tree.find('AbC').data == ['AbC'] - assert tree.find('A').data == ['A'] - assert tree.find('X') is None - - -class TestTrieNode(object): - """Collection of tests for the TrieNode class.""" - - def test_add_child(self): - """Verify we add children appropriately.""" - node = trie.TrieNode('E', 'E is for Eat') - assert node.find_prefix('a') is None - added = node.add_child('a', 'a is for Apple') - assert node.find_prefix('a') is added - - def test_add_child_overrides_previous_child(self): - """Verify adding a child will replace the previous child.""" - node = trie.TrieNode('E', 'E is for Eat', children={ - 'a': trie.TrieNode('a', 'a is for Apple') - }) - previous = node.find_prefix('a') - assert previous is not None - - added = node.add_child('a', 'a is for Ascertain') - assert node.find_prefix('a') is added - - def test_find_prefix(self): - """Verify we can find a child with the specified prefix.""" - node = trie.TrieNode('E', 'E is for Eat', children={ - 'a': trie.TrieNode('a', 'a is for Apple') - }) - child = node.find_prefix('a') - assert child is not None - assert child.prefix == 'a' - assert child.data == 'a is for Apple' - - def test_find_prefix_returns_none_when_no_children_have_the_prefix(self): - """Verify we receive None from find_prefix for missing children.""" - node = trie.TrieNode('E', 'E is for Eat', children={ - 'a': trie.TrieNode('a', 'a is for Apple') - }) - assert node.find_prefix('b') is None - - def test_traverse_does_nothing_when_a_node_has_no_children(self): - """Verify traversing a node with no children does nothing.""" - node = trie.TrieNode('E', 'E is for Eat') - assert list(node.traverse()) == [] - - def test_traverse(self): - """Verify traversal is depth-first and pre-order.""" - root = trie.TrieNode(None, None) - node = root.add_child('A', 'A') - root.add_child('a', 'a') - node.add_child('B', 'B') - node = node.add_child('b', 'b') - node.add_child('C', 'C') - node.add_child('c', 'c') - # The sub-tree here should look something like - # - # - # / \ - # A a - # / | - # B b - # / \ - # C c - # - # And the traversal should look like: - # - # A B b C c a - expected_order = ['A', 'B', 'b', 'C', 'c', 'a'] - for expected, actual_node in zip(expected_order, root.traverse()): - assert actual_node.prefix == expected