-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
support pep 673 Self type #11871
Comments
FWIW, both pyright and pyre have implemented this feature in its currently-documented form if you want to play with it. |
I know :) it's great. I hate when people email SQLAlchemy with a feature request and say " django does it! " :) but yeah, just trying to see if people using mypy can take advantage also in the near term or if there's no roadmap for this one here. |
There is already a draft PR working on adding support for PEP 673: #11666 |
@AlexWaygood we are literally trying to choose right now if SQLAlchemy 2.0, for which we hope to have beta releases by the end of Q1 2022, can use pep673 Self or not. I know this is normally not something projects can estimate but is it your experience a PR like the one suggested in #11666 can move towards being merged within a few months or is it likely it could stall for a long time? |
at the same time, if we do release 2.0 using pep 673, mypy users would be more interested in seeing this PR completed so for that reason alone I might decide to use it now. |
Hey @zzzeek -- unfortunately, I'm not really the right person to ask about this :// I'm not actually on the mypy core team, and have only contributed a few documentation fixes to mypy -- I tend to contribute more towards the CPython & typeshed repos, I just stalk the mypy issue tracker from time to time 😄 Perhaps @hauntsaninja might be able to shed some more light? Having said that, I think the approach typeshed has taken would probably serve you well! You could define a single # typing_utils.py
from typing import TypeVar
Self = TypeVar('Self') Then, in the rest of your code base, you could use that # foo.py
from typing_utils import Self
class Foo:
def returns_self(self: Self) -> Self:
return self
@classmethod
def returns_cls(cls: type[Self]) -> type[Self]:
return cls In that way, you'd get type annotations that work perfectly for now; and if PEP 673 is accepted and implemented, you could quite easily run a single script using AST to clean up your code base, converting # foo.py
from typing_extensions import Self
class Foo:
def returns_self(self) -> Self:
return self
@classmethod
def returns_cls(cls) -> type[Self]:
return cls The old version of |
I also just stalk the mypy issue tracker from time to time :-) I don't think there is anyone who gets paid time to work on mypy, so there isn't a concrete roadmap. In my experience, you can expect a lag time of a couple months from contributor-completes-PR to mypy-release-that-contains-said-PR. Re PEP 673 specifically: |
OK, we can certainly go with that, the approach we have at the moment is copied from how pep-673 illustrates it, with individual TypeVars that are each "bound" to the target type. There should be no reason that's needed though, right? that is, the "Self" that's not bound will work just as well? |
For situations like this, the It depends whether you're using mypy to check function implementations, or just writing stubs, though. If you're just writing stubs, you can get away with a lot more, and the |
this is inline typing in SQLAlchemy for 2.0 where we will no longer use stubs. |
In which case, yeah, you'll often need the from typing import TypeVar
FooSelf = TypeVar('F', bound='Foo')
class Foo:
bar: int
def change_bar(self: FooSelf, x: int) -> FooSelf:
self.bar = x # mypy erroneously complains about this line if the TypeVar is not bound
return self |
yes that's what we've been doing, thanks for the tips! |
No problem! |
This is probably a silly idea, but it would be rather neat if class methods returned class Widget:
def add_thing(self, value: str):
self.value = value
# return self is assumed if no return value specified
print("Hello").print(" World!") |
That's really a Python language change, not a Mypy change - type checkers can't affect what occurs at runtime. |
Just pitching what I assume you already know. All (well, nearly all) of my need for I also wanted good type checking. I came across Anyway, I am sure you see where this is going. I really want mypy to support PEP 673 sooner rather than later. If I actually knew how to work with ASTs in practice, I would offer to help. Again, I suspect that you don't need me nagging to know that there are people who are very much hoping for Self support in mypy. But at least let me say that your work on this is very much appreciated. |
Ref #12840 Fixes #11871 Fixes #14089 This is an alternative implementation to two existing PRs: #11666, #13133. This PR treats `typing.Self` as pure syntactic sugar, and transforms it into a type variable early during semantic analyzis. This way we can re-use all the existing machinery and handled edge cases for self-types. The only new thing is self-type for _attributes_ (as proposed in the PEP). This required handling in several places, since attribute access is duplicated in several places (see #7724), plus special forms (like NamedTuples and TypedDicts) and dataclasses plugin require additional care, since they use attribute annotations in special ways. I don't copy all the existing tests for "old style" self-types, but only some common use cases, possible error conditions, and relevant new edge cases, such as e.g. special forms mentioned above, and implicit type variable binding for callable types.
Feature
Support the pep-673 Self type
pep is at: https://www.python.org/dev/peps/pep-0673/
a rough idea of it is that this code:
is quasi-equivalent to:
Pitch
the appeal of the pep is that for the very common pattern of method-chained object construction, methods can easily indicate they return an object of the same type upon which the method is being invoked. For example if I made
class SubWidget(Widget)
, theSubWidget.add_thing()
method reportsSubWidget
as the return type automatically. The pattern using TypeVar seems to be more or less equivlant, but is more verbose requiring the declaration of TypeVar objects per class hierarchy as well as that it has to be explicitly present on the "self" parameter in methods.We are looking for this feature to make our job of integrating typing into SQLAlchemy an easier job. it seems to be a fairly straightforward translation between two idioms.
cc @CaselIT
The text was updated successfully, but these errors were encountered: