Skip to content

Commit b3bfe5c

Browse files
authored
[chore] Fix linting errors for agentscope/langchain/agno (#65)
2 parents fa45543 + 06d93d2 commit b3bfe5c

File tree

12 files changed

+89
-84
lines changed

12 files changed

+89
-84
lines changed

instrumentation-loongsuite/loongsuite-instrumentation-agentscope/pyproject.toml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,46 @@ dynamic = ["version"]
88
description = "OpenTelemetry AgentScope Instrumentation"
99
readme = "README.md"
1010
license = "Apache-2.0"
11-
requires-python = ">=3.8, <3.13"
11+
requires-python = ">=3.9"
1212
authors = [
13-
{ name = "LoongSuite Python Agent Authros", email = "[email protected]" },
13+
{ name = "LoongSuite Python Agent Authors", email = "[email protected]" },
1414
]
1515
classifiers = [
1616
"Development Status :: 5 - Production/Stable",
1717
"Intended Audience :: Developers",
1818
"License :: OSI Approved :: Apache Software License",
1919
"Programming Language :: Python",
2020
"Programming Language :: Python :: 3",
21-
"Programming Language :: Python :: 3.8",
2221
"Programming Language :: Python :: 3.9",
2322
"Programming Language :: Python :: 3.10",
2423
"Programming Language :: Python :: 3.11",
2524
"Programming Language :: Python :: 3.12",
2625
"Programming Language :: Python :: 3.13",
2726
]
2827
dependencies = [
29-
"opentelemetry-api>=1.37.0",
30-
"opentelemetry-sdk>=1.37.0",
31-
"opentelemetry-semantic-conventions>=0.58b0",
32-
"wrapt",
28+
"opentelemetry-api ~= 1.37",
29+
"opentelemetry-instrumentation ~= 0.58b0",
30+
"opentelemetry-semantic-conventions ~= 0.58b0",
3331
]
3432

3533
[project.optional-dependencies]
3634
instruments = [
3735
"agentscope",
3836
]
37+
# 支持两个版本的 agentscope 测试
3938
test = [
40-
"agentscope",
39+
"pytest",
40+
"opentelemetry-sdk",
41+
"respx",
42+
]
43+
test-v0 = [
44+
"agentscope>=0.1.0,<1.0.0",
45+
"pytest",
46+
"opentelemetry-sdk",
47+
"respx",
48+
]
49+
test-v1 = [
50+
"agentscope>=1.0.0",
4151
"pytest",
4252
"opentelemetry-sdk",
4353
"respx",

instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/shared/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT,
2121
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT_MAX_LENGTH,
2222
OTEL_INSTRUMENTATION_GENAI_MESSAGE_STRATEGY,
23+
AgentScopeGenAiProviderName,
2324
)
2425
from .telemetry_options import (
2526
GenAITelemetryOptions,
@@ -44,6 +45,7 @@
4445
"ToolRequestAttributes",
4546
# Enums
4647
"GenAiSpanKind",
48+
"AgentScopeGenAiProviderName",
4749
# Attribute constants
4850
"CommonAttributes",
4951
]

instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/v1/message_converter.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ class ToolCallResponsePart(MessagePart):
6565
class GenericPart(MessagePart):
6666
"""通用部件,支持任意属性"""
6767

68-
# FIXME: ruff failed
69-
def __init__(self, type: str, **kwargs: Any): # noqa: A002
70-
super().__init__(type)
68+
def __init__(self, part_type: str, **kwargs: Any):
69+
super().__init__(type=part_type)
7170
for key, value in kwargs.items():
7271
setattr(self, key, value)
7372

@@ -101,24 +100,22 @@ def create_text_part(content: str) -> TextPart:
101100
@staticmethod
102101
def create_tool_call_part(
103102
name: str,
104-
# FIXME: ruff failed
105-
id: Optional[str] = None, # noqa: A002
103+
call_id: Optional[str] = None,
106104
arguments: Optional[Dict[str, Any]] = None,
107105
) -> ToolCallRequestPart:
108106
"""创建工具调用部件"""
109107
return ToolCallRequestPart(
110-
type="tool_call", name=name, id=id, arguments=arguments
108+
type="tool_call", name=name, id=call_id, arguments=arguments
111109
)
112110

113111
@staticmethod
114112
def create_tool_response_part(
115113
response: Any,
116-
# FIXME: ruff failed
117-
id: Optional[str] = None, # noqa: A002
114+
call_id: Optional[str] = None,
118115
) -> ToolCallResponsePart:
119116
"""创建工具响应部件"""
120117
return ToolCallResponsePart(
121-
type="tool_call_response", response=response, id=id
118+
type="tool_call_response", response=response, id=call_id
122119
)
123120

124121
@staticmethod
@@ -184,7 +181,8 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
184181
# 处理tool消息
185182
if role == "tool":
186183
part = PartFactory.create_tool_response_part(
187-
response=msg.get("content", ""), id=msg.get("tool_call_id", "")
184+
response=msg.get("content", ""),
185+
call_id=msg.get("tool_call_id", ""),
188186
)
189187
parts.append(part)
190188
else:
@@ -198,7 +196,7 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
198196

199197
part = PartFactory.create_tool_call_part(
200198
name=function_info.get("name", "unknown_tool"),
201-
id=tool_call.get("id", "unknown_id"),
199+
call_id=tool_call.get("id", "unknown_id"),
202200
arguments=arguments,
203201
)
204202
parts.append(part)
@@ -295,7 +293,7 @@ def _parse_content_list(
295293
parts.append(
296294
PartFactory.create_tool_call_part(
297295
name=item.get("name", ""),
298-
id=item.get("id", ""),
296+
call_id=item.get("id", ""),
299297
arguments=item.get("input", {}),
300298
)
301299
)
@@ -306,7 +304,7 @@ def _parse_content_list(
306304
parts.append(
307305
PartFactory.create_tool_response_part(
308306
response=result_text,
309-
id=item.get("tool_use_id", ""),
307+
call_id=item.get("tool_use_id", ""),
310308
)
311309
)
312310
elif content_type == "image":
@@ -377,7 +375,7 @@ def _parse_parts_list(self, parts_list: List[Any]) -> List[MessagePart]:
377375
parts.append(
378376
PartFactory.create_tool_call_part(
379377
name=func_call.get("name", ""),
380-
id=func_call.get("id", ""),
378+
call_id=func_call.get("id", ""),
381379
arguments=func_call.get("args", {}),
382380
)
383381
)
@@ -391,7 +389,8 @@ def _parse_parts_list(self, parts_list: List[Any]) -> List[MessagePart]:
391389
)
392390
parts.append(
393391
PartFactory.create_tool_response_part(
394-
response=result_text, id=func_resp.get("id", "")
392+
response=result_text,
393+
call_id=func_resp.get("id", ""),
395394
)
396395
)
397396
elif "inline_data" in item:
@@ -439,7 +438,7 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
439438
parts.append(
440439
PartFactory.create_tool_response_part(
441440
response=msg.get("content", ""),
442-
id=msg.get("tool_call_id", ""),
441+
call_id=msg.get("tool_call_id", ""),
443442
)
444443
)
445444
else:
@@ -454,7 +453,7 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
454453
parts.append(
455454
PartFactory.create_tool_call_part(
456455
name=function_info.get("name", ""),
457-
id=tool_call.get("id", ""),
456+
call_id=tool_call.get("id", ""),
458457
arguments=arguments,
459458
)
460459
)
@@ -519,7 +518,7 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
519518
parts.append(
520519
PartFactory.create_tool_response_part(
521520
response=msg.get("content", ""),
522-
id=msg.get("tool_call_id", ""),
521+
call_id=msg.get("tool_call_id", ""),
523522
)
524523
)
525524
else:
@@ -577,7 +576,7 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
577576
parts.append(
578577
PartFactory.create_tool_response_part(
579578
response=msg.get("content", ""),
580-
id=msg.get("tool_call_id", ""),
579+
call_id=msg.get("tool_call_id", ""),
581580
)
582581
)
583582
else:
@@ -592,7 +591,7 @@ def parse_message(self, msg: Dict[str, Any]) -> ChatMessage:
592591
parts.append(
593592
PartFactory.create_tool_call_part(
594593
name=function_info.get("name", ""),
595-
id=tool_call.get("id", ""),
594+
call_id=tool_call.get("id", ""),
596595
arguments=arguments,
597596
)
598597
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# -*- coding: utf-8 -*-
2+
"""顶层测试配置,配置 Python 路径以便测试可以导入包"""
3+
4+
import sys
5+
from pathlib import Path
6+
7+
# 获取项目根目录
8+
TESTS_ROOT = Path(__file__).resolve().parent
9+
PROJECT_ROOT = TESTS_ROOT.parent
10+
SRC_PATH = PROJECT_ROOT / "src"
11+
12+
# 将 src 目录添加到 Python 路径
13+
# 这样测试就可以直接导入 opentelemetry.instrumentation.agentscope
14+
if str(SRC_PATH) not in sys.path:
15+
sys.path.insert(0, str(SRC_PATH))
16+
17+
# 将 tests 目录的父目录添加到 Python 路径
18+
# 这样测试就可以使用 `from tests.shared.version_utils import ...`
19+
# 无论 pytest 从哪个目录运行
20+
if str(PROJECT_ROOT) not in sys.path:
21+
sys.path.insert(0, str(PROJECT_ROOT))
Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
# -*- coding: utf-8 -*-
22
"""版本检测和测试跳过工具"""
33

4-
import os
5-
import sys
4+
import importlib.util
65

76
import pytest
87

9-
# 添加src目录到Python路径
10-
src_path = os.path.join(
11-
os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "src"
12-
)
13-
if src_path not in sys.path:
14-
sys.path.insert(0, src_path)
15-
16-
# FIXME: ruff failed
17-
from opentelemetry.instrumentation.agentscope.utils import ( # noqa: E402
8+
from opentelemetry.instrumentation.agentscope.utils import (
189
_AGENTSCOPE_VERSION,
1910
is_agentscope_v1,
2011
)
@@ -43,16 +34,6 @@ def skip_if_not_v1():
4334

4435
def skip_if_no_agentscope():
4536
"""如果没有安装agentscope则跳过测试"""
46-
try:
47-
# test the import of agentscope, skip the warning
48-
import agentscope # noqa: F401, PLC0415
49-
50-
return pytest.mark.skipif(False, reason="")
51-
except ImportError:
37+
if importlib.util.find_spec("agentscope") is None:
5238
return pytest.mark.skipif(True, reason="需要安装 agentscope")
53-
54-
55-
# pytest markers
56-
pytestmark = [
57-
pytest.mark.agentscope, # 标记所有agentscope相关测试
58-
]
39+
return pytest.mark.skipif(False, reason="")

instrumentation-loongsuite/loongsuite-instrumentation-agentscope/tests/v1/test_agentscope_v1.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
"""v1版本的AgentScope测试"""
33

4+
import asyncio
45
from typing import Generator
56

67
import agentscope
@@ -84,8 +85,6 @@ def test_agentscope_v1_basic(
8485
msg_task = Msg("user", "compute 1615114134*4343434343 for me", "user")
8586

8687
# 使用 asyncio 来运行异步函数
87-
import asyncio # noqa: PLC0415
88-
8988
async def run_agent():
9089
response = await agent(msg_task)
9190
# 如果是异步生成器,需要消费它
@@ -96,10 +95,10 @@ async def run_agent():
9695
return result
9796
return response
9897

99-
# FIXME: ruff failed
100-
response = asyncio.run(run_agent()) # noqa: F841
98+
# 运行异步函数以生成 spans
99+
_ = asyncio.run(run_agent())
101100

102-
check_model, check_tool = False, False
101+
check_model = False
103102
spans = in_memory_span_exporter.get_finished_spans()
104103

105104
# 调试:打印所有 span 名称
@@ -109,9 +108,6 @@ async def run_agent():
109108
# 检查是否是聊天模型的 span(格式:chat model_name)
110109
if span.name.startswith("chat "):
111110
check_model = True
112-
if "tool" in span.name.lower():
113-
# FIXME: ruff failed
114-
check_tool = True # noqa: F841
115111

116112
# 先检查是否至少有模型调用 span
117113
assert check_model, (
@@ -144,8 +140,6 @@ def test_agentscope_v1_simple_chat(
144140

145141
msg_task = Msg("user", "Hello, how are you?", "user")
146142

147-
import asyncio # noqa: PLC0415
148-
149143
async def run_agent():
150144
response = await agent(msg_task)
151145
if hasattr(response, "__aiter__"):
@@ -187,8 +181,6 @@ def test_agentscope_v1_model_direct(
187181
# 直接调用模型(使用字典格式避免 Msg 对象问题)
188182
messages = [{"role": "user", "content": "Hello, what is 1+1?"}]
189183

190-
import asyncio # noqa: PLC0415
191-
192184
async def call_model():
193185
response = await model(messages)
194186
if hasattr(response, "__aiter__"):
@@ -230,8 +222,6 @@ def test_agentscope_v1_span_attributes(
230222
# 直接调用模型(使用字典格式)
231223
messages = [{"role": "user", "content": "Simple test message"}]
232224

233-
import asyncio # noqa: PLC0415
234-
235225
async def call_model():
236226
response = await model(messages)
237227
if hasattr(response, "__aiter__"):

instrumentation-loongsuite/loongsuite-instrumentation-agno/pyproject.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ dynamic = ["version"]
88
description = "OpenTelemetry Agno Instrumentation"
99
readme = "README.md"
1010
license = "Apache-2.0"
11-
requires-python = ">=3.8, <3.13"
11+
requires-python = ">=3.9"
1212
authors = [
1313
{ name = "LoongSuite Python Agent Authors", email = "[email protected]" },
1414
]
@@ -18,15 +18,16 @@ classifiers = [
1818
"License :: OSI Approved :: Apache Software License",
1919
"Programming Language :: Python",
2020
"Programming Language :: Python :: 3",
21-
"Programming Language :: Python :: 3.8",
2221
"Programming Language :: Python :: 3.9",
2322
"Programming Language :: Python :: 3.10",
2423
"Programming Language :: Python :: 3.11",
2524
"Programming Language :: Python :: 3.12",
2625
"Programming Language :: Python :: 3.13",
2726
]
2827
dependencies = [
29-
"wrapt",
28+
"opentelemetry-api ~= 1.37",
29+
"opentelemetry-instrumentation ~= 0.58b0",
30+
"opentelemetry-semantic-conventions ~= 0.58b0",
3031
]
3132

3233
[project.optional-dependencies]
@@ -35,8 +36,10 @@ instruments = [
3536
]
3637
test = [
3738
"agno",
39+
"openai",
3840
"pytest",
3941
"opentelemetry-sdk",
42+
"yfinance",
4043
]
4144
type-check = []
4245

instrumentation-loongsuite/loongsuite-instrumentation-agno/src/opentelemetry/instrumentation/agno/_extractor.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,12 @@ def extract(
180180
f"{GenAIAttributes.GEN_AI_RESPONSE_FINISH_REASONS}.image",
181181
json.dumps(response.image.to_dict(), indent=2),
182182
)
183-
# FIXME: ruff failed
184-
for idx, exec in enumerate( # noqa: A001
183+
for idx, tool_execution in enumerate(
185184
getattr(response, "tool_executions", []) or []
186185
):
187186
yield (
188187
f"{GenAIAttributes.GEN_AI_RESPONSE_FINISH_REASONS}.tool_executions.{idx}",
189-
json.dumps(exec.to_dict(), indent=2),
188+
json.dumps(tool_execution.to_dict(), indent=2),
190189
)
191190
# other metadata
192191
if getattr(response, "event", None):

0 commit comments

Comments
 (0)