From 6a1ddb19c0c331ee400e1d4d9125b0549cb9c6a9 Mon Sep 17 00:00:00 2001 From: Mirochill <200482516+Mirochill@users.noreply.github.com> Date: Mon, 25 May 2026 21:59:44 +0200 Subject: [PATCH] Drop pkg_resources CLI plugin loading --- keg/cli.py | 22 +++++----------------- keg/tests/test_cli.py | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/keg/cli.py b/keg/cli.py index 3aa4f58..874a868 100644 --- a/keg/cli.py +++ b/keg/cli.py @@ -37,28 +37,16 @@ def __init__(self, create_app, add_default_commands=True, load_dotenv=True, *arg def _load_plugin_commands(self): if self._loaded_plugin_commands: return - entry_point_iterables = [] - # older Flask try: - import pkg_resources - entry_point_iterables.extend([ - pkg_resources.iter_entry_points('flask.commands'), - pkg_resources.iter_entry_points('keg.commands'), - ]) + from flask.cli import metadata except ImportError: return - # newer Flask - try: - # uses importlib, but python has some API variations. Let flask handle that. - from flask.cli import metadata - entry_point_iterables.extend([ - metadata.entry_points(group="flask.commands"), - metadata.entry_points(group="keg.commands"), - ]) - except ImportError: - pass + entry_point_iterables = [ + metadata.entry_points(group="flask.commands"), + metadata.entry_points(group="keg.commands"), + ] for ep in chain.from_iterable(entry_point_iterables): self.add_command(ep.load(), ep.name) diff --git a/keg/tests/test_cli.py b/keg/tests/test_cli.py index 6fa051e..141790d 100644 --- a/keg/tests/test_cli.py +++ b/keg/tests/test_cli.py @@ -1,9 +1,15 @@ import os from unittest import mock +import click import pytest -from keg.cli import dotenv, get_load_dotenv +try: + from flask.cli import metadata as flask_cli_metadata +except ImportError: + flask_cli_metadata = None + +from keg.cli import KegAppGroup, dotenv, get_load_dotenv from keg.testing import CLIBase, app_config from keg_apps.cli import CLIApp from keg_apps.cli2.app import CLI2App @@ -19,6 +25,36 @@ class TestCLI(CLIBase): app_cls = CLIApp cmd_name = 'hello' + @pytest.mark.skipif(flask_cli_metadata is None, reason='Flask CLI metadata not supported') + def test_load_plugin_commands_with_flask_metadata(self): + @click.command('plugin') + def plugin_command(): + pass + + class EntryPoint: + name = 'plugin' + + def load(self): + return plugin_command + + def entry_points(group): + if group == 'keg.commands': + return [EntryPoint()] + return [] + + app_group = KegAppGroup(lambda: None, add_default_commands=False) + + with mock.patch( + 'flask.cli.metadata.entry_points', side_effect=entry_points + ) as m_entry_points: + app_group._load_plugin_commands() + + assert app_group.commands['plugin'] is plugin_command + assert [call.kwargs['group'] for call in m_entry_points.call_args_list] == [ + 'flask.commands', + 'keg.commands', + ] + def test_class_command(self): result = self.invoke() assert 'hello keg test' in result.output