From 3d253e07f3f33e7897d39336c26d2c6cd2b2d0cd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 30 Mar 2021 17:17:58 -0400 Subject: [PATCH] Rely on backports.entry_points_selectable for forward compatibility with importlib.metadata. --- setup.cfg | 3 ++- src/flake8/plugins/manager.py | 4 +++- tests/integration/test_checker.py | 5 ++--- tests/unit/test_plugin_manager.py | 36 ++++++++++++++----------------- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/setup.cfg b/setup.cfg index 9103522..2722991 100644 --- a/setup.cfg +++ b/setup.cfg @@ -48,7 +48,8 @@ install_requires= typing; python_version<"3.5" configparser; python_version<"3.2" functools32; python_version<"3.2" - importlib-metadata; python_version<"3.8" + importlib_metadata; python_version<"3.8" + backports.entry_points_selectable >= 1.0.2 python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* diff --git a/src/flake8/plugins/manager.py b/src/flake8/plugins/manager.py index abfd14b..98b0bb0 100644 --- a/src/flake8/plugins/manager.py +++ b/src/flake8/plugins/manager.py @@ -2,6 +2,8 @@ import logging from typing import Any, Dict, List, Optional, Set +from backports.entry_points_selectable import entry_points + from flake8 import exceptions from flake8 import utils from flake8._compat import importlib_metadata @@ -251,7 +253,7 @@ class PluginManager(object): # pylint: disable=too-few-public-methods def _load_entrypoint_plugins(self): LOG.info('Loading entry-points for "%s".', self.namespace) - eps = importlib_metadata.entry_points().get(self.namespace, ()) + eps = entry_points(group=self.namespace) # python2.7 occasionally gives duplicate results due to redundant # `local/lib` -> `../lib` symlink on linux in virtualenvs so we # eliminate duplicates here diff --git a/tests/integration/test_checker.py b/tests/integration/test_checker.py index 836b543..97c38ce 100644 --- a/tests/integration/test_checker.py +++ b/tests/integration/test_checker.py @@ -3,7 +3,6 @@ import mock import pytest from flake8 import checker -from flake8._compat import importlib_metadata from flake8.plugins import manager from flake8.processor import FileProcessor @@ -104,9 +103,9 @@ def mock_file_checker_with_plugin(plugin_target): # Load the checker plugins using the entry point mock with mock.patch.object( - importlib_metadata, + manager, 'entry_points', - return_value={'flake8.extension': [entry_point]}, + return_value=[entry_point], ): checks = manager.Checkers() diff --git a/tests/unit/test_plugin_manager.py b/tests/unit/test_plugin_manager.py index 9ad6aba..872bf83 100644 --- a/tests/unit/test_plugin_manager.py +++ b/tests/unit/test_plugin_manager.py @@ -5,51 +5,47 @@ from flake8._compat import importlib_metadata from flake8.plugins import manager -@mock.patch.object(importlib_metadata, 'entry_points') +@mock.patch.object(manager, 'entry_points') def test_calls_entrypoints_on_instantiation(entry_points_mck): """Verify that we call entry_points() when we create a manager.""" - entry_points_mck.return_value = {} + entry_points_mck.return_value = [] manager.PluginManager(namespace='testing.entrypoints') - entry_points_mck.assert_called_once_with() + entry_points_mck.assert_called_once_with(group='testing.entrypoints') -@mock.patch.object(importlib_metadata, 'entry_points') +@mock.patch.object(manager, 'entry_points') def test_calls_entrypoints_creates_plugins_automaticaly(entry_points_mck): """Verify that we create Plugins on instantiation.""" - entry_points_mck.return_value = { - 'testing.entrypoints': [ - importlib_metadata.EntryPoint('T100', '', None), - importlib_metadata.EntryPoint('T200', '', None), - ], - } + entry_points_mck.return_value = [ + importlib_metadata.EntryPoint('T100', '', None), + importlib_metadata.EntryPoint('T200', '', None), + ] plugin_mgr = manager.PluginManager(namespace='testing.entrypoints') - entry_points_mck.assert_called_once_with() + entry_points_mck.assert_called_once_with(group='testing.entrypoints') assert 'T100' in plugin_mgr.plugins assert 'T200' in plugin_mgr.plugins assert isinstance(plugin_mgr.plugins['T100'], manager.Plugin) assert isinstance(plugin_mgr.plugins['T200'], manager.Plugin) -@mock.patch.object(importlib_metadata, 'entry_points') +@mock.patch.object(manager, 'entry_points') def test_handles_mapping_functions_across_plugins(entry_points_mck): """Verify we can use the PluginManager call functions on all plugins.""" - entry_points_mck.return_value = { - 'testing.entrypoints': [ - importlib_metadata.EntryPoint('T100', '', None), - importlib_metadata.EntryPoint('T200', '', None), - ], - } + entry_points_mck.return_value = [ + importlib_metadata.EntryPoint('T100', '', None), + importlib_metadata.EntryPoint('T200', '', None), + ] plugin_mgr = manager.PluginManager(namespace='testing.entrypoints') plugins = [plugin_mgr.plugins[name] for name in plugin_mgr.names] assert list(plugin_mgr.map(lambda x: x)) == plugins -@mock.patch.object(importlib_metadata, 'entry_points') +@mock.patch.object(manager, 'entry_points') def test_local_plugins(entry_points_mck): """Verify PluginManager can load given local plugins.""" - entry_points_mck.return_value = {} + entry_points_mck.return_value = [] plugin_mgr = manager.PluginManager( namespace='testing.entrypoints', local_plugins=['X = path.to:Plugin']