Ruff 0.16.0 compatibility changes (#834)
This commit is contained in:
+1
-1
@@ -28,4 +28,4 @@
|
||||
# ├── test_summarize_pr.py
|
||||
# └── ...
|
||||
|
||||
__version__ = "0.2.35"
|
||||
__version__ = "0.2.36"
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ def _ledger(action: Action) -> tuple[dict, str]:
|
||||
payload = response.json()
|
||||
content = json.loads(base64.b64decode(payload["content"]))
|
||||
if not isinstance(content.get("signedContributors"), list):
|
||||
raise RuntimeError("CLA signature ledger has an invalid schema")
|
||||
raise TypeError("CLA signature ledger has an invalid schema")
|
||||
return content, payload["sha"]
|
||||
|
||||
|
||||
|
||||
@@ -121,10 +121,9 @@ def compute_update(current_ref, comment, latest):
|
||||
# Major-only tag like @v6 -> update to @v8 only if that tag actually exists.
|
||||
if int(latest_major.group(1)) > int(current_major.group(1)) and latest.get("major_tag"):
|
||||
return latest["major_tag"], comment
|
||||
elif current_ref != latest_tag:
|
||||
# Specific tag like @v2.8.0 -> update to the latest tag only when it is semantically newer.
|
||||
if is_newer_version(current_ref, latest_tag):
|
||||
return latest_tag, comment
|
||||
# Specific tag like @v2.8.0 -> update to the latest tag only when it is semantically newer.
|
||||
elif current_ref != latest_tag and is_newer_version(current_ref, latest_tag):
|
||||
return latest_tag, comment
|
||||
|
||||
return None
|
||||
|
||||
@@ -180,6 +179,7 @@ def get_open_pr_titles(org, repo):
|
||||
["gh", "pr", "list", "--repo", f"{org}/{repo}", "--state", "open", "--json", "title", "--limit", "100"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
return set()
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from .utils import ACTIONS_CREDIT, GITHUB_API_URL, Action
|
||||
|
||||
@@ -139,7 +139,7 @@ def update_comment(event, comment_body: str, command: str, triggered_actions: li
|
||||
if not triggered_actions:
|
||||
return
|
||||
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||
failed = all(action.get("error") for action in triggered_actions)
|
||||
status = (
|
||||
"No GitHub Actions workflows were started" if failed else "GitHub Actions below triggered via workflow dispatch"
|
||||
|
||||
@@ -473,7 +473,8 @@ def format_python_file(text: str, width: int = 120, start_newline: bool = False)
|
||||
nl[0] = src[sl][:sc] + nl[0]
|
||||
nl[-1] += src[el][ec:]
|
||||
src[sl : el + 1] = nl
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
print(f"Failed to apply docstring replacement: {e}")
|
||||
continue
|
||||
return "\n".join(src)
|
||||
|
||||
@@ -505,7 +506,8 @@ def iter_py_files(paths: list[Path]) -> list[Path]:
|
||||
stack.append(child)
|
||||
elif child.is_file() and child.suffix == ".py":
|
||||
out.append(child)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
print(f"Failed to inspect {d}: {e}")
|
||||
continue
|
||||
return list(dict.fromkeys(sorted(out)))
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@ def auto_merge_actions_prs(org, repos):
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
prs.extend(json.loads(result.stdout or "[]"))
|
||||
@@ -232,6 +233,7 @@ def auto_merge_actions_prs(org, repos):
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
print(f" ✅ Merged {pr_ref}")
|
||||
|
||||
@@ -6,7 +6,7 @@ import os
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from .utils import GITHUB_API_URL, Action, get_response, remove_html_comments
|
||||
|
||||
@@ -60,7 +60,7 @@ def get_prs_between_tags(event, previous_tag: str, latest_tag: str) -> list:
|
||||
)
|
||||
|
||||
# Sort PRs by merge date
|
||||
prs.sort(key=lambda x: datetime.strptime(x["merged_at"], "%Y-%m-%dT%H:%M:%SZ"))
|
||||
prs.sort(key=lambda x: datetime.strptime(x["merged_at"], "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc))
|
||||
|
||||
return prs
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from actions.utils import Action
|
||||
@@ -178,7 +178,7 @@ def update_file(file_path, prefix, block_start, block_end, base_header):
|
||||
def main(*args, **kwargs):
|
||||
"""Automates file header updates for supported file types under the current working directory."""
|
||||
event = Action(*args, **kwargs)
|
||||
current_year = datetime.now().year
|
||||
current_year = datetime.now(timezone.utc).year
|
||||
repository = (event.repository or "").lower()
|
||||
|
||||
# Only process repos owned by the Ultralytics organization
|
||||
|
||||
@@ -444,9 +444,12 @@ Thank you 🙏
|
||||
for commit in data["commits"]["nodes"]:
|
||||
commit_data = commit["commit"]
|
||||
for user_type in ["author", "committer"]:
|
||||
if user := commit_data[user_type].get("user"):
|
||||
if user["__typename"] != "Bot" and (login := user.get("login")):
|
||||
contributors.add(login)
|
||||
if (
|
||||
(user := commit_data[user_type].get("user"))
|
||||
and user["__typename"] != "Bot"
|
||||
and (login := user.get("login"))
|
||||
):
|
||||
contributors.add(login)
|
||||
|
||||
contributors.discard(author)
|
||||
contributors.discard(username)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from actions.dispatch_actions import (
|
||||
@@ -40,9 +40,10 @@ def test_get_pr_branch_fork():
|
||||
"base": {"repo": {"id": 1}},
|
||||
}
|
||||
|
||||
with patch("time.time", return_value=1234567.890), patch("subprocess.run") as mock_run:
|
||||
with patch("os.environ.get", return_value="test-token"):
|
||||
branch, temp_branch = get_pr_branch(mock_event)
|
||||
with patch("time.time", return_value=1234567.890), patch("subprocess.run") as mock_run, patch(
|
||||
"os.environ.get", return_value="test-token"
|
||||
):
|
||||
branch, temp_branch = get_pr_branch(mock_event)
|
||||
|
||||
assert branch == "temp-ci-456-1234567890"
|
||||
assert temp_branch == "temp-ci-456-1234567890"
|
||||
@@ -204,7 +205,7 @@ def test_update_comment_function():
|
||||
|
||||
# Mock datetime to have a consistent timestamp
|
||||
with patch("actions.dispatch_actions.datetime") as mock_datetime:
|
||||
mock_datetime.now.return_value = datetime(2023, 1, 1, 12, 0, 0)
|
||||
mock_datetime.now.return_value = datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc)
|
||||
# Call without capturing return value
|
||||
update_comment(mock_event, comment_body, RUN_CI_KEYWORD, triggered_actions)
|
||||
|
||||
@@ -271,12 +272,12 @@ def test_main_triggers_ci_only():
|
||||
}
|
||||
mock_event.is_org_member.return_value = True
|
||||
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch:
|
||||
with patch("actions.dispatch_actions.trigger_and_get_workflow_info") as mock_trigger:
|
||||
with patch("actions.dispatch_actions.update_comment"):
|
||||
mock_get_branch.return_value = ("feature-branch", None)
|
||||
mock_trigger.return_value = [{"name": "CI", "file": "ci.yml", "url": "url", "run_number": 1}]
|
||||
main()
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch, patch(
|
||||
"actions.dispatch_actions.trigger_and_get_workflow_info"
|
||||
) as mock_trigger, patch("actions.dispatch_actions.update_comment"):
|
||||
mock_get_branch.return_value = ("feature-branch", None)
|
||||
mock_trigger.return_value = [{"name": "CI", "file": "ci.yml", "url": "url", "run_number": 1}]
|
||||
main()
|
||||
|
||||
mock_trigger.assert_called_once_with(mock_event, "feature-branch", ["ci.yml"], None)
|
||||
|
||||
@@ -294,12 +295,12 @@ def test_main_triggers_all_workflows():
|
||||
}
|
||||
mock_event.is_org_member.return_value = True
|
||||
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch:
|
||||
with patch("actions.dispatch_actions.trigger_and_get_workflow_info") as mock_trigger:
|
||||
with patch("actions.dispatch_actions.update_comment"):
|
||||
mock_get_branch.return_value = ("feature-branch", None)
|
||||
mock_trigger.return_value = [{"name": "CI", "file": "ci.yml", "url": "url", "run_number": 1}]
|
||||
main()
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch, patch(
|
||||
"actions.dispatch_actions.trigger_and_get_workflow_info"
|
||||
) as mock_trigger, patch("actions.dispatch_actions.update_comment"):
|
||||
mock_get_branch.return_value = ("feature-branch", None)
|
||||
mock_trigger.return_value = [{"name": "CI", "file": "ci.yml", "url": "url", "run_number": 1}]
|
||||
main()
|
||||
|
||||
mock_trigger.assert_called_once_with(mock_event, "feature-branch", ["ci.yml", "docker.yml"], None)
|
||||
|
||||
@@ -317,14 +318,12 @@ def test_main_triggers_docker_only():
|
||||
}
|
||||
mock_event.is_org_member.return_value = True
|
||||
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch:
|
||||
with patch("actions.dispatch_actions.trigger_and_get_workflow_info") as mock_trigger:
|
||||
with patch("actions.dispatch_actions.update_comment"):
|
||||
mock_get_branch.return_value = ("feature-branch", None)
|
||||
mock_trigger.return_value = [
|
||||
{"name": "Docker", "file": "docker.yml", "url": "url", "run_number": 1}
|
||||
]
|
||||
main()
|
||||
with patch("actions.dispatch_actions.get_pr_branch") as mock_get_branch, patch(
|
||||
"actions.dispatch_actions.trigger_and_get_workflow_info"
|
||||
) as mock_trigger, patch("actions.dispatch_actions.update_comment"):
|
||||
mock_get_branch.return_value = ("feature-branch", None)
|
||||
mock_trigger.return_value = [{"name": "Docker", "file": "docker.yml", "url": "url", "run_number": 1}]
|
||||
main()
|
||||
|
||||
mock_trigger.assert_called_once_with(mock_event, "feature-branch", ["docker.yml"], None)
|
||||
|
||||
|
||||
+36
-34
@@ -130,23 +130,24 @@ def test_ignore_paths():
|
||||
|
||||
def test_main_real_files():
|
||||
"""Test main function on actual repository files."""
|
||||
with patch("actions.update_file_headers.update_file", return_value=False) as mock_update:
|
||||
with patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_action.return_value.repository = "ultralytics/actions"
|
||||
mock_action.return_value.is_repo_private.return_value = False
|
||||
main()
|
||||
assert mock_update.call_count > 0
|
||||
with patch("actions.update_file_headers.update_file", return_value=False) as mock_update, patch(
|
||||
"actions.update_file_headers.Action"
|
||||
) as mock_action:
|
||||
mock_action.return_value.repository = "ultralytics/actions"
|
||||
mock_action.return_value.is_repo_private.return_value = False
|
||||
main()
|
||||
assert mock_update.call_count > 0
|
||||
|
||||
|
||||
def test_main_with_custom_header():
|
||||
"""Test main function with custom header environment variable."""
|
||||
with patch("actions.update_file_headers.update_file", return_value=False):
|
||||
with patch("actions.update_file_headers.HEADER", "Custom Test Header"):
|
||||
with patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_event = mock_action.return_value
|
||||
mock_event.repository = "test/repo"
|
||||
main()
|
||||
mock_action.assert_called_once()
|
||||
with patch("actions.update_file_headers.update_file", return_value=False), patch(
|
||||
"actions.update_file_headers.HEADER", "Custom Test Header"
|
||||
), patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_event = mock_action.return_value
|
||||
mock_event.repository = "test/repo"
|
||||
main()
|
||||
mock_action.assert_called_once()
|
||||
|
||||
|
||||
def test_main_private_and_skipped_repos():
|
||||
@@ -155,22 +156,22 @@ def test_main_private_and_skipped_repos():
|
||||
tmp_path = Path(tmp_dir)
|
||||
(tmp_path / "app.py").write_text("print('hello')\n")
|
||||
|
||||
with patch("actions.update_file_headers.Path.cwd", return_value=tmp_path):
|
||||
with patch("actions.update_file_headers.update_file", return_value=False) as mock_update:
|
||||
with patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_event = mock_action.return_value
|
||||
mock_event.repository = "ultralytics/private"
|
||||
mock_event.is_repo_private.return_value = True
|
||||
main()
|
||||
assert any("CONFIDENTIAL" in call.args[4] for call in mock_update.call_args_list)
|
||||
with patch("actions.update_file_headers.Path.cwd", return_value=tmp_path), patch(
|
||||
"actions.update_file_headers.update_file", return_value=False
|
||||
) as mock_update, patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_event = mock_action.return_value
|
||||
mock_event.repository = "ultralytics/private"
|
||||
mock_event.is_repo_private.return_value = True
|
||||
main()
|
||||
assert any("CONFIDENTIAL" in call.args[4] for call in mock_update.call_args_list)
|
||||
|
||||
with patch("actions.update_file_headers.update_file", return_value=False) as mock_update:
|
||||
with patch("actions.update_file_headers.HEADER", None):
|
||||
with patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_action.return_value.repository = "other/repo"
|
||||
main()
|
||||
mock_action.return_value.is_repo_private.assert_not_called()
|
||||
mock_update.assert_not_called()
|
||||
with patch("actions.update_file_headers.update_file", return_value=False) as mock_update, patch(
|
||||
"actions.update_file_headers.HEADER", None
|
||||
), patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_action.return_value.repository = "other/repo"
|
||||
main()
|
||||
mock_action.return_value.is_repo_private.assert_not_called()
|
||||
mock_update.assert_not_called()
|
||||
|
||||
|
||||
def test_main_updates_files_in_current_directory():
|
||||
@@ -180,11 +181,12 @@ def test_main_updates_files_in_current_directory():
|
||||
test_file = tmp_path / "app.py"
|
||||
test_file.write_text("print('hello')\n")
|
||||
|
||||
with patch("actions.update_file_headers.Path.cwd", return_value=tmp_path):
|
||||
with patch("actions.update_file_headers.Action") as mock_action:
|
||||
mock_event = mock_action.return_value
|
||||
mock_event.repository = "ultralytics/actions"
|
||||
mock_event.is_repo_private.return_value = False
|
||||
main()
|
||||
with patch("actions.update_file_headers.Path.cwd", return_value=tmp_path), patch(
|
||||
"actions.update_file_headers.Action"
|
||||
) as mock_action:
|
||||
mock_event = mock_action.return_value
|
||||
mock_event.repository = "ultralytics/actions"
|
||||
mock_event.is_repo_private.return_value = False
|
||||
main()
|
||||
|
||||
assert test_file.read_text().startswith("# Ultralytics 🚀 AGPL-3.0 License")
|
||||
|
||||
+18
-16
@@ -11,19 +11,20 @@ from actions.utils import Action, check_pypi_version, ultralytics_actions_info
|
||||
@pytest.mark.skipif(sys.version_info < (3, 11), reason="tomllib requires Python 3.11+")
|
||||
def test_check_pypi_version():
|
||||
"""Test check_pypi_version function."""
|
||||
with patch("tomllib.load", return_value={"project": {"name": "test-package", "version": "1.0.0"}}):
|
||||
with patch("requests.get") as mock_get:
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.elapsed.total_seconds.return_value = 0.5
|
||||
mock_response.json.return_value = {"info": {"version": "0.9.0"}}
|
||||
mock_get.return_value = mock_response
|
||||
with patch("tomllib.load", return_value={"project": {"name": "test-package", "version": "1.0.0"}}), patch(
|
||||
"requests.get"
|
||||
) as mock_get:
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.elapsed.total_seconds.return_value = 0.5
|
||||
mock_response.json.return_value = {"info": {"version": "0.9.0"}}
|
||||
mock_get.return_value = mock_response
|
||||
|
||||
local_version, online_version, publish = check_pypi_version()
|
||||
local_version, online_version, publish = check_pypi_version()
|
||||
|
||||
assert local_version == "1.0.0"
|
||||
assert online_version == "0.9.0"
|
||||
assert publish is True
|
||||
assert local_version == "1.0.0"
|
||||
assert online_version == "0.9.0"
|
||||
assert publish is True
|
||||
|
||||
|
||||
def test_action_init():
|
||||
@@ -89,11 +90,12 @@ def test_get_pr_contributors_excludes_bots():
|
||||
|
||||
def test_load_event_data():
|
||||
"""Test loading event data from file."""
|
||||
with patch("pathlib.Path.exists", return_value=True):
|
||||
with patch("pathlib.Path.read_text", return_value='{"test": "data"}'):
|
||||
action = Action()
|
||||
data = action._load_event_data("fake_path")
|
||||
assert data == {"test": "data"}
|
||||
with patch("pathlib.Path.exists", return_value=True), patch(
|
||||
"pathlib.Path.read_text", return_value='{"test": "data"}'
|
||||
):
|
||||
action = Action()
|
||||
data = action._load_event_data("fake_path")
|
||||
assert data == {"test": "data"}
|
||||
|
||||
|
||||
def test_ultralytics_actions_info():
|
||||
|
||||
+27
-23
@@ -88,9 +88,10 @@ def test_remove_outer_codeblocks():
|
||||
|
||||
def test_get_review_model_override():
|
||||
"""Test review model override logic."""
|
||||
with patch("actions.utils.openai_utils.REVIEW_MODEL", "claude-opus-4-7"):
|
||||
with patch("actions.utils.openai_utils.MODEL", "gpt-5.6-terra"):
|
||||
assert get_review_model() == "claude-opus-4-7"
|
||||
with patch("actions.utils.openai_utils.REVIEW_MODEL", "claude-opus-4-7"), patch(
|
||||
"actions.utils.openai_utils.MODEL", "gpt-5.6-terra"
|
||||
):
|
||||
assert get_review_model() == "claude-opus-4-7"
|
||||
|
||||
|
||||
def test_get_review_model_fallback():
|
||||
@@ -120,9 +121,10 @@ def test_get_response(mock_post):
|
||||
messages = [{"role": "system", "content": "You are a helpful assistant"}, {"role": "user", "content": "Hello"}]
|
||||
|
||||
# Use a context manager for the environment variable
|
||||
with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}, clear=False):
|
||||
with patch("actions.utils.openai_utils.OPENAI_API_KEY", "test-key"):
|
||||
result = get_response(messages, check_links=False)
|
||||
with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}, clear=False), patch(
|
||||
"actions.utils.openai_utils.OPENAI_API_KEY", "test-key"
|
||||
):
|
||||
result = get_response(messages, check_links=False)
|
||||
|
||||
assert result == "Test response from OpenAI"
|
||||
mock_post.assert_called_once()
|
||||
@@ -186,9 +188,10 @@ def test_get_response_with_link_check(mock_check_links, mock_post):
|
||||
messages = [{"role": "user", "content": "Hello"}]
|
||||
|
||||
# Use a context manager for the environment variable
|
||||
with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}, clear=False):
|
||||
with patch("actions.utils.openai_utils.OPENAI_API_KEY", "test-key"):
|
||||
result = get_response(messages)
|
||||
with patch.dict("os.environ", {"OPENAI_API_KEY": "test-key"}, clear=False), patch(
|
||||
"actions.utils.openai_utils.OPENAI_API_KEY", "test-key"
|
||||
):
|
||||
result = get_response(messages)
|
||||
|
||||
assert result == "Response with https://example.com link"
|
||||
mock_check_links.assert_called_once()
|
||||
@@ -350,16 +353,17 @@ def test_get_agent_response_summarizes_after_max_turns(mock_post):
|
||||
}
|
||||
]
|
||||
|
||||
with patch("actions.utils.openai_utils.OPENAI_API_KEY", "test-key"):
|
||||
with patch("actions.utils.openai_utils.time.sleep") as mock_sleep:
|
||||
result = get_agent_response(
|
||||
[{"role": "user", "content": "review"}],
|
||||
tools=tools,
|
||||
tool_handlers={"lookup_value": lambda value: f"raw tool output for {value}"},
|
||||
text_format={"format": {"type": "json_schema", "name": "review", "strict": True, "schema": schema}},
|
||||
max_turns=1,
|
||||
retries=0,
|
||||
)
|
||||
with patch("actions.utils.openai_utils.OPENAI_API_KEY", "test-key"), patch(
|
||||
"actions.utils.openai_utils.time.sleep"
|
||||
) as mock_sleep:
|
||||
result = get_agent_response(
|
||||
[{"role": "user", "content": "review"}],
|
||||
tools=tools,
|
||||
tool_handlers={"lookup_value": lambda value: f"raw tool output for {value}"},
|
||||
text_format={"format": {"type": "json_schema", "name": "review", "strict": True, "schema": schema}},
|
||||
max_turns=1,
|
||||
retries=0,
|
||||
)
|
||||
|
||||
assert result == {"comments": [], "summary": "synthesized"}
|
||||
assert mock_post.call_count == 3
|
||||
@@ -396,10 +400,10 @@ def test_get_response_anthropic(mock_post):
|
||||
|
||||
messages = [{"role": "system", "content": "You are a helpful assistant"}, {"role": "user", "content": "Hello"}]
|
||||
|
||||
with patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"}, clear=False):
|
||||
with patch("actions.utils.openai_utils.ANTHROPIC_API_KEY", "test-key"):
|
||||
with patch("builtins.print") as mock_print:
|
||||
result = get_response(messages, check_links=False, model="claude-sonnet-4-6", background=True)
|
||||
with patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"}, clear=False), patch(
|
||||
"actions.utils.openai_utils.ANTHROPIC_API_KEY", "test-key"
|
||||
), patch("builtins.print") as mock_print:
|
||||
result = get_response(messages, check_links=False, model="claude-sonnet-4-6", background=True)
|
||||
|
||||
assert result == "Test response from Claude"
|
||||
printed = "\n".join(str(c.args[0]) for c in mock_print.call_args_list if c.args)
|
||||
|
||||
Reference in New Issue
Block a user