Commit c33e3c68 by Arun Babu Neelicattu

replace entrypoints use with importlib.metadata

parent c1475a0b
...@@ -190,14 +190,6 @@ paramiko = ["paramiko"] ...@@ -190,14 +190,6 @@ paramiko = ["paramiko"]
pgp = ["gpg"] pgp = ["gpg"]
[[package]] [[package]]
name = "entrypoints"
version = "0.4"
description = "Discover and load entry points from installed packages."
category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "execnet" name = "execnet"
version = "1.9.0" version = "1.9.0"
description = "execnet: rapid multi-Python deployment" description = "execnet: rapid multi-Python deployment"
...@@ -787,14 +779,6 @@ optional = false ...@@ -787,14 +779,6 @@ optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]] [[package]]
name = "types-entrypoints"
version = "0.3.7"
description = "Typing stubs for entrypoints"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "types-html5lib" name = "types-html5lib"
version = "1.1.7" version = "1.1.7"
description = "Typing stubs for html5lib" description = "Typing stubs for html5lib"
...@@ -903,7 +887,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- ...@@ -903,7 +887,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.7" python-versions = "^3.7"
content-hash = "0eeafb89a4be53861db33f20d414e84bcf87c4e90a2c7b70ce66e40846d99e02" content-hash = "4c18d27808d5a637e9591ff8444ef9435ffa1fa1df5cdffd5e4fd1c5780547a4"
[metadata.files] [metadata.files]
atomicwrites = [ atomicwrites = [
...@@ -1096,10 +1080,6 @@ dulwich = [ ...@@ -1096,10 +1080,6 @@ dulwich = [
{file = "dulwich-0.20.42-cp39-cp39-win_amd64.whl", hash = "sha256:23922557bc487597ff1a0efc56e4436e275a82837b55e5f733e3e05c873e92b1"}, {file = "dulwich-0.20.42-cp39-cp39-win_amd64.whl", hash = "sha256:23922557bc487597ff1a0efc56e4436e275a82837b55e5f733e3e05c873e92b1"},
{file = "dulwich-0.20.42.tar.gz", hash = "sha256:72ba3b60ae6a554d1332b3b40a345febe16ec469cf6014bb443b719902e33ef0"}, {file = "dulwich-0.20.42.tar.gz", hash = "sha256:72ba3b60ae6a554d1332b3b40a345febe16ec469cf6014bb443b719902e33ef0"},
] ]
entrypoints = [
{file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"},
{file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"},
]
execnet = [ execnet = [
{file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"},
{file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"},
...@@ -1454,10 +1434,6 @@ typed-ast = [ ...@@ -1454,10 +1434,6 @@ typed-ast = [
{file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"},
{file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
] ]
types-entrypoints = [
{file = "types-entrypoints-0.3.7.tar.gz", hash = "sha256:3d002ba32fc2c7fb44f65228fb912969a495cb4aa4ae63e05152f4304bc9bba2"},
{file = "types_entrypoints-0.3.7-py3-none-any.whl", hash = "sha256:06aea9245f25b7b335ef0c3e8e4cc422b1f7c2cc47ae11f9a000a0a15d8ea6aa"},
]
types-html5lib = [ types-html5lib = [
{file = "types-html5lib-1.1.7.tar.gz", hash = "sha256:fdb307102ceea52adf52aea0e10255d142ee29d7f169014144a730707a92066a"}, {file = "types-html5lib-1.1.7.tar.gz", hash = "sha256:fdb307102ceea52adf52aea0e10255d142ee29d7f169014144a730707a92066a"},
{file = "types_html5lib-1.1.7-py3-none-any.whl", hash = "sha256:4bc5a1de03b9a697b7cc04b0d03eeed5d36c0073165dd9dc54f2f43d0f23b31f"}, {file = "types_html5lib-1.1.7-py3-none-any.whl", hash = "sha256:4bc5a1de03b9a697b7cc04b0d03eeed5d36c0073165dd9dc54f2f43d0f23b31f"},
......
...@@ -50,7 +50,6 @@ cachecontrol = { version = "^0.12.9", extras = ["filecache"] } ...@@ -50,7 +50,6 @@ cachecontrol = { version = "^0.12.9", extras = ["filecache"] }
cachy = "^0.3.0" cachy = "^0.3.0"
cleo = "^1.0.0a5" cleo = "^1.0.0a5"
crashtest = "^0.3.0" crashtest = "^0.3.0"
entrypoints = "^0.4"
html5lib = "^1.0" html5lib = "^1.0"
importlib-metadata = { version = "^4.4", python = "<3.10" } importlib-metadata = { version = "^4.4", python = "<3.10" }
# keyring uses calver, so version is unclamped # keyring uses calver, so version is unclamped
...@@ -85,7 +84,6 @@ typing-extensions = { version = "^4.0.0", python = "<3.8" } ...@@ -85,7 +84,6 @@ typing-extensions = { version = "^4.0.0", python = "<3.8" }
zipp = { version = "^3.4", python = "<3.8" } zipp = { version = "^3.4", python = "<3.8" }
flatdict = "^4.0.1" flatdict = "^4.0.1"
mypy = ">=0.960" mypy = ">=0.960"
types-entrypoints = ">=0.3.7"
types-html5lib = ">=1.1.7" types-html5lib = ">=1.1.7"
types-jsonschema = ">=4.4.4" types-jsonschema = ">=4.4.4"
types-requests = ">=2.27.11" types-requests = ">=2.27.11"
...@@ -140,8 +138,10 @@ enable_error_code = [ ...@@ -140,8 +138,10 @@ enable_error_code = [
# warning. # warning.
[[tool.mypy.overrides]] [[tool.mypy.overrides]]
module = [ module = [
'poetry.console.commands.self.show.plugins',
'poetry.installation.executor', 'poetry.installation.executor',
'poetry.mixology.version_solver', 'poetry.mixology.version_solver',
'poetry.plugins.plugin_manager',
'poetry.repositories.installed_repository', 'poetry.repositories.installed_repository',
'poetry.utils.env', 'poetry.utils.env',
] ]
......
...@@ -8,15 +8,32 @@ from poetry.console.commands.self.self_command import SelfCommand ...@@ -8,15 +8,32 @@ from poetry.console.commands.self.self_command import SelfCommand
if TYPE_CHECKING: if TYPE_CHECKING:
from entrypoints import EntryPoint
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.utils._compat import metadata
@dataclasses.dataclass @dataclasses.dataclass
class PluginPackage: class PluginPackage:
package: Package package: Package
plugins: list[EntryPoint] = dataclasses.field(default_factory=list) plugins: list[metadata.EntryPoint] = dataclasses.field(default_factory=list)
application_plugins: list[EntryPoint] = dataclasses.field(default_factory=list) application_plugins: list[metadata.EntryPoint] = dataclasses.field(
default_factory=list
)
def append(self, entry_point: metadata.EntryPoint) -> None:
from poetry.plugins.application_plugin import ApplicationPlugin
from poetry.plugins.plugin import Plugin
group = entry_point.group # type: ignore[attr-defined]
if group == ApplicationPlugin.group:
self.application_plugins.append(entry_point)
elif group == Plugin.group:
self.plugins.append(entry_point)
else:
name = entry_point.name # type: ignore[attr-defined]
raise ValueError(f"Unknown plugin group ({group}) for {name}")
class SelfShowPluginsCommand(SelfCommand): class SelfShowPluginsCommand(SelfCommand):
...@@ -43,9 +60,6 @@ commands respectively. ...@@ -43,9 +60,6 @@ commands respectively.
plugins: dict[str, PluginPackage] = {} plugins: dict[str, PluginPackage] = {}
system_env = EnvManager.get_system_env(naive=True) system_env = EnvManager.get_system_env(naive=True)
entry_points = PluginManager(ApplicationPlugin.group).get_plugin_entry_points(
env=system_env
) + PluginManager(Plugin.group).get_plugin_entry_points(env=system_env)
installed_repository = InstalledRepository.load( installed_repository = InstalledRepository.load(
system_env, with_dependencies=True system_env, with_dependencies=True
) )
...@@ -54,21 +68,20 @@ commands respectively. ...@@ -54,21 +68,20 @@ commands respectively.
pkg.name: pkg for pkg in installed_repository.packages pkg.name: pkg for pkg in installed_repository.packages
} }
for entry_point in entry_points: for group in [ApplicationPlugin.group, Plugin.group]:
plugin = entry_point.load() for entry_point in PluginManager(group).get_plugin_entry_points(
env=system_env
):
assert entry_point.dist is not None
assert entry_point.distro is not None package = packages_by_name[canonicalize_name(entry_point.dist.name)]
package = packages_by_name[canonicalize_name(entry_point.distro.name)]
name = package.pretty_name name = package.pretty_name
info = plugins.get(name) or PluginPackage(package=package)
if issubclass(plugin, ApplicationPlugin): info = plugins.get(name) or PluginPackage(package=package)
info.application_plugins.append(entry_point) info.append(entry_point)
else:
info.plugins.append(entry_point)
plugins[name] = info plugins[name] = info
for name, info in plugins.items(): for name, info in plugins.items():
package = info.package package = info.package
......
from __future__ import annotations from __future__ import annotations
import logging import logging
import sys
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import entrypoints
from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.application_plugin import ApplicationPlugin
from poetry.plugins.plugin import Plugin from poetry.plugins.plugin import Plugin
from poetry.utils._compat import metadata
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -36,16 +34,29 @@ class PluginManager: ...@@ -36,16 +34,29 @@ class PluginManager:
plugin_entrypoints = self.get_plugin_entry_points(env=env) plugin_entrypoints = self.get_plugin_entry_points(env=env)
for entrypoint in plugin_entrypoints: for ep in plugin_entrypoints:
self._load_plugin_entrypoint(entrypoint) self._load_plugin_entry_point(ep)
@staticmethod
def _is_plugin_candidate(ep: metadata.EntryPoint, env: Env | None = None) -> bool:
"""
Helper method to check if given entry point is a valid as a plugin candidate.
When an environment is specified, the entry point's associated distribution
should be installed, and discoverable in the given environment.
"""
return env is None or (
ep.dist is not None
and env.site_packages.find_distribution(ep.dist.name) is not None
)
def get_plugin_entry_points( def get_plugin_entry_points(
self, env: Env | None = None self, env: Env | None = None
) -> list[entrypoints.EntryPoint]: ) -> list[metadata.EntryPoint]:
entry_points: list[entrypoints.EntryPoint] = entrypoints.get_group_all( return [
self._group, path=env.sys_path if env else sys.path ep
) for ep in metadata.entry_points(group=self._group)
return entry_points if self._is_plugin_candidate(ep, env)
]
def add_plugin(self, plugin: Plugin) -> None: def add_plugin(self, plugin: Plugin) -> None:
if not isinstance(plugin, (Plugin, ApplicationPlugin)): if not isinstance(plugin, (Plugin, ApplicationPlugin)):
...@@ -59,10 +70,10 @@ class PluginManager: ...@@ -59,10 +70,10 @@ class PluginManager:
for plugin in self._plugins: for plugin in self._plugins:
plugin.activate(*args, **kwargs) plugin.activate(*args, **kwargs)
def _load_plugin_entrypoint(self, entrypoint: entrypoints.EntryPoint) -> None: def _load_plugin_entry_point(self, ep: metadata.EntryPoint) -> None:
logger.debug(f"Loading the {entrypoint.name} plugin") logger.debug(f"Loading the {ep.name} plugin") # type: ignore[attr-defined]
plugin = entrypoint.load() plugin = ep.load() # type: ignore[no-untyped-call]
if not issubclass(plugin, (Plugin, ApplicationPlugin)): if not issubclass(plugin, (Plugin, ApplicationPlugin)):
raise ValueError( raise ValueError(
......
from __future__ import annotations from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
import pytest import pytest
from entrypoints import Distribution from poetry.core.packages.dependency import Dependency
from entrypoints import EntryPoint as _EntryPoint
from poetry.core.packages.package import Package from poetry.core.packages.package import Package
from poetry.factory import Factory
from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.application_plugin import ApplicationPlugin
from poetry.plugins.plugin import Plugin from poetry.plugins.plugin import Plugin
from poetry.utils._compat import metadata
if TYPE_CHECKING: if TYPE_CHECKING:
from os import PathLike
from cleo.io.io import IO
from cleo.testers.command_tester import CommandTester from cleo.testers.command_tester import CommandTester
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from poetry.plugins.base_plugin import BasePlugin from poetry.plugins.base_plugin import BasePlugin
from poetry.poetry import Poetry
from poetry.repositories import Repository from poetry.repositories import Repository
from poetry.utils.env import Env
from tests.helpers import PoetryTestApplication from tests.helpers import PoetryTestApplication
from tests.types import CommandTesterFactory from tests.types import CommandTesterFactory
class EntryPoint(_EntryPoint): class DoNothingPlugin(Plugin):
def activate(self, poetry: Poetry, io: IO) -> None:
pass
class EntryPoint(metadata.EntryPoint):
def load(self) -> type[BasePlugin]: def load(self) -> type[BasePlugin]:
if "ApplicationPlugin" in self.object_name: if self.group == ApplicationPlugin.group:
return ApplicationPlugin return ApplicationPlugin
return Plugin return DoNothingPlugin
@pytest.fixture() @pytest.fixture()
...@@ -37,49 +49,112 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester: ...@@ -37,49 +49,112 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
@pytest.fixture() @pytest.fixture()
def plugin_package() -> Package: def plugin_package_requires_dist() -> list[str]:
return Package("poetry-plugin", "1.2.3") return []
@pytest.fixture() @pytest.fixture()
def plugin_distro(plugin_package: Package) -> Distribution: def plugin_package(plugin_package_requires_dist: list[str]) -> Package:
return Distribution(plugin_package.name, plugin_package.version.to_string()) package = Package("poetry-plugin", "1.2.3")
for requirement in plugin_package_requires_dist:
package.add_dependency(Dependency.create_from_pep_508(requirement))
@pytest.mark.parametrize("entrypoint_name", ["poetry-plugin", "not-package-name"]) return package
def test_show_displays_installed_plugins(
app: PoetryTestApplication,
tester: CommandTester, @pytest.fixture()
installed: Repository, def plugin_distro(plugin_package: Package, tmp_dir: str) -> metadata.Distribution:
mocker: MockerFixture, class MockDistribution(metadata.Distribution):
plugin_package: Package, def read_text(self, filename: str) -> str | None:
plugin_distro: Distribution, if filename == "METADATA":
entrypoint_name: str, return "\n".join(
): [
mocker.patch( f"Name: {plugin_package.name}",
"entrypoints.get_group_all", f"Version: {plugin_package.version}",
side_effect=[ *[
[ f"Requires-Dist: {dep.to_pep_508()}"
EntryPoint( for dep in plugin_package.requires
entrypoint_name, ],
"poetry_plugin.plugins:ApplicationPlugin", ]
"FirstApplicationPlugin",
distro=plugin_distro,
)
],
[
EntryPoint(
entrypoint_name,
"poetry_plugin.plugins:Plugin",
"FirstPlugin",
distro=plugin_distro,
) )
], return None
],
) def locate_file(self, path: PathLike[str]) -> PathLike[str]:
return Path(tmp_dir, path)
return MockDistribution()
@pytest.fixture
def entry_point_name() -> str:
return "poetry-plugin"
@pytest.fixture
def entry_point_values_by_group() -> dict[str, list[str]]:
return {}
@pytest.fixture
def entry_points(
entry_point_name: str,
entry_point_values_by_group: dict[str, list[str]],
plugin_distro: metadata.Distribution,
) -> Callable[[...], list[metadata.EntryPoint]]:
by_group = {
key: [
EntryPoint(name=entry_point_name, group=key, value=value)._for(
plugin_distro
)
for value in values
]
for key, values in entry_point_values_by_group.items()
}
def _entry_points(**params: Any) -> list[metadata.EntryPoint]:
group = params.get("group")
if group not in by_group:
return []
return by_group.get(group)
return _entry_points
@pytest.fixture(autouse=True)
def mock_metadata_entry_points(
plugin_package: Package,
plugin_distro: metadata.Distribution,
installed: Repository,
mocker: MockerFixture,
tmp_venv: Env,
entry_points: Callable[[...], metadata.EntryPoint],
) -> None:
installed.add_package(plugin_package) installed.add_package(plugin_package)
mocker.patch.object(
tmp_venv.site_packages, "find_distribution", return_value=plugin_distro
)
mocker.patch.object(metadata, "entry_points", entry_points)
@pytest.mark.parametrize("entry_point_name", ["poetry-plugin", "not-package-name"])
@pytest.mark.parametrize(
"entry_point_values_by_group",
[
{
ApplicationPlugin.group: ["FirstApplicationPlugin"],
Plugin.group: ["FirstPlugin"],
}
],
)
def test_show_displays_installed_plugins(
app: PoetryTestApplication,
tester: CommandTester,
):
tester.execute("") tester.execute("")
expected = """ expected = """
...@@ -90,50 +165,22 @@ def test_show_displays_installed_plugins( ...@@ -90,50 +165,22 @@ def test_show_displays_installed_plugins(
assert tester.io.fetch_output() == expected assert tester.io.fetch_output() == expected
@pytest.mark.parametrize(
"entry_point_values_by_group",
[
{
ApplicationPlugin.group: [
"FirstApplicationPlugin",
"SecondApplicationPlugin",
],
Plugin.group: ["FirstPlugin", "SecondPlugin"],
}
],
)
def test_show_displays_installed_plugins_with_multiple_plugins( def test_show_displays_installed_plugins_with_multiple_plugins(
app: PoetryTestApplication, app: PoetryTestApplication,
tester: CommandTester, tester: CommandTester,
installed: Repository,
mocker: MockerFixture,
plugin_package: Package,
plugin_distro: Distribution,
): ):
mocker.patch(
"entrypoints.get_group_all",
side_effect=[
[
EntryPoint(
"poetry-plugin",
"poetry_plugin.plugins:ApplicationPlugin",
"FirstApplicationPlugin",
distro=plugin_distro,
),
EntryPoint(
"poetry-plugin",
"poetry_plugin.plugins:ApplicationPlugin",
"SecondApplicationPlugin",
distro=plugin_distro,
),
],
[
EntryPoint(
"poetry-plugin",
"poetry_plugin.plugins:Plugin",
"FirstPlugin",
distro=plugin_distro,
),
EntryPoint(
"poetry-plugin",
"poetry_plugin.plugins:Plugin",
"SecondPlugin",
distro=plugin_distro,
),
],
],
)
installed.add_package(plugin_package)
tester.execute("") tester.execute("")
expected = """ expected = """
...@@ -144,40 +191,22 @@ def test_show_displays_installed_plugins_with_multiple_plugins( ...@@ -144,40 +191,22 @@ def test_show_displays_installed_plugins_with_multiple_plugins(
assert tester.io.fetch_output() == expected assert tester.io.fetch_output() == expected
@pytest.mark.parametrize(
"plugin_package_requires_dist", [["foo (>=1.2.3)", "bar (<4.5.6)"]]
)
@pytest.mark.parametrize(
"entry_point_values_by_group",
[
{
ApplicationPlugin.group: ["FirstApplicationPlugin"],
Plugin.group: ["FirstPlugin"],
}
],
)
def test_show_displays_installed_plugins_with_dependencies( def test_show_displays_installed_plugins_with_dependencies(
app: PoetryTestApplication, app: PoetryTestApplication,
tester: CommandTester, tester: CommandTester,
installed: Repository,
mocker: MockerFixture,
plugin_package: Package,
plugin_distro: Distribution,
): ):
mocker.patch(
"entrypoints.get_group_all",
side_effect=[
[
EntryPoint(
"poetry-plugin",
"poetry_plugin.plugins:ApplicationPlugin",
"FirstApplicationPlugin",
distro=plugin_distro,
)
],
[
EntryPoint(
"poetry-plugin",
"poetry_plugin.plugins:Plugin",
"FirstPlugin",
distro=plugin_distro,
)
],
],
)
plugin_package.add_dependency(Factory.create_dependency("foo", ">=1.2.3"))
plugin_package.add_dependency(Factory.create_dependency("bar", "<4.5.6"))
installed.add_package(plugin_package)
tester.execute("") tester.execute("")
expected = """ expected = """
......
...@@ -7,11 +7,11 @@ from typing import TYPE_CHECKING ...@@ -7,11 +7,11 @@ from typing import TYPE_CHECKING
import pytest import pytest
from cleo.testers.application_tester import ApplicationTester from cleo.testers.application_tester import ApplicationTester
from entrypoints import EntryPoint
from poetry.console.application import Application from poetry.console.application import Application
from poetry.console.commands.command import Command from poetry.console.commands.command import Command
from poetry.plugins.application_plugin import ApplicationPlugin from poetry.plugins.application_plugin import ApplicationPlugin
from tests.helpers import mock_metadata_entry_points
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -33,16 +33,12 @@ class AddCommandPlugin(ApplicationPlugin): ...@@ -33,16 +33,12 @@ class AddCommandPlugin(ApplicationPlugin):
commands = [FooCommand] commands = [FooCommand]
def test_application_with_plugins(mocker: MockerFixture): @pytest.fixture
mocker.patch( def with_add_command_plugin(mocker: MockerFixture) -> None:
"entrypoints.get_group_all", mock_metadata_entry_points(mocker, AddCommandPlugin)
return_value=[
EntryPoint(
"my-plugin", "tests.console.test_application", "AddCommandPlugin"
)
],
)
def test_application_with_plugins(with_add_command_plugin: None):
app = Application() app = Application()
tester = ApplicationTester(app) tester = ApplicationTester(app)
...@@ -52,16 +48,7 @@ def test_application_with_plugins(mocker: MockerFixture): ...@@ -52,16 +48,7 @@ def test_application_with_plugins(mocker: MockerFixture):
assert tester.status_code == 0 assert tester.status_code == 0
def test_application_with_plugins_disabled(mocker: MockerFixture): def test_application_with_plugins_disabled(with_add_command_plugin: None):
mocker.patch(
"entrypoints.get_group_all",
return_value=[
EntryPoint(
"my-plugin", "tests.console.test_application", "AddCommandPlugin"
)
],
)
app = Application() app = Application()
tester = ApplicationTester(app) tester = ApplicationTester(app)
...@@ -71,16 +58,7 @@ def test_application_with_plugins_disabled(mocker: MockerFixture): ...@@ -71,16 +58,7 @@ def test_application_with_plugins_disabled(mocker: MockerFixture):
assert tester.status_code == 0 assert tester.status_code == 0
def test_application_execute_plugin_command(mocker: MockerFixture): def test_application_execute_plugin_command(with_add_command_plugin: None):
mocker.patch(
"entrypoints.get_group_all",
return_value=[
EntryPoint(
"my-plugin", "tests.console.test_application", "AddCommandPlugin"
)
],
)
app = Application() app = Application()
tester = ApplicationTester(app) tester = ApplicationTester(app)
...@@ -91,17 +69,8 @@ def test_application_execute_plugin_command(mocker: MockerFixture): ...@@ -91,17 +69,8 @@ def test_application_execute_plugin_command(mocker: MockerFixture):
def test_application_execute_plugin_command_with_plugins_disabled( def test_application_execute_plugin_command_with_plugins_disabled(
mocker: MockerFixture, with_add_command_plugin: None,
): ):
mocker.patch(
"entrypoints.get_group_all",
return_value=[
EntryPoint(
"my-plugin", "tests.console.test_application", "AddCommandPlugin"
)
],
)
app = Application() app = Application()
tester = ApplicationTester(app) tester = ApplicationTester(app)
......
...@@ -25,6 +25,7 @@ from poetry.installation.executor import Executor ...@@ -25,6 +25,7 @@ from poetry.installation.executor import Executor
from poetry.packages import Locker from poetry.packages import Locker
from poetry.repositories import Repository from poetry.repositories import Repository
from poetry.repositories.exceptions import PackageNotFound from poetry.repositories.exceptions import PackageNotFound
from poetry.utils._compat import metadata
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -32,6 +33,7 @@ if TYPE_CHECKING: ...@@ -32,6 +33,7 @@ if TYPE_CHECKING:
from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency import Dependency
from poetry.core.semver.version import Version from poetry.core.semver.version import Version
from pytest_mock import MockerFixture
from tomlkit.toml_document import TOMLDocument from tomlkit.toml_document import TOMLDocument
from poetry.installation.operations.operation import Operation from poetry.installation.operations.operation import Operation
...@@ -251,3 +253,31 @@ def isolated_environment( ...@@ -251,3 +253,31 @@ def isolated_environment(
os.environ.clear() os.environ.clear()
os.environ.update(original_environ) os.environ.update(original_environ)
def make_entry_point_from_plugin(
name: str, cls: type[Any], dist: metadata.Distribution | None = None
) -> metadata.EntryPoint:
ep = metadata.EntryPoint(
name=name,
group=getattr(cls, "group", None),
value=f"{cls.__module__}:{cls.__name__}",
)
if dist:
return ep._for(dist)
return ep
def mock_metadata_entry_points(
mocker: MockerFixture,
cls: type[Any],
name: str = "my-plugin",
dist: metadata.Distribution | None = None,
) -> None:
mocker.patch.object(
metadata,
"entry_points",
return_value=[make_entry_point_from_plugin(name, cls, dist)],
)
...@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING ...@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING
import pytest import pytest
from cleo.io.buffered_io import BufferedIO from cleo.io.buffered_io import BufferedIO
from entrypoints import EntryPoint
from poetry.core.packages.project_package import ProjectPackage from poetry.core.packages.project_package import ProjectPackage
from poetry.packages.locker import Locker from poetry.packages.locker import Locker
...@@ -15,6 +14,7 @@ from poetry.plugins import Plugin ...@@ -15,6 +14,7 @@ from poetry.plugins import Plugin
from poetry.plugins.plugin_manager import PluginManager from poetry.plugins.plugin_manager import PluginManager
from poetry.poetry import Poetry from poetry.poetry import Poetry
from tests.compat import Protocol from tests.compat import Protocol
from tests.helpers import mock_metadata_entry_points
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -81,17 +81,9 @@ def test_load_plugins_and_activate( ...@@ -81,17 +81,9 @@ def test_load_plugins_and_activate(
manager_factory: ManagerFactory, manager_factory: ManagerFactory,
poetry: Poetry, poetry: Poetry,
io: BufferedIO, io: BufferedIO,
mocker: MockerFixture, with_my_plugin: None,
): ):
manager = manager_factory() manager = manager_factory()
mocker.patch(
"entrypoints.get_group_all",
return_value=[
EntryPoint("my-plugin", "tests.plugins.test_plugin_manager", "MyPlugin")
],
)
manager.load_plugins() manager.load_plugins()
manager.activate(poetry, io) manager.activate(poetry, io)
...@@ -99,23 +91,24 @@ def test_load_plugins_and_activate( ...@@ -99,23 +91,24 @@ def test_load_plugins_and_activate(
assert io.fetch_output() == "Setting readmes\n" assert io.fetch_output() == "Setting readmes\n"
@pytest.fixture
def with_my_plugin(mocker: MockerFixture) -> None:
mock_metadata_entry_points(mocker, MyPlugin)
@pytest.fixture
def with_invalid_plugin(mocker: MockerFixture) -> None:
mock_metadata_entry_points(mocker, InvalidPlugin)
def test_load_plugins_with_invalid_plugin( def test_load_plugins_with_invalid_plugin(
manager_factory: ManagerFactory, manager_factory: ManagerFactory,
poetry: Poetry, poetry: Poetry,
io: BufferedIO, io: BufferedIO,
mocker: MockerFixture, with_invalid_plugin: None,
): ):
manager = manager_factory() manager = manager_factory()
mocker.patch(
"entrypoints.get_group_all",
return_value=[
EntryPoint(
"my-plugin", "tests.plugins.test_plugin_manager", "InvalidPlugin"
)
],
)
with pytest.raises(ValueError): with pytest.raises(ValueError):
manager.load_plugins() manager.load_plugins()
...@@ -124,15 +117,8 @@ def test_load_plugins_with_plugins_disabled( ...@@ -124,15 +117,8 @@ def test_load_plugins_with_plugins_disabled(
no_plugin_manager: PluginManager, no_plugin_manager: PluginManager,
poetry: Poetry, poetry: Poetry,
io: BufferedIO, io: BufferedIO,
mocker: MockerFixture, with_my_plugin: None,
): ):
mocker.patch(
"entrypoints.get_group_all",
return_value=[
EntryPoint("my-plugin", "tests.plugins.test_plugin_manager", "MyPlugin")
],
)
no_plugin_manager.load_plugins() no_plugin_manager.load_plugins()
assert poetry.package.version.text == "1.2.3" assert poetry.package.version.text == "1.2.3"
......
...@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING ...@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING
import pytest import pytest
from deepdiff import DeepDiff from deepdiff import DeepDiff
from entrypoints import EntryPoint
from poetry.core.semver.helpers import parse_constraint from poetry.core.semver.helpers import parse_constraint
from poetry.core.toml.file import TOMLFile from poetry.core.toml.file import TOMLFile
...@@ -14,6 +13,7 @@ from poetry.factory import Factory ...@@ -14,6 +13,7 @@ from poetry.factory import Factory
from poetry.plugins.plugin import Plugin from poetry.plugins.plugin import Plugin
from poetry.repositories.legacy_repository import LegacyRepository from poetry.repositories.legacy_repository import LegacyRepository
from poetry.repositories.pypi_repository import PyPiRepository from poetry.repositories.pypi_repository import PyPiRepository
from tests.helpers import mock_metadata_entry_points
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -336,10 +336,7 @@ def test_create_poetry_with_local_config(fixture_dir: FixtureDirGetter): ...@@ -336,10 +336,7 @@ def test_create_poetry_with_local_config(fixture_dir: FixtureDirGetter):
def test_create_poetry_with_plugins(mocker: MockerFixture): def test_create_poetry_with_plugins(mocker: MockerFixture):
mocker.patch( mock_metadata_entry_points(mocker, MyPlugin)
"entrypoints.get_group_all",
return_value=[EntryPoint("my-plugin", "tests.test_factory", "MyPlugin")],
)
poetry = Factory().create_poetry(fixtures_dir / "sample_project") poetry = Factory().create_poetry(fixtures_dir / "sample_project")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment