@@ -90,6 +90,11 @@ class Component:
90
90
transformed_part : TransformedPart, optional
91
91
This argument should be present when creating a nested instance component. It will use the
92
92
given transformed_part instead of creating a new one.
93
+ read_existing_comp : bool, optional
94
+ Indicates whether an existing component on the service should be read
95
+ or not. By default, ``False``. This is only valid when connecting
96
+ to an existing service session. Otherwise, avoid using this optional
97
+ argument.
93
98
"""
94
99
95
100
# Types of the class instance private attributes
@@ -108,8 +113,10 @@ def __init__(
108
113
template : Optional ["Component" ] = None ,
109
114
preexisting_id : Optional [str ] = None ,
110
115
transformed_part : Optional [TransformedPart ] = None ,
116
+ read_existing_comp : bool = False ,
111
117
):
112
118
"""Initialize ``Component`` class."""
119
+ # Initialize the client and stubs needed
113
120
self ._grpc_client = grpc_client
114
121
self ._component_stub = ComponentsStub (self ._grpc_client .channel )
115
122
self ._bodies_stub = BodiesStub (self ._grpc_client .channel )
@@ -124,27 +131,27 @@ def __init__(
124
131
new_component = self ._component_stub .Create (
125
132
CreateRequest (name = name , parent = parent_component .id , template = template_id )
126
133
)
127
- self ._id = new_component .component .id
134
+ # Remove this method call once we know Service sends correct ObjectPath id
135
+ self ._id = self .__remove_duplicate_ids (new_component .component .id )
128
136
self ._name = new_component .component .name
129
137
else :
130
138
self ._name = name
131
139
self ._id = None
132
140
141
+ # Initialize needed instance variables
133
142
self ._components = []
134
143
self ._beams = []
135
144
self ._coordinate_systems = []
136
145
self ._design_points = []
137
146
self ._parent_component = parent_component
138
147
self ._is_alive = True
139
148
self ._shared_topology = None
140
- self ._transformed_part = None
149
+ self ._transformed_part = transformed_part
141
150
142
151
# Populate client data model
143
152
if template :
144
- if transformed_part :
145
- # Re-use an existing tp if this is a nested instance
146
- self ._transformed_part = transformed_part
147
- else :
153
+ # If this is not a nested instance
154
+ if not transformed_part :
148
155
# Create new TransformedPart, but use template's Part
149
156
tp = TransformedPart (
150
157
uuid .uuid4 (),
@@ -157,8 +164,10 @@ def __init__(
157
164
158
165
# Recurse - Create more children components from template's remaining children
159
166
self .__create_children (template )
160
- else :
161
- # Create new Part and TransformedPart since this is creating a new "master"
167
+ return
168
+
169
+ elif not read_existing_comp :
170
+ # This is an independent Component - Create new Part and TransformedPart
162
171
p = Part (uuid .uuid4 (), f"p_{ name } " , [], [])
163
172
tp = TransformedPart (uuid .uuid4 (), f"tp_{ name } " , p )
164
173
p .parts .append (tp )
@@ -184,8 +193,7 @@ def bodies(self) -> List[Body]:
184
193
"""``Body`` objects inside of the component."""
185
194
bodies = []
186
195
for body in self ._transformed_part .part .bodies :
187
- id = self .id + body .id if self .parent_component else body .id
188
- id = self .__fix_moniker (id )
196
+ id = f"{ self .id } /{ body .id } " if self .parent_component else body .id
189
197
bodies .append (Body (id , body .name , self , body ))
190
198
return bodies
191
199
@@ -226,43 +234,37 @@ def shared_topology(self) -> Union[SharedTopologyType, None]:
226
234
227
235
def __create_children (self , template : "Component" ) -> None :
228
236
"""Create new Component and Body children in ``self`` from ``template``."""
229
- for t_body in template .bodies :
230
- new_id = self .id + ("~" + t_body .id .split ("~" )[- 1 ])
231
- new_body = Body (new_id , t_body .name , self , t_body ._template )
232
- self .bodies .append (new_body )
233
-
234
237
for template_comp in template .components :
238
+ new_id = self .id + "/" + template_comp .id .split ("/" )[- 1 ]
235
239
new = Component (
236
240
template_comp .name ,
237
241
self ,
238
242
self ._grpc_client ,
239
243
template = template_comp ,
240
- preexisting_id = self . __fix_moniker ( self . id + template_comp . id ) ,
244
+ preexisting_id = new_id ,
241
245
transformed_part = template_comp ._transformed_part ,
242
246
)
243
247
self .components .append (new )
244
248
245
- def __fix_moniker (self , string : str ) -> str :
246
- """Format a chain of monikers so the service can identify the entities."""
247
- x = string .split ("~" )[1 :]
248
- if len (x ) > 1 :
249
- x [0 ] = x [0 ].replace ("sE" , "~sO_~iI" , 1 )
250
- for s in x [1 :- 1 ]:
251
- index = x .index (s )
252
- s = "~" + s if s [0 ] != "~" else s
253
- s = s .replace ("sE" , "oO" , 1 )
254
- s = s .replace ("oE" , "oO" , 1 )
255
- if "iI" not in x [index + 1 ]:
256
- s = s .replace ("oO" , "oO_~iI" , 1 )
257
- s = s .replace ("___" , "__" , 1 )
258
- x [index ] = s
259
- x [- 1 ] = x [- 1 ].replace ("sE" , "~oE" , 1 )
260
- x = "" .join (x ) + "_"
261
- else :
262
- x = "" .join (x )
263
- if x [0 ] != "~" :
264
- x = "~" + x
265
- return x
249
+ def __remove_duplicate_ids (self , path : str ) -> str :
250
+ """
251
+ Remove duplicate entries in the ID path.
252
+
253
+ Notes
254
+ -----
255
+ This is a safeguard, as the server is known to have issues sometimes.
256
+
257
+ Examples
258
+ --------
259
+ This method converts "0:26/0:44/0:44/0:53" to "0:26/0:44/0:53".
260
+ """
261
+ # Split the string into a list -> convert list into a set but maintain order
262
+ res = []
263
+ [res .append (x ) for x in path .split ("/" ) if x not in res ]
264
+ id = "/" .join (res )
265
+ if id != path :
266
+ print ("Removed duplicate!" )
267
+ return id
266
268
267
269
def get_world_transform (self ) -> Matrix44 :
268
270
"""
@@ -421,7 +423,9 @@ def extrude_sketch(
421
423
response = self ._bodies_stub .CreateExtrudedBody (request )
422
424
tb = TemplateBody (response .master_id , name , self ._grpc_client , is_surface = False )
423
425
self ._transformed_part .part .bodies .append (tb )
424
- return Body (response .id , response .name , self , tb )
426
+ # TODO: fix when DMS ObjectPath is fixed - previously we return the body with response.id
427
+ body_id = f"{ self .id } /{ tb .id } " if self .parent_component else tb .id
428
+ return Body (body_id , response .name , self , tb )
425
429
426
430
@protect_grpc
427
431
@check_input_types
@@ -468,7 +472,9 @@ def extrude_face(self, name: str, face: Face, distance: Union[Quantity, Distance
468
472
469
473
tb = TemplateBody (response .master_id , name , self ._grpc_client , is_surface = False )
470
474
self ._transformed_part .part .bodies .append (tb )
471
- return Body (response .id , response .name , self , tb )
475
+ # TODO: fix when DMS ObjectPath is fixed - previously we return the body with response.id
476
+ body_id = f"{ self .id } /{ tb .id } " if self .parent_component else tb .id
477
+ return Body (body_id , response .name , self , tb )
472
478
473
479
@protect_grpc
474
480
@check_input_types
@@ -505,7 +511,9 @@ def create_surface(self, name: str, sketch: Sketch) -> Body:
505
511
506
512
tb = TemplateBody (response .master_id , name , self ._grpc_client , is_surface = True )
507
513
self ._transformed_part .part .bodies .append (tb )
508
- return Body (response .id , response .name , self , tb )
514
+ # TODO: fix when DMS ObjectPath is fixed - previously we return the body with response.id
515
+ body_id = f"{ self .id } /{ tb .id } " if self .parent_component else tb .id
516
+ return Body (body_id , response .name , self , tb )
509
517
510
518
@protect_grpc
511
519
@check_input_types
@@ -545,7 +553,9 @@ def create_surface_from_face(self, name: str, face: Face) -> Body:
545
553
546
554
tb = TemplateBody (response .master_id , name , self ._grpc_client , is_surface = True )
547
555
self ._transformed_part .part .bodies .append (tb )
548
- return Body (response .id , response .name , self , tb )
556
+ # TODO: fix when DMS ObjectPath is fixed - previously we return the body with response.id
557
+ body_id = f"{ self .id } /{ tb .id } " if self .parent_component else tb .id
558
+ return Body (body_id , response .name , self , tb )
549
559
550
560
@check_input_types
551
561
def create_coordinate_system (self , name : str , frame : Frame ) -> CoordinateSystem :
0 commit comments