Skip to content

Commit c9b9161

Browse files
committed
Address review on explicit import-surface coverage
1 parent bb5f540 commit c9b9161

4 files changed

Lines changed: 51 additions & 29 deletions

File tree

src/openai/__init__.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,6 @@
112112
pass
113113

114114

115-
def _is_truthy_env_var(name: str) -> bool:
116-
value = _os.environ.get(name, "")
117-
return value not in ("", "0", "false", "False")
118-
119-
120115
def _lazy_azure_openai() -> object:
121116
from .lib.azure import AzureOpenAI
122117

@@ -171,21 +166,6 @@ def __getattr__(name: str) -> object:
171166

172167
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
173168

174-
175-
def _resolve_eager_imports() -> None:
176-
if not _is_truthy_env_var("OPENAI_EAGER_IMPORT"):
177-
return
178-
179-
import importlib
180-
181-
# Resolve all lazy exports up-front in eager mode to catch import failures in CI/dev.
182-
globals()["types"] = importlib.import_module("openai.types")
183-
for name in _LAZY_EXPORTS:
184-
__getattr__(name)
185-
186-
187-
_resolve_eager_imports()
188-
189169
# ------ Module level client ------
190170
import typing as _t
191171
import typing_extensions as _te

src/openai/lib/__init__.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,23 @@
1-
from ._tools import pydantic_function_tool as pydantic_function_tool
2-
from ._parsing import ResponseFormatT as ResponseFormatT
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING, Any
4+
5+
if TYPE_CHECKING:
6+
from ._parsing import ResponseFormatT as ResponseFormatT
7+
from ._tools import pydantic_function_tool as pydantic_function_tool
8+
9+
10+
def __getattr__(name: str) -> Any:
11+
if name == "pydantic_function_tool":
12+
from ._tools import pydantic_function_tool
13+
14+
globals()[name] = pydantic_function_tool
15+
return pydantic_function_tool
16+
17+
if name == "ResponseFormatT":
18+
from ._parsing import ResponseFormatT
19+
20+
globals()[name] = ResponseFormatT
21+
return ResponseFormatT
22+
23+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

tests/lib/test_import_surface_live.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,18 @@ def _restore_openai_modules(original_modules: dict[str, object]) -> None:
1818
sys.modules.update(original_modules)
1919

2020

21+
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")
28+
29+
2130
@pytest.mark.skipif(os.environ.get("OPENAI_LIVE") != "1", reason="requires OPENAI_LIVE=1")
2231
@pytest.mark.skipif(not os.environ.get("OPENAI_API_KEY"), reason="requires OPENAI_API_KEY")
23-
def test_eager_import_with_live_token_allows_real_request(monkeypatch) -> None:
24-
# Exercise eager mode in a real SDK flow behind explicit live-test flags.
25-
monkeypatch.setenv("OPENAI_EAGER_IMPORT", "1")
32+
def test_explicit_lazy_export_resolution_allows_real_request() -> None:
2633
original_modules = _openai_modules()
2734

2835
for name in original_modules:
@@ -32,6 +39,8 @@ def test_eager_import_with_live_token_allows_real_request(monkeypatch) -> None:
3239
try:
3340
openai = importlib.import_module("openai")
3441

42+
_resolve_lazy_exports(openai)
43+
3544
assert "openai.types" in sys.modules
3645
assert "openai.lib.azure" in sys.modules
3746
assert "AzureOpenAI" in openai.__dict__

tests/test_import_surface.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@ def _restore_openai_modules(original_modules: dict[str, object]) -> None:
1515
sys.modules.update(original_modules)
1616

1717

18-
def test_openai_azure_is_lazy_imported(monkeypatch) -> None:
19-
monkeypatch.delenv("OPENAI_EAGER_IMPORT", raising=False)
18+
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")
25+
26+
27+
def test_openai_azure_is_lazy_imported() -> None:
2028
original_modules = _openai_modules()
2129

2230
for name in original_modules:
@@ -33,16 +41,20 @@ def test_openai_azure_is_lazy_imported(monkeypatch) -> None:
3341
_restore_openai_modules(original_modules)
3442

3543

36-
def test_openai_eager_import_resolves_lazy_exports(monkeypatch) -> None:
44+
def test_openai_can_explicitly_resolve_lazy_exports() -> None:
3745
original_modules = _openai_modules()
38-
monkeypatch.setenv("OPENAI_EAGER_IMPORT", "1")
3946

4047
for name in original_modules:
4148
sys.modules.pop(name, None)
4249

4350
try:
4451
openai = importlib.import_module("openai")
4552

53+
assert "openai.types" not in sys.modules
54+
assert "openai.lib.azure" not in sys.modules
55+
56+
_resolve_lazy_exports(openai)
57+
4658
assert "openai.types" in sys.modules
4759
assert "openai.lib.azure" in sys.modules
4860
assert "AzureOpenAI" in openai.__dict__

0 commit comments

Comments
 (0)