Skip to content

Commit 66532e1

Browse files
committed
Adapt to eager openai.types loading via _client
The 2.32.0 release added 'from .types.websocket_reconnection import ...' at the top of openai/__init__.py, which transitively loads openai.types through openai._client as well. That invalidates the 'openai.types is lazy' assertion the earlier test relied on, so the lazy-types live test is removed and the remaining tests assert the boundaries that still hold (lib.azure, lib.streaming, lib._tools). Also stabilize pyright under strict: - preserve static visibility of AzureOpenAI / AsyncAzureOpenAI / pydantic_function_tool / AssistantEventHandler under TYPE_CHECKING so callers keep their signatures - rename _AZURE_MODULE_CLIENT_CLASS to a non-constant symbol and type the module-client factory as type[AzureOpenAI] to silence strict reportCallIssue / reportConstantRedefinition warnings - tidy ruff imports / I001 noise in scripts/bench_import.py and the test files added in this branch
1 parent 017efdc commit 66532e1

6 files changed

Lines changed: 62 additions & 78 deletions

File tree

scripts/bench_import.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/usr/bin/env python3
22
from __future__ import annotations
33

4-
import argparse
54
import os
6-
import subprocess
75
import sys
86
import time
7+
import argparse
8+
import subprocess
99
from pathlib import Path
1010

1111

src/openai/__init__.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,16 @@
9797

9898
if _t.TYPE_CHECKING:
9999
from . import types as types
100-
from .lib.azure import AzureADTokenProvider, AzureOpenAI, AsyncAzureOpenAI
100+
from .lib.azure import (
101+
AzureOpenAI as AzureOpenAI,
102+
AsyncAzureOpenAI as AsyncAzureOpenAI,
103+
AzureADTokenProvider,
104+
)
105+
from .lib._tools import pydantic_function_tool as pydantic_function_tool
106+
from .lib.streaming import (
107+
AssistantEventHandler as AssistantEventHandler,
108+
AsyncAssistantEventHandler as AsyncAssistantEventHandler,
109+
)
101110

102111
from .version import VERSION as VERSION
103112
from .lib._old_api import *
@@ -332,25 +341,25 @@ def _client(self, value: _httpx.Client) -> None: # type: ignore
332341
http_client = value
333342

334343

335-
def _create_azure_module_client_class() -> type[OpenAI]:
344+
def _create_azure_module_client_class() -> type[AzureOpenAI]:
336345
from .lib.azure import AzureOpenAI
337346

338347
class _AzureModuleClient(_ModuleClient, AzureOpenAI): # type: ignore
339348
...
340349

341-
return _AzureModuleClient
350+
return _AzureModuleClient # type: ignore[return-value]
342351

343352

344-
_AZURE_MODULE_CLIENT_CLASS: type[OpenAI] | None = None
353+
_azure_module_client_class_cache: type[AzureOpenAI] | None = None
345354

346355

347-
def _azure_module_client_class() -> type[OpenAI]:
348-
global _AZURE_MODULE_CLIENT_CLASS
356+
def _azure_module_client_class() -> type[AzureOpenAI]:
357+
global _azure_module_client_class_cache
349358

350-
if _AZURE_MODULE_CLIENT_CLASS is None:
351-
_AZURE_MODULE_CLIENT_CLASS = _create_azure_module_client_class()
359+
if _azure_module_client_class_cache is None:
360+
_azure_module_client_class_cache = _create_azure_module_client_class()
352361

353-
return _AZURE_MODULE_CLIENT_CLASS
362+
return _azure_module_client_class_cache
354363

355364

356365
class _AmbiguousModuleClientUsageError(OpenAIError):

src/openai/lib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from typing import TYPE_CHECKING, Any
44

55
if TYPE_CHECKING:
6-
from ._parsing import ResponseFormatT as ResponseFormatT
76
from ._tools import pydantic_function_tool as pydantic_function_tool
7+
from ._parsing import ResponseFormatT as ResponseFormatT
88

99

1010
def __getattr__(name: str) -> Any:

tests/lib/test_import_surface_live.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,34 @@
33
import os
44
import sys
55
import importlib
6+
from types import ModuleType
67

78
import pytest
89

910

10-
def _openai_modules() -> dict[str, object]:
11+
def _openai_modules() -> dict[str, ModuleType]:
1112
return {name: mod for name, mod in sys.modules.items() if name == "openai" or name.startswith("openai.")}
1213

1314

