Skip to content

qc.serializers

ITypeSerializer

Bases: Protocol

Protocol defining the interface for type-specific serializers.

This protocol ensures that all serializer implementations provide both byte-based (for embedding) and file-based (for external storage) serialization.

can_serialize

can_serialize(obj: Any) -> bool

Check if this serializer can handle the given object type.

Parameters:

Name Type Description Default
obj Any

Object to check.

required

Returns:

Name Type Description
bool bool

True if this serializer can handle the object.

Source code in src/contraqctor/qc/serializers.py
17
18
19
20
21
22
23
24
25
26
def can_serialize(self, obj: t.Any) -> bool:
    """Check if this serializer can handle the given object type.

    Args:
        obj: Object to check.

    Returns:
        bool: True if this serializer can handle the object.
    """
    ...

serialize_as_bytes

serialize_as_bytes(obj: Any) -> Dict[str, Any]

Serialize the object to a dictionary with base64-encoded bytes.

Used for embedding data directly in reports (e.g., HTML).

Parameters:

Name Type Description Default
obj Any

Object to serialize.

required

Returns:

Type Description
Dict[str, Any]

Dict containing the serialized representation with base64-encoded data.

Source code in src/contraqctor/qc/serializers.py
28
29
30
31
32
33
34
35
36
37
38
39
def serialize_as_bytes(self, obj: t.Any) -> t.Dict[str, t.Any]:
    """Serialize the object to a dictionary with base64-encoded bytes.

    Used for embedding data directly in reports (e.g., HTML).

    Args:
        obj: Object to serialize.

    Returns:
        Dict containing the serialized representation with base64-encoded data.
    """
    ...

serialize_as_file

serialize_as_file(
    obj: Any, output_dir: Path, filename: str
) -> Dict[str, Any]

Serialize the object to a file and return metadata.

Used for saving data to external files (e.g., for CLI reports).

Parameters:

Name Type Description Default
obj Any

Object to serialize.

required
output_dir Path

Directory where the file should be saved.

required
filename str

Name for the output file (without extension).

required

Returns:

Type Description
Dict[str, Any]

Dict containing metadata including 'type', 'path', and other relevant info.

Source code in src/contraqctor/qc/serializers.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def serialize_as_file(self, obj: t.Any, output_dir: Path, filename: str) -> t.Dict[str, t.Any]:
    """Serialize the object to a file and return metadata.

    Used for saving data to external files (e.g., for CLI reports).

    Args:
        obj: Object to serialize.
        output_dir: Directory where the file should be saved.
        filename: Name for the output file (without extension).

    Returns:
        Dict containing metadata including 'type', 'path', and other relevant info.
    """
    ...

TypeSerializer

Bases: ABC

Base class for type-specific serializers.

Implements the ITypeSerializer protocol with abstract methods that must be overridden by subclasses.

can_serialize abstractmethod

can_serialize(obj: Any) -> bool

Check if this serializer can handle the given object type.

Parameters:

Name Type Description Default
obj Any

Object to check.

required

Returns:

Name Type Description
bool bool

True if this serializer can handle the object.

Source code in src/contraqctor/qc/serializers.py
64
65
66
67
68
69
70
71
72
73
74
@abstractmethod
def can_serialize(self, obj: t.Any) -> bool:
    """Check if this serializer can handle the given object type.

    Args:
        obj: Object to check.

    Returns:
        bool: True if this serializer can handle the object.
    """
    pass

serialize_as_bytes abstractmethod

serialize_as_bytes(obj: Any) -> Dict[str, Any]

Serialize the object to a dictionary with base64-encoded bytes.

Used for embedding data directly in reports (e.g., HTML).

Parameters:

Name Type Description Default
obj Any

Object to serialize.

required

Returns:

Type Description
Dict[str, Any]

Dict containing the serialized representation with base64-encoded data.

Source code in src/contraqctor/qc/serializers.py
76
77
78
79
80
81
82
83
84
85
86
87
88
@abstractmethod
def serialize_as_bytes(self, obj: t.Any) -> t.Dict[str, t.Any]:
    """Serialize the object to a dictionary with base64-encoded bytes.

    Used for embedding data directly in reports (e.g., HTML).

    Args:
        obj: Object to serialize.

    Returns:
        Dict containing the serialized representation with base64-encoded data.
    """
    pass

serialize_as_file abstractmethod

serialize_as_file(
    obj: Any, output_dir: Path, filename: str
) -> Dict[str, Any]

Serialize the object to a file and return metadata.

Used for saving data to external files (e.g., for CLI reports).

Parameters:

Name Type Description Default
obj Any

Object to serialize.

