From db029a596c90b1af4ef0bfb1cdf31f54b2f5755d Mon Sep 17 00:00:00 2001 From: Stainless Bot <107565488+stainless-bot@users.noreply.github.com> Date: Wed, 29 Nov 2023 06:38:46 -0500 Subject: [PATCH] fix(client): don't cause crashes when inspecting the module (#897) --- src/openai/_utils/_proxy.py | 26 ++++++++++++++++++++++---- src/openai/lib/_old_api.py | 12 +++++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/openai/_utils/_proxy.py b/src/openai/_utils/_proxy.py index aa934a3fbc..3c9e790a25 100644 --- a/src/openai/_utils/_proxy.py +++ b/src/openai/_utils/_proxy.py @@ -18,25 +18,43 @@ class LazyProxy(Generic[T], ABC): def __init__(self) -> None: self.__proxied: T | None = None + # Note: we have to special case proxies that themselves return proxies + # to support using a proxy as a catch-all for any random access, e.g. `proxy.foo.bar.baz` + def __getattr__(self, attr: str) -> object: - return getattr(self.__get_proxied__(), attr) + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return proxied # pyright: ignore + return getattr(proxied, attr) @override def __repr__(self) -> str: + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return proxied.__class__.__name__ return repr(self.__get_proxied__()) @override def __str__(self) -> str: - return str(self.__get_proxied__()) + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return proxied.__class__.__name__ + return str(proxied) @override def __dir__(self) -> Iterable[str]: - return self.__get_proxied__().__dir__() + proxied = self.__get_proxied__() + if isinstance(proxied, LazyProxy): + return [] + return proxied.__dir__() @property # type: ignore @override def __class__(self) -> type: - return self.__get_proxied__().__class__ + proxied = self.__get_proxied__() + if issubclass(type(proxied), LazyProxy): + return type(proxied) + return proxied.__class__ def __get_proxied__(self) -> T: if not self.should_cache: diff --git a/src/openai/lib/_old_api.py b/src/openai/lib/_old_api.py index c4038fcfaf..929c87e80b 100644 --- a/src/openai/lib/_old_api.py +++ b/src/openai/lib/_old_api.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from typing_extensions import override from .._utils import LazyProxy @@ -23,13 +23,19 @@ def __init__(self, *, symbol: str) -> None: super().__init__(INSTRUCTIONS.format(symbol=symbol)) -class APIRemovedInV1Proxy(LazyProxy[None]): +class APIRemovedInV1Proxy(LazyProxy[Any]): def __init__(self, *, symbol: str) -> None: super().__init__() self._symbol = symbol @override - def __load__(self) -> None: + def __load__(self) -> Any: + # return the proxy until it is eventually called so that + # we don't break people that are just checking the attributes + # of a module + return self + + def __call__(self, *_args: Any, **_kwargs: Any) -> Any: raise APIRemovedInV1(symbol=self._symbol)