feat(clew): serialize Python callables in AST output

This commit is contained in:
2026-09-07 19:53:14 -04:00
parent 3b96f5fca6
commit bb6600ba9d

View File

@@ -5,6 +5,7 @@ import json
import os import os
import struct import struct
import sys import sys
import types
import zlib import zlib
try: try:
@@ -110,6 +111,41 @@ def is_primitive(value):
return value is None or isinstance(value, (bool, int, long, float, basestring)) return value is None or isinstance(value, (bool, int, long, float, basestring))
def serialize_function(value):
code = getattr(value, "func_code", None) or getattr(value, "__code__", None)
result = {
"type": "function",
"name": safe_text(getattr(value, "func_name", None) or getattr(value, "__name__", None)),
"module": safe_text(getattr(value, "__module__", None)),
}
if code is not None:
result["filename"] = safe_text(getattr(code, "co_filename", None))
result["firstlineno"] = getattr(code, "co_firstlineno", None)
return result
def serialize_method(value):
function = getattr(value, "im_func", None) or getattr(value, "__func__", None)
receiver = getattr(value, "im_self", None) or getattr(value, "__self__", None)
result = serialize_function(function) if function is not None else {
"type": "function",
"name": safe_text(getattr(value, "__name__", None)),
"module": safe_text(getattr(value, "__module__", None)),
}
result["type"] = "method"
if receiver is not None:
result["receiver_class"] = class_name(receiver)
return result
def serialize_type(value):
return {
"type": "python-type",
"name": safe_text(getattr(value, "__name__", None)),
"module": safe_text(getattr(value, "__module__", None)),
}
class Serializer(object): class Serializer(object):
def __init__(self, max_depth): def __init__(self, max_depth):
self.max_depth = max_depth self.max_depth = max_depth
@@ -148,12 +184,14 @@ class Serializer(object):
self.active_containers.remove(object_id) self.active_containers.remove(object_id)
return {"type": "dict", "items": items} return {"type": "dict", "items": items}
if isinstance(value, types.FunctionType) or isinstance(value, types.BuiltinFunctionType):
return serialize_function(value)
if isinstance(value, types.MethodType):
return serialize_method(value)
if isinstance(value, type): if isinstance(value, type):
return { return serialize_type(value)
"type": "repr",
"class": class_name(value),
"repr": repr(value),
}
identity = id(value) identity = id(value)
if identity in self.seen: if identity in self.seen: