Skip to content
Open
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
2 changes: 1 addition & 1 deletion invoke/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def complete_context(self) -> None:
if self.context and self.context.missing_positional_args:
err = "'{}' did not receive required positional arguments: {}"
names = ", ".join(
"'{}'".format(x.name)
"'{}'".format(x.names[0])
for x in self.context.missing_positional_args
)
self.error(err.format(self.context.name, names))
Expand Down
2 changes: 2 additions & 0 deletions sites/www/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Changelog
=========

- :bug:`1017` Report missing required arguments using their command-line
names instead of their Python attribute names. Patch by ``@Hugohong258``.
- :release:`2.2.1 <2025-10-10>`
- :release:`2.1.4 <2025-10-10>`
- :bug:`1038` (fixed in :issue:`1040`) Python 3.14 tweaked the behavior of
Expand Down
27 changes: 26 additions & 1 deletion tests/parser_parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pytest import raises
from pytest import raises, mark

from invoke.parser import Parser, Context, Argument, ParseError

Expand Down Expand Up @@ -188,6 +188,31 @@ def attached_context_is_None_outside_contexts(self):
assert e.context is None

class positional_arguments:
@mark.parametrize(
"cli_name,attr_name",
[
("param-1", "param_1"),
("param_1", None),
("public-name", "internal_name"),
],
)
def omitted_positionals_report_cli_names(
self, cli_name, attr_name
):
arg = Argument(
names=(cli_name, "p"),
attr_name=attr_name,
positional=True,
)
context = Context("mytask", args=[arg])
with raises(ParseError) as error:
Parser([context]).parse_argv(["mytask"])
expected = (
"'mytask' did not receive required positional arguments: "
"'{}'".format(cli_name)
)
assert str(error.value) == expected

def _basic(self):
arg = Argument("pos", positional=True)
mytask = Context(name="mytask", args=[arg])
Expand Down