habana-pyhlml 1.10.0.494__py3-none-any.whl

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.

Potentially problematic release.


This version of habana-pyhlml might be problematic. Click here for more details.

@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 HabanaAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.1
2
+ Name: habana-pyhlml
3
+ Version: 1.10.0.494
4
+ Summary: Python3 wrapper for the HLML library.
5
+ Home-page: UNKNOWN
6
+ Author: HabanaAI
7
+ Author-email: "support@habana.ai"
8
+ License: MIT
9
+ Platform: UNKNOWN
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Requires-Python: >=3.6
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+
16
+ # pyhlml
17
+ Python3 wrapper for the HLML library
18
+
19
+ ## Getting Started
20
+
21
+ The pyhlml library is an python API wrapper for the Synapse HLML library, documented here: https://docs.habana.ai/en/latest/API_Reference_Guides/HLML_API_Reference.html
22
+
23
+ ### Requirements
24
+
25
+ - Python3
26
+ - Habana-enabled device ( inc. Drivers/Firmware )
27
+ - Synapse version 1.0.1-81 or later
28
+
29
+ ### Install - PIP
30
+
31
+ ```bash
32
+ $ pip3 install -e git+https://github.com/HabanaAI/pyhlml.git#egg=pyhlml
33
+ ```
34
+
35
+ ### Basic Usage
36
+
37
+ ```python3
38
+ import pyhlml
39
+
40
+ # Initialize the library
41
+ pyhlml.hlmlInit()
42
+
43
+ # Get total number of devices in the system
44
+ device_count = pyhlml.hlmlDeviceGetCount()
45
+
46
+ # For each device print utilization
47
+ for i in range(device_count):
48
+ device = pyhlml.hlmlDeviceGetHandleByIndex(i)
49
+ print(f"Device {i} Utilization: {pyhlml.hlmlDeviceGetUtilizationRates(device)}
50
+
51
+ # Shutdown
52
+ pyhlml.hlmlShutdown()
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Versions
58
+
59
+ This wrapper shadows the synapse release versions and uses the scheme
60
+
61
+ $release-$build
62
+
63
+ where release is the synapse release and build is the build of this repo ( 0 indexed ).
64
+
65
+
66
+
@@ -0,0 +1,10 @@
1
+ pyhlml/__init__.py,sha256=VjbHqSSypSMmVK7UTxuCyOs_AE8HhTXX9EGr6NbaQNk,25
2
+ pyhlml/hlml_error.py,sha256=GQulGXf-jX38jEASXF22qJ0yL8eC57vUo8s9lVI7q_E,2113
3
+ pyhlml/hlml_lib.py,sha256=JiHRLl3vpAozhCSs9eJC8xlhIMxR2wNVZdmahjlgDfc,1430
4
+ pyhlml/hlml_types.py,sha256=RESPajQUNWCb0y8KmtyCtwRyKbTYflboOzjMJHY75mo,10630
5
+ pyhlml/main.py,sha256=rCy1nkae5lPmC2nz5PGbp8lVE_1CcZboVqLw1CDrmug,36087
6
+ habana_pyhlml-1.10.0.494.dist-info/LICENSE,sha256=_J8fTEtZF8y69onNU5_EAdOn0AC9RM2uHPh_q36-5bc,1065
7
+ habana_pyhlml-1.10.0.494.dist-info/METADATA,sha256=JyxSH6kA33wOc9rSmhaLfRtrpOcEVJP9Gu_G1FCrePA,1457
8
+ habana_pyhlml-1.10.0.494.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
9
+ habana_pyhlml-1.10.0.494.dist-info/top_level.txt,sha256=0jXJHTTotoeuyzpI1dcVr0mzCVB0NKY7LyCF4OwoMZU,7
10
+ habana_pyhlml-1.10.0.494.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.38.4)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ pyhlml
pyhlml/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from pyhlml.main import *
pyhlml/hlml_error.py ADDED
@@ -0,0 +1,50 @@
1
+ from string import capwords
2
+ from sys import modules
3
+
4
+ import pyhlml.hlml_types as hlml_t
5
+
6
+ def ErrorsAsClass():
7
+ this_module = modules[__name__]
8
+ names = [x for x in dir(hlml_t.HLML_RETURN) if x.startswith("HLML_ERROR")]
9
+ for err in names:
10
+ class_name = "HLMLError_" + capwords(err.replace("HLML_ERROR_", ""), "_").replace("_", "")
11
+ err_v = getattr(hlml_t.HLML_RETURN, err)
12
+ def gen_new(val):
13
+ def new(typ):
14
+ obj = HLMLError.__new__(typ, val)
15
+ return obj
16
+ return new
17
+ new_class = type(class_name, (HLMLError,), {'__new__': gen_new(err_v)})
18
+ new_class.__module__ = __name__
19
+ setattr(this_module, class_name, new_class)
20
+ HLMLError._cMap[err_v] = new_class
21
+
22
+ class HLMLError(Exception):
23
+ _cMap = {}
24
+ _errcodes = {
25
+ hlml_t.HLML_RETURN.HLML_ERROR_UNINITIALIZED : "Lib not initialized",
26
+ hlml_t.HLML_RETURN.HLML_ERROR_INVALID_ARGUMENT : "Invalid argument",
27
+ hlml_t.HLML_RETURN.HLML_ERROR_NOT_SUPPORTED : "Not supported",
28
+ hlml_t.HLML_RETURN.HLML_ERROR_ALREADY_INITIALIZED : "Libhlml already initialized",
29
+ hlml_t.HLML_RETURN.HLML_ERROR_NOT_FOUND : "Not found",
30
+ hlml_t.HLML_RETURN.HLML_ERROR_INSUFFICIENT_SIZE : "Insufficient size",
31
+ hlml_t.HLML_RETURN.HLML_ERROR_DRIVER_NOT_LOADED : "Driver not loaded",
32
+ hlml_t.HLML_RETURN.HLML_ERROR_TIMEOUT : "Timeout",
33
+ hlml_t.HLML_RETURN.HLML_ERROR_AIP_IS_LOST : "AIP Lost",
34
+ hlml_t.HLML_RETURN.HLML_ERROR_MEMORY : "Memory error",
35
+ hlml_t.HLML_RETURN.HLML_ERROR_NO_DATA : "No Data",
36
+ hlml_t.HLML_RETURN.HLML_ERROR_UNKNOWN : "Unknown"
37
+ }
38
+
39
+ def __new__(typ, value):
40
+ if typ == HLMLError:
41
+ typ = HLMLError._cMap.get(value, typ)
42
+ obj = Exception.__new__(typ)
43
+ obj.value = value
44
+ return obj
45
+
46
+ def __str__(self):
47
+ return f"HLML Error with code {self.value}"
48
+
49
+ def __eq__(self, other):
50
+ return self.value == other.value
pyhlml/hlml_lib.py ADDED
@@ -0,0 +1,49 @@
1
+ import ctypes
2
+
3
+ from threading import Lock
4
+
5
+ from pyhlml.hlml_error import HLMLError
6
+ from pyhlml.hlml_types import HLML_RETURN
7
+
8
+ class LibHLML:
9
+ def __init__(self, path="/usr/lib/habanalabs/libhlml.so"):
10
+ self.default_path = path
11
+ self.lib = None
12
+ self.lib_load_lock = Lock()
13
+ self.func_ptr_cache = dict()
14
+ self.ref_count = 0 # INC on init DEC on dest
15
+
16
+ self._load_lib()
17
+
18
+ def _load_lib(self):
19
+ with self.lib_load_lock:
20
+ try:
21
+ self.lib = ctypes.CDLL(self.default_path)
22
+ except Exception as e:
23
+ print("Failed to load libhlml")
24
+ raise HLMLError(HLML_RETURN.HLML_ERROR_UNINITIALIZED)
25
+
26
+ def inc_ref(self):
27
+ with self.lib_load_lock:
28
+ self.ref_count += 1
29
+
30
+ def dec_ref(self):
31
+ if self.ref_count > 0:
32
+ with self.lib_load_lock:
33
+ self.ref_count -= 1
34
+
35
+ def get_func_ptr(self, name):
36
+ if self.lib == None:
37
+ raise HLMLError(HLML_RETURN.HLML_ERROR_UNINITIALIZED)
38
+
39
+ if name in self.func_ptr_cache:
40
+ return self.func_ptr_cache[name]
41
+
42
+ with self.lib_load_lock:
43
+ try:
44
+ self.func_ptr_cache[name] = getattr(self.lib, name)
45
+ return self.func_ptr_cache[name]
46
+ except Exception as e:
47
+ raise HLMLError(HLML_RETURN.HLML_ERROR_INVALID_ARGUMENT)
48
+
49
+
pyhlml/hlml_types.py ADDED
@@ -0,0 +1,291 @@
1
+ """
2
+ Python bindings for HLML types
3
+ """
4
+
5
+ import ctypes
6
+
7
+ class HLML_DEVICE:
8
+ TYPE = ctypes.c_void_p()
9
+
10
+ class HLML_DEFINE:
11
+ PCI_DOMAIN_LEN = 5
12
+ PCI_ADDR_LEN = ( PCI_DOMAIN_LEN + 10 )
13
+ PCI_LINK_INFO_LEN = 10
14
+ HL_FIELD_MAX_SIZE = 32
15
+ PORTS_ARR_SIZE = 2
16
+ HLML_DEVICE_ROW_RPL_MAX = 32
17
+ HLML_DEVICE_MAC_MAX_ADDRESSES = 48
18
+ HLML_EVENT_ECC_ERR = ( 1 << 0 )
19
+ HLML_EVENT_ECC_DERR = ( 1 << 0 )
20
+ HLML_EVENT_CRITICAL_ERR = ( 1 << 1 )
21
+ HLML_EVENT_CLOCK_RATE = ( 1 << 2 )
22
+ HLML_EVENT_DRAM_ERR = ( 1 << 3 )
23
+ HLML_EVENT_DRAM_DERR = ( 1 << 3 )
24
+ HLML_EVENT_ECC_SERR = ( 1 << 4 )
25
+ HLML_EVENT_DRAM_SERR = ( 1 << 5 )
26
+ HLML_CLOCKS_THROTTLE_REASON_POWER = ( 1 << 0 )
27
+ HLML_CLOCKS_THROTTLE_REASON_THERMAL = ( 1 << 1 )
28
+ HLML_AFFINITY_SCOPE_NODE = 0
29
+ HLML_AFFINITY_SCOPE_SOCKET = 1
30
+
31
+ class COMMON_DEFINE:
32
+ VERSION_MAX_LEN = 128
33
+ ETHER_ADDR_LEN = 6
34
+ HABANA_LINK_CNT_MAX_NUM = 256
35
+
36
+ class HLML_AFFINITY_SCOPE:
37
+ TYPE = ctypes.c_uint()
38
+ HLML_AFFINITY_SCOPE_NODE = 0
39
+ HLML_AFFINITY_SCOPE_SOCKET = 1
40
+
41
+ class HLML_RETURN:
42
+ TYPE = ctypes.c_uint()
43
+ HLML_SUCCESS = 0
44
+ HLML_ERROR_UNINITIALIZED = 1
45
+ HLML_ERROR_INVALID_ARGUMENT = 2
46
+ HLML_ERROR_NOT_SUPPORTED = 3
47
+ HLML_ERROR_ALREADY_INITIALIZED = 5
48
+ HLML_ERROR_NOT_FOUND = 6
49
+ HLML_ERROR_INSUFFICIENT_SIZE = 7
50
+ HLML_ERROR_DRIVER_NOT_LOADED = 9
51
+ HLML_ERROR_TIMEOUT = 10
52
+ HLML_ERROR_AIP_IS_LOST = 15
53
+ HLML_ERROR_MEMORY = 20
54
+ HLML_ERROR_NO_DATA = 21
55
+ HLML_ERROR_UNKNOWN = 49
56
+
57
+ class HLML_CLOCK_TYPE:
58
+ TYPE = ctypes.c_uint()
59
+ HLML_CLOCK_SOC = 0
60
+ HLML_CLOCK_IC = 1
61
+ HLML_CLOCK_MME = 2
62
+ HLML_CLOCK_TPC = 3
63
+ HLML_CLOCK_COUNT = 4
64
+
65
+ class HLML_TEMP_SENS:
66
+ TYPE = ctypes.c_uint()
67
+ HLML_TEMPERATURE_ON_AIP = 0
68
+ HLML_TEMPERATURE_ON_BOARD = 1
69
+ HLML_TEMPERATURE_OTHER = 2
70
+
71
+ class HLML_TEMP_THRESH:
72
+ TYPE = ctypes.c_uint()
73
+ HLML_TEMPERATURE_THRESHOLD_SHUTDOWN = 0
74
+ HLML_TEMPERATURE_THRESHOLD_SLOWDOWN = 1
75
+ HLML_TEMPERATURE_THRESHOLD_MEM_MAX = 2
76
+ HLML_TEMPERATURE_THRESHOLD_GPU_MAX = 3
77
+ HLML_TEMPERATURE_THRESHOLD_COUNT = 4
78
+
79
+ class HLML_ENABLE_STATE:
80
+ TYPE = ctypes.c_uint()
81
+ HLML_FEATURE_DISABLED = 0
82
+ HLML_FEATURE_ENABLED = 1
83
+
84
+ class HLML_P_STATES:
85
+ TYPE = ctypes.c_uint()
86
+ HLML_PSTATE_0 = 0
87
+ HLML_PSTATE_UNKNOWN = 32
88
+
89
+ class HLML_MEMORY_ERROR:
90
+ TYPE = ctypes.c_uint()
91
+ HLML_MEMORY_ERROR_TYPE_CORRECTED = 0 # NOT SUPPORTED BY HLML
92
+ HLML_MEMORY_ERROR_TYPE_UNCORRECTED = 1
93
+ HLML_MEMORY_ERROR_TYPE_COUNT = 2
94
+
95
+ class HLML_MEMORY_LOCATION:
96
+ TYPE = ctypes.c_uint()
97
+ HLML_MEMORY_LOCATION_SRAM = 0
98
+ HLML_MEMORY_LOCATION_DRAM = 1
99
+ HLML_MEMORY_LOCATION_COUNT = 2
100
+
101
+ class HLML_ECC_COUNTER:
102
+ TYPE = ctypes.c_uint()
103
+ HLML_VOLATILE_ECC = 0
104
+ HLML_AGGREGATE_ECC = 1
105
+ HLML_ECC_COUNTER_TYPE_COUNT = 2
106
+
107
+ class HLML_ERR_INJECT:
108
+ TYPE = ctypes.c_uint()
109
+ HLML_ERR_INJECT_ENDLESS_COMMAND = 0
110
+ HLML_ERR_INJECT_NON_FATAL_EVENT = 1
111
+ HLML_ERR_INJECT_FATAL_EVENT = 2
112
+ HLML_ERR_INJECT_LOSS_OF_HEARTBEAT = 3
113
+ HLML_ERR_INJECT_THERMAL_EVENT = 4
114
+ HLML_ERR_INJECT_COUNT = 5
115
+
116
+ class HLML_PCIE_UTIL_COUNTER:
117
+ TYPE = ctypes.c_uint()
118
+ HLML_PCIE_UTIL_TX_BYTES = 0
119
+ HLML_PCIE_UTIL_RX_BYTES = 1
120
+ HLML_PCIE_UTIL_COUNT = 2
121
+
122
+ class HLML_EVENT_SET:
123
+ TYPE = ctypes.c_void_p()
124
+
125
+ class HLML_ROW_REPLACEMENT_CAUSE:
126
+ TYPE = ctypes.c_uint()
127
+ HLML_ROW_REPLACEMENT_CAUSE_MULTIPLE_SINGLE_BIT_ECC_ERRORS = 0,
128
+ HLML_ROW_REPLACEMENT_CAUSE_DOUBLE_BIT_ECC_ERROR = 1,
129
+ HLML_ROW_REPLACEMENT_CAUSE_COUNT = 2
130
+
131
+ class HLML_PERF_POLICY:
132
+ TYPE = ctypes.c_uint()
133
+ HLML_PERF_POLICY_POWER = 0,
134
+ HLML_PERF_POLICY_THERMAL = 1,
135
+ HLML_PERF_POLICY_COUNT = 0
136
+
137
+ class _struct_c_hlml_unit(ctypes.Structure):
138
+ pass # opaque handle
139
+
140
+ class HLML_UNIT:
141
+ TYPE = _struct_c_hlml_unit()
142
+
143
+ class _PrintS(ctypes.Structure):
144
+ """
145
+ Produces nicer __str__ output than ctypes.Structure.
146
+
147
+ e.g. instead of:
148
+
149
+ > print str(obj)
150
+ <class_name object at 0x7fdf82fef9e0>
151
+
152
+ this class will print...
153
+
154
+ > print str(obj)
155
+ class_name(field_name: formatted_value, field_name: formatted_value)
156
+ _fmt_ dictionary of <str _field_ name> -> <str format>
157
+
158
+ Default formatting string for all fields can be set with key "<default>" like:
159
+ _fmt_ = {"<default>" : "%d MHz"} # e.g all values are numbers in MHz.
160
+
161
+ If not set it's assumed to be just "%s"
162
+
163
+ e.g. class that has _field_ 'hex_value', c_uint could be formatted with
164
+ _fmt_ = {"hex_value" : "%08X"}
165
+ to produce nicer output.
166
+ """
167
+ _fmt_ = {}
168
+ def __str__(self):
169
+ result = []
170
+ for x in self._fields_:
171
+ key = x[0]
172
+ value = getattr(self, key)
173
+ fmt = "%s"
174
+ if key in self._fmt_:
175
+ fmt = self._fmt_[key]
176
+ elif "<default>" in self._fmt_:
177
+ fmt = self._fmt_["<default>"]
178
+ result.append(("%s: " + fmt) % (key, value))
179
+ return self.__class__.__name__ + "(" + ", ".join(result) + ")"
180
+
181
+ class c_hlml_pci_cap(_PrintS):
182
+ _fields_ = [("link_speed", ctypes.c_char * HLML_DEFINE.PCI_LINK_INFO_LEN),
183
+ ("link_width",ctypes.c_char * HLML_DEFINE.PCI_LINK_INFO_LEN)
184
+ ]
185
+
186
+ class c_hlml_pci_info(_PrintS):
187
+ """
188
+ /*
189
+ * bus - The bus on which the device resides, 0 to 0xf
190
+ * bus_id - The tuple domain:bus:device.function
191
+ * device - The device's id on the bus, 0 to 31
192
+ * domain - The PCI domain on which the device's bus resides
193
+ * pci_device_id - The combined 16b deviceId and 16b vendor id
194
+ */
195
+ """
196
+ _fields_ = [("bus", ctypes.c_uint),
197
+ ("bus_id", ctypes.c_char * HLML_DEFINE.PCI_ADDR_LEN),
198
+ ("device", ctypes.c_uint),
199
+ ("domain", ctypes.c_uint),
200
+ ("pci_device_id", ctypes.c_uint),
201
+ ("caps", c_hlml_pci_cap)
202
+ ]
203
+
204
+ class c_hlml_utilization(_PrintS):
205
+ _fields_ = [("aip", ctypes.c_uint)]
206
+
207
+ class c_hlml_memory(_PrintS):
208
+ _fields_ = [("free", ctypes.c_ulonglong),
209
+ ("total", ctypes.c_ulonglong),
210
+ ("used", ctypes.c_ulonglong)
211
+ ]
212
+
213
+ class c_hlml_pcb_info(_PrintS):
214
+ _fields_ = [("pcb_ver", ctypes.c_char * HLML_DEFINE.HL_FIELD_MAX_SIZE),
215
+ ("pcb_assembly_ver", ctypes.c_char * HLML_DEFINE.HL_FIELD_MAX_SIZE)
216
+ ]
217
+
218
+ class c_hlml_event_data(_PrintS):
219
+ _fields_ = [("device", ctypes.c_void_p),
220
+ ("event_type", ctypes.c_ulonglong)
221
+ ]
222
+
223
+ class c_hlml_mac_info(_PrintS):
224
+ _fields_ = [("addr", ctypes.c_ubyte * COMMON_DEFINE.ETHER_ADDR_LEN), # unsigned char
225
+ ("id", ctypes.c_int)
226
+ ]
227
+
228
+ class c_hlml_nic_stats_info(_PrintS):
229
+ _fields_ = [("port", ctypes.c_uint32),
230
+ ("str_buf", ctypes.POINTER(ctypes.c_char)),
231
+ ("val_buf", ctypes.POINTER(ctypes.c_uint64)),
232
+ ("num_of_counters_out", ctypes.POINTER(ctypes.c_uint32))
233
+ ]
234
+
235
+ def __init__(self, port: int, num_of_counters: int = None):
236
+ num_of_counters = num_of_counters or COMMON_DEFINE.HABANA_LINK_CNT_MAX_NUM
237
+ self.port = port
238
+
239
+ str_buf_size = num_of_counters * 32
240
+ self.str_buf = ctypes.cast(ctypes.create_string_buffer(str_buf_size), ctypes.POINTER(ctypes.c_char))
241
+
242
+ val_buf_size = num_of_counters * ctypes.sizeof(ctypes.c_uint64)
243
+ self.val_buf = (ctypes.c_uint64 * val_buf_size)()
244
+
245
+ self.num_of_counters_out = (ctypes.c_uint32 * 1)()
246
+
247
+ class c_hlml_violation_time(_PrintS):
248
+ _fields_ = [("reference_time", ctypes.c_ulonglong),
249
+ ("violation_time", ctypes.c_ulonglong)
250
+ ]
251
+
252
+ class c_hlml_row_address(_PrintS):
253
+ _fields_ = [("hbm_idx", ctypes.c_uint8),
254
+ ("pc", ctypes.c_uint8),
255
+ ("sid", ctypes.c_uint8),
256
+ ("bank_idx", ctypes.c_uint8),
257
+ ("row_addr", ctypes.c_uint16)
258
+ ]
259
+
260
+ class hlml_ecc_mode(_PrintS):
261
+ _fields_ = [("current", ctypes.c_uint),
262
+ ("pending", ctypes.c_uint)
263
+ ]
264
+
265
+ ## Alternative object
266
+ # Allows the object to be printed
267
+ # Allows mismatched types to be assigned
268
+ # - like None when the Structure variant requires c_uint
269
+
270
+ class hlml_friendly_obj(object):
271
+ def __init__(self, dic):
272
+ for x in dic:
273
+ setattr(self, x, dic[x])
274
+ def __str__(self):
275
+ return self.__dict__.__str__()
276
+
277
+ def hlml_struct_to_friendly(struct):
278
+ dic = {}
279
+ for x in struct._fields_:
280
+ key = x[0]
281
+ value = getattr(struct, key)
282
+ dic[key] = value
283
+ obj = hlml_friendly_obj(dic)
284
+ return obj
285
+
286
+ def hlml_friendly_to_struct(obj, model):
287
+ for x in model._fields_:
288
+ key = x[0]
289
+ value = obj.__dict__[key]
290
+ setattr(model, key, value)
291
+ return model