required
output_dir Path

Directory where the file should be saved.

required
filename str

Name for the output file (without extension).

required

Returns:

Type Description
Dict[str, Any]

Dict containing metadata including 'type', 'path', and other relevant info.

Source code in src/contraqctor/qc/serializers.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
@abstractmethod
def serialize_as_file(self, obj: t.Any, output_dir: Path, filename: str) -> t.Dict[str, t.Any]:
    """Serialize the object to a file and return metadata.

    Used for saving data to external files (e.g., for CLI reports).

    Args:
        obj: Object to serialize.
        output_dir: Directory where the file should be saved.
        filename: Name for the output file (without extension).

    Returns:
        Dict containing metadata including 'type', 'path', and other relevant info.
    """
    pass

MatplotlibFigureSerializer

Bases: TypeSerializer

Serializer for matplotlib Figure objects.

can_serialize

can_serialize(obj: Any) -> bool

Check if object is a matplotlib Figure.

Source code in src/contraqctor/qc/serializers.py
110
111
112
113
114
115
116
117
def can_serialize(self, obj: t.Any) -> bool:
    """Check if object is a matplotlib Figure."""
    try:
        import matplotlib.figure

        return isinstance(obj, matplotlib.figure.Figure)
    except ImportError:
        return False

serialize_as_bytes

serialize_as_bytes(obj: Any) -> Dict[str, Any]

Serialize matplotlib Figure to base64-encoded PNG.

Parameters:

Name Type Description Default
obj Any

Matplotlib Figure object.

required

Returns:

Type Description
Dict[str, Any]

Dict with 'type' and 'data' keys containing base64-encoded PNG.

Source code in src/contraqctor/qc/serializers.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def serialize_as_bytes(self, obj: t.Any) -> t.Dict[str, t.Any]:
    """Serialize matplotlib Figure to base64-encoded PNG.

    Args:
        obj: Matplotlib Figure object.

    Returns:
        Dict with 'type' and 'data' keys containing base64-encoded PNG.
    """
    buf = io.BytesIO()
    obj.savefig(buf, format="png", bbox_inches="tight")
    buf.seek(0)
    img_base64 = base64.b64encode(buf.read()).decode("utf-8")
    buf.close()

    return {"type": "image", "data": f"data:image/png;base64,{img_base64}"}

serialize_as_file

serialize_as_file(
    obj: Any, output_dir: Path, filename: str
) -> Dict[str, Any]

Serialize matplotlib Figure to a PNG file.

Parameters:

Name Type Description Default
obj Any

Matplotlib Figure object.

required
output_dir Path

Directory where the file should be saved.

required
filename str

Name for the output file (without extension).

required

Returns:

Type Description
Dict[str, Any]

Dict with 'type' and 'path' keys.

Source code in src/contraqctor/qc/serializers.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def serialize_as_file(self, obj: t.Any, output_dir: Path, filename: str) -> t.Dict[str, t.Any]:
    """Serialize matplotlib Figure to a PNG file.

    Args:
        obj: Matplotlib Figure object.
        output_dir: Directory where the file should be saved.
        filename: Name for the output file (without extension).

    Returns:
        Dict with 'type' and 'path' keys.
    """
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / f"{filename}.png"
    obj.savefig(output_path, format="png", bbox_inches="tight")

    return {"type": "image", "path": str(output_path)}

PILImageSerializer

Bases: TypeSerializer

Serializer for PIL Image objects.

can_serialize

can_serialize(obj: Any) -> bool

Check if object is a PIL Image.

Source code in src/contraqctor/qc/serializers.py
157
158
159
160
161
162
163
164
def can_serialize(self, obj: t.Any) -> bool:
    """Check if object is a PIL Image."""
    try:
        from PIL import Image

        return isinstance(obj, Image.Image)
    except ImportError:
        return False

serialize_as_bytes

serialize_as_bytes(obj: Any) -> Dict[str, Any]

Serialize PIL Image to base64-encoded PNG.

Parameters:

Name Type Description Default
obj Any

PIL Image object.

required

Returns:

Type Description
Dict[str, Any]

Dict with 'type' and 'data' keys containing base64-encoded PNG.

Source code in src/contraqctor/qc/serializers.py
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
def serialize_as_bytes(self, obj: t.Any) -> t.Dict[str, t.Any]:
    """Serialize PIL Image to base64-encoded PNG.

    Args:
        obj: PIL Image object.

    Returns:
        Dict with 'type' and 'data' keys containing base64-encoded PNG.
    """
    buf = io.BytesIO()
    obj.save(buf, format="PNG")
    buf.seek(0)
    img_base64 = base64.b64encode(buf.read()).decode("utf-8")
    buf.close()

    return {"type": "image", "data": f"data:image/png;base64,{img_base64}"}

