You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Type expression is coerced to a list of parameter arguments in substitution of ParamSpec #88964
bpo-44793: Arguments ignored in substitution in typing.Callable
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=Noneclosed_at=<Date2021-08-04.21:00:34.993>created_at=<Date2021-08-01.07:08:58.391>labels= ['type-bug', 'library', '3.10', '3.11']
title='Type expression is coerced to a list of parameter arguments in substitution of ParamSpec'updated_at=<Date2021-08-04.21:00:34.992>user='https://github.com/serhiy-storchaka'
Because __args__ *must* be hashable and immutable. Otherwise, it will not work with Union or Literal. Some time ago we tried converting to nested tuple. But that was too difficult (and backwards incompatible) because every other typing operation expected __args__ to contain types, not a tuple.
Thank you Ken Jin. So the problem is the __args__ (x, str) is interpreted differently depending on x, and after substituting x the interpretation can be changed. If x was ParamSpec, it was interpreted in one way, but if it becomes int, it is now interpreted in other way.
The solution is to forbid substitution of P with wrong values (not parameters expression). Some normalization is also needed, before and after substitution.
Other related example is:
>>> from typing import*
>>> P = ParamSpec("P")
>>> classZ(Generic[P]): pass
...
>>> A = Z[[int]]
>>> B = Z[int]
>>> A
__main__.Z[(<class 'int'>,)]
>>> B
__main__.Z[int]
>>> A.__args__
((<class 'int'>,),)
>>> B.__args__
(<class 'int'>,)
Activity
serhiy-storchaka commentedon Aug 1, 2021
Type expression is coerced to a list of parameter arguments in substitution of ParamSpec. For example:
int becomes [int]. There is even a dedicated test for this.
But it is not followed from PEP-612. Furthermore, it contradicts one of examples in the PEP:
It makes the implementation (at least the code in bpo-44796) more complex and makes the user code more errorprone.
Fidget-Spinner commentedon Aug 1, 2021
It's not, only the repr is like that. Internally it's not coerced.
Because Callable's correct form is Callable[[type], type] (where type is not ParamSpec or Concatenate) so the repr reflects that.
Internally, Callable also flattens the list of args:
Because __args__ *must* be hashable and immutable. Otherwise, it will not work with Union or Literal. Some time ago we tried converting to nested tuple. But that was too difficult (and backwards incompatible) because every other typing operation expected __args__ to contain types, not a tuple.
serhiy-storchaka commentedon Aug 3, 2021
Thank you Ken Jin. So the problem is the __args__ (x, str) is interpreted differently depending on x, and after substituting x the interpretation can be changed. If x was ParamSpec, it was interpreted in one way, but if it becomes int, it is now interpreted in other way.
The solution is to forbid substitution of P with wrong values (not parameters expression). Some normalization is also needed, before and after substitution.
Other related example is:
It is expected that A and B should the same.
ambv commentedon Aug 4, 2021
New changeset 3875a69 by Serhiy Storchaka in branch 'main':
bpo-44801: Check arguments in substitution of ParamSpec in Callable (GH-27585)
3875a69
miss-islington commentedon Aug 4, 2021
New changeset 536e35a by Miss Islington (bot) in branch '3.10':
bpo-44801: Check arguments in substitution of ParamSpec in Callable (GH-27585)
536e35a