psr-factory 4.0.27__py3-none-win_amd64.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/factory/api.py ADDED
@@ -0,0 +1,1950 @@
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
+ INT = 0
133
+ FLOAT = 1
134
+ BOOL = 2
135
+ STRING = 3
136
+ DATE = 4
137
+ OBJECT = 5
138
+ LIST = 6
139
+ NULL = 7
140
+
141
+
142
+ def _version_long() -> str:
143
+ _check_loaded()
144
+ size = 200
145
+ buffer = ctypes.create_string_buffer(size)
146
+ status = factorylib.lib.psrd_version_long(buffer, size)
147
+ if status == 0:
148
+ return _from_c_str(buffer.value)
149
+ return ""
150
+
151
+
152
+ def _version_short() -> str:
153
+ _check_loaded()
154
+ size = 200
155
+ buffer = ctypes.create_string_buffer(size)
156
+ status = factorylib.lib.psrd_version_short(buffer, size)
157
+ if status == 0:
158
+ return _from_c_str(buffer.value)
159
+ return ""
160
+
161
+
162
+ def version() -> str:
163
+ """Returns module version."""
164
+ return _version_long()
165
+
166
+
167
+ def build_version() -> str:
168
+ """Returns short library version."""
169
+ return _version_short()
170
+
171
+
172
+ def get_log_level() -> LogLevel:
173
+ """Get log level."""
174
+ _check_loaded()
175
+ log_level = ctypes.c_int()
176
+ code = factorylib.lib.psrd_get_log_level(ctypes.byref(log_level))
177
+ if code != 0:
178
+ raise FactoryException("Error getting log level")
179
+ return LogLevel(log_level.value)
180
+
181
+
182
+ def set_log_level(log_level: LogLevel):
183
+ """Set log level."""
184
+ if not isinstance(log_level, LogLevel):
185
+ raise TypeError("log_level must be an instance of LogLevel")
186
+ _check_loaded()
187
+ as_int = log_level.value
188
+ code = factorylib.lib.psrd_set_log_level(as_int)
189
+ if code != 0:
190
+ raise FactoryException("Error setting log level")
191
+
192
+
193
+ def set_debug_mode(value: Union[bool, int]):
194
+ """Set debug mode."""
195
+ _check_loaded()
196
+ if isinstance(value, bool):
197
+ value = 1 if value else 0
198
+ code = factorylib.lib.psrd_set_debug_mode(value)
199
+ if code != 0:
200
+ raise FactoryException("Error setting debug mode")
201
+
202
+
203
+ def _get_context(models_or_context: Union[str, list, "Context", None],
204
+ blocks: Optional[int] = None):
205
+ if isinstance(models_or_context, Context):
206
+ context = models_or_context
207
+ elif isinstance(models_or_context, (str, list)) or models_or_context is None:
208
+ context = Context.create()
209
+ if isinstance(models_or_context, list):
210
+ context.set("Models", models_or_context)
211
+ elif isinstance(models_or_context, str):
212
+ context.set("Models", [models_or_context, ])
213
+ else:
214
+ raise TypeError("Unexpected type for profile_or_context argument.")
215
+ if blocks is not None and isinstance(blocks, int):
216
+ context.set("Blocks", blocks)
217
+ return context
218
+
219
+
220
+ class _BaseObject:
221
+ def __init__(self):
222
+ self._hdr = None
223
+
224
+ def handler(self):
225
+ return self._hdr
226
+
227
+ def __hash__(self):
228
+ return self._hdr
229
+
230
+
231
+ class Error(_BaseObject):
232
+ def __init__(self):
233
+ super().__init__()
234
+ self._hdr = factorylib.lib.psrd_new_error()
235
+
236
+ @property
237
+ def code(self) -> int:
238
+ return factorylib.lib.psrd_error_code(self._hdr)
239
+
240
+ @code.setter
241
+ def code(self, value):
242
+ raise AttributeError("do not set code")
243
+
244
+ @code.deleter
245
+ def code(self):
246
+ raise AttributeError("do not delete code")
247
+
248
+ @property
249
+ def what(self) -> str:
250
+ size = factorylib.lib.psrd_error_message(self._hdr, None, 0)
251
+ if size <= 0:
252
+ size = 800
253
+ buffer = ctypes.create_string_buffer(size)
254
+ status = factorylib.lib.psrd_error_message(self._hdr,
255
+ buffer, size)
256
+ if status == 0:
257
+ return _from_c_str(buffer.value)
258
+ return ""
259
+
260
+ @what.deleter
261
+ def what(self):
262
+ raise AttributeError("do not delete what")
263
+
264
+ @what.setter
265
+ def what(self, value):
266
+ raise AttributeError("do not set what")
267
+
268
+ def __del__(self):
269
+ if self._hdr is not None:
270
+ factorylib.lib.psrd_free_error(self._hdr)
271
+
272
+ def __repr__(self):
273
+ return f"Error object with code \"{self.code}\" and message:\n" \
274
+ f"{self.what}"
275
+
276
+ def __str__(self):
277
+ return self.what
278
+
279
+
280
+ class _TableColumn:
281
+ def __init__(self):
282
+ self.name = ""
283
+ # values: a pure Python list or a ctypes array
284
+ self.values: Union[list, ctypes.c_int, ctypes.c_long, ctypes.c_float, ctypes.c_double] = []
285
+
286
+ def __len__(self):
287
+ return len(self.values)
288
+
289
+
290
+ class ValueList(_BaseObject):
291
+ def __init__(self, initialized=True):
292
+ super().__init__()
293
+ self._hdr = factorylib.lib.psrd_new_list() if initialized else None
294
+
295
+ def __del__(self):
296
+ if self._hdr is not None:
297
+ factorylib.lib.psrd_free_list(self._hdr)
298
+
299
+ @staticmethod
300
+ def from_list(value: Union[List, Tuple]):
301
+ _err = Error()
302
+ list_obj = ValueList()
303
+ for obj in value:
304
+ val_obj = Value()
305
+ val_obj.set(obj)
306
+ factorylib.lib.psrd_list_append(list_obj.handler(),
307
+ val_obj.handler(),
308
+ _err.handler())
309
+ if _err.code != 0:
310
+ FactoryException(_err.what)
311
+ return list_obj
312
+
313
+ def to_list(self) -> list:
314
+ _err = Error()
315
+ count_value = ctypes.c_long()
316
+ factorylib.lib.psrd_list_count(self._hdr,
317
+ ctypes.byref(count_value),
318
+ _err.handler())
319
+ if _err.code != 0:
320
+ raise FactoryException(_err.what)
321
+ values_count = int(count_value.value)
322
+
323
+ list_of_values = []
324
+ _value = Value()
325
+ for i_value in range(values_count):
326
+ factorylib.lib.psrd_list_get(self._hdr, i_value,
327
+ _value.handler(), _err.handler())
328
+ if _err.code != 0:
329
+ raise FactoryException(_err.what)
330
+ list_of_values.append(_value.get())
331
+ return list_of_values
332
+
333
+
334
+ class Value(_BaseObject):
335
+ def __init__(self):
336
+ super().__init__()
337
+ self._hdr = factorylib.lib.psrd_new_value()
338
+
339
+ def __del__(self):
340
+ if self._hdr is not None:
341
+ factorylib.lib.psrd_free_value(self._hdr)
342
+
343
+ def get(self) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
344
+ _err = Error()
345
+ uint_value = ctypes.c_long()
346
+ factorylib.lib.psrd_value_get_type(self._hdr,
347
+ ctypes.byref(uint_value),
348
+ _err.handler())
349
+ if _err.code != 0:
350
+ raise FactoryException(_err.what)
351
+ var_type = int(uint_value.value)
352
+ if var_type in (ValueType.INT.value, ValueType.BOOL.value):
353
+ # as int
354
+ int_value = ctypes.c_int()
355
+ factorylib.lib.psrd_value_get_int(self._hdr,
356
+ ctypes.byref(int_value),
357
+ _err.handler())
358
+ if _err.code != 0:
359
+ raise FactoryException(_err.what)
360
+ return int(int_value.value)
361
+ elif var_type == ValueType.FLOAT.value:
362
+ float_value = ctypes.c_double()
363
+ factorylib.lib.psrd_value_get_real(self._hdr,
364
+ ctypes.byref(float_value),
365
+ _err.handler())
366
+ if _err.code != 0:
367
+ raise FactoryException(_err.what)
368
+ return float(float_value.value)
369
+ elif var_type == ValueType.STRING.value:
370
+ size = factorylib.lib.psrd_value_get_string(self._hdr, None, 0,
371
+ _err.handler())
372
+ buffer = ctypes.create_string_buffer(size)
373
+ factorylib.lib.psrd_value_get_string(self._hdr, buffer, size,
374
+ _err.handler())
375
+ if _err.code != 0:
376
+ raise FactoryException(_err.what)
377
+ return _from_c_str(buffer.value)
378
+ elif var_type == ValueType.DATE.value:
379
+ date_value = ctypes.c_longlong()
380
+ factorylib.lib.psrd_value_get_date(self._hdr,
381
+ ctypes.byref(date_value),
382
+ _err.handler())
383
+ if _err.code != 0:
384
+ raise FactoryException(_err.what)
385
+
386
+ return dt.datetime.fromtimestamp(date_value.value - _date_transform, dt.timezone.utc)
387
+
388
+ elif var_type == ValueType.NULL.value:
389
+ # Null type
390
+ return None
391
+ elif var_type == ValueType.OBJECT.value:
392
+ obj = DataObject()
393
+ ref = factorylib.lib.psrd_value_get_object(self._hdr,
394
+ _err.handler())
395
+ if _err.code != 0 or ref is None:
396
+ raise FactoryException(_err.what)
397
+ obj._hdr = ref
398
+ return obj
399
+ elif var_type == ValueType.LIST.value:
400
+ list_obj = ValueList()
401
+ ref = factorylib.lib.psrd_value_get_list(self._hdr,
402
+ _err.handler())
403
+ if _err.code != 0 or ref is None:
404
+ raise FactoryException(_err.what)
405
+ list_obj._hdr = ref
406
+ return list_obj.to_list()
407
+ else:
408
+ raise NotImplementedError()
409
+
410
+ def set(self, value: Union[int, float, dt.datetime, str, "DataObject", list, None]):
411
+ _err = Error()
412
+ if isinstance(value, numbers.Integral):
413
+ factorylib.lib.psrd_value_set_int(self._hdr, value,
414
+ _err.handler())
415
+ if _err.code != 0:
416
+ raise FactoryException(_err.what)
417
+
418
+ elif isinstance(value, numbers.Real):
419
+ factorylib.lib.psrd_value_set_real(self._hdr, value,
420
+ _err.handler())
421
+ if _err.code != 0:
422
+ raise FactoryException(_err.what)
423
+
424
+ elif isinstance(value, dt.datetime):
425
+ value.replace(tzinfo=dt.timezone.utc)
426
+ date_epoch = int(value.timestamp()) + _date_transform
427
+ factorylib.lib.psrd_value_set_date(self._hdr, date_epoch,
428
+ _err.handler())
429
+ if _err.code != 0:
430
+ raise FactoryException(_err.what)
431
+
432
+ elif isinstance(value, str):
433
+ factorylib.lib.psrd_value_set_string(self._hdr,
434
+ _c_str(value),
435
+ _bytes(value),
436
+ _err.handler())
437
+ if _err.code != 0:
438
+ raise FactoryException(_err.what)
439
+
440
+ elif isinstance(value, DataObject):
441
+ factorylib.lib.psrd_value_set_object(self._hdr,
442
+ value.handler(),
443
+ _err.handler())
444
+ if _err.code != 0:
445
+ raise FactoryException(_err.what)
446
+
447
+ elif isinstance(value, (list, tuple, ValueList)):
448
+ if isinstance(value, (list, tuple)):
449
+ list_obj = ValueList.from_list(value)
450
+ else:
451
+ list_obj = value
452
+ factorylib.lib.psrd_value_set_list(self._hdr,
453
+ list_obj.handler(),
454
+ _err.handler())
455
+ if _err.code != 0:
456
+ raise FactoryException(_err.what)
457
+
458
+ elif isinstance(value, Study):
459
+ raise FactoryException("Study object cannot be set as value.")
460
+
461
+ elif value is None:
462
+ factorylib.lib.psrd_value_set_null(self._hdr,
463
+ _err.handler())
464
+ if _err.code != 0:
465
+ raise FactoryException(_err.what)
466
+
467
+ else:
468
+ raise FactoryException(f"Unsupported type \"{type(value).name}\" for value.")
469
+
470
+
471
+ class PropertyDescription(_BaseObject):
472
+ def __init__(self):
473
+ super().__init__()
474
+ self._hdr = None
475
+
476
+ def __del__(self):
477
+ if self._hdr is not None:
478
+ factorylib.lib.psrd_free_property_description(self._hdr)
479
+
480
+ @property
481
+ def name(self) -> str:
482
+ _err = Error()
483
+ # TODO: determine size automatically
484
+ size = 300
485
+ buffer = ctypes.create_string_buffer(size)
486
+ factorylib.lib.psrd_property_description_get_name(self._hdr, buffer, size,
487
+ _err.handler())
488
+ if _err.code != 0:
489
+ raise FactoryException(_err.what)
490
+ return _from_c_str(buffer.value)
491
+
492
+ @name.setter
493
+ def name(self, value):
494
+ raise AttributeError("do not set name")
495
+
496
+ @name.deleter
497
+ def name(self):
498
+ raise AttributeError("do not delete name")
499
+
500
+ @property
501
+ def alt_name(self) -> str:
502
+ _err = Error()
503
+ # TODO: determine size automatically
504
+ size = 300
505
+ buffer = ctypes.create_string_buffer(size)
506
+ factorylib.lib.psrd_property_description_get_alternative_name(
507
+ self._hdr, buffer, size, _err.handler())
508
+ if _err.code != 0:
509
+ raise FactoryException(_err.what)
510
+ return _from_c_str(buffer.value)
511
+
512
+ @alt_name.setter
513
+ def alt_name(self, value):
514
+ raise AttributeError("do not set alt_name")
515
+
516
+ @alt_name.deleter
517
+ def alt_name(self):
518
+ raise AttributeError("do not delete alt_name")
519
+
520
+ def is_dynamic(self) -> bool:
521
+ _err = Error()
522
+ value = ctypes.c_bool()
523
+ factorylib.lib.psrd_property_description_is_dynamic(self._hdr,
524
+ ctypes.byref(value),
525
+ _err.handler())
526
+ if _err.code != 0:
527
+ raise FactoryException(_err.what)
528
+ return bool(value.value)
529
+
530
+ def is_indexed(self) -> bool:
531
+ _err = Error()
532
+ value = ctypes.c_bool()
533
+ factorylib.lib.psrd_property_description_is_indexed(self._hdr,
534
+ ctypes.byref(value),
535
+ _err.handler())
536
+ if _err.code != 0:
537
+ raise FactoryException(_err.what)
538
+ return bool(value.value)
539
+
540
+ def is_grouped(self) -> bool:
541
+ _err = Error()
542
+ value = ctypes.c_bool()
543
+ factorylib.lib.psrd_property_description_is_grouped(self._hdr,
544
+ ctypes.byref(value),
545
+ _err.handler())
546
+ if _err.code != 0:
547
+ raise FactoryException(_err.what)
548
+ return bool(value.value)
549
+
550
+ def grouped_with(self) -> List[str]:
551
+ _err = Error()
552
+ _list_obj = ValueList()
553
+ ref = factorylib.lib.psrd_property_description_grouped_with(self._hdr,
554
+ _err.handler())
555
+ if _err.code != 0 or ref is None:
556
+ raise FactoryException(_err.what)
557
+ _list_obj._hdr = ref
558
+ return _list_obj.to_list()
559
+
560
+ def dimensions(self) -> Dict[str, int]:
561
+ _err = Error()
562
+ dimensions = {}
563
+ value = ctypes.c_long()
564
+ factorylib.lib.psrd_property_description_dimensions_count(self._hdr,
565
+ ctypes.byref(value),
566
+ _err.handler())
567
+ if _err.code != 0:
568
+ raise FactoryException(_err.what)
569
+ dimensions_count = int(value.value)
570
+
571
+ for i_dim in range(dimensions_count):
572
+ # TODO: get size automatically
573
+ size = 100
574
+ buffer = ctypes.create_string_buffer(size)
575
+ factorylib.lib.psrd_property_description_get_dimension_name(self._hdr,
576
+ i_dim, buffer,
577
+ size,
578
+ _err.handler())
579
+ if _err.code != 0:
580
+ raise FactoryException(_err.what)
581
+ name = _from_c_str(buffer.value)
582
+
583
+ factorylib.lib.psrd_property_description_get_dimension_size(self._hdr,
584
+ i_dim,
585
+ ctypes.byref(value),
586
+ _err.handler())
587
+ if _err.code != 0:
588
+ raise FactoryException(_err.what)
589
+ size = int(value.value)
590
+
591
+ dimensions[name] = size
592
+ return dimensions
593
+
594
+ def type(self) -> ValueType:
595
+ _err = Error()
596
+ value = ctypes.c_long()
597
+ factorylib.lib.psrd_property_description_get_type(self._hdr,
598
+ ctypes.byref(value),
599
+ _err.handler())
600
+ if _err.code != 0:
601
+ raise FactoryException(_err.what)
602
+ return ValueType(value.value)
603
+
604
+ def __repr__(self):
605
+ return self.__str__()
606
+
607
+ def __str__(self):
608
+ dimensions = self.dimensions()
609
+ if len(dimensions) == 0:
610
+ return f"Property {self.name}"
611
+ else:
612
+ return f"Property {self.name} with dimensions {self.dimensions()}"
613
+
614
+
615
+
616
+ class DataObject(_BaseObject):
617
+ def __init__(self):
618
+ super().__init__()
619
+ self._hdr = None
620
+
621
+ def __del__(self):
622
+ if self._hdr is not None:
623
+ factorylib.lib.psrd_free_object(self._hdr)
624
+
625
+ def __eq__(self, other):
626
+ _err = Error()
627
+ value = ctypes.c_bool()
628
+ if self._hdr == other.handler():
629
+ return True
630
+ factorylib.lib.psrd_object_is_equals_to(self._hdr,
631
+ other.handler(),
632
+ ctypes.byref(value),
633
+ _err.handler())
634
+ if _err.code != 0:
635
+ raise FactoryException(_err.what)
636
+ return bool(value.value)
637
+
638
+ def __hash__(self):
639
+ _err = Error()
640
+ handler = factorylib.lib.psrd_object_get_handler(self._hdr, _err.handler())
641
+ if _err.code != 0:
642
+ raise FactoryException(_err.what)
643
+ return handler
644
+
645
+ def __copy__(self):
646
+ dest = DataObject()
647
+ _err = Error()
648
+ ref = factorylib.lib.psrd_object_clone(self.handler(),
649
+ _err.handler())
650
+ if _err.code != 0 or ref is None:
651
+ raise FactoryException(_err.what)
652
+ dest._hdr = ref
653
+ return dest
654
+
655
+ def __deepcopy__(self, memodict=None):
656
+ raise NotImplementedError()
657
+
658
+ def __repr__(self):
659
+ identifiers = []
660
+ if self.code != 0:
661
+ identifiers.append(f"code={self.code}")
662
+ if self.id != "":
663
+ identifiers.append(f"id={self.id.strip()}")
664
+ if self.name != "":
665
+ identifiers.append(f"name={self.name.strip()}")
666
+ return f"psr.factory.DataObject({self.type}, {', '.join(identifiers)})"
667
+
668
+ def help(self) -> str:
669
+ return help(self.type)
670
+
671
+ @property
672
+ def context(self) -> "Context":
673
+ _check_initialized()
674
+ obj = Context()
675
+ _err = Error()
676
+ ref = factorylib.lib.psrd_object_context(self._hdr,
677
+ _err.handler())
678
+ if _err.code != 0 or ref is None:
679
+ raise FactoryException(_err.what)
680
+ obj._hdr = ref
681
+ return obj
682
+
683
+ def properties(self) -> Dict[str, PropertyDescription]:
684
+ _err = Error()
685
+ value = ctypes.c_long()
686
+ factorylib.lib.psrd_object_property_description_count(self._hdr,
687
+ ctypes.byref(value),
688
+ _err.handler())
689
+ if _err.code != 0:
690
+ raise FactoryException(_err.what)
691
+ var_count = int(value.value)
692
+ properties = {}
693
+ for i_var in range(var_count):
694
+ var = PropertyDescription()
695
+ ref = factorylib.lib.psrd_object_get_property_description(self._hdr,
696
+ i_var,
697
+ _err.handler())
698
+ if _err.code != 0 or ref is None:
699
+ raise FactoryException(_err.what)
700
+ var._hdr = ref
701
+ properties[var.name] = var
702
+ return properties
703
+
704
+ def get(self, expression: str) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
705
+ value = Value()
706
+ _err = Error()
707
+ factorylib.lib.psrd_object_get_value(self._hdr,
708
+ _c_str(expression),
709
+ value.handler(),
710
+ _err.handler())
711
+ if _err.code != 0:
712
+ raise FactoryException(_err.what)
713
+ return value.get()
714
+
715
+ def get_at(self, expression: str, range_expr: Union[str, dt.datetime]) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
716
+ if not isinstance(range_expr, (str, dt.datetime)):
717
+ raise FactoryException("range_expr must be a string or datetime object.")
718
+ _value = Value()
719
+ _err = Error()
720
+ _range = Value()
721
+ _range.set(range_expr)
722
+ factorylib.lib.psrd_object_get_value_at(self._hdr,
723
+ _c_str(expression),
724
+ _range.handler(),
725
+ _value.handler(),
726
+ _err.handler())
727
+ if _err.code != 0:
728
+ raise FactoryException(_err.what)
729
+ return _value.get()
730
+
731
+ def get_df(self, expression: str) -> "pandas.DataFrame":
732
+ _err = Error()
733
+ _df = DataFrame()
734
+ factorylib.lib.psrd_object_get_table(self._hdr, _df.handler(),
735
+ _c_str(expression),
736
+ _bytes(expression),
737
+ _err.handler())
738
+ if _err.code != 0:
739
+ raise FactoryException(_err.what)
740
+ df_builder = _DataFrameBuilder()
741
+ df_builder.build_dataframe(_df)
742
+ return df_builder.build_pandas_dataframe()
743
+
744
+ def set(self, expression: str, value):
745
+ _err = Error()
746
+ _val = Value()
747
+ _val.set(value)
748
+ factorylib.lib.psrd_object_set_value(self._hdr, _c_str(expression),
749
+ _bytes(expression),
750
+ _val.handler(),
751
+ _err.handler())
752
+ if _err.code != 0:
753
+ raise FactoryException(_err.what)
754
+
755
+ def set_at(self, expression: str, range_expr: Union[str, dt.datetime], value):
756
+ if not isinstance(range_expr, (str, dt.datetime)):
757
+ raise FactoryException("range_expr must be a string or datetime object.")
758
+ _err = Error()
759
+ _value = Value()
760
+ _value.set(value)
761
+ _range = Value()
762
+ _range.set(range_expr)
763
+ factorylib.lib.psrd_object_set_value_at(self._hdr,
764
+ _c_str(expression),
765
+ _bytes(expression),
766
+ _range.handler(),
767
+ _value.handler(),
768
+ _err.handler())
769
+ if _err.code != 0:
770
+ raise FactoryException(_err.what)
771
+
772
+ def set_df(self, dataframe_like):
773
+ if not _has_pandas():
774
+ raise ModuleNotFoundError("pandas required.")
775
+ dataframe_like = pandas.api.interchange.from_dataframe(dataframe_like)
776
+ df_builder = _DataFrameBuilder()
777
+ _df = df_builder.build_from_pandas(dataframe_like)
778
+ _err = Error()
779
+ factorylib.lib.psrd_object_set_table(self._hdr, _df.handler(),
780
+ _err.handler())
781
+ if _err.code != 0:
782
+ raise FactoryException(_err.what)
783
+
784
+
785
+ def clear_values(self, expression: str):
786
+ _err = Error()
787
+ factorylib.lib.psrd_object_clear_values(self._hdr,
788
+ _c_str(expression),
789
+ _bytes(expression),
790
+ _err.handler())
791
+ if _err.code != 0:
792
+ raise FactoryException(_err.what)
793
+
794
+ def parent(self) -> Optional["Study"]:
795
+ study_ptr = Study()
796
+ _err = Error()
797
+ ref = factorylib.lib.psrd_object_get_parent(self._hdr,
798
+ _err.handler())
799
+ if _err.code != 0:
800
+ raise FactoryException(_err.what)
801
+ if ref is None:
802
+ return None
803
+ study_ptr._hdr = ref
804
+ return study_ptr
805
+
806
+ def referenced_by(self) -> List["DataObject"]:
807
+ object_list = ValueList(False)
808
+ _err = Error()
809
+ ref = factorylib.lib.psrd_object_referenced_by(self._hdr,
810
+ _err.handler())
811
+ if _err.code != 0 or ref is None:
812
+ raise FactoryException(_err.what)
813
+ object_list._hdr = ref
814
+ return object_list.to_list()
815
+
816
+ @property
817
+ def code(self) -> int:
818
+ _err = Error()
819
+ value = ctypes.c_int()
820
+ factorylib.lib.psrd_object_get_code(self._hdr,
821
+ ctypes.byref(value),
822
+ _err.handler())
823
+ if _err.code != 0:
824
+ raise FactoryException(_err.what)
825
+ return value.value
826
+
827
+ @code.setter
828
+ def code(self, value: int):
829
+ _err = Error()
830
+ factorylib.lib.psrd_object_set_code(self._hdr, value,
831
+ _err.handler())
832
+ if _err.code != 0:
833
+ raise FactoryException(_err.what)
834
+
835
+ @code.deleter
836
+ def code(self):
837
+ raise AttributeError("do not delete code")
838
+
839
+ @property
840
+ def type(self) -> str:
841
+ err = Error()
842
+ size = factorylib.lib.psrd_object_get_type(self._hdr, None,
843
+ 0, err.handler())
844
+ if err.code != 0:
845
+ raise FactoryException(err.what)
846
+ buffer = ctypes.create_string_buffer(size)
847
+ factorylib.lib.psrd_object_get_type(self._hdr, buffer,
848
+ size, err.handler())
849
+ if err.code != 0:
850
+ raise FactoryException(err.what)
851
+ return _from_c_str(buffer.value)
852
+
853
+ @type.setter
854
+ def type(self, value: str):
855
+ raise AttributeError("do not set type")
856
+
857
+ @type.deleter
858
+ def type(self):
859
+ raise AttributeError("do not delete type")
860
+
861
+ @property
862
+ def name(self) -> str:
863
+ err = Error()
864
+ size = factorylib.lib.psrd_object_get_name(self._hdr, None,
865
+ 0, err.handler())
866
+ if err.code != 0:
867
+ raise FactoryException(err.what)
868
+ buffer = ctypes.create_string_buffer(size)
869
+ factorylib.lib.psrd_object_get_name(self._hdr, buffer,
870
+ size, err.handler())
871
+ if err.code == 0:
872
+ return _from_c_str(buffer.value)
873
+ raise FactoryException(err.what)
874
+
875
+ @name.setter
876
+ def name(self, value: str):
877
+ err = Error()
878
+ factorylib.lib.psrd_object_set_name(self._hdr,
879
+ _c_str(value),
880
+ _bytes(value),
881
+ err.handler())
882
+ if err.code != 0:
883
+ raise FactoryException(err.what)
884
+
885
+ @name.deleter
886
+ def name(self):
887
+ raise AttributeError("do not delete name")
888
+
889
+ @property
890
+ def id(self) -> str:
891
+ err = Error()
892
+ size = factorylib.lib.psrd_object_get_id(self._hdr, None,
893
+ 0, err.handler())
894
+ if err.code != 0:
895
+ raise FactoryException(err.what)
896
+ buffer = ctypes.create_string_buffer(size)
897
+ factorylib.lib.psrd_object_get_id(self._hdr, buffer,
898
+ size, err.handler())
899
+ if err.code == 0:
900
+ return _from_c_str(buffer.value)
901
+ raise FactoryException(err.what)
902
+
903
+ @id.setter
904
+ def id(self, value: str):
905
+ _err = Error()
906
+ factorylib.lib.psrd_object_set_id(self._hdr,
907
+ _c_str(value),
908
+ _bytes(value),
909
+ _err.handler())
910
+ if _err.code != 0:
911
+ raise FactoryException(_err.what)
912
+
913
+ @id.deleter
914
+ def id(self):
915
+ raise AttributeError("do not delete id")
916
+
917
+
918
+ class Context(DataObject):
919
+ @staticmethod
920
+ def default_context() -> "Context":
921
+ _check_initialized()
922
+ context = Context()
923
+ err = Error()
924
+ ref = factorylib.lib.psrd_get_default_context(err.handler())
925
+ if err.code != 0 or ref is None:
926
+ raise FactoryException(err.what)
927
+ context._hdr = ref
928
+ return context
929
+
930
+ @staticmethod
931
+ def create() -> "Context":
932
+ context_obj = create("Context", None)
933
+ context = Context()
934
+ context._hdr = context_obj._hdr
935
+ context_obj._hdr = None
936
+ return context
937
+
938
+
939
+ class Study(_BaseObject):
940
+ def __init__(self):
941
+ super().__init__()
942
+ self.find_by_name = self.find
943
+
944
+ def __del__(self):
945
+ if self._hdr is not None:
946
+ factorylib.lib.psrd_free_study(self._hdr)
947
+
948
+ def __hash__(self):
949
+ return factorylib.lib.psrd_study_get_handler(self._hdr)
950
+
951
+ def __eq__(self, other: "Study"):
952
+ _err = Error()
953
+ value = ctypes.c_bool()
954
+ if self._hdr == other.handler():
955
+ return True
956
+ factorylib.lib.psrd_study_is_equals_to(self._hdr,
957
+ other.handler(),
958
+ ctypes.byref(value),
959
+ _err.handler())
960
+ if _err.code != 0:
961
+ raise FactoryException(_err.what)
962
+ return bool(value.value)
963
+
964
+ def __copy__(self):
965
+ raise NotImplementedError()
966
+
967
+ def __deepcopy__(self, memodict=None):
968
+ dest = Study()
969
+ _err = Error()
970
+ ref = factorylib.lib.psrd_study_clone(self.handler(),
971
+ _err.handler())
972
+ if _err.code != 0 or ref is None:
973
+ raise FactoryException(_err.what)
974
+ dest._hdr = ref
975
+ return dest
976
+
977
+ @staticmethod
978
+ def help():
979
+ return help("Study")
980
+
981
+ @staticmethod
982
+ def create_object(profile_or_context: Union[str, Context, None],
983
+ blocks: Optional[int] = None):
984
+ _check_initialized()
985
+ err = Error()
986
+ context = _get_context(profile_or_context, blocks)
987
+ study = Study()
988
+ study._hdr = factorylib.lib.psrd_study_create(context.handler(),
989
+ err.handler())
990
+ if err.code != 0:
991
+ raise FactoryException(err.what)
992
+ return study
993
+
994
+ @staticmethod
995
+ def load(study_path: Union[str, pathlib.Path], profile_or_context: Union[str, Context, None],
996
+ options: Optional[DataObject] = None):
997
+ if not isinstance(options, (DataObject, type(None))):
998
+ raise TypeError("options must be a DataObject or None.")
999
+ study_path = str(study_path)
1000
+ context = _get_context(profile_or_context, None)
1001
+ err = Error()
1002
+ options_handler = options.handler() if options is not None else None
1003
+ study = Study()
1004
+ study._hdr = factorylib.lib.psrd_study_load(_c_str(study_path),
1005
+ _bytes(study_path),
1006
+ options_handler,
1007
+ context.handler(),
1008
+ err.handler())
1009
+ if err.code != 0:
1010
+ raise FactoryException(err.what)
1011
+ return study
1012
+
1013
+ def save(self, output_path: Union[str, pathlib.Path], options: Optional[DataObject] = None):
1014
+ if not isinstance(options, (DataObject, type(None))):
1015
+ raise TypeError("options must be a DataObject or None.")
1016
+ output_path = str(output_path)
1017
+ _err = Error()
1018
+ _options_handler = options.handler() if options is not None else None
1019
+ factorylib.lib.psrd_study_save(self._hdr, _c_str(output_path),
1020
+ _bytes(output_path),
1021
+ _options_handler,
1022
+ _err.handler())
1023
+ if _err.code != 0:
1024
+ raise FactoryException(_err.what)
1025
+
1026
+ @property
1027
+ def context(self) -> "Context":
1028
+ _check_initialized()
1029
+ obj = Context()
1030
+ _err = Error()
1031
+ ref = factorylib.lib.psrd_study_context(self._hdr,
1032
+ _err.handler())
1033
+ if _err.code != 0 or ref is None:
1034
+ raise FactoryException(_err.what)
1035
+ obj._hdr = ref
1036
+ return obj
1037
+
1038
+ def get(self, expression: str) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
1039
+ value = Value()
1040
+ _err = Error()
1041
+ factorylib.lib.psrd_study_get_value(self._hdr,
1042
+ _c_str(expression),
1043
+ value.handler(),
1044
+ _err.handler())
1045
+ if _err.code != 0:
1046
+ raise FactoryException(_err.what)
1047
+ return value.get()
1048
+
1049
+ def get_at(self, expression: str, range_expr: Union[str, dt.datetime]) -> Union[int, float, dt.datetime, str, "DataObject", list, None]:
1050
+ if not isinstance(range_expr, str):
1051
+ raise FactoryException("range_expr must be a string or datetime object.")
1052
+ _value = Value()
1053
+ _err = Error()
1054
+ _range = Value()
1055
+ _range.set(range_expr)
1056
+ factorylib.lib.psrd_study_get_value_at(self._hdr,
1057
+ _c_str(expression),
1058
+ _range.handler(),
1059
+ _value.handler(),
1060
+ _err.handler())
1061
+ if _err.code != 0:
1062
+ raise FactoryException(_err.what)
1063
+ return _value.get()
1064
+
1065
+ def add(self, obj: DataObject):
1066
+ if not isinstance(obj, DataObject):
1067
+ raise TypeError("obj must be a DataObject.")
1068
+ _err = Error()
1069
+ factorylib.lib.psrd_study_add(self._hdr,
1070
+ obj.handler(),
1071
+ _err.handler())
1072
+ if _err.code != 0:
1073
+ raise FactoryException(_err.what)
1074
+
1075
+ def remove(self, obj: DataObject):
1076
+ if not isinstance(obj, DataObject):
1077
+ raise TypeError("obj must be a DataObject.")
1078
+ _err = Error()
1079
+ factorylib.lib.psrd_study_remove(self._hdr,
1080
+ obj.handler(),
1081
+ _err.handler())
1082
+ if _err.code != 0:
1083
+ raise FactoryException(_err.what)
1084
+
1085
+ def find(self, expression: str) -> List[DataObject]:
1086
+ object_list = ValueList(False)
1087
+ _err = Error()
1088
+ ref = factorylib.lib.psrd_study_find(self._hdr,
1089
+ _c_str(expression),
1090
+ _err.handler())
1091
+ if _err.code != 0 or ref is None:
1092
+ raise FactoryException(_err.what)
1093
+ object_list._hdr = ref
1094
+ return object_list.to_list()
1095
+
1096
+ def find_by_name(self, type_name: str, name: str) -> List[DataObject]:
1097
+ object_list = ValueList(False)
1098
+ _err = Error()
1099
+ if name.strip() == "":
1100
+ name = "*"
1101
+ expression = f"{type_name}.{name}"
1102
+ ref = factorylib.lib.psrd_study_find(self._hdr,
1103
+ _c_str(expression),
1104
+ _err.handler())
1105
+ if _err.code != 0 or ref is None:
1106
+ raise FactoryException(_err.what)
1107
+ object_list._hdr = ref
1108
+ return object_list.to_list()
1109
+
1110
+ def find_by_code(self, type_name: str, code: Optional[int] = None) -> List[DataObject]:
1111
+ if code is None:
1112
+ warnings.warn(DeprecationWarning("Starting from Factory 4.0.9 "
1113
+ "the second argument 'code' must be provided.\n"
1114
+ "Use find_by_code(type_name, code)"))
1115
+
1116
+ type_name, code_str = type_name.split(".", 1)
1117
+ code = int(code_str)
1118
+
1119
+ object_list = ValueList(False)
1120
+ _err = Error()
1121
+ ref = factorylib.lib.psrd_study_find_by_code(self._hdr,
1122
+ _c_str(type_name),
1123
+ code,
1124
+ _err.handler())
1125
+ if _err.code != 0 or ref is None:
1126
+ raise FactoryException(_err.what)
1127
+ object_list._hdr = ref
1128
+ return object_list.to_list()
1129
+
1130
+ def find_by_id(self, expression: str) -> List[DataObject]:
1131
+ object_list = ValueList(False)
1132
+ _err = Error()
1133
+ ref = factorylib.lib.psrd_study_find_by_id(self._hdr,
1134
+ _c_str(expression),
1135
+ _err.handler())
1136
+ if _err.code != 0 or ref is None:
1137
+ raise FactoryException(_err.what)
1138
+ object_list._hdr = ref
1139
+ return object_list.to_list()
1140
+
1141
+ def set(self, expression: str, value):
1142
+ _err = Error()
1143
+ _val = Value()
1144
+ _val.set(value)
1145
+ factorylib.lib.psrd_study_set_value(self._hdr,
1146
+ _c_str(expression),
1147
+ _bytes(expression),
1148
+ _val.handler(),
1149
+ _err.handler())
1150
+ if _err.code != 0:
1151
+ raise FactoryException(_err.what)
1152
+
1153
+ def set_at(self, expression: str, range_expr: Union[str, dt.datetime], value):
1154
+ if not isinstance(range_expr, (str, dt.datetime)):
1155
+ raise FactoryException("range_expr must be a string or datetime object.")
1156
+ _err = Error()
1157
+ _value = Value()
1158
+ _value.set(value)
1159
+ _range = Value()
1160
+ _range.set(range_expr)
1161
+ factorylib.lib.psrd_study_set_value_at(self._hdr,
1162
+ _c_str(expression),
1163
+ _bytes(expression),
1164
+ _range.handler(),
1165
+ _value.handler(),
1166
+ _err.handler())
1167
+ if _err.code != 0:
1168
+ raise FactoryException(_err.what)
1169
+
1170
+ def get_df(self, expression: str) -> "pandas.DataFrame":
1171
+ _err = Error()
1172
+ _df = DataFrame()
1173
+ factorylib.lib.psrd_study_get_table(self._hdr, _df.handler(),
1174
+ _c_str(expression),
1175
+ _bytes(expression),
1176
+ _err.handler())
1177
+ if _err.code != 0:
1178
+ raise FactoryException(_err.what)
1179
+ df_builder = _DataFrameBuilder()
1180
+ df_builder.build_dataframe(_df)
1181
+ return df_builder.build_pandas_dataframe()
1182
+
1183
+ def get_objects_values(self, object_type: str, columns: List[str]) -> "pandas.DataFrame":
1184
+ _err = Error()
1185
+ _table = DataFrame()
1186
+ columns_list = Value()
1187
+ columns_list.set(columns)
1188
+ factorylib.lib.psrd_study_get_objects_values(self._hdr, _table.handler(),
1189
+ _c_str(object_type),
1190
+ columns_list.handler(),
1191
+ _err.handler())
1192
+ if _err.code != 0:
1193
+ raise FactoryException(_err.what)
1194
+ df_builder = _DataFrameBuilder()
1195
+ df_builder.build_dataframe(_table)
1196
+ return df_builder.build_pandas_dataframe()
1197
+
1198
+ def get_objects_values_at(self, object_type: str, columns: List[str], range: Union[str, dt.datetime]) -> "pandas.DataFrame":
1199
+ _err = Error()
1200
+ _df = DataFrame()
1201
+ _range = Value()
1202
+ _range.set(range)
1203
+ columns_list = Value()
1204
+ columns_list.set(columns)
1205
+ factorylib.lib.psrd_study_get_objects_values_at(self._hdr, _df.handler(),
1206
+ _c_str(object_type),
1207
+ columns_list.handler(),
1208
+ _range.handler(),
1209
+ _err.handler())
1210
+ if _err.code != 0:
1211
+ raise FactoryException(_err.what)
1212
+ df_builder = _DataFrameBuilder()
1213
+ df_builder.build_dataframe(_df)
1214
+ return df_builder.build_pandas_dataframe()
1215
+
1216
+ def properties(self) -> Dict[str, PropertyDescription]:
1217
+ _err = Error()
1218
+ value = ctypes.c_long()
1219
+ factorylib.lib.psrd_study_property_description_count(self._hdr,
1220
+ ctypes.byref(value),
1221
+ _err.handler())
1222
+ if _err.code != 0:
1223
+ raise FactoryException(_err.what)
1224
+ var_count = int(value.value)
1225
+ properties = {}
1226
+ for i_var in range(var_count):
1227
+ var = PropertyDescription()
1228
+ ref = factorylib.lib.psrd_study_get_property_description(self._hdr,
1229
+ i_var,
1230
+ _err.handler())
1231
+ if _err.code != 0 or ref is None:
1232
+ raise FactoryException(_err.what)
1233
+ var._hdr = ref
1234
+ properties[var.name] = var
1235
+ return properties
1236
+
1237
+ def set_df(self, dataframe_like):
1238
+ if not _has_pandas():
1239
+ raise ModuleNotFoundError("pandas required.")
1240
+ dataframe_like = pandas.api.interchange.from_dataframe(dataframe_like)
1241
+ df_builder = _DataFrameBuilder()
1242
+ _df = df_builder.build_from_pandas(dataframe_like)
1243
+ _err = Error()
1244
+ factorylib.lib.psrd_study_set_table(self._hdr, _df.handler(),
1245
+ _err.handler())
1246
+ if _err.code != 0:
1247
+ raise FactoryException(_err.what)
1248
+
1249
+ def clear_values(self, expression: str):
1250
+ _err = Error()
1251
+ factorylib.lib.psrd_study_clear_values(self._hdr,
1252
+ _c_str(expression),
1253
+ _bytes(expression),
1254
+ _err.handler())
1255
+ if _err.code != 0:
1256
+ raise FactoryException(_err.what)
1257
+
1258
+
1259
+ class _DataFrameBuilder:
1260
+ def __init__(self):
1261
+ self.indices: List[Optional[_TableColumn]] = []
1262
+ self.columns: List[Optional[_TableColumn]] = []
1263
+ self.column_names: List[str] = []
1264
+ self.index_names: List[str] = []
1265
+ self.column_types: List[int] = []
1266
+ self.index_types: List[int] = []
1267
+ self._not_built = True
1268
+ self._value: Optional[Value] = None
1269
+ self._err: Optional[Error] = None
1270
+
1271
+ def _pandas_dtype_to_column_type(self, dtype: str) -> int:
1272
+ if dtype == "object":
1273
+ return 0
1274
+ elif dtype == "int64":
1275
+ return 1
1276
+ elif dtype == "float32":
1277
+ return 2
1278
+ elif dtype == "float64":
1279
+ return 3
1280
+ elif dtype == "string":
1281
+ return 4
1282
+ elif dtype == "datetime64[ns]":
1283
+ return 5
1284
+ else:
1285
+ raise FactoryException(f"Unsupported pandas dtype \"{dtype}\".")
1286
+
1287
+ def _polars_dtype_to_column_type(self, dtype: "polars.datatypes.classes.DataTypeClass") -> int:
1288
+ if dtype == polars.Int32:
1289
+ return 1
1290
+ if dtype == polars.Int64:
1291
+ return 1
1292
+ if dtype == polars.Float64:
1293
+ return 3
1294
+ else:
1295
+ raise FactoryException(f"Unsupported polars dtype \"{dtype}\".")
1296
+
1297
+
1298
+ def build_dataframe(self, df: "DataFrame"):
1299
+ self._err = Error()
1300
+ name_buffer_length = 200
1301
+ _columns_count = ctypes.c_long()
1302
+ factorylib.lib.psrd_table_columns_count(df.handler(),
1303
+ ctypes.byref(_columns_count),
1304
+ self._err.handler())
1305
+ if self._err.code != 0:
1306
+ raise FactoryException(self._err.what)
1307
+ columns_count = _columns_count.value
1308
+
1309
+ _rows_count = ctypes.c_long()
1310
+ factorylib.lib.psrd_table_rows_count(df.handler(),
1311
+ ctypes.byref(_rows_count),
1312
+ self._err.handler())
1313
+ if self._err.code != 0:
1314
+ raise FactoryException(self._err.what)
1315
+ rows_count = _rows_count.value
1316
+
1317
+ _indices_count = ctypes.c_long()
1318
+ factorylib.lib.psrd_table_index_count(df.handler(),
1319
+ ctypes.byref(_indices_count),
1320
+ self._err.handler())
1321
+ if self._err.code != 0:
1322
+ raise FactoryException(self._err.what)
1323
+ indices_count = _indices_count.value
1324
+
1325
+ value = Value()
1326
+ buffer = ctypes.create_string_buffer(name_buffer_length)
1327
+
1328
+ self.indices = [_TableColumn() for _ in range(indices_count)]
1329
+ for index in range(indices_count):
1330
+ factorylib.lib.psrd_table_index_get_name(df.handler(), index,
1331
+ buffer, name_buffer_length,
1332
+ self._err.handler())
1333
+ if self._err.code != 0:
1334
+ raise FactoryException(self._err.what)
1335
+ self.indices[index].name = _from_c_str(buffer.value)
1336
+
1337
+ self.indices[index].values = [None] * rows_count
1338
+ for i_row in range(0, rows_count):
1339
+ factorylib.lib.psrd_table_index_get_value(df.handler(), index,
1340
+ i_row, value.handler(),
1341
+ self._err.handler())
1342
+ if self._err.code != 0:
1343
+ raise FactoryException(self._err.what)
1344
+ self.indices[index].values[i_row] = value.get()
1345
+
1346
+ self.columns = [_TableColumn() for _ in range(columns_count)]
1347
+ for column in range(columns_count):
1348
+ factorylib.lib.psrd_table_column_get_name(df.handler(), column,
1349
+ buffer, name_buffer_length,
1350
+ self._err.handler())
1351
+ if self._err.code != 0:
1352
+ raise FactoryException(self._err.what)
1353
+ self.columns[column].name = _from_c_str(buffer.value)
1354
+
1355
+ self.columns[column].values = [None] * rows_count
1356
+ for row in range(rows_count):
1357
+ factorylib.lib.psrd_table_column_get_value(df.handler(),
1358
+ column, row,
1359
+ value.handler(),
1360
+ self._err.handler())
1361
+ if self._err.code != 0:
1362
+ raise FactoryException(self._err.what)
1363
+ self.columns[column].values[row] = value.get()
1364
+ self._not_built = False
1365
+
1366
+ def build_dataframe_of_integral_types(self, df: "DataFrame"):
1367
+ self._err = Error()
1368
+ name_buffer_length = 200
1369
+ _columns_count = ctypes.c_long()
1370
+ factorylib.lib.psrd_table_columns_count(df.handler(),
1371
+ ctypes.byref(_columns_count),
1372
+ self._err.handler())
1373
+ if self._err.code != 0:
1374
+ raise FactoryException(self._err.what)
1375
+ columns_count = _columns_count.value
1376
+
1377
+ _rows_count = ctypes.c_long()
1378
+ factorylib.lib.psrd_table_rows_count(df.handler(),
1379
+ ctypes.byref(_rows_count),
1380
+ self._err.handler())
1381
+ if self._err.code != 0:
1382
+ raise FactoryException(self._err.what)
1383
+ rows_count = _rows_count.value
1384
+
1385
+ _indices_count = ctypes.c_long()
1386
+ factorylib.lib.psrd_table_index_count(df.handler(),
1387
+ ctypes.byref(_indices_count),
1388
+ self._err.handler())
1389
+ if self._err.code != 0:
1390
+ raise FactoryException(self._err.what)
1391
+ indices_count = _indices_count.value
1392
+
1393
+ buffer = ctypes.create_string_buffer(name_buffer_length)
1394
+
1395
+ self.indices = [_TableColumn() for _ in range(indices_count)]
1396
+ for index in range(indices_count):
1397
+ factorylib.lib.psrd_table_index_get_name(df.handler(), index,
1398
+ buffer, name_buffer_length,
1399
+ self._err.handler())
1400
+ if self._err.code != 0:
1401
+ raise FactoryException(self._err.what)
1402
+ index_name = _from_c_str(buffer.value)
1403
+ self.indices[index].name = index_name
1404
+ self.indices[index].values = [None] * rows_count
1405
+ if index_name in ("date", "datetime"):
1406
+ array_values = (ctypes.c_longlong * rows_count)()
1407
+ factorylib.lib.psrd_table_index_get_date_values(df.handler(),
1408
+ index,
1409
+ array_values,
1410
+ self._err.handler())
1411
+ if self._err.code != 0:
1412
+ raise FactoryException(self._err.what)
1413
+ # convert array values to python datetime
1414
+ self.indices[index].values = [dt.datetime.utcfromtimestamp(value - _date_transform) for value in array_values]
1415
+ else:
1416
+ array_values = (ctypes.c_int * rows_count)()
1417
+ factorylib.lib.psrd_table_index_get_int_values(df.handler(),
1418
+ index,
1419
+ array_values,
1420
+ self._err.handler())
1421
+ if self._err.code != 0:
1422
+ raise FactoryException(self._err.what)
1423
+ self.indices[index].values = array_values
1424
+
1425
+ self.columns = [_TableColumn() for _ in range(columns_count)]
1426
+ for column in range(columns_count):
1427
+ factorylib.lib.psrd_table_column_get_name(df.handler(), column,
1428
+ buffer, name_buffer_length,
1429
+ self._err.handler())
1430
+ if self._err.code != 0:
1431
+ raise FactoryException(self._err.what)
1432
+ self.columns[column].name = _from_c_str(buffer.value)
1433
+
1434
+ array_values = (ctypes.c_double * rows_count)()
1435
+ factorylib.lib.psrd_table_column_get_double_values(df.handler(),
1436
+ column,
1437
+ array_values,
1438
+ self._err.handler())
1439
+ if self._err.code != 0:
1440
+ raise FactoryException(self._err.what)
1441
+ self.columns[column].values = array_values
1442
+ self._not_built = False
1443
+
1444
+ def build_pandas_dataframe(self, **kwargs) -> "pandas.DataFrame":
1445
+ use_object_dtype = kwargs.get("use_object_dtype", True)
1446
+ if not _has_pandas():
1447
+ raise ModuleNotFoundError("pandas required.")
1448
+ def convert_column_values(values):
1449
+ if isinstance(values, list):
1450
+ return values
1451
+ # Looks like ctype array, smells like ctype array
1452
+ if hasattr(values, "_length_") and hasattr(values, "_type_"):
1453
+ return numpy.ctypeslib.as_array(values)
1454
+ return values
1455
+
1456
+ data = {column.name: convert_column_values(column.values)
1457
+ for column in self.columns}
1458
+ if len(self.indices) > 1:
1459
+ # TODO: store index as rows of tuples
1460
+ index = pandas.MultiIndex.from_tuples(
1461
+ [tuple(self.indices[i].values[row] for i in range(len(self.indices))) for row in range(len(self.indices[0].values))],
1462
+ names=[index.name for index in self.indices])
1463
+ elif len(self.indices) == 1:
1464
+ index_value_type = type(self.indices[0].values[0]) if len(self.indices[0].values) > 0 else object
1465
+ if index_value_type == dt.datetime:
1466
+ index = pandas.DatetimeIndex(self.indices[0].values, name=self.indices[0].name)
1467
+ else:
1468
+ if index_value_type == DataObject:
1469
+ index_value_type = object
1470
+ index = pandas.Index(tuple(self.indices[0].values), dtype=index_value_type, name=self.indices[0].name)
1471
+ else:
1472
+ index = None
1473
+ if use_object_dtype:
1474
+ return pandas.DataFrame(data=data, index=index, dtype=object)
1475
+ else:
1476
+ return pandas.DataFrame(data=data, index=index)
1477
+
1478
+ def build_from_pandas(self, table_data: "pandas.DataFrame") -> "DataFrame":
1479
+ # check if the table has indices and if its multi-index or common index
1480
+ if isinstance(table_data.index, pandas.MultiIndex):
1481
+ table_data_indices = table_data.index.levels
1482
+ elif isinstance(table_data.index, pandas.Index) and not table_data.index.empty:
1483
+ table_data_indices = [table_data.index]
1484
+ else:
1485
+ table_data_indices = []
1486
+
1487
+ self.column_names = table_data.columns
1488
+ self.index_names = [index.name for index in table_data_indices]
1489
+ self.column_types = [self._pandas_dtype_to_column_type(dtype) for dtype in table_data.dtypes]
1490
+ self.index_types = [self._pandas_dtype_to_column_type(index.dtype) for index in table_data_indices]
1491
+ replaced_name = False
1492
+ for i, name in enumerate(self.index_names):
1493
+ if name is None:
1494
+ self.index_names[i] = 'date'
1495
+ replaced_name = True
1496
+ rows = len(table_data.index)
1497
+ _df = self._pre_build_generic(rows, self.index_types, self.column_types)
1498
+
1499
+ test_conversion_types = {
1500
+ pandas.api.types.is_integer_dtype: numpy.int32,
1501
+ pandas.api.types.is_float_dtype: numpy.float64,
1502
+ pandas.api.types.is_datetime64_any_dtype: numpy.datetime64,
1503
+ }
1504
+ convert_to_ctype = {
1505
+ numpy.int32: ctypes.c_int32,
1506
+ numpy.float32: ctypes.c_float,
1507
+ numpy.float64: ctypes.c_double,
1508
+ numpy.datetime64: ctypes.c_longlong,
1509
+
1510
+ }
1511
+
1512
+ # Check column value types - if they support, call efficient set methods
1513
+ column_convert_to = {}
1514
+ column_fast_set = {}
1515
+ for i_column, column_name in enumerate(table_data.columns):
1516
+ column_values = table_data[column_name]
1517
+ column_fast_set[column_name] = False
1518
+ for test_func, convert_to_type in test_conversion_types.items():
1519
+ if test_func(column_values):
1520
+ column_convert_to[column_name] = convert_to_type
1521
+ column_fast_set[column_name] = True
1522
+ break
1523
+
1524
+ if replaced_name:
1525
+ for i, name in enumerate(self.index_names):
1526
+ if name == "date":
1527
+ self.index_names[i] = None
1528
+ # check index value types
1529
+ index_convert_to = {}
1530
+ index_fast_set = {}
1531
+ for i_index, index_name in enumerate(self.index_names):
1532
+ index_fast_set[index_name] = False
1533
+ index_values = table_data.index.get_level_values(index_name)
1534
+ for test_func, convert_to_type in test_conversion_types.items():
1535
+ if test_func(index_values):
1536
+ index_convert_to[index_name] = convert_to_type
1537
+ index_fast_set[index_name] = True
1538
+ break
1539
+
1540
+ # replace None as index name with "date", the default index type.
1541
+ for i_index, index_name in enumerate(self.index_names):
1542
+ if index_name is None:
1543
+ self.index_names[i_index] = "date"
1544
+
1545
+ for i_index, index_name in enumerate(self.index_names):
1546
+ if index_name in index_convert_to.keys():
1547
+ convert_to_type = index_convert_to[index_name]
1548
+ else:
1549
+ convert_to_type = None
1550
+ if isinstance(table_data.index, pandas.MultiIndex):
1551
+ index_values = table_data.index.get_level_values(index_name).to_numpy(dtype=convert_to_type)
1552
+ else:
1553
+ index_values = table_data.index.to_numpy(dtype=convert_to_type)
1554
+ if index_name in index_fast_set.keys() and index_fast_set[index_name]:
1555
+ if convert_to_type == numpy.datetime64:
1556
+ # convert index_values to utc timezone and then to timestamp
1557
+ # TODO: check if original dataframe values is unaltered
1558
+ index_values = index_values.astype('datetime64[s]').astype(dt.datetime)
1559
+ # for each value, convert to timestamp
1560
+ for ix, x in enumerate(index_values):
1561
+ index_values[ix] = int(x.replace(tzinfo=dt.timezone.utc).timestamp() + _date_transform)
1562
+ # convert to int64
1563
+ index_values = index_values.astype(numpy.int64)
1564
+ ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
1565
+ factorylib.lib.psrd_table_index_set_date_values(_df.handler(),
1566
+ i_index,
1567
+ ptr,
1568
+ self._err.handler())
1569
+ if self._err.code != 0:
1570
+ raise FactoryException(self._err.what)
1571
+ elif convert_to_type == numpy.int32:
1572
+ ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
1573
+ factorylib.lib.psrd_table_index_set_int_values(_df.handler(),
1574
+ i_index,
1575
+ ptr,
1576
+ self._err.handler())
1577
+ if self._err.code != 0:
1578
+ raise FactoryException(self._err.what)
1579
+ elif convert_to_type == numpy.float32:
1580
+ ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
1581
+ factorylib.lib.psrd_table_index_set_float_values(_df.handler(),
1582
+ i_index,
1583
+ ptr,
1584
+ self._err.handler())
1585
+ if self._err.code != 0:
1586
+ raise FactoryException(self._err.what)
1587
+ elif convert_to_type == numpy.float64:
1588
+ ptr = index_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
1589
+ factorylib.lib.psrd_table_index_set_double_values(_df.handler(),
1590
+ i_index,
1591
+ ptr,
1592
+ self._err.handler())
1593
+ if self._err.code != 0:
1594
+ raise FactoryException(self._err.what)
1595
+ else:
1596
+ raise FactoryException("Unsupported index type: " + str(convert_to_type))
1597
+ else:
1598
+ for i_row, column_value in enumerate(index_values):
1599
+ self._value.set(column_value)
1600
+ factorylib.lib.psrd_table_index_set_value(_df.handler(),
1601
+ i_index,
1602
+ i_row,
1603
+ self._value.handler(),
1604
+ self._err.handler())
1605
+ if self._err.code != 0:
1606
+ raise FactoryException(self._err.what)
1607
+
1608
+ for i_column, column_name in enumerate(self.column_names):
1609
+ if column_name in column_convert_to.keys():
1610
+ convert_to_type = column_convert_to[column_name]
1611
+ else:
1612
+ convert_to_type = None
1613
+ column_values = table_data[column_name].to_numpy(dtype=convert_to_type)
1614
+ if column_name in column_fast_set.keys() and column_fast_set[column_name]:
1615
+ if convert_to_type == numpy.float64:
1616
+ ptr = column_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
1617
+ factorylib.lib.psrd_table_column_set_double_values(_df.handler(),
1618
+ i_column,
1619
+ ptr,
1620
+ self._err.handler())
1621
+ if self._err.code != 0:
1622
+ raise FactoryException(self._err.what)
1623
+ elif convert_to_type == numpy.int32:
1624
+ ptr = column_values.ctypes.data_as(ctypes.POINTER(convert_to_ctype[convert_to_type]))
1625
+ factorylib.lib.psrd_table_column_set_int_values(_df.handler(),
1626
+ i_column,
1627
+ ptr,
1628
+ self._err.handler())
1629
+ if self._err.code != 0:
1630
+ raise FactoryException(self._err.what)
1631
+ else:
1632
+ column_values = table_data[column_name]
1633
+ for i_row, column_value in enumerate(column_values):
1634
+ self._value.set(column_value)
1635
+ factorylib.lib.psrd_table_column_set_value(_df.handler(),
1636
+ i_column,
1637
+ i_row,
1638
+ self._value.handler(),
1639
+ self._err.handler())
1640
+ if self._err.code != 0:
1641
+ raise FactoryException(self._err.what)
1642
+ return _df
1643
+
1644
+
1645
+ def build_polars_dataframe(self, **kwargs) -> "polars.DataFrame":
1646
+ use_object_dtype = kwargs.get("use_object_dtype", True)
1647
+ if not _has_polars():
1648
+ raise ModuleNotFoundError("polars required.")
1649
+ def convert_column_values(column_name:str, values):
1650
+ if isinstance(values, list):
1651
+ return values
1652
+ # Looks like ctype array, smells like ctype array
1653
+ if hasattr(values, "_length_") and hasattr(values, "_type_"):
1654
+ return polars.Series(column_name, numpy.ctypeslib.as_array(values))
1655
+ return values
1656
+
1657
+ data = {column.name: convert_column_values(column.name, column.values)
1658
+ for column in self.indices + self.columns}
1659
+ if use_object_dtype:
1660
+ return polars.DataFrame(data=data, dtype=object)
1661
+ else:
1662
+ return polars.DataFrame(data=data)
1663
+
1664
+ def build_from_polars(self, table_data: "polars.DataFrame") -> "DataFrame":
1665
+ # check if the table has indices and if its multi-index or common index
1666
+ _index_names = ("year", "week", "month", "hour", "scenario", "block", "stage")
1667
+ column_index = 0
1668
+ data_columns = table_data.columns[:]
1669
+ index_columns = []
1670
+ while column_index < len(data_columns):
1671
+ if data_columns[column_index] in _index_names:
1672
+ index_columns.append(data_columns.pop(column_index))
1673
+ continue
1674
+ column_index += 1
1675
+ self.column_types = [self._polars_dtype_to_column_type(table_data[column_name].dtype) for column_name in data_columns]
1676
+ self.index_types = [self._polars_dtype_to_column_type(table_data[index_name].dtype) for index_name in index_columns]
1677
+
1678
+ self.column_names = data_columns
1679
+ self.index_names = index_columns
1680
+ rows = table_data.height
1681
+ _df = self._pre_build_generic(rows, self.index_types, self.column_types)
1682
+
1683
+ for i_row, all_row_values in enumerate(table_data.iter_rows()):
1684
+ index = all_row_values[:len(index_columns)]
1685
+ row_values = all_row_values[len(index_columns):]
1686
+ self._set_row_values(_df, i_row, index, row_values)
1687
+ return _df
1688
+
1689
+ def _pre_build_generic(self, rows: int, index_types: List[int], column_types: List[int]) -> "DataFrame":
1690
+ _df = DataFrame()
1691
+ self._err = Error()
1692
+ self._value = Value()
1693
+
1694
+ factorylib.lib.psrd_table_resize(_df.handler(), rows,
1695
+ self._err.handler())
1696
+ if self._err.code != 0:
1697
+ raise FactoryException(self._err.what)
1698
+
1699
+ for i_index, index_type in enumerate(index_types):
1700
+ factorylib.lib.psrd_table_configure_index(_df.handler(),
1701
+ i_index,
1702
+ index_type,
1703
+ self._err.handler())
1704
+ if self._err.code != 0:
1705
+ raise FactoryException(self._err.what)
1706
+ for i_column, column_type in enumerate(column_types):
1707
+ factorylib.lib.psrd_table_configure_column(_df.handler(),
1708
+ i_column,
1709
+ column_type,
1710
+ self._err.handler())
1711
+ if self._err.code != 0:
1712
+ raise FactoryException(self._err.what)
1713
+
1714
+ # Set column names
1715
+ for i_column, column_name in enumerate(self.column_names):
1716
+ factorylib.lib.psrd_table_column_set_name(_df.handler(),
1717
+ i_column,
1718
+ _c_str(column_name),
1719
+ _bytes(column_name),
1720
+ self._err.handler())
1721
+ if self._err.code != 0:
1722
+ raise FactoryException(self._err.what)
1723
+
1724
+ # Set index names
1725
+ for i_index, index_name in enumerate(self.index_names):
1726
+ factorylib.lib.psrd_table_index_set_name(_df.handler(),
1727
+ i_index,
1728
+ _c_str(index_name),
1729
+ _bytes(index_name),
1730
+ self._err.handler())
1731
+ if self._err.code != 0:
1732
+ raise FactoryException(self._err.what)
1733
+
1734
+ return _df
1735
+
1736
+ def _set_row_values(self, df: "DataFrame", i_row: int, index_values: List[Union[int, float, str]], column_values: List[Union[int, float, str]]):
1737
+ self._value = Value()
1738
+ for i_index, index_value in enumerate(index_values):
1739
+ self._value.set(index_value)
1740
+ factorylib.lib.psrd_table_index_set_value(df.handler(),
1741
+ i_index,
1742
+ i_row,
1743
+ self._value.handler(),
1744
+ self._err.handler())
1745
+ if self._err.code != 0:
1746
+ raise FactoryException(self._err.what)
1747
+
1748
+ for i_column, column_value in enumerate(column_values):
1749
+ self._value.set(column_value)
1750
+ factorylib.lib.psrd_table_column_set_value(df.handler(),
1751
+ i_column,
1752
+ i_row,
1753
+ self._value.handler(),
1754
+ self._err.handler())
1755
+ if self._err.code != 0:
1756
+ raise FactoryException(self._err.what)
1757
+
1758
+
1759
+ class DataFrame(_BaseObject):
1760
+ def __init__(self):
1761
+ super().__init__()
1762
+ self._hdr = factorylib.lib.psrd_new_table()
1763
+ self._not_built = True
1764
+
1765
+ def __del__(self):
1766
+ if self._hdr is not None:
1767
+ factorylib.lib.psrd_free_table(self._hdr)
1768
+
1769
+ @staticmethod
1770
+ def load_from_file(input_file: Union[str, pathlib.Path], options: Optional[DataObject] = None) -> "DataFrame":
1771
+ input_file = str(input_file)
1772
+ _check_initialized()
1773
+ _err = Error()
1774
+ table = DataFrame()
1775
+ options_handler = options.handler() if options is not None else None
1776
+ factorylib.lib.psrd_table_load(table.handler(),
1777
+ _c_str(input_file),
1778
+ _bytes(input_file),
1779
+ options_handler,
1780
+ _err.handler())
1781
+ if _err.code != 0:
1782
+ raise FactoryException(_err.what)
1783
+ return table
1784
+
1785
+ @staticmethod
1786
+ def from_dataframe(df: Union["pandas.DataFrame", "polars.DataFrame"], **kwargs) -> "DataFrame":
1787
+ _check_initialized()
1788
+ df_builder = _DataFrameBuilder()
1789
+ if _has_pandas() and isinstance(df, pandas.DataFrame):
1790
+ dataframe_like = pandas.api.interchange.from_dataframe(df)
1791
+ return df_builder.build_from_pandas(dataframe_like)
1792
+ if _has_polars() and isinstance(df, polars.DataFrame):
1793
+ dataframe_like = polars.from_dataframe(df)
1794
+ # FIXME: needs auto tests.
1795
+ return df_builder.build_from_polars(dataframe_like)
1796
+ raise ImportError("Pandas or polars is not available. Please install pandas to use this feature.")
1797
+
1798
+ def save(self, output_file: Union[str, pathlib.Path], options: Optional[DataObject] = None):
1799
+ output_file = str(output_file)
1800
+ _err = Error()
1801
+ options_handler = options.handler() if options is not None else None
1802
+ factorylib.lib.psrd_table_save(self._hdr, _c_str(output_file),
1803
+ _bytes(output_file),
1804
+ options_handler,
1805
+ _err.handler())
1806
+ if _err.code != 0:
1807
+ raise FactoryException(_err.what)
1808
+
1809
+ def to_pandas(self) -> "pandas.DataFrame":
1810
+ df_builder = _DataFrameBuilder()
1811
+ df_builder.build_dataframe_of_integral_types(self)
1812
+ return df_builder.build_pandas_dataframe(use_object_dtype=False)
1813
+
1814
+ def to_polars(self) -> "polars.DataFrame":
1815
+ df_builder = _DataFrameBuilder()
1816
+ df_builder.build_dataframe_of_integral_types(self)
1817
+ return df_builder.build_polars_dataframe(use_object_dtype=False)
1818
+
1819
+
1820
+ def load_dataframe(input_file: Union[str, pathlib.Path], **kwargs) -> DataFrame:
1821
+ options = kwargs.get("options", None)
1822
+ return DataFrame.load_from_file(input_file, options)
1823
+
1824
+
1825
+ def create_dataframe(data: "pandas.DataFrame", **kwargs) -> DataFrame:
1826
+ return DataFrame.from_dataframe(data, **kwargs)
1827
+
1828
+
1829
+ def _load_library():
1830
+ global _loaded
1831
+ global _loaded_lock
1832
+ with _loaded_lock:
1833
+ factorylib.initialize()
1834
+ _loaded = True
1835
+ return _loaded
1836
+
1837
+
1838
+
1839
+ def _initialize():
1840
+ global _initialized
1841
+ global _initialized_lock
1842
+ with _initialized_lock:
1843
+ _check_loaded()
1844
+ _err = Error()
1845
+
1846
+ # Set binding info
1847
+ map_prop_values = {
1848
+ "NULL_TYPE": "None",
1849
+ "LIST_TYPE": "list",
1850
+ "INDEX_STARTS_AT_ZERO": True,
1851
+ "NAME": "Python",
1852
+ "VERSION": f"{sys.version}",
1853
+ "EXE": f"{sys.executable}",
1854
+ "LIB": f"{factorylib.get_lib_path()}",
1855
+ "BASE_PREFIX": f"{sys.base_prefix}",
1856
+ "REAL_PREFIX": f"{sys.prefix}",
1857
+ }
1858
+ for prop, value in map_prop_values.items():
1859
+ _value = Value()
1860
+ _value.set(value)
1861
+ factorylib.lib.psrd_set_binding_property(_c_str(prop),
1862
+ _bytes(prop),
1863
+ _value.handler(),
1864
+ _err.handler())
1865
+ if _err.code != 0:
1866
+ raise FactoryException(_err.what)
1867
+
1868
+ # Where to look for pmd and pmk files
1869
+ common_path = os.path.dirname(__file__)
1870
+ factorylib.lib.psrd_initialize(_c_str(common_path),
1871
+ _bytes(common_path),
1872
+ _err.handler())
1873
+ if _err.code != 0:
1874
+ raise FactoryException(_err.what)
1875
+ _initialized = True
1876
+
1877
+
1878
+ def _unload():
1879
+ _err = Error()
1880
+ factorylib.lib.psrd_unload(_err.handler())
1881
+ if _err.code != 0:
1882
+ raise FactoryException(_err.what)
1883
+
1884
+
1885
+ def help(context: str = "") -> str:
1886
+ _err = Error()
1887
+ size = factorylib.lib.psrd_help(_c_str(context), _bytes(context),
1888
+ None, 0, _err.handler())
1889
+ if _err.code != 0:
1890
+ raise FactoryException(_err.what)
1891
+ buffer = ctypes.create_string_buffer(size)
1892
+ factorylib.lib.psrd_help(_c_str(context), _bytes(context),
1893
+ buffer, size, _err.handler())
1894
+ if _err.code != 0:
1895
+ raise FactoryException(_err.what)
1896
+ return _from_c_str(buffer.value)
1897
+
1898
+
1899
+ def create_study(*args, **kwargs) -> Study:
1900
+ blocks = kwargs.get("blocks", None)
1901
+ models = kwargs.get("models", None)
1902
+ context = kwargs.get("context", None) if len(args) == 0 else args[0]
1903
+ profile = kwargs.get("profile", None)
1904
+ if models is None and profile is not None and len(profile) > 0:
1905
+ models = [profile, ]
1906
+ profile_or_context = models if models is not None and len(models) > 0 \
1907
+ else context
1908
+ return Study.create_object(profile_or_context, blocks)
1909
+
1910
+
1911
+ def load_study(study_path: Union[str, pathlib.Path],
1912
+ profile_or_context: Union[str, Context, None] = None,
1913
+ options: Optional[DataObject] = None) -> Study:
1914
+ return Study.load(study_path, profile_or_context, options)
1915
+
1916
+
1917
+ def create(class_name: str,
1918
+ profile_or_context: Union[str, Context, None] = None) -> Optional[DataObject]:
1919
+ _check_initialized()
1920
+ obj = DataObject()
1921
+ _err = Error()
1922
+ context = _get_context(profile_or_context, None) \
1923
+ if class_name != "Context" else None
1924
+ context_hdr = context.handler() if context is not None else None
1925
+ ref = factorylib.lib.psrd_create(_c_str(class_name),
1926
+ context_hdr,
1927
+ _err.handler())
1928
+ if _err.code != 0 or ref is None:
1929
+ raise FactoryException(_err.what)
1930
+ obj._hdr = ref
1931
+ return obj
1932
+
1933
+
1934
+ def get_default_context() -> "Context":
1935
+ _check_initialized()
1936
+ return Context.default_context()
1937
+
1938
+
1939
+ def get_new_context() -> "Context":
1940
+ _check_initialized()
1941
+ return Context.create()
1942
+
1943
+
1944
+ def get_default_encoding() -> str:
1945
+ return _preferred_encoding
1946
+
1947
+
1948
+ def set_default_encoding(encoding: str):
1949
+ global _preferred_encoding
1950
+ _preferred_encoding = encoding