serialize_as_file

serialize_as_file(
    obj: Any, output_dir: Path, filename: str
) -> Dict[str, Any]

Serialize PIL Image to a PNG file.

Parameters:

Name Type Description Default
obj Any

PIL Image object.

required
output_dir Path

Directory where the file should be saved.

required
filename str

Name for the output file (without extension).

required

Returns:

Type Description
Dict[str, Any]

Dict with 'type' and 'path' keys.

Source code in src/contraqctor/qc/serializers.py
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
def serialize_as_file(self, obj: t.Any, output_dir: Path, filename: str) -> t.Dict[str, t.Any]:
    """Serialize PIL Image to a PNG file.

    Args:
        obj: PIL Image object.
        output_dir: Directory where the file should be saved.
        filename: Name for the output file (without extension).

    Returns:
        Dict with 'type' and 'path' keys.
    """
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / f"{filename}.png"
    obj.save(output_path, format="PNG")

    return {"type": "image", "path": str(output_path)}

NumpyArrayImageSerializer

Bases: TypeSerializer

Serializer for numpy arrays representing images.

can_serialize

can_serialize(obj: Any) -> bool

Check if object is a numpy array that could be an image.

Valid image arrays are 2D (grayscale) or 3D with 3 or 4 channels (RGB/RGBA).

Source code in src/contraqctor/qc/serializers.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
def can_serialize(self, obj: t.Any) -> bool:
    """Check if object is a numpy array that could be an image.

    Valid image arrays are 2D (grayscale) or 3D with 3 or 4 channels (RGB/RGBA).
    """
    try:
        import numpy as np

        if not isinstance(obj, np.ndarray):
            return False

        if obj.ndim == 2:
            return True
        elif obj.ndim == 3 and obj.shape[2] in (3, 4):
            return True

        return False
    except ImportError:
        return False

serialize_as_bytes

serialize_as_bytes(obj: Any) -> Dict[str, Any]

Serialize numpy array to base64-encoded PNG using PIL.

Parameters:

Name Type Description Default
obj Any

Numpy array representing an image.

required

Returns:

Type Description
Dict[str, Any]

Dict with 'type' and 'data' keys containing base64-encoded PNG.

Source code in src/contraqctor/qc/serializers.py
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
def serialize_as_bytes(self, obj: t.Any) -> t.Dict[str, t.Any]:
    """Serialize numpy array to base64-encoded PNG using PIL.

    Args:
        obj: Numpy array representing an image.

    Returns:
        Dict with 'type' and 'data' keys containing base64-encoded PNG.
    """
    img = self._array_to_pil(obj)

    buf = io.BytesIO()
    img.save(buf, format="PNG")
    buf.seek(0)
    img_base64 = base64.b64encode(buf.read()).decode("utf-8")
    buf.close()

    return {"type": "image", "data": f"data:image/png;base64,{img_base64}"}

serialize_as_file

serialize_as_file(
    obj: Any, output_dir: Path, filename: str
) -> Dict[str, Any]

Serialize numpy array to a PNG file.

Parameters:

Name Type Description Default
obj Any

Numpy array representing an image.

required
output_dir Path

Directory where the file should be saved.

required
filename str

Name for the output file (without extension).

required

Returns:

Type Description
Dict[str, Any]

Dict with 'type' and 'path' keys.

Source code in src/contraqctor/qc/serializers.py
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
def serialize_as_file(self, obj: t.Any, output_dir: Path, filename: str) -> t.Dict[str, t.Any]:
    """Serialize numpy array to a PNG file.

    Args:
        obj: Numpy array representing an image.
        output_dir: Directory where the file should be saved.
        filename: Name for the output file (without extension).

    Returns:
        Dict with 'type' and 'path' keys.
    """
    img = self._array_to_pil(obj)

    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / f"{filename}.png"
    img.save(output_path, format="PNG")

    return {"type": "image", "path": str(output_path)}

ContextExportableObjSerializer

ContextExportableObjSerializer(
    serializers: Optional[List[ITypeSerializer]] = None,
)

Serializer for ContextExportableObj instances.

This class recursively searches through dictionaries and serializes ContextExportableObj instances based on their wrapped object types.

Attributes:

Name Type Description
serializers List[ITypeSerializer]

List of ITypeSerializer instances to use for serialization.

Initialize the serializer with optional custom type serializers.

Parameters:

Name Type Description Default
serializers Optional[List[ITypeSerializer]]

List of ITypeSerializer instances. If None, uses default serializers for matplotlib figures and PIL/numpy images.

