Repository navigation
PEP 612 tracking issue #8645
Description
Hello!
I got a little scared off from working on this by the many other enthusiastic people volunteering their time in #8373. However, there doesn't seem to have been much progress; since I have some extra time now, I figured sharing what I've got could kickstart things. Apologies if someone — or whatever a GSoC is — is already working on it :-) Branch is visible at https://github.com/hauntsaninja/mypy/tree/pep612, happy to make it a draft PR if that would help anything.
Overall seems like the plan would be:
- Focus on generic functions first, implement generic class support later, as pyre plans to.
- Make the fairly straight forward changes in semanal.py and nodes.py so you have the AST. Make relevant visitors visit it (look at where we visit_type_var_expr).
- Change typeanal.py, tvar_scope.py, etc to get binding going to the types you create in types.py. Seems like this would be the place to enforce valid use location too.
- Implement the semantics of ParameterSpecification in checkexpr.py, infer.py, solve.py, etc.
- Add a runtime implementation to mypy_extensions
Since ParameterSpecification is just a juiced up type variable, it makes sense to try and re-use existing logic for TypeVar as much as possible (especially if later PEPs make use of the bounds and variance arguments that PEP 612 reserves). In my branch, I've chosen to add a base class TypeVarLikeX in a couple different class hierarchies, e.g. TypeVarLikeExpr, TypeVarLikeDef. Since I'm not super familiar with mypy's code, this also helps me stumble upon things that I might need to change (it feels great trusting mypy to help improve mypy!). But this is a fairly large refactor (the one-line change in the details snippet alone will require changes in a dozen files), and could maybe affect like plugins or something, so I thought I'd post this before exploring further.
Details
--- a/mypy/types.py
+++ b/mypy/types.py
@@ -983,7 +983,7 @@ class CallableType(FunctionLike):
fallback: Instance,
name: Optional[str] = None,
definition: Optional[SymbolNode] = None,
- variables: Optional[List[TypeVarDef]] = None,
+ variables: Optional[Sequence[TypeVarLikeDef]] = None,
I'm also a little worried about issues like #1317 and #5738. I don't yet know the code well enough to anticipate what issues we might run into, but I'd welcome any thoughts on interactions between existing TypeVar code and any PEP 612 implementation.
Activity
JukkaL commentedon Apr 9, 2020
Your plan looks good to me!
I don't expect that #1317 or #5738 will be blockers for this, though they may affect some use cases (which likely don't work currently anyway). In particular, decorating generic functions might not work. I'm planning to work on one or both of those issues in the near future, since they are really quite bad and have been open for a long time.
Please don't hesitate to ask further questions here (or email be directly).
gvanrossum commentedon Jul 29, 2020
I encourage you to start the work on this. Most likely I will just accept the PEP, given that we've seen no further feedback on typing-sig.
hauntsaninja commentedon Aug 2, 2020
Thanks for the kick! I threw some hours at this today, in particular I managed to get through a good amount of the somewhat tedious refactoring caused by generalising TypeVar. I've made a good amount of progress for typeanal of ParamSpec. Branch is still at https://github.com/hauntsaninja/mypy/tree/pep612
gvanrossum commentedon Aug 2, 2020
Maybe you can submit it as a PR and mark it Draft? I personally find it hard to follow a change like this as a branch in someone else's repo.
hauntsaninja commentedon Aug 3, 2020
Sure, I opened a draft PR here: #9250 All feedback welcome!
Some notes:
testParamSpecLocationsin the draft PR passeschanges_return_type_to_strwould workpep612: more semantic analysis for paramspec (#9422)
gvanrossum commentedon Dec 10, 2020
So how far have you gotten with this? I see two merged PRs but am afraid to look.
One comment: we're currently looking into support for PEP 612 in typing.py for 3.10, and after that in typing_extensions.py for previous Python versions, so it would be nice if these were also supported:
We could actually use some feedback on the PR we're working on: the contributor is currently looking into fairly strict checking of the arguments, but I'm wondering if that's useful -- we can't go as far as what you did in mypy_extensions.pyi (
ParamSpec = 0,Concatenate = 0:-) but we could perhaps just accept anything once we see aParamSpecorConcatenateas part of a type, rather than validating that the usage matches with the PEP (that could be considered mypy's responsibility). Thoughts?hauntsaninja commentedon Dec 10, 2020
There hasn't been much progress since my last comment; I sort of deprioritised this in favour of working on other mypy issues that seemed more pressing. But what exists should already support both typing_extensions and typing:
mypy/mypy/semanal.py
Line 3109 in 35e5031
I very much agree that ParamSpec shouldn't validate much at runtime. I think Callable already validates too much, which will necessitate hacks for the backport of ParamSpec to typing_extensions like https://github.com/facebook/pyre-check/blob/0ba810e07635955cbcdef7cd2ab3722ab01dde5b/pyre_extensions/__init__.py#L75 I'll take a look at that PR soon.
gvanrossum commentedon Dec 13, 2020
I currently get a traceback when using ParamSpec in code:
I'd like to make some progress with this -- I don't think I would be very useful with this traceback, but I can do things like adding ParamSpec etc. to typing_extensions (so they can be used with earlier Python versions), both in typeshed and in the actual typing_extensions.py module, and also do a release of the latter (once it's ready).
gvanrossum commentedon Jan 2, 2021
Huh, there are TODOs all over the code
TODO(shantanu): fix for ParamSpecDefand my example hit one. This is a minimal example BTW:I'll see if I can do something about it.
(UPDATE: I should have read your update a few comments earlier before reporting a traceback. :-)
sebastian-philipp commentedon Aug 25, 2021
Fascinating. I'm hitting the very problem described in PEP 612's Motivation chapter. Would be great to have a solution for this.
graingert commentedon Aug 25, 2021
@sebastian-philipp I think #10883 and #10866 and #10862 does enough to let you use ParamSpec in your projects without breaking downstream mypy users, but you'd need to use pyre or another checker to make sure your own usage is valid
sebastian-philipp commentedon Aug 25, 2021
well, for now I'd like to stick with mypy. Switching to a different type checker, especially one that doesn't support getting installed via pip is a non-trivial task.
shughes-uk commentedon Oct 19, 2021
ParamSpec with Generic seems missing
#11362
6 remaining items
erictraut commentedon Dec 24, 2021
@NeilGirdhar, the
api_boundarydecorator directly returns aCallablewhereas this example returns a specialized generic class (SyncToAsync). Pyright and (I presume) mypy special-caseCallablewhen it is used as a return type so unsolved TypeVars can be solved when the callable is invoked even if these TypeVars are no longer in scope. Technically, this is incorrect behavior, but from a practical standpoint, it's important to bend the rules here to support a variety of common use cases. The same accommodation isn't made for arbitrary generic classes. Arguably, it should be applied for callback protocols or for__call__methods in general, since they act likeCallable.graingert commentedon Dec 24, 2021
I think at least mypy should complain where the unusable instance is created in addition to when the unusable instance is used:
NeilGirdhar commentedon Dec 24, 2021
Why is it incorrect behavior?
Yes, that makes sense. It seems like it could work in general though—not just with callables. If MyPy ever supports higher-kinded type variables, this kind of functions of generic will need to be supported, I think.
Properly type _generative, decorator, public_factory
kshpytsya commentedon Jan 5, 2022
I am facing issue with the following code:
Checking it with
mypy(0.930and0.940+dev.ba0e9d6427fa15a2c3420d4427e88b99514d22f9), Python 3.9 and 3.10, I get the following:whereas
pyrightseems to get it right:pyregets some things right but also emits some strange error (the first one):P.S.: if
Signalclass is declared in a separate module, runningmypyfor the second time fails with the following assertion:which keeps on occurring until removal of mypy's cache entry corresponding to the file containing the
Signalclass.kasium commentedon Jan 24, 2022
Hi, I face issues, when using
ParamSpec.argsas a tuple andParamSpec.kwargsas a dictError:
testscript.py:10: error: "P.kwargs" has no attribute "pop"The code works at runtime. Not sure if it's part of the PEP, that this is possible
I opened #12386 for that
JelleZijlstra commentedon Mar 19, 2022
We also have topic-paramspecPEP 612, ParamSpec, Concatenate
now for listing remaining bugs with ParamSpec.
Basic ParamSpec Concatenate and literal support (#11847)
srittau commentedon May 21, 2022
I believe,
ParamSpecis now fully implemented in mypy (minus potential bugs)?emmatyping commentedon May 21, 2022
#11847 made a lot of progress to full implementation.
There are a few more
TODO(PEP612):in the code base but I think they all cover cases where the results are a little looser but should still work acceptably.(Someone please correct me if I am wrong)
hauntsaninja commentedon May 21, 2022
Yeah, I think users should be able to expect PEP 612 to work, and remaining work is better tracked as individual bugs
mristin commentedon May 22, 2022
@hauntsaninja Thanks a lot for working on this feature! Do you happen to know when the new version of mypy which includes it is going to be released?
hauntsaninja commentedon May 22, 2022
(Others did much more than I did here) mypy 0.950 should already support most things and was released about a month ago. #12807 for tracking the next release