Conversation
Previously, plugin-specific options like `--interactive` had to come after `--how` on the command line. For example: ``` tmt run execute --interactive -h tmt # failed tmt run execute -h tmt --interactive # worked ``` The root cause was in `_find_how()` which scans CLI args to locate `--how`. When encountering an unknown option (not in the base command params), it gave up immediately. Plugin-specific options are only registered on method subcommands, not the base command. Fix `_find_option_by_arg()` to also search params across all plugin method commands. When the same short option appears in multiple plugins with different `nargs`, the match consuming the most arguments is used conservatively. This is safe because `_find_how()` operates on a copy of args and Click re-parses the original args for actual option handling. The worst case is `_find_how()` returning `None` — identical to the current behavior. Assisted-by: Claude Code Signed-off-by: Miroslav Vadkerti <mvadkert@redhat.com>
| if result.exit_code != 0: | ||
| assert 'No such option' not in result.output |
|
I don't think it's that easy. Consider the following example: diff --git a/tmt/steps/report/html.py b/tmt/steps/report/html.py
index 1480d047..7d4898a6 100644
--- a/tmt/steps/report/html.py
+++ b/tmt/steps/report/html.py
@@ -52,6 +52,12 @@ class ReportHtmlData(tmt.steps.report.ReportStepData):
""",
)
+ baz: int = field(
+ option='--baz',
+ is_flag=True,
+ default=False,
+ )
+
@tmt.steps.provides_method('html')
class ReportHtml(tmt.steps.report.ReportPlugin[ReportHtmlData]):
diff --git a/tmt/steps/report/junit.py b/tmt/steps/report/junit.py
index c16e6294..09f73226 100644
--- a/tmt/steps/report/junit.py
+++ b/tmt/steps/report/junit.py
@@ -491,6 +491,11 @@ class ReportJUnitData(tmt.steps.report.ReportStepData):
help='Include full standard output in resulting xml file.',
)
+ baz: str = field(
+ option='--baz',
+ default='quack',
+ )
+
@tmt.steps.provides_method(
'junit',Two plugins, both define same key and option, but one plugin requires a value while the other treats it as a flag. Then: IIUIC, new process selected What is the use case, BTW? The PR description seems to me as if the current behavior would be a bug ("The root cause was ..."). |
|
@happz I thought so ... well, I got hit by it while manually testing and seems not properly documeted as a known behaviour (although the cmdline examples of course are correct) . So maybe I can just document it more ... |
|
One possible improvement: does tmt really need to consume the options? All it tries to do is finding def _find_how(args: list[str]) -> Optional[str]:
while args:
arg = args.pop(0)
# Handle '--how method' or '-h method'
if arg in ['--how', '-h']:
# Found `-h/--how foo`, next argument is how'
return args.pop(0)
# Handle '--how=method'
if arg.startswith('--how='):
return re.sub('^--how=', '', arg)
# Handle '-hmethod'
if arg.startswith('-h'):
return re.sub('^-h ?', '', arg)
return None |
Previously, plugin-specific options like
--interactivehad to come after--howon the command line. For example:The root cause was in
_find_how()which scans CLI args to locate--how. When encountering an unknown option (not in the base command params), it gave up immediately. Plugin-specific options are only registered on method subcommands, not the base command.Fix
_find_option_by_arg()to also search params across all plugin method commands. When the same short option appears in multiple plugins with differentnargs, the match consuming the most arguments is used conservatively.This is safe because
_find_how()operates on a copy of args and Click re-parses the original args for actual option handling. The worst case is_find_how()returningNone— identical to the current behavior.Generated-by: Claude Code
Pull Request Checklist