14-
def _restore_openai_modules(original_modules: dict[str, object]) -> None:
15+
def _restore_openai_modules(original_modules: dict[str, ModuleType]) -> None:
1516
for name in list(sys.modules):
1617
if name == "openai" or name.startswith("openai."):
1718
sys.modules.pop(name, None)
1819
sys.modules.update(original_modules)
1920

2021

22+
_LAZY_EXPORT_NAMES = (
23+
"AzureOpenAI",
24+
"AsyncAzureOpenAI",
25+
"pydantic_function_tool",
26+
"AssistantEventHandler",
27+
"AsyncAssistantEventHandler",
28+
)
29+
30+
2131
def _resolve_lazy_exports(openai_module: object) -> None:
22-
getattr(openai_module, "types")
23-
getattr(openai_module, "AzureOpenAI")
24-
getattr(openai_module, "AsyncAzureOpenAI")
25-
getattr(openai_module, "pydantic_function_tool")
26-
getattr(openai_module, "AssistantEventHandler")
27-
getattr(openai_module, "AsyncAssistantEventHandler")
32+
for name in _LAZY_EXPORT_NAMES:
33+
getattr(openai_module, name)
2834

2935

3036
@pytest.mark.skipif(os.environ.get("OPENAI_LIVE") != "1", reason="requires OPENAI_LIVE=1")
@@ -41,7 +47,6 @@ def test_explicit_lazy_export_resolution_allows_real_request() -> None:
4147

4248
_resolve_lazy_exports(openai)
4349

44-
assert "openai.types" in sys.modules
4550
assert "openai.lib.azure" in sys.modules
4651
assert "AzureOpenAI" in openai.__dict__
4752

tests/test_import_surface.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
11
from __future__ import annotations
22

3-
import importlib
43
import sys
4+
import importlib
5+
from types import ModuleType
56

67

7-
def _openai_modules() -> dict[str, object]:
8+
def _openai_modules() -> dict[str, ModuleType]:
89
return {name: mod for name, mod in sys.modules.items() if name == "openai" or name.startswith("openai.")}
910

1011

11-
def _restore_openai_modules(original_modules: dict[str, object]) -> None:
12+
def _restore_openai_modules(original_modules: dict[str, ModuleType]) -> None:
1213
for name in list(sys.modules):
1314
if name == "openai" or name.startswith("openai."):
1415
sys.modules.pop(name, None)
1516
sys.modules.update(original_modules)
1617

1718

19+
_LAZY_EXPORT_NAMES = (
20+
"AzureOpenAI",
21+
"AsyncAzureOpenAI",
22+
"pydantic_function_tool",
23+
"AssistantEventHandler",
24+
"AsyncAssistantEventHandler",
25+
)
26+
27+
_LAZY_EXPORT_MODULES = (
28+
"openai.lib.azure",
29+
"openai.lib.streaming",
30+
"openai.lib._tools",
31+
)
32+
33+
1834
def _resolve_lazy_exports(openai_module: object) -> None:
19-
getattr(openai_module, "types")
20-
getattr(openai_module, "AzureOpenAI")
21-
getattr(openai_module, "AsyncAzureOpenAI")
22-
getattr(openai_module, "pydantic_function_tool")
23-
getattr(openai_module, "AssistantEventHandler")
24-
getattr(openai_module, "AsyncAssistantEventHandler")
35+
for name in _LAZY_EXPORT_NAMES:
36+
getattr(openai_module, name)
2537

2638

2739
def test_openai_azure_is_lazy_imported() -> None:
@@ -50,17 +62,14 @@ def test_openai_can_explicitly_resolve_lazy_exports() -> None:
5062
try:
5163
openai = importlib.import_module("openai")
5264

53-
assert "openai.types" not in sys.modules
54-
assert "openai.lib.azure" not in sys.modules
65+
for mod_name in _LAZY_EXPORT_MODULES:
66+
assert mod_name not in sys.modules
5567

5668
_resolve_lazy_exports(openai)
5769

58-
assert "openai.types" in sys.modules
59-
assert "openai.lib.azure" in sys.modules
60-
assert "AzureOpenAI" in openai.__dict__
61-
assert "AsyncAzureOpenAI" in openai.__dict__
62-
assert "pydantic_function_tool" in openai.__dict__
63-
assert "AssistantEventHandler" in openai.__dict__
64-
assert "AsyncAssistantEventHandler" in openai.__dict__
70+
for mod_name in _LAZY_EXPORT_MODULES:
71+
assert mod_name in sys.modules
72+
for attr_name in _LAZY_EXPORT_NAMES:
73+
assert attr_name in openai.__dict__
6574
finally:
6675
_restore_openai_modules(original_modules)

tests/test_lazy_types_import.py

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)