|
6 | 6 | import typing as _t |
7 | 7 | from typing_extensions import override |
8 | 8 |
|
9 | | -from . import types |
10 | 9 | from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given |
11 | 10 | from ._utils import file_from_path |
12 | 11 | from ._client import Client, OpenAI, Stream, Timeout, Transport, AsyncClient, AsyncOpenAI, AsyncStream, RequestOptions |
|
87 | 86 | if not _t.TYPE_CHECKING: |
88 | 87 | from ._utils._resources_proxy import resources as resources |
89 | 88 |
|
90 | | -from .lib import azure as _azure, pydantic_function_tool as pydantic_function_tool |
| 89 | +if _t.TYPE_CHECKING: |
| 90 | + from . import types as types |
| 91 | + from .lib.azure import AzureADTokenProvider, AzureOpenAI, AsyncAzureOpenAI |
| 92 | +else: |
| 93 | + from ._utils._proxy import LazyProxy as _LazyProxy |
| 94 | + |
| 95 | + class _TypesProxy(_LazyProxy[_t.Any]): |
| 96 | + @override |
| 97 | + def __load__(self) -> _t.Any: |
| 98 | + import importlib |
| 99 | + |
| 100 | + return importlib.import_module("openai.types") |
| 101 | + |
| 102 | + types = _TypesProxy().__as_proxied__() |
| 103 | + |
91 | 104 | from .version import VERSION as VERSION |
92 | | -from .lib.azure import AzureOpenAI as AzureOpenAI, AsyncAzureOpenAI as AsyncAzureOpenAI |
93 | 105 | from .lib._old_api import * |
94 | | -from .lib.streaming import ( |
95 | | - AssistantEventHandler as AssistantEventHandler, |
96 | | - AsyncAssistantEventHandler as AsyncAssistantEventHandler, |
97 | | -) |
98 | 106 |
|
99 | 107 | _setup_logging() |
100 | 108 |
|
|
105 | 113 | __locals = locals() |
106 | 114 | for __name in __all__: |
107 | 115 | if not __name.startswith("__"): |
| 116 | + __obj = __locals.get(__name) |
| 117 | + if __obj is None: |
| 118 | + continue |
108 | 119 | try: |
109 | | - __locals[__name].__module__ = "openai" |
| 120 | + __obj.__module__ = "openai" |
110 | 121 | except (TypeError, AttributeError): |
111 | 122 | # Some of our exported symbols are builtins which we can't set attributes for. |
112 | 123 | pass |
113 | 124 |
|
| 125 | + |
| 126 | +def _is_truthy_env_var(name: str) -> bool: |
| 127 | + value = _os.environ.get(name, "") |
| 128 | + return value not in ("", "0", "false", "False") |
| 129 | + |
| 130 | + |
| 131 | +def _lazy_azure_openai() -> object: |
| 132 | + from .lib.azure import AzureOpenAI |
| 133 | + |
| 134 | + return AzureOpenAI |
| 135 | + |
| 136 | + |
| 137 | +def _lazy_async_azure_openai() -> object: |
| 138 | + from .lib.azure import AsyncAzureOpenAI |
| 139 | + |
| 140 | + return AsyncAzureOpenAI |
| 141 | + |
| 142 | + |
| 143 | +def _lazy_pydantic_function_tool() -> object: |
| 144 | + from .lib._tools import pydantic_function_tool |
| 145 | + |
| 146 | + return pydantic_function_tool |
| 147 | + |
| 148 | + |
| 149 | +def _lazy_assistant_event_handler() -> object: |
| 150 | + from .lib.streaming import AssistantEventHandler |
| 151 | + |
| 152 | + return AssistantEventHandler |
| 153 | + |
| 154 | + |
| 155 | +def _lazy_async_assistant_event_handler() -> object: |
| 156 | + from .lib.streaming import AsyncAssistantEventHandler |
| 157 | + |
| 158 | + return AsyncAssistantEventHandler |
| 159 | + |
| 160 | + |
| 161 | +_LAZY_EXPORTS: dict[str, _t.Callable[[], object]] = { |
| 162 | + "AzureOpenAI": _lazy_azure_openai, |
| 163 | + "AsyncAzureOpenAI": _lazy_async_azure_openai, |
| 164 | + "pydantic_function_tool": _lazy_pydantic_function_tool, |
| 165 | + "AssistantEventHandler": _lazy_assistant_event_handler, |
| 166 | + "AsyncAssistantEventHandler": _lazy_async_assistant_event_handler, |
| 167 | +} |
| 168 | + |
| 169 | + |
| 170 | +def __getattr__(name: str) -> object: |
| 171 | + if name in _LAZY_EXPORTS: |
| 172 | + value = _LAZY_EXPORTS[name]() |
| 173 | + globals()[name] = value |
| 174 | + return value |
| 175 | + |
| 176 | + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") |
| 177 | + |
| 178 | + |
| 179 | +def _resolve_eager_imports() -> None: |
| 180 | + if not _is_truthy_env_var("OPENAI_EAGER_IMPORT"): |
| 181 | + return |
| 182 | + |
| 183 | + import importlib |
| 184 | + |
| 185 | + # Resolve all lazy exports up-front in eager mode to catch import failures in CI/dev. |
| 186 | + globals()["types"] = importlib.import_module("openai.types") |
| 187 | + for name in _LAZY_EXPORTS: |
| 188 | + __getattr__(name) |
| 189 | + |
| 190 | + |
| 191 | +_resolve_eager_imports() |
| 192 | + |
114 | 193 | # ------ Module level client ------ |
115 | 194 | import typing as _t |
116 | 195 | import typing_extensions as _te |
|
149 | 228 |
|
150 | 229 | azure_ad_token: str | None = _os.environ.get("AZURE_OPENAI_AD_TOKEN") |
151 | 230 |
|
152 | | -azure_ad_token_provider: _azure.AzureADTokenProvider | None = None |
| 231 | +azure_ad_token_provider: AzureADTokenProvider | None = None |
153 | 232 |
|
154 | 233 |
|
155 | 234 | class _ModuleClient(OpenAI): |
@@ -268,8 +347,25 @@ def _client(self, value: _httpx.Client) -> None: # type: ignore |
268 | 347 | http_client = value |
269 | 348 |
|
270 | 349 |
|
271 | | -class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore |
272 | | - ... |
| 350 | +def _create_azure_module_client_class() -> type[OpenAI]: |
| 351 | + from .lib.azure import AzureOpenAI |
| 352 | + |
| 353 | + class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore |
| 354 | + ... |
| 355 | + |
| 356 | + return _AzureModuleClient |
| 357 | + |
| 358 | + |
| 359 | +_AZURE_MODULE_CLIENT_CLASS: type[OpenAI] | None = None |
| 360 | + |
| 361 | + |
| 362 | +def _azure_module_client_class() -> type[OpenAI]: |
| 363 | + global _AZURE_MODULE_CLIENT_CLASS |
| 364 | + |
| 365 | + if _AZURE_MODULE_CLIENT_CLASS is None: |
| 366 | + _AZURE_MODULE_CLIENT_CLASS = _create_azure_module_client_class() |
| 367 | + |
| 368 | + return _AZURE_MODULE_CLIENT_CLASS |
273 | 369 |
|
274 | 370 |
|
275 | 371 | class _AmbiguousModuleClientUsageError(OpenAIError): |
@@ -332,7 +428,7 @@ def _load_client() -> OpenAI: # type: ignore[reportUnusedFunction] |
332 | 428 | api_type = "openai" |
333 | 429 |
|
334 | 430 | if api_type == "azure": |
335 | | - _client = _AzureModuleClient( # type: ignore |
| 431 | + _client = _azure_module_client_class()( # type: ignore |
336 | 432 | api_version=api_version, |
337 | 433 | azure_endpoint=azure_endpoint, |
338 | 434 | api_key=api_key, |
|
0 commit comments