None
Source code in src/contraqctor/qc/serializers.py
306
307
308
309
310
311
312
313
314
315
316
def __init__(self, serializers: t.Optional[t.List[ITypeSerializer]] = None):
    """Initialize the serializer with optional custom type serializers.

    Args:
        serializers: List of ITypeSerializer instances. If None, uses default
            serializers for matplotlib figures and PIL/numpy images.
    """
    if serializers is None:
        self.serializers: t.List[ITypeSerializer] = t.cast(t.List[ITypeSerializer], KNOWN_SERIALIZERS.copy())
    else:
        self.serializers = serializers

add_serializer

add_serializer(serializer: ITypeSerializer) -> None

Add a custom type serializer.

Parameters:

Name Type Description Default
serializer ITypeSerializer

ITypeSerializer instance to add.

required
Source code in src/contraqctor/qc/serializers.py
318
319
320
321
322
323
324
def add_serializer(self, serializer: ITypeSerializer) -> None:
    """Add a custom type serializer.

    Args:
        serializer: ITypeSerializer instance to add.
    """
    self.serializers.append(serializer)

serialize_as_bytes

serialize_as_bytes(context: Any) -> Any

Recursively serialize ContextExportableObj instances to base64-encoded bytes.

This method walks through the context structure and serializes any ContextExportableObj instances it finds to base64-encoded data.

Parameters:

Name Type Description Default
context Any

Context data to serialize (can be dict, list, or any value).

required

Returns:

Type Description
Any

Serialized context with ContextExportableObj instances replaced by

Any

their base64-encoded representations.

Source code in src/contraqctor/qc/serializers.py
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
def serialize_as_bytes(self, context: t.Any) -> t.Any:
    """Recursively serialize ContextExportableObj instances to base64-encoded bytes.

    This method walks through the context structure and serializes any
    ContextExportableObj instances it finds to base64-encoded data.

    Args:
        context: Context data to serialize (can be dict, list, or any value).

    Returns:
        Serialized context with ContextExportableObj instances replaced by
        their base64-encoded representations.
    """
    if isinstance(context, dict):
        result = {}
        for key, value in context.items():
            if isinstance(value, ContextExportableObj):
                result[key] = self._serialize_exportable_obj_as_bytes(value)
            else:
                result[key] = self.serialize_as_bytes(value)
        return result
    elif isinstance(context, (list, tuple)):
        return type(context)(self.serialize_as_bytes(item) for item in context)
    elif isinstance(context, ContextExportableObj):
        return self._serialize_exportable_obj_as_bytes(context)
    else:
        return context

serialize_as_file

serialize_as_file(
    context: Any,
    output_dir: Path,
    base_filename: str = "asset",
    counter: Optional[dict] = None,
) -> Any

Recursively serialize ContextExportableObj instances to files.

This method walks through the context structure and serializes any ContextExportableObj instances it finds to external files.

Parameters:

Name Type Description Default
context Any

Context data to serialize (can be dict, list, or any value).

required
output_dir Path

Directory where files should be saved.

required
base_filename str

Base name for output files.

'asset'
counter Optional[dict]

Optional counter dict to track file numbers (for internal use).

None

Returns:

Type Description
Any

Serialized context with ContextExportableObj instances replaced by

Any

their file path representations.

Source code in src/contraqctor/qc/serializers.py
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
def serialize_as_file(
    self, context: t.Any, output_dir: Path, base_filename: str = "asset", counter: t.Optional[dict] = None
) -> t.Any:
    """Recursively serialize ContextExportableObj instances to files.

    This method walks through the context structure and serializes any
    ContextExportableObj instances it finds to external files.

    Args:
        context: Context data to serialize (can be dict, list, or any value).
        output_dir: Directory where files should be saved.
        base_filename: Base name for output files.
        counter: Optional counter dict to track file numbers (for internal use).

    Returns:
        Serialized context with ContextExportableObj instances replaced by
        their file path representations.
    """
    if counter is None:
        counter = {"count": 0}

    if isinstance(context, dict):
        result = {}
        for key, value in context.items():
            if isinstance(value, ContextExportableObj):
                result[key] = self._serialize_exportable_obj_as_file(value, output_dir, base_filename, counter)
            else:
                result[key] = self.serialize_as_file(value, output_dir, base_filename, counter)
        return result
    elif isinstance(context, (list, tuple)):
        return type(context)(self.serialize_as_file(item, output_dir, base_filename, counter) for item in context)
    elif isinstance(context, ContextExportableObj):
        return self._serialize_exportable_obj_as_file(context, output_dir, base_filename, counter)
    else:
        return context