fix(serializer): handle single-string __slots__ and detect cycles in slotted objects
维护者通常 1 天内回复
评估
这个 Issue 还没有评估数据。
描述
Describe the bug
In langfuse._utils.serializer.EventSerializer, slotted objects are handled by iterating over obj.__slots__:
if hasattr(obj, "__slots__"):
return {
slot: self.default(getattr(obj, slot, None))
for slot in obj.__slots__
}
Two distinct defects exist in this logic:
-
Single string
__slots__attribute loss:
According to the Python Language Reference (Data Model §3.3.2.4:__slots__),__slots__can be defined as a single string naming a single attribute (e.g.__slots__ = "query"). When__slots__is a string, iterating directly over it yields individual characters (q,u,e,r,y).getattr(obj, "q", None)returnsNone, resulting in{"q": null, "u": null, ...}while the actual attributequeryis lost. -
Missing circular reference detection:
Unlike the__dict__branch which tracksobj_id in self.seento immediately break reference cycles, the__slots__branch lacksself.seenprotection. When slotted objects contain reference cycles, each branch expands down to_MAX_DEPTH = 20, causing redundant recursion and bloated payloads.
To Reproduce
import json
from langfuse._utils.serializer import EventSerializer
# Case 1: Single string slot
class SingleSlot:
__slots__ = "query"
def __init__(self):
self.query = "SELECT 1"
res = json.loads(EventSerializer().encode(SingleSlot()))
print(res)
# Current output: {"q": null, "u": null, "e": null, "r": null, "y": null}
# Expected: {"query": "SELECT 1"}
# Case 2: Self-referential slotted node
class SlotNode:
__slots__ = ("next",)
node = SlotNode()
node.next = node
res = json.loads(EventSerializer().encode(node))
# Current output: recurses 20 layers deep
# Expected: {"next": "SlotNode"}
Proposed Fix
- Normalize string
__slots__to a 1-tuple(obj.__slots__,)ifisinstance(obj.__slots__, str). - Add
self.seentracking withtry...finallyto__slots__(matching__dict__).
- 主要语言
- Python
- 星标
- 500
- 派生
- 367
- 平均合并
- 16 小时 18 分钟
- 30 天内合并 PR
- 51
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
langfuse/langfuse-python 的其他 Issue
-
tests/unit/test_prompt.py fails on a fresh clone without LANGFUSE_* env vars可能已有人在做 @Mathoholic 于 7 天前认领。 未关闭bug feat-prompt-management sdk-python
难度 2/5 1-3 小时 新手友好度 80/100
langfuse/langfuse-python#1976 · 3 条评论 ·
维护者通常 1 天内回复
-
bug(langchain): failed streaming LLM runs retain IDs in callback memo可能已有人在做 @hassiebp 于 7 天前认领。 未关闭bug integration-langchain sdk-python
langfuse/langfuse-python#1977 · 已指派 1 人 ·
维护者通常 1 天内回复
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder item可能已有人在做 @hassiebp 于 8 天前认领。 未关闭bug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 已指派 1 人 ·
维护者通常 1 天内回复
-
bug: GCS upload detection in MediaManager uses substring match on the full URL可能已有人在做 @hassiebp 于 17 天前认领。 未关闭bug feat-multimodal-media sdk-python
langfuse/langfuse-python#1913 · 1 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
mask is not applied to create_dataset_item or create_score(comment=)可能已有人在做 @hassiebp 于 25 天前认领。 未关闭bug compliance feat-data-masking sdk-python security
langfuse/langfuse-python#1896 · 1 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
查看 langfuse/langfuse-python 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
-
难度 2/5 1-3 小时 新手友好度 68/100
collective/icalendar#1968 · 1 条评论 ·
维护者通常 1 天内回复
-
Deferred from #1869: Complete the companion pytest guardrail update noted in the PR description...未关闭
难度 1/5 1 小时以内 新手友好度 95/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 88/100
NousResearch/hermes-agent#140958 ·
维护者通常 1 天内回复
-
Bug triage/confirmed
难度 2/5 半天 新手友好度 85/100
agentscope-ai/agentscope#3355 ·
维护者通常 2 天内回复