@@ -974,28 +974,47 @@ def _handle_catalog_invocation(
974974
975975 fn_log .debug ("catalog_method_result" , result = result )
976976
977- # Serialize and stream result
977+ # Serialize and stream result with protocol state metadata
978978 # Result types:
979979 # - None → empty batch (0 rows, 0 columns)
980980 # - list of primitives → convert to single-column batch (e.g., catalogs())
981981 # - Dataclass with serialize() → serialize to bytes, write
982982 # - Iterable of dataclasses → stream multiple serialized items
983+ from vgi .ipc_utils import ProtocolState , protocol_state_metadata
984+
985+ catalog_result_metadata = protocol_state_metadata (ProtocolState .CATALOG_RESULT )
986+
983987 if result is None :
984988 # Write empty batch to signal no result
985989 batch = pa .RecordBatch .from_pydict ({})
986- stdout . write ( batch .schema . serialize (). to_pybytes ())
987- stdout . write (batch . serialize (). to_pybytes () )
990+ with pa . ipc . new_stream ( cast ( IOBase , stdout ), batch .schema ) as writer :
991+ writer . write_batch (batch , custom_metadata = catalog_result_metadata )
988992 elif isinstance (result , list ) and (
989993 not result or not hasattr (result [0 ], "serialize" )
990994 ):
991995 # List of primitives (e.g., strings from catalogs())
992996 batch = pa .RecordBatch .from_pydict ({"value" : result })
993- stdout . write ( batch .schema . serialize (). to_pybytes ())
994- stdout . write (batch . serialize (). to_pybytes () )
997+ with pa . ipc . new_stream ( cast ( IOBase , stdout ), batch .schema ) as writer :
998+ writer . write_batch (batch , custom_metadata = catalog_result_metadata )
995999 elif hasattr (result , "serialize" ):
996- # Single dataclass result - write serialized bytes directly
997- result_bytes = result .serialize ()
998- stdout .write (result_bytes )
1000+ # Single dataclass result - serialize with protocol state if possible
1001+ # Check if serialize() accepts custom_metadata parameter
1002+ import inspect
1003+
1004+ sig = inspect .signature (result .serialize )
1005+ if "custom_metadata" in sig .parameters :
1006+ result_bytes = result .serialize (custom_metadata = catalog_result_metadata )
1007+ stdout .write (result_bytes )
1008+ else :
1009+ # Fallback: use serialize() then we need to re-wrap with protocol state
1010+ # This is less efficient but ensures protocol state is included
1011+ result_bytes = result .serialize ()
1012+ # Deserialize and re-serialize with protocol state
1013+ from vgi .ipc_utils import deserialize_record_batch
1014+
1015+ batch , _ = deserialize_record_batch (result_bytes )
1016+ with pa .ipc .new_stream (cast (IOBase , stdout ), batch .schema ) as writer :
1017+ writer .write_batch (batch , custom_metadata = catalog_result_metadata )
9991018 elif isinstance (result , list ) and result and hasattr (result [0 ], "to_row_dict" ):
10001019 # List of catalog objects with to_row_dict() - use efficient batch writing
10011020 # Determine the schema based on method and type parameter
@@ -1045,12 +1064,12 @@ def _handle_catalog_invocation(
10451064 # Fallback: use the ARROW_SCHEMA from the first item's class
10461065 schema = type (result [0 ]).ARROW_SCHEMA
10471066
1048- # Collect all rows and write as single batch
1067+ # Collect all rows and write as single batch with protocol state
10491068 rows = [item .to_row_dict () for item in result ]
10501069 batch = pa .RecordBatch .from_pylist (rows , schema = schema )
10511070
10521071 with pa .ipc .new_stream (cast (IOBase , stdout ), schema ) as writer :
1053- writer .write_batch (batch )
1072+ writer .write_batch (batch , custom_metadata = catalog_result_metadata )
10541073 elif isinstance (result , list ) and not result :
10551074 # Empty list - need to determine schema for empty batch
10561075 from vgi .catalog import (
@@ -1086,7 +1105,7 @@ def _handle_catalog_invocation(
10861105
10871106 batch = pa .RecordBatch .from_pylist ([], schema = schema )
10881107 with pa .ipc .new_stream (cast (IOBase , stdout ), schema ) as writer :
1089- writer .write_batch (batch )
1108+ writer .write_batch (batch , custom_metadata = catalog_result_metadata )
10901109 else :
10911110 raise TypeError (
10921111 f"Catalog method returned unsupported type: "
0 commit comments