ag2 0.8.1__tar.gz → 0.8.2rc0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ag2 might be problematic. Click here for more details.
- {ag2-0.8.1/ag2.egg-info → ag2-0.8.2rc0}/PKG-INFO +2 -1
- {ag2-0.8.1 → ag2-0.8.2rc0/ag2.egg-info}/PKG-INFO +2 -1
- ag2-0.8.2rc0/ag2.egg-info/requires.txt +154 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/pyproject.toml +12 -4
- {ag2-0.8.1 → ag2-0.8.2rc0}/setup_ag2.py +1 -0
- ag2-0.8.2rc0/test/test_import_utils.py +451 -0
- ag2-0.8.1/ag2.egg-info/requires.txt +0 -151
- ag2-0.8.1/test/test_import_utils.py +0 -200
- {ag2-0.8.1 → ag2-0.8.2rc0}/LICENSE +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/NOTICE.md +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/README.md +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/ag2.egg-info/SOURCES.txt +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/ag2.egg-info/dependency_links.txt +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/ag2.egg-info/top_level.txt +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/setup.cfg +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_browser_utils.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_code_utils.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_conftest.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_graph_utils.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_import.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_logging.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_notebook.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_retrieve_utils.py +0 -0
- {ag2-0.8.1 → ag2-0.8.2rc0}/test/test_token_count.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ag2
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2rc0
|
|
4
4
|
Summary: Alias package for pyautogen
|
|
5
5
|
Home-page: https://github.com/ag2ai/ag2
|
|
6
6
|
Author: Chi Wang & Qingyun Wu
|
|
@@ -25,6 +25,7 @@ Provides-Extra: graph-rag-falkor-db
|
|
|
25
25
|
Provides-Extra: rag
|
|
26
26
|
Provides-Extra: crawl4ai
|
|
27
27
|
Provides-Extra: browser-use
|
|
28
|
+
Provides-Extra: google-search
|
|
28
29
|
Provides-Extra: neo4j
|
|
29
30
|
Provides-Extra: twilio
|
|
30
31
|
Provides-Extra: interop-crewai
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ag2
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2rc0
|
|
4
4
|
Summary: Alias package for pyautogen
|
|
5
5
|
Home-page: https://github.com/ag2ai/ag2
|
|
6
6
|
Author: Chi Wang & Qingyun Wu
|
|
@@ -25,6 +25,7 @@ Provides-Extra: graph-rag-falkor-db
|
|
|
25
25
|
Provides-Extra: rag
|
|
26
26
|
Provides-Extra: crawl4ai
|
|
27
27
|
Provides-Extra: browser-use
|
|
28
|
+
Provides-Extra: google-search
|
|
28
29
|
Provides-Extra: neo4j
|
|
29
30
|
Provides-Extra: twilio
|
|
30
31
|
Provides-Extra: interop-crewai
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
pyautogen==0.8.2rc0
|
|
2
|
+
|
|
3
|
+
[anthropic]
|
|
4
|
+
pyautogen[anthropic]==0.8.2rc0
|
|
5
|
+
|
|
6
|
+
[autobuild]
|
|
7
|
+
pyautogen[autobuild]==0.8.2rc0
|
|
8
|
+
|
|
9
|
+
[bedrock]
|
|
10
|
+
pyautogen[bedrock]==0.8.2rc0
|
|
11
|
+
|
|
12
|
+
[blendsearch]
|
|
13
|
+
pyautogen[blendsearch]==0.8.2rc0
|
|
14
|
+
|
|
15
|
+
[browser-use]
|
|
16
|
+
pyautogen[browser-use]==0.8.2rc0
|
|
17
|
+
|
|
18
|
+
[captainagent]
|
|
19
|
+
pyautogen[captainagent]==0.8.2rc0
|
|
20
|
+
|
|
21
|
+
[cerebras]
|
|
22
|
+
pyautogen[cerebras]==0.8.2rc0
|
|
23
|
+
|
|
24
|
+
[cohere]
|
|
25
|
+
pyautogen[cohere]==0.8.2rc0
|
|
26
|
+
|
|
27
|
+
[commsagent-discord]
|
|
28
|
+
pyautogen[commsagent-discord]==0.8.2rc0
|
|
29
|
+
|
|
30
|
+
[commsagent-slack]
|
|
31
|
+
pyautogen[commsagent-slack]==0.8.2rc0
|
|
32
|
+
|
|
33
|
+
[commsagent-telegram]
|
|
34
|
+
pyautogen[commsagent-telegram]==0.8.2rc0
|
|
35
|
+
|
|
36
|
+
[cosmosdb]
|
|
37
|
+
pyautogen[cosmosdb]==0.8.2rc0
|
|
38
|
+
|
|
39
|
+
[crawl4ai]
|
|
40
|
+
pyautogen[crawl4ai]==0.8.2rc0
|
|
41
|
+
|
|
42
|
+
[deepseek]
|
|
43
|
+
pyautogen[deepseek]==0.8.2rc0
|
|
44
|
+
|
|
45
|
+
[dev]
|
|
46
|
+
pyautogen[dev]==0.8.2rc0
|
|
47
|
+
|
|
48
|
+
[docs]
|
|
49
|
+
pyautogen[docs]==0.8.2rc0
|
|
50
|
+
|
|
51
|
+
[flaml]
|
|
52
|
+
pyautogen[flaml]==0.8.2rc0
|
|
53
|
+
|
|
54
|
+
[gemini]
|
|
55
|
+
pyautogen[gemini]==0.8.2rc0
|
|
56
|
+
|
|
57
|
+
[gemini-realtime]
|
|
58
|
+
pyautogen[gemini-realtime]==0.8.2rc0
|
|
59
|
+
|
|
60
|
+
[google-search]
|
|
61
|
+
pyautogen[google-search]==0.8.2rc0
|
|
62
|
+
|
|
63
|
+
[graph]
|
|
64
|
+
pyautogen[graph]==0.8.2rc0
|
|
65
|
+
|
|
66
|
+
[graph-rag-falkor-db]
|
|
67
|
+
pyautogen[graph-rag-falkor-db]==0.8.2rc0
|
|
68
|
+
|
|
69
|
+
[groq]
|
|
70
|
+
pyautogen[groq]==0.8.2rc0
|
|
71
|
+
|
|
72
|
+
[interop]
|
|
73
|
+
pyautogen[interop]==0.8.2rc0
|
|
74
|
+
|
|
75
|
+
[interop-crewai]
|
|
76
|
+
pyautogen[interop-crewai]==0.8.2rc0
|
|
77
|
+
|
|
78
|
+
[interop-langchain]
|
|
79
|
+
pyautogen[interop-langchain]==0.8.2rc0
|
|
80
|
+
|
|
81
|
+
[interop-pydantic-ai]
|
|
82
|
+
pyautogen[interop-pydantic-ai]==0.8.2rc0
|
|
83
|
+
|
|
84
|
+
[jupyter-executor]
|
|
85
|
+
pyautogen[jupyter-executor]==0.8.2rc0
|
|
86
|
+
|
|
87
|
+
[lint]
|
|
88
|
+
pyautogen[lint]==0.8.2rc0
|
|
89
|
+
|
|
90
|
+
[lmm]
|
|
91
|
+
pyautogen[lmm]==0.8.2rc0
|
|
92
|
+
|
|
93
|
+
[long-context]
|
|
94
|
+
pyautogen[long-context]==0.8.2rc0
|
|
95
|
+
|
|
96
|
+
[mathchat]
|
|
97
|
+
pyautogen[mathchat]==0.8.2rc0
|
|
98
|
+
|
|
99
|
+
[mistral]
|
|
100
|
+
pyautogen[mistral]==0.8.2rc0
|
|
101
|
+
|
|
102
|
+
[neo4j]
|
|
103
|
+
pyautogen[neo4j]==0.8.2rc0
|
|
104
|
+
|
|
105
|
+
[ollama]
|
|
106
|
+
pyautogen[ollama]==0.8.2rc0
|
|
107
|
+
|
|
108
|
+
[openai]
|
|
109
|
+
pyautogen[openai]==0.8.2rc0
|
|
110
|
+
|
|
111
|
+
[openai-realtime]
|
|
112
|
+
pyautogen[openai-realtime]==0.8.2rc0
|
|
113
|
+
|
|
114
|
+
[rag]
|
|
115
|
+
pyautogen[rag]==0.8.2rc0
|
|
116
|
+
|
|
117
|
+
[redis]
|
|
118
|
+
pyautogen[redis]==0.8.2rc0
|
|
119
|
+
|
|
120
|
+
[retrievechat]
|
|
121
|
+
pyautogen[retrievechat]==0.8.2rc0
|
|
122
|
+
|
|
123
|
+
[retrievechat-couchbase]
|
|
124
|
+
pyautogen[retrievechat-couchbase]==0.8.2rc0
|
|
125
|
+
|
|
126
|
+
[retrievechat-mongodb]
|
|
127
|
+
pyautogen[retrievechat-mongodb]==0.8.2rc0
|
|
128
|
+
|
|
129
|
+
[retrievechat-pgvector]
|
|
130
|
+
pyautogen[retrievechat-pgvector]==0.8.2rc0
|
|
131
|
+
|
|
132
|
+
[retrievechat-qdrant]
|
|
133
|
+
pyautogen[retrievechat-qdrant]==0.8.2rc0
|
|
134
|
+
|
|
135
|
+
[teachable]
|
|
136
|
+
pyautogen[teachable]==0.8.2rc0
|
|
137
|
+
|
|
138
|
+
[test]
|
|
139
|
+
pyautogen[test]==0.8.2rc0
|
|
140
|
+
|
|
141
|
+
[together]
|
|
142
|
+
pyautogen[together]==0.8.2rc0
|
|
143
|
+
|
|
144
|
+
[twilio]
|
|
145
|
+
pyautogen[twilio]==0.8.2rc0
|
|
146
|
+
|
|
147
|
+
[types]
|
|
148
|
+
pyautogen[types]==0.8.2rc0
|
|
149
|
+
|
|
150
|
+
[websockets]
|
|
151
|
+
pyautogen[websockets]==0.8.2rc0
|
|
152
|
+
|
|
153
|
+
[websurfer]
|
|
154
|
+
pyautogen[websurfer]==0.8.2rc0
|
|
@@ -60,8 +60,9 @@ dependencies = [
|
|
|
60
60
|
"docker",
|
|
61
61
|
"packaging",
|
|
62
62
|
"asyncer==0.0.8",
|
|
63
|
-
"fast-depends>=2.4.12,<3",
|
|
63
|
+
# "fast-depends>=2.4.12,<3", # integrated into the package
|
|
64
64
|
"httpx>=0.28.1,<1",
|
|
65
|
+
"anyio>=3.0.0,<5.0.0" # needed by the internal fast-depends
|
|
65
66
|
]
|
|
66
67
|
|
|
67
68
|
[project.optional-dependencies]
|
|
@@ -76,7 +77,7 @@ flaml = [
|
|
|
76
77
|
# public distributions
|
|
77
78
|
|
|
78
79
|
openai = [
|
|
79
|
-
"openai>=1.
|
|
80
|
+
"openai>=1.66.2",
|
|
80
81
|
]
|
|
81
82
|
|
|
82
83
|
openai-realtime = [
|
|
@@ -156,6 +157,10 @@ browser-use = [
|
|
|
156
157
|
"browser-use==0.1.37",
|
|
157
158
|
]
|
|
158
159
|
|
|
160
|
+
google-search = [
|
|
161
|
+
"google-api-python-client>=2.163.0,<3.0",
|
|
162
|
+
]
|
|
163
|
+
|
|
159
164
|
neo4j = [
|
|
160
165
|
"docx2txt==0.8",
|
|
161
166
|
"llama-index==0.12.22",
|
|
@@ -181,8 +186,7 @@ interop =[
|
|
|
181
186
|
"pyautogen[interop-crewai, interop-langchain, interop-pydantic-ai]",
|
|
182
187
|
]
|
|
183
188
|
|
|
184
|
-
|
|
185
|
-
autobuild = ["chromadb", "sentence-transformers", "huggingface-hub", "pysqlite3-binary"]
|
|
189
|
+
autobuild = ["chromadb", "sentence-transformers", "huggingface-hub"]
|
|
186
190
|
|
|
187
191
|
blendsearch = ["flaml[blendsearch]"]
|
|
188
192
|
mathchat = ["sympy", "wolframalpha"]
|
|
@@ -237,6 +241,7 @@ test = [
|
|
|
237
241
|
"mock==5.1.0",
|
|
238
242
|
"pandas==2.2.3",
|
|
239
243
|
"fastapi==0.115.11",
|
|
244
|
+
"dirty-equals==0.9.0",
|
|
240
245
|
]
|
|
241
246
|
|
|
242
247
|
docs = [
|
|
@@ -341,6 +346,7 @@ markers = [
|
|
|
341
346
|
"interop",
|
|
342
347
|
"browser_use",
|
|
343
348
|
"crawl4ai",
|
|
349
|
+
"google_search",
|
|
344
350
|
"websockets",
|
|
345
351
|
"commsagent_discord",
|
|
346
352
|
"commsagent_slack",
|
|
@@ -438,6 +444,7 @@ files = [
|
|
|
438
444
|
"autogen/agents",
|
|
439
445
|
"autogen/coding",
|
|
440
446
|
"autogen/exception_utils.py",
|
|
447
|
+
"autogen/fast_depends",
|
|
441
448
|
"autogen/import_utils.py",
|
|
442
449
|
"autogen/interop",
|
|
443
450
|
"autogen/io",
|
|
@@ -454,6 +461,7 @@ files = [
|
|
|
454
461
|
"test/agentchat/realtime_agent",
|
|
455
462
|
"test/agents",
|
|
456
463
|
"test/conftest.py",
|
|
464
|
+
# "test/fast_depends",
|
|
457
465
|
"test/interop",
|
|
458
466
|
"test/io",
|
|
459
467
|
"test/messages",
|
|
@@ -41,6 +41,7 @@ setuptools.setup(
|
|
|
41
41
|
"rag": ["pyautogen[rag]==" + __version__],
|
|
42
42
|
"crawl4ai": ["pyautogen[crawl4ai]==" + __version__],
|
|
43
43
|
"browser-use": ["pyautogen[browser-use]==" + __version__],
|
|
44
|
+
"google-search": ["pyautogen[google-search]==" + __version__],
|
|
44
45
|
"neo4j": ["pyautogen[neo4j]==" + __version__],
|
|
45
46
|
"twilio": ["pyautogen[twilio]==" + __version__],
|
|
46
47
|
"interop-crewai": ["pyautogen[interop-crewai]==" + __version__],
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
from types import ModuleType
|
|
8
|
+
from typing import Any, Iterable, Iterator, Optional, Type, Union
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from autogen.import_utils import ModuleInfo, get_missing_imports, optional_import_block, require_optional_import
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def mock_module() -> Iterator[ModuleType]:
|
|
17
|
+
module_name = "mock_module"
|
|
18
|
+
module = ModuleType(module_name)
|
|
19
|
+
module.__version__ = "1.0.0" # type: ignore[attr-defined]
|
|
20
|
+
sys.modules[module_name] = module
|
|
21
|
+
yield module
|
|
22
|
+
del sys.modules[module_name]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture
|
|
26
|
+
def mock_module_without_version() -> Iterator[ModuleType]:
|
|
27
|
+
module_name = "mock_module"
|
|
28
|
+
module = ModuleType(module_name)
|
|
29
|
+
sys.modules[module_name] = module
|
|
30
|
+
yield module
|
|
31
|
+
del sys.modules[module_name]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class MockModule:
|
|
35
|
+
def __init__(self, name: str, version: str):
|
|
36
|
+
self.__name__ = name
|
|
37
|
+
self.__version__ = version
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.fixture
|
|
41
|
+
def mock_modules() -> Iterator[dict[str, ModuleType]]:
|
|
42
|
+
modules = {
|
|
43
|
+
"module_a": MockModule("module_a", "1.0.0"),
|
|
44
|
+
"module_b": MockModule("module_b", "2.0.0"),
|
|
45
|
+
"module_c": MockModule("module_c", "3.0.0"),
|
|
46
|
+
}
|
|
47
|
+
original_sys_modules = sys.modules.copy()
|
|
48
|
+
sys.modules.update(modules) # type: ignore[arg-type]
|
|
49
|
+
assert all(module in sys.modules for module in modules)
|
|
50
|
+
try:
|
|
51
|
+
yield modules # type: ignore[misc]
|
|
52
|
+
finally:
|
|
53
|
+
sys.modules.clear()
|
|
54
|
+
sys.modules.update(original_sys_modules)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TestmoduleInfo:
|
|
58
|
+
@pytest.mark.parametrize(
|
|
59
|
+
"module_info, expected",
|
|
60
|
+
[
|
|
61
|
+
(
|
|
62
|
+
"jupyter-client>=8.6.0,<9.0.0",
|
|
63
|
+
ModuleInfo(
|
|
64
|
+
name="jupyter-client",
|
|
65
|
+
min_version="8.6.0",
|
|
66
|
+
max_version="9.0.0",
|
|
67
|
+
min_inclusive=True,
|
|
68
|
+
max_inclusive=False,
|
|
69
|
+
),
|
|
70
|
+
),
|
|
71
|
+
(
|
|
72
|
+
"jupyter-client>=8.6.0",
|
|
73
|
+
ModuleInfo(
|
|
74
|
+
name="jupyter-client",
|
|
75
|
+
min_version="8.6.0",
|
|
76
|
+
max_version=None,
|
|
77
|
+
min_inclusive=True,
|
|
78
|
+
max_inclusive=False,
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
(
|
|
82
|
+
"jupyter-client<9.0.0",
|
|
83
|
+
ModuleInfo(
|
|
84
|
+
name="jupyter-client",
|
|
85
|
+
min_version=None,
|
|
86
|
+
max_version="9.0.0",
|
|
87
|
+
min_inclusive=False,
|
|
88
|
+
max_inclusive=False,
|
|
89
|
+
),
|
|
90
|
+
),
|
|
91
|
+
(
|
|
92
|
+
"jupyter-client",
|
|
93
|
+
ModuleInfo(
|
|
94
|
+
name="jupyter-client", min_version=None, max_version=None, min_inclusive=False, max_inclusive=False
|
|
95
|
+
),
|
|
96
|
+
),
|
|
97
|
+
],
|
|
98
|
+
)
|
|
99
|
+
def test_from_str_success(self, module_info: str, expected: ModuleInfo) -> None:
|
|
100
|
+
result = ModuleInfo.from_str(module_info)
|
|
101
|
+
assert result == expected
|
|
102
|
+
|
|
103
|
+
def test_from_str_with_invalid_format(self) -> None:
|
|
104
|
+
module_info = "jupyter-client>="
|
|
105
|
+
with pytest.raises(ValueError, match="Invalid module information: jupyter-client>="):
|
|
106
|
+
ModuleInfo.from_str(module_info)
|
|
107
|
+
|
|
108
|
+
@pytest.mark.parametrize(
|
|
109
|
+
"module_info, expected",
|
|
110
|
+
[
|
|
111
|
+
(ModuleInfo(name="mock_module"), None),
|
|
112
|
+
(ModuleInfo(name="non_existent_module"), "'non_existent_module' is not installed."),
|
|
113
|
+
(ModuleInfo(name="mock_module", min_version="1.0.0", min_inclusive=True), None),
|
|
114
|
+
(
|
|
115
|
+
ModuleInfo(name="mock_module", min_version="1.0.0", min_inclusive=False),
|
|
116
|
+
"'mock_module' is installed, but the installed version 1.0.0 is too low (required 'mock_module>1.0.0').",
|
|
117
|
+
),
|
|
118
|
+
(ModuleInfo(name="mock_module", min_version="0.9.0", min_inclusive=True), None),
|
|
119
|
+
(
|
|
120
|
+
ModuleInfo(name="mock_module", min_version="1.1.0", min_inclusive=True),
|
|
121
|
+
"'mock_module' is installed, but the installed version 1.0.0 is too low (required 'mock_module>=1.1.0').",
|
|
122
|
+
),
|
|
123
|
+
(ModuleInfo(name="mock_module", max_version="1.0.0", max_inclusive=True), None),
|
|
124
|
+
(
|
|
125
|
+
ModuleInfo(name="mock_module", max_version="1.0.0", max_inclusive=False),
|
|
126
|
+
"'mock_module' is installed, but the installed version 1.0.0 is too high (required 'mock_module<1.0.0').",
|
|
127
|
+
),
|
|
128
|
+
(ModuleInfo(name="mock_module", max_version="1.1.0", max_inclusive=True), None),
|
|
129
|
+
(
|
|
130
|
+
ModuleInfo(name="mock_module", max_version="0.9.0", max_inclusive=True),
|
|
131
|
+
"'mock_module' is installed, but the installed version 1.0.0 is too high (required 'mock_module<=0.9.0').",
|
|
132
|
+
),
|
|
133
|
+
(
|
|
134
|
+
ModuleInfo(
|
|
135
|
+
name="mock_module", min_version="0.9.0", max_version="1.1.0", min_inclusive=True, max_inclusive=True
|
|
136
|
+
),
|
|
137
|
+
None,
|
|
138
|
+
),
|
|
139
|
+
(
|
|
140
|
+
ModuleInfo(
|
|
141
|
+
name="mock_module", min_version="1.0.0", max_version="1.0.0", min_inclusive=True, max_inclusive=True
|
|
142
|
+
),
|
|
143
|
+
None,
|
|
144
|
+
),
|
|
145
|
+
(
|
|
146
|
+
ModuleInfo(
|
|
147
|
+
name="mock_module",
|
|
148
|
+
min_version="1.0.0",
|
|
149
|
+
max_version="1.0.0",
|
|
150
|
+
min_inclusive=False,
|
|
151
|
+
max_inclusive=False,
|
|
152
|
+
),
|
|
153
|
+
"'mock_module' is installed, but the installed version 1.0.0 is too low (required 'mock_module>1.0.0<1.0.0').",
|
|
154
|
+
),
|
|
155
|
+
],
|
|
156
|
+
)
|
|
157
|
+
def test_is_in_sys_modules(self, mock_module: ModuleType, module_info: ModuleInfo, expected: Optional[str]) -> None:
|
|
158
|
+
assert module_info.is_in_sys_modules() == expected
|
|
159
|
+
|
|
160
|
+
@pytest.mark.parametrize(
|
|
161
|
+
"module_info, expected",
|
|
162
|
+
[
|
|
163
|
+
(ModuleInfo(name="mock_module"), None),
|
|
164
|
+
(
|
|
165
|
+
ModuleInfo(name="mock_module", min_version="1.0.0", min_inclusive=True),
|
|
166
|
+
"'mock_module' is installed, but the version is not available.",
|
|
167
|
+
),
|
|
168
|
+
],
|
|
169
|
+
)
|
|
170
|
+
def test_is_in_sys_modules_without_version(
|
|
171
|
+
self, mock_module_without_version: ModuleType, module_info: ModuleInfo, expected: Optional[str]
|
|
172
|
+
) -> None:
|
|
173
|
+
assert module_info.is_in_sys_modules() == expected
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class TestOptionalImportBlock:
|
|
177
|
+
def test_optional_import_block(self) -> None:
|
|
178
|
+
with optional_import_block():
|
|
179
|
+
import ast
|
|
180
|
+
|
|
181
|
+
import some_module
|
|
182
|
+
import some_other_module
|
|
183
|
+
|
|
184
|
+
assert ast is not None
|
|
185
|
+
with pytest.raises(
|
|
186
|
+
UnboundLocalError,
|
|
187
|
+
match=r"(local variable 'some_module' referenced before assignment|cannot access local variable 'some_module' where it is not associated with a value)",
|
|
188
|
+
):
|
|
189
|
+
some_module
|
|
190
|
+
|
|
191
|
+
with pytest.raises(
|
|
192
|
+
UnboundLocalError,
|
|
193
|
+
match=r"(local variable 'some_other_module' referenced before assignment|cannot access local variable 'some_other_module' where it is not associated with a value)",
|
|
194
|
+
):
|
|
195
|
+
some_other_module
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class TestRequiresOptionalImportCallables:
|
|
199
|
+
def test_version_too_high(self, mock_module: ModuleInfo) -> None:
|
|
200
|
+
assert mock_module.__name__ in sys.modules # type: ignore[attr-defined]
|
|
201
|
+
mock_info = f"{mock_module.__name__}>{mock_module.__version__}" # type: ignore[attr-defined]
|
|
202
|
+
|
|
203
|
+
@require_optional_import(mock_info, "mock-module")
|
|
204
|
+
def dummy_function() -> None:
|
|
205
|
+
"""Dummy function to test requires_optional_import"""
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
with pytest.raises(
|
|
209
|
+
ImportError,
|
|
210
|
+
match=re.escape("""A module needed for test.test_import_utils.dummy_function is missing:
|
|
211
|
+
- 'mock_module' is installed, but the installed version 1.0.0 is too low (required 'mock_module>1.0.0').
|
|
212
|
+
Please install it using:
|
|
213
|
+
'pip install ag2[mock-module]'"""),
|
|
214
|
+
):
|
|
215
|
+
dummy_function()
|
|
216
|
+
|
|
217
|
+
@pytest.mark.parametrize("except_for", [None, "dummy_function", ["dummy_function"]])
|
|
218
|
+
def test_function_attributes(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
219
|
+
def dummy_function() -> None:
|
|
220
|
+
"""Dummy function to test requires_optional_import"""
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
dummy_function.__module__ = "some_random_module.dummy_stuff"
|
|
224
|
+
|
|
225
|
+
actual = require_optional_import("some_optional_module", "optional_dep", except_for=except_for)(dummy_function)
|
|
226
|
+
|
|
227
|
+
assert actual is not None
|
|
228
|
+
assert actual.__module__ == "some_random_module.dummy_stuff"
|
|
229
|
+
assert actual.__name__ == "dummy_function"
|
|
230
|
+
assert actual.__doc__ == "Dummy function to test requires_optional_import"
|
|
231
|
+
|
|
232
|
+
if not except_for:
|
|
233
|
+
with pytest.raises(
|
|
234
|
+
ImportError,
|
|
235
|
+
match=re.escape("""A module needed for some_random_module.dummy_stuff.dummy_function is missing:
|
|
236
|
+
- 'some_optional_module' is not installed.
|
|
237
|
+
Please install it using:
|
|
238
|
+
'pip install ag2[optional_dep]"""),
|
|
239
|
+
):
|
|
240
|
+
actual()
|
|
241
|
+
else:
|
|
242
|
+
actual()
|
|
243
|
+
|
|
244
|
+
@pytest.mark.parametrize("except_for", [None, "dummy_function", ["dummy_function"]])
|
|
245
|
+
def test_function_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
246
|
+
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
247
|
+
def dummy_function() -> None:
|
|
248
|
+
"""Dummy function to test requires_optional_import"""
|
|
249
|
+
pass
|
|
250
|
+
|
|
251
|
+
if not except_for:
|
|
252
|
+
with pytest.raises(
|
|
253
|
+
ImportError,
|
|
254
|
+
match=re.escape("""A module needed for test.test_import_utils.dummy_function is missing:
|
|
255
|
+
- 'some_optional_module' is not installed.
|
|
256
|
+
Please install it using:
|
|
257
|
+
'pip install ag2[optional_dep]'"""),
|
|
258
|
+
):
|
|
259
|
+
dummy_function()
|
|
260
|
+
else:
|
|
261
|
+
dummy_function()
|
|
262
|
+
|
|
263
|
+
@pytest.mark.parametrize("except_for", [None, "dummy_method", ["dummy_method"]])
|
|
264
|
+
def test_method_attributes(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
265
|
+
class DummyClass:
|
|
266
|
+
def dummy_method(self) -> None:
|
|
267
|
+
"""Dummy method to test requires_optional_import"""
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
assert hasattr(DummyClass.dummy_method, "__module__")
|
|
271
|
+
assert DummyClass.dummy_method.__module__ == "test.test_import_utils"
|
|
272
|
+
|
|
273
|
+
DummyClass.__module__ = "some_random_module.dummy_stuff"
|
|
274
|
+
DummyClass.dummy_method.__module__ = "some_random_module.dummy_stuff"
|
|
275
|
+
|
|
276
|
+
DummyClass.dummy_method = require_optional_import( # type: ignore[method-assign]
|
|
277
|
+
"some_optional_module", "optional_dep", except_for=except_for
|
|
278
|
+
)(DummyClass.dummy_method)
|
|
279
|
+
|
|
280
|
+
assert DummyClass.dummy_method is not None
|
|
281
|
+
assert DummyClass.dummy_method.__module__ == "some_random_module.dummy_stuff"
|
|
282
|
+
assert DummyClass.dummy_method.__name__ == "dummy_method"
|
|
283
|
+
assert DummyClass.dummy_method.__doc__ == "Dummy method to test requires_optional_import"
|
|
284
|
+
|
|
285
|
+
dummy = DummyClass()
|
|
286
|
+
|
|
287
|
+
if not except_for:
|
|
288
|
+
with pytest.raises(
|
|
289
|
+
ImportError,
|
|
290
|
+
match=re.escape("""A module needed for some_random_module.dummy_stuff.dummy_method is missing:
|
|
291
|
+
- 'some_optional_module' is not installed.
|
|
292
|
+
Please install it using:
|
|
293
|
+
'pip install ag2[optional_dep]'"""),
|
|
294
|
+
):
|
|
295
|
+
dummy.dummy_method()
|
|
296
|
+
else:
|
|
297
|
+
dummy.dummy_method()
|
|
298
|
+
|
|
299
|
+
@pytest.mark.parametrize("except_for", [None, "dummy_method", ["dummy_method"]])
|
|
300
|
+
def test_method_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
301
|
+
class DummyClass:
|
|
302
|
+
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
303
|
+
def dummy_method(self) -> None:
|
|
304
|
+
"""Dummy method to test requires_optional_import"""
|
|
305
|
+
pass
|
|
306
|
+
|
|
307
|
+
dummy = DummyClass()
|
|
308
|
+
|
|
309
|
+
if not except_for:
|
|
310
|
+
with pytest.raises(
|
|
311
|
+
ImportError,
|
|
312
|
+
match=re.escape("""A module needed for test.test_import_utils.dummy_method is missing:
|
|
313
|
+
- 'some_optional_module' is not installed.
|
|
314
|
+
Please install it using:
|
|
315
|
+
'pip install ag2[optional_dep]'"""),
|
|
316
|
+
):
|
|
317
|
+
dummy.dummy_method()
|
|
318
|
+
else:
|
|
319
|
+
dummy.dummy_method()
|
|
320
|
+
|
|
321
|
+
@pytest.mark.parametrize("except_for", [None, "dummy_static_function", ["dummy_static_function"]])
|
|
322
|
+
def test_static_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
323
|
+
class DummyClass:
|
|
324
|
+
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
325
|
+
@staticmethod
|
|
326
|
+
def dummy_static_function() -> None:
|
|
327
|
+
"""Dummy static function to test requires_optional_import"""
|
|
328
|
+
pass
|
|
329
|
+
|
|
330
|
+
dummy = DummyClass()
|
|
331
|
+
|
|
332
|
+
if not except_for:
|
|
333
|
+
with pytest.raises(
|
|
334
|
+
ImportError,
|
|
335
|
+
match=re.escape("""A module needed for test.test_import_utils.dummy_static_function is missing:
|
|
336
|
+
- 'some_optional_module' is not installed.
|
|
337
|
+
Please install it using:
|
|
338
|
+
'pip install ag2[optional_dep]'"""),
|
|
339
|
+
):
|
|
340
|
+
dummy.dummy_static_function()
|
|
341
|
+
else:
|
|
342
|
+
dummy.dummy_static_function()
|
|
343
|
+
|
|
344
|
+
@pytest.mark.parametrize("except_for", [None, "dummy_property", ["dummy_property"]])
|
|
345
|
+
def test_property_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
346
|
+
class DummyClass:
|
|
347
|
+
@property
|
|
348
|
+
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
349
|
+
def dummy_property(self) -> int:
|
|
350
|
+
"""Dummy property to test requires_optional_import"""
|
|
351
|
+
return 4
|
|
352
|
+
|
|
353
|
+
dummy = DummyClass()
|
|
354
|
+
|
|
355
|
+
if not except_for:
|
|
356
|
+
with pytest.raises(
|
|
357
|
+
ImportError,
|
|
358
|
+
match=re.escape("""A module needed for test.test_import_utils.dummy_property is missing:
|
|
359
|
+
- 'some_optional_module' is not installed.
|
|
360
|
+
Please install it using:
|
|
361
|
+
'pip install ag2[optional_dep]'"""),
|
|
362
|
+
):
|
|
363
|
+
dummy.dummy_property
|
|
364
|
+
|
|
365
|
+
else:
|
|
366
|
+
dummy.dummy_property
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
class TestRequiresOptionalImportClasses:
|
|
370
|
+
@pytest.fixture
|
|
371
|
+
def dummy_cls(self) -> Type[Any]:
|
|
372
|
+
@require_optional_import("some_optional_module", "optional_dep")
|
|
373
|
+
class DummyClass:
|
|
374
|
+
def dummy_method(self) -> None:
|
|
375
|
+
"""Dummy method to test requires_optional_import"""
|
|
376
|
+
pass
|
|
377
|
+
|
|
378
|
+
@staticmethod
|
|
379
|
+
def dummy_static_method() -> None:
|
|
380
|
+
"""Dummy static method to test requires_optional_import"""
|
|
381
|
+
pass
|
|
382
|
+
|
|
383
|
+
@classmethod
|
|
384
|
+
def dummy_class_method(cls) -> None:
|
|
385
|
+
"""Dummy class method to test requires_optional_import"""
|
|
386
|
+
pass
|
|
387
|
+
|
|
388
|
+
@property
|
|
389
|
+
def dummy_property(self) -> int:
|
|
390
|
+
"""Dummy property to test requires_optional_import"""
|
|
391
|
+
return 4
|
|
392
|
+
|
|
393
|
+
return DummyClass
|
|
394
|
+
|
|
395
|
+
def test_class_init_call(self, dummy_cls: Type[Any]) -> None:
|
|
396
|
+
with pytest.raises(
|
|
397
|
+
ImportError,
|
|
398
|
+
match=re.escape("""A module needed for __init__ is missing:
|
|
399
|
+
- 'some_optional_module' is not installed.
|
|
400
|
+
Please install it using:\n'pip install ag2[optional_dep]'"""),
|
|
401
|
+
):
|
|
402
|
+
dummy_cls()
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class TestGetMissingImports:
|
|
406
|
+
@pytest.mark.parametrize(
|
|
407
|
+
"modules, expected_missing",
|
|
408
|
+
[
|
|
409
|
+
(["module_a", "module_b", "module_c"], {}),
|
|
410
|
+
(["module_a>=1.0.0", "module_b>=2.0.0", "module_c>=3.0.0"], {}),
|
|
411
|
+
(
|
|
412
|
+
["module_a>=1.0.1", "module_b>=2.0.0", "module_c>=3.0.0"],
|
|
413
|
+
{
|
|
414
|
+
"module_a": "'module_a' is installed, but the installed version 1.0.0 is too low (required 'module_a>=1.0.1')."
|
|
415
|
+
},
|
|
416
|
+
),
|
|
417
|
+
(
|
|
418
|
+
["module_a>=1.0.0", "module_b>=2.1.0", "module_c>=3.0.0"],
|
|
419
|
+
{
|
|
420
|
+
"module_b": "'module_b' is installed, but the installed version 2.0.0 is too low (required 'module_b>=2.1.0')."
|
|
421
|
+
},
|
|
422
|
+
),
|
|
423
|
+
(
|
|
424
|
+
["module_a>=1.0.0", "module_b>=2.0.0", "module_c>=3.1.0"],
|
|
425
|
+
{
|
|
426
|
+
"module_c": "'module_c' is installed, but the installed version 3.0.0 is too low (required 'module_c>=3.1.0')."
|
|
427
|
+
},
|
|
428
|
+
),
|
|
429
|
+
(["module_a>=1.0.0", "module_b>=2.0.0", "module_d"], {"module_d": "'module_d' is not installed."}),
|
|
430
|
+
(
|
|
431
|
+
["module_a>=1.0.0", "module_b>=2.0.0", "module_c<3.0.0"],
|
|
432
|
+
{
|
|
433
|
+
"module_c": "'module_c' is installed, but the installed version 3.0.0 is too high (required 'module_c<3.0.0')."
|
|
434
|
+
},
|
|
435
|
+
),
|
|
436
|
+
(["module_a>=1.0.0", "module_b>=2.0.0", "module_c<=3.0.0"], {}),
|
|
437
|
+
(
|
|
438
|
+
["module_a>=1.0.0", "module_b>=2.0.0", "module_c>3.0.0"],
|
|
439
|
+
{
|
|
440
|
+
"module_c": "'module_c' is installed, but the installed version 3.0.0 is too low (required 'module_c>3.0.0')."
|
|
441
|
+
},
|
|
442
|
+
),
|
|
443
|
+
(["module_a>=1.0.0", "module_b>=2.0.0", "module_c<3.1.0"], {}),
|
|
444
|
+
],
|
|
445
|
+
)
|
|
446
|
+
def test_get_missing_imports(
|
|
447
|
+
self, mock_modules: dict[str, MockModule], modules: Union[str, Iterable[str]], expected_missing: dict[str, str]
|
|
448
|
+
) -> None:
|
|
449
|
+
assert mock_modules
|
|
450
|
+
missing = get_missing_imports(modules)
|
|
451
|
+
assert missing == expected_missing
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
pyautogen==0.8.1
|
|
2
|
-
|
|
3
|
-
[anthropic]
|
|
4
|
-
pyautogen[anthropic]==0.8.1
|
|
5
|
-
|
|
6
|
-
[autobuild]
|
|
7
|
-
pyautogen[autobuild]==0.8.1
|
|
8
|
-
|
|
9
|
-
[bedrock]
|
|
10
|
-
pyautogen[bedrock]==0.8.1
|
|
11
|
-
|
|
12
|
-
[blendsearch]
|
|
13
|
-
pyautogen[blendsearch]==0.8.1
|
|
14
|
-
|
|
15
|
-
[browser-use]
|
|
16
|
-
pyautogen[browser-use]==0.8.1
|
|
17
|
-
|
|
18
|
-
[captainagent]
|
|
19
|
-
pyautogen[captainagent]==0.8.1
|
|
20
|
-
|
|
21
|
-
[cerebras]
|
|
22
|
-
pyautogen[cerebras]==0.8.1
|
|
23
|
-
|
|
24
|
-
[cohere]
|
|
25
|
-
pyautogen[cohere]==0.8.1
|
|
26
|
-
|
|
27
|
-
[commsagent-discord]
|
|
28
|
-
pyautogen[commsagent-discord]==0.8.1
|
|
29
|
-
|
|
30
|
-
[commsagent-slack]
|
|
31
|
-
pyautogen[commsagent-slack]==0.8.1
|
|
32
|
-
|
|
33
|
-
[commsagent-telegram]
|
|
34
|
-
pyautogen[commsagent-telegram]==0.8.1
|
|
35
|
-
|
|
36
|
-
[cosmosdb]
|
|
37
|
-
pyautogen[cosmosdb]==0.8.1
|
|
38
|
-
|
|
39
|
-
[crawl4ai]
|
|
40
|
-
pyautogen[crawl4ai]==0.8.1
|
|
41
|
-
|
|
42
|
-
[deepseek]
|
|
43
|
-
pyautogen[deepseek]==0.8.1
|
|
44
|
-
|
|
45
|
-
[dev]
|
|
46
|
-
pyautogen[dev]==0.8.1
|
|
47
|
-
|
|
48
|
-
[docs]
|
|
49
|
-
pyautogen[docs]==0.8.1
|
|
50
|
-
|
|
51
|
-
[flaml]
|
|
52
|
-
pyautogen[flaml]==0.8.1
|
|
53
|
-
|
|
54
|
-
[gemini]
|
|
55
|
-
pyautogen[gemini]==0.8.1
|
|
56
|
-
|
|
57
|
-
[gemini-realtime]
|
|
58
|
-
pyautogen[gemini-realtime]==0.8.1
|
|
59
|
-
|
|
60
|
-
[graph]
|
|
61
|
-
pyautogen[graph]==0.8.1
|
|
62
|
-
|
|
63
|
-
[graph-rag-falkor-db]
|
|
64
|
-
pyautogen[graph-rag-falkor-db]==0.8.1
|
|
65
|
-
|
|
66
|
-
[groq]
|
|
67
|
-
pyautogen[groq]==0.8.1
|
|
68
|
-
|
|
69
|
-
[interop]
|
|
70
|
-
pyautogen[interop]==0.8.1
|
|
71
|
-
|
|
72
|
-
[interop-crewai]
|
|
73
|
-
pyautogen[interop-crewai]==0.8.1
|
|
74
|
-
|
|
75
|
-
[interop-langchain]
|
|
76
|
-
pyautogen[interop-langchain]==0.8.1
|
|
77
|
-
|
|
78
|
-
[interop-pydantic-ai]
|
|
79
|
-
pyautogen[interop-pydantic-ai]==0.8.1
|
|
80
|
-
|
|
81
|
-
[jupyter-executor]
|
|
82
|
-
pyautogen[jupyter-executor]==0.8.1
|
|
83
|
-
|
|
84
|
-
[lint]
|
|
85
|
-
pyautogen[lint]==0.8.1
|
|
86
|
-
|
|
87
|
-
[lmm]
|
|
88
|
-
pyautogen[lmm]==0.8.1
|
|
89
|
-
|
|
90
|
-
[long-context]
|
|
91
|
-
pyautogen[long-context]==0.8.1
|
|
92
|
-
|
|
93
|
-
[mathchat]
|
|
94
|
-
pyautogen[mathchat]==0.8.1
|
|
95
|
-
|
|
96
|
-
[mistral]
|
|
97
|
-
pyautogen[mistral]==0.8.1
|
|
98
|
-
|
|
99
|
-
[neo4j]
|
|
100
|
-
pyautogen[neo4j]==0.8.1
|
|
101
|
-
|
|
102
|
-
[ollama]
|
|
103
|
-
pyautogen[ollama]==0.8.1
|
|
104
|
-
|
|
105
|
-
[openai]
|
|
106
|
-
pyautogen[openai]==0.8.1
|
|
107
|
-
|
|
108
|
-
[openai-realtime]
|
|
109
|
-
pyautogen[openai-realtime]==0.8.1
|
|
110
|
-
|
|
111
|
-
[rag]
|
|
112
|
-
pyautogen[rag]==0.8.1
|
|
113
|
-
|
|
114
|
-
[redis]
|
|
115
|
-
pyautogen[redis]==0.8.1
|
|
116
|
-
|
|
117
|
-
[retrievechat]
|
|
118
|
-
pyautogen[retrievechat]==0.8.1
|
|
119
|
-
|
|
120
|
-
[retrievechat-couchbase]
|
|
121
|
-
pyautogen[retrievechat-couchbase]==0.8.1
|
|
122
|
-
|
|
123
|
-
[retrievechat-mongodb]
|
|
124
|
-
pyautogen[retrievechat-mongodb]==0.8.1
|
|
125
|
-
|
|
126
|
-
[retrievechat-pgvector]
|
|
127
|
-
pyautogen[retrievechat-pgvector]==0.8.1
|
|
128
|
-
|
|
129
|
-
[retrievechat-qdrant]
|
|
130
|
-
pyautogen[retrievechat-qdrant]==0.8.1
|
|
131
|
-
|
|
132
|
-
[teachable]
|
|
133
|
-
pyautogen[teachable]==0.8.1
|
|
134
|
-
|
|
135
|
-
[test]
|
|
136
|
-
pyautogen[test]==0.8.1
|
|
137
|
-
|
|
138
|
-
[together]
|
|
139
|
-
pyautogen[together]==0.8.1
|
|
140
|
-
|
|
141
|
-
[twilio]
|
|
142
|
-
pyautogen[twilio]==0.8.1
|
|
143
|
-
|
|
144
|
-
[types]
|
|
145
|
-
pyautogen[types]==0.8.1
|
|
146
|
-
|
|
147
|
-
[websockets]
|
|
148
|
-
pyautogen[websockets]==0.8.1
|
|
149
|
-
|
|
150
|
-
[websurfer]
|
|
151
|
-
pyautogen[websurfer]==0.8.1
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
-
#
|
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
|
|
5
|
-
from typing import Any, Optional, Type, Union
|
|
6
|
-
|
|
7
|
-
import pytest
|
|
8
|
-
|
|
9
|
-
from autogen.import_utils import optional_import_block, require_optional_import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TestOptionalImportBlock:
|
|
13
|
-
def test_optional_import_block(self) -> None:
|
|
14
|
-
with optional_import_block():
|
|
15
|
-
import ast
|
|
16
|
-
|
|
17
|
-
import some_module
|
|
18
|
-
import some_other_module
|
|
19
|
-
|
|
20
|
-
assert ast is not None
|
|
21
|
-
with pytest.raises(
|
|
22
|
-
UnboundLocalError,
|
|
23
|
-
match=r"(local variable 'some_module' referenced before assignment|cannot access local variable 'some_module' where it is not associated with a value)",
|
|
24
|
-
):
|
|
25
|
-
some_module
|
|
26
|
-
|
|
27
|
-
with pytest.raises(
|
|
28
|
-
UnboundLocalError,
|
|
29
|
-
match=r"(local variable 'some_other_module' referenced before assignment|cannot access local variable 'some_other_module' where it is not associated with a value)",
|
|
30
|
-
):
|
|
31
|
-
some_other_module
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class TestRequiresOptionalImportCallables:
|
|
35
|
-
@pytest.mark.parametrize("except_for", [None, "dummy_function", ["dummy_function"]])
|
|
36
|
-
def test_function_attributes(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
37
|
-
def dummy_function() -> None:
|
|
38
|
-
"""Dummy function to test requires_optional_import"""
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
dummy_function.__module__ = "some_random_module.dummy_stuff"
|
|
42
|
-
|
|
43
|
-
actual = require_optional_import("some_optional_module", "optional_dep", except_for=except_for)(dummy_function)
|
|
44
|
-
|
|
45
|
-
assert actual is not None
|
|
46
|
-
assert actual.__module__ == "some_random_module.dummy_stuff"
|
|
47
|
-
assert actual.__name__ == "dummy_function"
|
|
48
|
-
assert actual.__doc__ == "Dummy function to test requires_optional_import"
|
|
49
|
-
|
|
50
|
-
if not except_for:
|
|
51
|
-
with pytest.raises(
|
|
52
|
-
ImportError,
|
|
53
|
-
match=r"Module 'some_optional_module' needed for some_random_module.dummy_stuff.dummy_function is missing, please install it using 'pip install ag2\[optional_dep\]'",
|
|
54
|
-
):
|
|
55
|
-
actual()
|
|
56
|
-
else:
|
|
57
|
-
actual()
|
|
58
|
-
|
|
59
|
-
@pytest.mark.parametrize("except_for", [None, "dummy_function", ["dummy_function"]])
|
|
60
|
-
def test_function_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
61
|
-
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
62
|
-
def dummy_function() -> None:
|
|
63
|
-
"""Dummy function to test requires_optional_import"""
|
|
64
|
-
pass
|
|
65
|
-
|
|
66
|
-
if not except_for:
|
|
67
|
-
with pytest.raises(
|
|
68
|
-
ImportError,
|
|
69
|
-
match=r"Module 'some_optional_module' needed for test.test_import_utils.dummy_function is missing, please install it using 'pip install ag2\[optional_dep\]'",
|
|
70
|
-
):
|
|
71
|
-
dummy_function()
|
|
72
|
-
else:
|
|
73
|
-
dummy_function()
|
|
74
|
-
|
|
75
|
-
@pytest.mark.parametrize("except_for", [None, "dummy_method", ["dummy_method"]])
|
|
76
|
-
def test_method_attributes(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
77
|
-
class DummyClass:
|
|
78
|
-
def dummy_method(self) -> None:
|
|
79
|
-
"""Dummy method to test requires_optional_import"""
|
|
80
|
-
pass
|
|
81
|
-
|
|
82
|
-
assert hasattr(DummyClass.dummy_method, "__module__")
|
|
83
|
-
assert DummyClass.dummy_method.__module__ == "test.test_import_utils"
|
|
84
|
-
|
|
85
|
-
DummyClass.__module__ = "some_random_module.dummy_stuff"
|
|
86
|
-
DummyClass.dummy_method.__module__ = "some_random_module.dummy_stuff"
|
|
87
|
-
|
|
88
|
-
DummyClass.dummy_method = require_optional_import( # type: ignore[method-assign]
|
|
89
|
-
"some_optional_module", "optional_dep", except_for=except_for
|
|
90
|
-
)(DummyClass.dummy_method)
|
|
91
|
-
|
|
92
|
-
assert DummyClass.dummy_method is not None
|
|
93
|
-
assert DummyClass.dummy_method.__module__ == "some_random_module.dummy_stuff"
|
|
94
|
-
assert DummyClass.dummy_method.__name__ == "dummy_method"
|
|
95
|
-
assert DummyClass.dummy_method.__doc__ == "Dummy method to test requires_optional_import"
|
|
96
|
-
|
|
97
|
-
dummy = DummyClass()
|
|
98
|
-
|
|
99
|
-
if not except_for:
|
|
100
|
-
with pytest.raises(
|
|
101
|
-
ImportError,
|
|
102
|
-
match=r"Module 'some_optional_module' needed for some_random_module.dummy_stuff.dummy_method is missing, please install it using 'pip install ag2\[optional_dep\]",
|
|
103
|
-
):
|
|
104
|
-
dummy.dummy_method()
|
|
105
|
-
else:
|
|
106
|
-
dummy.dummy_method()
|
|
107
|
-
|
|
108
|
-
@pytest.mark.parametrize("except_for", [None, "dummy_method", ["dummy_method"]])
|
|
109
|
-
def test_method_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
110
|
-
class DummyClass:
|
|
111
|
-
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
112
|
-
def dummy_method(self) -> None:
|
|
113
|
-
"""Dummy method to test requires_optional_import"""
|
|
114
|
-
pass
|
|
115
|
-
|
|
116
|
-
dummy = DummyClass()
|
|
117
|
-
|
|
118
|
-
if not except_for:
|
|
119
|
-
with pytest.raises(
|
|
120
|
-
ImportError,
|
|
121
|
-
match=r"Module 'some_optional_module' needed for test.test_import_utils.dummy_method is missing, please install it using 'pip install ag2\[optional_dep\]'",
|
|
122
|
-
):
|
|
123
|
-
dummy.dummy_method()
|
|
124
|
-
else:
|
|
125
|
-
dummy.dummy_method()
|
|
126
|
-
|
|
127
|
-
@pytest.mark.parametrize("except_for", [None, "dummy_static_function", ["dummy_static_function"]])
|
|
128
|
-
def test_static_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
129
|
-
class DummyClass:
|
|
130
|
-
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
131
|
-
@staticmethod
|
|
132
|
-
def dummy_static_function() -> None:
|
|
133
|
-
"""Dummy static function to test requires_optional_import"""
|
|
134
|
-
pass
|
|
135
|
-
|
|
136
|
-
dummy = DummyClass()
|
|
137
|
-
|
|
138
|
-
if not except_for:
|
|
139
|
-
with pytest.raises(
|
|
140
|
-
ImportError,
|
|
141
|
-
match=r"Module 'some_optional_module' needed for test.test_import_utils.dummy_static_function is missing, please install it using 'pip install ag2\[optional_dep\]'",
|
|
142
|
-
):
|
|
143
|
-
dummy.dummy_static_function()
|
|
144
|
-
else:
|
|
145
|
-
dummy.dummy_static_function()
|
|
146
|
-
|
|
147
|
-
@pytest.mark.parametrize("except_for", [None, "dummy_property", ["dummy_property"]])
|
|
148
|
-
def test_property_call(self, except_for: Optional[Union[str, list[str]]]) -> None:
|
|
149
|
-
class DummyClass:
|
|
150
|
-
@property
|
|
151
|
-
@require_optional_import("some_optional_module", "optional_dep", except_for=except_for)
|
|
152
|
-
def dummy_property(self) -> int:
|
|
153
|
-
"""Dummy property to test requires_optional_import"""
|
|
154
|
-
return 4
|
|
155
|
-
|
|
156
|
-
dummy = DummyClass()
|
|
157
|
-
|
|
158
|
-
if not except_for:
|
|
159
|
-
with pytest.raises(
|
|
160
|
-
ImportError,
|
|
161
|
-
match=r"Module 'some_optional_module' needed for test.test_import_utils.dummy_property is missing, please install it using 'pip install ag2\[optional_dep\]'",
|
|
162
|
-
):
|
|
163
|
-
dummy.dummy_property
|
|
164
|
-
|
|
165
|
-
else:
|
|
166
|
-
dummy.dummy_property
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
class TestRequiresOptionalImportClasses:
|
|
170
|
-
@pytest.fixture
|
|
171
|
-
def dummy_cls(self) -> Type[Any]:
|
|
172
|
-
@require_optional_import("some_optional_module", "optional_dep")
|
|
173
|
-
class DummyClass:
|
|
174
|
-
def dummy_method(self) -> None:
|
|
175
|
-
"""Dummy method to test requires_optional_import"""
|
|
176
|
-
pass
|
|
177
|
-
|
|
178
|
-
@staticmethod
|
|
179
|
-
def dummy_static_method() -> None:
|
|
180
|
-
"""Dummy static method to test requires_optional_import"""
|
|
181
|
-
pass
|
|
182
|
-
|
|
183
|
-
@classmethod
|
|
184
|
-
def dummy_class_method(cls) -> None:
|
|
185
|
-
"""Dummy class method to test requires_optional_import"""
|
|
186
|
-
pass
|
|
187
|
-
|
|
188
|
-
@property
|
|
189
|
-
def dummy_property(self) -> int:
|
|
190
|
-
"""Dummy property to test requires_optional_import"""
|
|
191
|
-
return 4
|
|
192
|
-
|
|
193
|
-
return DummyClass
|
|
194
|
-
|
|
195
|
-
def test_class_init_call(self, dummy_cls: Type[Any]) -> None:
|
|
196
|
-
with pytest.raises(
|
|
197
|
-
ImportError,
|
|
198
|
-
match=r"Module 'some_optional_module' needed for __init__ is missing, please install it using 'pip install ag2\[optional_dep\]'",
|
|
199
|
-
):
|
|
200
|
-
dummy_cls()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|