Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

fix(serializer): handle single-string __slots__ and detect cycles in slotted objects

Đang mở
#2,014 0 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@hassiebp đang làm issue này rồi.

Từ ngày 16/10/2026.

  • #2015 của @passionworkeer — đang mở

Đánh giá

Issue này chưa được đánh giá.

Mô tả

bug sdk-python
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:

  1. 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) returns None, resulting in {"q": null, "u": null, ...} while the actual attribute query is lost.

  2. Missing circular reference detection:
    Unlike the __dict__ branch which tracks obj_id in self.seen to immediately break reference cycles, the __slots__ branch lacks self.seen protection. 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
  1. Normalize string __slots__ to a 1-tuple (obj.__slots__,) if isinstance(obj.__slots__, str).
  2. Add self.seen tracking with try...finally to __slots__ (matching __dict__).
Ngôn ngữ chính
Python
Star
500
Fork
367
Merge trung bình
16 giờ 18 phút
Pull request đã merge (30 ngày)
51

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của langfuse/langfuse-python

Tất cả issue của langfuse/langfuse-python

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.