[issue43413] tuple subclasses allow kwargs

2021-03-06 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

> Hmm, but in my experience, tuple on Python 3.6 doesn't take keyword arguments 
> either:

They do.

>>> tuple(sequence='abc')
('a', 'b', 'c')

>>> list(sequence='abc')
['a', 'b', 'c']
>>> int(x='123')
123
>>> bool(x='123')
True
>>> float(x='123')
123.0

It was changed in bpo-29695.

But accepting arbitrary keyword arguments is another issue.

Object creation in Python can be customized be implementing special methods 
__new__ and __init__. They both are called sequentially with arguments passed 
to the constructor. If object is mutable, it is enough to implement __init__. 
If the object contains immutable data which should be initialized at creation 
time, it needs __new__, and __init__ is not necessary. So the list class has 
__init__, but the tuple and int classes have __new__. Usually class implements 
only one of __new__ or __init__, and inherits the other one from parent classes.

Since positional and keyword arguments are passed to both __new__ and __init__, 
they should accept same arguments. If __new__ and __init__ are inherited from 
parent class, they cannot know about arguments supported in the other method. 
Therefore object's __new__ and __init__ accept and ignore all arguments (if the 
other method is overridden).

Implementations of __new__ for most builtin classes which accept only 
positional arguments accept and ignore also arbitrary keyword arguments in 
subclasses. It makes easier to implement a subclass with non-trivial __init__. 
You just add additional keyword arguments which will be ignored in __new__. It 
is long tradition. Example:

if (type == _type && !_PyArg_NoKeywords("cycle()", kwds))
return NULL;

bpo-20186 just used this idiom for tuple and several other classes. It is a 
feature which makes subclassing these classes easier. And with converting more 
classes to Argument Clinic it is now used in more and more classes.

Now, perhaps it would be more correct to test `type->tp_init == 
cycle_type.tp_init` or `type->tp_init != PyBaseObject_Type.tp_init` instead of 
`type == _type`. It will ignore keyword arguments only if __init__ is 
overridden. If __init__ is overridden, it is now responsible for validating 
arguments.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43413] tuple subclasses allow kwargs

2021-03-05 Thread Raymond Hettinger


Change by Raymond Hettinger :


--
nosy: +serhiy.storchaka

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43413] tuple subclasses allow kwargs

2021-03-05 Thread Jason R. Coombs


Jason R. Coombs  added the comment:

In particular, [this 
commit](https://github.com/python/cpython/commit/0b5615926a573c19c887a701a2f7047f4fd06de6).

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43413] tuple subclasses allow kwargs

2021-03-05 Thread Jason R. Coombs


Jason R. Coombs  added the comment:

I suspect bpo-20186 is implicated.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43413] tuple subclasses allow kwargs

2021-03-05 Thread Jason R. Coombs


Jason R. Coombs  added the comment:

I see that changelog entry traces back to bpo-29695, but I don't believe it's 
relevant to this issue.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43413] tuple subclasses allow kwargs

2021-03-05 Thread Jason R. Coombs


Jason R. Coombs  added the comment:

To be abundantly clear, the downstream issue was a coding error, but the coding 
error was masked on Python 3.7+ when the subclass didn't reject the invalid 
usage.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue43413] tuple subclasses allow kwargs

2021-03-05 Thread Jason R. Coombs


New submission from Jason R. Coombs :

While troubleshooting a strange problem 
(https://github.com/jaraco/keyring/issues/498) where a program worked on Python 
3.7+ but failed on Python 3.6, I discovered a somewhat unintuitive behavior. On 
Python 3.7+, keyword arguments to tuple subclasses are allowed and ignored:

>>> class Foo(tuple): pass
>>> tuple(name='xyz')
TypeError: tuple() takes no keyword arguments
>>> Foo(name='xyz')
()

But on Python 3.6, the keyword parameter causes an error:

$ python3.6 -c "type('Foo', (tuple,), {})(name='xyz')"
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'name' is an invalid keyword argument for this function

I checked out the What's new in Python 3.7 and I see this notice:

Functions bool(), float(), list() and tuple() no longer take keyword arguments. 
The first argument of int() can now be passed only as positional argument.

Hmm, but in my experience, tuple on Python 3.6 doesn't take keyword arguments 
either:

importlib_metadata main $ python3.6 -c "tuple(name='xyz')"
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'name' is an invalid keyword argument for this function


So that change may be related, but I'm not sure where or how.

The main place my expectation is violated is in the subclass. Why should a 
subclass of tuple allow keyword arguments when the parent class does not? I'd 
expect that the subclass should reject keyword arguments as well.

Less importantly, the What's New doc implies that keyword arguments were 
accepted in Python 3.6; why aren't they?

--
components: Interpreter Core
keywords: 3.7regression
messages: 388183
nosy: jaraco
priority: normal
severity: normal
status: open
title: tuple subclasses allow kwargs
versions: Python 3.10, Python 3.7, Python 3.8, Python 3.9

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com