Pyright Compatibility #909
Replies: 3 comments 1 reply
-
If taking on the larger task of rewriting the classes is too daunting, it might be possible to just put in some safeguards for the cases that you highlight (and that other people will probably bring up in this thread/after it happens). Property setter overrides that throw could be a pragmatic way to mitigate those types of errors. Something like class Client:
@attribute.setter
def base_url(self, value):
raise Exception("This doesn't work") |
Beta Was this translation helpful? Give feedback.
-
Just chiming in to say that I very much would like to see this too. I default to using both Mypy and Pyright together, both in strict mode, and for the project I'm working on now, openapi-python-client using underscores for these attributes is the one thing that's preventing me from using Pyright. I'm contemplating overriding the template just to get around it. One option here could be to use # eq=False makes the dataclass use id-based hashing (inherits object.__hash__)
@dataclasses.dataclass(frozen=True, eq=False)
class Client:
base_url: str
_client_cache: ClassVar[
MutableMapping["Client", httpx.Client]
] = weakref.WeakKeyDictionary()
def set_httpx_client(self, client: httpx.Client) -> "Client":
self._client_cache[self] = client
return self
def get_httpx_client(self) -> httpx.Client:
client = self._client_cache.get(self)
if client is None:
client = httpx.Client(
base_url=self.base_url,
)
self._client_cache[self] = client
return client This seems to work fine in testing, and PyCharm, Mypy and Pyright all correctly complain if you try to assign something to Alternatively Yet another option is to have the class _ClientCacher:
def __init__(self):
self._client: httpx.Client | None = None
def set(self, client: httpx.Client) -> None:
self._client = client
def get(self, parent: "Client") -> httpx.Client:
client = self._client
if client is None:
client = httpx.Client(base_url=parent.base_url,)
self._client = client
return client
@dataclasses.dataclass(frozen=True, eq=False)
class Client:
base_url: str
_client: _ClientCacher = dataclasses.field(default_factory=_ClientCacher)
def set_httpx_client(self, client: httpx.Client) -> "Client":
self._client.set(client)
return self
def get_httpx_client(self) -> httpx.Client:
return self._client.get(self) attrs also allows you to selectively specify fields as frozen using Essentially it's perfectly doable, and it's up to personal preference which solution seems less bad. I find the |
Beta Was this translation helpful? Give feedback.
-
Done in 0.19.1 |
Beta Was this translation helpful? Give feedback.
-
This comes from @naddeoa over in #856. The current generated client classes do not play nicely with pyright, which specifically doesn't like the way that attrs auto-generates constructor parameters from "private" (those beginning with
_
) attributes like_base_url
.The reason for these "private" attributes is that generated
Client
classes cache their underlyinghttpx
clients for much-improved performance. If someone were to change a value (like_base_url
) after the inner client is constructed, it would have no effect, which could be very surprising to consumers at runtime. The_
prefix should indicate to most Python programmers that they should not touch that field directly.The most obvious solution to me is to stop using
attrs
for these classes and instead create a standard Python class, but please discuss alternative solutions down below.Beta Was this translation helpful? Give feedback.
All reactions