37
37
from ansys .geometry .core .connection .client import GrpcClient
38
38
from ansys .geometry .core .connection .defaults import DEFAULT_HOST , DEFAULT_PORT
39
39
from ansys .geometry .core .errors import GeometryRuntimeError , protect_grpc
40
- from ansys .geometry .core .logger import LOG
41
- from ansys .geometry .core .misc .checks import check_type , min_backend_version
40
+ from ansys .geometry .core .misc .checks import check_type , deprecated_method , min_backend_version
42
41
from ansys .geometry .core .misc .options import ImportOptions
43
42
from ansys .geometry .core .tools .measurement_tools import MeasurementTools
44
43
from ansys .geometry .core .tools .prepare_tools import PrepareTools
@@ -120,15 +119,15 @@ def __init__(
120
119
backend_type = backend_type ,
121
120
)
122
121
123
- # Maintaining references to all designs within the modeler workspace
124
- self ._designs : dict [ str , "Design" ] = {}
122
+ # Single design for the Modeler
123
+ self ._design : Optional [ "Design" ] = None
125
124
126
125
# Initialize the RepairTools - Not available on Linux
127
126
# TODO: delete "if" when Linux service is able to use repair tools
128
127
# https://github.com/ansys/pyansys-geometry/issues/1319
129
128
if BackendType .is_core_service (self .client .backend_type ):
130
129
self ._measurement_tools = None
131
- LOG .warning ("CoreService backend does not support measurement tools." )
130
+ self . client . log .warning ("CoreService backend does not support measurement tools." )
132
131
else :
133
132
self ._measurement_tools = MeasurementTools (self ._grpc_client )
134
133
@@ -138,28 +137,26 @@ def __init__(
138
137
self ._geometry_commands = GeometryCommands (self ._grpc_client )
139
138
self ._unsupported = UnsupportedCommands (self ._grpc_client , self )
140
139
141
- # Check if the backend allows for multiple designs and throw warning if needed
142
- if not self .client .multiple_designs_allowed :
143
- LOG .warning (
144
- "Linux and Ansys Discovery backends do not support multiple "
145
- "designs open in the same session. Only the last design created "
146
- "will be available to perform modeling operations."
147
- )
148
-
149
140
@property
150
141
def client (self ) -> GrpcClient :
151
142
"""``Modeler`` instance client."""
152
143
return self ._grpc_client
153
144
154
145
@property
146
+ def design (self ) -> "Design" :
147
+ """Retrieve the design within the modeler workspace."""
148
+ return self ._design
149
+
150
+ @property
151
+ @deprecated_method (alternative = "design" )
155
152
def designs (self ) -> dict [str , "Design" ]:
156
- """All designs within the modeler workspace.
153
+ """Retrieve the design within the modeler workspace.
157
154
158
155
Notes
159
156
-----
160
- This property is read-only. **DO NOT** modify the dictionary .
157
+ This method is deprecated. Use the :func:`design` property instead .
161
158
"""
162
- return self ._designs
159
+ return { self ._design . id : self . _design }
163
160
164
161
def create_design (self , name : str ) -> "Design" :
165
162
"""Initialize a new design with the connected client.
@@ -177,14 +174,20 @@ def create_design(self, name: str) -> "Design":
177
174
from ansys .geometry .core .designer .design import Design
178
175
179
176
check_type (name , str )
177
+
178
+ # If a previous design was available... inform the user that it will be deleted
179
+ # when creating a new design.
180
+ if self ._design is not None and self ._design .is_active :
181
+ self .client .log .warning ("Closing previous design before creating a new one." )
182
+ self ._design .close ()
183
+
184
+ # Create the new design
180
185
design = Design (name , self )
181
- self ._designs [design .design_id ] = design
182
- if len (self ._designs ) > 1 :
183
- LOG .warning (
184
- "Some backends only support one design. "
185
- + "Previous designs may be deleted (on the service) when creating a new one."
186
- )
187
- return self ._designs [design .design_id ]
186
+
187
+ # Update the design stored in the modeler
188
+ self ._design = design
189
+
190
+ return self ._design
188
191
189
192
def get_active_design (self , sync_with_backend : bool = True ) -> "Design" :
190
193
"""Get the active design on the modeler object.
@@ -201,14 +204,13 @@ def get_active_design(self, sync_with_backend: bool = True) -> "Design":
201
204
Design
202
205
Design object already existing on the modeler.
203
206
"""
204
- for _ , design in self ._designs .items ():
205
- if design ._is_active :
206
- # Check if sync_with_backend is requested
207
- if sync_with_backend :
208
- design ._update_design_inplace ()
209
-
210
- # Return the active design
211
- return design
207
+ if self ._design is not None and self ._design .is_active :
208
+ # Check if sync_with_backend is requested
209
+ if sync_with_backend :
210
+ self ._design ._update_design_inplace ()
211
+ return self ._design
212
+ else :
213
+ self .client .log .warning ("No active design available." )
212
214
213
215
return None
214
216
@@ -222,43 +224,45 @@ def read_existing_design(self) -> "Design":
222
224
"""
223
225
from ansys .geometry .core .designer .design import Design
224
226
225
- design = Design ("" , self , read_existing_design = True )
226
- self ._designs [design .design_id ] = design
227
- if len (self ._designs ) > 1 :
228
- LOG .warning (
229
- "Some backends only support one design. "
230
- + "Previous designs may be deleted (on the service) when reading a new one."
231
- )
232
- return self ._designs [design .design_id ]
227
+ # Simply deactivate the existing design in case it is active...
228
+ # - If it is the same design, it will be re-read (but we should not close it on the server)
229
+ # - If it is a different design, it was closed previously (via open_file or create_design)
230
+ if self ._design is not None and self ._design .is_active :
231
+ self ._design ._is_active = False
233
232
234
- def close (self , close_designs : bool = True ) -> None :
233
+ self ._design = Design ("" , self , read_existing_design = True )
234
+
235
+ return self ._design
236
+
237
+ def close (self , close_design : bool = True ) -> None :
235
238
"""Access the client's close method.
236
239
237
240
Parameters
238
241
----------
239
- close_designs : bool, default: True
240
- Whether to close all designs before closing the client.
242
+ close_design : bool, default: True
243
+ Whether to close the design before closing the client.
241
244
"""
242
- # Close all designs (if requested)
243
- [design .close () for design in self ._designs .values () if close_designs ]
245
+ # Close design (if requested)
246
+ if close_design and self ._design is not None :
247
+ self ._design .close ()
244
248
245
249
# Close the client
246
250
self .client .close ()
247
251
248
- def exit (self , close_designs : bool = True ) -> None :
252
+ def exit (self , close_design : bool = True ) -> None :
249
253
"""Access the client's close method.
250
254
251
255
Parameters
252
256
----------
253
- close_designs : bool, default: True
254
- Whether to close all designs before closing the client.
257
+ close_design : bool, default: True
258
+ Whether to close the design before closing the client.
255
259
256
260
Notes
257
261
-----
258
262
This method is calling the same method as
259
263
:func:`close() <ansys.geometry.core.modeler.Modeler.close>`.
260
264
"""
261
- self .close (close_designs = close_designs )
265
+ self .close (close_design = close_design )
262
266
263
267
def _upload_file (
264
268
self ,
@@ -301,7 +305,7 @@ def _upload_file(
301
305
with fp_path .open (mode = "rb" ) as file :
302
306
data = file .read ()
303
307
304
- c_stub = CommandsStub (self ._grpc_client .channel )
308
+ c_stub = CommandsStub (self .client .channel )
305
309
306
310
response = c_stub .UploadFile (
307
311
UploadFileRequest (
@@ -348,6 +352,10 @@ def open_file(
348
352
# Use str format of Path object here
349
353
file_path = str (file_path ) if isinstance (file_path , Path ) else file_path
350
354
355
+ # Close the existing design if it is active
356
+ if self ._design is not None and self ._design .is_active :
357
+ self ._design .close ()
358
+
351
359
# Format-specific logic - upload the whole containing folder for assemblies
352
360
if upload_to_server :
353
361
if any (
@@ -361,7 +369,7 @@ def open_file(
361
369
self ._upload_file (full_path )
362
370
self ._upload_file (file_path , True , import_options )
363
371
else :
364
- DesignsStub (self ._grpc_client .channel ).Open (
372
+ DesignsStub (self .client .channel ).Open (
365
373
OpenRequest (filepath = file_path , import_options = import_options .to_dict ())
366
374
)
367
375
@@ -372,7 +380,7 @@ def __repr__(self) -> str:
372
380
lines = []
373
381
lines .append (f"Ansys Geometry Modeler ({ hex (id (self ))} )" )
374
382
lines .append ("" )
375
- lines .append (str (self ._grpc_client ))
383
+ lines .append (str (self .client ))
376
384
return "\n " .join (lines )
377
385
378
386
@protect_grpc
@@ -468,7 +476,7 @@ def run_discovery_script_file(
468
476
api_version = ApiVersions .parse_input (api_version )
469
477
470
478
serv_path = self ._upload_file (file_path )
471
- ga_stub = DbuApplicationStub (self ._grpc_client .channel )
479
+ ga_stub = DbuApplicationStub (self .client .channel )
472
480
request = RunScriptFileRequest (
473
481
script_path = serv_path ,
474
482
script_args = script_args ,
0 commit comments