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

Positional-only argument containing = is considered named argument if keyword accepts **named #5094

Open
pekkaklarck opened this issue Mar 25, 2024 · 1 comment

Comments

@pekkaklarck
Copy link
Member

If a keyword accepts a positional only argument like

def example(arg, /):
    print(arg)

using it like

Example    foo=bar
Example    arg=xxx

works fine and the keyword gets foo=bar and arg=xxx as an argument, respectively. The argument is positional-only so = has no special meaning.

If the keyword also accepts free named arguments like

def example(arg, /, **named):
    print(arg, named)

using it like

Example    foo=bar

fails like

Keyword 'example.Example' expected 1 non-named argument, got 0.

This is due to a bug in argument resolving logic where all arguments containing = are considered named if the keyword accepts free named arguments. This needs to be fixed so that positional-only arguments are excluded.

After the fix we can fix #4821 by changing the signature of the Format String keyword to template, /, *positional, **named. We also should check are there other keywords accepting **named that could get the same treatment.

@pekkaklarck
Copy link
Member Author

It seems that the following change is enough to fix this, but the this needs to be tested more thoroughly:

--- a/src/robot/running/arguments/argumentresolver.py
+++ b/src/robot/running/arguments/argumentresolver.py
@@ -56,9 +56,10 @@ class NamedArgumentResolver:
 
     def resolve(self, arguments, variables=None):
         spec = self.spec
-        positional = list(arguments[:len(spec.embedded)])
+        positional_count = max(len(spec.positional_only), len(spec.embedded))
+        positional = list(arguments[:positional_count])
         named = []
-        for arg in arguments[len(spec.embedded):]:
+        for arg in arguments[positional_count:]:
             if is_dict_variable(arg):
                 named.append(arg)
             else:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant