|
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 |
|
96 | 95 | if not _t.TYPE_CHECKING: |
97 | 96 | from ._utils._resources_proxy import resources as resources |
98 | 97 |
|
99 | | -from .lib import azure as _azure, pydantic_function_tool as pydantic_function_tool |
| 98 | +if _t.TYPE_CHECKING: |
| 99 | + from . import types as types |
| 100 | + from .lib.azure import AzureADTokenProvider, AzureOpenAI, AsyncAzureOpenAI |
| 101 | +else: |
| 102 | + from ._utils._proxy import LazyProxy as _LazyProxy |
| 103 | + |
| 104 | + class _TypesProxy(_LazyProxy[_t.Any]): |
| 105 | + @override |
| 106 | + def __load__(self) -> _t.Any: |
| 107 | + import importlib |
| 108 | + |
| 109 | + return importlib.import_module("openai.types") |
| 110 | + |
| 111 | + types = _TypesProxy().__as_proxied__() |
| 112 | + |
100 | 113 | from .version import VERSION as VERSION |
101 | | -from .lib.azure import AzureOpenAI as AzureOpenAI, AsyncAzureOpenAI as AsyncAzureOpenAI |
102 | 114 | from .lib._old_api import * |
103 | | -from .lib.streaming import ( |
104 | | - AssistantEventHandler as AssistantEventHandler, |
105 | | - AsyncAssistantEventHandler as AsyncAssistantEventHandler, |
106 | | -) |
107 | 115 |
|
108 | 116 | _setup_logging() |
109 | 117 |
|
|
114 | 122 | __locals = locals() |
115 | 123 | for __name in __all__: |
116 | 124 | if not __name.startswith("__"): |
| 125 | + __obj = __locals.get(__name) |
| 126 | + if __obj is None: |
| 127 | + continue |
117 | 128 | try: |
118 | | - __locals[__name].__module__ = "openai" |
| 129 | + __obj.__module__ = "openai" |
119 | 130 | except (TypeError, AttributeError): |
120 | 131 | # Some of our exported symbols are builtins which we can't set attributes for. |
121 | 132 | pass |
122 | 133 |
|
| 134 | + |
| 135 | +def _is_truthy_env_var(name: str) -> bool: |
| 136 | + value = _os.environ.get(name, "") |
| 137 | + return value not in ("", "0", "false", "False") |
| 138 | + |
| 139 | + |
| 140 | +def _lazy_azure_openai() -> object: |
| 141 | + from .lib.azure import AzureOpenAI |
| 142 | + |
| 143 | + return AzureOpenAI |
| 144 | + |
| 145 | + |
| 146 | +def _lazy_async_azure_openai() -> object: |
| 147 | + from .lib.azure import AsyncAzureOpenAI |
| 148 | + |
| 149 | + return AsyncAzureOpenAI |
| 150 | + |
| 151 | + |
| 152 | +def _lazy_pydantic_function_tool() -> object: |
| 153 | + from .lib._tools import pydantic_function_tool |
| 154 | + |
| 155 | + return pydantic_function_tool |
| 156 | + |
| 157 | + |
| 158 | +def _lazy_assistant_event_handler() -> object: |
| 159 | + from .lib.streaming import AssistantEventHandler |
| 160 | + |
| 161 | + return AssistantEventHandler |
| 162 | + |
| 163 | + |
| 164 | +def _lazy_async_assistant_event_handler() -> object: |
| 165 | + from .lib.streaming import AsyncAssistantEventHandler |
| 166 | + |
| 167 | + return AsyncAssistantEventHandler |
| 168 | + |
| 169 | + |
| 170 | +_LAZY_EXPORTS: dict[str, _t.Callable[[], object]] = { |
| 171 | + "AzureOpenAI": _lazy_azure_openai, |
| 172 | + "AsyncAzureOpenAI": _lazy_async_azure_openai, |
| 173 | + "pydantic_function_tool": _lazy_pydantic_function_tool, |
| 174 | + "AssistantEventHandler": _lazy_assistant_event_handler, |
| 175 | + "AsyncAssistantEventHandler": _lazy_async_assistant_event_handler, |
| 176 | +} |
| 177 | + |
| 178 | + |
| 179 | +def __getattr__(name: str) -> object: |
| 180 | + if name in _LAZY_EXPORTS: |
| 181 | + value = _LAZY_EXPORTS[name]() |
| 182 | + globals()[name] = value |
| 183 | + return value |
| 184 | + |
| 185 | + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") |
| 186 | + |
| 187 | + |
| 188 | +def _resolve_eager_imports() -> None: |
| 189 | + if not _is_truthy_env_var("OPENAI_EAGER_IMPORT"): |
| 190 | + return |
| 191 | + |
| 192 | + import importlib |
| 193 | + |
| 194 | + # Resolve all lazy exports up-front in eager mode to catch import failures in CI/dev. |
| 195 | + globals()["types"] = importlib.import_module("openai.types") |
| 196 | + for name in _LAZY_EXPORTS: |
| 197 | + __getattr__(name) |
| 198 | + |
| 199 | + |
| 200 | +_resolve_eager_imports() |
| 201 | + |
123 | 202 | # ------ Module level client ------ |
124 | 203 | import typing as _t |
125 | 204 | import typing_extensions as _te |
|
160 | 239 |
|
161 | 240 | azure_ad_token: str | None = _os.environ.get("AZURE_OPENAI_AD_TOKEN") |
162 | 241 |
|
163 | | -azure_ad_token_provider: _azure.AzureADTokenProvider | None = None |
| 242 | +azure_ad_token_provider: AzureADTokenProvider | None = None |
164 | 243 |
|
165 | 244 |
|
166 | 245 | class _ModuleClient(OpenAI): |
@@ -290,8 +369,25 @@ def _client(self, value: _httpx.Client) -> None: # type: ignore |
290 | 369 | http_client = value |
291 | 370 |
|
292 | 371 |
|
293 | | -class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore |
294 | | - ... |
| 372 | +def _create_azure_module_client_class() -> type[OpenAI]: |
| 373 | + from .lib.azure import AzureOpenAI |
| 374 | + |
| 375 | + class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore |
| 376 | + ... |
| 377 | + |
| 378 | + return _AzureModuleClient |
| 379 | + |
| 380 | + |
| 381 | +_AZURE_MODULE_CLIENT_CLASS: type[OpenAI] | None = None |
| 382 | + |
| 383 | + |
| 384 | +def _azure_module_client_class() -> type[OpenAI]: |
| 385 | + global _AZURE_MODULE_CLIENT_CLASS |
| 386 | + |
| 387 | + if _AZURE_MODULE_CLIENT_CLASS is None: |
| 388 | + _AZURE_MODULE_CLIENT_CLASS = _create_azure_module_client_class() |
| 389 | + |
| 390 | + return _AZURE_MODULE_CLIENT_CLASS |
295 | 391 |
|
296 | 392 |
|
297 | 393 | class _AmbiguousModuleClientUsageError(OpenAIError): |
@@ -354,7 +450,7 @@ def _load_client() -> OpenAI: # type: ignore[reportUnusedFunction] |
354 | 450 | api_type = "openai" |
355 | 451 |
|
356 | 452 | if api_type == "azure": |
357 | | - _client = _AzureModuleClient( # type: ignore |
| 453 | + _client = _azure_module_client_class()( # type: ignore |
358 | 454 | api_version=api_version, |
359 | 455 | azure_endpoint=azure_endpoint, |
360 | 456 | api_key=api_key, |
|
0 commit comments