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.
Files changed (37) hide show
  1. PySimultan2/CHANGELOG.md +4 -0
  2. PySimultan2/__about__.py +1 -1
  3. PySimultan2/__init__.py +1 -0
  4. PySimultan2/data_model.py +185 -80
  5. PySimultan2/default_types.py +125 -23
  6. PySimultan2/files.py +55 -5
  7. PySimultan2/object_mapper.py +146 -9
  8. PySimultan2/resources/ComponentBuilder.dll +0 -0
  9. PySimultan2/resources/ComponentBuilder.runtimeconfig.json +2 -1
  10. PySimultan2/resources/ComponentBuilder.xml +47 -1
  11. PySimultan2/resources/SIMULTAN.AutoUpdate.Client.dll +0 -0
  12. PySimultan2/resources/SIMULTAN.AutoUpdate.DataTransferLibrary.dll +0 -0
  13. PySimultan2/resources/SIMULTAN.Lang.dll +0 -0
  14. PySimultan2/resources/SIMULTAN.Lang.xml +94 -7
  15. PySimultan2/resources/SIMULTAN.Plugins.dll +0 -0
  16. PySimultan2/resources/SIMULTAN.UI.dll +0 -0
  17. PySimultan2/resources/SIMULTAN.UI.xml +136 -43
  18. PySimultan2/resources/SIMULTAN.dll +0 -0
  19. PySimultan2/resources/SIMULTAN.xml +364 -97
  20. PySimultan2/resources/System.Collections.Immutable.dll +0 -0
  21. PySimultan2/resources/System.Reflection.Metadata.dll +0 -0
  22. PySimultan2/resources/System.Reflection.MetadataLoadContext.dll +0 -0
  23. PySimultan2/resources/componentmanager.user +0 -0
  24. PySimultan2/simultan_object.py +64 -15
  25. PySimultan2/taxonomy_maps.py +20 -12
  26. PySimultan2/type_setter_lookup.py +46 -33
  27. PySimultan2/utils.py +79 -14
  28. {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/METADATA +2 -3
  29. {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/RECORD +31 -32
  30. {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/WHEEL +1 -1
  31. PySimultan2/resources/GeometryViewer.dll +0 -0
  32. PySimultan2/resources/GeometryViewer.dll.config +0 -42
  33. PySimultan2/resources/GeometryViewer.xml +0 -6425
  34. PySimultan2/resources/SitePlanner.dll +0 -0
  35. PySimultan2/resources/SitePlanner.dll.config +0 -11
  36. PySimultan2/resources/SitePlanner.xml +0 -2736
  37. {pysimultan-0.4.22.dist-info → pysimultan-0.5.2.5.dist-info}/licenses/LICENSE.txt +0 -0
@@ -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', True) and comp_dict is not None and key in object.__getattribute__(self,
358
- '_dict').keys():
359
- return object.__getattribute__(self, '_dict').get(key, None)
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(type(value), set_property_to_unknown_type)
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
- self._dict[key] = item
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
- comp_dict[parameter.NameTaxonomyEntry.TextOrKey] = get_obj_value(parameter,
486
- data_model=self._data_model,
487
- object_mapper=self._object_mapper)
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
- comp_dict[component.Slot.SlotBase.Target.Key] = get_obj_value(component.Component,
490
- data_model=self._data_model,
491
- object_mapper=self._object_mapper)
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
- comp_dict[ref_component.Slot.SlotBase.Target.Key] = get_obj_value(ref_component.Target,
494
- data_model=self._data_model,
495
- object_mapper=self._object_mapper)
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
- comp_dict[tag.Target.Key] = get_obj_value(ref_asset.Target,
499
- data_model=self._data_model,
500
- object_mapper=self._object_mapper)
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
- add_tag_to_resource(asset, tag)
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
- return ComponentMapping.AddAsset(wrapped_obj, asset, content_id)
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, filename: str, content: str, *args, **kwargs) -> FileInfo:
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
- return os.path.getsize(self.file_path)
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
+ }
@@ -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, taxonomy, cls, taxonomy_map=None):
76
- if not self.re_register and taxonomy in self.registered_classes.keys():
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, component, data_model=None, *args, **kwargs):
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, data_model, *args, **kwargs)
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
- new_mapper = PythonMapper()
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
  }