Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

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

Abierto
#2,014 0 comentarios 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@hassiebp ya está trabajando en esto.

Desde el 16/10/2026.

  • #2015 de @passionworkeer — abierto

Evaluación

Este issue todavía no se ha evaluado.

Descripción

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__).
Lenguaje dominante
Python
Estrellas
500
Forks
367
Merge medio
16 h 18 min
PR fusionados (30 d)
51

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de langfuse/langfuse-python

Todos los issues de langfuse/langfuse-python

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.