steer-core 0.1.30__tar.gz → 0.1.32__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {steer_core-0.1.30 → steer_core-0.1.32}/PKG-INFO +1 -1
- {steer_core-0.1.30/steer_core → steer_core-0.1.32/steer_core/Data}/DataManager.py +76 -1
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/Plotter.py +2 -0
- steer_core-0.1.32/steer_core/Mixins/Serializer.py +281 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/TypeChecker.py +2 -1
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/__init__.py +1 -4
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core.egg-info/PKG-INFO +1 -1
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core.egg-info/SOURCES.txt +1 -2
- steer_core-0.1.30/steer_core/Data/database.db +0 -0
- steer_core-0.1.30/steer_core/Mixins/Serializer.py +0 -46
- {steer_core-0.1.30 → steer_core-0.1.32}/README.md +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/pyproject.toml +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/setup.cfg +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Constants/Units.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Constants/Universal.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Constants/__init__.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/ContextManagers/ContextManagers.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/ContextManagers/__init__.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Data/__init__.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Decorators/Coordinates.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Decorators/General.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Decorators/Objects.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Decorators/__init__.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/Colors.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/Coordinates.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/Data.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/Dunder.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core/Mixins/__init__.py +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core.egg-info/dependency_links.txt +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core.egg-info/requires.txt +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/steer_core.egg-info/top_level.txt +0 -0
- {steer_core-0.1.30 → steer_core-0.1.32}/test/test_validation_mixin.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: steer-core
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.32
|
|
4
4
|
Summary: Modelling energy storage from cell to site - STEER OpenCell Design
|
|
5
5
|
Author-email: Nicholas Siemons <nsiemons@stanford.edu>
|
|
6
6
|
Maintainer-email: Nicholas Siemons <nsiemons@stanford.edu>
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import sqlite3 as sql
|
|
2
2
|
from pathlib import Path
|
|
3
|
+
from typing import TypeVar
|
|
3
4
|
import pandas as pd
|
|
4
5
|
import importlib.resources
|
|
5
6
|
|
|
6
7
|
from steer_core.Constants.Units import *
|
|
8
|
+
from steer_core.Mixins.Serializer import SerializerMixin
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
T = TypeVar('T', bound='SerializerMixin')
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
class DataManager:
|
|
10
15
|
|
|
11
16
|
def __init__(self):
|
|
12
|
-
with importlib.resources.path("
|
|
17
|
+
with importlib.resources.path("steer_opencell_data", "database.db") as db_path:
|
|
13
18
|
self._db_path = db_path
|
|
14
19
|
self._connection = sql.connect(self._db_path)
|
|
15
20
|
self._cursor = self._connection.cursor()
|
|
@@ -356,5 +361,75 @@ class DataManager:
|
|
|
356
361
|
self._cursor.execute(f"DELETE FROM {table_name} WHERE {condition}")
|
|
357
362
|
self._connection.commit()
|
|
358
363
|
|
|
364
|
+
|
|
365
|
+
@classmethod
|
|
366
|
+
def from_database(cls: type[T], name: str, table_name: str = None) -> T:
|
|
367
|
+
"""
|
|
368
|
+
Pull object from the database by name.
|
|
369
|
+
|
|
370
|
+
Subclasses must define a '_table_name' class variable (str or list of str)
|
|
371
|
+
unless table_name is explicitly provided.
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
name : str
|
|
376
|
+
Name of the object to retrieve.
|
|
377
|
+
table_name : str, optional
|
|
378
|
+
Specific table to search. If provided, '_table_name' is not required.
|
|
379
|
+
If None, uses class's _table_name.
|
|
380
|
+
|
|
381
|
+
Returns
|
|
382
|
+
-------
|
|
383
|
+
T
|
|
384
|
+
Instance of the class.
|
|
385
|
+
|
|
386
|
+
Raises
|
|
387
|
+
------
|
|
388
|
+
NotImplementedError
|
|
389
|
+
If the subclass doesn't define '_table_name' and table_name is not provided.
|
|
390
|
+
ValueError
|
|
391
|
+
If the object name is not found in any of the tables.
|
|
392
|
+
"""
|
|
393
|
+
database = cls()
|
|
394
|
+
|
|
395
|
+
# Get list of tables to search
|
|
396
|
+
if table_name:
|
|
397
|
+
tables_to_search = [table_name]
|
|
398
|
+
else:
|
|
399
|
+
# Only check for _table_name if table_name wasn't provided
|
|
400
|
+
if not hasattr(cls, '_table_name'):
|
|
401
|
+
raise NotImplementedError(
|
|
402
|
+
f"{cls.__name__} must define a '_table_name' class variable "
|
|
403
|
+
"or provide 'table_name' argument"
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
if isinstance(cls._table_name, (list, tuple)):
|
|
407
|
+
tables_to_search = cls._table_name
|
|
408
|
+
else:
|
|
409
|
+
tables_to_search = [cls._table_name]
|
|
410
|
+
|
|
411
|
+
# Try each table until found
|
|
412
|
+
for table in tables_to_search:
|
|
413
|
+
available_materials = database.get_unique_values(table, "name")
|
|
414
|
+
|
|
415
|
+
if name in available_materials:
|
|
416
|
+
data = database.get_data(table, condition=f"name = '{name}'")
|
|
417
|
+
serialized_bytes = data["object"].iloc[0]
|
|
418
|
+
return cls.deserialize(serialized_bytes)
|
|
419
|
+
|
|
420
|
+
# Not found in any table
|
|
421
|
+
all_available = []
|
|
422
|
+
for table in tables_to_search:
|
|
423
|
+
all_available.extend(database.get_unique_values(table, "name"))
|
|
424
|
+
|
|
425
|
+
raise ValueError(
|
|
426
|
+
f"'{name}' not found in tables {tables_to_search}. "
|
|
427
|
+
f"Available: {all_available}"
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
359
432
|
def __del__(self):
|
|
360
433
|
self._connection.close()
|
|
434
|
+
|
|
435
|
+
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import msgpack
|
|
2
|
+
import msgpack_numpy as m
|
|
3
|
+
import zlib
|
|
4
|
+
from typing import TypeVar, Any
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from enum import Enum
|
|
7
|
+
|
|
8
|
+
T = TypeVar('T', bound='SerializerMixin')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SerializerMixin:
|
|
12
|
+
|
|
13
|
+
def serialize(self, compress: bool = True) -> bytes:
|
|
14
|
+
"""
|
|
15
|
+
Serialize object using MessagePack with numpy support.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
compress : bool, optional
|
|
20
|
+
Whether to compress the serialized data (default: True)
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
bytes
|
|
25
|
+
The serialized byte representation of the object.
|
|
26
|
+
"""
|
|
27
|
+
m.patch() # Enable numpy support
|
|
28
|
+
data = msgpack.packb(self._to_dict(), use_bin_type=True)
|
|
29
|
+
|
|
30
|
+
if compress:
|
|
31
|
+
# Add marker byte to indicate compression
|
|
32
|
+
return b'\x01' + zlib.compress(data, level=6)
|
|
33
|
+
else:
|
|
34
|
+
return b'\x00' + data
|
|
35
|
+
|
|
36
|
+
def _serialize_value(self, value: Any) -> Any:
|
|
37
|
+
"""
|
|
38
|
+
Recursively serialize a value, handling nested structures.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
value : Any
|
|
43
|
+
The value to serialize.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
Any
|
|
48
|
+
The serialized representation.
|
|
49
|
+
"""
|
|
50
|
+
if hasattr(value, '_to_dict'):
|
|
51
|
+
# Add marker and class info for object reconstruction
|
|
52
|
+
return {
|
|
53
|
+
'__object__': True,
|
|
54
|
+
'_class': f"{value.__class__.__module__}.{value.__class__.__name__}",
|
|
55
|
+
**value._to_dict()
|
|
56
|
+
}
|
|
57
|
+
elif isinstance(value, datetime):
|
|
58
|
+
return {'__datetime__': value.isoformat()}
|
|
59
|
+
elif isinstance(value, Enum):
|
|
60
|
+
return {
|
|
61
|
+
'__enum__': True,
|
|
62
|
+
'class': f"{value.__class__.__module__}.{value.__class__.__name__}",
|
|
63
|
+
'value': value.value
|
|
64
|
+
}
|
|
65
|
+
elif isinstance(value, tuple):
|
|
66
|
+
# Recursively serialize tuple items
|
|
67
|
+
return {
|
|
68
|
+
'__tuple__': True,
|
|
69
|
+
'items': [self._serialize_value(item) for item in value]
|
|
70
|
+
}
|
|
71
|
+
elif isinstance(value, list):
|
|
72
|
+
# Recursively serialize list items
|
|
73
|
+
return [self._serialize_value(item) for item in value]
|
|
74
|
+
elif isinstance(value, dict):
|
|
75
|
+
# Handle dictionaries with object keys or values
|
|
76
|
+
has_object_keys = value and any(hasattr(k, '_to_dict') for k in value.keys())
|
|
77
|
+
has_object_values = value and any(hasattr(v, '_to_dict') for v in value.values())
|
|
78
|
+
|
|
79
|
+
if has_object_keys or has_object_values:
|
|
80
|
+
return {
|
|
81
|
+
'__object_dict__': True,
|
|
82
|
+
'items': [
|
|
83
|
+
{
|
|
84
|
+
'key': self._serialize_value(k),
|
|
85
|
+
'value': self._serialize_value(v)
|
|
86
|
+
}
|
|
87
|
+
for k, v in value.items()
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
else:
|
|
91
|
+
# Recursively serialize regular dict values
|
|
92
|
+
return {k: self._serialize_value(v) for k, v in value.items()}
|
|
93
|
+
else:
|
|
94
|
+
return value
|
|
95
|
+
|
|
96
|
+
def _to_dict(self) -> dict:
|
|
97
|
+
"""
|
|
98
|
+
Convert object to dictionary for serialization.
|
|
99
|
+
Override this in subclasses to customize serialization behavior.
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
dict
|
|
104
|
+
Dictionary representation of the object.
|
|
105
|
+
"""
|
|
106
|
+
result = {}
|
|
107
|
+
for key, value in self.__dict__.items():
|
|
108
|
+
result[key] = self._serialize_value(value)
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def deserialize(cls: type[T], data: bytes) -> T:
|
|
113
|
+
"""
|
|
114
|
+
Deserialize byte data into an object.
|
|
115
|
+
Automatically detects and decompresses if needed.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
data : bytes
|
|
120
|
+
The byte data to deserialize.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
T
|
|
125
|
+
Instance of the class.
|
|
126
|
+
"""
|
|
127
|
+
m.patch() # Enable numpy support
|
|
128
|
+
|
|
129
|
+
# Check compression marker
|
|
130
|
+
if data[0:1] == b'\x01':
|
|
131
|
+
data = zlib.decompress(data[1:])
|
|
132
|
+
else:
|
|
133
|
+
data = data[1:]
|
|
134
|
+
|
|
135
|
+
obj_dict = msgpack.unpackb(data, raw=False)
|
|
136
|
+
return cls._from_dict(obj_dict)
|
|
137
|
+
|
|
138
|
+
@classmethod
|
|
139
|
+
def _deserialize_value(cls, value: Any) -> Any:
|
|
140
|
+
"""
|
|
141
|
+
Recursively deserialize a value, handling nested structures.
|
|
142
|
+
|
|
143
|
+
Parameters
|
|
144
|
+
----------
|
|
145
|
+
value : Any
|
|
146
|
+
The value to deserialize.
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
Any
|
|
151
|
+
The deserialized object.
|
|
152
|
+
"""
|
|
153
|
+
if isinstance(value, dict):
|
|
154
|
+
if '__datetime__' in value:
|
|
155
|
+
return datetime.fromisoformat(value['__datetime__'])
|
|
156
|
+
elif '__enum__' in value:
|
|
157
|
+
# Reconstruct enum
|
|
158
|
+
module_name, class_name = value['class'].rsplit('.', 1)
|
|
159
|
+
import importlib
|
|
160
|
+
module = importlib.import_module(module_name)
|
|
161
|
+
enum_class = getattr(module, class_name)
|
|
162
|
+
return enum_class(value['value'])
|
|
163
|
+
elif '__tuple__' in value:
|
|
164
|
+
# Recursively reconstruct tuple items
|
|
165
|
+
return tuple(cls._deserialize_value(item) for item in value['items'])
|
|
166
|
+
elif '__object__' in value:
|
|
167
|
+
# Reconstruct regular object
|
|
168
|
+
import importlib
|
|
169
|
+
module_name, class_name = value['_class'].rsplit('.', 1)
|
|
170
|
+
module = importlib.import_module(module_name)
|
|
171
|
+
obj_class = getattr(module, class_name)
|
|
172
|
+
# Remove marker fields before passing to _from_dict
|
|
173
|
+
obj_data = {k: v for k, v in value.items() if k not in ('__object__', '_class')}
|
|
174
|
+
return obj_class._from_dict(obj_data)
|
|
175
|
+
elif '__object_dict__' in value:
|
|
176
|
+
# Reconstruct dictionary with object keys or values
|
|
177
|
+
reconstructed_dict = {}
|
|
178
|
+
for item in value['items']:
|
|
179
|
+
key_obj = cls._deserialize_value(item['key'])
|
|
180
|
+
value_obj = cls._deserialize_value(item['value'])
|
|
181
|
+
reconstructed_dict[key_obj] = value_obj
|
|
182
|
+
return reconstructed_dict
|
|
183
|
+
else:
|
|
184
|
+
# Recursively deserialize regular dict values
|
|
185
|
+
return {k: cls._deserialize_value(v) for k, v in value.items()}
|
|
186
|
+
elif isinstance(value, list):
|
|
187
|
+
# Recursively deserialize list items
|
|
188
|
+
return [cls._deserialize_value(item) for item in value]
|
|
189
|
+
else:
|
|
190
|
+
return value
|
|
191
|
+
|
|
192
|
+
@classmethod
|
|
193
|
+
def _from_dict(cls: type[T], data: dict) -> T:
|
|
194
|
+
"""
|
|
195
|
+
Reconstruct object from dictionary.
|
|
196
|
+
Override in subclasses for custom deserialization.
|
|
197
|
+
|
|
198
|
+
Parameters
|
|
199
|
+
----------
|
|
200
|
+
data : dict
|
|
201
|
+
Dictionary representation to reconstruct from.
|
|
202
|
+
|
|
203
|
+
Returns
|
|
204
|
+
-------
|
|
205
|
+
T
|
|
206
|
+
Reconstructed object instance.
|
|
207
|
+
"""
|
|
208
|
+
obj = cls.__new__(cls)
|
|
209
|
+
reconstructed = {}
|
|
210
|
+
for key, value in data.items():
|
|
211
|
+
reconstructed[key] = cls._deserialize_value(value)
|
|
212
|
+
obj.__dict__.update(reconstructed)
|
|
213
|
+
return obj
|
|
214
|
+
|
|
215
|
+
@classmethod
|
|
216
|
+
def from_database(cls: type[T], name: str, table_name: str = None) -> T:
|
|
217
|
+
"""
|
|
218
|
+
Pull object from the database by name.
|
|
219
|
+
|
|
220
|
+
Subclasses must define a '_table_name' class variable (str or list of str)
|
|
221
|
+
unless table_name is explicitly provided.
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
name : str
|
|
226
|
+
Name of the object to retrieve.
|
|
227
|
+
table_name : str, optional
|
|
228
|
+
Specific table to search. If provided, '_table_name' is not required.
|
|
229
|
+
If None, uses class's _table_name.
|
|
230
|
+
|
|
231
|
+
Returns
|
|
232
|
+
-------
|
|
233
|
+
T
|
|
234
|
+
Instance of the class.
|
|
235
|
+
|
|
236
|
+
Raises
|
|
237
|
+
------
|
|
238
|
+
NotImplementedError
|
|
239
|
+
If the subclass doesn't define '_table_name' and table_name is not provided.
|
|
240
|
+
ValueError
|
|
241
|
+
If the object name is not found in any of the tables.
|
|
242
|
+
"""
|
|
243
|
+
from steer_core.Data.DataManager import DataManager
|
|
244
|
+
|
|
245
|
+
database = DataManager()
|
|
246
|
+
|
|
247
|
+
# Get list of tables to search
|
|
248
|
+
if table_name:
|
|
249
|
+
tables_to_search = [table_name]
|
|
250
|
+
else:
|
|
251
|
+
# Only check for _table_name if table_name wasn't provided
|
|
252
|
+
if not hasattr(cls, '_table_name'):
|
|
253
|
+
raise NotImplementedError(
|
|
254
|
+
f"{cls.__name__} must define a '_table_name' class variable "
|
|
255
|
+
"or provide 'table_name' argument"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if isinstance(cls._table_name, (list, tuple)):
|
|
259
|
+
tables_to_search = cls._table_name
|
|
260
|
+
else:
|
|
261
|
+
tables_to_search = [cls._table_name]
|
|
262
|
+
|
|
263
|
+
# Try each table until found
|
|
264
|
+
for table in tables_to_search:
|
|
265
|
+
available_materials = database.get_unique_values(table, "name")
|
|
266
|
+
|
|
267
|
+
if name in available_materials:
|
|
268
|
+
data = database.get_data(table, condition=f"name = '{name}'")
|
|
269
|
+
serialized_bytes = data["object"].iloc[0]
|
|
270
|
+
return cls.deserialize(serialized_bytes)
|
|
271
|
+
|
|
272
|
+
# Not found in any table
|
|
273
|
+
all_available = []
|
|
274
|
+
for table in tables_to_search:
|
|
275
|
+
all_available.extend(database.get_unique_values(table, "name"))
|
|
276
|
+
|
|
277
|
+
raise ValueError(
|
|
278
|
+
f"'{name}' not found in tables {tables_to_search}. "
|
|
279
|
+
f"Available: {all_available}"
|
|
280
|
+
)
|
|
281
|
+
|
|
@@ -208,8 +208,9 @@ class ValidationMixin:
|
|
|
208
208
|
ValueError
|
|
209
209
|
If the value is not a positive float.
|
|
210
210
|
"""
|
|
211
|
+
value = float(value) # Ensure value is float
|
|
211
212
|
if not isinstance(value, (int, float)):
|
|
212
|
-
raise ValueError(f"{name} must be a positive float. Provided: {value}.")
|
|
213
|
+
raise ValueError(f"{name} must be a positive float. Provided: {value} of type {type(value).__name__}.")
|
|
213
214
|
|
|
214
215
|
@staticmethod
|
|
215
216
|
def validate_positive_int(value: int, name: str) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: steer-core
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.32
|
|
4
4
|
Summary: Modelling energy storage from cell to site - STEER OpenCell Design
|
|
5
5
|
Author-email: Nicholas Siemons <nsiemons@stanford.edu>
|
|
6
6
|
Maintainer-email: Nicholas Siemons <nsiemons@stanford.edu>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
README.md
|
|
2
2
|
pyproject.toml
|
|
3
|
-
steer_core/DataManager.py
|
|
4
3
|
steer_core/__init__.py
|
|
5
4
|
steer_core.egg-info/PKG-INFO
|
|
6
5
|
steer_core.egg-info/SOURCES.txt
|
|
@@ -12,8 +11,8 @@ steer_core/Constants/Universal.py
|
|
|
12
11
|
steer_core/Constants/__init__.py
|
|
13
12
|
steer_core/ContextManagers/ContextManagers.py
|
|
14
13
|
steer_core/ContextManagers/__init__.py
|
|
14
|
+
steer_core/Data/DataManager.py
|
|
15
15
|
steer_core/Data/__init__.py
|
|
16
|
-
steer_core/Data/database.db
|
|
17
16
|
steer_core/Decorators/Coordinates.py
|
|
18
17
|
steer_core/Decorators/General.py
|
|
19
18
|
steer_core/Decorators/Objects.py
|
|
Binary file
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
from pickle import loads, dumps
|
|
3
|
-
from typing import Type
|
|
4
|
-
from copy import deepcopy
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class SerializerMixin:
|
|
8
|
-
|
|
9
|
-
def serialize(self) -> str:
|
|
10
|
-
"""
|
|
11
|
-
Serialize an object to a string representation.
|
|
12
|
-
|
|
13
|
-
Parameters
|
|
14
|
-
----------
|
|
15
|
-
obj : Type
|
|
16
|
-
The object to serialize.
|
|
17
|
-
|
|
18
|
-
Returns
|
|
19
|
-
-------
|
|
20
|
-
str
|
|
21
|
-
The serialized string representation of the object.
|
|
22
|
-
"""
|
|
23
|
-
pickled = dumps(self)
|
|
24
|
-
based = base64.b64encode(pickled).decode("utf-8")
|
|
25
|
-
return based
|
|
26
|
-
|
|
27
|
-
@staticmethod
|
|
28
|
-
def deserialize(String: str) -> Type:
|
|
29
|
-
"""
|
|
30
|
-
Deserialize a string representation into an object.
|
|
31
|
-
|
|
32
|
-
Parameters
|
|
33
|
-
----------
|
|
34
|
-
String : str
|
|
35
|
-
The string representation to deserialize.
|
|
36
|
-
|
|
37
|
-
Returns
|
|
38
|
-
-------
|
|
39
|
-
SerializerMixin
|
|
40
|
-
The deserialized object.
|
|
41
|
-
"""
|
|
42
|
-
decoded = base64.b64decode(String.encode("utf-8"))
|
|
43
|
-
obj = deepcopy(loads(decoded))
|
|
44
|
-
return obj
|
|
45
|
-
|
|
46
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|