Coverage for pyguymer3/serializer.py: 2%
51 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def serializer(
5 obj,
6 /,
7 *,
8 evaluate = False,
9):
10 """Serialize an object into an intrinsic type
12 Serializer for objects not serializable by Python's default :mod:`json`
13 code. Converts all non-intrinsic types to intrinsic types.
15 Parameters
16 ----------
17 obj : anything
18 object to be serialized
19 evaluate : bool, optional
20 evaluate exifread.utils.Ratio objects into floats, otherwise return as string of form "X/Y" (default false)
22 Notes
23 -----
24 Copyright 2017 Thomas Guymer [1]_
26 References
27 ----------
28 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
29 """
31 # Import standard modules ...
32 import datetime
34 # Import special modules ...
35 try:
36 import exifread
37 except:
38 raise Exception("\"exifread\" is not installed; run \"pip install --user ExifRead\"") from None
39 try:
40 import numpy
41 except:
42 raise Exception("\"numpy\" is not installed; run \"pip install --user numpy\"") from None
44 # **************************************************************************
46 # Check type ...
47 if isinstance(obj, datetime.date):
48 # Return serializable answer ...
49 return obj.isoformat(sep = "T", timespec = "microseconds")
51 # Check type ...
52 if isinstance(obj, datetime.time):
53 # Return serializable answer ...
54 return obj.isoformat(sep = "T", timespec = "microseconds")
56 # Check type ...
57 if isinstance(obj, datetime.datetime):
58 # Return serializable answer ...
59 return obj.isoformat(sep = "T", timespec = "microseconds")
61 # Check type ...
62 if isinstance(obj, datetime.timedelta):
63 # Return serializable answer ...
64 return obj.total_seconds()
66 # **************************************************************************
68 # Check type ...
69 if isinstance(obj, exifread.utils.Ratio):
70 # Check if it is an integer mascarading as a fraction ...
71 if obj.den == 1:
72 return obj.num
74 # Check if the user wants to evaluate fractions ...
75 if evaluate:
76 # Catch floating-point exceptions ...
77 if obj.den == 0:
78 # Check sign ...
79 if obj.num < 0:
80 # Return serializable answer ...
81 return float("-inf")
83 # Return serializable answer ...
84 return float("inf")
86 # Return serializable answer ...
87 return float(obj.num) / float(obj.den)
89 # Return serializable answer ...
90 return f"{obj.num:d}/{obj.den:d}"
92 # **************************************************************************
94 # Check type ...
95 if isinstance(obj, numpy.int8):
96 # Return serializable answer ...
97 return int(obj)
99 # Check type ...
100 if isinstance(obj, numpy.int16):
101 # Return serializable answer ...
102 return int(obj)
104 # Check type ...
105 if isinstance(obj, numpy.int32):
106 # Return serializable answer ...
107 return int(obj)
109 # Check type ...
110 if isinstance(obj, numpy.int64):
111 # Return serializable answer ...
112 return int(obj)
114 # Check type ...
115 if isinstance(obj, numpy.uint8):
116 # Return serializable answer ...
117 return int(obj)
119 # Check type ...
120 if isinstance(obj, numpy.uint16):
121 # Return serializable answer ...
122 return int(obj)
124 # Check type ...
125 if isinstance(obj, numpy.uint32):
126 # Return serializable answer ...
127 return int(obj)
129 # Check type ...
130 if isinstance(obj, numpy.uint64):
131 # Return serializable answer ...
132 return int(obj)
134 # Check type ...
135 if isinstance(obj, numpy.float16):
136 # Return serializable answer ...
137 return float(obj)
139 # Check type ...
140 if isinstance(obj, numpy.float32):
141 # Return serializable answer ...
142 return float(obj)
144 # Check type ...
145 if isinstance(obj, numpy.float64):
146 # Return serializable answer ...
147 return float(obj)
149 # **************************************************************************
151 # Catch errors ...
152 raise TypeError("\"obj\" is an unexpected type", type(obj)) from None