Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 5 additions & 17 deletions keg/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
38 changes: 37 additions & 1 deletion keg/tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down