11import inspect
22from abc import ABCMeta , abstractmethod
33from collections import namedtuple
4+ from enum import Enum
5+ from typing import Any , List , Optional , Tuple , Type , Union
46
57
6- # Serialization formats. STORAGE produces (blobs, metadata) for the datastore;
7- # WIRE produces a str for CLI args, protobuf payloads, and cross-process IPC.
8- STORAGE = "storage"
9- WIRE = "wire"
8+ class SerializationFormat (str , Enum ):
9+ """
10+ Representation a serializer produces or consumes.
11+
12+ - ``STORAGE`` yields ``(List[SerializedBlob], SerializationMetadata)`` for
13+ the datastore save path.
14+ - ``WIRE`` yields a ``str`` for CLI args, protobuf payloads, and
15+ cross-process IPC.
16+
17+ Subclassing ``str`` keeps ``SerializationFormat.STORAGE == "storage"``
18+ True, so existing call sites that compare against the string literal
19+ keep working without a migration.
20+ """
21+
22+ STORAGE = "storage"
23+ WIRE = "wire"
24+
25+
26+ # Module-level aliases kept so call sites can write ``format=STORAGE`` without
27+ # importing the enum itself.
28+ STORAGE = SerializationFormat .STORAGE
29+ WIRE = SerializationFormat .WIRE
1030
1131
1232SerializationMetadata = namedtuple (
@@ -30,7 +50,11 @@ class SerializedBlob(object):
3050 If None, auto-detected from value type: str -> reference, bytes -> new data.
3151 """
3252
33- def __init__ (self , value , is_reference = None ):
53+ def __init__ (
54+ self ,
55+ value : Union [str , bytes ],
56+ is_reference : Optional [bool ] = None ,
57+ ):
3458 if not isinstance (value , (str , bytes )):
3559 raise TypeError (
3660 "SerializedBlob value must be str or bytes, got %s" % type (value ).__name__
@@ -42,7 +66,7 @@ def __init__(self, value, is_reference=None):
4266 self .is_reference = is_reference
4367
4468 @property
45- def needs_save (self ):
69+ def needs_save (self ) -> bool :
4670 """True if this blob contains new bytes that need to be stored."""
4771 return not self .is_reference
4872
@@ -69,7 +93,7 @@ def __init__(cls, name, bases, namespace):
6993 SerializerStore ._ordered_cache = None
7094
7195 @staticmethod
72- def get_ordered_serializers ():
96+ def get_ordered_serializers () -> List [ Type [ "ArtifactSerializer" ]] :
7397 """
7498 Return serializer classes sorted by (PRIORITY, registration_order).
7599
@@ -127,12 +151,12 @@ class ArtifactSerializer(object, metaclass=SerializerStore):
127151 PickleSerializer uses 9999 as the universal fallback.
128152 """
129153
130- TYPE = None
131- PRIORITY = 100
154+ TYPE : Optional [ str ] = None
155+ PRIORITY : int = 100
132156
133157 @classmethod
134158 @abstractmethod
135- def can_serialize (cls , obj ) :
159+ def can_serialize (cls , obj : Any ) -> bool :
136160 """
137161 Return True if this serializer can handle the given object.
138162
@@ -149,7 +173,7 @@ def can_serialize(cls, obj):
149173
150174 @classmethod
151175 @abstractmethod
152- def can_deserialize (cls , metadata ) :
176+ def can_deserialize (cls , metadata : SerializationMetadata ) -> bool :
153177 """
154178 Return True if this serializer can deserialize given the metadata.
155179
@@ -166,7 +190,11 @@ def can_deserialize(cls, metadata):
166190
167191 @classmethod
168192 @abstractmethod
169- def serialize (cls , obj , format = STORAGE ):
193+ def serialize (
194+ cls ,
195+ obj : Any ,
196+ format : SerializationFormat = STORAGE ,
197+ ) -> Union [Tuple [List [SerializedBlob ], SerializationMetadata ], str ]:
170198 """
171199 Serialize obj. Must be side-effect-free: this method may be invoked
172200 multiple times (caching, retries, parallel dispatch) and must not
@@ -178,7 +206,7 @@ def serialize(cls, obj, format=STORAGE):
178206 ----------
179207 obj : Any
180208 The Python object to serialize.
181- format : str
209+ format : SerializationFormat
182210 Either ``STORAGE`` (default) or ``WIRE``.
183211 - ``STORAGE`` returns a tuple ``(List[SerializedBlob], SerializationMetadata)``
184212 for persisting through the datastore.
@@ -194,7 +222,12 @@ def serialize(cls, obj, format=STORAGE):
194222
195223 @classmethod
196224 @abstractmethod
197- def deserialize (cls , data , metadata = None , context = None , format = STORAGE ):
225+ def deserialize (
226+ cls ,
227+ data : Union [List [bytes ], str ],
228+ metadata : Optional [SerializationMetadata ] = None ,
229+ format : SerializationFormat = STORAGE ,
230+ ) -> Any :
198231 """
199232 Deserialize back to a Python object.
200233
@@ -205,9 +238,7 @@ def deserialize(cls, data, metadata=None, context=None, format=STORAGE):
205238 metadata : SerializationMetadata, optional
206239 Metadata stored alongside the artifact. Required for STORAGE,
207240 ignored for WIRE.
208- context : Any, optional
209- Optional context for deserialization (e.g., task vs client loading).
210- format : str
241+ format : SerializationFormat
211242 Either ``STORAGE`` (default) or ``WIRE``.
212243
213244 Returns
0 commit comments