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

Disallow iterable argument unpacking after a keyword argument? #82741

Closed
brandtbucher opened this issue Oct 23, 2019 · 7 comments
Closed

Disallow iterable argument unpacking after a keyword argument? #82741

brandtbucher opened this issue Oct 23, 2019 · 7 comments
Labels
3.9 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@brandtbucher
Copy link
Member

BPO 38560
Nosy @gvanrossum, @rhettinger, @MojoVampire, @brandtbucher

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2019-10-29.17:28:43.417>
created_at = <Date 2019-10-23.00:20:42.309>
labels = ['interpreter-core', 'type-bug', 'invalid', '3.9']
title = 'Disallow iterable argument unpacking after a keyword argument?'
updated_at = <Date 2019-10-29.17:28:43.413>
user = 'https://github.com/brandtbucher'

bugs.python.org fields:

activity = <Date 2019-10-29.17:28:43.413>
actor = 'gvanrossum'
assignee = 'none'
closed = True
closed_date = <Date 2019-10-29.17:28:43.417>
closer = 'gvanrossum'
components = ['Interpreter Core']
creation = <Date 2019-10-23.00:20:42.309>
creator = 'brandtbucher'
dependencies = []
files = []
hgrepos = []
issue_num = 38560
keywords = []
message_count = 6.0
messages = ['355195', '355251', '355267', '355658', '355660', '355663']
nosy_count = 4.0
nosy_names = ['gvanrossum', 'rhettinger', 'josh.r', 'brandtbucher']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue38560'
versions = ['Python 3.9']

@brandtbucher
Copy link
Member Author

Calls of the form f(name=value, *args) are currently legal syntax. The resulting argument binding is awkward, and almost never does what you want/expect it to:

>>> def f(x, y, z):
...     print(x, y, z)
... 

>>> f(x=0, *(1, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for argument 'x'

>>> f(y=0, *(1, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for argument 'y'

>>> f(z=0, *(1, 2))
1 2 0

I'm not sure if this is intentional, or an oversight. Every other way of passing positional arguments after keyword arguments results in an error:

f(kwarg=kwarg, arg)  # SyntaxError: positional argument follows keyword argument
f(**kwargs, arg)     # SyntaxError: positional argument follows keyword argument unpacking
f(**kwargs, *args)   # SyntaxError: iterable argument unpacking follows keyword argument unpacking

I think this case should raise a "SyntaxError: iterable argument unpacking follows keyword argument".

I'd like to work on this if we believe it should be changed.

@brandtbucher brandtbucher added 3.9 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error labels Oct 23, 2019
@MojoVampire
Copy link
Mannequin

MojoVampire mannequin commented Oct 23, 2019

I'd be +1 on this, but I'm worried about existing code relying on the functional use case from your example.

If we are going to discourage it, I think we either have to:

  1. Have DeprecationWarning that turns into a SyntaxError, or
  2. Never truly remove it, but make it a SyntaxWarning immediately and leave it that way indefinitely

@brandtbucher
Copy link
Member Author

I've found one occurrence of this in the CPython codebase, in test_ast.py. Basically it makes sure that the following expression parses and compiles correctly:

f(1,2,c=3,*d,**e)

I doubt that this is to protect against regressions in this specific syntax. More likely it's just trying to create as many of the different argument passing AST nodes as possible in one call (it's the only test for function calls with arguments). It can probably be slightly refactored:

f(1,2,*c,d=3,**e)

@brandtbucher
Copy link
Member Author

I’ve thought about it and I’m +1 on DeprecationWarning in 3.9 and SyntaxError in 3.10.

Removing any type of legal function call is tricky, but this is such obscure, sneaky syntax that it’s likely an accident/bug if it does pop up (that’s how I discovered it). And every instance can be trivially refactored.

@brandtbucher brandtbucher changed the title Allow iterable argument unpacking after a keyword argument? Disallow iterable argument unpacking after a keyword argument? Oct 29, 2019
@rhettinger
Copy link
Contributor

Changes to the grammar of the language need to be discussed on python-dev (especially ones that can break existing code and ones that change syntax that has worked for many years). Arguably, this is something that should just go into a lint tool.

@gvanrossum
Copy link
Member

Well, as you point out, f(z=0, *(1, 2)) is legal, and the parser doesn't know what the names of the keyword arguments are. SO this cannot be changed.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
ccostino added a commit to GSA/notifications-admin that referenced this issue Nov 28, 2023
The new release of flake8-bugbear is starting to flag positional argument unpacking that comes after keyword arguments in function calls as a style warning that fails.  This is a good thing to catch because it can lead to unexpected side effects with function arguments and/or errors thrown by Python.

See the following links for more details:

- https://stackoverflow.com/questions/58961715/python-value-unpacking-order-in-method-parameters
- python/cpython#82741

This changeset fixes a couple of instances where the positional argument unpacking was happening after keyword arguments were being provided.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
ccostino added a commit to GSA/notifications-admin that referenced this issue Nov 29, 2023
The new release of flake8-bugbear is starting to flag positional argument unpacking that comes after keyword arguments in function calls as a style warning that fails.  This is a good thing to catch because it can lead to unexpected side effects with function arguments and/or errors thrown by Python.

See the following links for more details:

- https://stackoverflow.com/questions/58961715/python-value-unpacking-order-in-method-parameters
- python/cpython#82741

This changeset fixes a couple of instances where the positional argument unpacking was happening after keyword arguments were being provided.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
@konflic

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.9 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants