psr-factory 4.1.0b5__py3-none-manylinux_2_28_x86_64.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.
- psr/apps/__init__.py +7 -0
- psr/apps/apps.py +232 -0
- psr/apps/version.py +5 -0
- psr/cloud/__init__.py +7 -0
- psr/cloud/cloud.py +1079 -0
- psr/cloud/data.py +105 -0
- psr/cloud/desktop.py +82 -0
- psr/cloud/log.py +40 -0
- psr/cloud/status.py +81 -0
- psr/cloud/tempfile.py +117 -0
- psr/cloud/version.py +5 -0
- psr/cloud/xml.py +55 -0
- psr/factory/__init__.py +7 -0
- psr/factory/api.py +2339 -0
- psr/factory/factory.pmd +6830 -0
- psr/factory/factory.pmk +18299 -0
- psr/factory/factorylib.py +366 -0
- psr/factory/libfactory.so +0 -0
- psr/factory/py.typed +0 -0
- psr/psrfcommon/__init__.py +6 -0
- psr/psrfcommon/psrfcommon.py +54 -0
- psr/psrfcommon/tempfile.py +118 -0
- psr/runner/__init__.py +7 -0
- psr/runner/runner.py +649 -0
- psr/runner/version.py +5 -0
- psr_factory-4.1.0b5.dist-info/METADATA +86 -0
- psr_factory-4.1.0b5.dist-info/RECORD +30 -0
- psr_factory-4.1.0b5.dist-info/WHEEL +5 -0
- psr_factory-4.1.0b5.dist-info/licenses/LICENSE.txt +21 -0
- psr_factory-4.1.0b5.dist-info/top_level.txt +1 -0
psr/factory/api.py
ADDED
@@ -0,0 +1,2339 @@
|
|
1
|
+
# PSR Factory. Copyright (C) PSR, Inc - All Rights Reserved
|
2
|
+
# Unauthorized copying of this file, via any medium is strictly prohibited
|
3
|
+
# Proprietary and confidential
|
4
|
+
|
5
|
+
import locale
|
6
|
+
from typing import Dict, List, Optional, Tuple, Union
|
7
|
+
from types import ModuleType
|
8
|
+
import ctypes
|
9
|
+
import datetime as dt
|
10
|
+
import enum
|
11
|
+
import numbers
|
12
|
+
import os
|
13
|
+
import sys
|
14
|
+
import threading
|
15
|
+
import pathlib
|
16
|
+
import warnings
|
17
|
+
|
18
|
+
from . import factorylib
|
19
|
+
|
20
|
+
|
21
|
+
# Check whether pandas' dataframe is available.
|
22
|
+
_HAS_PANDAS: Optional[bool] = None
|
23
|
+
|
24
|
+
# Check whether polars' dataframe is available.
|
25
|
+
_HAS_POLARS: Optional[bool] = None
|
26
|
+
|
27
|
+
|
28
|
+
pandas: Optional[ModuleType] = None
|
29
|
+
polars: Optional[ModuleType] = None
|
30
|
+
numpy: Optional[ModuleType] = None
|
31
|
+
|
32
|
+
|
33
|
+
def _has_pandas() -> bool:
|
34
|
+
"""Check if pandas is available."""
|
35
|
+
global _HAS_PANDAS
|
36
|
+
global pandas
|
37
|
+
global numpy
|
38
|
+
if _HAS_PANDAS is None:
|
39
|
+
try:
|
40
|
+
import pandas
|
41
|
+
import pandas.api.interchange
|
42
|
+
import pandas.api.types
|
43
|
+
if numpy is not None:
|
44
|
+
import numpy
|
45
|
+
import numpy.ctypeslib
|
46
|
+
_HAS_PANDAS = True
|
47
|
+
except ImportError:
|
48
|
+
_HAS_PANDAS = False
|
49
|
+
return _HAS_PANDAS
|
50
|
+
|
51
|
+
|
52
|
+
def _has_polars() -> bool:
|
53
|
+
"""Check if polars is available."""
|
54
|
+
global _HAS_POLARS
|
55
|
+
global polars
|
56
|
+
global numpy
|
57
|
+
if _HAS_POLARS is None:
|
58
|
+
try:
|
59
|
+
import polars
|
60
|
+
import polars.datatypes.classes
|
61
|
+
if numpy is not None:
|
62
|
+
import numpy
|
63
|
+
import numpy.ctypeslib
|
64
|
+
_HAS_POLARS = True
|
65
|
+
except ImportError:
|
66
|
+
_HAS_POLARS = False
|
67
|
+
return _HAS_POLARS
|
68
|
+
|
69
|
+
|
70
|
+
# States whether the library is initialized.
|
71
|
+
# It should be to correctly load and build models.
|
72
|
+
_initialized = False
|
73
|
+
_initialized_lock = threading.Lock()
|
74
|
+
|
75
|
+
_loaded = False
|
76
|
+
_loaded_lock = threading.Lock()
|
77
|
+
|
78
|
+
# System encoding for interface with the library.
|
79
|
+
_preferred_encoding = locale.getpreferredencoding()
|
80
|
+
|
81
|
+
# Internal date epoch
|
82
|
+
# TODO: make it a library call.
|
83
|
+
_date_transform = 12622780800
|
84
|
+
|
85
|
+
|
86
|
+
def _check_initialized():
|
87
|
+
"""Checks if the module was initialized."""
|
88
|
+
global _initialized
|
89
|
+
if not _initialized:
|
90
|
+
_initialize()
|
91
|
+
return _initialized
|
92
|
+
|
93
|
+
|
94
|
+
def _check_loaded() -> bool:
|
95
|
+
"""Checks if the library was loaded."""
|
96
|
+
global _loaded
|
97
|
+
if not _loaded:
|
98
|
+
_load_library()
|
99
|
+
return _loaded
|
100
|
+
|
101
|
+
|
102
|
+
def _c_str(value: str) -> bytes:
|
103
|
+
"""Convert a Python object/string into a bytes/c-array."""
|
104
|
+
return bytes(value, encoding=_preferred_encoding)
|
105
|
+
|
106
|
+
|
107
|
+
def _from_c_str(value: bytes) -> str:
|
108
|
+
"""Convert ASCII bytes back into utf-8 strings."""
|
109
|
+
return value.decode(encoding=_preferred_encoding)
|
110
|
+
|
111
|
+
|
112
|
+
def _bytes(value: str) -> int:
|
113
|
+
"""Return the bytes' count of the equivalent C buffer to
|
114
|
+
hold this string."""
|
115
|
+
return len(value) + 1
|
116
|
+
|
117
|
+
|
118
|
+
class FactoryException(Exception):
|
119
|
+
pass
|
120
|
+
|
121
|
+
|
122
|
+
class LogLevel(enum.Enum):
|
123
|
+
NOTSET = 0
|
124
|
+
DEBUG = 10
|
125
|
+
INFO = 20
|
126
|
+
WARNING = 30
|
127
|
+
ERROR = 40
|
128
|
+
CRITICAL = 50
|
129
|
+
|
130
|
+
|
131
|
+
class ValueType(enum.Enum):
|
132
|
+
INT32 = 0
|
133
|
+
INT64 = 1
|
134
|
+
FLOAT32 = 2
|
135
|
+
FLOAT64 = 3
|
136
|
+
BOOL = 4
|
137
|
+
STRING = 5
|
138
|
+
DATE = 6
|
139
|
+
OBJECT = 7
|
140
|
+
LIST = 8
|
141
|
+
DICT = 9
|
142
|
+
NULL = 10
|
143
|
+
|
144
|
+
|
145
|
+
def _version_long() -> str:
|
146
|
+
_check_loaded()
|
147
|
+
size = 200
|
148
|
+
buffer = ctypes.create_string_buffer(size)
|
149
|
+
status = factorylib.lib.psrd_version_long(buffer, size)
|
150
|
+
if status == 0:
|
151
|
+
return _from_c_str(buffer.value)
|
152
|
+
return ""
|
153
|
+
|
154
|
+
|
155
|
+
def _version_short() -> str:
|
156
|
+
_check_loaded()
|
157
|
+
size = 200
|
158
|
+
buffer = ctypes.create_string_buffer(size)
|
159
|
+
status = factorylib.lib.psrd_version_short(buffer, size)
|
160
|
+
if status == 0:
|
161
|
+
return _from_c_str(buffer.value)
|
162
|
+
return ""
|
163
|
+
|
164
|
+
|
165
|
+
def version() -> str:
|
166
|
+
"""Returns module version."""
|
167
|
+
return _version_long()
|
168
|
+
|
169
|
+
|
170
|
+
def build_version() -> str:
|
171
|
+
"""Returns short library version."""
|
172
|
+
return _version_short()
|
173
|
+
|
174
|
+
|
175
|
+
def get_log_level() -> LogLevel:
|
176
|
+
"""Get log level."""
|
177
|
+
_check_loaded()
|
178
|
+
log_level = ctypes.c_int()
|
179
|
+
code = factorylib.lib.psrd_get_log_level(ctypes.byref(log_level))
|
180
|
+
if code != 0:
|
181
|
+
raise FactoryException("Error getting log level")
|
182
|
+
return LogLevel(log_level.value)
|
183
|
+
|
184
|
+
|
185
|
+
def set_log_level(log_level: LogLevel):
|
186
|
+
"""Set log level."""
|
187
|
+
if not isinstance(log_level, LogLevel):
|
188
|
+
raise TypeError("log_level must be an instance of LogLevel")
|
189
|
+
_check_loaded()
|
190
|
+
as_int = log_level.value
|
191
|
+
code = factorylib.lib.psrd_set_log_level(as_int)
|
192
|
+
if code != 0:
|
193
|
+
raise FactoryException("Error setting log level")
|
194
|
+
|
195
|
+
|
196
|
+
def set_debug_mode(value: Union[bool, int]):
|
197
|
+
"""Set debug mode."""
|
198
|
+
_check_loaded()
|
199
|
+
if isinstance(value, bool):
|
200
|
+
value = 1 if value else 0
|
201
|
+
code = factorylib.lib.psrd_set_debug_mode(value)
|
202
|
+
if code != 0:
|
203
|
+
raise FactoryException("Error setting debug mode")
|
204
|
+
|
205
|
+
|
206
|
+
def get_setting(key: str) -> Union[str, int, float, bool]:
|
207
|
+
global _initialized
|
208
|
+
global _initialized_lock
|
209
|
+
with _initialized_lock:
|
210
|
+
_check_loaded()
|
211
|
+
error = Error()
|
212
|
+
value = Value()
|
213
|
+
factorylib.lib.psrd_get_global_setting(_c_str(key),
|
214
|
+
_bytes(key),
|
215
|
+
value.handler(),
|
216
|
+
error.handler())
|
217
|
+
if error.code != 0:
|
218
|
+
raise FactoryException(error.what)
|
219
|
+
return value.get()
|
220
|
+
|
221
|
+
|
222
|
+
def set_setting(key: str, value: Union[str, int, float, bool]):
|
223
|
+
global _initialized
|
224
|
+
global _initialized_lock
|
225
|
+
with _initialized_lock:
|
226
|
+
_check_loaded()
|
227
|
+
error = Error()
|
228
|
+
_value = Value()
|
229
|
+
_value.set(value)
|
230
|
+
factorylib.lib.psrd_set_global_setting(_c_str(key),
|
231
|
+
_bytes(key),
|
232
|
+
_value.handler(),
|
233
|
+
error.handler())
|
234
|
+
if error.code != 0:
|
235
|
+
raise FactoryException(error.what)
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
def _get_context(models_or_context: Union[str, list, dict, "Context", None],
|
240
|
+
blocks: Optional[int] = None) -> "Value":
|
241
|
+
value = Value()
|
242
|
+
if isinstance(models_or_context, (Context, dict)):
|
243
|
+
context = models_or_context
|
244
|
+
elif isinstance(models_or_context, (str, list)) or models_or_context is None:
|
245
|
+
context = dict()
|
246
|
+
if isinstance(models_or_context, list):
|
247
|
+
context["Models"] = models_or_context
|
248
|
+
elif isinstance(models_or_context, str):
|
249
|
+
context["Models"] = [models_or_context, ]
|
250
|
+
else:
|
251
|
+
raise TypeError("Unexpected type for profile_or_context argument.")
|
252
|
+
if blocks is not None and isinstance(blocks, int):
|
253
|
+
if isinstance(blocks, Context):
|
254
|
+
context.set("Blocks", blocks)
|
255
|
+
else:
|
256
|
+
context["Blocks"] = blocks
|
257
|
+
value.set(context)
|
258
|
+
return value
|
259
|
+
|
260
|
+
def _get_arg_object(arg: Union[dict, "Value", "DataObject", None]) -> "Value":
|
261
|
+
if isinstance(arg, dict):
|
262
|
+
value = Value()
|
263
|
+
value.set(arg)
|
264
|
+
return value
|
265
|
+
elif isinstance(arg, Value):
|
266
|
+
return arg
|
267
|
+
elif isinstance(arg, DataObject):
|
268
|
+
value = Value()
|
269
|
+
value.set(arg)
|
270
|
+
return value
|
271
|
+
elif arg is None:
|
272
|
+
return Value()
|
273
|
+
else:
|
274
|
+
raise TypeError("Unexpected type for argument.")
|
275
|
+
|
276
|
+
|
277
|
+
|
278
|
+
class _BaseObject:
|
279
|
+
def __init__(self):
|
280
|
+
self._hdr = None
|
281
|
+
|
282
|
+
def handler(self):
|
283
|
+
return self._hdr
|
284
|
+
|
285
|
+
def __hash__(self):
|
286
|
+
return self._hdr
|
287
|
+
|
288
|
+
|
289
|
+
class Error(_BaseObject):
|
290
|
+
def __init__(self):
|
291
|
+
super().__init__()
|
292
|
+
self._hdr = factorylib.lib.psrd_new_error()
|
293
|
+
|
294
|
+
@property
|
295
|
+
def code(self) -> int:
|
296
|
+
return factorylib.lib.psrd_error_code(self._hdr)
|
297
|
+
|
298
|
+
@code.setter
|
299
|
+
def code(self, value):
|
300
|
+
raise AttributeError("do not set code")
|
301
|
+
|
302
|
+
@code.deleter
|
303
|
+
def code(self):
|
304
|
+
raise AttributeError("do not delete code")
|
305
|
+
|
306
|
+
@property
|
307
|
+
def what(self) -> str:
|
308
|
+
size = factorylib.lib.psrd_error_message(self._hdr, None, 0)
|
309
|
+
if size <= 0:
|
310
|
+
size = 800
|
311
|
+
buffer = ctypes.create_string_buffer(size)
|
312
|
+
status = factorylib.lib.psrd_error_message(self._hdr,
|
313
|
+
buffer, size)
|
314
|
+
if status == 0:
|
315
|
+
return _from_c_str(buffer.value)
|
316
|
+
return ""
|
317
|
+
|
318
|
+
@what.deleter
|
319
|
+
def what(self):
|
320
|
+
raise AttributeError("do not delete what")
|
321
|
+
|
322
|
+
@what.setter
|
323
|
+
def what(self, value):
|
324
|
+
raise AttributeError("do not set what")
|
325
|
+
|
326
|
+
def __del__(self):
|
327
|
+
if self._hdr is not None:
|
328
|
+
factorylib.lib.psrd_free_error(self._hdr)
|
329
|
+
|
330
|
+
def __repr__(self):
|
331
|
+
return f"Error object with code \"{self.code}\" and message:\n" \
|
332
|
+
f"{self.what}"
|
333
|
+
|
334
|
+
def __str__(self):
|
335
|
+
return self.what
|
336
|
+
|
337
|
+
|
338
|
+
class _TableColumn:
|
339
|
+
def __init__(self):
|
340
|
+
self.name = ""
|
341
|
+
# values: a pure Python list or a ctypes array
|
342
|
+
self.values: Union[list, ctypes.c_int, ctypes.c_long, ctypes.c_float, ctypes.c_double] = []
|
343
|
+
|
344
|
+
def __len__(self):
|
345
|
+
return len(self.values)
|
346
|
+
|
347
|
+
|
348
|
+
class ValueList(_BaseObject):
|
349
|
+
def __init__(self, initialized=True):
|
350
|
+
super().__init__()
|
351
|
+
self._hdr = factorylib.lib.psrd_new_list() if initialized else None
|
352
|
+
|
353
|
+
def __del__(self):
|
354
|
+
if self._hdr is not None:
|
355
|
+
factorylib.lib.psrd_free_list(self._hdr)
|
356
|
+
|
357
|
+
@staticmethod
|
358
|
+
def from_list(value: Union[List, Tuple]):
|
359
|
+
_err = Error()
|
360
|
+
list_obj = ValueList()
|
361
|
+
for obj in value:
|
362
|
+
val_obj = Value()
|
363
|
+
val_obj.set(obj)
|
364
|
+
factorylib.lib.psrd_list_append(list_obj.handler(),
|
365
|
+
val_obj.handler(),
|
366
|
+
_err.handler())
|
367
|
+
if _err.code != 0:
|
368
|
+
FactoryException(_err.what)
|
369
|
+
return list_obj
|
370
|
+
|
371
|
+
def to_list(self) -> list:
|
372
|
+
_err = Error()
|
373
|
+
count_value = ctypes.c_long()
|
374
|
+
factorylib.lib.psrd_list_count(self._hdr,
|
375
|
+
ctypes.byref(count_value),
|
376
|
+
_err.handler())
|
377
|
+
if _err.code != 0:
|
378
|
+
raise FactoryException(_err.what)
|
379
|
+
values_count = int(count_value.value)
|
380
|
+
|
381
|
+
list_of_values = []
|
382
|
+
_value = Value()
|
383
|
+
for i_value in range(values_count):
|
384
|
+
factorylib.lib.psrd_list_get(self._hdr, i_value,
|
385
|
+
_value.handler(), _err.handler())
|
386
|
+
if _err.code != 0:
|
387
|
+
raise FactoryException(_err.what)
|
388
|
+
list_of_values.append(_value.get())
|
389
|
+
return list_of_values
|
390
|
+
|
391
|
+
|
392
|
+
class ValueDict(_BaseObject):
|
393
|
+
def __init__(self, initialized=True):
|
394
|
+
super().__init__()
|
395
|
+
self._hdr = factorylib.lib.psrd_new_dict() if initialized else None
|
396
|
+
|
397
|
+
def __del__(self):
|
398
|
+
if self._hdr is not None:
|
399
|
+
factorylib.lib.psrd_free_dict(self._hdr)
|
400
|
+
|
401
|
+
def __getitem__(self, key: Union["Value", bool, int, float, dt.datetime, str, "DataObject", list, dict, None]) -> Union["Value", bool, int, float, dt.datetime, str, "DataObject", list, dict, None]:
|
402
|
+
if not isinstance(key, Value):
|
403
|
+
old_key = key
|
404
|
+
key = Value()
|
405
|
+
key.set(old_key)
|
406
|
+
error = Error()
|
407
|
+
value = Value()
|
408
|
+
factorylib.lib.psrd_dict_get_by_key(self._hdr,
|
409
|
+
key.handler(),
|
410
|
+
value.handler(),
|
411
|
+
error.handler())
|
412
|
+
if error.code != 0:
|
413
|
+
raise FactoryException(error.what)
|
414
|
+
return value.get()
|
415
|
+
|
416
|
+
def __contains__(self, key: Union["Value", bool, int, float, dt.datetime, str, "DataObject", list, dict, None]) -> bool:
|
417
|
+
if not isinstance(key, Value):
|
418
|
+
old_key = key
|
419
|
+
key = Value()
|
420
|
+
key.set(old_key)
|
421
|
+
error = Error()
|
422
|
+
value = Value()
|
423
|
+
factorylib.lib.psrd_dict_get_by_key(self._hdr,
|
424
|
+
key.handler(),
|
425
|
+
value.handler(),
|
426
|
+
error.handler())
|
427
|
+
return error.code == 0
|
428
|
+
|
429
|
+
def __len__(self) -> int:
|
430
|
+
error = Error()
|
431
|
+
count_value = ctypes.c_long()
|
432
|
+
factorylib.lib.psrd_dict_count(self._hdr,
|
433
|
+
ctypes.byref(count_value),
|
434
|
+
error.handler())
|
435
|
+
if error.code != 0:
|
436
|
+
raise FactoryException(error.what)
|
437
|
+
return int(count_value.value)
|
438
|
+
|
439
|
+
class KeyIterator:
|
440
|
+
def __init__(self, dict_obj: "ValueDict"):
|
441
|
+
self.dict_obj = dict_obj
|
442
|
+
self.error = Error()
|
443
|
+
self.key = Value()
|
444
|
+
self.index = 0
|
445
|
+
|
446
|
+
def __iter__(self):
|
447
|
+
return self
|
448
|
+
|
449
|
+
def __next__(self) -> "Value":
|
450
|
+
if self.index >= self.dict_obj.__len__():
|
451
|
+
raise StopIteration
|
452
|
+
factorylib.lib.psrd_dict_get_key_by_index(self.dict_obj._hdr, self.index,
|
453
|
+
self.key.handler(),
|
454
|
+
self.error.handler())
|
455
|
+
if self.error.code != 0:
|
456
|
+
raise FactoryException(self.error.what)
|
457
|
+
self.index += 1
|
458
|
+
return self.key.get()
|
459
|
+
|
460
|
+
def keys(self) -> KeyIterator:
|
461
|
+
return self.KeyIterator(self)
|
462
|
+
|
463
|
+
class ValueIterator:
|
464
|
+
def __init__(self, dict_obj: "ValueDict"):
|
465
|
+
self.dict_obj = dict_obj
|
466
|
+
self.error = Error()
|
467
|
+
self.value = Value()
|
468
|
+
self.index = 0
|
469
|
+
|
470
|
+
def __iter__(self):
|
471
|
+
return self
|
472
|
+
|
473
|
+
def __next__(self) -> "Value":
|
474
|
+
if self.index >= self.dict_obj.__len__():
|
475
|
+
raise StopIteration
|
476
|
+
factorylib.lib.psrd_dict_get_value_by_index(self.dict_obj._hdr, self.index,
|
477
|
+
self.value.handler(),
|
478
|
+
self.error.handler())
|
479
|
+
if self.error.code != 0:
|
480
|
+
raise FactoryException(self.error.what)
|
481
|
+
self.index += 1
|
482
|
+
return self.value.get()
|
483
|
+
|
484
|
+
def values(self) -> ValueIterator:
|
485
|
+
return self.ValueIterator(self)
|
486
|
+
|
487
|
+
class ItemIterator:
|
488
|
+
def __init__(self, dict_obj: "ValueDict"):
|
489
|
+
self.dict_obj = dict_obj
|
490
|
+
self.error = Error()
|
491
|
+
self.key = Value()
|
492
|
+
self.value = Value()
|
493
|
+
self.index = 0
|
494
|
+
|
495
|
+
def __iter__(self):
|
496
|
+
return self
|
497
|
+
|
498
|
+
def __next__(self) -> Tuple["Value", "Value"]:
|
499
|
+
if self.index >= self.dict_obj.__len__():
|
500
|
+
raise StopIteration
|
501
|
+
factorylib.lib.psrd_dict_get_by_index(self.dict_obj._hdr, self.index,
|
502
|
+
self.key.handler(),
|
503
|
+
self.value.handler(),
|
504
|
+
self.error.handler())
|
505
|
+
if self.error.code != 0:
|
506
|
+
raise FactoryException(self.error.what)
|
507
|
+
self.index += 1
|
508
|
+
return self.key.get(), self.value.get()
|
509
|
+
|
510
|
+
def items(self) -> ItemIterator:
|
511
|
+
return self.ItemIterator(self)
|
512
|
+
|
513
|
+
def clear(self):
|
514
|
+
error = Error()
|
515
|
+
factorylib.lib.psrd_dict_clear(self._hdr, error.handler())
|
516
|
+
if error.code != 0:
|
517
|
+
raise FactoryException(error.what)
|
518
|
+
|
519
|
+
|
520
|
+
@staticmethod
|
521
|
+
def from_dict(dict_value: dict):
|
522
|
+
error = Error()
|
523
|
+
dict_obj = ValueDict()
|
524
|
+
key_obj = Value()
|
525
|
+
val_obj = Value()
|
526
|
+
for key, value in dict_value.items():
|
527
|
+
key_obj.set(key)
|
528
|
+
val_obj.set(value)
|
529
|
+
factorylib.lib.psrd_dict_set(dict_obj.handler(),
|
530
|
+
key_obj.handler(),
|
531
|
+
val_obj.handler(),
|
532
|
+
error.handler())
|
533
|
+
if error.code != 0:
|
534
|
+
FactoryException(error.what)
|
535
|
+
return dict_obj
|
536
|
+
|
537
|
+
def to_dict(self) -> dict:
|
538
|
+
"""Converts Factory dictionary to Python's"""
|
539
|
+
error = Error()
|
540
|
+
count_value: Union[ctypes.c_long, int] = ctypes.c_long()
|
541
|
+
factorylib.lib.psrd_dict_count(self._hdr,
|
542
|
+
ctypes.byref(count_value),
|
543
|
+
error.handler())
|
544
|
+
if error.code != 0:
|
545
|
+
raise FactoryException(error.what)
|
546
|
+
count_value = int(count_value.value)
|
547
|
+
|
548
|
+
read_dict = dict()
|
549
|
+
key = Value()
|
550
|
+
value = Value()
|
551
|
+
for i_value in range(count_value):
|
552
|
+
factorylib.lib.psrd_dict_get_by_index(self._hdr, i_value,
|
553
|
+
key.handler(),
|
554
|
+
value.handler(),
|
555
|
+
error.handler())
|
556
|
+
if error.code != 0:
|
557
|
+
raise FactoryException(error.what)
|
558
|
+
read_dict[key.get()] = value.get()
|
559
|
+
return read_dict
|
560
|
+
|
561
|
+
|
562
|
+
class Value(_BaseObject):
|
563
|
+
def __init__(self):
|
564
|
+
super().__init__()
|
565
|
+
_check_loaded()
|
566
|
+
self._hdr = factorylib.lib.psrd_new_value()
|
567
|
+
|
568
|
+
def __del__(self):
|
569
|
+
if self._hdr is not None:
|
570
|
+
factorylib.lib.psrd_free_value(self._hdr)
|
571
|
+
|
572
|
+
def get(self) -> Union[bool, int, float, dt.datetime, str, "DataObject", list, dict, None]:
|
573
|
+
_err = Error()
|
574
|
+
uint_value = ctypes.c_long()
|
575
|
+
factorylib.lib.psrd_value_get_type(self._hdr,
|
576
|
+
ctypes.byref(uint_value),
|
577
|
+
_err.handler())
|
578
|
+
if _err.code != 0:
|
579
|
+
raise FactoryException(_err.what)
|
580
|
+
var_type = int(uint_value.value)
|
581
|
+
if var_type == ValueType.INT32.value:
|
582
|
+
int_value = ctypes.c_int()
|
583
|
+
factorylib.lib.psrd_value_get_int32(self._hdr,
|
584
|
+
ctypes.byref(int_value),
|
585
|
+
_err.handler())
|
586
|
+
if _err.code != 0:
|
587
|
+
raise FactoryException(_err.what)
|
588
|
+
return int(int_value.value)
|
589
|
+
elif var_type == ValueType.INT64.value:
|
590
|
+
long_value = ctypes.c_long()
|
591
|
+
factorylib.lib.psrd_value_get_int64(self._hdr,
|
592
|
+
ctypes.byref(long_value),
|
593
|
+
_err.handler())
|
594
|
+
if _err.code != 0:
|
595
|
+
raise FactoryException(_err.what)
|
596
|
+
return int(int_value.value)
|
597
|
+
elif var_type == ValueType.FLOAT32.value:
|
598
|
+
float_value = ctypes.c_float()
|
599
|
+
factorylib.lib.psrd_value_get_float32(self._hdr,
|
600
|
+
ctypes.byref(float_value),
|
601
|
+
_err.handler())
|
602
|
+
if _err.code != 0:
|
603
|
+
raise FactoryException(_err.what)
|
604
|
+
return float(float_value.value)
|
605
|
+
elif var_type == ValueType.FLOAT64.value:
|
606
|
+
float_value = ctypes.c_double()
|
607
|
+
factorylib.lib.psrd_value_get_float64(self._hdr,
|
608
|
+
ctypes.byref(float_value),
|
609
|
+
_err.handler())
|
610
|
+
if _err.code != 0:
|
611
|
+
raise FactoryException(_err.what)
|
612
|
+
return float(float_value.value)
|
613
|
+
elif var_type == ValueType.STRING.value:
|
614
|
+
size = factorylib.lib.psrd_value_get_string(self._hdr, None, 0,
|
615
|
+
_err.handler())
|
616
|
+
buffer = ctypes.create_string_buffer(size)
|
617
|
+
factorylib.lib.psrd_value_get_string(self._hdr, buffer, size,
|
618
|
+
_err.handler())
|
619
|
+
if _err.code != 0:
|
620
|
+
raise FactoryException(_err.what)
|
621
|
+
return _from_c_str(buffer.value)
|
622
|
+
elif var_type == ValueType.DATE.value:
|
623
|
+
date_value = ctypes.c_longlong()
|
624
|
+
factorylib.lib.psrd_value_get_date(self._hdr,
|
625
|
+
ctypes.byref(date_value),
|
626
|
+
_err.handler())
|
627
|
+
if _err.code != 0:
|
628
|
+
raise FactoryException(_err.what)
|
629
|
+
|
630
|
+
return dt.datetime.fromtimestamp(date_value.value - _date_transform, dt.timezone.utc)
|
631
|
+
|
632
|
+
elif var_type == ValueType.BOOL.value:
|
633
|
+
# read bool as int first
|
634
|
+
bool_value = ctypes.c_bool()
|
635
|
+
factorylib.lib.psrd_value_get_bool(self._hdr,
|
636
|
+
ctypes.byref(bool_value),
|
637
|
+
_err.handler())
|
638
|
+
if _err.code != 0:
|
639
|
+
raise FactoryException(_err.what)
|
640
|
+
return bool(bool_value.value)
|
641
|
+
elif var_type == ValueType.NULL.value:
|
642
|
+
# Null type
|
643
|
+
return None
|
644
|
+
elif var_type == ValueType.OBJECT.value:
|
645
|
+
obj = DataObject()
|
646
|
+
ref = factorylib.lib.psrd_value_get_object(self._hdr,
|
647
|
+
_err.handler())
|
648
|
+
if _err.code != 0 or ref is None:
|
649
|
+
raise FactoryException(_err.what)
|
650
|
+
obj._hdr = ref
|
651
|
+
return obj
|
652
|
+
elif var_type == ValueType.LIST.value:
|
653
|
+
dict_obj = ValueList()
|
654
|
+
ref = factorylib.lib.psrd_value_get_list(self._hdr,
|
655
|
+
_err.handler())
|
656
|
+
if _err.code != 0 or ref is None:
|
657
|
+
raise FactoryException(_err.what)
|
658
|
+
dict_obj._hdr = ref
|
659
|
+
return dict_obj.to_list()
|
660
|
+
elif var_type == ValueType.DICT.value:
|
661
|
+
dict_obj = ValueDict()
|
662
|
+
ref = factorylib.lib.psrd_value_get_dict(self._hdr,
|
663
|
+
_err.handler())
|
664
|
+
if _err.code != 0 or ref is None:
|
665
|
+
raise FactoryException(_err.what)
|
666
|
+
dict_obj._hdr = ref
|
667
|
+
return dict_obj.to_dict()
|
668
|
+
else:
|
669
|
+
raise NotImplementedError()
|
670
|
+
|
671
|
+
def set(self, value: Union[bool, int, float, dt.datetime, str, "DataObject", list, dict, None]):
|
672
|
+
_err = Error()
|
673
|
+
if isinstance(value, bool):
|
674
|
+
factorylib.lib.psrd_value_set_bool(self._hdr, value,
|
675
|
+
_err.handler())
|
676
|
+
if _err.code != 0:
|
677
|
+
raise FactoryException(_err.what)
|
678
|
+
elif isinstance(value, dt.datetime):
|
679
|
+
value.replace(tzinfo=dt.timezone.utc)
|
680
|
+
date_epoch = int(value.timestamp()) + _date_transform
|
681
|
+
factorylib.lib.psrd_value_set_date(self._hdr, date_epoch,
|
682
|
+
_err.handler())
|
683
|
+
if _err.code != 0:
|
684
|
+
raise FactoryException(_err.what)
|
685
|
+
# TODO: individual test for int32 and int64
|
686
|
+
elif isinstance(value, numbers.Integral):
|
687
|
+
factorylib.lib.psrd_value_set_int32(self._hdr, value,
|
688
|
+
_err.handler())
|
689
|
+
if _err.code != 0:
|
690
|
+
raise FactoryException(_err.what)
|
691
|
+
|
692
|
+
# TODO: individual test for float32 and float64
|
693
|
+
elif isinstance(value, numbers.Real):
|
694
|
+
factorylib.lib.psrd_value_set_float64(self._hdr, value,
|
695
|
+
_err.handler())
|
696
|
+
if _err.code != 0:
|
697
|
+
raise FactoryException(_err.what)
|
698
|
+
|
699
|
+
elif isinstance(value, str):
|
700
|
+
factorylib.lib.psrd_value_set_string(self._hdr,
|
701
|
+
_c_str(value),
|
702
|
+
_bytes(value),
|
703
|
+
_err.handler())
|
704
|
+
if _err.code != 0:
|
705
|
+
raise FactoryException(_err.what)
|
706
|
+
|
707
|
+
elif isinstance(value, DataObject):
|
708
|
+
factorylib.lib.psrd_value_set_object(self._hdr,
|
709
|
+
value.handler(),
|
710
|
+
_err.handler())
|
711
|
+
if _err.code != 0:
|
712
|
+
raise FactoryException(_err.what)
|
713
|
+
|
714
|
+
elif isinstance(value, (list, tuple, ValueList)):
|
715
|
+
if isinstance(value, (list, tuple)):
|
716
|
+
dict_obj = ValueList.from_list(value)
|
717
|
+
else:
|
718
|
+
dict_obj = value
|
719
|
+
factorylib.lib.psrd_value_set_list(self._hdr,
|
720
|
+
dict_obj.handler(),
|
721
|
+
_err.handler())
|
722
|
+
if _err.code != 0:
|
723
|
+
raise FactoryException(_err.what)
|
724
|
+
|
725
|
+
elif isinstance(value, dict):
|
726
|
+
dict_obj = ValueDict.from_dict(value)
|
727
|
+
factorylib.lib.psrd_value_set_dict(self._hdr,
|
728
|
+
dict_obj.handler(),
|
729
|
+
_err.handler())
|
730
|
+
if _err.code != 0:
|
731
|
+
raise FactoryException(_err.what)
|
732
|
+
|
733
|
+
elif isinstance(value, Study):
|
734
|
+
raise FactoryException("Study object cannot be set as value.")
|
735
|
+
|
736
|
+
elif value is None:
|
737
|
+
factorylib.lib.psrd_value_set_null(self._hdr,
|
738
|
+
_err.handler())
|
739
|
+
if _err.code != 0:
|
740
|
+
raise FactoryException(_err.what)
|
741
|
+
|
742
|
+
else:
|
743
|
+
raise FactoryException(f"Unsupported type \"{type(value).name}\" for value.")
|
744
|
+
|
745
|
+
|
746
|
+
class PropertyDescription(_BaseObject):
|
747
|
+
def __init__(self):
|
748
|
+
super().__init__()
|
749
|
+
self._hdr = None
|
750
|
+
|
751
|
+
def __del__(self):
|
752
|
+
if self._hdr is not None:
|
753
|
+
factorylib.lib.psrd_free_property_description(self._hdr)
|
754
|
+
|
755
|
+
@property
|
756
|
+
def name(self) -> str:
|
757
|
+
_err = Error()
|
758
|
+
# TODO: determine size automatically
|
759
|
+
size = 300
|
760
|
+
buffer = ctypes.create_string_buffer(size)
|
761
|
+
factorylib.lib.psrd_property_description_get_name(self._hdr, buffer, size,
|
762
|
+
_err.handler())
|
763
|
+
if _err.code != 0:
|
764
|
+
raise FactoryException(_err.what)
|
765
|
+
return _from_c_str(buffer.value)
|
766
|
+
|
767
|
+
@name.setter
|
768
|
+
def name(self, value):
|
769
|
+
raise AttributeError("do not set name")
|
770
|
+
|
771
|
+
@name.deleter
|
772
|
+
def name(self):
|
773
|
+
raise AttributeError("do not delete name")
|
774
|
+
|
775
|
+
@property
|
776
|
+
def alt_name(self) -> str:
|
777
|
+
_err = Error()
|
778
|
+
# TODO: determine size automatically
|
779
|
+
size = 300
|
780
|
+
buffer = ctypes.create_string_buffer(size)
|
781
|
+
factorylib.lib.psrd_property_description_get_alternative_name(
|
782
|
+
self._hdr, buffer, size, _err.handler())
|
783
|
+
if _err.code != 0:
|
784
|
+
raise FactoryException(_err.what)
|
785
|
+
return _from_c_str(buffer.value)
|
786
|
+
|
787
|
+
@alt_name.setter
|
788
|
+
def alt_name(self, value):
|
789
|
+
raise AttributeError("do not set alt_name")
|
790
|
+
|
791
|
+
@alt_name.deleter
|
792
|
+
def alt_name(self):
|
793
|
+
raise AttributeError("do not delete alt_name")
|
794
|
+
|
795
|
+
def is_dynamic(self) -> bool:
|
796
|
+
_err = Error()
|
797
|
+
value = ctypes.c_bool()
|
798
|
+
factorylib.lib.psrd_property_description_is_dynamic(self._hdr,
|
799
|
+
ctypes.byref(value),
|
800
|
+
_err.handler())
|
801
|
+
if _err.code != 0:
|
802
|
+
raise FactoryException(_err.what)
|
803
|
+
return bool(value.value)
|
804
|
+
|
805
|
+
def is_indexed(self) -> bool:
|
806
|
+
_err = Error()
|
807
|
+
value = ctypes.c_bool()
|
808
|
+
factorylib.lib.psrd_property_description_is_indexed(self._hdr,
|
809
|
+
ctypes.byref(value),
|
810
|
+
_err.handler())
|
811
|
+
if _err.code != 0:
|
812
|
+
raise FactoryException(_err.what)
|
813
|
+
return bool(value.value)
|
814
|
+
|
815
|
+
def is_grouped(self) -> bool:
|
816
|
+
_err = Error()
|
817
|
+
value = ctypes.c_bool()
|
818
|
+
factorylib.lib.psrd_property_description_is_grouped(self._hdr,
|
819
|
+
ctypes.byref(value),
|
820
|
+
_err.handler())
|
821
|
+
if _err.code != 0:
|
822
|
+
raise FactoryException(_err.what)
|
823
|
+
return bool(value.value)
|
824
|
+
|
825
|
+
def grouped_with(self) -> List[str]:
|
826
|
+
_err = Error()
|
827
|
+
_list_obj = ValueList()
|
828
|
+
ref = factorylib.lib.psrd_property_description_grouped_with(self._hdr,
|
829
|
+
_err.handler())
|
830
|
+
if _err.code != 0 or ref is None:
|
831
|
+
raise FactoryException(_err.what)
|
832
|
+
_list_obj._hdr = ref
|
833
|
+
return _list_obj.to_list()
|
834
|
+
|
835
|
+
def dimensions(self) -> Dict[str, int]:
|
836
|
+
_err = Error()
|
837
|
+
dimensions = {}
|
838
|
+
value = ctypes.c_long()
|
839
|
+
factorylib.lib.psrd_property_description_dimensions_count(self._hdr,
|
840
|
+
ctypes.byref(value),
|
841
|
+
_err.handler())
|
842
|
+
if _err.code != 0:
|
843
|
+
raise FactoryException(_err.what)
|
844
|
+
dimensions_count = int(value.value)
|
845
|
+
|
846
|
+
for i_dim in range(dimensions_count):
|
847
|
+
# TODO: get size automatically
|
848
|
+
size = 100
|
849
|
+
buffer = ctypes.create_string_buffer(size)
|
850
|
+
factorylib.lib.psrd_property_description_get_dimension_name(self._hdr,
|
851
|
+
i_dim, buffer,
|
852
|
+
size,
|
853
|
+
_err.handler())
|
854
|
+
if _err.code != 0:
|
855
|
+
raise FactoryException(_err.what)
|
856
|
+
name = _from_c_str(buffer.value)
|
857
|
+
|
858
|
+
factorylib.lib.psrd_property_description_get_dimension_size(self._hdr,
|
859
|
+
i_dim,
|
860
|
+
ctypes.byref(value),
|
861
|
+
_err.handler())
|
862
|
+
if _err.code != 0:
|
863
|
+
raise FactoryException(_err.what)
|
864
|
+
size = int(value.value)
|
865
|
+
|
866
|
+
dimensions[name] = size
|
867
|
+
return dimensions
|
868
|
+
|
869
|
+
def type(self) -> ValueType:
|
870
|
+
_err = Error()
|
871
|
+
value = ctypes.c_long()
|
872
|
+
factorylib.lib.psrd_property_description_get_type(self._hdr,
|
873
|
+
ctypes.byref(value),
|
874
|
+
_err.handler())
|
875
|
+
if _err.code != 0:
|
876
|
+
raise FactoryException(_err.what)
|
877
|
+
return ValueType(value.value)
|
878
|
+
|
879
|
+
def __repr__(self):
|
880
|
+
return self.__str__()
|
881
|
+
|
882
|
+
def __str__(self):
|
883
|
+
dimensions = self.dimensions()
|
884
|
+
if len(dimensions) == 0:
|
885
|
+
return f"Property {self.name}"
|
886
|
+
else:
|
887
|
+
return f"Property {self.name} with dimensions {self.dimensions()}"
|
888
|
+
|
889
|
+
|
890
|
+
|
891
|
+
class DataObject(_BaseObject):
|
892
|
+
def __init__(self):
|
893
|
+
super().__init__()
|
894
|
+
self._hdr = None
|
895
|
+
|
896
|
+
def __del__(self):
|
897
|
+
if self._hdr is not None:
|
898
|
+
factorylib.lib.psrd_free_object(self._hdr)
|
899
|
+
|
900
|
+
def __eq__(self, other):
|
901
|
+
if not isinstance(other, DataObject):
|
902
|
+
return False
|
903
|
+
_err = Error()
|
904
|
+
value = ctypes.c_bool()
|
905
|
+
if self._hdr == other.handler():
|
906
|
+
return True
|
907
|
+
factorylib.lib.psrd_object_is_equals_to(self._hdr,
|
908
|
+
other.handler(),
|
909
|
+
ctypes.byref(value),
|
910
|
+
_err.handler())
|
911
|
+
if _err.code != 0:
|
912
|
+
raise FactoryException(_err.what)
|
913
|
+
return bool(value.value)
|
914
|
+
|
915
|
+
def __hash__(self):
|
916
|
+
_err = Error()
|
917
|
+
handler = factorylib.lib.psrd_object_get_handler(self._hdr, _err.handler())
|
918
|
+
if _err.code != 0:
|
919
|
+
raise FactoryException(_err.what)
|
920
|
+
return handler
|
921
|
+
|
922
|
+
def __copy__(self):
|
923
|
+
dest = DataObject()
|
924
|
+
_err = Error()
|
925
|
+
ref = factorylib.lib.psrd_object_clone(self.handler(),
|
926
|
+
_err.handler())
|
927
|
+
if _err.code != 0 or ref is None:
|
928
|
+
raise FactoryException(_err.what)
|
929
|
+
dest._hdr = ref
|
930
|
+
return dest
|
931
|
+
|
932
|
+
def __deepcopy__(self, memodict=None):
|
933
|
+
raise NotImplementedError()
|
934
|
+
|
935
|
+
def __repr__(self):
|
936
|
+
identifiers = []
|
937
|
+
if self.code != 0:
|
938
|
+
identifiers.append(f"code={self.code}")
|
939
|
+
if self.id != "":
|
940
|
+
identifiers.append(f"id={self.id.strip()}")
|
941
|
+
if self.name != "":
|
942
|
+
identifiers.append(f"name={self.name.strip()}")
|
943
|
+
return f"psr.factory.DataObject({self.type}, {', '.join(identifiers)})"
|
944
|
+
|
945
|
+
def help(self) -> str:
|
946
|
+
return help(self.type)
|
947
|
+
|
948
|
+
@property
|
949
|
+
def context(self) -> "Context":
|
950
|
+
_check_initialized()
|
951
|
+
obj = Context()
|
952
|
+
_err = Error()
|
953
|
+
ref = factorylib.lib.psrd_object_context(self._hdr,
|
954
|
+
_err.handler())
|
955
|
+
if _err.code != 0 or ref is None:
|
956
|
+
raise FactoryException(_err.what)
|
957
|
+
obj._hdr = ref
|
958
|
+
return obj
|
959
|
+
|
960
|
+
def properties(self) -> Dict[str, PropertyDescription]:
|
961
|
+
_err = Error()
|
962
|
+
value = ctypes.c_long()
|
963
|
+
factorylib.lib.psrd_object_property_description_count(self._hdr,
|
964
|
+
ctypes.byref(value),
|
965
|
+
_err.handler())
|
966
|
+
if _err.code != 0:
|
967
|
+
raise FactoryException(_err.what)
|
968
|
+
var_count = int(value.value)
|
969
|
+
properties = {}
|
970
|
+
for i_var in range(var_count):
|
971
|
+
var = PropertyDescription()
|
972
|
+
ref = factorylib.lib.psrd_object_get_property_description(self._hdr,
|
973
|
+
i_var,
|
974
|
+
_err.handler())
|
975
|
+
if _err.code != 0 or ref is None:
|
976
|
+
raise FactoryException(_err.what)
|
977
|
+
var._hdr = ref
|
978
|
+
properties[var.name] = var
|
979
|
+
return properties
|
980
|
+
|
981
|
+
def get(self, expression: str) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
|
982
|
+
value = Value()
|
983
|
+
_err = Error()
|
984
|
+
factorylib.lib.psrd_object_get_value(self._hdr,
|
985
|
+
_c_str(expression),
|
986
|
+
value.handler(),
|
987
|
+
_err.handler())
|
988
|
+
if _err.code != 0:
|
989
|
+
raise FactoryException(_err.what)
|
990
|
+
return value.get()
|
991
|
+
|
992
|
+
def get_at(self, expression: str, range_expr: Union[str, dt.datetime]) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
|
993
|
+
if not isinstance(range_expr, (str, dt.datetime)):
|
994
|
+
raise FactoryException("range_expr must be a string or datetime object.")
|
995
|
+
_value = Value()
|
996
|
+
_err = Error()
|
997
|
+
_range = Value()
|
998
|
+
_range.set(range_expr)
|
999
|
+
factorylib.lib.psrd_object_get_value_at(self._hdr,
|
1000
|
+
_c_str(expression),
|
1001
|
+
_range.handler(),
|
1002
|
+
_value.handler(),
|
1003
|
+
_err.handler())
|
1004
|
+
if _err.code != 0:
|
1005
|
+
raise FactoryException(_err.what)
|
1006
|
+
return _value.get()
|
1007
|
+
|
1008
|
+
def as_dict(self) -> Dict[str, any]:
|
1009
|
+
value_dict = ValueDict()
|
1010
|
+
error = Error()
|
1011
|
+
handler = factorylib.lib.psrd_object_get_as_dict(self._hdr,
|
1012
|
+
error.handler())
|
1013
|
+
if error.code != 0 or handler is None:
|
1014
|
+
raise FactoryException(error.what)
|
1015
|
+
value_dict._hdr = handler
|
1016
|
+
return value_dict.to_dict()
|
1017
|
+
|
1018
|
+
def from_dict(self, input_dict: Dict[str, any]):
|
1019
|
+
value_dict = ValueDict.from_dict(input_dict)
|
1020
|
+
error = Error()
|
1021
|
+
factorylib.lib.psrd_object_set_from_dict(self._hdr, value_dict.handler(),
|
1022
|
+
error.handler())
|
1023
|
+
if error.code != 0:
|
1024
|
+
raise FactoryException(error.what)
|
1025
|
+
|
1026
|
+
def get_df(self, expression: str) -> "pandas.DataFrame":
|
1027
|
+
_err = Error()
|
1028
|
+
_df = DataFrame()
|
1029
|
+
factorylib.lib.psrd_object_get_table(self._hdr, _df.handler(),
|
1030
|
+
_c_str(expression),
|
1031
|
+
_bytes(expression),
|
1032
|
+
_err.handler())
|
1033
|
+
if _err.code != 0:
|
1034
|
+
raise FactoryException(_err.what)
|
1035
|
+
df_builder = _DataFrameBuilder()
|
1036
|
+
df_builder.build_dataframe(_df)
|
1037
|
+
return df_builder.build_pandas_dataframe()
|
1038
|
+
|
1039
|
+
def set(self, expression: str, value):
|
1040
|
+
_err = Error()
|
1041
|
+
_val = Value()
|
1042
|
+
_val.set(value)
|
1043
|
+
factorylib.lib.psrd_object_set_value(self._hdr, _c_str(expression),
|
1044
|
+
_bytes(expression),
|
1045
|
+
_val.handler(),
|
1046
|
+
_err.handler())
|
1047
|
+
if _err.code != 0:
|
1048
|
+
raise FactoryException(_err.what)
|
1049
|
+
|
1050
|
+
def set_at(self, expression: str, range_expr: Union[str, dt.datetime], value):
|
1051
|
+
if not isinstance(range_expr, (str, dt.datetime)):
|
1052
|
+
raise FactoryException("range_expr must be a string or datetime object.")
|
1053
|
+
_err = Error()
|
1054
|
+
_value = Value()
|
1055
|
+
_value.set(value)
|
1056
|
+
_range = Value()
|
1057
|
+
_range.set(range_expr)
|
1058
|
+
factorylib.lib.psrd_object_set_value_at(self._hdr,
|
1059
|
+
_c_str(expression),
|
1060
|
+
_bytes(expression),
|
1061
|
+
_range.handler(),
|
1062
|
+
_value.handler(),
|
1063
|
+
_err.handler())
|
1064
|
+
if _err.code != 0:
|
1065
|
+
raise FactoryException(_err.what)
|
1066
|
+
|
1067
|
+
def set_df(self, dataframe_like):
|
1068
|
+
if not _has_pandas():
|
1069
|
+
raise ModuleNotFoundError("pandas required.")
|
1070
|
+
dataframe_like = pandas.api.interchange.from_dataframe(dataframe_like)
|
1071
|
+
df_builder = _DataFrameBuilder()
|
1072
|
+
_df = df_builder.build_from_pandas(dataframe_like)
|
1073
|
+
_err = Error()
|
1074
|
+
factorylib.lib.psrd_object_set_table(self._hdr, _df.handler(),
|
1075
|
+
_err.handler())
|
1076
|
+
if _err.code != 0:
|
1077
|
+
raise FactoryException(_err.what)
|
1078
|
+
|
1079
|
+
|
1080
|
+
def clear_values(self, expression: str):
|
1081
|
+
_err = Error()
|
1082
|
+
factorylib.lib.psrd_object_clear_values(self._hdr,
|
1083
|
+
_c_str(expression),
|
1084
|
+
_bytes(expression),
|
1085
|
+
_err.handler())
|
1086
|
+
if _err.code != 0:
|
1087
|
+
raise FactoryException(_err.what)
|
1088
|
+
|
1089
|
+
def parent(self) -> Optional["Study"]:
|
1090
|
+
study_ptr = Study()
|
1091
|
+
_err = Error()
|
1092
|
+
ref = factorylib.lib.psrd_object_get_parent(self._hdr,
|
1093
|
+
_err.handler())
|
1094
|
+
if _err.code != 0:
|
1095
|
+
raise FactoryException(_err.what)
|
1096
|
+
if ref is None:
|
1097
|
+
return None
|
1098
|
+
study_ptr._hdr = ref
|
1099
|
+
return study_ptr
|
1100
|
+
|
1101
|
+
def referenced_by(self) -> List["DataObject"]:
|
1102
|
+
object_list = ValueList(False)
|
1103
|
+
_err = Error()
|
1104
|
+
ref = factorylib.lib.psrd_object_referenced_by(self._hdr,
|
1105
|
+
_err.handler())
|
1106
|
+
if _err.code != 0 or ref is None:
|
1107
|
+
raise FactoryException(_err.what)
|
1108
|
+
object_list._hdr = ref
|
1109
|
+
return object_list.to_list()
|
1110
|
+
|
1111
|
+
@property
|
1112
|
+
def code(self) -> int:
|
1113
|
+
_err = Error()
|
1114
|
+
value = ctypes.c_int()
|
1115
|
+
factorylib.lib.psrd_object_get_code(self._hdr,
|
1116
|
+
ctypes.byref(value),
|
1117
|
+
_err.handler())
|
1118
|
+
if _err.code != 0:
|
1119
|
+
raise FactoryException(_err.what)
|
1120
|
+
return value.value
|
1121
|
+
|
1122
|
+
@code.setter
|
1123
|
+
def code(self, value: int):
|
1124
|
+
_err = Error()
|
1125
|
+
factorylib.lib.psrd_object_set_code(self._hdr, value,
|
1126
|
+
_err.handler())
|
1127
|
+
if _err.code != 0:
|
1128
|
+
raise FactoryException(_err.what)
|
1129
|
+
|
1130
|
+
@code.deleter
|
1131
|
+
def code(self):
|
1132
|
+
raise AttributeError("do not delete code")
|
1133
|
+
|
1134
|
+
@property
|
1135
|
+
def type(self) -> str:
|
1136
|
+
err = Error()
|
1137
|
+
size = factorylib.lib.psrd_object_get_type(self._hdr, None,
|
1138
|
+
0, err.handler())
|
1139
|
+
if err.code != 0:
|
1140
|
+
raise FactoryException(err.what)
|
1141
|
+
buffer = ctypes.create_string_buffer(size)
|
1142
|
+
factorylib.lib.psrd_object_get_type(self._hdr, buffer,
|
1143
|
+
size, err.handler())
|
1144
|
+
if err.code != 0:
|
1145
|
+
raise FactoryException(err.what)
|
1146
|
+
return _from_c_str(buffer.value)
|
1147
|
+
|
1148
|
+
@type.setter
|
1149
|
+
def type(self, value: str):
|
1150
|
+
raise AttributeError("do not set type")
|
1151
|
+
|
1152
|
+
@type.deleter
|
1153
|
+
def type(self):
|
1154
|
+
raise AttributeError("do not delete type")
|
1155
|
+
|
1156
|
+
@property
|
1157
|
+
def name(self) -> str:
|
1158
|
+
err = Error()
|
1159
|
+
size = factorylib.lib.psrd_object_get_name(self._hdr, None,
|
1160
|
+
0, err.handler())
|
1161
|
+
if err.code != 0:
|
1162
|
+
raise FactoryException(err.what)
|
1163
|
+
buffer = ctypes.create_string_buffer(size)
|
1164
|
+
factorylib.lib.psrd_object_get_name(self._hdr, buffer,
|
1165
|
+
size, err.handler())
|
1166
|
+
if err.code == 0:
|
1167
|
+
return _from_c_str(buffer.value)
|
1168
|
+
raise FactoryException(err.what)
|
1169
|
+
|
1170
|
+
@name.setter
|
1171
|
+
def name(self, value: str):
|
1172
|
+
err = Error()
|
1173
|
+
factorylib.lib.psrd_object_set_name(self._hdr,
|
1174
|
+
_c_str(value),
|
1175
|
+
_bytes(value),
|
1176
|
+
err.handler())
|
1177
|
+
if err.code != 0:
|
1178
|
+
raise FactoryException(err.what)
|
1179
|
+
|
1180
|
+
@name.deleter
|
1181
|
+
def name(self):
|
1182
|
+
raise AttributeError("do not delete name")
|
1183
|
+
|
1184
|
+
@property
|
1185
|
+
def id(self) -> str:
|
1186
|
+
err = Error()
|
1187
|
+
size = factorylib.lib.psrd_object_get_id(self._hdr, None,
|
1188
|
+
0, err.handler())
|
1189
|
+
if err.code != 0:
|
1190
|
+
raise FactoryException(err.what)
|
1191
|
+
buffer = ctypes.create_string_buffer(size)
|
1192
|
+
factorylib.lib.psrd_object_get_id(self._hdr, buffer,
|
1193
|
+
size, err.handler())
|
1194
|
+
if err.code == 0:
|
1195
|
+
return _from_c_str(buffer.value)
|
1196
|
+
raise FactoryException(err.what)
|
1197
|
+
|
1198
|
+
@id.setter
|
1199
|
+
def id(self, value: str):
|
1200
|
+
_err = Error()
|
1201
|
+
factorylib.lib.psrd_object_set_id(self._hdr,
|
1202
|
+
_c_str(value),
|
1203
|
+
_bytes(value),
|
1204
|
+
_err.handler())
|
1205
|
+
if _err.code != 0:
|
1206
|
+
raise FactoryException(_err.what)
|
1207
|
+
|
1208
|
+
@id.deleter
|
1209
|
+
def id(self):
|
1210
|
+
raise AttributeError("do not delete id")
|
1211
|
+
|
1212
|
+
|
1213
|
+
class Context(DataObject):
|
1214
|
+
@staticmethod
|
1215
|
+
def default_context() -> "Context":
|
1216
|
+
_check_initialized()
|
1217
|
+
context = Context()
|
1218
|
+
err = Error()
|
1219
|
+
ref = factorylib.lib.psrd_get_default_context(err.handler())
|
1220
|
+
if err.code != 0 or ref is None:
|
1221
|
+
raise FactoryException(err.what)
|
1222
|
+
context._hdr = ref
|
1223
|
+
return context
|
1224
|
+
|
1225
|
+
@staticmethod
|
1226
|
+
def create() -> "Context":
|
1227
|
+
context_obj = create("Context", None)
|
1228
|
+
context = Context()
|
1229
|
+
context._hdr = context_obj._hdr
|
1230
|
+
context_obj._hdr = None
|
1231
|
+
return context
|
1232
|
+
|
1233
|
+
|
1234
|
+
class Study(_BaseObject):
|
1235
|
+
def __init__(self):
|
1236
|
+
super().__init__()
|
1237
|
+
self.find_by_name = self.find
|
1238
|
+
|
1239
|
+
def __del__(self):
|
1240
|
+
if self._hdr is not None:
|
1241
|
+
factorylib.lib.psrd_free_study(self._hdr)
|
1242
|
+
|
1243
|
+
def __hash__(self):
|
1244
|
+
return factorylib.lib.psrd_study_get_handler(self._hdr)
|
1245
|
+
|
1246
|
+
def __eq__(self, other: "Study"):
|
1247
|
+
_err = Error()
|
1248
|
+
value = ctypes.c_bool()
|
1249
|
+
if self._hdr == other.handler():
|
1250
|
+
return True
|
1251
|
+
factorylib.lib.psrd_study_is_equals_to(self._hdr,
|
1252
|
+
other.handler(),
|
1253
|
+
ctypes.byref(value),
|
1254
|
+
_err.handler())
|
1255
|
+
if _err.code != 0:
|
1256
|
+
raise FactoryException(_err.what)
|
1257
|
+
return bool(value.value)
|
1258
|
+
|
1259
|
+
def __copy__(self):
|
1260
|
+
raise NotImplementedError()
|
1261
|
+
|
1262
|
+
def __deepcopy__(self, memodict=None):
|
1263
|
+
dest = Study()
|
1264
|
+
_err = Error()
|
1265
|
+
ref = factorylib.lib.psrd_study_clone(self.handler(),
|
1266
|
+
_err.handler())
|
1267
|
+
if _err.code != 0 or ref is None:
|
1268
|
+
raise FactoryException(_err.what)
|
1269
|
+
dest._hdr = ref
|
1270
|
+
return dest
|
1271
|
+
|
1272
|
+
@staticmethod
|
1273
|
+
def help():
|
1274
|
+
return help("Study")
|
1275
|
+
|
1276
|
+
@staticmethod
|
1277
|
+
def create_object(profile_or_context: Union[str, Context, dict, None],
|
1278
|
+
blocks: Optional[int] = None):
|
1279
|
+
_check_initialized()
|
1280
|
+
err = Error()
|
1281
|
+
context = _get_context(profile_or_context, blocks)
|
1282
|
+
study = Study()
|
1283
|
+
study._hdr = factorylib.lib.psrd_study_create(context.handler(),
|
1284
|
+
err.handler())
|
1285
|
+
if err.code != 0:
|
1286
|
+
raise FactoryException(err.what)
|
1287
|
+
return study
|
1288
|
+
|
1289
|
+
@staticmethod
|
1290
|
+
def load(study_path: Union[str, pathlib.Path], profile_or_context: Union[str, Context, None],
|
1291
|
+
settings_only: bool = False,
|
1292
|
+
options: Optional[Union[dict, "Value", "DataObject"]] = None):
|
1293
|
+
if not isinstance(options, (DataObject, type(None))):
|
1294
|
+
raise TypeError("options must be a DataObject or None.")
|
1295
|
+
_check_initialized()
|
1296
|
+
study_path = str(study_path)
|
1297
|
+
context = _get_context(profile_or_context, None)
|
1298
|
+
err = Error()
|
1299
|
+
options_value = _get_arg_object(options)
|
1300
|
+
study = Study()
|
1301
|
+
if not settings_only:
|
1302
|
+
load_fn = factorylib.lib.psrd_study_load
|
1303
|
+
else:
|
1304
|
+
load_fn = factorylib.lib.psrd_study_load_settings
|
1305
|
+
study._hdr = load_fn(_c_str(study_path), _bytes(study_path),
|
1306
|
+
options_value.handler(), context.handler(),
|
1307
|
+
err.handler())
|
1308
|
+
if err.code != 0:
|
1309
|
+
raise FactoryException(err.what)
|
1310
|
+
return study
|
1311
|
+
|
1312
|
+
def save(self, output_path: Union[str, pathlib.Path],
|
1313
|
+
options: Optional[Union[dict, Value, DataObject]] = None):
|
1314
|
+
output_path = str(output_path)
|
1315
|
+
_err = Error()
|
1316
|
+
options_value = _get_arg_object(options)
|
1317
|
+
factorylib.lib.psrd_study_save(self._hdr,
|
1318
|
+
_c_str(output_path), _bytes(output_path),
|
1319
|
+
options_value.handler(),
|
1320
|
+
_err.handler())
|
1321
|
+
if _err.code != 0:
|
1322
|
+
raise FactoryException(_err.what)
|
1323
|
+
|
1324
|
+
def save_settings(self, output_path: Union[str, pathlib.Path],
|
1325
|
+
options: Optional[Union[dict, Value, DataObject]] = None):
|
1326
|
+
output_path = str(output_path)
|
1327
|
+
_err = Error()
|
1328
|
+
options_value = _get_arg_object(options)
|
1329
|
+
factorylib.lib.psrd_study_save_settings(self._hdr, _c_str(output_path),
|
1330
|
+
_bytes(output_path),
|
1331
|
+
options_value.handler(),
|
1332
|
+
_err.handler())
|
1333
|
+
if _err.code != 0:
|
1334
|
+
raise FactoryException(_err.what)
|
1335
|
+
|
1336
|
+
@property
|
1337
|
+
def context(self) -> "Context":
|
1338
|
+
_check_initialized()
|
1339
|
+
obj = Context()
|
1340
|
+
_err = Error()
|
1341
|
+
ref = factorylib.lib.psrd_study_context(self._hdr,
|
1342
|
+
_err.handler())
|
1343
|
+
if _err.code != 0 or ref is None:
|
1344
|
+
raise FactoryException(_err.what)
|
1345
|
+
obj._hdr = ref
|
1346
|
+
return obj
|
1347
|
+
|
1348
|
+
def get(self, expression: str) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
|
1349
|
+
value = Value()
|
1350
|
+
_err = Error()
|
1351
|
+
factorylib.lib.psrd_study_get_value(self._hdr,
|
1352
|
+
_c_str(expression),
|
1353
|
+
value.handler(),
|
1354
|
+
_err.handler())
|
1355
|
+
if _err.code != 0:
|
1356
|
+
raise FactoryException(_err.what)
|
1357
|
+
return value.get()
|
1358
|
+
|
1359
|
+
def get_at(self, expression: str, range_expr: Union[str, dt.datetime]) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
|
1360
|
+
if not isinstance(range_expr, str):
|
1361
|
+
raise FactoryException("range_expr must be a string or datetime object.")
|
1362
|
+
_value = Value()
|
1363
|
+
_err = Error()
|
1364
|
+
_range = Value()
|
1365
|
+
_range.set(range_expr)
|
1366
|
+
factorylib.lib.psrd_study_get_value_at(self._hdr,
|
1367
|
+
_c_str(expression),
|
1368
|
+
_range.handler(),
|
1369
|
+
_value.handler(),
|
1370
|
+
_err.handler())
|
1371
|
+
if _err.code != 0:
|
1372
|
+
raise FactoryException(_err.what)
|
1373
|
+
return _value.get()
|
1374
|
+
|
1375
|
+
def as_dict(self) -> Dict[str, any]:
|
1376
|
+
value_dict = ValueDict()
|
1377
|
+
error = Error()
|
1378
|
+
handler = factorylib.lib.psrd_study_get_as_dict(self._hdr,
|
1379
|
+
error.handler())
|
1380
|
+
if error.code != 0 or handler is None:
|
1381
|
+
raise FactoryException(error.what)
|
1382
|
+
value_dict._hdr = handler
|
1383
|
+
return value_dict.to_dict()
|
1384
|
+
|
1385
|
+
def from_dict(self, input_dict: Dict[str, any]):
|
1386
|
+
value_dict = ValueDict.from_dict(input_dict)
|
1387
|
+
error = Error()
|
1388
|
+
factorylib.lib.psrd_study_set_from_dict(self._hdr, value_dict.handler(),
|
1389
|
+
error.handler())
|
1390
|
+
if error.code != 0:
|
1391
|
+
raise FactoryException(error.what)
|
1392
|
+
|
1393
|
+
def add(self, obj: DataObject):
|
1394
|
+
if not isinstance(obj, DataObject):
|
1395
|
+
raise TypeError("obj must be a DataObject.")
|
1396
|
+
_err = Error()
|
1397
|
+
factorylib.lib.psrd_study_add(self._hdr,
|
1398
|
+
obj.handler(),
|
1399
|
+
_err.handler())
|
1400
|
+
if _err.code != 0:
|
1401
|
+
raise FactoryException(_err.what)
|
1402
|
+
|
1403
|
+
def remove(self, obj: DataObject):
|
1404
|
+
if not isinstance(obj, DataObject):
|
1405
|
+
raise TypeError("obj must be a DataObject.")
|
1406
|
+
_err = Error()
|
1407
|
+
factorylib.lib.psrd_study_remove(self._hdr,
|
1408
|
+
obj.handler(),
|
1409
|
+
_err.handler())
|
1410
|
+
if _err.code != 0:
|
1411
|
+
raise FactoryException(_err.what)
|
1412
|
+
|
1413
|
+
def get_all_objects(self) -> List[DataObject]:
|
1414
|
+
object_list = ValueList(False)
|
1415
|
+
error = Error()
|
1416
|
+
ref = factorylib.lib.psrd_study_get_all_objects(self._hdr,
|
1417
|
+
error.handler())
|
1418
|
+
if error.code != 0 or ref is None:
|
1419
|
+
raise FactoryException(error.what)
|
1420
|
+
object_list._hdr = ref
|
1421
|
+
return object_list.to_list()
|
1422
|
+
|
1423
|
+
def find(self, expression: str) -> List[DataObject]:
|
1424
|
+
object_list = ValueList(False)
|
1425
|
+
_err = Error()
|
1426
|
+
ref = factorylib.lib.psrd_study_find(self._hdr,
|
1427
|
+
_c_str(expression),
|
1428
|
+
_err.handler())
|
1429
|
+
if _err.code != 0 or ref is None:
|
1430
|
+
raise FactoryException(_err.what)
|
1431
|
+
object_list._hdr = ref
|
1432
|
+
return object_list.to_list()
|
1433
|
+
|
1434
|
+
def find_by_name(self, type_name: str, name: str) -> List[DataObject]:
|
1435
|
+
object_list = ValueList(False)
|
1436
|
+
_err = Error()
|
1437
|
+
if name.strip() == "":
|
1438
|
+
name = "*"
|
1439
|
+
expression = f"{type_name}.{name}"
|
1440
|
+
ref = factorylib.lib.psrd_study_find(self._hdr,
|
1441
|
+
_c_str(expression),
|
1442
|
+
_err.handler())
|
1443
|
+
if _err.code != 0 or ref is None:
|
1444
|
+
raise FactoryException(_err.what)
|
1445
|
+
object_list._hdr = ref
|
1446
|
+
return object_list.to_list()
|
1447
|
+
|
1448
|
+
def find_by_code(self, type_name: str, code: Optional[int] = None) -> List[DataObject]:
|
1449
|
+
if code is None:
|
1450
|
+
warnings.warn(DeprecationWarning("Starting from Factory 4.0.9 "
|
1451
|
+
"the second argument 'code' must be provided.\n"
|
1452
|
+
"Use find_by_code(type_name, code)"))
|
1453
|
+
|
1454
|
+
type_name, code_str = type_name.split(".", 1)
|
1455
|
+
code = int(code_str)
|
1456
|
+
|
1457
|
+
object_list = ValueList(False)
|
1458
|
+
_err = Error()
|
1459
|
+
ref = factorylib.lib.psrd_study_find_by_code(self._hdr,
|
1460
|
+
_c_str(type_name),
|
1461
|
+
code,
|
1462
|
+
_err.handler())
|
1463
|
+
if _err.code != 0 or ref is None:
|
1464
|
+
raise FactoryException(_err.what)
|
1465
|
+
object_list._hdr = ref
|
1466
|
+
return object_list.to_list()
|
1467
|
+
|
1468
|
+
def find_by_id(self, expression: str) -> List[DataObject]:
|
1469
|
+
object_list = ValueList(False)
|
1470
|
+
_err = Error()
|
1471
|
+
ref = factorylib.lib.psrd_study_find_by_id(self._hdr,
|
1472
|
+
_c_str(expression),
|
1473
|
+
_err.handler())
|
1474
|
+
if _err.code != 0 or ref is None:
|
1475
|
+
raise FactoryException(_err.what)
|
1476
|
+
object_list._hdr = ref
|
1477
|
+
return object_list.to_list()
|
1478
|
+
|
1479
|
+
def set(self, expression: str, value):
|
1480
|
+
_err = Error()
|
1481
|
+
_val = Value()
|
1482
|
+
_val.set(value)
|
1483
|
+
factorylib.lib.psrd_study_set_value(self._hdr,
|
1484
|
+
_c_str(expression),
|
1485
|
+
_bytes(expression),
|
1486
|
+
_val.handler(),
|
1487
|
+
_err.handler())
|
1488
|
+
if _err.code != 0:
|
1489
|
+
raise FactoryException(_err.what)
|
1490
|
+
|
1491
|
+
def set_at(self, expression: str, range_expr: Union[str, dt.datetime], value):
|
1492
|
+
if not isinstance(range_expr, (str, dt.datetime)):
|
1493
|
+
raise FactoryException("range_expr must be a string or datetime object.")
|
1494
|
+
_err = Error()
|
1495
|
+
_value = Value()
|
1496
|
+
_value.set(value)
|
1497
|
+
_range = Value()
|
1498
|
+
_range.set(range_expr)
|
1499
|
+
factorylib.lib.psrd_study_set_value_at(self._hdr,
|
1500
|
+
_c_str(expression),
|
1501
|
+
_bytes(expression),
|
1502
|
+
_range.handler(),
|
1503
|
+
_value.handler(),
|
1504
|
+
_err.handler())
|
1505
|
+
if _err.code != 0:
|
1506
|
+
raise FactoryException(_err.what)
|
1507
|
+
|
1508
|
+
def get_df(self, expression: str) -> "pandas.DataFrame":
|
1509
|
+
_err = Error()
|
1510
|
+
_df = DataFrame()
|
1511
|
+
factorylib.lib.psrd_study_get_table(self._hdr, _df.handler(),
|
1512
|
+
_c_str(expression),
|
1513
|
+
_bytes(expression),
|
1514
|
+
_err.handler())
|
1515
|
+
if _err.code != 0:
|
1516
|
+
raise FactoryException(_err.what)
|
1517
|
+
df_builder = _DataFrameBuilder()
|
1518
|
+
df_builder.build_dataframe(_df)
|
1519
|
+
return df_builder.build_pandas_dataframe()
|
1520
|
+
|
1521
|
+
def get_objects_values(self, object_type: str, columns: List[str]) -> "pandas.DataFrame":
|
1522
|
+
_err = Error()
|
1523
|
+
_table = DataFrame()
|
1524
|
+
columns_list = Value()
|
1525
|
+
columns_list.set(columns)
|
1526
|
+
factorylib.lib.psrd_study_get_objects_values(self._hdr, _table.handler(),
|
1527
|
+
_c_str(object_type),
|
1528
|
+
columns_list.handler(),
|
1529
|
+
_err.handler())
|
1530
|
+
if _err.code != 0:
|
1531
|
+
raise FactoryException(_err.what)
|
1532
|
+
df_builder = _DataFrameBuilder()
|
1533
|
+
df_builder.build_dataframe(_table)
|
1534
|
+
return df_builder.build_pandas_dataframe()
|
1535
|
+
|
1536
|
+
def get_objects_values_at(self, object_type: str, columns: List[str], range: Union[str, dt.datetime]) -> "pandas.DataFrame":
|
1537
|
+
_err = Error()
|
1538
|
+
_df = DataFrame()
|
1539
|
+
_range = Value()
|
1540
|
+
_range.set(range)
|
1541
|
+
columns_list = Value()
|
1542
|
+
columns_list.set(columns)
|
1543
|
+
factorylib.lib.psrd_study_get_objects_values_at(self._hdr, _df.handler(),
|
1544
|
+
_c_str(object_type),
|
1545
|
+
columns_list.handler(),
|
1546
|
+
_range.handler(),
|
1547
|
+
_err.handler())
|
1548
|
+
if _err.code != 0:
|
1549
|
+
raise FactoryException(_err.what)
|
1550
|
+
df_builder = _DataFrameBuilder()
|
1551
|
+
df_builder.build_dataframe(_df)
|
1552
|
+
return df_builder.build_pandas_dataframe()
|
1553
|
+
|
1554
|
+
def properties(self) -> Dict[str, PropertyDescription]:
|
1555
|
+
_err = Error()
|
1556
|
+
value = ctypes.c_long()
|
1557
|
+
factorylib.lib.psrd_study_property_description_count(self._hdr,
|
1558
|
+
ctypes.byref(value),
|
1559
|
+
_err.handler())
|
1560
|
+
if _err.code != 0:
|
1561
|
+
raise FactoryException(_err.what)
|
1562
|
+
var_count = int(value.value)
|
1563
|
+
properties = {}
|
1564
|
+
for i_var in range(var_count):
|
1565
|
+
var = PropertyDescription()
|
1566
|
+
ref = factorylib.lib.psrd_study_get_property_description(self._hdr,
|
1567
|
+
i_var,
|
1568
|
+
_err.handler())
|
1569
|
+
if _err.code != 0 or ref is None:
|
1570
|
+
raise FactoryException(_err.what)
|
1571
|
+
var._hdr = ref
|
1572
|
+
properties[var.name] = var
|
1573
|
+
return properties
|
1574
|
+
|
1575
|
+
def set_df(self, dataframe_like):
|
1576
|
+
if not _has_pandas():
|
1577
|
+
raise ModuleNotFoundError("pandas required.")
|
1578
|
+
dataframe_like = pandas.api.interchange.from_dataframe(dataframe_like)
|
1579
|
+
df_builder = _DataFrameBuilder()
|
1580
|
+
_df = df_builder.build_from_pandas(dataframe_like)
|
1581
|
+
_err = Error()
|
1582
|
+
factorylib.lib.psrd_study_set_table(self._hdr, _df.handler(),
|
1583
|
+
_err.handler())
|
1584
|
+
if _err.code != 0:
|
1585
|
+
raise FactoryException(_err.what)
|
1586
|
+
|
1587
|
+
def clear_values(self, expression: str):
|
1588
|
+
_err = Error()
|
1589
|
+
factorylib.lib.psrd_study_clear_values(self._hdr,
|
1590
|
+
_c_str(expression),
|
1591
|
+
_bytes(expression),
|
1592
|
+
_err.handler())
|
1593
|
+
if _err.code != 0:
|
1594
|
+
raise FactoryException(_err.what)
|
1595
|
+
|
1596
|
+
|
1597
|
+
def _is_int64(value):
|
1598
|
+
return isinstance(value, int) or isinstance(value, numpy.int64) or (isinstance(value, numpy.ndarray) and value.dtype == numpy.int64)
|
1599
|
+
|
1600
|
+
def _is_float32(value):
|
1601
|
+
return isinstance(value, (numpy.float32,)) or (isinstance(value, numpy.ndarray) and value.dtype == numpy.float32)
|
1602
|
+
|
1603
|
+
def _is_float64(value):
|
1604
|
+
return isinstance(value, (numpy.float64, float)) or (isinstance(value, numpy.ndarray) and value.dtype == numpy.float64)
|
1605
|
+
|
1606
|
+
|
1607
|
+
class _DataFrameBuilder:
|
1608
|
+
def __init__(self):
|
1609
|
+
self.indices: List[Optional[_TableColumn]] = []
|
1610
|
+
self.columns: List[Optional[_TableColumn]] = []
|
1611
|
+
self.column_names: List[str] = []
|
1612
|
+
self.index_names: List[str] = []
|
1613
|
+
self.column_types: List[int] = []
|
1614
|
+
self.index_types: List[int] = []
|
1615
|
+
self._not_built = True
|
1616
|
+
self._value: Optional[Value] = None
|
1617
|
+
self._err: Optional[Error] = None
|
1618
|
+
|
1619
|
+
def _pandas_dtype_to_column_type(self, dtype: str) -> int:
|
1620
|
+
if dtype == "object":
|
1621
|
+
return 0
|
1622
|
+
elif dtype == "int32":
|
1623
|
+
return 1
|
1624
|
+
elif dtype == "int64":
|
1625
|
+
return 2
|
1626
|
+
elif dtype == "float32":
|
1627
|
+
return 3
|
1628
|
+
elif dtype == "float64":
|
1629
|
+
return 4
|
1630
|
+
elif dtype == "string":
|
1631
|
+
return 5
|
1632
|
+
elif dtype == "datetime64[ns]":
|
1633
|
+
return 6
|
1634
|
+
else:
|
1635
|
+
raise FactoryException(f"Unsupported pandas dtype \"{dtype}\".")
|
1636
|
+
|
1637
|
+
def _polars_dtype_to_column_type(self, dtype: "polars.datatypes.classes.DataTypeClass") -> int:
|
1638
|
+
if dtype == polars.Int32:
|
1639
|
+
return 1
|
1640
|
+
if dtype == polars.Int64:
|
1641
|
+
return 2
|
1642
|
+
if dtype == polars.Float64:
|
1643
|
+
return 3
|
1644
|
+
if dtype == polars.Float64:
|
1645
|
+
return 4
|
1646
|
+
if dtype == polars.String:
|
1647
|
+
return 5
|
1648
|
+
else:
|
1649
|
+
raise FactoryException(f"Unsupported polars dtype \"{dtype}\".")
|
1650
|
+
|
1651
|
+
|
1652
|
+
def build_dataframe(self, df: "DataFrame"):
|
1653
|
+
self._err = Error()
|
1654
|
+
name_buffer_length = 200
|
1655
|
+
_columns_count = ctypes.c_long()
|
1656
|
+
factorylib.lib.psrd_table_columns_count(df.handler(),
|
1657
|
+
ctypes.byref(_columns_count),
|
1658
|
+
self._err.handler())
|
1659
|
+
if self._err.code != 0:
|
1660
|
+
raise FactoryException(self._err.what)
|
1661
|
+
columns_count = _columns_count.value
|
1662
|
+
|
1663
|
+
_rows_count = ctypes.c_long()
|
1664
|
+
factorylib.lib.psrd_table_rows_count(df.handler(),
|
1665
|
+
ctypes.byref(_rows_count),
|
1666
|
+
self._err.handler())
|
1667
|
+
if self._err.code != 0:
|
1668
|
+
raise FactoryException(self._err.what)
|
1669
|
+
rows_count = _rows_count.value
|
1670
|
+
|
1671
|
+
_indices_count = ctypes.c_long()
|
1672
|
+
factorylib.lib.psrd_table_index_count(df.handler(),
|
1673
|
+
ctypes.byref(_indices_count),
|
1674
|
+
self._err.handler())
|
1675
|
+
if self._err.code != 0:
|
1676
|
+
raise FactoryException(self._err.what)
|
1677
|
+
indices_count = _indices_count.value
|
1678
|
+
|
1679
|
+
value = Value()
|
1680
|
+
buffer = ctypes.create_string_buffer(name_buffer_length)
|
1681
|
+
|
1682
|
+
self.indices = [_TableColumn() for _ in range(indices_count)]
|
1683
|
+
for index in range(indices_count):
|
1684
|
+
factorylib.lib.psrd_table_index_get_name(df.handler(), index,
|
1685
|
+
buffer, name_buffer_length,
|
1686
|
+
self._err.handler())
|
1687
|
+
if self._err.code != 0:
|
1688
|
+
raise FactoryException(self._err.what)
|
1689
|
+
self.indices[index].name = _from_c_str(buffer.value)
|
1690
|
+
|
1691
|
+
self.indices[index].values = [None] * rows_count
|
1692
|
+
for i_row in range(0, rows_count):
|
1693
|
+
factorylib.lib.psrd_table_index_get_value(df.handler(), index,
|
1694
|
+
i_row, value.handler(),
|
1695
|
+
self._err.handler())
|
1696
|
+
if self._err.code != 0:
|
1697
|
+
raise FactoryException(self._err.what)
|
1698
|
+
self.indices[index].values[i_row] = value.get()
|
1699
|
+
|
1700
|
+
self.columns = [_TableColumn() for _ in range(columns_count)]
|
1701
|
+
for column in range(columns_count):
|
1702
|
+
factorylib.lib.psrd_table_column_get_name(df.handler(), column,
|
1703
|
+
buffer, name_buffer_length,
|
1704
|
+
self._err.handler())
|
1705
|
+
if self._err.code != 0:
|
1706
|
+
raise FactoryException(self._err.what)
|
1707
|
+
self.columns[column].name = _from_c_str(buffer.value)
|
1708
|
+
|
1709
|
+
self.columns[column].values = [None] * rows_count
|
1710
|
+
for row in range(rows_count):
|
1711
|
+
factorylib.lib.psrd_table_column_get_value(df.handler(),
|
1712
|
+
column, row,
|
1713
|
+
value.handler(),
|
1714
|
+
self._err.handler())
|
1715
|
+
if self._err.code != 0:
|
1716
|
+
raise FactoryException(self._err.what)
|
1717
|
+
self.columns[column].values[row] = value.get()
|
1718
|
+
self._not_built = False
|
1719
|
+
|
1720
|
+
def build_dataframe_of_integral_types(self, df: "DataFrame"):
|
1721
|
+
self._err = Error()
|
1722
|
+
name_buffer_length = 200
|
1723
|
+
_columns_count = ctypes.c_long()
|
1724
|
+
factorylib.lib.psrd_table_columns_count(df.handler(),
|
1725
|
+
ctypes.byref(_columns_count),
|
1726
|
+
self._err.handler())
|
1727
|
+
if self._err.code != 0:
|
1728
|
+
raise FactoryException(self._err.what)
|
1729
|
+
columns_count = _columns_count.value
|
1730
|
+
|
1731
|
+
_rows_count = ctypes.c_long()
|
1732
|
+
factorylib.lib.psrd_table_rows_count(df.handler(),
|
1733
|
+
ctypes.byref(_rows_count),
|
1734
|
+
self._err.handler())
|
1735
|
+
if self._err.code != 0:
|
1736
|
+
raise FactoryException(self._err.what)
|
1737
|
+
rows_count = _rows_count.value
|
1738
|
+
|
1739
|
+
_indices_count = ctypes.c_long()
|
1740
|
+
factorylib.lib.psrd_table_index_count(df.handler(),
|
1741
|
+
ctypes.byref(_indices_count),
|
1742
|
+
self._err.handler())
|
1743
|
+
if self._err.code != 0:
|
1744
|
+
raise FactoryException(self._err.what)
|
1745
|
+
indices_count = _indices_count.value
|
1746
|
+
|
1747
|
+
buffer = ctypes.create_string_buffer(name_buffer_length)
|
1748
|
+
|
1749
|
+
self.indices = [_TableColumn() for _ in range(indices_count)]
|
1750
|
+
for index in range(indices_count):
|
1751
|
+
factorylib.lib.psrd_table_index_get_name(df.handler(), index,
|
1752
|
+
buffer, name_buffer_length,
|
1753
|
+
self._err.handler())
|
1754
|
+
if self._err.code != 0:
|
1755
|
+
raise FactoryException(self._err.what)
|
1756
|
+
index_name = _from_c_str(buffer.value)
|
1757
|
+
self.indices[index].name = index_name
|
1758
|
+
self.indices[index].values = [None] * rows_count
|
1759
|
+
if index_name in ("date", "datetime"):
|
1760
|
+
array_values = (ctypes.c_longlong * rows_count)()
|
1761
|
+
factorylib.lib.psrd_table_index_get_date_values(df.handler(),
|
1762
|
+
index,
|
1763
|
+
array_values,
|
1764
|
+
self._err.handler())
|
1765
|
+
if self._err.code != 0:
|
1766
|
+
raise FactoryException(self._err.what)
|
1767
|
+
# convert array values to python datetime
|
1768
|
+
self.indices[index].values = [dt.datetime.utcfromtimestamp(value - _date_transform) for value in array_values]
|
1769
|
+
else:
|
1770
|
+
array_values = (ctypes.c_int * rows_count)()
|
1771
|
+
factorylib.lib.psrd_table_index_get_int32_values(df.handler(),
|
1772
|
+
index,
|
1773
|
+
array_values,
|
1774
|
+
self._err.handler())
|
1775
|
+
if self._err.code != 0:
|
1776
|
+
raise FactoryException(self._err.what)
|
1777
|
+
self.indices[index].values = array_values
|
1778
|
+
|
1779
|
+
self.columns = [_TableColumn() for _ in range(columns_count)]
|
1780
|
+
for column in range(columns_count):
|
1781
|
+
factorylib.lib.psrd_table_column_get_name(df.handler(), column,
|
1782
|
+
buffer, name_buffer_length,
|
1783
|
+
self._err.handler())
|
1784
|
+
if self._err.code != 0:
|
1785
|
+
raise FactoryException(self._err.what)
|
1786
|
+
self.columns[column].name = _from_c_str(buffer.value)
|
1787
|
+
|
1788
|
+
array_values = (ctypes.c_double * rows_count)()
|
1789
|
+
factorylib.lib.psrd_table_column_get_float64_values(df.handler(),
|
1790
|
+
column,
|
1791
|
+
array_values,
|
1792
|
+
self._err.handler())
|
1793
|
+
if self._err.code != 0:
|
1794
|
+
raise FactoryException(self._err.what)
|
1795
|
+
self.columns[column].values = array_values
|
1796
|
+
self._not_built = False
|
1797
|
+
|
1798
|
+
def build_pandas_dataframe(self, **kwargs) -> "pandas.DataFrame":
|
1799
|
+
use_object_dtype = kwargs.get("use_object_dtype", True)
|
1800
|
+
if not _has_pandas():
|
1801
|
+
raise ModuleNotFoundError("pandas required.")
|
1802
|
+
def convert_column_values(values):
|
1803
|
+
if isinstance(values, list):
|
1804
|
+
return values
|
1805
|
+
# Looks like ctype array, smells like ctype array
|
1806
|
+
if hasattr(values, "_length_") and hasattr(values, "_type_"):
|
1807
|
+
return numpy.ctypeslib.as_array(values)
|
1808
|
+
return values
|
1809
|
+
|
1810
|
+
data = {column.name: convert_column_values(column.values)
|
1811
|
+
for column in self.columns}
|
1812
|
+
if len(self.indices) > 1:
|
1813
|
+
# TODO: store index as rows of tuples
|
1814
|
+
index = pandas.MultiIndex.from_tuples(
|
1815
|
+
[tuple(self.indices[i].values[row] for i in range(len(self.indices))) for row in range(len(self.indices[0].values))],
|
1816
|
+
names=[index.name for index in self.indices])
|
1817
|
+
elif len(self.indices) == 1:
|
1818
|
+
index_value_type = type(self.indices[0].values[0]) if len(self.indices[0].values) > 0 else object
|
1819
|
+
if index_value_type == dt.datetime:
|
1820
|
+
index = pandas.DatetimeIndex(self.indices[0].values, name=self.indices[0].name)
|
1821
|
+
else:
|
1822
|
+
if index_value_type == DataObject:
|
1823
|
+
index_value_type = object
|
1824
|
+
index = pandas.Index(tuple(self.indices[0].values), dtype=index_value_type, name=self.indices[0].name)
|
1825
|
+
else:
|
1826
|
+
index = None
|
1827
|
+
if use_object_dtype:
|
1828
|
+
return pandas.DataFrame(data=data, index=index, dtype=object)
|
1829
|
+
else:
|
1830
|
+
return pandas.DataFrame(data=data, index=index)
|
1831
|
+
|
1832
|
+
def build_from_pandas(self, table_data: "pandas.DataFrame") -> "DataFrame":
|
1833
|
+
# check if the table has indices and if its multi-index or common index
|
1834
|
+
if isinstance(table_data.index, pandas.MultiIndex):
|
1835
|
+
table_data_indices = table_data.index.levels
|
1836
|
+
elif isinstance(table_data.index, pandas.Index) and not table_data.index.empty:
|
1837
|
+
table_data_indices = [table_data.index]
|
1838
|
+
else:
|
1839
|
+
table_data_indices = []
|
1840
|
+
|
1841
|
+
self.column_names = table_data.columns
|
1842
|
+
self.index_names = [index.name for index in table_data_indices]
|
1843
|
+
self.column_types = [self._pandas_dtype_to_column_type(dtype) for dtype in table_data.dtypes]
|
1844
|
+
self.index_types = [self._pandas_dtype_to_column_type(index.dtype) for index in table_data_indices]
|
1845
|
+
replaced_name = False
|
1846
|
+
for i, name in enumerate(self.index_names):
|
1847
|
+
if name is None:
|
1848
|
+
self.index_names[i] = 'date'
|
1849
|
+
replaced_name = True
|
1850
|
+
rows = len(table_data.index)
|
1851
|
+
_df = self._pre_build_generic(rows, self.index_types, self.column_types)
|
1852
|
+
|
1853
|
+
test_conversion_types = {
|
1854
|
+
pandas.api.types.is_integer_dtype: numpy.int32,
|
1855
|
+
_is_int64: numpy.int64,
|
1856
|
+
_is_float32: numpy.float32,
|
1857
|
+
_is_float64: numpy.float64,
|
1858
|
+
pandas.api.types.is_datetime64_any_dtype: numpy.datetime64,
|
1859
|
+
}
|
1860
|
+
convert_to_ctype = {
|
1861
|
+
numpy.int32: ctypes.c_int32,
|
1862
|
+
numpy.int64: ctypes.c_int64,
|
1863
|
+
numpy.float32: ctypes.c_float,
|
1864
|
+
numpy.float64: ctypes.c_double,
|
1865
|
+
numpy.datetime64: ctypes.c_longlong,
|
1866
|
+
|
1867
|
+
}
|
1868
|
+
|
1869
|
+
# Check column value types - if they support, call efficient set methods
|
1870
|
+
column_convert_to = {}
|
1871
|
+
column_fast_set = {}
|
1872
|
+
for i_column, column_name in enumerate(table_data.columns):
|
1873
|
+
column_values = table_data[column_name]
|
1874
|
+
column_fast_set[column_name] = False
|
1875
|
+
for test_func, convert_to_type in test_conversion_types.items():
|
1876
|
+
if test_func(column_values):
|
1877
|
+
column_convert_to[column_name] = convert_to_type
|
1878
|
+
column_fast_set[column_name] = True
|
1879
|
+
break
|
1880
|
+
|
1881
|
+
if replaced_name:
|
1882
|
+
for i, name in enumerate(self.index_names):
|
1883
|
+
if name == "date":
|
1884
|
+
self.index_names[i] = None
|
1885
|
+
# check index value types
|
1886
|
+
index_convert_to = {}
|
1887
|
+
index_fast_set = {}
|
1888
|
+
for i_index, index_name in enumerate(self.index_names):
|
1889
|
+
index_fast_set[index_name] = False
|
1890
|
+
index_values = table_data.index.get_level_values(index_name)
|
1891
|
+
for test_func, convert_to_type in test_conversion_types.items():
|
1892
|
+
if test_func(index_values):
|
1893
|
+
index_convert_to[index_name] = convert_to_type
|
1894
|
+
index_fast_set[index_name] = True
|
1895
|
+
break
|
1896
|
+
|
1897
|
+
# replace None as index name with "date", the default index type.
|
1898
|
+
for i_index, index_name in enumerate(self.index_names):
|
1899
|
+
if index_name is None:
|
1900
|
+
self.index_names[i_index] = "date"
|
1901
|
+
|
1902
|
+
for i_index, index_name in enumerate(self.index_names):
|
1903
|
+
if index_name in index_convert_to.keys():
|
1904
|
+
convert_to_type = index_convert_to[index_name]
|
1905
|
+
else:
|
1906
|
+
convert_to_type = None
|
1907
|
+
if isinstance(table_data.index, pandas.MultiIndex):
|
1908
|
+
index_values = table_data.index.get_level_values(index_name).to_numpy(dtype=convert_to_type)
|
1909
|
+
else:
|
1910
|
+
index_values = table_data.index.to_numpy(dtype=convert_to_type)
|
1911
|
+
if index_name in index_fast_set.keys() and index_fast_set[index_name]:
|
1912
|
+
if convert_to_type == numpy.datetime64:
|
1913
|
+
# convert index_values to utc timezone and then to timestamp
|
1914
|
+
# TODO: check if original dataframe values is unaltered
|
1915
|
+
index_values = index_values.astype('datetime64[s]').astype(dt.datetime)
|
1916
|
+
# for each value, convert to timestamp
|
1917
|
+
for ix, x in enumerate(index_values):
|
1918
|
+
index_values[ix] = int(x.replace(tzinfo=dt.timezone.utc).timestamp() + _date_transform)
|
1919
|
+
# convert to int64
|
1920
|
+
index_values = index_values.astype(numpy.int64)
|
1921
|
+
ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1922
|
+
factorylib.lib.psrd_table_index_set_date_values(_df.handler(),
|
1923
|
+
i_index,
|
1924
|
+
ptr,
|
1925
|
+
self._err.handler())
|
1926
|
+
if self._err.code != 0:
|
1927
|
+
raise FactoryException(self._err.what)
|
1928
|
+
elif convert_to_type == numpy.int32:
|
1929
|
+
ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1930
|
+
factorylib.lib.psrd_table_index_set_int32_values(_df.handler(),
|
1931
|
+
i_index,
|
1932
|
+
ptr,
|
1933
|
+
self._err.handler())
|
1934
|
+
if self._err.code != 0:
|
1935
|
+
raise FactoryException(self._err.what)
|
1936
|
+
elif convert_to_type == numpy.int64:
|
1937
|
+
ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1938
|
+
factorylib.lib.psrd_table_index_set_int64_values(_df.handler(),
|
1939
|
+
i_index,
|
1940
|
+
ptr,
|
1941
|
+
self._err.handler())
|
1942
|
+
if self._err.code != 0:
|
1943
|
+
raise FactoryException(self._err.what)
|
1944
|
+
elif convert_to_type == numpy.float32:
|
1945
|
+
ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1946
|
+
factorylib.lib.psrd_table_index_set_float32_values(_df.handler(),
|
1947
|
+
i_index,
|
1948
|
+
ptr,
|
1949
|
+
self._err.handler())
|
1950
|
+
if self._err.code != 0:
|
1951
|
+
raise FactoryException(self._err.what)
|
1952
|
+
elif convert_to_type == numpy.float64:
|
1953
|
+
ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1954
|
+
factorylib.lib.psrd_table_index_set_float64_values(_df.handler(),
|
1955
|
+
i_index,
|
1956
|
+
ptr,
|
1957
|
+
self._err.handler())
|
1958
|
+
if self._err.code != 0:
|
1959
|
+
raise FactoryException(self._err.what)
|
1960
|
+
else:
|
1961
|
+
raise FactoryException("Unsupported index type: " + str(convert_to_type))
|
1962
|
+
else:
|
1963
|
+
for i_row, column_value in enumerate(index_values):
|
1964
|
+
self._value.set(column_value)
|
1965
|
+
factorylib.lib.psrd_table_index_set_value(_df.handler(),
|
1966
|
+
i_index,
|
1967
|
+
i_row,
|
1968
|
+
self._value.handler(),
|
1969
|
+
self._err.handler())
|
1970
|
+
if self._err.code != 0:
|
1971
|
+
raise FactoryException(self._err.what)
|
1972
|
+
|
1973
|
+
for i_column, column_name in enumerate(self.column_names):
|
1974
|
+
if column_name in column_convert_to.keys():
|
1975
|
+
convert_to_type = column_convert_to[column_name]
|
1976
|
+
else:
|
1977
|
+
convert_to_type = None
|
1978
|
+
column_values = table_data[column_name].to_numpy(dtype=convert_to_type)
|
1979
|
+
if column_name in column_fast_set.keys() and column_fast_set[column_name]:
|
1980
|
+
if convert_to_type == numpy.float32:
|
1981
|
+
ptr = column_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1982
|
+
factorylib.lib.psrd_table_column_set_float32_values(_df.handler(),
|
1983
|
+
i_column,
|
1984
|
+
ptr,
|
1985
|
+
self._err.handler())
|
1986
|
+
if self._err.code != 0:
|
1987
|
+
raise FactoryException(self._err.code)
|
1988
|
+
if convert_to_type == numpy.float64:
|
1989
|
+
ptr = column_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1990
|
+
factorylib.lib.psrd_table_column_set_float64_values(_df.handler(),
|
1991
|
+
i_column,
|
1992
|
+
ptr,
|
1993
|
+
self._err.handler())
|
1994
|
+
if self._err.code != 0:
|
1995
|
+
raise FactoryException(self._err.what)
|
1996
|
+
elif convert_to_type == numpy.int32:
|
1997
|
+
ptr = column_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
1998
|
+
factorylib.lib.psrd_table_column_set_int32_values(_df.handler(),
|
1999
|
+
i_column,
|
2000
|
+
ptr,
|
2001
|
+
self._err.handler())
|
2002
|
+
if self._err.code != 0:
|
2003
|
+
raise FactoryException(self._err.what)
|
2004
|
+
elif convert_to_type == numpy.int64:
|
2005
|
+
ptr = column_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
|
2006
|
+
factorylib.lib.psrd_table_column_set_int64_values(_df.handler(),
|
2007
|
+
i_column,
|
2008
|
+
ptr,
|
2009
|
+
self._err.handler())
|
2010
|
+
if self._err.code != 0:
|
2011
|
+
raise FactoryException(self._err.what)
|
2012
|
+
else:
|
2013
|
+
column_values = table_data[column_name]
|
2014
|
+
for i_row, column_value in enumerate(column_values):
|
2015
|
+
self._value.set(column_value)
|
2016
|
+
factorylib.lib.psrd_table_column_set_value(_df.handler(),
|
2017
|
+
i_column,
|
2018
|
+
i_row,
|
2019
|
+
self._value.handler(),
|
2020
|
+
self._err.handler())
|
2021
|
+
if self._err.code != 0:
|
2022
|
+
raise FactoryException(self._err.what)
|
2023
|
+
return _df
|
2024
|
+
|
2025
|
+
|
2026
|
+
def build_polars_dataframe(self, **kwargs) -> "polars.DataFrame":
|
2027
|
+
use_object_dtype = kwargs.get("use_object_dtype", True)
|
2028
|
+
if not _has_polars():
|
2029
|
+
raise ModuleNotFoundError("polars required.")
|
2030
|
+
def convert_column_values(column_name:str, values):
|
2031
|
+
if isinstance(values, list):
|
2032
|
+
return values
|
2033
|
+
# Looks like ctype array, smells like ctype array
|
2034
|
+
if hasattr(values, "_length_") and hasattr(values, "_type_"):
|
2035
|
+
return polars.Series(column_name, numpy.ctypeslib.as_array(values))
|
2036
|
+
return values
|
2037
|
+
|
2038
|
+
data = {column.name: convert_column_values(column.name, column.values)
|
2039
|
+
for column in self.indices + self.columns}
|
2040
|
+
if use_object_dtype:
|
2041
|
+
return polars.DataFrame(data=data, dtype=object)
|
2042
|
+
else:
|
2043
|
+
return polars.DataFrame(data=data)
|
2044
|
+
|
2045
|
+
def build_from_polars(self, table_data: "polars.DataFrame") -> "DataFrame":
|
2046
|
+
# check if the table has indices and if its multi-index or common index
|
2047
|
+
_index_names = ("year", "week", "month", "hour", "scenario", "block", "stage")
|
2048
|
+
column_index = 0
|
2049
|
+
data_columns = table_data.columns[:]
|
2050
|
+
index_columns = []
|
2051
|
+
while column_index < len(data_columns):
|
2052
|
+
if data_columns[column_index] in _index_names:
|
2053
|
+
index_columns.append(data_columns.pop(column_index))
|
2054
|
+
continue
|
2055
|
+
column_index += 1
|
2056
|
+
self.column_types = [self._polars_dtype_to_column_type(table_data[column_name].dtype) for column_name in data_columns]
|
2057
|
+
self.index_types = [self._polars_dtype_to_column_type(table_data[index_name].dtype) for index_name in index_columns]
|
2058
|
+
|
2059
|
+
self.column_names = data_columns
|
2060
|
+
self.index_names = index_columns
|
2061
|
+
rows = table_data.height
|
2062
|
+
_df = self._pre_build_generic(rows, self.index_types, self.column_types)
|
2063
|
+
|
2064
|
+
for i_row, all_row_values in enumerate(table_data.iter_rows()):
|
2065
|
+
index = all_row_values[:len(index_columns)]
|
2066
|
+
row_values = all_row_values[len(index_columns):]
|
2067
|
+
self._set_row_values(_df, i_row, index, row_values)
|
2068
|
+
return _df
|
2069
|
+
|
2070
|
+
def _pre_build_generic(self, rows: int, index_types: List[int], column_types: List[int]) -> "DataFrame":
|
2071
|
+
_df = DataFrame()
|
2072
|
+
self._err = Error()
|
2073
|
+
self._value = Value()
|
2074
|
+
|
2075
|
+
factorylib.lib.psrd_table_resize(_df.handler(), rows,
|
2076
|
+
self._err.handler())
|
2077
|
+
if self._err.code != 0:
|
2078
|
+
raise FactoryException(self._err.what)
|
2079
|
+
|
2080
|
+
for i_index, index_type in enumerate(index_types):
|
2081
|
+
factorylib.lib.psrd_table_configure_index(_df.handler(),
|
2082
|
+
i_index,
|
2083
|
+
index_type,
|
2084
|
+
self._err.handler())
|
2085
|
+
if self._err.code != 0:
|
2086
|
+
raise FactoryException(self._err.what)
|
2087
|
+
for i_column, column_type in enumerate(column_types):
|
2088
|
+
factorylib.lib.psrd_table_configure_column(_df.handler(),
|
2089
|
+
i_column,
|
2090
|
+
column_type,
|
2091
|
+
self._err.handler())
|
2092
|
+
if self._err.code != 0:
|
2093
|
+
raise FactoryException(self._err.what)
|
2094
|
+
|
2095
|
+
# Set column names
|
2096
|
+
for i_column, column_name in enumerate(self.column_names):
|
2097
|
+
factorylib.lib.psrd_table_column_set_name(_df.handler(),
|
2098
|
+
i_column,
|
2099
|
+
_c_str(column_name),
|
2100
|
+
_bytes(column_name),
|
2101
|
+
self._err.handler())
|
2102
|
+
if self._err.code != 0:
|
2103
|
+
raise FactoryException(self._err.what)
|
2104
|
+
|
2105
|
+
# Set index names
|
2106
|
+
for i_index, index_name in enumerate(self.index_names):
|
2107
|
+
factorylib.lib.psrd_table_index_set_name(_df.handler(),
|
2108
|
+
i_index,
|
2109
|
+
_c_str(index_name),
|
2110
|
+
_bytes(index_name),
|
2111
|
+
self._err.handler())
|
2112
|
+
if self._err.code != 0:
|
2113
|
+
raise FactoryException(self._err.what)
|
2114
|
+
|
2115
|
+
return _df
|
2116
|
+
|
2117
|
+
def _set_row_values(self, df: "DataFrame", i_row: int, index_values: List[Union[int, float, str]], column_values: List[Union[int, float, str]]):
|
2118
|
+
self._value = Value()
|
2119
|
+
for i_index, index_value in enumerate(index_values):
|
2120
|
+
self._value.set(index_value)
|
2121
|
+
factorylib.lib.psrd_table_index_set_value(df.handler(),
|
2122
|
+
i_index,
|
2123
|
+
i_row,
|
2124
|
+
self._value.handler(),
|
2125
|
+
self._err.handler())
|
2126
|
+
if self._err.code != 0:
|
2127
|
+
raise FactoryException(self._err.what)
|
2128
|
+
|
2129
|
+
for i_column, column_value in enumerate(column_values):
|
2130
|
+
self._value.set(column_value)
|
2131
|
+
factorylib.lib.psrd_table_column_set_value(df.handler(),
|
2132
|
+
i_column,
|
2133
|
+
i_row,
|
2134
|
+
self._value.handler(),
|
2135
|
+
self._err.handler())
|
2136
|
+
if self._err.code != 0:
|
2137
|
+
raise FactoryException(self._err.what)
|
2138
|
+
|
2139
|
+
|
2140
|
+
class DataFrame(_BaseObject):
|
2141
|
+
def __init__(self):
|
2142
|
+
super().__init__()
|
2143
|
+
self._hdr = factorylib.lib.psrd_new_table()
|
2144
|
+
self._not_built = True
|
2145
|
+
|
2146
|
+
def __del__(self):
|
2147
|
+
if self._hdr is not None:
|
2148
|
+
factorylib.lib.psrd_free_table(self._hdr)
|
2149
|
+
|
2150
|
+
@staticmethod
|
2151
|
+
def load_from_file(input_file: Union[str, pathlib.Path], options: Optional[Union[dict, Value, DataObject]] = None) -> "DataFrame":
|
2152
|
+
input_file = str(input_file)
|
2153
|
+
_check_initialized()
|
2154
|
+
_err = Error()
|
2155
|
+
table = DataFrame()
|
2156
|
+
options_value = _get_arg_object(options)
|
2157
|
+
factorylib.lib.psrd_table_load(table.handler(),
|
2158
|
+
_c_str(input_file),
|
2159
|
+
_bytes(input_file),
|
2160
|
+
options_value.handler(),
|
2161
|
+
_err.handler())
|
2162
|
+
if _err.code != 0:
|
2163
|
+
raise FactoryException(_err.what)
|
2164
|
+
return table
|
2165
|
+
|
2166
|
+
@staticmethod
|
2167
|
+
def from_dataframe(df: Union["pandas.DataFrame", "polars.DataFrame"], **kwargs) -> "DataFrame":
|
2168
|
+
_check_initialized()
|
2169
|
+
df_builder = _DataFrameBuilder()
|
2170
|
+
if _has_pandas() and isinstance(df, pandas.DataFrame):
|
2171
|
+
dataframe_like = pandas.api.interchange.from_dataframe(df)
|
2172
|
+
return df_builder.build_from_pandas(dataframe_like)
|
2173
|
+
if _has_polars() and isinstance(df, polars.DataFrame):
|
2174
|
+
dataframe_like = polars.from_dataframe(df)
|
2175
|
+
# FIXME: needs auto tests.
|
2176
|
+
return df_builder.build_from_polars(dataframe_like)
|
2177
|
+
raise ImportError("Pandas or polars is not available. Please install pandas to use this feature.")
|
2178
|
+
|
2179
|
+
def save(self, output_file: Union[str, pathlib.Path], options: Optional[Union[dict, Value, DataObject]] = None):
|
2180
|
+
output_file = str(output_file)
|
2181
|
+
_err = Error()
|
2182
|
+
options_value = _get_arg_object(options)
|
2183
|
+
factorylib.lib.psrd_table_save(self._hdr, _c_str(output_file),
|
2184
|
+
_bytes(output_file),
|
2185
|
+
options_value.handler(),
|
2186
|
+
_err.handler())
|
2187
|
+
if _err.code != 0:
|
2188
|
+
raise FactoryException(_err.what)
|
2189
|
+
|
2190
|
+
def to_pandas(self) -> "pandas.DataFrame":
|
2191
|
+
df_builder = _DataFrameBuilder()
|
2192
|
+
df_builder.build_dataframe_of_integral_types(self)
|
2193
|
+
return df_builder.build_pandas_dataframe(use_object_dtype=False)
|
2194
|
+
|
2195
|
+
def to_polars(self) -> "polars.DataFrame":
|
2196
|
+
df_builder = _DataFrameBuilder()
|
2197
|
+
df_builder.build_dataframe_of_integral_types(self)
|
2198
|
+
return df_builder.build_polars_dataframe(use_object_dtype=False)
|
2199
|
+
|
2200
|
+
|
2201
|
+
def load_dataframe(input_file: Union[str, pathlib.Path], **kwargs) -> DataFrame:
|
2202
|
+
options = kwargs.get("options", None)
|
2203
|
+
return DataFrame.load_from_file(input_file, options)
|
2204
|
+
|
2205
|
+
|
2206
|
+
def create_dataframe(data: "pandas.DataFrame", **kwargs) -> DataFrame:
|
2207
|
+
return DataFrame.from_dataframe(data, **kwargs)
|
2208
|
+
|
2209
|
+
|
2210
|
+
def _load_library():
|
2211
|
+
global _loaded
|
2212
|
+
global _loaded_lock
|
2213
|
+
with _loaded_lock:
|
2214
|
+
factorylib.initialize()
|
2215
|
+
_loaded = True
|
2216
|
+
return _loaded
|
2217
|
+
|
2218
|
+
|
2219
|
+
|
2220
|
+
def _initialize():
|
2221
|
+
global _initialized
|
2222
|
+
global _initialized_lock
|
2223
|
+
with _initialized_lock:
|
2224
|
+
_check_loaded()
|
2225
|
+
_err = Error()
|
2226
|
+
|
2227
|
+
# Set binding info
|
2228
|
+
map_prop_values = {
|
2229
|
+
"NULL_TYPE": "None",
|
2230
|
+
"LIST_TYPE": "list",
|
2231
|
+
"INDEX_STARTS_AT_ZERO": True,
|
2232
|
+
"NAME": "Python",
|
2233
|
+
"VERSION": f"{sys.version}",
|
2234
|
+
"EXE": f"{sys.executable}",
|
2235
|
+
"LIB": f"{factorylib.get_lib_path()}",
|
2236
|
+
"BASE_PREFIX": f"{sys.base_prefix}",
|
2237
|
+
"REAL_PREFIX": f"{sys.prefix}",
|
2238
|
+
}
|
2239
|
+
for prop, value in map_prop_values.items():
|
2240
|
+
_value = Value()
|
2241
|
+
_value.set(value)
|
2242
|
+
factorylib.lib.psrd_set_binding_property(_c_str(prop),
|
2243
|
+
_bytes(prop),
|
2244
|
+
_value.handler(),
|
2245
|
+
_err.handler())
|
2246
|
+
if _err.code != 0:
|
2247
|
+
raise FactoryException(_err.what)
|
2248
|
+
|
2249
|
+
# Where to look for pmd and pmk files
|
2250
|
+
common_path = os.path.dirname(__file__)
|
2251
|
+
factorylib.lib.psrd_initialize(_c_str(common_path),
|
2252
|
+
_bytes(common_path),
|
2253
|
+
_err.handler())
|
2254
|
+
if _err.code != 0:
|
2255
|
+
raise FactoryException(_err.what)
|
2256
|
+
_initialized = True
|
2257
|
+
|
2258
|
+
|
2259
|
+
def _unload():
|
2260
|
+
_err = Error()
|
2261
|
+
factorylib.lib.psrd_unload(_err.handler())
|
2262
|
+
if _err.code != 0:
|
2263
|
+
raise FactoryException(_err.what)
|
2264
|
+
|
2265
|
+
|
2266
|
+
def help(context: str = "") -> str:
|
2267
|
+
_err = Error()
|
2268
|
+
size = factorylib.lib.psrd_help(_c_str(context), _bytes(context),
|
2269
|
+
None, 0, _err.handler())
|
2270
|
+
if _err.code != 0:
|
2271
|
+
raise FactoryException(_err.what)
|
2272
|
+
buffer = ctypes.create_string_buffer(size)
|
2273
|
+
factorylib.lib.psrd_help(_c_str(context), _bytes(context),
|
2274
|
+
buffer, size, _err.handler())
|
2275
|
+
if _err.code != 0:
|
2276
|
+
raise FactoryException(_err.what)
|
2277
|
+
return _from_c_str(buffer.value)
|
2278
|
+
|
2279
|
+
|
2280
|
+
def create_study(*args, **kwargs) -> Study:
|
2281
|
+
blocks = kwargs.get("blocks", None)
|
2282
|
+
models = kwargs.get("models", None)
|
2283
|
+
context = kwargs.get("context", None) if len(args) == 0 else args[0]
|
2284
|
+
profile = kwargs.get("profile", None)
|
2285
|
+
if models is None and profile is not None and len(profile) > 0:
|
2286
|
+
models = [profile, ]
|
2287
|
+
profile_or_context = models if models is not None and len(models) > 0 \
|
2288
|
+
else context
|
2289
|
+
return Study.create_object(profile_or_context, blocks)
|
2290
|
+
|
2291
|
+
|
2292
|
+
def load_study(study_path: Union[str, pathlib.Path],
|
2293
|
+
profile_or_context: Union[str, Context, None] = None,
|
2294
|
+
options: Optional[DataObject] = None) -> Study:
|
2295
|
+
settings_only = False
|
2296
|
+
return Study.load(study_path, profile_or_context, settings_only, options)
|
2297
|
+
|
2298
|
+
|
2299
|
+
def load_study_settings(study_path: Union[str, pathlib.Path],
|
2300
|
+
profile_or_context: Union[str, Context, None] = None,
|
2301
|
+
options: Optional[DataObject] = None) -> Study:
|
2302
|
+
settings_only = True
|
2303
|
+
return Study.load(study_path, profile_or_context, settings_only, options)
|
2304
|
+
|
2305
|
+
|
2306
|
+
def create(class_name: str,
|
2307
|
+
profile_or_context: Union[str, Context, None] = None) -> Optional[DataObject]:
|
2308
|
+
_check_initialized()
|
2309
|
+
obj = DataObject()
|
2310
|
+
_err = Error()
|
2311
|
+
context = _get_context(profile_or_context, None) \
|
2312
|
+
if class_name != "Context" else None
|
2313
|
+
context_hdr = context.handler() if context is not None else None
|
2314
|
+
ref = factorylib.lib.psrd_create(_c_str(class_name),
|
2315
|
+
context_hdr,
|
2316
|
+
_err.handler())
|
2317
|
+
if _err.code != 0 or ref is None:
|
2318
|
+
raise FactoryException(_err.what)
|
2319
|
+
obj._hdr = ref
|
2320
|
+
return obj
|
2321
|
+
|
2322
|
+
|
2323
|
+
def get_default_context() -> "Context":
|
2324
|
+
_check_initialized()
|
2325
|
+
return Context.default_context()
|
2326
|
+
|
2327
|
+
|
2328
|
+
def get_new_context() -> "Context":
|
2329
|
+
_check_initialized()
|
2330
|
+
return Context.create()
|
2331
|
+
|
2332
|
+
|
2333
|
+
def get_default_encoding() -> str:
|
2334
|
+
return _preferred_encoding
|
2335
|
+
|
2336
|
+
|
2337
|
+
def set_default_encoding(encoding: str):
|
2338
|
+
global _preferred_encoding
|
2339
|
+
_preferred_encoding = encoding
|