PySimultan 0.4.22__py3-none-any.whl → 0.5.2.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PySimultan2/CHANGELOG.md +4 -0
- PySimultan2/__about__.py +1 -1
- PySimultan2/__init__.py +1 -0
- PySimultan2/data_model.py +185 -80
- PySimultan2/default_types.py +125 -23
- PySimultan2/files.py +55 -5
- PySimultan2/object_mapper.py +146 -9
- PySimultan2/resources/ComponentBuilder.dll +0 -0
- PySimultan2/resources/ComponentBuilder.runtimeconfig.json +2 -1
- PySimultan2/resources/ComponentBuilder.xml +47 -1
- PySimultan2/resources/SIMULTAN.AutoUpdate.Client.dll +0 -0
- PySimultan2/resources/SIMULTAN.AutoUpdate.DataTransferLibrary.dll +0 -0
- PySimultan2/resources/SIMULTAN.Lang.dll +0 -0
- PySimultan2/resources/SIMULTAN.Lang.xml +94 -7
- PySimultan2/resources/SIMULTAN.Plugins.dll +0 -0
- PySimultan2/resources/SIMULTAN.UI.dll +0 -0
- PySimultan2/resources/SIMULTAN.UI.xml +136 -43
- PySimultan2/resources/SIMULTAN.dll +0 -0
- PySimultan2/resources/SIMULTAN.xml +364 -97
- PySimultan2/resources/System.Collections.Immutable.dll +0 -0
- PySimultan2/resources/System.Reflection.Metadata.dll +0 -0
- PySimultan2/resources/System.Reflection.MetadataLoadContext.dll +0 -0
- PySimultan2/resources/componentmanager.user +0 -0
- PySimultan2/simultan_object.py +64 -15
- PySimultan2/taxonomy_maps.py +20 -12
- PySimultan2/type_setter_lookup.py +46 -33
- PySimultan2/utils.py +79 -14
- {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/METADATA +2 -3
- {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/RECORD +31 -32
- {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/WHEEL +1 -1
- PySimultan2/resources/GeometryViewer.dll +0 -0
- PySimultan2/resources/GeometryViewer.dll.config +0 -42
- PySimultan2/resources/GeometryViewer.xml +0 -6425
- PySimultan2/resources/SitePlanner.dll +0 -0
- PySimultan2/resources/SitePlanner.dll.config +0 -11
- PySimultan2/resources/SitePlanner.xml +0 -2736
- {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/licenses/LICENSE.txt +0 -0
PySimultan2/default_types.py
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import xxsubtype
|
4
3
|
from collections.abc import Iterable
|
5
4
|
import numpy as np
|
6
|
-
import pandas as pd
|
7
5
|
import colorlog
|
8
6
|
from typing import Union, List, Type, Set, Tuple, Any, Optional
|
9
7
|
|
@@ -139,11 +137,19 @@ class ComponentList(SimultanObject):
|
|
139
137
|
|
140
138
|
def append(self, values: Union[SimultanObject, List]):
|
141
139
|
|
140
|
+
return_val = []
|
141
|
+
|
142
|
+
as_list = True
|
142
143
|
if not isinstance(values, Iterable):
|
144
|
+
as_list = False
|
143
145
|
values = [values]
|
144
146
|
|
145
147
|
for i, value in enumerate(values, start=len(self.data)):
|
146
|
-
self._set_value(value, i)
|
148
|
+
return_val.append(self._set_value(value, i))
|
149
|
+
|
150
|
+
if not as_list:
|
151
|
+
return return_val[0]
|
152
|
+
return return_val
|
147
153
|
|
148
154
|
def _update_slot_extensions(self, index: int):
|
149
155
|
|
@@ -160,6 +166,9 @@ class ComponentList(SimultanObject):
|
|
160
166
|
|
161
167
|
def _set_value(self, value, i):
|
162
168
|
|
169
|
+
if isinstance(value, FileInfo):
|
170
|
+
raise ValueError(f'FileInfos cannot be added to ComponentLists')
|
171
|
+
|
163
172
|
if isinstance(value, SimultanObject):
|
164
173
|
slot = value._wrapped_obj.Slots.Items[0]
|
165
174
|
|
@@ -171,6 +180,9 @@ class ComponentList(SimultanObject):
|
|
171
180
|
self.add_referenced_component(value._wrapped_obj,
|
172
181
|
slot_extension=str(i),
|
173
182
|
slot=slot)
|
183
|
+
|
184
|
+
return value
|
185
|
+
|
174
186
|
else:
|
175
187
|
new_val = create_mapped_python_object(value,
|
176
188
|
data_model=self._data_model,
|
@@ -193,6 +205,8 @@ class ComponentList(SimultanObject):
|
|
193
205
|
slot_extension=str(i),
|
194
206
|
slot=taxonomy_entry)
|
195
207
|
|
208
|
+
return new_val
|
209
|
+
|
196
210
|
def __setitem__(self, i, value):
|
197
211
|
if isinstance(i, slice):
|
198
212
|
for j, val in enumerate(value):
|
@@ -210,7 +224,7 @@ class ComponentList(SimultanObject):
|
|
210
224
|
self._set_value(value, i)
|
211
225
|
|
212
226
|
def extend(self, values: List):
|
213
|
-
self.append(values)
|
227
|
+
return self.append(values)
|
214
228
|
|
215
229
|
def remove(self, value: SimultanObject):
|
216
230
|
self.discard(value)
|
@@ -292,6 +306,41 @@ class ComponentList(SimultanObject):
|
|
292
306
|
self._wrapped_obj.Components.Clear()
|
293
307
|
self._wrapped_obj.ReferencedComponents.Clear()
|
294
308
|
|
309
|
+
def to_json(self) -> dict[Any: Any]:
|
310
|
+
|
311
|
+
return_val = [None] * len(self.data)
|
312
|
+
|
313
|
+
for i, val in enumerate(self.data):
|
314
|
+
|
315
|
+
if hasattr(val, 'json_ref'):
|
316
|
+
return_val[i] = val.json_ref()
|
317
|
+
elif isinstance(val, list):
|
318
|
+
return_val[i] = [v.json_ref() if hasattr(v, 'json_ref') else v for v in val]
|
319
|
+
elif isinstance(val, dict):
|
320
|
+
return_val[i] = {k: v.json_ref() if hasattr(v, 'json_ref') else v for k, v in val.items()}
|
321
|
+
elif isinstance(val, np.ndarray):
|
322
|
+
return_val[i] = val.tolist()
|
323
|
+
else:
|
324
|
+
return_val[i] = val
|
325
|
+
|
326
|
+
return {
|
327
|
+
str(self.id): {
|
328
|
+
'name': self.name,
|
329
|
+
'taxonomies': self.taxonomy_keys,
|
330
|
+
'items': return_val
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
def json_ref(self):
|
335
|
+
return {"$ref": {
|
336
|
+
"$type": 'ComponentList',
|
337
|
+
"$taxonomies": self.taxonomy_keys,
|
338
|
+
"$id": {'local_id': self.id.LocalId,
|
339
|
+
'global_id': str(self.id.GlobalId)
|
340
|
+
},
|
341
|
+
"length": len(self)
|
342
|
+
}
|
343
|
+
}
|
295
344
|
|
296
345
|
component_list_map = TaxonomyMap(taxonomy_name='PySimultan',
|
297
346
|
taxonomy_key='PySimultan',
|
@@ -319,9 +368,11 @@ class ComponentDictionary(SimultanObject):
|
|
319
368
|
self._dict = {}
|
320
369
|
super().__init__(*args, **kwargs)
|
321
370
|
self.component_policy = kwargs.get('component_policy', 'subcomponent') # component add policy of the content/parameter/property, 'reference' or 'subcomponent'
|
371
|
+
self._generate_internal_dict()
|
322
372
|
|
323
373
|
def __load_init__(self, *args, **kwargs):
|
324
374
|
self._dict = {}
|
375
|
+
self._generate_internal_dict()
|
325
376
|
|
326
377
|
@classmethod
|
327
378
|
def create_from_values(cls,
|
@@ -348,15 +399,20 @@ class ComponentDictionary(SimultanObject):
|
|
348
399
|
for key, value in values.items():
|
349
400
|
new_component_dict[key] = value
|
350
401
|
|
402
|
+
new_component_dict._generate_internal_dict()
|
403
|
+
|
351
404
|
return new_component_dict
|
352
405
|
|
353
406
|
def __getitem__(self, key, *args, **kwargs):
|
354
407
|
|
355
408
|
comp_dict = object.__getattribute__(self, '_dict')
|
356
409
|
|
357
|
-
if kwargs.get('check_dict',
|
358
|
-
|
359
|
-
|
410
|
+
if (kwargs.get('check_dict', False) and comp_dict is not None and
|
411
|
+
(key in comp_dict.keys() or '__dict_key__' + key in comp_dict.keys())):
|
412
|
+
if key in comp_dict.keys():
|
413
|
+
return comp_dict.get(key, None)
|
414
|
+
else:
|
415
|
+
return comp_dict.get('__dict_key__' + key, None)
|
360
416
|
else:
|
361
417
|
# data_model = config.default_data_model
|
362
418
|
# obj = get_component_taxonomy_entry(self._wrapped_obj, key)
|
@@ -406,6 +462,8 @@ class ComponentDictionary(SimultanObject):
|
|
406
462
|
object_mapper=object_mapper)
|
407
463
|
|
408
464
|
if val is not None:
|
465
|
+
if key.startswith('__dict_key__'):
|
466
|
+
key = key.replace('__dict_key__', '')
|
409
467
|
self._dict[key] = val
|
410
468
|
|
411
469
|
return self._dict.get(key, None)
|
@@ -454,27 +512,32 @@ class ComponentDictionary(SimultanObject):
|
|
454
512
|
return
|
455
513
|
|
456
514
|
from .type_setter_lookup import type_setter_fcn_lookup_dict
|
457
|
-
setter_fcn = type_setter_fcn_lookup_dict.get(
|
515
|
+
setter_fcn = type_setter_fcn_lookup_dict.get(value, set_property_to_unknown_type)
|
458
516
|
|
459
517
|
setter_fcn(*fcn_arg_list)
|
460
518
|
item = self.__getitem__(key, check_dict=False)
|
461
519
|
|
462
|
-
|
520
|
+
if key.startswith('__dict_key__'):
|
521
|
+
self._dict[key.replace('__dict_key__', '')] = item
|
522
|
+
else:
|
523
|
+
self._dict[key] = item
|
463
524
|
|
464
525
|
def __delitem__(self, key):
|
465
526
|
self[key] = None
|
466
527
|
del self._dict[key]
|
467
528
|
|
468
529
|
def items(self):
|
530
|
+
if self._dict is None or not self._dict:
|
531
|
+
self._generate_internal_dict()
|
469
532
|
return self._dict.items()
|
470
533
|
|
471
534
|
def keys(self):
|
472
|
-
if not self._dict:
|
535
|
+
if not self._dict or not self._dict:
|
473
536
|
self._generate_internal_dict()
|
474
537
|
return self._dict.keys()
|
475
538
|
|
476
539
|
def values(self):
|
477
|
-
if not self._dict:
|
540
|
+
if not self._dict or not self._dict:
|
478
541
|
self._generate_internal_dict()
|
479
542
|
return self._dict.values()
|
480
543
|
|
@@ -482,22 +545,26 @@ class ComponentDictionary(SimultanObject):
|
|
482
545
|
comp_dict = {}
|
483
546
|
|
484
547
|
for parameter in self._wrapped_obj.Parameters.Items:
|
485
|
-
|
486
|
-
|
487
|
-
|
548
|
+
key = parameter.NameTaxonomyEntry.TextOrKey.replace('__dict_key__', '')
|
549
|
+
comp_dict[key] = get_obj_value(parameter,
|
550
|
+
data_model=self._data_model,
|
551
|
+
object_mapper=self._object_mapper)
|
488
552
|
for component in self._wrapped_obj.Components.Items:
|
489
|
-
|
490
|
-
|
491
|
-
|
553
|
+
key = component.Slot.SlotBase.Target.Key.replace('__dict_key__', '')
|
554
|
+
comp_dict[key] = get_obj_value(component.Component,
|
555
|
+
data_model=self._data_model,
|
556
|
+
object_mapper=self._object_mapper)
|
492
557
|
for ref_component in self._wrapped_obj.ReferencedComponents.Items:
|
493
|
-
|
494
|
-
|
495
|
-
|
558
|
+
key = ref_component.Slot.SlotBase.Target.Key.replace('__dict_key__', '')
|
559
|
+
comp_dict[key] = get_obj_value(ref_component.Target,
|
560
|
+
data_model=self._data_model,
|
561
|
+
object_mapper=self._object_mapper)
|
496
562
|
for ref_asset in self._wrapped_obj.ReferencedAssets.Items:
|
497
563
|
for tag in ref_asset.Resource.Tags:
|
498
|
-
|
499
|
-
|
500
|
-
|
564
|
+
key = tag.Target.Key.replace('__dict_key__', '')
|
565
|
+
comp_dict[key] = get_obj_value(ref_asset.Target,
|
566
|
+
data_model=self._data_model,
|
567
|
+
object_mapper=self._object_mapper)
|
501
568
|
|
502
569
|
object.__setattr__(self, '_dict', comp_dict)
|
503
570
|
|
@@ -529,5 +596,40 @@ class ComponentDictionary(SimultanObject):
|
|
529
596
|
for key, value in other.items():
|
530
597
|
self[key] = value
|
531
598
|
|
599
|
+
def to_json(self) -> dict:
|
600
|
+
|
601
|
+
return_value = {}
|
602
|
+
|
603
|
+
for key, value in self.items():
|
604
|
+
if isinstance(value, SimultanObject):
|
605
|
+
return_value[key] = value.to_json()
|
606
|
+
elif isinstance(value, list):
|
607
|
+
return_value[key] = [v.json_ref() if hasattr(v, 'json_ref') else v for v in value]
|
608
|
+
elif isinstance(value, dict):
|
609
|
+
return_value[key] = {k: v.json_ref() if hasattr(v, 'json_ref') else v for k, v in value.items()}
|
610
|
+
elif isinstance(value, np.ndarray):
|
611
|
+
return_value[key] = value.tolist()
|
612
|
+
else:
|
613
|
+
return_value[key] = value
|
614
|
+
|
615
|
+
return {
|
616
|
+
str(self.id): {
|
617
|
+
'name': self.name,
|
618
|
+
'taxonomies': self.taxonomy_keys,
|
619
|
+
'items': return_value
|
620
|
+
}
|
621
|
+
}
|
622
|
+
|
623
|
+
def json_ref(self):
|
624
|
+
return {"$ref": {
|
625
|
+
"$type": 'ComponentDictionary',
|
626
|
+
"$taxonomies": self.taxonomy_keys,
|
627
|
+
"$id": {'local_id': self.id.LocalId,
|
628
|
+
'global_id': str(self.id.GlobalId)
|
629
|
+
},
|
630
|
+
"length": len(self)
|
631
|
+
}
|
632
|
+
}
|
633
|
+
|
532
634
|
|
533
635
|
component_dict_map = ComponentDictionary._taxonomy_map
|
PySimultan2/files.py
CHANGED
@@ -81,9 +81,17 @@ def add_asset_to_component(comp: [SimComponent, SimultanObject],
|
|
81
81
|
wrapped_obj = comp if isinstance(comp, SimComponent) else comp._wrapped_obj
|
82
82
|
|
83
83
|
if tag is not None:
|
84
|
-
|
84
|
+
try:
|
85
|
+
add_tag_to_resource(asset, tag)
|
86
|
+
except Exception as e:
|
87
|
+
logger.error(f'Error adding tag to asset {asset}: {e} ')
|
88
|
+
raise e
|
85
89
|
|
86
|
-
|
90
|
+
try:
|
91
|
+
return ComponentMapping.AddAsset(wrapped_obj, asset, content_id)
|
92
|
+
except Exception as e:
|
93
|
+
logger.error(f'Error adding asset {asset} to component: {e}')
|
94
|
+
raise e
|
87
95
|
|
88
96
|
|
89
97
|
def remove_asset_from_component(comp: Union[SimComponent, SimultanObject],
|
@@ -187,7 +195,9 @@ class FileInfo(object, metaclass=MetaMock):
|
|
187
195
|
_cls_instances = {}
|
188
196
|
|
189
197
|
@classmethod
|
190
|
-
def from_string(cls,
|
198
|
+
def from_string(cls,
|
199
|
+
filename: str,
|
200
|
+
content: str, *args, **kwargs) -> FileInfo:
|
191
201
|
"""
|
192
202
|
Create a file info object from a string.
|
193
203
|
:param filename: Name of the file to be created. E.g. 'new_file.txt'
|
@@ -237,6 +247,13 @@ class FileInfo(object, metaclass=MetaMock):
|
|
237
247
|
self.args = args
|
238
248
|
self.kwargs = kwargs
|
239
249
|
|
250
|
+
@property
|
251
|
+
def key(self) -> int:
|
252
|
+
try:
|
253
|
+
return self.resource_entry.Key
|
254
|
+
except Exception as e:
|
255
|
+
return None
|
256
|
+
|
240
257
|
@property
|
241
258
|
def resource_entry(self) -> Union[ResourceFileEntry, ContainedResourceFileEntry, None]:
|
242
259
|
if self._resource_entry is None:
|
@@ -258,8 +275,13 @@ class FileInfo(object, metaclass=MetaMock):
|
|
258
275
|
self._resource_entry = value
|
259
276
|
|
260
277
|
@property
|
261
|
-
def file_size(self) -> int:
|
262
|
-
|
278
|
+
def file_size(self) -> Optional[int]:
|
279
|
+
try:
|
280
|
+
return os.path.getsize(self.file_path)
|
281
|
+
except FileNotFoundError:
|
282
|
+
raise FileNotFoundError(f'File not found: {self.file_path}')
|
283
|
+
except Exception as e:
|
284
|
+
raise e
|
263
285
|
|
264
286
|
@property
|
265
287
|
def last_modified(self) -> datetime:
|
@@ -269,6 +291,10 @@ class FileInfo(object, metaclass=MetaMock):
|
|
269
291
|
def resource_entry(self, value):
|
270
292
|
self._resource_entry = value
|
271
293
|
|
294
|
+
@property
|
295
|
+
def filename(self) -> str:
|
296
|
+
return self.resource_entry.File.Name
|
297
|
+
|
272
298
|
@property
|
273
299
|
def name(self) -> str:
|
274
300
|
return os.path.basename(self.file_path)
|
@@ -317,6 +343,9 @@ class FileInfo(object, metaclass=MetaMock):
|
|
317
343
|
def __exit__(self, *args):
|
318
344
|
self.file_obj.close()
|
319
345
|
|
346
|
+
def __repr__(self):
|
347
|
+
return f'FileInfo({self.file_path})'
|
348
|
+
|
320
349
|
def get_content(self, encoding='utf-8') -> Optional[Union[str, dict[str, str]]]:
|
321
350
|
"""
|
322
351
|
Get the content of the file.
|
@@ -373,3 +402,24 @@ class FileInfo(object, metaclass=MetaMock):
|
|
373
402
|
if self.resource_entry is not None:
|
374
403
|
self.data_model.delete_resource(self.resource_entry)
|
375
404
|
os.remove(self.file_path)
|
405
|
+
|
406
|
+
def to_json(self) -> dict:
|
407
|
+
|
408
|
+
obj_dict = {
|
409
|
+
'key': self.key,
|
410
|
+
'name': self.name,
|
411
|
+
'file_path': self.file_path,
|
412
|
+
'file_size': self.file_size,
|
413
|
+
'last_modified': self.last_modified,
|
414
|
+
'encoding': self.encoding,
|
415
|
+
'is_zip': self.is_zip,
|
416
|
+
}
|
417
|
+
|
418
|
+
return obj_dict
|
419
|
+
|
420
|
+
def json_ref(self):
|
421
|
+
return {"$ref": {
|
422
|
+
"$type": 'FileInfo',
|
423
|
+
"$key": str(self.key)
|
424
|
+
}
|
425
|
+
}
|
PySimultan2/object_mapper.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Optional, Type, TYPE_CHECKING, Union
|
1
|
+
from typing import Optional, Type, TYPE_CHECKING, Union, Any
|
2
2
|
from copy import copy
|
3
3
|
from collections import UserList
|
4
4
|
from colorlog import getLogger
|
@@ -32,9 +32,21 @@ default_taxonomy_maps = {'ComponentList': component_list_map,
|
|
32
32
|
|
33
33
|
class PythonMapper(object):
|
34
34
|
|
35
|
+
mappers = {}
|
36
|
+
|
35
37
|
def __new__(cls, *args, **kwargs):
|
36
38
|
instance = super(PythonMapper, cls).__new__(cls)
|
37
39
|
config.set_default_mapper(instance)
|
40
|
+
|
41
|
+
if kwargs.get('add_to_mappers', True):
|
42
|
+
initial_module_name = kwargs.get('module', 'unknown_module')
|
43
|
+
module_name = initial_module_name
|
44
|
+
i = 0
|
45
|
+
while module_name in cls.mappers.keys():
|
46
|
+
module_name = f'{initial_module_name}_{i}'
|
47
|
+
i+=1
|
48
|
+
cls.mappers[module_name] = instance
|
49
|
+
|
38
50
|
return instance
|
39
51
|
|
40
52
|
def __init__(self, *args, **kwargs):
|
@@ -42,6 +54,9 @@ class PythonMapper(object):
|
|
42
54
|
self._mapped_classes = {}
|
43
55
|
|
44
56
|
self.name = kwargs.get('name', 'PythonMapper')
|
57
|
+
self._module = kwargs.get('module', 'unknown_module')
|
58
|
+
self.submodules = kwargs.get('submodules', {})
|
59
|
+
|
45
60
|
self.registered_classes: dict[str: SimultanObject] = copy(default_registered_classes) # dict with all registered classes: {taxonomy: class}
|
46
61
|
|
47
62
|
self.undefined_registered_classes: dict[str: SimultanObject] = {} # dict with all registered classes: {taxonomy: class}
|
@@ -59,6 +74,18 @@ class PythonMapper(object):
|
|
59
74
|
self.re_register = False
|
60
75
|
self.load_undefined = False
|
61
76
|
|
77
|
+
@property
|
78
|
+
def module(self):
|
79
|
+
return self._module
|
80
|
+
|
81
|
+
@module.setter
|
82
|
+
def module(self, value):
|
83
|
+
if self._module != value:
|
84
|
+
del self.mappers[self._module]
|
85
|
+
|
86
|
+
self._module = value
|
87
|
+
self.mappers[value] = self
|
88
|
+
|
62
89
|
@property
|
63
90
|
def mapped_classes(self):
|
64
91
|
if len(self.registered_classes) > len(self._mapped_classes):
|
@@ -72,10 +99,24 @@ class PythonMapper(object):
|
|
72
99
|
def mapped_classes(self, value):
|
73
100
|
self._mapped_classes = value
|
74
101
|
|
75
|
-
def register(self,
|
76
|
-
|
102
|
+
def register(self,
|
103
|
+
taxonomy: str,
|
104
|
+
cls: Type[Any],
|
105
|
+
re_register=True,
|
106
|
+
update_in_other_mappers=False,
|
107
|
+
taxonomy_map=None):
|
108
|
+
|
109
|
+
# print(f'Registering {taxonomy} with {cls} {hash(cls)}')
|
110
|
+
|
111
|
+
if not (self.re_register or re_register) and taxonomy in self.registered_classes.keys():
|
77
112
|
return
|
78
113
|
|
114
|
+
if taxonomy in self.mapped_classes.keys():
|
115
|
+
try:
|
116
|
+
del self.mapped_classes[taxonomy]
|
117
|
+
except KeyError:
|
118
|
+
pass
|
119
|
+
|
79
120
|
if taxonomy_map is None:
|
80
121
|
taxonomy_map = TaxonomyMap(taxonomy_name='PySimultan',
|
81
122
|
taxonomy_key='PySimultan',
|
@@ -85,8 +126,28 @@ class PythonMapper(object):
|
|
85
126
|
self.registered_classes[taxonomy] = cls
|
86
127
|
self.taxonomy_maps[taxonomy] = taxonomy_map
|
87
128
|
|
129
|
+
if update_in_other_mappers:
|
130
|
+
self.update_from_other_mappers()
|
131
|
+
|
88
132
|
return self.get_mapped_class(taxonomy)
|
89
133
|
|
134
|
+
def update_from_other_mappers(self):
|
135
|
+
for mapper in self.mappers.values():
|
136
|
+
if mapper is not self:
|
137
|
+
for cls, taxonomy in mapper.registered_classes.items():
|
138
|
+
if cls in self.registered_classes.values():
|
139
|
+
key = list(filter(lambda x: mapper.registered_classes[x] == cls,
|
140
|
+
mapper.registered_classes)
|
141
|
+
)[0]
|
142
|
+
mapper.registered_classes[key] = cls
|
143
|
+
print(f'Updated {cls} in {mapper.module} with {taxonomy}')
|
144
|
+
|
145
|
+
def update_from_submodules(self):
|
146
|
+
for submodule in self.submodules.values():
|
147
|
+
self.registered_classes.update(submodule.registered_classes)
|
148
|
+
self.taxonomy_maps.update(submodule.taxonomy_maps)
|
149
|
+
self.registered_geometry_classes.update(submodule.registered_geometry_classes)
|
150
|
+
|
90
151
|
def create_mapped_class(self, taxonomy, cls):
|
91
152
|
|
92
153
|
if any([issubclass(cls, x) for x in (SimultanObject, UserList)]):
|
@@ -171,7 +232,11 @@ class PythonMapper(object):
|
|
171
232
|
typed_data.append(typed_object)
|
172
233
|
return typed_data
|
173
234
|
|
174
|
-
def create_python_geometry_object(self,
|
235
|
+
def create_python_geometry_object(self,
|
236
|
+
component: Union[Layer, Vertex, Edge, PEdge, Face, Volume, EdgeLoop],
|
237
|
+
data_model: 'DataModel' = None,
|
238
|
+
*args,
|
239
|
+
**kwargs):
|
175
240
|
|
176
241
|
if component is None:
|
177
242
|
return None
|
@@ -191,7 +256,7 @@ class PythonMapper(object):
|
|
191
256
|
self.create_python_object(component, data_model, *args, **kwargs)
|
192
257
|
|
193
258
|
def get_mapped_class_from_component(self,
|
194
|
-
component,
|
259
|
+
component: Union[SimComponent, Layer, Vertex, Edge, PEdge, Face, Volume, EdgeLoop],
|
195
260
|
data_model: Optional['DataModel'] = None,
|
196
261
|
*args,
|
197
262
|
**kwargs) -> Optional[Type[SimultanObject]]:
|
@@ -205,7 +270,10 @@ class PythonMapper(object):
|
|
205
270
|
if isinstance(component,
|
206
271
|
(Layer, Vertex, Edge, PEdge, Face, Volume, EdgeLoop)
|
207
272
|
):
|
208
|
-
self.create_python_geometry_object(component,
|
273
|
+
self.create_python_geometry_object(component,
|
274
|
+
data_model,
|
275
|
+
*args,
|
276
|
+
**kwargs)
|
209
277
|
|
210
278
|
c_slots = [x.Target.Key for x in component.Slots.Items]
|
211
279
|
c_slot = list(set(c_slots) & set(self.registered_classes.keys()))
|
@@ -266,6 +334,21 @@ class PythonMapper(object):
|
|
266
334
|
*args,
|
267
335
|
**kwargs)
|
268
336
|
|
337
|
+
def create_mapped_python_object(self,
|
338
|
+
obj: Any,
|
339
|
+
data_model=None,
|
340
|
+
add_to_data_model=True,
|
341
|
+
*args,
|
342
|
+
**kwargs) -> Optional[SimultanObject]:
|
343
|
+
|
344
|
+
from .utils import create_mapped_python_object
|
345
|
+
return create_mapped_python_object(obj,
|
346
|
+
object_mapper=self,
|
347
|
+
data_model=data_model,
|
348
|
+
add_to_data_model=add_to_data_model,
|
349
|
+
*args,
|
350
|
+
**kwargs)
|
351
|
+
|
269
352
|
def get_typed_data_with_taxonomy(self, taxonomy: str, data_model=None, first=False):
|
270
353
|
|
271
354
|
tax_components = data_model.find_components_with_taxonomy(taxonomy=taxonomy, first=first)
|
@@ -307,14 +390,68 @@ class PythonMapper(object):
|
|
307
390
|
new_val = create_mapped_python_object(obj, self, data_model)
|
308
391
|
return new_val
|
309
392
|
|
310
|
-
def copy(self
|
311
|
-
|
393
|
+
def copy(self,
|
394
|
+
*args,
|
395
|
+
**kwargs) -> 'PythonMapper':
|
396
|
+
|
397
|
+
orig_new_module_name = kwargs.get('module', self.module)
|
398
|
+
new_module_name = orig_new_module_name
|
399
|
+
i = 0
|
400
|
+
while new_module_name in self.mappers.keys():
|
401
|
+
new_module_name = f'copy_{i}_of_{new_module_name}'
|
402
|
+
i+=1
|
403
|
+
|
404
|
+
new_mapper = PythonMapper(add_to_mappers=kwargs.get('add_to_mappers', True),
|
405
|
+
module=new_module_name)
|
312
406
|
new_mapper.registered_classes = self.registered_classes
|
313
407
|
new_mapper.taxonomy_maps = self.taxonomy_maps
|
314
408
|
new_mapper.registered_geometry_classes = self.registered_geometry_classes
|
315
409
|
new_mapper.load_undefined = self.load_undefined
|
410
|
+
|
316
411
|
return new_mapper
|
317
412
|
|
413
|
+
def __add__(self, other: 'PythonMapper') -> 'PythonMapper':
|
414
|
+
# new_mapper = self.copy(add_to_mappers=True)
|
415
|
+
self.submodules[other.module] = other
|
416
|
+
self.submodules.update(other.submodules)
|
417
|
+
self.registered_classes.update(other.registered_classes)
|
418
|
+
self.taxonomy_maps.update(other.taxonomy_maps)
|
419
|
+
self.registered_geometry_classes.update(other.registered_geometry_classes)
|
420
|
+
return self
|
421
|
+
|
422
|
+
def get_mapped_class_for_python_type(self, python_type: type) -> Optional[Type[SimultanObject]]:
|
423
|
+
try:
|
424
|
+
key = list(filter(lambda x: self.registered_classes[x] == python_type,
|
425
|
+
self.registered_classes)
|
426
|
+
)[0]
|
427
|
+
mapped_cls = self.get_mapped_class(key)
|
428
|
+
return mapped_cls
|
429
|
+
except IndexError:
|
430
|
+
return None
|
431
|
+
|
432
|
+
def __repr__(self):
|
433
|
+
return f'PythonMapper(module={self.module}, {len(self.registered_classes)} registered classes)'
|
434
|
+
|
318
435
|
|
319
436
|
if config.get_default_mapper() is None:
|
320
|
-
config.set_default_mapper(PythonMapper())
|
437
|
+
config.set_default_mapper(PythonMapper(module='default'))
|
438
|
+
|
439
|
+
|
440
|
+
def register(taxonomy: str,
|
441
|
+
taxonomy_map: TaxonomyMap,
|
442
|
+
re_register=True,
|
443
|
+
module: str = 'unknown_module') -> Any:
|
444
|
+
|
445
|
+
if module not in PythonMapper.mappers.keys():
|
446
|
+
PythonMapper(module=module)
|
447
|
+
|
448
|
+
mapper = PythonMapper.mappers[module]
|
449
|
+
|
450
|
+
def decorator(cls):
|
451
|
+
mapper.register(taxonomy,
|
452
|
+
cls,
|
453
|
+
re_register=re_register,
|
454
|
+
taxonomy_map=taxonomy_map)
|
455
|
+
return cls
|
456
|
+
|
457
|
+
return decorator
|
Binary file
|
@@ -12,7 +12,8 @@
|
|
12
12
|
}
|
13
13
|
],
|
14
14
|
"configProperties": {
|
15
|
-
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
|
15
|
+
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
|
16
|
+
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": true
|
16
17
|
}
|
17
18
|
}
|
18
19
|
}
|