-
Notifications
You must be signed in to change notification settings - Fork 3
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
Remove generic type from BaseApiClient
#92
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor comments to check for
but in the `.pyi` file, so the type can be used to specify type hints, but | ||
**not** in any other context, as the class doesn't really exist for the Python | ||
interpreter. This include generics, and because of this, this class can't be | ||
even parametrized using the async class, so the instantiation of the stub can't |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even parametrized using the async class, so the instantiation of the stub can't | |
even parameterized using the async class, so the instantiation of the stub can't |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found it confusing :D
I seems I was wrong 👼
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is an irregular language.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The `BaseApiClient` class is not generic anymore, and doesn't take a function to create the stub. Instead, subclasses should create their own stub right after calling the parent constructor. This enables subclasses to cast the stub to the generated `XxxAsyncStub` class, which have proper `async` type hints. Signed-off-by: Leandro Lucarella <[email protected]>
Rebased to resolve release notes conflicts too. |
Enabled auto-merge. |
Signed-off-by: Leandro Lucarella <[email protected]>
class MyApiClient(BaseApiClient): | ||
def __init__(self, server_url: str, *, ...) -> None: | ||
super().__init__(server_url, connect=connect) | ||
self._stub = cast(MyServiceAsyncStub, MyServiceStub(self.channel)) | ||
... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just ask them to pass cast(MyServiceAsyncStub, MyServiceStub(service.channel))
as an argument, and make the base client generic over MyServiceAsyncStub
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because __init__
can't have MyServiceAsyncStub
as a type hint, to do that we need to take the type as a generic, and we can't use an async stub as a generic because it is parsed by the interpreter, and it can't find it because it is not present in the .py
file, only the .pyi
file.
This is how great grpio is handling asyncio and type-hinting 😬 (there is a new experimental interface in the cooking, let's see how that turns out).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't parse them with from __future__ import annotations
right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never mind, it will parse them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because it is not an annotation in this case, is is a proper object for the interpreter. You can give it a go if you want, I already tried many different attempts and nothing seemed to work.
$ head -n 100 t.py* t2.py
==> t.py <==
class IDoExist:
pass
==> t.pyi <==
class IDoExist:
pass
class IDontExist:
pass
==> t2.py <==
from __future__ import annotations
from typing import Generic, TypeVar
from t import IDoExist, IDontExist
T = TypeVar("T")
class G(Generic[T]):
def __init__(self, x: T):
self.x = x
class Sub(G[IDoExist]):
pass
class Sub2(G[IDontExist]):
pass
$ python t2.py
Traceback (most recent call last):
File "/home/luca/devel/client-base/t2.py", line 5, in <module>
from t import IDoExist, IDontExist
ImportError: cannot import name 'IDontExist' from 't' (/home/luca/devel/client-base/t.py)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put another way, with TYPE_CHECKING
:
from t import IDoExist
if TYPE_CHECKING:
from t import IDontExist
Then the error becomes:
$ python t2.py
Traceback (most recent call last):
File "/home/luca/devel/client-base/t2.py", line 22, in <module>
class Sub2(G[IDontExist]):
^^^^^^^^^^
NameError: name 'IDontExist' is not defined. Did you mean: 'IDoExist'?
Maybe it is more clear to see this way. Only stuff after a :
(or used in special constructs, like cast
), are type hints, the rest is just code.
I just added back the commit in #86 adding the channels defaults to the examples too. |
I've removed it from the queue because Sahas had some comments |
Dismissing only to be able to enable auto-merge again, and let Sahas make the final approval that triggers the merging
The
BaseApiClient
class is not generic anymore, and doesn't take a function to create the stub. Instead, subclasses should create their own stub right after calling the parent constructor. This enables subclasses to cast the stub to the generatedXxxAsyncStub
class, which have properasync
type hints.