Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing plug-ins from vpype --help string #444

Merged
merged 2 commits into from
Apr 2, 2022
Merged
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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ Release date: UNRELEASED

### Bug fixes

* Fixed issue with `forlayer` where the `_n` variable was set improperly (#443)
* Fixed issue with `write` where layer opacity was included in the `stroke` attribute instead of using `stroke-opacity`, which, although compliant, was not compatible with Inkscape (#429)
* Fixed an issue with `forlayer` where the `_n` variable was set improperly (#443)
* Fixed an issue with `write` where layer opacity was included in the `stroke` attribute instead of using `stroke-opacity`, which, although compliant, was not compatible with Inkscape (#429)
* Fixed an issue with `vpype --help` where commands from plug-ins would not be listed (#444)
* Fixed a minor issue where plug-ins would be reloaded each time `vpype_cli.execute()` is called (#444)


### API changes
Expand Down
6 changes: 3 additions & 3 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,11 @@ def test_pagerotate_error(caplog):
doc = vpype_cli.execute("random pagerotate")
assert doc.page_size is None
assert "page size is not defined, page not rotated" in caplog.text


def test_help(runner):
res = runner.invoke(cli, "--help")

assert res.exit_code == 0
assert "Execute the sequence of commands passed in argument." in res.stdout
assert "multipass" in res.stdout
55 changes: 41 additions & 14 deletions vpype_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,13 @@ def parse_args(self, ctx, args):
return args


# noinspection PyUnusedLocal,PyUnresolvedReferences
@click.group(cls=GroupedGroup, chain=True)
_PLUGINS_LOADED = False


# noinspection PyUnusedLocal
@click.group(cls=GroupedGroup, chain=True, invoke_without_command=True)
@click.version_option(version=vp.__version__, message="%(prog)s %(version)s")
@click.option("-h", "--help", "help_flag", is_flag=True, help="Show this message and exit.")
@click.option("-v", "--verbose", count=True)
@click.option("-I", "--include", type=click.Path(), help="Load commands from a command file.")
@click.option(
Expand All @@ -132,7 +136,15 @@ def parse_args(self, ctx, args):
"-c", "--config", type=click.Path(exists=True), help="Load an additional config file."
)
@click.pass_context
def cli(ctx, verbose, include, history, seed, config):
def cli(
ctx: click.Context,
help_flag: bool,
verbose: int,
include: bool,
history: bool,
seed: int,
config: str,
):
"""Execute the sequence of commands passed in argument.

The available commands are listed below. Information on each command may be obtained using:
Expand Down Expand Up @@ -183,15 +195,30 @@ def cli(ctx, verbose, include, history, seed, config):
# 1) Deferred plug-in loading avoid circular import between vpype and vpype_cli when plug-
# in uses deprecated APIs.
# 2) Avoids the PyCharm type error with CliRunner.invoke()
for entry_point in iter_entry_points("vpype.plugins"):
# noinspection PyBroadException
try:
ctx.command.add_command(entry_point.load())
except Exception:
# Catch this so a busted plugin doesn't take down the CLI.
# Handled by registering a dummy command that does nothing
# other than explain the error.
ctx.command.add_command(_BrokenCommand(entry_point.name))
global _PLUGINS_LOADED
if not _PLUGINS_LOADED:
_PLUGINS_LOADED = True
for entry_point in iter_entry_points("vpype.plugins"):
# noinspection PyBroadException
try:
cast(click.Group, ctx.command).add_command(entry_point.load())
except Exception:
# Catch this so a busted plugin doesn't take down the CLI.
# Handled by registering a dummy command that does nothing
# other than explain the error.
cast(click.Group, ctx.command).add_command(_BrokenCommand(entry_point.name))

# Manual handling of the help to work around circular import issues.
# Background: when importing plug-ins in the style of `click-plugin` (decorator, so plug-
# ins are loaded during the loading of `cli` itself), plug-in may not import things from
# `vpype_cli` since it is still partially loaded. Plug-ins are thus loaded when `cli` is
# actually executed (see previous lines). As a result, the Click's default behaviour for
# handling `--help` (i.e. print and exit *before* even executing `cli`) is unable to list
# the plug-ins. This is addressed by manually handling the top-level `--help` parameter
# *after* plug-ins are loaded.
if help_flag:
print(ctx.command.get_help(ctx))
sys.exit(0)

# We use the command string as context object, mainly for the purpose of the `write`
# command. This is a bit of a hack, and will need to be updated if we ever need more state
Expand All @@ -218,9 +245,9 @@ def cli(ctx, verbose, include, history, seed, config):
cli = cast(GroupedGroup, cli)


# noinspection PyShadowingNames,PyUnusedLocal
# noinspection PyUnusedLocal
@cli.result_callback()
def process_pipeline(processors, verbose, include, history, seed, config):
def process_pipeline(processors, help_flag, verbose, include, history, seed, config):
execute_processors(processors, State())


Expand Down