Serialize a function by capturing all its components.
(self, write_context, func)
| 1409 | ) |
| 1410 | |
| 1411 | def _serialize_function(self, write_context, func): |
| 1412 | """Serialize a function by capturing all its components.""" |
| 1413 | # Get function metadata |
| 1414 | instance = getattr(func, "__self__", None) |
| 1415 | if instance is not None and not inspect.ismodule(instance): |
| 1416 | # Handle bound methods |
| 1417 | self_obj = instance |
| 1418 | func_name = func.__name__ |
| 1419 | # Serialize as a tuple (is_method, self_obj, method_name) |
| 1420 | write_context.write_int8(0) |
| 1421 | write_context.write_ref(self_obj) |
| 1422 | write_context.write_string(func_name) |
| 1423 | return |
| 1424 | |
| 1425 | # Regular function or lambda |
| 1426 | code = func.__code__ |
| 1427 | module = func.__module__ |
| 1428 | qualname = func.__qualname__ |
| 1429 | |
| 1430 | if "<locals>" not in qualname and module != "__main__": |
| 1431 | write_context.write_int8(1) |
| 1432 | write_context.write_string(module) |
| 1433 | write_context.write_string(qualname) |
| 1434 | return |
| 1435 | |
| 1436 | write_context.write_int8(2) |
| 1437 | write_context.write_string(module) |
| 1438 | write_context.write_string(qualname) |
| 1439 | |
| 1440 | defaults = func.__defaults__ |
| 1441 | closure = func.__closure__ |
| 1442 | globals_dict = func.__globals__ |
| 1443 | |
| 1444 | # Instead of trying to serialize the code object in parts, use marshal |
| 1445 | # which is specifically designed for code objects |
| 1446 | marshalled_code = marshal.dumps(code) |
| 1447 | write_context.write_bytes_and_size(marshalled_code) |
| 1448 | |
| 1449 | # Serialize defaults (or None if no defaults) |
| 1450 | # Write whether defaults exist |
| 1451 | write_context.write_bool(defaults is not None) |
| 1452 | if defaults is not None: |
| 1453 | write_context.write_var_uint32(len(defaults)) |
| 1454 | for default_value in defaults: |
| 1455 | write_context.write_ref(default_value) |
| 1456 | |
| 1457 | # Handle closure |
| 1458 | # We need to serialize both the closure values and the fact that there is a closure |
| 1459 | # The code object's co_freevars tells us what variables are in the closure |
| 1460 | write_context.write_bool(closure is not None) |
| 1461 | write_context.write_var_uint32(len(code.co_freevars) if code.co_freevars else 0) |
| 1462 | |
| 1463 | if closure: |
| 1464 | for cell in closure: |
| 1465 | write_context.write_ref(cell.cell_contents) |
| 1466 | |
| 1467 | # Serialize free variable names as a list of strings |
| 1468 | # Convert tuple to list since tuple might not be registered |
no test coverage detected