openai/openai-python
Publicmirrored from https://github.com/openai/openai-pythonAvailable
src/openai/_utils/_proxy.py
65lines · modecode
| 1 | from __future__ import annotations |
| 2 | |
| 3 | from abc import ABC, abstractmethod |
| 4 | from typing import Generic, TypeVar, Iterable, cast |
| 5 | from typing_extensions import override |
| 6 | |
| 7 | T = TypeVar("T") |
| 8 | |
| 9 | |
| 10 | class LazyProxy(Generic[T], ABC): |
| 11 | """Implements data methods to pretend that an instance is another instance. |
| 12 | |
| 13 | This includes forwarding attribute access and other methods. |
| 14 | """ |
| 15 | |
| 16 | # Note: we have to special case proxies that themselves return proxies |
| 17 | # to support using a proxy as a catch-all for any random access, e.g. `proxy.foo.bar.baz` |
| 18 | |
| 19 | def __getattr__(self, attr: str) -> object: |
| 20 | proxied = self.__get_proxied__() |
| 21 | if isinstance(proxied, LazyProxy): |
| 22 | return proxied # pyright: ignore |
| 23 | return getattr(proxied, attr) |
| 24 | |
| 25 | @override |
| 26 | def __repr__(self) -> str: |
| 27 | proxied = self.__get_proxied__() |
| 28 | if isinstance(proxied, LazyProxy): |
| 29 | return proxied.__class__.__name__ |
| 30 | return repr(self.__get_proxied__()) |
| 31 | |
| 32 | @override |
| 33 | def __str__(self) -> str: |
| 34 | proxied = self.__get_proxied__() |
| 35 | if isinstance(proxied, LazyProxy): |
| 36 | return proxied.__class__.__name__ |
| 37 | return str(proxied) |
| 38 | |
| 39 | @override |
| 40 | def __dir__(self) -> Iterable[str]: |
| 41 | proxied = self.__get_proxied__() |
| 42 | if isinstance(proxied, LazyProxy): |
| 43 | return [] |
| 44 | return proxied.__dir__() |
| 45 | |
| 46 | @property # type: ignore |
| 47 | @override |
| 48 | def __class__(self) -> type: # pyright: ignore |
| 49 | try: |
| 50 | proxied = self.__get_proxied__() |
| 51 | except Exception: |
| 52 | return type(self) |
| 53 | if issubclass(type(proxied), LazyProxy): |
| 54 | return type(proxied) |
| 55 | return proxied.__class__ |
| 56 | |
| 57 | def __get_proxied__(self) -> T: |
| 58 | return self.__load__() |
| 59 | |
| 60 | def __as_proxied__(self) -> T: |
| 61 | """Helper method that returns the current proxy, typed as the loaded object""" |
| 62 | return cast(T, self) |
| 63 | |
| 64 | @abstractmethod |
| 65 | def __load__(self) -> T: ... |
| 66 | |