From 306541e2472e8c207c2c053cc4ea5b1aeef3e332 Mon Sep 17 00:00:00 2001 From: Jack Gerrits Date: Fri, 13 Sep 2024 10:41:15 -0400 Subject: [PATCH] Fixup ruff config and inclusions (#495) * add tests to ruff for core * fmt * lint * lint fixes * fixup more dirs * dont include non python * lint fixes * lint fixes * fix dir name * dont relative include --- python/packages/agbench/pyproject.toml | 3 +- .../extracting-results-with-an-agent.ipynb | 2 +- .../termination-with-intervention.ipynb | 4 +- python/packages/autogen-core/pyproject.toml | 2 +- .../test_azure_container_code_executor.py | 49 ++++--- .../test_commandline_code_executor.py | 4 +- .../execution/test_extract_code_blocks.py | 2 - .../execution/test_user_defined_functions.py | 96 +++++++------- .../autogen-core/tests/test_base_agent.py | 5 +- .../autogen-core/tests/test_cancellation.py | 4 +- .../autogen-core/tests/test_closure_agent.py | 16 +-- .../autogen-core/tests/test_intervention.py | 27 ++-- .../autogen-core/tests/test_llm_usage.py | 1 - .../autogen-core/tests/test_model_client.py | 7 +- .../autogen-core/tests/test_routed_agent.py | 13 +- .../autogen-core/tests/test_runtime.py | 50 +++++-- .../autogen-core/tests/test_serialization.py | 22 ++- .../packages/autogen-core/tests/test_state.py | 7 +- .../autogen-core/tests/test_subscription.py | 23 ++-- .../autogen-core/tests/test_tool_agent.py | 38 +++--- .../packages/autogen-core/tests/test_tools.py | 65 +++++---- .../packages/autogen-core/tests/test_types.py | 4 +- .../autogen-core/tests/test_utils/__init__.py | 14 +- .../tests/test_utils/telemetry_test_utils.py | 1 + python/packages/team-one/pyproject.toml | 3 +- .../test_bing_markdown_search.py | 2 +- .../tests/browser_utils/test_mdconvert.py | 14 +- .../test_requests_markdown_browser.py | 27 ++-- .../tests/headless_web_surfer/conftest.py | 2 +- .../headless_web_surfer/test_web_surfer.py | 125 ++++++++++-------- .../packages/team-one/tests/test_example.py | 3 +- 31 files changed, 345 insertions(+), 290 deletions(-) diff --git a/python/packages/agbench/pyproject.toml b/python/packages/agbench/pyproject.toml index 0586eed11823..ad37a85c7ac1 100644 --- a/python/packages/agbench/pyproject.toml +++ b/python/packages/agbench/pyproject.toml @@ -42,8 +42,7 @@ agbench = "agbench.cli:main" extend = "../../pyproject.toml" exclude = ["build", "dist", "page_script.js", "src/agbench/res/Dockerfile", "src/agbench/template/global_init.sh"] include = [ - "src/**", - "examples/*.py", + "src/**" ] [tool.pyright] diff --git a/python/packages/autogen-core/docs/src/cookbook/extracting-results-with-an-agent.ipynb b/python/packages/autogen-core/docs/src/cookbook/extracting-results-with-an-agent.ipynb index 3094db49ee31..e858782d914e 100644 --- a/python/packages/autogen-core/docs/src/cookbook/extracting-results-with-an-agent.ipynb +++ b/python/packages/autogen-core/docs/src/cookbook/extracting-results-with-an-agent.ipynb @@ -26,7 +26,7 @@ "from dataclasses import dataclass\n", "\n", "from autogen_core.application import SingleThreadedAgentRuntime\n", - "from autogen_core.base import AgentRuntime, AgentId, MessageContext\n", + "from autogen_core.base import AgentId, AgentRuntime, MessageContext\n", "from autogen_core.components import ClosureAgent, DefaultSubscription, DefaultTopicId" ] }, diff --git a/python/packages/autogen-core/docs/src/cookbook/termination-with-intervention.ipynb b/python/packages/autogen-core/docs/src/cookbook/termination-with-intervention.ipynb index a66f6c3028c6..51f7f13879ed 100644 --- a/python/packages/autogen-core/docs/src/cookbook/termination-with-intervention.ipynb +++ b/python/packages/autogen-core/docs/src/cookbook/termination-with-intervention.ipynb @@ -23,9 +23,9 @@ "from typing import Any\n", "\n", "from autogen_core.application import SingleThreadedAgentRuntime\n", - "from autogen_core.components import RoutedAgent, message_handler, DefaultSubscription, DefaultTopicId\n", "from autogen_core.base import AgentId, MessageContext\n", - "from autogen_core.base.intervention import DefaultInterventionHandler" + "from autogen_core.base.intervention import DefaultInterventionHandler\n", + "from autogen_core.components import DefaultSubscription, DefaultTopicId, RoutedAgent, message_handler" ] }, { diff --git a/python/packages/autogen-core/pyproject.toml b/python/packages/autogen-core/pyproject.toml index 8f72488fdbac..d4c2a3ec73cb 100644 --- a/python/packages/autogen-core/pyproject.toml +++ b/python/packages/autogen-core/pyproject.toml @@ -69,7 +69,7 @@ dev-dependencies = [ [tool.ruff] extend = "../../pyproject.toml" exclude = ["build", "dist", "src/autogen_core/application/protos"] -include = ["src/**", "samples/*.py", "docs/**/*.ipynb"] +include = ["src/**", "samples/*.py", "docs/**/*.ipynb", "tests/**"] [tool.pyright] extend = "../../pyproject.toml" diff --git a/python/packages/autogen-core/tests/execution/test_azure_container_code_executor.py b/python/packages/autogen-core/tests/execution/test_azure_container_code_executor.py index dd65ef677461..a700f171ecbb 100644 --- a/python/packages/autogen-core/tests/execution/test_azure_container_code_executor.py +++ b/python/packages/autogen-core/tests/execution/test_azure_container_code_executor.py @@ -5,12 +5,12 @@ import os import sys import tempfile -from anyio import open_file import pytest -from azure.identity import DefaultAzureCredential -from autogen_core.components.code_executor import CodeBlock, AzureContainerCodeExecutor +from anyio import open_file from autogen_core.base import CancellationToken +from autogen_core.components.code_executor import AzureContainerCodeExecutor, CodeBlock +from azure.identity import DefaultAzureCredential UNIX_SHELLS = ["bash", "sh", "shell"] WINDOWS_SHELLS = ["ps1", "pwsh", "powershell"] @@ -20,6 +20,7 @@ POOL_ENDPOINT = os.getenv(ENVIRON_KEY_AZURE_POOL_ENDPOINT) + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -41,11 +42,7 @@ async def test_execute_code() -> None: CodeBlock(code="a = 100 + 100; print(a)", language="python"), ] code_result = await executor.execute_code_blocks(code_blocks, cancellation_token) - assert ( - code_result.exit_code == 0 - and "hello world!" in code_result.output - and "200" in code_result.output - ) + assert code_result.exit_code == 0 and "hello world!" in code_result.output and "200" in code_result.output # Test bash script. if sys.platform not in ["win32"]: @@ -58,11 +55,8 @@ async def test_execute_code() -> None: file_lines = ["import sys", "print('hello world!')", "a = 100 + 100", "print(a)"] code_blocks = [CodeBlock(code="\n".join(file_lines), language="python")] code_result = await executor.execute_code_blocks(code_blocks, cancellation_token) - assert ( - code_result.exit_code == 0 - and "hello world!" in code_result.output - and "200" in code_result.output - ) + assert code_result.exit_code == 0 and "hello world!" in code_result.output and "200" in code_result.output + @pytest.mark.skipif( not POOL_ENDPOINT, @@ -72,11 +66,14 @@ async def test_execute_code() -> None: async def test_azure_container_code_executor_timeout() -> None: assert POOL_ENDPOINT is not None cancellation_token = CancellationToken() - executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), timeout=1) + executor = AzureContainerCodeExecutor( + pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), timeout=1 + ) code_blocks = [CodeBlock(code="import time; time.sleep(10); print('hello world!')", language="python")] with pytest.raises(asyncio.TimeoutError): await executor.execute_code_blocks(code_blocks, cancellation_token) + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -111,7 +108,9 @@ async def test_upload_files() -> None: cancellation_token = CancellationToken() with tempfile.TemporaryDirectory() as temp_dir: - executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), work_dir=temp_dir) + executor = AzureContainerCodeExecutor( + pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), work_dir=temp_dir + ) async with await open_file(os.path.join(temp_dir, test_file_1), "w") as f: await f.write(test_file_1_contents) @@ -124,12 +123,17 @@ async def test_upload_files() -> None: assert test_file_1 in file_list assert test_file_2 in file_list - code_blocks = [CodeBlock(code=f""" + code_blocks = [ + CodeBlock( + code=f""" with open("{test_file_1}") as f: print(f.read()) with open("{test_file_2}") as f: print(f.read()) -""", language="python")] +""", + language="python", + ) + ] code_result = await executor.execute_code_blocks(code_blocks, cancellation_token) assert code_result.exit_code == 0 assert test_file_1_contents in code_result.output @@ -150,15 +154,20 @@ async def test_download_files() -> None: cancellation_token = CancellationToken() with tempfile.TemporaryDirectory() as temp_dir: - executor = AzureContainerCodeExecutor(pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), work_dir=temp_dir) + executor = AzureContainerCodeExecutor( + pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), work_dir=temp_dir + ) code_blocks = [ - CodeBlock(code=f""" + CodeBlock( + code=f""" with open("{test_file_1}", "w") as f: f.write("{test_file_1_contents}") with open("{test_file_2}", "w") as f: f.write("{test_file_2_contents}") -""", language="python"), +""", + language="python", + ), ] code_result = await executor.execute_code_blocks(code_blocks, cancellation_token) assert code_result.exit_code == 0 diff --git a/python/packages/autogen-core/tests/execution/test_commandline_code_executor.py b/python/packages/autogen-core/tests/execution/test_commandline_code_executor.py index 26868d1ba7bd..7ed8c026c80e 100644 --- a/python/packages/autogen-core/tests/execution/test_commandline_code_executor.py +++ b/python/packages/autogen-core/tests/execution/test_commandline_code_executor.py @@ -10,10 +10,10 @@ import pytest import pytest_asyncio +from aiofiles import open from autogen_core.base import CancellationToken from autogen_core.components.code_executor import CodeBlock, DockerCommandLineCodeExecutor, LocalCommandLineCodeExecutor -from aiofiles import open def docker_tests_enabled() -> bool: if os.environ.get("SKIP_DOCKER", "unset").lower() == "true": @@ -190,5 +190,5 @@ async def test_docker_commandline_code_executor_start_stop_context_manager() -> pytest.skip("Docker tests are disabled") with tempfile.TemporaryDirectory() as temp_dir: - async with DockerCommandLineCodeExecutor(work_dir=temp_dir) as exec: + async with DockerCommandLineCodeExecutor(work_dir=temp_dir) as _exec: pass diff --git a/python/packages/autogen-core/tests/execution/test_extract_code_blocks.py b/python/packages/autogen-core/tests/execution/test_extract_code_blocks.py index 99e439f32a9c..c955a2ddaa13 100644 --- a/python/packages/autogen-core/tests/execution/test_extract_code_blocks.py +++ b/python/packages/autogen-core/tests/execution/test_extract_code_blocks.py @@ -2,7 +2,6 @@ def test_extract_markdown_code_blocks() -> None: - text = """# This is a markdown text ```python print("Hello World") @@ -15,7 +14,6 @@ def test_extract_markdown_code_blocks() -> None: assert code_blocks[0].language == "python" assert code_blocks[0].code == 'print("Hello World")\n' - text = """More markdown text ```python print("Hello World") diff --git a/python/packages/autogen-core/tests/execution/test_user_defined_functions.py b/python/packages/autogen-core/tests/execution/test_user_defined_functions.py index c8f46d58dd04..7b92df1d7573 100644 --- a/python/packages/autogen-core/tests/execution/test_user_defined_functions.py +++ b/python/packages/autogen-core/tests/execution/test_user_defined_functions.py @@ -4,24 +4,24 @@ import os import tempfile - import polars import pytest -from azure.identity import DefaultAzureCredential +from autogen_core.base import CancellationToken from autogen_core.components.code_executor import ( + AzureContainerCodeExecutor, CodeBlock, FunctionWithRequirements, LocalCommandLineCodeExecutor, - AzureContainerCodeExecutor, with_requirements, ) -from autogen_core.base import CancellationToken +from azure.identity import DefaultAzureCredential ENVIRON_KEY_AZURE_POOL_ENDPOINT = "AZURE_POOL_ENDPOINT" DUMMY_POOL_ENDPOINT = "DUMMY_POOL_ENDPOINT" POOL_ENDPOINT = os.getenv(ENVIRON_KEY_AZURE_POOL_ENDPOINT) + def add_two_numbers(a: int, b: int) -> int: """Add two numbers together.""" return a + b @@ -60,9 +60,7 @@ def function_missing_reqs() -> "polars.DataFrame": async def test_can_load_function_with_reqs() -> None: with tempfile.TemporaryDirectory() as temp_dir: cancellation_token = CancellationToken() - executor = LocalCommandLineCodeExecutor( - work_dir=temp_dir, functions=[load_data] - ) + executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[load_data]) code = f"""from {executor.functions_module} import load_data import polars @@ -74,11 +72,12 @@ async def test_can_load_function_with_reqs() -> None: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert result.output == "John\n" assert result.exit_code == 0 + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -91,7 +90,7 @@ async def test_azure_can_load_function_with_reqs() -> None: pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[load_data] ) # AzureContainerCodeExecutor doesn't use the functions module import - code = f"""import polars + code = """import polars # Get first row's name data = load_data() @@ -101,18 +100,17 @@ async def test_azure_can_load_function_with_reqs() -> None: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert azure_result.output == "John\n" assert azure_result.exit_code == 0 + @pytest.mark.asyncio async def test_can_load_function() -> None: with tempfile.TemporaryDirectory() as temp_dir: cancellation_token = CancellationToken() - executor = LocalCommandLineCodeExecutor( - work_dir=temp_dir, functions=[add_two_numbers] - ) + executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[add_two_numbers]) code = f"""from {executor.functions_module} import add_two_numbers print(add_two_numbers(1, 2))""" @@ -120,7 +118,7 @@ async def test_can_load_function() -> None: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert result.output == "3\n" assert result.exit_code == 0 @@ -139,24 +137,23 @@ async def test_azure_can_load_function() -> None: pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[add_two_numbers] ) # AzureContainerCodeExecutor doesn't use the functions module import - code = f"""print(add_two_numbers(1, 2))""" + code = """print(add_two_numbers(1, 2))""" azure_result = await azure_executor.execute_code_blocks( code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert azure_result.output == "3\n" assert azure_result.exit_code == 0 + @pytest.mark.asyncio async def test_fails_for_function_incorrect_import() -> None: with tempfile.TemporaryDirectory() as temp_dir: cancellation_token = CancellationToken() - executor = LocalCommandLineCodeExecutor( - work_dir=temp_dir, functions=[function_incorrect_import] - ) + executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[function_incorrect_import]) code = f"""from {executor.functions_module} import function_incorrect_import function_incorrect_import()""" @@ -165,9 +162,10 @@ async def test_fails_for_function_incorrect_import() -> None: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -177,25 +175,26 @@ async def test_azure_fails_for_function_incorrect_import() -> None: assert POOL_ENDPOINT is not None cancellation_token = CancellationToken() azure_executor = AzureContainerCodeExecutor( - pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[function_incorrect_import] + pool_management_endpoint=POOL_ENDPOINT, + credential=DefaultAzureCredential(), + functions=[function_incorrect_import], ) - code = f"""function_incorrect_import()""" + code = """function_incorrect_import()""" with pytest.raises(ValueError): await azure_executor.execute_code_blocks( code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) + @pytest.mark.asyncio async def test_fails_for_function_incorrect_dep() -> None: with tempfile.TemporaryDirectory() as temp_dir: cancellation_token = CancellationToken() - executor = LocalCommandLineCodeExecutor( - work_dir=temp_dir, functions=[function_incorrect_dep] - ) + executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[function_incorrect_dep]) code = f"""from {executor.functions_module} import function_incorrect_dep function_incorrect_dep()""" @@ -204,9 +203,10 @@ async def test_fails_for_function_incorrect_dep() -> None: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -218,34 +218,34 @@ async def test_azure_fails_for_function_incorrect_dep() -> None: azure_executor = AzureContainerCodeExecutor( pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[function_incorrect_dep] ) - code = f"""function_incorrect_dep()""" + code = """function_incorrect_dep()""" with pytest.raises(ValueError): await azure_executor.execute_code_blocks( code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) + def test_formatted_prompt() -> None: assert_str = '''def add_two_numbers(a: int, b: int) -> int: """Add two numbers together.""" ''' with tempfile.TemporaryDirectory() as temp_dir: - executor = LocalCommandLineCodeExecutor( - work_dir=temp_dir, functions=[add_two_numbers] - ) + executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[add_two_numbers]) result = executor.format_functions_for_prompt() - assert (assert_str in result) + assert assert_str in result azure_executor = AzureContainerCodeExecutor( pool_management_endpoint=DUMMY_POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[add_two_numbers] ) azure_result = azure_executor.format_functions_for_prompt() - assert (assert_str in azure_result) + assert assert_str in azure_result + def test_formatted_prompt_str_func() -> None: func = FunctionWithRequirements.from_str( @@ -254,25 +254,25 @@ def add_two_numbers(a: int, b: int) -> int: """Add two numbers together.""" return a + b ''' - ) + ) assert_str = '''def add_two_numbers(a: int, b: int) -> int: """Add two numbers together.""" ''' with tempfile.TemporaryDirectory() as temp_dir: - executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[func]) result = executor.format_functions_for_prompt() - assert (assert_str in result) + assert assert_str in result azure_executor = AzureContainerCodeExecutor( pool_management_endpoint=DUMMY_POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[func] ) azure_result = azure_executor.format_functions_for_prompt() - assert (assert_str in azure_result) + assert assert_str in azure_result + @pytest.mark.asyncio async def test_can_load_str_function_with_reqs() -> None: @@ -294,11 +294,12 @@ def add_two_numbers(a: int, b: int) -> int: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert result.output == "3\n" assert result.exit_code == 0 + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -317,19 +318,19 @@ def add_two_numbers(a: int, b: int) -> int: azure_executor = AzureContainerCodeExecutor( pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[func] ) - code = f"""print(add_two_numbers(1, 2))""" + code = """print(add_two_numbers(1, 2))""" azure_result = await azure_executor.execute_code_blocks( code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert azure_result.output == "3\n" assert azure_result.exit_code == 0 -def test_cant_load_broken_str_function_with_reqs() -> None: +def test_cant_load_broken_str_function_with_reqs() -> None: with pytest.raises(ValueError): _ = FunctionWithRequirements.from_str( ''' @@ -360,11 +361,12 @@ def add_two_numbers(a: int, b: int) -> int: code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) assert "TypeError: unsupported operand type(s) for +:" in result.output assert result.exit_code == 1 + @pytest.mark.skipif( not POOL_ENDPOINT, reason="do not run if pool endpoint is not defined", @@ -384,15 +386,15 @@ def add_two_numbers(a: int, b: int) -> int: azure_executor = AzureContainerCodeExecutor( pool_management_endpoint=POOL_ENDPOINT, credential=DefaultAzureCredential(), functions=[func] ) - code = f"""print(add_two_numbers(object(), False))""" + code = """print(add_two_numbers(object(), False))""" azure_result = await azure_executor.execute_code_blocks( code_blocks=[ CodeBlock(language="python", code=code), ], - cancellation_token=cancellation_token + cancellation_token=cancellation_token, ) - #result.output = result.output.encode().decode('unicode_escape') + # result.output = result.output.encode().decode('unicode_escape') print(azure_result.output) assert "TypeError: unsupported operand type(s) for +:" in azure_result.output - assert azure_result.exit_code == 1 \ No newline at end of file + assert azure_result.exit_code == 1 diff --git a/python/packages/autogen-core/tests/test_base_agent.py b/python/packages/autogen-core/tests/test_base_agent.py index cd3fdcd8b4cf..884a42527d39 100644 --- a/python/packages/autogen-core/tests/test_base_agent.py +++ b/python/packages/autogen-core/tests/test_base_agent.py @@ -1,11 +1,9 @@ import pytest +from autogen_core.base import AgentId, AgentInstantiationContext, AgentRuntime from pytest_mock import MockerFixture -from autogen_core.base import AgentRuntime, AgentInstantiationContext, AgentId - from test_utils import NoopAgent - @pytest.mark.asyncio async def test_base_agent_create(mocker: MockerFixture) -> None: runtime = mocker.Mock(spec=AgentRuntime) @@ -15,4 +13,3 @@ async def test_base_agent_create(mocker: MockerFixture) -> None: agent = NoopAgent() assert agent.runtime == runtime assert agent.id == AgentId("name", "namespace") - diff --git a/python/packages/autogen-core/tests/test_cancellation.py b/python/packages/autogen-core/tests/test_cancellation.py index 470655582a43..d971ef50fc36 100644 --- a/python/packages/autogen-core/tests/test_cancellation.py +++ b/python/packages/autogen-core/tests/test_cancellation.py @@ -3,10 +3,8 @@ import pytest from autogen_core.application import SingleThreadedAgentRuntime +from autogen_core.base import AgentId, AgentInstantiationContext, CancellationToken, MessageContext from autogen_core.components import RoutedAgent, message_handler -from autogen_core.base import AgentId, CancellationToken -from autogen_core.base import MessageContext -from autogen_core.base import AgentInstantiationContext @dataclass diff --git a/python/packages/autogen-core/tests/test_closure_agent.py b/python/packages/autogen-core/tests/test_closure_agent.py index 32a358cf50b7..8fe391a9a671 100644 --- a/python/packages/autogen-core/tests/test_closure_agent.py +++ b/python/packages/autogen-core/tests/test_closure_agent.py @@ -1,27 +1,18 @@ - - +import asyncio from dataclasses import dataclass import pytest from autogen_core.application import SingleThreadedAgentRuntime - -from autogen_core.components._type_subscription import TypeSubscription -from autogen_core.base import AgentRuntime, AgentId - +from autogen_core.base import AgentId, AgentRuntime, MessageContext, TopicId from autogen_core.components import ClosureAgent +from autogen_core.components._type_subscription import TypeSubscription -import asyncio - -from autogen_core.base import MessageContext -from autogen_core.base import TopicId - @dataclass class Message: content: str - @pytest.mark.asyncio async def test_register_receives_publish() -> None: runtime = SingleThreadedAgentRuntime() @@ -41,7 +32,6 @@ async def log_message(_runtime: AgentRuntime, id: AgentId, message: Message, ctx await runtime.publish_message(Message("second message"), topic_id=topic_id) await runtime.publish_message(Message("third message"), topic_id=topic_id) - await runtime.stop_when_idle() assert queue.qsize() == 3 diff --git a/python/packages/autogen-core/tests/test_intervention.py b/python/packages/autogen-core/tests/test_intervention.py index adbc76d7ad35..6b3d18c7e0a4 100644 --- a/python/packages/autogen-core/tests/test_intervention.py +++ b/python/packages/autogen-core/tests/test_intervention.py @@ -8,7 +8,6 @@ @pytest.mark.asyncio async def test_intervention_count_messages() -> None: - class DebugInterventionHandler(DefaultInterventionHandler): def __init__(self) -> None: self.num_messages = 0 @@ -31,11 +30,13 @@ async def on_send(self, message: MessageType, *, sender: AgentId | None, recipie loopback_agent = await runtime.try_get_underlying_agent_instance(loopback, type=LoopbackAgent) assert loopback_agent.num_calls == 1 + @pytest.mark.asyncio async def test_intervention_drop_send() -> None: - class DropSendInterventionHandler(DefaultInterventionHandler): - async def on_send(self, message: MessageType, *, sender: AgentId | None, recipient: AgentId) -> MessageType | type[DropMessage]: + async def on_send( + self, message: MessageType, *, sender: AgentId | None, recipient: AgentId + ) -> MessageType | type[DropMessage]: return DropMessage handler = DropSendInterventionHandler() @@ -56,9 +57,10 @@ async def on_send(self, message: MessageType, *, sender: AgentId | None, recipie @pytest.mark.asyncio async def test_intervention_drop_response() -> None: - class DropResponseInterventionHandler(DefaultInterventionHandler): - async def on_response(self, message: MessageType, *, sender: AgentId, recipient: AgentId | None) -> MessageType | type[DropMessage]: + async def on_response( + self, message: MessageType, *, sender: AgentId, recipient: AgentId | None + ) -> MessageType | type[DropMessage]: return DropMessage handler = DropResponseInterventionHandler() @@ -76,12 +78,13 @@ async def on_response(self, message: MessageType, *, sender: AgentId, recipient: @pytest.mark.asyncio async def test_intervention_raise_exception_on_send() -> None: - class InterventionException(Exception): pass - class ExceptionInterventionHandler(DefaultInterventionHandler): # type: ignore - async def on_send(self, message: MessageType, *, sender: AgentId | None, recipient: AgentId) -> MessageType | type[DropMessage]: # type: ignore + class ExceptionInterventionHandler(DefaultInterventionHandler): # type: ignore + async def on_send( + self, message: MessageType, *, sender: AgentId | None, recipient: AgentId + ) -> MessageType | type[DropMessage]: # type: ignore raise InterventionException handler = ExceptionInterventionHandler() @@ -99,14 +102,16 @@ async def on_send(self, message: MessageType, *, sender: AgentId | None, recipie long_running_agent = await runtime.try_get_underlying_agent_instance(loopback, type=LoopbackAgent) assert long_running_agent.num_calls == 0 + @pytest.mark.asyncio async def test_intervention_raise_exception_on_respond() -> None: - class InterventionException(Exception): pass - class ExceptionInterventionHandler(DefaultInterventionHandler): # type: ignore - async def on_response(self, message: MessageType, *, sender: AgentId, recipient: AgentId | None) -> MessageType | type[DropMessage]: # type: ignore + class ExceptionInterventionHandler(DefaultInterventionHandler): # type: ignore + async def on_response( + self, message: MessageType, *, sender: AgentId, recipient: AgentId | None + ) -> MessageType | type[DropMessage]: # type: ignore raise InterventionException handler = ExceptionInterventionHandler() diff --git a/python/packages/autogen-core/tests/test_llm_usage.py b/python/packages/autogen-core/tests/test_llm_usage.py index 83b465b97d91..9f858669260e 100644 --- a/python/packages/autogen-core/tests/test_llm_usage.py +++ b/python/packages/autogen-core/tests/test_llm_usage.py @@ -5,7 +5,6 @@ def test_llm_usage() -> None: - # Set up the logging configuration to use the custom handler logger = logging.getLogger(EVENT_LOGGER_NAME) logger.setLevel(logging.INFO) diff --git a/python/packages/autogen-core/tests/test_model_client.py b/python/packages/autogen-core/tests/test_model_client.py index e4d793e5b90b..988a6fe6a219 100644 --- a/python/packages/autogen-core/tests/test_model_client.py +++ b/python/packages/autogen-core/tests/test_model_client.py @@ -2,6 +2,7 @@ from typing import Any, AsyncGenerator, List import pytest +from autogen_core.base import CancellationToken from autogen_core.components import Image from autogen_core.components.models import ( AssistantMessage, @@ -16,7 +17,6 @@ ) from autogen_core.components.models._model_info import resolve_model from autogen_core.components.tools import FunctionTool -from autogen_core.base import CancellationToken from openai.resources.chat.completions import AsyncCompletions from openai.types.chat.chat_completion import ChatCompletion, Choice from openai.types.chat.chat_completion_chunk import ChatCompletionChunk, ChoiceDelta @@ -48,9 +48,7 @@ async def _mock_create_stream(*args: Any, **kwargs: Any) -> AsyncGenerator[ChatC ) -async def _mock_create( - *args: Any, **kwargs: Any -) -> ChatCompletion | AsyncGenerator[ChatCompletionChunk, None]: +async def _mock_create(*args: Any, **kwargs: Any) -> ChatCompletion | AsyncGenerator[ChatCompletionChunk, None]: stream = kwargs.get("stream", False) model = resolve_model(kwargs.get("model", "gpt-4o")) if not stream: @@ -68,6 +66,7 @@ async def _mock_create( else: return _mock_create_stream(*args, **kwargs) + @pytest.mark.asyncio async def test_openai_chat_completion_client() -> None: client = OpenAIChatCompletionClient(model="gpt-4o", api_key="api_key") diff --git a/python/packages/autogen-core/tests/test_routed_agent.py b/python/packages/autogen-core/tests/test_routed_agent.py index 3d0c79a38c40..e4afbdfaed3f 100644 --- a/python/packages/autogen-core/tests/test_routed_agent.py +++ b/python/packages/autogen-core/tests/test_routed_agent.py @@ -90,6 +90,7 @@ async def handler_one(self, message: TestMessage, ctx: MessageContext) -> None: async def handler_two(self, message: TestMessage, ctx: MessageContext) -> None: self.handler_two_called = True + @pytest.mark.asyncio async def test_routed_agent_message_matching() -> None: runtime = SingleThreadedAgentRuntime() @@ -98,19 +99,19 @@ async def test_routed_agent_message_matching() -> None: agent = await runtime.try_get_underlying_agent_instance(agent_id, type=RoutedAgentMessageCustomMatch) assert agent is not None - assert agent.handler_one_called == False - assert agent.handler_two_called == False + assert agent.handler_one_called is False + assert agent.handler_two_called is False runtime.start() await runtime.send_message(TestMessage("one"), recipient=agent_id) await runtime.stop_when_idle() agent = await runtime.try_get_underlying_agent_instance(agent_id, type=RoutedAgentMessageCustomMatch) - assert agent.handler_one_called == True - assert agent.handler_two_called == False + assert agent.handler_one_called is True + assert agent.handler_two_called is False runtime.start() await runtime.send_message(TestMessage("two"), recipient=agent_id) await runtime.stop_when_idle() agent = await runtime.try_get_underlying_agent_instance(agent_id, type=RoutedAgentMessageCustomMatch) - assert agent.handler_one_called == True - assert agent.handler_two_called == True + assert agent.handler_one_called is True + assert agent.handler_two_called is True diff --git a/python/packages/autogen-core/tests/test_runtime.py b/python/packages/autogen-core/tests/test_runtime.py index bfdc5073f941..60000484aca7 100644 --- a/python/packages/autogen-core/tests/test_runtime.py +++ b/python/packages/autogen-core/tests/test_runtime.py @@ -10,12 +10,13 @@ TopicId, ) from autogen_core.components import DefaultSubscription, DefaultTopicId, TypeSubscription +from opentelemetry.sdk.trace import TracerProvider from test_utils import CascadingAgent, CascadingMessageType, LoopbackAgent, MessageType, NoopAgent from test_utils.telemetry_test_utils import TestExporter, get_test_tracer_provider -from opentelemetry.sdk.trace import TracerProvider test_exporter = TestExporter() + @pytest.fixture def tracer_provider() -> TracerProvider: test_exporter.clear() @@ -59,13 +60,19 @@ async def test_register_receives_publish(tracer_provider: TracerProvider) -> Non assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 exported_spans = test_exporter.get_exported_spans() assert len(exported_spans) == 3 span_names = [span.name for span in exported_spans] - assert span_names == ["autogen create default.(default)-T", "autogen process name.(default)-A", "autogen publish default.(default)-T"] + assert span_names == [ + "autogen create default.(default)-T", + "autogen process name.(default)-A", + "autogen publish default.(default)-T", + ] @pytest.mark.asyncio @@ -98,6 +105,7 @@ async def test_register_receives_publish_cascade() -> None: agent = await runtime.try_get_underlying_agent_instance(AgentId(f"name{i}", "default"), CascadingAgent) assert agent.num_calls == total_num_calls_expected + @pytest.mark.asyncio async def test_register_factory_explicit_name() -> None: runtime = SingleThreadedAgentRuntime() @@ -115,14 +123,19 @@ async def test_register_factory_explicit_name() -> None: assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 + @pytest.mark.asyncio async def test_register_factory_context_var_name() -> None: runtime = SingleThreadedAgentRuntime() - await runtime.register("name", LoopbackAgent, lambda: [TypeSubscription("default", SubscriptionInstantiationContext.agent_type().type)]) + await runtime.register( + "name", LoopbackAgent, lambda: [TypeSubscription("default", SubscriptionInstantiationContext.agent_type().type)] + ) runtime.start() agent_id = AgentId("name", key="default") topic_id = TopicId("default", "default") @@ -135,9 +148,12 @@ async def test_register_factory_context_var_name() -> None: assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 + @pytest.mark.asyncio async def test_register_factory_async() -> None: runtime = SingleThreadedAgentRuntime() @@ -159,9 +175,12 @@ async def sub_factory() -> list[Subscription]: assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 + @pytest.mark.asyncio async def test_register_factory_direct_list() -> None: runtime = SingleThreadedAgentRuntime() @@ -179,7 +198,9 @@ async def test_register_factory_direct_list() -> None: assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 @@ -199,9 +220,12 @@ async def test_default_subscription() -> None: assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 + @pytest.mark.asyncio async def test_non_default_default_subscription() -> None: runtime = SingleThreadedAgentRuntime() @@ -218,7 +242,9 @@ async def test_non_default_default_subscription() -> None: assert long_running_agent.num_calls == 1 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 0 @@ -238,5 +264,7 @@ async def test_non_publish_to_other_source() -> None: assert long_running_agent.num_calls == 0 # Agent in other namespace should not have received the message - other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance(AgentId("name", key="other"), type=LoopbackAgent) + other_long_running_agent: LoopbackAgent = await runtime.try_get_underlying_agent_instance( + AgentId("name", key="other"), type=LoopbackAgent + ) assert other_long_running_agent.num_calls == 1 diff --git a/python/packages/autogen-core/tests/test_serialization.py b/python/packages/autogen-core/tests/test_serialization.py index 28cce82a38c0..7ca3fa722b4d 100644 --- a/python/packages/autogen-core/tests/test_serialization.py +++ b/python/packages/autogen-core/tests/test_serialization.py @@ -1,32 +1,41 @@ -from pydantic import BaseModel from dataclasses import dataclass import pytest +from autogen_core.base import ( + JSON_DATA_CONTENT_TYPE, + MessageSerializer, + Serialization, + try_get_known_serializers_for_type, +) +from pydantic import BaseModel -from autogen_core.base import Serialization -from autogen_core.base import JSON_DATA_CONTENT_TYPE, MessageSerializer, try_get_known_serializers_for_type class PydanticMessage(BaseModel): message: str + class NestingPydanticMessage(BaseModel): message: str nested: PydanticMessage + @dataclass class DataclassMessage: message: str + @dataclass class NestingDataclassMessage: message: str nested: DataclassMessage + @dataclass class NestingPydanticDataclassMessage: message: str nested: PydanticMessage + def test_pydantic() -> None: serde = Serialization() serde.add_serializer(try_get_known_serializers_for_type(PydanticMessage)) @@ -39,6 +48,7 @@ def test_pydantic() -> None: deserialized = serde.deserialize(json, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE) assert deserialized == message + def test_nested_pydantic() -> None: serde = Serialization() serde.add_serializer(try_get_known_serializers_for_type(NestingPydanticMessage)) @@ -50,6 +60,7 @@ def test_nested_pydantic() -> None: deserialized = serde.deserialize(json, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE) assert deserialized == message + def test_dataclass() -> None: serde = Serialization() serde.add_serializer(try_get_known_serializers_for_type(DataclassMessage)) @@ -61,6 +72,7 @@ def test_dataclass() -> None: deserialized = serde.deserialize(json, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE) assert deserialized == message + def test_nesting_dataclass_dataclass() -> None: serde = Serialization() serde.add_serializer(try_get_known_serializers_for_type(NestingDataclassMessage)) @@ -70,6 +82,7 @@ def test_nesting_dataclass_dataclass() -> None: with pytest.raises(ValueError): _json = serde.serialize(message, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE) + def test_nesting_dataclass_pydantic() -> None: serde = Serialization() serde.add_serializer(try_get_known_serializers_for_type(NestingPydanticDataclassMessage)) @@ -79,6 +92,7 @@ def test_nesting_dataclass_pydantic() -> None: with pytest.raises(ValueError): _json = serde.serialize(message, type_name=name, data_content_type=JSON_DATA_CONTENT_TYPE) + def test_invalid_type() -> None: serde = Serialization() try: @@ -86,6 +100,7 @@ def test_invalid_type() -> None: except ValueError as e: assert str(e) == "Unsupported type " + def test_custom_type() -> None: serde = Serialization() @@ -105,7 +120,6 @@ def deserialize(self, payload: bytes) -> str: def serialize(self, message: str) -> bytes: return f'"{message}"'.encode("utf-8") - serde.add_serializer(CustomStringTypeSerializer()) message = "hello" json = serde.serialize(message, type_name="custom_str", data_content_type="str") diff --git a/python/packages/autogen-core/tests/test_state.py b/python/packages/autogen-core/tests/test_state.py index 987fcbc56ab0..cba5631bec71 100644 --- a/python/packages/autogen-core/tests/test_state.py +++ b/python/packages/autogen-core/tests/test_state.py @@ -2,8 +2,7 @@ import pytest from autogen_core.application import SingleThreadedAgentRuntime -from autogen_core.base import BaseAgent, MessageContext -from autogen_core.base import AgentId +from autogen_core.base import AgentId, BaseAgent, MessageContext class StatefulAgent(BaseAgent): @@ -40,6 +39,7 @@ async def test_agent_can_save_state() -> None: agent1.load_state(agent1_state) assert agent1.state == 1 + @pytest.mark.asyncio async def test_runtime_can_save_state() -> None: runtime = SingleThreadedAgentRuntime() @@ -60,6 +60,3 @@ async def test_runtime_can_save_state() -> None: await runtime2.load_state(runtime_state) assert agent2.state == 1 - - - diff --git a/python/packages/autogen-core/tests/test_subscription.py b/python/packages/autogen-core/tests/test_subscription.py index 99b22b182589..74f345b58bf1 100644 --- a/python/packages/autogen-core/tests/test_subscription.py +++ b/python/packages/autogen-core/tests/test_subscription.py @@ -1,23 +1,17 @@ -from autogen_core.application import SingleThreadedAgentRuntime -from autogen_core.components import TypeSubscription -from autogen_core.base import TopicId, AgentId import pytest from autogen_core.application import SingleThreadedAgentRuntime -from autogen_core.components import TypeSubscription, DefaultTopicId -from autogen_core.base import AgentId -from autogen_core.base import TopicId +from autogen_core.base import AgentId, TopicId +from autogen_core.base.exceptions import CantHandleException +from autogen_core.components import DefaultTopicId, TypeSubscription from test_utils import LoopbackAgent, MessageType -import pytest - -from autogen_core.base.exceptions import CantHandleException def test_type_subscription_match() -> None: sub = TypeSubscription(topic_type="t1", agent_type="a1") - assert sub.is_match(TopicId(type="t0", source="s1")) == False - assert sub.is_match(TopicId(type="t1", source="s1")) == True - assert sub.is_match(TopicId(type="t1", source="s2")) == True + assert sub.is_match(TopicId(type="t0", source="s1")) is False + assert sub.is_match(TopicId(type="t1", source="s1")) is True + assert sub.is_match(TopicId(type="t1", source="s2")) is True def test_type_subscription_map() -> None: @@ -39,7 +33,9 @@ async def test_non_default_default_subscription() -> None: await runtime.stop_when_idle() # Not subscribed - agent_instance = await runtime.try_get_underlying_agent_instance(AgentId("MyAgent", key="default"), type=LoopbackAgent) + agent_instance = await runtime.try_get_underlying_agent_instance( + AgentId("MyAgent", key="default"), type=LoopbackAgent + ) assert agent_instance.num_calls == 0 # Subscribed @@ -84,4 +80,3 @@ async def test_non_default_default_subscription() -> None: await runtime.stop_when_idle() assert agent_instance.num_calls == 3 - diff --git a/python/packages/autogen-core/tests/test_tool_agent.py b/python/packages/autogen-core/tests/test_tool_agent.py index 00aa83ab6369..322fdf6b7941 100644 --- a/python/packages/autogen-core/tests/test_tool_agent.py +++ b/python/packages/autogen-core/tests/test_tool_agent.py @@ -3,15 +3,16 @@ from typing import Any, AsyncGenerator, List import pytest -from openai.resources.chat.completions import AsyncCompletions -from openai.types.chat.chat_completion import ChatCompletion, Choice -from openai.types.chat.chat_completion_chunk import ChatCompletionChunk -from openai.types.chat.chat_completion_message import ChatCompletionMessage -from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall, Function -from openai.types.completion_usage import CompletionUsage - from autogen_core.application import SingleThreadedAgentRuntime +from autogen_core.base import AgentId, CancellationToken from autogen_core.components import FunctionCall +from autogen_core.components.models import ( + AssistantMessage, + FunctionExecutionResult, + FunctionExecutionResultMessage, + OpenAIChatCompletionClient, + UserMessage, +) from autogen_core.components.tool_agent import ( InvalidToolArgumentsException, ToolAgent, @@ -20,15 +21,12 @@ tool_agent_caller_loop, ) from autogen_core.components.tools import FunctionTool, Tool -from autogen_core.base import CancellationToken, AgentId -from autogen_core.components.models import ( - AssistantMessage, - FunctionExecutionResult, - FunctionExecutionResultMessage, - OpenAIChatCompletionClient, - UserMessage, -) -from autogen_core.components.tools import FunctionTool +from openai.resources.chat.completions import AsyncCompletions +from openai.types.chat.chat_completion import ChatCompletion, Choice +from openai.types.chat.chat_completion_chunk import ChatCompletionChunk +from openai.types.chat.chat_completion_message import ChatCompletionMessage +from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall, Function +from openai.types.completion_usage import CompletionUsage def _pass_function(input: str) -> str: @@ -150,7 +148,7 @@ async def test_caller_loop(monkeypatch: pytest.MonkeyPatch) -> None: mock = _MockChatCompletion(model="gpt-4o-2024-05-13") monkeypatch.setattr(AsyncCompletions, "create", mock.mock_create) client = OpenAIChatCompletionClient(model="gpt-4o-2024-05-13", api_key="api_key") - tools : List[Tool] = [FunctionTool(_pass_function, name="pass", description="Pass function")] + tools: List[Tool] = [FunctionTool(_pass_function, name="pass", description="Pass function")] runtime = SingleThreadedAgentRuntime() await runtime.register( "tool_agent", @@ -162,11 +160,7 @@ async def test_caller_loop(monkeypatch: pytest.MonkeyPatch) -> None: agent = AgentId("tool_agent", "default") runtime.start() messages = await tool_agent_caller_loop( - runtime, - agent, - client, - [UserMessage(content="Hello", source="user")], - tool_schema=tools + runtime, agent, client, [UserMessage(content="Hello", source="user")], tool_schema=tools ) assert len(messages) == 3 assert isinstance(messages[0], AssistantMessage) diff --git a/python/packages/autogen-core/tests/test_tools.py b/python/packages/autogen-core/tests/test_tools.py index a18b18734d3d..2a0c82b8f67b 100644 --- a/python/packages/autogen-core/tests/test_tools.py +++ b/python/packages/autogen-core/tests/test_tools.py @@ -1,12 +1,11 @@ - import inspect from typing import Annotated import pytest +from autogen_core.base import CancellationToken from autogen_core.components._function_utils import get_typed_signature -from autogen_core.components.tools import BaseTool, FunctionTool from autogen_core.components.models._openai_client import convert_tools -from autogen_core.base import CancellationToken +from autogen_core.components.tools import BaseTool, FunctionTool from pydantic import BaseModel, Field, model_serializer from pydantic_core import PydanticUndefined @@ -33,6 +32,7 @@ async def run(self, args: MyArgs, cancellation_token: CancellationToken) -> MyRe self.called_count += 1 return MyResult(result="value") + def test_tool_schema_generation() -> None: schema = MyTool().schema @@ -48,9 +48,11 @@ def test_tool_schema_generation() -> None: assert schema["parameters"]["required"] == ["query"] assert len(schema["parameters"]["properties"]) == 1 + def test_func_tool_schema_generation() -> None: def my_function(arg: str, other: Annotated[int, "int arg"], nonrequired: int = 5) -> MyResult: return MyResult(result="test") + tool = FunctionTool(my_function, description="Function tool.") schema = tool.schema @@ -70,9 +72,11 @@ def my_function(arg: str, other: Annotated[int, "int arg"], nonrequired: int = 5 assert schema["parameters"]["required"] == ["arg", "other"] assert len(schema["parameters"]["properties"]) == 3 + def test_func_tool_schema_generation_only_default_arg() -> None: def my_function(arg: str = "default") -> MyResult: return MyResult(result="test") + tool = FunctionTool(my_function, description="Function tool.") schema = tool.schema @@ -87,7 +91,7 @@ def my_function(arg: str = "default") -> MyResult: @pytest.mark.asyncio -async def test_tool_run()-> None: +async def test_tool_run() -> None: tool = MyTool() result = await tool.run_json({"query": "test"}, CancellationToken()) @@ -101,7 +105,7 @@ async def test_tool_run()-> None: assert tool.called_count == 3 -def test_tool_properties()-> None: +def test_tool_properties() -> None: tool = MyTool() assert tool.name == "TestTool" @@ -110,7 +114,8 @@ def test_tool_properties()-> None: assert tool.return_type() == MyResult assert tool.state_type() is None -def test_get_typed_signature()-> None: + +def test_get_typed_signature() -> None: def my_function() -> str: return "result" @@ -119,7 +124,8 @@ def my_function() -> str: assert len(sig.parameters) == 0 assert sig.return_annotation == str -def test_get_typed_signature_annotated()-> None: + +def test_get_typed_signature_annotated() -> None: def my_function() -> Annotated[str, "The return type"]: return "result" @@ -128,7 +134,8 @@ def my_function() -> Annotated[str, "The return type"]: assert len(sig.parameters) == 0 assert sig.return_annotation == Annotated[str, "The return type"] -def test_get_typed_signature_string()-> None: + +def test_get_typed_signature_string() -> None: def my_function() -> "str": return "result" @@ -138,7 +145,7 @@ def my_function() -> "str": assert sig.return_annotation == str -def test_func_tool()-> None: +def test_func_tool() -> None: def my_function() -> str: return "result" @@ -149,7 +156,8 @@ def my_function() -> str: assert issubclass(tool.return_type(), str) assert tool.state_type() is None -def test_func_tool_annotated_arg()-> None: + +def test_func_tool_annotated_arg() -> None: def my_function(my_arg: Annotated[str, "test description"]) -> str: return "result" @@ -166,7 +174,8 @@ def my_function(my_arg: Annotated[str, "test description"]) -> str: assert tool.return_type() == str assert tool.state_type() is None -def test_func_tool_return_annotated()-> None: + +def test_func_tool_return_annotated() -> None: def my_function() -> Annotated[str, "test description"]: return "result" @@ -177,7 +186,8 @@ def my_function() -> Annotated[str, "test description"]: assert tool.return_type() == str assert tool.state_type() is None -def test_func_tool_no_args()-> None: + +def test_func_tool_no_args() -> None: def my_function() -> str: return "result" @@ -189,7 +199,8 @@ def my_function() -> str: assert tool.return_type() == str assert tool.state_type() is None -def test_func_tool_return_none()-> None: + +def test_func_tool_return_none() -> None: def my_function() -> None: return None @@ -200,7 +211,8 @@ def my_function() -> None: assert tool.return_type() is None assert tool.state_type() is None -def test_func_tool_return_base_model()-> None: + +def test_func_tool_return_base_model() -> None: def my_function() -> MyResult: return MyResult(result="value") @@ -211,8 +223,9 @@ def my_function() -> MyResult: assert tool.return_type() is MyResult assert tool.state_type() is None + @pytest.mark.asyncio -async def test_func_call_tool()-> None: +async def test_func_call_tool() -> None: def my_function() -> str: return "result" @@ -220,8 +233,9 @@ def my_function() -> str: result = await tool.run_json({}, CancellationToken()) assert result == "result" + @pytest.mark.asyncio -async def test_func_call_tool_base_model()-> None: +async def test_func_call_tool_base_model() -> None: def my_function() -> MyResult: return MyResult(result="value") @@ -232,7 +246,7 @@ def my_function() -> MyResult: @pytest.mark.asyncio -async def test_func_call_tool_with_arg_base_model()-> None: +async def test_func_call_tool_with_arg_base_model() -> None: def my_function(arg: str) -> MyResult: return MyResult(result="value") @@ -241,8 +255,9 @@ def my_function(arg: str) -> MyResult: assert isinstance(result, MyResult) assert result.result == "value" + @pytest.mark.asyncio -async def test_func_str_res()-> None: +async def test_func_str_res() -> None: def my_function(arg: str) -> str: return "test" @@ -250,10 +265,9 @@ def my_function(arg: str) -> str: result = await tool.run_json({"arg": "test"}, CancellationToken()) assert tool.return_value_as_string(result) == "test" -@pytest.mark.asyncio -async def test_func_base_model_res()-> None: - +@pytest.mark.asyncio +async def test_func_base_model_res() -> None: def my_function(arg: str) -> MyResult: return MyResult(result="test") @@ -261,9 +275,9 @@ def my_function(arg: str) -> MyResult: result = await tool.run_json({"arg": "test"}, CancellationToken()) assert tool.return_value_as_string(result) == '{"result": "test"}' -@pytest.mark.asyncio -async def test_func_base_model_custom_dump_res()-> None: +@pytest.mark.asyncio +async def test_func_base_model_custom_dump_res() -> None: class MyResultCustomDump(BaseModel): result: str = Field(description="The other description.") @@ -271,7 +285,6 @@ class MyResultCustomDump(BaseModel): def ser_model(self) -> str: return "custom: " + self.result - def my_function(arg: str) -> MyResultCustomDump: return MyResultCustomDump(result="test") @@ -279,8 +292,9 @@ def my_function(arg: str) -> MyResultCustomDump: result = await tool.run_json({"arg": "test"}, CancellationToken()) assert tool.return_value_as_string(result) == "custom: test" + @pytest.mark.asyncio -async def test_func_int_res()-> None: +async def test_func_int_res() -> None: def my_function(arg: int) -> int: return arg @@ -292,6 +306,7 @@ def my_function(arg: int) -> int: def test_convert_tools_accepts_both_func_tool_and_schema() -> None: def my_function(arg: str, other: Annotated[int, "int arg"], nonrequired: int = 5) -> MyResult: return MyResult(result="test") + tool = FunctionTool(my_function, description="Function tool.") schema = tool.schema diff --git a/python/packages/autogen-core/tests/test_types.py b/python/packages/autogen-core/tests/test_types.py index d331ceaff7b6..9037e3d3f29f 100644 --- a/python/packages/autogen-core/tests/test_types.py +++ b/python/packages/autogen-core/tests/test_types.py @@ -1,9 +1,9 @@ from types import NoneType from typing import Any, Optional, Union +from autogen_core.base import MessageContext from autogen_core.components._routed_agent import message_handler from autogen_core.components._type_helpers import AnyType, get_types -from autogen_core.base import MessageContext def test_get_types() -> None: @@ -18,7 +18,6 @@ def test_get_types() -> None: def test_handler() -> None: - class HandlerClass: @message_handler() async def handler(self, message: int, ctx: MessageContext) -> Any: @@ -34,6 +33,7 @@ async def handler2(self, message: str | bool, ctx: MessageContext) -> None: assert HandlerClass.handler2.target_types == [str, bool] assert HandlerClass.handler2.produces_types == [NoneType] + class HandlerClass: @message_handler() async def handler(self, message: int, ctx: MessageContext) -> Any: diff --git a/python/packages/autogen-core/tests/test_utils/__init__.py b/python/packages/autogen-core/tests/test_utils/__init__.py index f1cad107da5b..e09a3dac1fdc 100644 --- a/python/packages/autogen-core/tests/test_utils/__init__.py +++ b/python/packages/autogen-core/tests/test_utils/__init__.py @@ -1,26 +1,24 @@ from dataclasses import dataclass from typing import Any -from autogen_core.components import RoutedAgent, message_handler -from autogen_core.components import DefaultTopicId -from autogen_core.base import BaseAgent -from autogen_core.base import MessageContext +from autogen_core.base import BaseAgent, MessageContext +from autogen_core.components import DefaultTopicId, RoutedAgent, message_handler @dataclass -class MessageType: - ... +class MessageType: ... + @dataclass class CascadingMessageType: round: int + class LoopbackAgent(RoutedAgent): def __init__(self) -> None: super().__init__("A loop back agent.") self.num_calls = 0 - @message_handler async def on_new_message(self, message: MessageType, ctx: MessageContext) -> MessageType: self.num_calls += 1 @@ -28,7 +26,6 @@ async def on_new_message(self, message: MessageType, ctx: MessageContext) -> Mes class CascadingAgent(RoutedAgent): - def __init__(self, max_rounds: int) -> None: super().__init__("A cascading agent.") self.num_calls = 0 @@ -41,6 +38,7 @@ async def on_new_message(self, message: CascadingMessageType, ctx: MessageContex return await self.publish_message(CascadingMessageType(round=message.round + 1), topic_id=DefaultTopicId()) + class NoopAgent(BaseAgent): def __init__(self) -> None: super().__init__("A no op agent") diff --git a/python/packages/autogen-core/tests/test_utils/telemetry_test_utils.py b/python/packages/autogen-core/tests/test_utils/telemetry_test_utils.py index 943631311889..994e2104272f 100644 --- a/python/packages/autogen-core/tests/test_utils/telemetry_test_utils.py +++ b/python/packages/autogen-core/tests/test_utils/telemetry_test_utils.py @@ -23,6 +23,7 @@ def get_exported_spans(self) -> List[ReadableSpan]: """Returns the list of exported spans.""" return self.exported_spans + def get_test_tracer_provider(exporter: TestExporter) -> TracerProvider: tracer_provider = TracerProvider() tracer_provider.add_span_processor(SimpleSpanProcessor(exporter)) diff --git a/python/packages/team-one/pyproject.toml b/python/packages/team-one/pyproject.toml index 2672d52607da..d848844675b3 100644 --- a/python/packages/team-one/pyproject.toml +++ b/python/packages/team-one/pyproject.toml @@ -68,9 +68,10 @@ exclude = ["build", "dist", "page_script.js"] include = [ "src/**", "examples/*.py", + "tests/**/*.py", ] [tool.pyright] extend = "../../pyproject.toml" -include = ["src", "tests"] \ No newline at end of file +include = ["src", "tests", "examples"] \ No newline at end of file diff --git a/python/packages/team-one/tests/browser_utils/test_bing_markdown_search.py b/python/packages/team-one/tests/browser_utils/test_bing_markdown_search.py index 80a7d982a1e0..82bbca461597 100644 --- a/python/packages/team-one/tests/browser_utils/test_bing_markdown_search.py +++ b/python/packages/team-one/tests/browser_utils/test_bing_markdown_search.py @@ -2,8 +2,8 @@ import os import pytest - from team_one.markdown_browser import BingMarkdownSearch + skip_all = False bing_api_key = None diff --git a/python/packages/team-one/tests/browser_utils/test_mdconvert.py b/python/packages/team-one/tests/browser_utils/test_mdconvert.py index 796b6dae6bdb..8b9282418149 100644 --- a/python/packages/team-one/tests/browser_utils/test_mdconvert.py +++ b/python/packages/team-one/tests/browser_utils/test_mdconvert.py @@ -5,8 +5,8 @@ import pytest import requests - from team_one.markdown_browser import MarkdownConverter + skip_all = False skip_exiftool = shutil.which("exiftool") is None @@ -119,30 +119,30 @@ def test_mdconvert_local() -> None: # Test XLSX processing result = mdconvert.convert(os.path.join(TEST_FILES_DIR, "test.xlsx")) for test_string in XLSX_TEST_STRINGS: - text_content = result.text_content.replace('\\','') + text_content = result.text_content.replace("\\", "") assert test_string in text_content # Test DOCX processing result = mdconvert.convert(os.path.join(TEST_FILES_DIR, "test.docx")) for test_string in DOCX_TEST_STRINGS: - text_content = result.text_content.replace('\\','') + text_content = result.text_content.replace("\\", "") assert test_string in text_content # Test PPTX processing result = mdconvert.convert(os.path.join(TEST_FILES_DIR, "test.pptx")) for test_string in PPTX_TEST_STRINGS: - text_content = result.text_content.replace('\\','') + text_content = result.text_content.replace("\\", "") assert test_string in text_content # Test HTML processing result = mdconvert.convert(os.path.join(TEST_FILES_DIR, "test_blog.html"), url=BLOG_TEST_URL) for test_string in BLOG_TEST_STRINGS: - text_content = result.text_content.replace('\\','') + text_content = result.text_content.replace("\\", "") assert test_string in text_content # Test Wikipedia processing result = mdconvert.convert(os.path.join(TEST_FILES_DIR, "test_wikipedia.html"), url=WIKIPEDIA_TEST_URL) - text_content = result.text_content.replace('\\','') + text_content = result.text_content.replace("\\", "") for test_string in WIKIPEDIA_TEST_EXCLUDES: assert test_string not in text_content for test_string in WIKIPEDIA_TEST_STRINGS: @@ -150,7 +150,7 @@ def test_mdconvert_local() -> None: # Test Bing processing result = mdconvert.convert(os.path.join(TEST_FILES_DIR, "test_serp.html"), url=SERP_TEST_URL) - text_content = result.text_content.replace('\\','') + text_content = result.text_content.replace("\\", "") for test_string in SERP_TEST_EXCLUDES: assert test_string not in text_content for test_string in SERP_TEST_STRINGS: diff --git a/python/packages/team-one/tests/browser_utils/test_requests_markdown_browser.py b/python/packages/team-one/tests/browser_utils/test_requests_markdown_browser.py index 2ccb2f7ab56b..5b9eebfda1ed 100644 --- a/python/packages/team-one/tests/browser_utils/test_requests_markdown_browser.py +++ b/python/packages/team-one/tests/browser_utils/test_requests_markdown_browser.py @@ -8,6 +8,7 @@ import pytest import requests +from team_one.markdown_browser import BingMarkdownSearch, RequestsMarkdownBrowser BLOG_POST_URL = "https://microsoft.github.io/autogen/blog/2023/04/21/LLM-tuning-math" BLOG_POST_TITLE = "Does Model and Inference Parameter Matter in LLM Applications? - A Case Study for MATH | AutoGen" @@ -37,7 +38,7 @@ BLOG_POST_FIND_ON_PAGE_MATCH, ] -from team_one.markdown_browser import BingMarkdownSearch, RequestsMarkdownBrowser + skip_all = False @@ -49,10 +50,12 @@ def _rm_folder(path: str) -> None: os.unlink(fpath) os.rmdir(path) + def normalize_text(text: str) -> str: text = "\n".join([line.rstrip() for line in re.split(r"\r?\n", text)]) return re.sub(r"\n{3,}", "\n\n", text) + @pytest.mark.skipif( skip_all, reason="do not run if dependency is not installed", @@ -77,7 +80,7 @@ def test_requests_markdown_browser() -> None: assert browser.viewport == top_viewport assert browser.page_title is not None assert browser.page_title.strip() == BLOG_POST_TITLE.strip() - page_content = browser.page_content.replace('\\','') + page_content = browser.page_content.replace("\\", "") assert BLOG_POST_STRING in page_content # Check if page splitting works @@ -98,7 +101,7 @@ def test_requests_markdown_browser() -> None: browser.page_down() assert browser.viewport_current_page == i # Test scrolloing beyond the limits - for i in range(0, 5): + for _ in range(0, 5): browser.page_down() assert browser.viewport_current_page == len(browser.viewport_pages) - 1 @@ -107,7 +110,7 @@ def test_requests_markdown_browser() -> None: browser.page_up() assert browser.viewport_current_page == i # Test scrolloing beyond the limits - for i in range(0, 5): + for _ in range(0, 5): browser.page_up() assert browser.viewport_current_page == 0 @@ -118,12 +121,12 @@ def test_requests_markdown_browser() -> None: # Visit a plain-text file response = requests.get(PLAIN_TEXT_URL) response.raise_for_status() - expected_results = re.sub(r"\s+", " ", response.text, re.DOTALL).strip() + expected_results = re.sub(r"\s+", " ", string=response.text, flags=re.DOTALL).strip() # Run the normalize code that the markdown request module uses expected_results = normalize_text(expected_results) browser.visit_page(PLAIN_TEXT_URL) - assert re.sub(r"\s+", " ", browser.page_content, re.DOTALL).strip() == expected_results + assert re.sub(r"\s+", " ", string=browser.page_content, flags=re.DOTALL).strip() == expected_results # Disrectly download a ZIP file and compute its md5 response = requests.get(DOWNLOAD_URL, stream=True) @@ -157,7 +160,7 @@ def test_requests_markdown_browser() -> None: assert find_viewport is not None # Find next using the same query - for i in range(0, 10): + for _ in range(0, 10): find_viewport = browser.find_on_page("LLM app*") assert find_viewport is not None @@ -166,7 +169,7 @@ def test_requests_markdown_browser() -> None: loc = new_loc # Find next using find_next - for i in range(0, 10): + for _ in range(0, 10): find_viewport = browser.find_next() assert find_viewport is not None @@ -207,25 +210,25 @@ def test_local_file_browsing() -> None: # Directory listing via open_local_file viewport = browser.open_local_file(directory) for target_string in DIR_TEST_STRINGS: - viewport = viewport.replace('\\','') + viewport = viewport.replace("\\", "") assert target_string in viewport # Directory listing via file URI viewport = browser.visit_page(pathlib.Path(os.path.abspath(directory)).as_uri()) for target_string in DIR_TEST_STRINGS: - viewport = viewport.replace('\\','') + viewport = viewport.replace("\\", "") assert target_string in viewport # File access via file open_local_file browser.open_local_file(test_file) for target_string in LOCAL_FILE_TEST_STRINGS: - page_content = browser.page_content.replace('\\','') + page_content = browser.page_content.replace("\\", "") assert target_string in page_content # File access via file URI browser.visit_page(pathlib.Path(os.path.abspath(test_file)).as_uri()) for target_string in LOCAL_FILE_TEST_STRINGS: - page_content = browser.page_content.replace('\\','') + page_content = browser.page_content.replace("\\", "") assert target_string in page_content diff --git a/python/packages/team-one/tests/headless_web_surfer/conftest.py b/python/packages/team-one/tests/headless_web_surfer/conftest.py index 6561689b91bd..894406423abf 100644 --- a/python/packages/team-one/tests/headless_web_surfer/conftest.py +++ b/python/packages/team-one/tests/headless_web_surfer/conftest.py @@ -8,4 +8,4 @@ "api_key": "sk-mockopenaiAPIkeyinexpectedformatfortestingonly", "model": "gpt-4o-2024-05-13" } -""" \ No newline at end of file +""" diff --git a/python/packages/team-one/tests/headless_web_surfer/test_web_surfer.py b/python/packages/team-one/tests/headless_web_surfer/test_web_surfer.py index 1235268faeb8..4f39800e3995 100644 --- a/python/packages/team-one/tests/headless_web_surfer/test_web_surfer.py +++ b/python/packages/team-one/tests/headless_web_surfer/test_web_surfer.py @@ -1,45 +1,21 @@ #!/usr/bin/env python3 -m pytest +import asyncio import os import re -import sys +from json import dumps from math import ceil +from typing import Mapping -import asyncio import pytest - -from autogen_core.base import AgentId -from autogen_core.base import AgentProxy -pytest_plugins = ('pytest_asyncio',) -from json import dumps - -from team_one.utils import ( - ENVIRON_KEY_CHAT_COMPLETION_PROVIDER, - ENVIRON_KEY_CHAT_COMPLETION_KWARGS_JSON, - create_completion_client_from_env -) -from team_one.agents.user_proxy import UserProxy -from team_one.agents.orchestrator import RoundRobinOrchestrator -from team_one.messages import BroadcastMessage from autogen_core.application import SingleThreadedAgentRuntime +from autogen_core.base import AgentId, AgentProxy from autogen_core.components import FunctionCall from autogen_core.components.models import ( UserMessage, ) from autogen_core.components.tools._base import ToolSchema - from openai import AuthenticationError - -sys.path.append(os.path.join(os.path.dirname(__file__), "../..")) -from conftest import MOCK_CHAT_COMPLETION_KWARGS, reason - -sys.path.append(os.path.join(os.path.dirname(__file__), "..")) -#from test_assistant_agent import KEY_LOC, OAI_CONFIG_LIST # noqa: E402 - -BLOG_POST_URL = "https://microsoft.github.io/autogen/blog/2023/04/21/LLM-tuning-math" -BLOG_POST_TITLE = "Does Model and Inference Parameter Matter in LLM Applications? - A Case Study for MATH | AutoGen" -BING_QUERY = "Microsoft" - from team_one.agents.multimodal_web_surfer import MultimodalWebSurfer from team_one.agents.multimodal_web_surfer.tool_definitions import ( TOOL_PAGE_DOWN, @@ -49,18 +25,37 @@ TOOL_VISIT_URL, TOOL_WEB_SEARCH, ) +from team_one.agents.orchestrator import RoundRobinOrchestrator +from team_one.agents.user_proxy import UserProxy +from team_one.messages import BroadcastMessage +from team_one.utils import ( + ENVIRON_KEY_CHAT_COMPLETION_KWARGS_JSON, + ENVIRON_KEY_CHAT_COMPLETION_PROVIDER, + create_completion_client_from_env, +) + +from conftest import MOCK_CHAT_COMPLETION_KWARGS, reason + +pytest_plugins = ("pytest_asyncio",) + + +BLOG_POST_URL = "https://microsoft.github.io/autogen/blog/2023/04/21/LLM-tuning-math" +BLOG_POST_TITLE = "Does Model and Inference Parameter Matter in LLM Applications? - A Case Study for MATH | AutoGen" +BING_QUERY = "Microsoft" + + skip_all = False -#except ImportError: +# except ImportError: # skip_all = True -#else: +# else: # skip_all = False -#try: +# try: # BING_API_KEY = os.environ["BING_API_KEY"] -#except KeyError: +# except KeyError: # skip_bing = True -#else: +# else: # skip_bing = False # Search currently does not require an API key skip_bing = False @@ -70,16 +65,19 @@ else: skip_openai = True -def generate_tool_request(tool: ToolSchema, args: dict[str, str]) -> list[FunctionCall]: - ret = [FunctionCall(id='', arguments='', name=tool["name"])] + +def generate_tool_request(tool: ToolSchema, args: Mapping[str, str]) -> list[FunctionCall]: + ret = [FunctionCall(id="", arguments="", name=tool["name"])] ret[0].arguments = dumps(args) return ret -async def make_browser_request(browser: MultimodalWebSurfer, tool: ToolSchema, args: dict[str, str]={}) -> str: - rects = await browser._get_interactive_rects() # type: ignore + +async def make_browser_request(browser: MultimodalWebSurfer, tool: ToolSchema, args: Mapping[str, str] = {}) -> str: + rects = await browser._get_interactive_rects() # type: ignore req = generate_tool_request(tool, args) - return str((await browser._execute_tool(req, rects, "", use_ocr=False))[1][0]) # type: ignore + return str((await browser._execute_tool(req, rects, "", use_ocr=False))[1][0]) # type: ignore + @pytest.mark.skipif( skip_all, @@ -89,7 +87,7 @@ async def make_browser_request(browser: MultimodalWebSurfer, tool: ToolSchema, a async def test_web_surfer() -> None: env = { ENVIRON_KEY_CHAT_COMPLETION_PROVIDER: "openai", - ENVIRON_KEY_CHAT_COMPLETION_KWARGS_JSON: MOCK_CHAT_COMPLETION_KWARGS + ENVIRON_KEY_CHAT_COMPLETION_KWARGS_JSON: MOCK_CHAT_COMPLETION_KWARGS, } runtime = SingleThreadedAgentRuntime() @@ -111,7 +109,7 @@ async def test_web_surfer() -> None: # Test some basic navigations tool_resp = await make_browser_request(actual_surfer, TOOL_VISIT_URL, {"url": BLOG_POST_URL}) - metadata = await actual_surfer._get_page_metadata() # type: ignore + metadata = await actual_surfer._get_page_metadata() # type: ignore assert f"{BLOG_POST_URL}".strip() in metadata["meta_tags"]["og:url"] assert f"{BLOG_POST_TITLE}".strip() in metadata["meta_tags"]["og:title"] @@ -122,36 +120,43 @@ async def test_web_surfer() -> None: tool_resp = await make_browser_request(actual_surfer, TOOL_PAGE_DOWN) assert ( - f"The viewport shows {viewport_percentage}% of the webpage, and is positioned {viewport_percentage}% down from the top of the page." in tool_resp + f"The viewport shows {viewport_percentage}% of the webpage, and is positioned {viewport_percentage}% down from the top of the page." + in tool_resp ) # Assumes the content is longer than one screen tool_resp = await make_browser_request(actual_surfer, TOOL_PAGE_UP) assert ( - f"The viewport shows {viewport_percentage}% of the webpage, and is positioned at the top of the page" in tool_resp + f"The viewport shows {viewport_percentage}% of the webpage, and is positioned at the top of the page" + in tool_resp ) # Assumes the content is longer than one screen -# # Try to scroll too far back up + # # Try to scroll too far back up tool_resp = await make_browser_request(actual_surfer, TOOL_PAGE_UP) assert ( - f"The viewport shows {viewport_percentage}% of the webpage, and is positioned at the top of the page" in tool_resp + f"The viewport shows {viewport_percentage}% of the webpage, and is positioned at the top of the page" + in tool_resp ) # Try to scroll too far down - total_pages = ceil(100/viewport_percentage) + total_pages = ceil(100 / viewport_percentage) for _ in range(0, total_pages + 1): tool_resp = await make_browser_request(actual_surfer, TOOL_PAGE_DOWN) assert ( - f"The viewport shows {viewport_percentage}% of the webpage, and is positioned at the bottom of the page" in tool_resp + f"The viewport shows {viewport_percentage}% of the webpage, and is positioned at the bottom of the page" + in tool_resp ) # Test Q&A and summarization -- we don't have a key so we expect it to fail #(but it means the code path is correct) with pytest.raises(AuthenticationError): - tool_resp = await make_browser_request(actual_surfer, TOOL_READ_PAGE_AND_ANSWER, {"question": "When was it founded?"}) + tool_resp = await make_browser_request( + actual_surfer, TOOL_READ_PAGE_AND_ANSWER, {"question": "When was it founded?"} + ) with pytest.raises(AuthenticationError): tool_resp = await make_browser_request(actual_surfer, TOOL_SUMMARIZE_PAGE) await runtime.stop_when_idle() + @pytest.mark.skipif( skip_all or skip_openai, reason="dependency is not installed OR" + reason, @@ -182,32 +187,37 @@ async def test_web_surfer_oai() -> None: await actual_surfer.init(model_client=client, downloads_folder=os.getcwd(), browser_channel="chromium") await runtime.send_message( - BroadcastMessage(content=UserMessage(content="Please visit the page 'https://en.wikipedia.org/wiki/Microsoft'", source="user")), + BroadcastMessage( + content=UserMessage( + content="Please visit the page 'https://en.wikipedia.org/wiki/Microsoft'", source="user" + ) + ), recipient=web_surfer.id, - sender=user_proxy.id + sender=user_proxy.id, ) await runtime.send_message( BroadcastMessage(content=UserMessage(content="Please scroll down.", source="user")), recipient=web_surfer.id, - sender=user_proxy.id + sender=user_proxy.id, ) await runtime.send_message( BroadcastMessage(content=UserMessage(content="Please scroll up.", source="user")), recipient=web_surfer.id, - sender=user_proxy.id + sender=user_proxy.id, ) await runtime.send_message( BroadcastMessage(content=UserMessage(content="When was it founded?", source="user")), recipient=web_surfer.id, - sender=user_proxy.id + sender=user_proxy.id, ) await runtime.send_message( BroadcastMessage(content=UserMessage(content="What's this page about?", source="user")), recipient=web_surfer.id, - sender=user_proxy.id + sender=user_proxy.id, ) await runtime.stop_when_idle() + @pytest.mark.skipif( skip_bing, reason="do not run if bing api key is not available", @@ -216,7 +226,7 @@ async def test_web_surfer_oai() -> None: async def test_web_surfer_bing() -> None: env = { ENVIRON_KEY_CHAT_COMPLETION_PROVIDER: "openai", - ENVIRON_KEY_CHAT_COMPLETION_KWARGS_JSON: MOCK_CHAT_COMPLETION_KWARGS + ENVIRON_KEY_CHAT_COMPLETION_KWARGS_JSON: MOCK_CHAT_COMPLETION_KWARGS, } runtime = SingleThreadedAgentRuntime() @@ -239,16 +249,17 @@ async def test_web_surfer_bing() -> None: # Test some basic navigations tool_resp = await make_browser_request(actual_surfer, TOOL_WEB_SEARCH, {"query": BING_QUERY}) - metadata = await actual_surfer._get_page_metadata() # type: ignore + metadata = await actual_surfer._get_page_metadata() # type: ignore assert f"{BING_QUERY}".strip() in metadata["meta_tags"]["og:url"] assert f"{BING_QUERY}".strip() in metadata["meta_tags"]["og:title"] - assert f"I typed '{BING_QUERY}' into the browser search bar." in tool_resp.replace("\\","") + assert f"I typed '{BING_QUERY}' into the browser search bar." in tool_resp.replace("\\", "") tool_resp = await make_browser_request(actual_surfer, TOOL_WEB_SEARCH, {"query": BING_QUERY + " Wikipedia"}) - markdown = await actual_surfer._get_page_markdown() # type: ignore + markdown = await actual_surfer._get_page_markdown() # type: ignore assert "https://en.wikipedia.org/wiki/" in markdown await runtime.stop_when_idle() + if __name__ == "__main__": """Runs this file's tests from the command line.""" asyncio.run(test_web_surfer()) diff --git a/python/packages/team-one/tests/test_example.py b/python/packages/team-one/tests/test_example.py index b18982b41c20..a9cda9be4353 100644 --- a/python/packages/team-one/tests/test_example.py +++ b/python/packages/team-one/tests/test_example.py @@ -1,6 +1,7 @@ import team_one + def test_about() -> None: about = team_one.ABOUT - assert isinstance(about, str) \ No newline at end of file + assert isinstance(about, str)