PySimultan 0.4.0__py3-none-any.whl → 0.4.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- PySimultan2/__about__.py +1 -1
- PySimultan2/__init__.py +94 -33
- PySimultan2/data_model.py +56 -68
- PySimultan2/default_types.py +2 -2
- PySimultan2/files.py +6 -3
- PySimultan2/geometry/geometry_base.py +3 -2
- PySimultan2/geometry/utils.py +1 -1
- PySimultan2/object_mapper.py +13 -5
- PySimultan2/simultan_object.py +20 -4
- PySimultan2/taxonomy_maps.py +13 -1
- PySimultan2/utils.py +36 -39
- {pysimultan-0.4.0.dist-info → pysimultan-0.4.1.dist-info}/METADATA +1 -1
- {pysimultan-0.4.0.dist-info → pysimultan-0.4.1.dist-info}/RECORD +15 -16
- PySimultan2/config.py +0 -52
- {pysimultan-0.4.0.dist-info → pysimultan-0.4.1.dist-info}/WHEEL +0 -0
- {pysimultan-0.4.0.dist-info → pysimultan-0.4.1.dist-info}/licenses/LICENSE.txt +0 -0
PySimultan2/__about__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
version = '0.4.
|
1
|
+
version = '0.4.1'
|
PySimultan2/__init__.py
CHANGED
@@ -1,38 +1,99 @@
|
|
1
|
+
import os
|
1
2
|
import sys
|
2
3
|
import colorlog
|
3
|
-
from .config import *
|
4
|
+
# from .config import *
|
5
|
+
from ruamel.yaml import YAML, yaml_object, add_representer
|
6
|
+
|
7
|
+
def setup_logging():
|
8
|
+
handler = colorlog.StreamHandler()
|
9
|
+
formatter = colorlog.ColoredFormatter(
|
10
|
+
"%(log_color)s%(levelname)-8s%(reset)s %(blue)s%(message)s",
|
11
|
+
datefmt=None,
|
12
|
+
reset=True,
|
13
|
+
log_colors={
|
14
|
+
'DEBUG': 'cyan',
|
15
|
+
'INFO': 'green',
|
16
|
+
'WARNING': 'yellow',
|
17
|
+
'ERROR': 'red',
|
18
|
+
'CRITICAL': 'red,bg_white',
|
19
|
+
},
|
20
|
+
secondary_log_colors={},
|
21
|
+
style='%'
|
22
|
+
)
|
23
|
+
|
24
|
+
handler.setFormatter(formatter)
|
25
|
+
|
26
|
+
logger = colorlog.getLogger('PySimultan')
|
27
|
+
logger.addHandler(handler)
|
28
|
+
|
29
|
+
return logger
|
30
|
+
|
31
|
+
|
32
|
+
def setup():
|
33
|
+
import colorlog
|
34
|
+
try:
|
35
|
+
import importlib.resources as pkg_resources
|
36
|
+
except ImportError:
|
37
|
+
# Try backported to PY<37 importlib_resources.
|
38
|
+
import importlib_resources as pkg_resources
|
39
|
+
|
40
|
+
from . import resources
|
41
|
+
sys.path.append(str(pkg_resources.files(resources)))
|
42
|
+
|
43
|
+
logger = colorlog.getLogger('PySimultan')
|
44
|
+
logger.setLevel('DEBUG')
|
45
|
+
|
46
|
+
dll_path = os.environ.get('SIMULTAN_SDK_DIR', None)
|
47
|
+
if dll_path is None:
|
48
|
+
with pkg_resources.path(resources, 'SIMULTAN.dll') as r_path:
|
49
|
+
dll_path = str(r_path)
|
50
|
+
sys.path.append(dll_path)
|
51
|
+
|
52
|
+
from pythonnet import load
|
53
|
+
from pythonnet import clr_loader, set_runtime
|
54
|
+
list(clr_loader.find_runtimes())
|
55
|
+
load('coreclr')
|
56
|
+
import clr
|
57
|
+
test = clr.AddReference(
|
58
|
+
os.path.join(dll_path, 'SIMULTAN.dll') if not dll_path.endswith('SIMULTAN.dll') else dll_path)
|
59
|
+
clr.AddReference("System.Security.Cryptography")
|
60
|
+
# clr.AddReference(os.path.join(dll_path, 'SIMULTAN'))
|
61
|
+
|
62
|
+
from SIMULTAN.Data.Components import SimComponent
|
63
|
+
|
64
|
+
continue_on_error = True
|
65
|
+
|
66
|
+
def represent_none(self, _):
|
67
|
+
return self.represent_scalar('tag:yaml.org,2002:null', '')
|
68
|
+
|
69
|
+
add_representer(type(None), represent_none)
|
70
|
+
yaml = YAML()
|
71
|
+
yaml.default_flow_style = None
|
72
|
+
yaml.preserve_quotes = True
|
73
|
+
yaml.allow_unicode = True
|
74
|
+
|
75
|
+
return yaml
|
76
|
+
|
77
|
+
|
78
|
+
logger = setup_logging()
|
79
|
+
yaml = setup()
|
80
|
+
|
81
|
+
|
82
|
+
class Config:
|
83
|
+
def __init__(self):
|
84
|
+
self._default_data_model = None
|
85
|
+
self._default_mapper = None
|
86
|
+
self.logger = logger
|
87
|
+
|
88
|
+
def get_default_data_model(self, *args, **kwargs):
|
89
|
+
return self._default_data_model
|
90
|
+
|
91
|
+
def get_default_mapper(self, *args, **kwargs):
|
92
|
+
return self._default_mapper
|
93
|
+
|
94
|
+
|
95
|
+
config = Config()
|
96
|
+
|
4
97
|
from .data_model import DataModel
|
5
98
|
from .files import FileInfo
|
6
99
|
from .object_mapper import PythonMapper
|
7
|
-
|
8
|
-
# from .simultan_utils import create_component
|
9
|
-
# from .template_tools import Template, TemplateParser
|
10
|
-
# from .geo_default_types import BaseGeometricLayer, BaseGeometricVertex, BaseGeometricEdge, BaseGeometricEdgeLoop, BaseGeometricFace, BaseGeometricVolume
|
11
|
-
#
|
12
|
-
# print(sys.version)
|
13
|
-
#
|
14
|
-
# from ParameterStructure.Components import SimComponent
|
15
|
-
# from ParameterStructure.Parameters import SimParameter
|
16
|
-
|
17
|
-
# from .utils import create_component
|
18
|
-
|
19
|
-
handler = colorlog.StreamHandler()
|
20
|
-
formatter = colorlog.ColoredFormatter(
|
21
|
-
"%(log_color)s%(levelname)-8s%(reset)s %(blue)s%(message)s",
|
22
|
-
datefmt=None,
|
23
|
-
reset=True,
|
24
|
-
log_colors={
|
25
|
-
'DEBUG': 'cyan',
|
26
|
-
'INFO': 'green',
|
27
|
-
'WARNING': 'yellow',
|
28
|
-
'ERROR': 'red',
|
29
|
-
'CRITICAL': 'red,bg_white',
|
30
|
-
},
|
31
|
-
secondary_log_colors={},
|
32
|
-
style='%'
|
33
|
-
)
|
34
|
-
|
35
|
-
handler.setFormatter(formatter)
|
36
|
-
|
37
|
-
logger = colorlog.getLogger('PySimultan')
|
38
|
-
logger.addHandler(handler)
|
PySimultan2/data_model.py
CHANGED
@@ -3,7 +3,6 @@ import os
|
|
3
3
|
import shutil
|
4
4
|
from uuid import uuid4
|
5
5
|
from colorlog import getLogger
|
6
|
-
from functools import lru_cache, reduce
|
7
6
|
from weakref import WeakSet, WeakValueDictionary
|
8
7
|
from . import config
|
9
8
|
from .utils import *
|
@@ -46,6 +45,7 @@ from .files import add_tag_to_resource
|
|
46
45
|
|
47
46
|
if TYPE_CHECKING:
|
48
47
|
from .object_mapper import PythonMapper
|
48
|
+
from .geometry import GeometryModel
|
49
49
|
|
50
50
|
|
51
51
|
logger = getLogger('PySimultan')
|
@@ -114,7 +114,7 @@ class DataModel:
|
|
114
114
|
else:
|
115
115
|
print("Failed to create project")
|
116
116
|
|
117
|
-
return cls(project_path=project_path, user_name=user_name, password=password)
|
117
|
+
return cls(project_path=project_path, user_name=user_name, password=password, project_data_manager=projectData)
|
118
118
|
|
119
119
|
def __new__(cls, *args, **kwargs):
|
120
120
|
|
@@ -147,6 +147,8 @@ class DataModel:
|
|
147
147
|
self._project = None
|
148
148
|
self._zip_loader = None
|
149
149
|
|
150
|
+
self.project_data_manager = kwargs.get('project_data_manager', None)
|
151
|
+
|
150
152
|
self.project_path = kwargs.get('project_path', None)
|
151
153
|
|
152
154
|
self.service_provider = Utils.ServicesProvider()
|
@@ -156,38 +158,10 @@ class DataModel:
|
|
156
158
|
self.i_aut_service.password = self.password
|
157
159
|
|
158
160
|
self.service_provider.AddService[SimultanUsers.IAuthenticationService](self.i_aut_service())
|
159
|
-
|
160
|
-
# self.serv = GeometryViewerService([], self.service_provider)
|
161
|
-
# self.service_provider.AddService[IGeometryViewerService](self.serv)
|
162
|
-
|
163
161
|
self.exch = self.project.AllProjectDataManagers.ComponentGeometryExchange
|
164
162
|
# self.exch.ModelStore = self.serv
|
165
163
|
|
166
164
|
self.resources = {}
|
167
|
-
# self.models_dict = {}
|
168
|
-
#
|
169
|
-
# if self.project_data_manager.AssetManager.Resources.__len__() > 0:
|
170
|
-
# for resource in self.project_data_manager.AssetManager.Resources:
|
171
|
-
# if resource is None:
|
172
|
-
# continue
|
173
|
-
# self.resources[resource.Key] = resource
|
174
|
-
# self.models_dict[resource.Key] = None
|
175
|
-
# current_full_path = resource.CurrentFullPath
|
176
|
-
# if current_full_path == '?':
|
177
|
-
# continue
|
178
|
-
#
|
179
|
-
# if resource.Extension == '.simgeo':
|
180
|
-
# error_list = NetList[SimGeoIOError]()
|
181
|
-
#
|
182
|
-
# model = SimGeoIO.Load(resource, self.project_data_manager, error_list, OffsetAlgorithm.Full)
|
183
|
-
# self.models_dict[resource.Key] = model
|
184
|
-
# try:
|
185
|
-
# self.project_data_manager.GeometryModels.AddGeometryModel(model)
|
186
|
-
# except Exception as e:
|
187
|
-
# logger.warning(f'Error while loading Model: {model} from {model.File}: {e}. Trying reload...')
|
188
|
-
# raise e
|
189
|
-
|
190
|
-
self.ValueFields = self.project_data_manager.ValueManager.Items
|
191
165
|
self.import_data_model()
|
192
166
|
|
193
167
|
self.__mongo_instance = None
|
@@ -197,40 +171,41 @@ class DataModel:
|
|
197
171
|
return self.project_data_manager.AssetManager.Resources
|
198
172
|
|
199
173
|
@property
|
200
|
-
def
|
201
|
-
|
202
|
-
|
203
|
-
return
|
174
|
+
def models(self) -> dict[int, 'GeometryModel']:
|
175
|
+
"""
|
176
|
+
Return the geometry models of the project
|
177
|
+
:return: dict[int, GeometryModel]
|
178
|
+
"""
|
204
179
|
|
205
|
-
|
206
|
-
|
207
|
-
self.__mongo_instance = value
|
180
|
+
# if self.models_dict:
|
181
|
+
# return self.models_dict
|
208
182
|
|
209
|
-
@property
|
210
|
-
def models(self):
|
211
183
|
self.models_dict = {}
|
212
184
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
185
|
+
# self.project_data_manager.Reset()
|
186
|
+
|
187
|
+
resources = self.project_data_manager.AssetManager.Resources
|
188
|
+
|
189
|
+
for resource in resources:
|
190
|
+
if resource is None:
|
191
|
+
continue
|
192
|
+
self.resources[resource.Key] = resource
|
218
193
|
|
219
|
-
|
220
|
-
|
221
|
-
|
194
|
+
current_full_path = resource.CurrentFullPath
|
195
|
+
if current_full_path == '?':
|
196
|
+
continue
|
222
197
|
|
223
|
-
|
224
|
-
|
225
|
-
|
198
|
+
if resource.Extension == '.simgeo':
|
199
|
+
self.models_dict[resource.Key] = None
|
200
|
+
error_list = NetList[SimGeoIOError]()
|
226
201
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
202
|
+
model = SimGeoIO.Load(resource, self.project_data_manager, error_list, OffsetAlgorithm.Full)
|
203
|
+
self.models_dict[resource.Key] = model
|
204
|
+
try:
|
205
|
+
self.project_data_manager.GeometryModels.AddGeometryModel(model)
|
206
|
+
except Exception as e:
|
207
|
+
logger.warning(f'Error while loading Model: {model} from {model.File}: {e}')
|
208
|
+
raise e
|
234
209
|
|
235
210
|
return self.models_dict
|
236
211
|
|
@@ -238,14 +213,20 @@ class DataModel:
|
|
238
213
|
def taxonomies(self):
|
239
214
|
return self.project_data_manager.Taxonomies
|
240
215
|
|
216
|
+
@property
|
217
|
+
def ValueFields(self):
|
218
|
+
return self.project_data_manager.ValueManager.Items
|
219
|
+
|
241
220
|
@property
|
242
221
|
def value_fields(self):
|
243
222
|
return self.project_data_manager.ValueManager
|
244
223
|
|
245
224
|
@property
|
246
225
|
def project_data_manager(self):
|
247
|
-
|
226
|
+
|
227
|
+
if self._project_data_manager is None:
|
248
228
|
self._project_data_manager = ExtendedProjectData()
|
229
|
+
|
249
230
|
return self._project_data_manager
|
250
231
|
|
251
232
|
@project_data_manager.setter
|
@@ -261,7 +242,6 @@ class DataModel:
|
|
261
242
|
@user.setter
|
262
243
|
def user(self, value: SimultanUsers.SimUserRole):
|
263
244
|
if value != self._user:
|
264
|
-
self.project_data_manager = None
|
265
245
|
self._project = None
|
266
246
|
self._user = value
|
267
247
|
|
@@ -306,7 +286,6 @@ class DataModel:
|
|
306
286
|
def remove_field(self, field: SimMultiValueField3D):
|
307
287
|
self.project_data_manager.ValueManager.Remove(field)
|
308
288
|
|
309
|
-
@lru_cache(maxsize=None)
|
310
289
|
def get_geo_instance(self, file_id, type, id):
|
311
290
|
geo_model = self.models[file_id]
|
312
291
|
objects = getattr(geo_model.Geometry, type)
|
@@ -381,16 +360,28 @@ class DataModel:
|
|
381
360
|
"""
|
382
361
|
logger.info('closing project...')
|
383
362
|
try:
|
363
|
+
|
384
364
|
self._project.DisableProjectUnpackFolderWatcher()
|
385
365
|
if self._project is not None:
|
366
|
+
if self._project.IsOpened:
|
367
|
+
ZipProjectIO.Close(self._project, True)
|
386
368
|
if self._project.IsLoaded:
|
387
369
|
ZipProjectIO.Unload(self._project)
|
388
|
-
if self._project.IsOpened:
|
389
|
-
ZipProjectIO.Close(self._project, False, True)
|
390
370
|
|
391
|
-
self._project_data_manager.Reset()
|
392
371
|
except Exception as e:
|
393
372
|
pass
|
373
|
+
finally:
|
374
|
+
if self._project_data_manager is not None:
|
375
|
+
del self._project_data_manager
|
376
|
+
self._project_data_manager = None
|
377
|
+
|
378
|
+
data_models = WeakSet()
|
379
|
+
data_models_dict = WeakValueDictionary()
|
380
|
+
|
381
|
+
if config.default_data_model is self:
|
382
|
+
config.default_data_model = None
|
383
|
+
|
384
|
+
del self
|
394
385
|
|
395
386
|
# def create_new_component(self):
|
396
387
|
#
|
@@ -570,14 +561,13 @@ class DataModel:
|
|
570
561
|
if isinstance(component, SimultanObject):
|
571
562
|
component = component._wrapped_obj
|
572
563
|
|
573
|
-
if not component.Instances:
|
574
|
-
return []
|
575
|
-
|
576
564
|
for instance in component.Instances:
|
577
565
|
for placement in instance.Placements.Items:
|
578
566
|
geo_model = next((x for x in self.models.values() if x is not None and x.File.Key == placement.FileId), None)
|
579
567
|
if geo_model is not None:
|
580
568
|
ref_geometries.append((geo_model.Geometry.GeometryFromId(placement.GeometryId), geo_model))
|
569
|
+
if geo_model is None:
|
570
|
+
logger.warning(f'Geometry model with id {placement.FileId} not found in project {self.project_path}')
|
581
571
|
|
582
572
|
return ref_geometries
|
583
573
|
|
@@ -665,7 +655,6 @@ class DataModel:
|
|
665
655
|
None)
|
666
656
|
return model_to_work_with, resource_file
|
667
657
|
|
668
|
-
@lru_cache(maxsize=None)
|
669
658
|
def get_or_create_taxonomy(self, taxonomy_key: str, taxonomy_name: str = None, description='', create=True):
|
670
659
|
taxonomy = next((x for x in self.taxonomies if x.Key == taxonomy_key), None)
|
671
660
|
if taxonomy is None:
|
@@ -676,7 +665,6 @@ class DataModel:
|
|
676
665
|
|
677
666
|
return next((x for x in self.taxonomies if x.Key == taxonomy_key), None)
|
678
667
|
|
679
|
-
@lru_cache(maxsize=None)
|
680
668
|
def get_or_create_taxonomy_entry(self,
|
681
669
|
name: str,
|
682
670
|
key: str,
|
PySimultan2/default_types.py
CHANGED
@@ -113,7 +113,7 @@ class ComponentList(SimultanObject):
|
|
113
113
|
|
114
114
|
try:
|
115
115
|
indices = sort_slots(slots)
|
116
|
-
return [self._object_mapper.create_python_object(x) for x in
|
116
|
+
return [self._object_mapper.create_python_object(x, data_model=self._data_model) for x in
|
117
117
|
[all_components[i] for i in np.argsort(indices)]]
|
118
118
|
except TypeError as e:
|
119
119
|
logger.warning(f'Could not sort list {all_components}:\n{e}')
|
@@ -259,7 +259,7 @@ class ComponentList(SimultanObject):
|
|
259
259
|
return f'List {self.name}: ' + repr(list(self.data))
|
260
260
|
|
261
261
|
def __iter__(self):
|
262
|
-
return iter([self._object_mapper.create_python_object(x) for x in self.data])
|
262
|
+
return iter([self._object_mapper.create_python_object(x, data_model=self._data_model) for x in self.data])
|
263
263
|
|
264
264
|
def __next__(self):
|
265
265
|
try:
|
PySimultan2/files.py
CHANGED
@@ -18,7 +18,9 @@ from SIMULTAN.Data.Assets import ResourceEntry, ResourceFileEntry, ContainedReso
|
|
18
18
|
from SIMULTAN.Data.Taxonomy import SimTaxonomyEntry, SimTaxonomyEntryReference, SimTaxonomy
|
19
19
|
from SIMULTAN.Data.Components import SimComponent, ComponentMapping
|
20
20
|
|
21
|
-
from .config import default_data_model
|
21
|
+
# from .config import default_data_model
|
22
|
+
|
23
|
+
from . import config
|
22
24
|
|
23
25
|
from typing import TYPE_CHECKING
|
24
26
|
if TYPE_CHECKING:
|
@@ -195,7 +197,7 @@ class FileInfo(object, metaclass=MetaMock):
|
|
195
197
|
:return: FileInfo
|
196
198
|
"""
|
197
199
|
|
198
|
-
data_model = kwargs.get('data_model', default_data_model)
|
200
|
+
data_model = kwargs.get('data_model', config.default_data_model)
|
199
201
|
resource = create_asset_from_string(filename, content, *args, **kwargs)
|
200
202
|
|
201
203
|
file_info = cls(resource_entry=resource,
|
@@ -239,7 +241,8 @@ class FileInfo(object, metaclass=MetaMock):
|
|
239
241
|
def resource_entry(self) -> Union[ResourceFileEntry, ContainedResourceFileEntry, None]:
|
240
242
|
if self._resource_entry is None:
|
241
243
|
if self.data_model is None:
|
242
|
-
|
244
|
+
logger.warning(f'No data model provided. Using default data model: {config.default_data_model.id}.')
|
245
|
+
self.data_model = config.default_data_model
|
243
246
|
if self.data_model is not None:
|
244
247
|
self.resource_entry = self.data_model.add_resource(self.file_path)
|
245
248
|
return self._resource_entry
|
@@ -30,7 +30,7 @@ from SIMULTAN.Data.Geometry import VolumeAlgorithms
|
|
30
30
|
# from ..utils import create_mapped_python_object, create_python_object
|
31
31
|
# from ..files import create_asset_from_file, FileInfo, create_asset_from_string
|
32
32
|
from .. import config
|
33
|
-
from ..
|
33
|
+
from .. import logger
|
34
34
|
|
35
35
|
from typing import TYPE_CHECKING
|
36
36
|
if TYPE_CHECKING:
|
@@ -538,11 +538,12 @@ class GeometryModel(object, metaclass=MetaMock):
|
|
538
538
|
def create_simultan_instance(cls, *args, **kwargs):
|
539
539
|
|
540
540
|
data_model: DataModel = kwargs.get('data_model', config.default_data_model)
|
541
|
-
name = kwargs.get('name', 'GeometryModel')
|
541
|
+
name: str = kwargs.get('name', 'GeometryModel')
|
542
542
|
|
543
543
|
new_geo_model, resource = data_model.create_new_geometry_model(name=name)
|
544
544
|
data_model.project_data_manager.GeometryModels.AddGeometryModel(new_geo_model)
|
545
545
|
data_model.models_dict[resource.Key] = new_geo_model
|
546
|
+
data_model.save()
|
546
547
|
|
547
548
|
return new_geo_model
|
548
549
|
|
PySimultan2/geometry/utils.py
CHANGED
@@ -57,7 +57,7 @@ def create_cube(data_model,
|
|
57
57
|
scale: Optional[float] = 1):
|
58
58
|
|
59
59
|
if obj_mapper is None:
|
60
|
-
obj_mapper = config.
|
60
|
+
obj_mapper = config.get_default_mapper()
|
61
61
|
|
62
62
|
new_layer = obj_mapper.registered_geometry_classes[Layer](geometry_model=geo_model,
|
63
63
|
data_model=data_model,
|
PySimultan2/object_mapper.py
CHANGED
@@ -136,15 +136,18 @@ class PythonMapper(object):
|
|
136
136
|
typed_data.append(typed_object)
|
137
137
|
return typed_data
|
138
138
|
|
139
|
-
# @lru_cache(maxsize=
|
139
|
+
# @lru_cache(maxsize=500)
|
140
140
|
def create_python_object(self, component, cls=None, data_model=None, *args, **kwargs):
|
141
141
|
|
142
142
|
if component is None:
|
143
143
|
return None
|
144
144
|
|
145
145
|
if data_model is None:
|
146
|
-
|
147
|
-
data_model =
|
146
|
+
logger.warning(f'No data model provided. Using default data model: {config.default_data_model.id}.')
|
147
|
+
data_model = config.default_data_model
|
148
|
+
data_model_id = data_model.id
|
149
|
+
# data_model_id = list(data_models)[0].id
|
150
|
+
# data_model = list(data_models)[0]
|
148
151
|
else:
|
149
152
|
data_model_id = data_model.id
|
150
153
|
|
@@ -201,6 +204,7 @@ class PythonMapper(object):
|
|
201
204
|
for prop in taxonomy_map.content:
|
202
205
|
|
203
206
|
prop_dict[prop.property_name] = add_properties(prop_name=prop.property_name,
|
207
|
+
text_or_key=prop.text_or_key,
|
204
208
|
content=prop,
|
205
209
|
taxonomy_map=taxonomy_map,
|
206
210
|
taxonomy=taxonomy)
|
@@ -213,6 +217,10 @@ class PythonMapper(object):
|
|
213
217
|
|
214
218
|
for cls in self.mapped_classes.values():
|
215
219
|
cls._cls_instances = WeakSet()
|
220
|
+
cls.__property_cache__ = {}
|
221
|
+
|
222
|
+
if config.default_mapper is self:
|
223
|
+
config.default_mapper = None
|
216
224
|
|
217
225
|
def copy(self):
|
218
226
|
new_mapper = PythonMapper()
|
@@ -222,5 +230,5 @@ class PythonMapper(object):
|
|
222
230
|
return new_mapper
|
223
231
|
|
224
232
|
|
225
|
-
if config.
|
226
|
-
config.
|
233
|
+
if config.get_default_mapper() is None:
|
234
|
+
config._default_mapper = PythonMapper()
|
PySimultan2/simultan_object.py
CHANGED
@@ -6,7 +6,7 @@ from weakref import WeakSet, WeakValueDictionary
|
|
6
6
|
from . import utils
|
7
7
|
from numpy import ndarray
|
8
8
|
import colorlog
|
9
|
-
from typing import Union
|
9
|
+
from typing import Union, Optional
|
10
10
|
|
11
11
|
logger = colorlog.getLogger('PySimultan')
|
12
12
|
|
@@ -69,6 +69,8 @@ class MetaMock(type):
|
|
69
69
|
kwargs['data_model'] = data_model
|
70
70
|
else:
|
71
71
|
if config.default_data_model is not None:
|
72
|
+
logger.warning(
|
73
|
+
f'No data model provided. Using default data model: {config.default_data_model.id}.')
|
72
74
|
data_model = config.default_data_model
|
73
75
|
kwargs['data_model'] = data_model
|
74
76
|
else:
|
@@ -102,6 +104,11 @@ class SimultanObject(object, metaclass=MetaMock):
|
|
102
104
|
_cls_instances_dict_cache = None
|
103
105
|
__type_view__ = None # ui view cls
|
104
106
|
|
107
|
+
@classmethod
|
108
|
+
def reset_cls(cls):
|
109
|
+
cls._cls_instances = WeakSet()
|
110
|
+
cls._cls_instances_dict_cache = None
|
111
|
+
|
105
112
|
@classmethod
|
106
113
|
def get_instance_by_id(cls, id: SimId) -> 'SimultanObject':
|
107
114
|
return cls._cls_instances_dict.get(id, None)
|
@@ -147,11 +154,12 @@ class SimultanObject(object, metaclass=MetaMock):
|
|
147
154
|
|
148
155
|
self._wrapped_obj: Union[SimComponent, None] = kwargs.get('wrapped_obj', None)
|
149
156
|
self.__obj_init__ = kwargs.get('__obj_init__', False)
|
150
|
-
self._data_model_id = kwargs.get('data_model_id', None)
|
151
157
|
self._data_model: Union[DataModel, None] = kwargs.get('data_model', config.default_data_model)
|
152
158
|
self._object_mapper: Union[PythonMapper, None] = kwargs.get('object_mapper', config.default_mapper)
|
153
159
|
self.name = kwargs.get('name', None)
|
154
160
|
|
161
|
+
self.__property_cache__ = {}
|
162
|
+
|
155
163
|
self._slot = None
|
156
164
|
|
157
165
|
def __getattribute__(self, attr):
|
@@ -328,8 +336,16 @@ class SimultanObject(object, metaclass=MetaMock):
|
|
328
336
|
"""
|
329
337
|
other.associate(self)
|
330
338
|
|
331
|
-
def get_raw_attr(self, attr: str):
|
332
|
-
|
339
|
+
def get_raw_attr(self, attr: Optional[str] = None, text_or_key: Optional[str] = None):
|
340
|
+
if attr is not None:
|
341
|
+
content = self._taxonomy_map.get_content_by_property_name(attr)
|
342
|
+
if content is None:
|
343
|
+
raise KeyError(f'No content found for attribute {attr}')
|
344
|
+
|
345
|
+
return utils.get_component_taxonomy_entry(self._wrapped_obj, content.text_or_key)
|
346
|
+
|
347
|
+
if text_or_key is not None:
|
348
|
+
return utils.get_component_taxonomy_entry(self._wrapped_obj, text_or_key)
|
333
349
|
|
334
350
|
def set_attr_prop(self, attr: str, prop: str, value):
|
335
351
|
"""
|
PySimultan2/taxonomy_maps.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import io
|
2
|
+
from functools import cache
|
2
3
|
from ruamel.yaml import YAML, yaml_object, add_representer
|
3
|
-
from .
|
4
|
+
from . import yaml
|
4
5
|
|
5
6
|
from typing import TYPE_CHECKING, Optional, Union, Literal
|
6
7
|
if TYPE_CHECKING:
|
@@ -113,6 +114,9 @@ class TaxonomyMap(object):
|
|
113
114
|
content._taxonomy_map = self
|
114
115
|
self._content_dict = {}
|
115
116
|
|
117
|
+
self.get_content_by_property_name.cache_clear()
|
118
|
+
self.get_content_by_text_or_key.cache_clear()
|
119
|
+
|
116
120
|
@property
|
117
121
|
def content_dict(self):
|
118
122
|
if self._content_dict == {}:
|
@@ -167,3 +171,11 @@ class TaxonomyMap(object):
|
|
167
171
|
|
168
172
|
def get_slot(self, data_model: 'DataModel'):
|
169
173
|
return SimTaxonomyEntryReference(self.get_or_create_simultan_taxonomy_entry(data_model=data_model, create=True))
|
174
|
+
|
175
|
+
@cache
|
176
|
+
def get_content_by_property_name(self, property_name: str):
|
177
|
+
return next((x for x in self.content if x.property_name == property_name), None)
|
178
|
+
|
179
|
+
@cache
|
180
|
+
def get_content_by_text_or_key(self, text_or_key: str):
|
181
|
+
return next((x for x in self.content if x.text_or_key == text_or_key), None)
|
PySimultan2/utils.py
CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
3
3
|
from . import config
|
4
4
|
from enum import Enum
|
5
5
|
from weakref import WeakSet
|
6
|
-
from functools import lru_cache
|
7
6
|
import numpy as np
|
8
7
|
import pandas as pd
|
9
8
|
from typing import List as TypeList, Union, Optional, Type
|
@@ -32,7 +31,7 @@ if TYPE_CHECKING:
|
|
32
31
|
from .taxonomy_maps import TaxonomyMap, Content
|
33
32
|
|
34
33
|
|
35
|
-
from .
|
34
|
+
from . import logger
|
36
35
|
from . import config
|
37
36
|
from .simultan_object import SimultanObject
|
38
37
|
|
@@ -94,7 +93,7 @@ def create_python_object(wrapped_obj: SimComponent, cls: Type[SimultanObject], *
|
|
94
93
|
for content in cls._taxonomy_map.content:
|
95
94
|
# logger.debug(f'Get property {content.text_or_key} from wrapped object {wrapped_obj.Name}')
|
96
95
|
kwargs[content.text_or_key] = get_property(wrapped_obj=wrapped_obj,
|
97
|
-
|
96
|
+
text_or_key=content.text_or_key,
|
98
97
|
object_mapper=kwargs.get('object_mapper', None),
|
99
98
|
)
|
100
99
|
|
@@ -103,6 +102,7 @@ def create_python_object(wrapped_obj: SimComponent, cls: Type[SimultanObject], *
|
|
103
102
|
|
104
103
|
obj = cls.__new__(cls)
|
105
104
|
obj.__obj_init__ = True
|
105
|
+
obj.__property_cache__ = dict()
|
106
106
|
obj._wrapped_obj = wrapped_obj
|
107
107
|
obj._data_model = kwargs.get('data_model', None)
|
108
108
|
obj._object_mapper = kwargs.get('object_mapper', None)
|
@@ -662,15 +662,25 @@ def sort_slots(slots, check_same_slot=False) -> list[SimSlot]:
|
|
662
662
|
return slot_extensions
|
663
663
|
|
664
664
|
|
665
|
-
def get_property(prop_name
|
665
|
+
def get_property(prop_name: Optional[str] = None,
|
666
|
+
text_or_key: Optional[str] = None,
|
667
|
+
component=None,
|
668
|
+
wrapped_obj=None,
|
669
|
+
object_mapper=None):
|
670
|
+
|
671
|
+
if prop_name is None and text_or_key is None:
|
672
|
+
raise ValueError('Either prop_name or text_or_key must be set.')
|
673
|
+
if prop_name is not None:
|
674
|
+
content = component._taxonomy_map.get_content_by_property_name(prop_name)
|
675
|
+
text_or_key = content.text_or_key
|
666
676
|
|
667
677
|
if component is not None:
|
668
|
-
obj = get_component_taxonomy_entry(component._wrapped_obj,
|
678
|
+
obj = get_component_taxonomy_entry(component._wrapped_obj, text_or_key)
|
669
679
|
data_model = component._data_model
|
670
680
|
object_mapper = component._object_mapper
|
671
681
|
else:
|
672
682
|
data_model = config.default_data_model
|
673
|
-
obj = get_component_taxonomy_entry(wrapped_obj,
|
683
|
+
obj = get_component_taxonomy_entry(wrapped_obj, text_or_key)
|
674
684
|
|
675
685
|
return get_obj_value(obj, data_model=data_model, object_mapper=object_mapper)
|
676
686
|
|
@@ -1269,6 +1279,7 @@ def set_property_to_dict(value: dict,
|
|
1269
1279
|
|
1270
1280
|
|
1271
1281
|
def add_properties(prop_name: str,
|
1282
|
+
text_or_key: str,
|
1272
1283
|
content: Content,
|
1273
1284
|
taxonomy: str,
|
1274
1285
|
taxonomy_map: 'TaxonomyMap') -> property:
|
@@ -1276,6 +1287,7 @@ def add_properties(prop_name: str,
|
|
1276
1287
|
"""
|
1277
1288
|
create property for a class
|
1278
1289
|
:param prop_name: name of the property (str)
|
1290
|
+
:param text_or_key: text or key of the taxonomy entry (str)
|
1279
1291
|
:param content: content of the property (Content)
|
1280
1292
|
:param prop_name: name of the synonym (str)
|
1281
1293
|
:param taxonomy: taxonomy to use (str)
|
@@ -1310,32 +1322,36 @@ def add_properties(prop_name: str,
|
|
1310
1322
|
np.ndarray: set_property_to_value_field,
|
1311
1323
|
pd.DataFrame: set_property_to_value_field}
|
1312
1324
|
|
1325
|
+
class Empty:
|
1326
|
+
pass
|
1327
|
+
|
1313
1328
|
def getx(self):
|
1314
|
-
return get_property(component=self,
|
1315
|
-
prop_name=content.text_or_key,
|
1316
|
-
object_mapper=self._object_mapper)
|
1317
1329
|
|
1318
|
-
|
1330
|
+
cache_value = self.__property_cache__.get(content.text_or_key, Empty)
|
1319
1331
|
|
1320
|
-
|
1332
|
+
if cache_value is not Empty:
|
1333
|
+
return self.__property_cache__[content.text_or_key]
|
1334
|
+
|
1335
|
+
val = get_property(component=self,
|
1336
|
+
text_or_key=content.text_or_key,
|
1337
|
+
object_mapper=self._object_mapper)
|
1338
|
+
|
1339
|
+
self.__property_cache__[content.text_or_key] = val
|
1340
|
+
return val
|
1341
|
+
|
1342
|
+
getx.__taxonomy__ = taxonomy
|
1343
|
+
content = taxonomy_map.get_content_by_property_name(prop_name)
|
1321
1344
|
|
1322
1345
|
def setx(self, value: Union[int, float, SimComponent, SimultanObject]):
|
1323
|
-
|
1346
|
+
self.__property_cache__.pop(content.text_or_key, None)
|
1347
|
+
|
1324
1348
|
slot_extension = content.slot_extension
|
1325
1349
|
|
1326
1350
|
if slot_extension is None:
|
1327
1351
|
slot_extension = 0
|
1328
1352
|
|
1329
|
-
# sim_taxonomy = taxonomy_map.get_or_create_simultan_taxonomy(self._data_model)
|
1330
1353
|
taxonomy_entry = content.get_taxonomie_entry(self._data_model)
|
1331
1354
|
|
1332
|
-
# sim_taxonomy = self._data_model.get_or_create_taxonomy(taxonomy_name=taxonomy_map.taxonomy_name,
|
1333
|
-
# taxonomy_key=taxonomy_map.taxonomy_key)
|
1334
|
-
# taxonomy_entry = self._data_model.get_or_create_taxonomy_entry(key=content.text_or_key,
|
1335
|
-
# name=content.property_name,
|
1336
|
-
# sim_taxonomy=sim_taxonomy)
|
1337
|
-
# getx.cache_clear()
|
1338
|
-
|
1339
1355
|
component_idx, ref_component_idx, parameter_idx, ref_asset_idx = get_param_indices(self._wrapped_obj,
|
1340
1356
|
taxonomy_entry)
|
1341
1357
|
|
@@ -1372,25 +1388,6 @@ def add_properties(prop_name: str,
|
|
1372
1388
|
|
1373
1389
|
setter_fcn(*fcn_arg_list)
|
1374
1390
|
|
1375
|
-
# elif isinstance(value, (SimComponent, SimultanObject)) and not isinstance(value, ComponentList):
|
1376
|
-
# set_property_to_sim_component(*fcn_arg_list)
|
1377
|
-
#
|
1378
|
-
# elif isinstance(value, (str, int, float)):
|
1379
|
-
# set_property_to_parameter(*fcn_arg_list)
|
1380
|
-
#
|
1381
|
-
# elif isinstance(value, (np.ndarray, pd.DataFrame)):
|
1382
|
-
# set_propperty_to_value_field(*fcn_arg_list)
|
1383
|
-
#
|
1384
|
-
# elif isinstance(value, (list, tuple, set, ComponentList)):
|
1385
|
-
# set_property_to_list(*fcn_arg_list)
|
1386
|
-
#
|
1387
|
-
# elif isinstance(value, FileInfo):
|
1388
|
-
# set_property_to_file_info(*fcn_arg_list, content=content)
|
1389
|
-
#
|
1390
|
-
# else:
|
1391
|
-
# new_val = create_mapped_python_object(value, self._object_mapper, self._data_model)
|
1392
|
-
# setattr(self, prop_name, new_val)
|
1393
|
-
|
1394
1391
|
setx.__taxonomy__ = taxonomy
|
1395
1392
|
|
1396
1393
|
def delx(self):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: PySimultan
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.1
|
4
4
|
Project-URL: Documentation, https://github.com/Bühler Maximilian/PySimultan2#readme
|
5
5
|
Project-URL: Issues, https://github.com/Bühler Maximilian/PySimultan2/issues
|
6
6
|
Project-URL: Source, https://github.com/Bühler Maximilian/PySimultan2
|
@@ -1,17 +1,16 @@
|
|
1
|
-
PySimultan2/__about__.py,sha256=
|
2
|
-
PySimultan2/__init__.py,sha256=
|
3
|
-
PySimultan2/
|
4
|
-
PySimultan2/
|
5
|
-
PySimultan2/
|
6
|
-
PySimultan2/files.py,sha256=q6A5KTqU1nCwh0W0Qf3Se7qcvhGiDAWza2v-X-rt6E4,12473
|
1
|
+
PySimultan2/__about__.py,sha256=L2Offsg-6m5gCNnCgevSz7hv6G-kIe1QidASLbohFtk,19
|
2
|
+
PySimultan2/__init__.py,sha256=00tn7bPM8yncDR41VxBYm5_gVy6i7ZdzpRJoop2pbLc,2692
|
3
|
+
PySimultan2/data_model.py,sha256=FBYw5yz4lNGgbpnuCnkkwBEkSxI3bv9eE4vumoxCeLU,26956
|
4
|
+
PySimultan2/default_types.py,sha256=GGAnuOCwF7YSt6tPDMr6houAILWyRsAhMfb9Y_Rpetk,22946
|
5
|
+
PySimultan2/files.py,sha256=97lRYzKP9hEqP0vKRUbYdd4WSRkgVQ-mJhSJuP_CYSY,12631
|
7
6
|
PySimultan2/multi_values.py,sha256=ZFXlTLuZo32x7_7diYAp2XEjp5uwgHLgNOzN7v74-5I,13650
|
8
|
-
PySimultan2/object_mapper.py,sha256=
|
9
|
-
PySimultan2/simultan_object.py,sha256=
|
10
|
-
PySimultan2/taxonomy_maps.py,sha256=
|
11
|
-
PySimultan2/utils.py,sha256=
|
7
|
+
PySimultan2/object_mapper.py,sha256=FvZR6qEB_dbsaH6V3EE9JgZdTgRTEvbYus01xp6wt9k,9676
|
8
|
+
PySimultan2/simultan_object.py,sha256=nK28YKOMAQfRJZGwjgbI9sFtJBb84kEaTIwGzWBiAqw,16900
|
9
|
+
PySimultan2/taxonomy_maps.py,sha256=aU9zUJph7QcInIZq0W-Vqoy4DYr0CEs-VsXwPMK_cxU,7976
|
10
|
+
PySimultan2/utils.py,sha256=w806h9aKT3T8Qn178qpXvuzaNpoNGzQVKORhtt3VGBM,62456
|
12
11
|
PySimultan2/geometry/__init__.py,sha256=nJolTD1i5J8qUkOQa-r3D20aq3Co3sN31Xc0n4wJpJo,248
|
13
|
-
PySimultan2/geometry/geometry_base.py,sha256=
|
14
|
-
PySimultan2/geometry/utils.py,sha256=
|
12
|
+
PySimultan2/geometry/geometry_base.py,sha256=HMz4jZk9Himd5zXZw642kX80bs5TcZNzAE4lPTIRwas,23393
|
13
|
+
PySimultan2/geometry/utils.py,sha256=J25YsK8sso_UL7xRusItQZvyjtvxdOsSPelBQYFABhY,8519
|
15
14
|
PySimultan2/resources/AssimpNet.dll,sha256=x8uwMHPRmEH9fDQihfEQLUdblM1u7RP-CCnUjOpXcLo,205312
|
16
15
|
PySimultan2/resources/AvalonDock.dll,sha256=9tCcw7cpaVq0bh1H2sfcxb8EWhySmgujPs89lAqIPZs,500224
|
17
16
|
PySimultan2/resources/BruTile.dll,sha256=ZiE_vovBW_CZOjDgOn8eaq_tfWRBD3-nSEk0ctBSdKI,198144
|
@@ -76,7 +75,7 @@ PySimultan2/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
76
75
|
PySimultan2/resources/assimp.dll,sha256=HwfDwXqoPDTFRyoQpA3qmgZoUdFtziJkV5fNtktEZEU,6081536
|
77
76
|
PySimultan2/resources/defaultsettings.xml,sha256=s6Tk1tubLz5UYqXZWpD42EDHzedemRY1nEneoIVcUfg,392
|
78
77
|
PySimultan2/resources/setup.bat,sha256=fjvvYfVM6TalS-QTSiKAbAId5nTsk8kGGo06ba-wWaY,32
|
79
|
-
pysimultan-0.4.
|
80
|
-
pysimultan-0.4.
|
81
|
-
pysimultan-0.4.
|
82
|
-
pysimultan-0.4.
|
78
|
+
pysimultan-0.4.1.dist-info/METADATA,sha256=J3X6HkTS9PHazoL50e2K-cugM3v3-7dRXjPe-oEVnRM,1657
|
79
|
+
pysimultan-0.4.1.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
|
80
|
+
pysimultan-0.4.1.dist-info/licenses/LICENSE.txt,sha256=pmSr98k6N005KMojnZxzLGRuRlDjDx3PUrK1lFj53HA,1126
|
81
|
+
pysimultan-0.4.1.dist-info/RECORD,,
|
PySimultan2/config.py
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import sys
|
3
|
-
from ruamel.yaml import YAML, yaml_object, add_representer
|
4
|
-
|
5
|
-
import colorlog
|
6
|
-
try:
|
7
|
-
import importlib.resources as pkg_resources
|
8
|
-
except ImportError:
|
9
|
-
# Try backported to PY<37 importlib_resources.
|
10
|
-
import importlib_resources as pkg_resources
|
11
|
-
|
12
|
-
|
13
|
-
from . import resources
|
14
|
-
sys.path.append(str(pkg_resources.files(resources)))
|
15
|
-
|
16
|
-
logger = colorlog.getLogger('PySimultan')
|
17
|
-
logger.setLevel('DEBUG')
|
18
|
-
|
19
|
-
dll_path = os.environ.get('SIMULTAN_SDK_DIR', None)
|
20
|
-
if dll_path is None:
|
21
|
-
with pkg_resources.path(resources, 'SIMULTAN.dll') as r_path:
|
22
|
-
dll_path = str(r_path)
|
23
|
-
sys.path.append(dll_path)
|
24
|
-
|
25
|
-
from pythonnet import load
|
26
|
-
from pythonnet import clr_loader, set_runtime
|
27
|
-
list(clr_loader.find_runtimes())
|
28
|
-
load('coreclr')
|
29
|
-
import clr
|
30
|
-
test = clr.AddReference(os.path.join(dll_path, 'SIMULTAN.dll') if not dll_path.endswith('SIMULTAN.dll') else dll_path)
|
31
|
-
clr.AddReference("System.Security.Cryptography")
|
32
|
-
# clr.AddReference(os.path.join(dll_path, 'SIMULTAN'))
|
33
|
-
|
34
|
-
from SIMULTAN.Data.Components import SimComponent
|
35
|
-
|
36
|
-
continue_on_error = True
|
37
|
-
|
38
|
-
|
39
|
-
def represent_none(self, _):
|
40
|
-
return self.represent_scalar('tag:yaml.org,2002:null', '')
|
41
|
-
|
42
|
-
|
43
|
-
add_representer(type(None), represent_none)
|
44
|
-
yaml = YAML()
|
45
|
-
yaml.default_flow_style = None
|
46
|
-
yaml.preserve_quotes = True
|
47
|
-
yaml.allow_unicode = True
|
48
|
-
|
49
|
-
# define which axis is in up/down direction; 0: x-axis; 1: y-axis; 2: z-axis; In SIMULTAN the y-axis is the up/down axis
|
50
|
-
cs_axis_up = 2
|
51
|
-
default_data_model = None
|
52
|
-
default_mapper = None
|
File without changes
|
File without changes
|