mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-10 06:44:18 +00:00
Emit an error when entry points are duplicated
This avoids flake8 silently ignoring one of the plugins and fixes https://gitlab.com/pycqa/flake8/-/issues/634.
This commit is contained in:
parent
03c7dd3a8d
commit
acced5f62a
4 changed files with 52 additions and 0 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
"""Exception classes for all of Flake8."""
|
"""Exception classes for all of Flake8."""
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
if False: # `typing.TYPE_CHECKING` was introduced in 3.5.2
|
||||||
|
from flake8.plugins.manager import Plugin
|
||||||
|
from flake8._compat import importlib_metadata
|
||||||
|
|
||||||
|
|
||||||
class Flake8Exception(Exception):
|
class Flake8Exception(Exception):
|
||||||
"""Plain Flake8 exception."""
|
"""Plain Flake8 exception."""
|
||||||
|
|
@ -14,6 +18,33 @@ class ExecutionError(Flake8Exception):
|
||||||
"""Exception raised during execution of Flake8."""
|
"""Exception raised during execution of Flake8."""
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicatePluginEntryPoint(Flake8Exception):
|
||||||
|
"""Exception raised when a plugin entry point is already taken."""
|
||||||
|
|
||||||
|
FORMAT = (
|
||||||
|
'Plugin entry point "%(entry_point)s" for "%(new)s" already taken by '
|
||||||
|
'"%(existing)s"'
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, entry_point, existing_plugin):
|
||||||
|
# type: (importlib_metadata.EntryPoint, Plugin) -> None
|
||||||
|
"""Initialize our DuplicatePluginEntryPoint exception."""
|
||||||
|
self.entry_point = entry_point
|
||||||
|
self.existing_plugin = existing_plugin
|
||||||
|
super(DuplicatePluginEntryPoint, self).__init__(
|
||||||
|
entry_point,
|
||||||
|
existing_plugin,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self): # type: () -> str
|
||||||
|
"""Format our exception message."""
|
||||||
|
return self.FORMAT % {
|
||||||
|
"entry_point": self.entry_point.name,
|
||||||
|
"new": self.entry_point.value,
|
||||||
|
"existing": self.existing_plugin.entry_point.value,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class FailedToLoadPlugin(Flake8Exception):
|
class FailedToLoadPlugin(Flake8Exception):
|
||||||
"""Exception raised when a plugin fails to load."""
|
"""Exception raised when a plugin fails to load."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,12 @@ class PluginManager(object): # pylint: disable=too-few-public-methods
|
||||||
Is this a repo-local plugin?
|
Is this a repo-local plugin?
|
||||||
"""
|
"""
|
||||||
name = entry_point.name
|
name = entry_point.name
|
||||||
|
|
||||||
|
if name in self.plugins:
|
||||||
|
raise exceptions.DuplicatePluginEntryPoint(
|
||||||
|
entry_point, self.plugins[name],
|
||||||
|
)
|
||||||
|
|
||||||
self.plugins[name] = Plugin(name, entry_point, local=local)
|
self.plugins[name] = Plugin(name, entry_point, local=local)
|
||||||
self.names.append(name)
|
self.names.append(name)
|
||||||
LOG.debug('Loaded %r for plugin "%s".', self.plugins[name], name)
|
LOG.debug('Loaded %r for plugin "%s".', self.plugins[name], name)
|
||||||
|
|
|
||||||
4
tests/fixtures/config_files/local-plugin-duplicate-entry-point.ini
vendored
Normal file
4
tests/fixtures/config_files/local-plugin-duplicate-entry-point.ini
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
[flake8:local-plugins]
|
||||||
|
extension =
|
||||||
|
XE = aplugin:ExtensionTestPluginA
|
||||||
|
XE = aplugin:ExtensionTestPluginB
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
"""Integration tests for plugin loading."""
|
"""Integration tests for plugin loading."""
|
||||||
|
import pytest
|
||||||
|
|
||||||
from flake8.main import application
|
from flake8.main import application
|
||||||
|
from flake8 import exceptions
|
||||||
|
|
||||||
|
|
||||||
LOCAL_PLUGIN_CONFIG = 'tests/fixtures/config_files/local-plugin.ini'
|
LOCAL_PLUGIN_CONFIG = 'tests/fixtures/config_files/local-plugin.ini'
|
||||||
LOCAL_PLUGIN_PATH_CONFIG = 'tests/fixtures/config_files/local-plugin-path.ini'
|
LOCAL_PLUGIN_PATH_CONFIG = 'tests/fixtures/config_files/local-plugin-path.ini'
|
||||||
|
LOCAL_PLUGIN_DUPLICATE_CONFIG = 'tests/fixtures/config_files/local-plugin-duplicate-entry-point.ini'
|
||||||
|
|
||||||
|
|
||||||
class ExtensionTestPlugin(object):
|
class ExtensionTestPlugin(object):
|
||||||
|
|
@ -61,3 +65,10 @@ def test_enable_local_plugin_at_non_installed_path():
|
||||||
app.initialize(['flake8', '--config', LOCAL_PLUGIN_PATH_CONFIG])
|
app.initialize(['flake8', '--config', LOCAL_PLUGIN_PATH_CONFIG])
|
||||||
|
|
||||||
assert app.check_plugins['XE'].plugin.name == 'ExtensionTestPlugin2'
|
assert app.check_plugins['XE'].plugin.name == 'ExtensionTestPlugin2'
|
||||||
|
|
||||||
|
|
||||||
|
def test_reject_local_plugins_with_duplicate_entry_point():
|
||||||
|
"""Reject duplicate entry points in local-plugins config section."""
|
||||||
|
with pytest.raises(exceptions.DuplicatePluginEntryPoint):
|
||||||
|
app = application.Application()
|
||||||
|
app.initialize(['flake8', '--config', LOCAL_PLUGIN_DUPLICATE_CONFIG])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue