ansys-mechanical-core 0.11.14__py3-none-any.whl → 0.11.16__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 (24) hide show
  1. ansys/mechanical/core/__init__.py +3 -3
  2. ansys/mechanical/core/embedding/app.py +26 -12
  3. ansys/mechanical/core/embedding/appdata.py +26 -22
  4. ansys/mechanical/core/embedding/enum_importer.py +6 -0
  5. ansys/mechanical/core/embedding/{viz → graphics}/embedding_plotter.py +1 -1
  6. ansys/mechanical/core/embedding/initializer.py +70 -0
  7. ansys/mechanical/core/embedding/messages.py +27 -22
  8. ansys/mechanical/core/embedding/resolver.py +1 -1
  9. ansys/mechanical/core/embedding/rpc/__init__.py +3 -7
  10. ansys/mechanical/core/embedding/rpc/client.py +19 -5
  11. ansys/mechanical/core/embedding/rpc/default_server.py +131 -0
  12. ansys/mechanical/core/embedding/rpc/server.py +146 -158
  13. ansys/mechanical/core/embedding/rpc/utils.py +18 -0
  14. ansys/mechanical/core/embedding/runtime.py +6 -0
  15. ansys/mechanical/core/ide_config.py +1 -0
  16. ansys/mechanical/core/mechanical.py +24 -12
  17. {ansys_mechanical_core-0.11.14.dist-info → ansys_mechanical_core-0.11.16.dist-info}/METADATA +15 -12
  18. {ansys_mechanical_core-0.11.14.dist-info → ansys_mechanical_core-0.11.16.dist-info}/RECORD +24 -23
  19. {ansys_mechanical_core-0.11.14.dist-info → ansys_mechanical_core-0.11.16.dist-info}/WHEEL +1 -1
  20. /ansys/mechanical/core/embedding/{viz → graphics}/__init__.py +0 -0
  21. /ansys/mechanical/core/embedding/{viz → graphics}/usd_converter.py +0 -0
  22. /ansys/mechanical/core/embedding/{viz → graphics}/utils.py +0 -0
  23. {ansys_mechanical_core-0.11.14.dist-info → ansys_mechanical_core-0.11.16.dist-info}/entry_points.txt +0 -0
  24. {ansys_mechanical_core-0.11.14.dist-info → ansys_mechanical_core-0.11.16.dist-info}/licenses/LICENSE +0 -0
@@ -21,7 +21,6 @@
21
21
  # SOFTWARE.
22
22
  """Remote Procedure Call (RPC) server."""
23
23
 
24
- import fnmatch
25
24
  import os
26
25
  import threading
27
26
  import time
@@ -31,26 +30,63 @@ import rpyc
31
30
  from rpyc.utils.server import ThreadedServer
32
31
  import toolz
33
32
 
33
+ from ansys.mechanical.core.embedding.app import App
34
34
  from ansys.mechanical.core.embedding.background import BackgroundApp
35
- from ansys.mechanical.core.mechanical import port_in_use
35
+ import ansys.mechanical.core.embedding.utils
36
36
 
37
- from .utils import MethodType, get_remote_methods, remote_method
37
+ from .utils import MethodType, get_free_port, get_remote_methods
38
38
 
39
39
  # TODO : implement logging
40
40
 
41
- PYMECHANICAL_DEFAULT_RPC_PORT = 20000
41
+
42
+ class ForegroundAppBackend:
43
+ """Backend for the python server where mechanical uses the main thread."""
44
+
45
+ def __init__(self, app: App):
46
+ """Create a new instance of ForegroundAppBackend."""
47
+ self._app = app
48
+ self._poster = app.poster
49
+
50
+ def try_post(self, callable: typing.Callable) -> typing.Any:
51
+ """Try to post to mechanical's main thread."""
52
+ return self._poster.try_post(callable)
53
+
54
+ def get_app(self) -> App:
55
+ """Get the app object."""
56
+ return self._app
57
+
58
+
59
+ class BackgroundAppBackend:
60
+ """Backend for the python server where mechanical uses the background thread."""
61
+
62
+ def __init__(self, backgroundapp: BackgroundApp):
63
+ """Create a new instance of BackgroundAppBackend."""
64
+ self._backgroundapp = backgroundapp
65
+
66
+ def try_post(self, callable: typing.Callable) -> typing.Any:
67
+ """Try to post to mechanical's main thread."""
68
+ return self._backgroundapp.try_post(callable)
69
+
70
+ def get_app(self) -> App:
71
+ """Get the app object."""
72
+ return self._backgroundapp.app
42
73
 
43
74
 
44
75
  class MechanicalService(rpyc.Service):
45
76
  """Starts Mechanical app services."""
46
77
 
47
- def __init__(self, backgroundapp, functions=[], impl=None):
78
+ def __init__(self, backend, functions=[], impl=[]):
48
79
  """Initialize the service."""
49
80
  super().__init__()
50
- self._backgroundapp = backgroundapp
81
+ self._backend = backend
51
82
  self._install_functions(functions)
52
- self._install_class(impl)
53
- self.EMBEDDED = True
83
+ self._install_classes(impl)
84
+
85
+ def _try_post(self, callable: typing.Callable) -> typing.Any:
86
+ return self._backend.try_post(callable)
87
+
88
+ def _get_app(self) -> App:
89
+ return self._backend.get_app()
54
90
 
55
91
  def on_connect(self, conn):
56
92
  """Handle client connection."""
@@ -62,8 +98,16 @@ class MechanicalService(rpyc.Service):
62
98
 
63
99
  def _install_functions(self, methods):
64
100
  """Install the given list of methods."""
101
+ if not methods:
102
+ return
65
103
  [self._install_function(method) for method in methods]
66
104
 
105
+ def _install_classes(self, impl):
106
+ """Install the given list of classes."""
107
+ if not impl:
108
+ return
109
+ [self._install_class(_impl) for _impl in impl]
110
+
67
111
  def _install_class(self, impl):
68
112
  """Install methods from the given implemented class."""
69
113
  if impl is None:
@@ -84,7 +128,7 @@ class MechanicalService(rpyc.Service):
84
128
  else:
85
129
  setattr(prop._owner, propname, *arg)
86
130
 
87
- return self._backgroundapp.try_post(curried)
131
+ return self._try_post(curried)
88
132
 
89
133
  return posted
90
134
 
@@ -97,7 +141,7 @@ class MechanicalService(rpyc.Service):
97
141
  result = original_method(*args, **kwargs)
98
142
  return result
99
143
 
100
- return self._backgroundapp.try_post(curried)
144
+ return self._try_post(curried)
101
145
 
102
146
  return posted
103
147
 
@@ -108,9 +152,9 @@ class MechanicalService(rpyc.Service):
108
152
 
109
153
  def posted(*args, **kwargs):
110
154
  def curried():
111
- return curried_method(self._app, *args, **kwargs)
155
+ return curried_method(self._get_app(), *args, **kwargs)
112
156
 
113
- return self._backgroundapp.try_post(curried)
157
+ return self._try_post(curried)
114
158
 
115
159
  return posted
116
160
 
@@ -209,9 +253,7 @@ class MechanicalService(rpyc.Service):
209
253
  def exposed_service_exit(self):
210
254
  """Exit the server."""
211
255
  print("Shutting down server ...")
212
- self._backgroundapp.stop()
213
- self._backgroundapp = None
214
- self._server.stop_async()
256
+ self._exit_f()
215
257
  print("Server stopped")
216
258
 
217
259
 
@@ -220,184 +262,130 @@ class MechanicalEmbeddedServer:
220
262
 
221
263
  def __init__(
222
264
  self,
223
- service: typing.Type[rpyc.Service] = MechanicalService,
224
265
  port: int = None,
225
266
  version: int = None,
226
267
  methods: typing.List[typing.Callable] = [],
227
- impl=None,
268
+ impl: typing.List = [],
228
269
  ):
229
270
  """Initialize the server."""
230
271
  self._exited = False
231
- self._background_app = BackgroundApp(version=version)
232
- self._service = service
233
- self._methods = methods
234
- self._exit_thread: threading.Thread = None
235
-
236
- self._port = self.get_free_port(port)
237
- if impl is None:
238
- self._impl = None
272
+ use_background_app = False
273
+ if use_background_app:
274
+ self._app_instance = BackgroundApp(version=version)
275
+ self._backend = BackgroundAppBackend(self._app_instance)
239
276
  else:
240
- self._impl = impl(self._background_app.app)
277
+ self._app_instance = App(version=version)
278
+ self._backend = ForegroundAppBackend(self._app_instance)
279
+ self._port = get_free_port(port)
280
+ self._install_methods(methods)
281
+ self._install_classes(impl)
282
+ self._server = ThreadedServer(self._create_service(), port=self._port)
241
283
 
242
- my_service = self._service(self._background_app, self._methods, self._impl)
243
- self._server = ThreadedServer(my_service, port=self._port)
244
- my_service._server = self
284
+ def _create_service(self):
285
+ service = MechanicalService(self._backend, self._methods, self._impl)
245
286
 
246
- @staticmethod
247
- def get_free_port(port=None):
248
- """Get free port.
287
+ def exit_f():
288
+ self.stop()
249
289
 
250
- If port is not given, it will find a free port starting from PYMECHANICAL_DEFAULT_RPC_PORT.
251
- """
252
- if port is None:
253
- port = PYMECHANICAL_DEFAULT_RPC_PORT
290
+ service._exit_f = exit_f
291
+ return service
254
292
 
255
- while port_in_use(port):
256
- port += 1
293
+ def _is_stopped(self):
294
+ return self._app_instance is None
257
295
 
258
- return port
296
+ def _wait_exit(self) -> None:
297
+ if self._exit_thread is None:
298
+ return
299
+ self._exit_thread.join()
259
300
 
260
- def start(self) -> None:
301
+ def _start_background_app(self) -> None:
261
302
  """Start server on specified port."""
262
- print(
263
- f"Starting mechanical application in server.\n"
264
- f"Listening on port {self._port}\n{self._background_app.app}"
265
- )
303
+ self._exit_thread: threading.Thread = None
266
304
  self._server.start()
267
- """try:
268
- try:
269
- conn.serve_all()
270
- except KeyboardInterrupt:
271
- print("User interrupt!")
272
- finally:
273
- conn.close()"""
274
305
  print("Server exited!")
275
306
  self._wait_exit()
276
307
  self._exited = True
277
308
 
278
- def _wait_exit(self) -> None:
279
- if self._exit_thread is None:
280
- return
281
- self._exit_thread.join()
309
+ def _stop_background_app(self):
310
+ """Return immediately but will stop the server.
282
311
 
283
- def stop_async(self):
284
- """Return immediately but will stop the server."""
312
+ Mechanical is running on the background but
313
+ the rpyc server is running on the main thread
314
+ this signals for the server to stop, and the main
315
+ thread will wait until the server has stopped.
316
+ """
285
317
 
286
318
  def stop_f(): # wait for all connections to close
287
319
  while len(self._server.clients) > 0:
288
320
  time.sleep(0.005)
289
- self._background_app.stop()
321
+ self._app_instance.stop()
322
+ self._app_instance = None
323
+ self._backend = None
290
324
  self._server.close()
291
325
  self._exited = True
292
326
 
293
327
  self._exit_thread = threading.Thread(target=stop_f)
294
328
  self._exit_thread.start()
295
329
 
296
- def stop(self) -> None:
297
- """Stop the server."""
298
- print("Stopping the server...")
299
- self._background_app.stop()
300
- self._server.close()
301
- self._exited = True
302
- print("Server stopped.")
330
+ def _start_foreground_app(self):
331
+ self._server_stopped = False
303
332
 
333
+ def start_f():
334
+ print("Server started!")
335
+ self._server.start()
336
+ print("Server exited!")
304
337
 
305
- class DefaultServiceMethods:
306
- """Default service methods for MechanicalEmbeddedServer."""
338
+ self._server_thread = threading.Thread(target=start_f)
339
+ self._server_thread.start()
340
+ while True:
341
+ if self._server_stopped:
342
+ break
343
+ try:
344
+ ansys.mechanical.core.embedding.utils.sleep(40)
345
+ except Exception as e:
346
+ print(f"An error occurred: {e}")
347
+ self._server_thread.join()
307
348
 
308
- def __init__(self, app):
309
- """Initialize the DefaultServiceMethods."""
310
- self._app = app
349
+ def _stop_foreground_app(self):
350
+ self._server_stopped = True
351
+ self._server.close()
352
+ # self._server_thread.join()
311
353
 
312
- def __repr__(self):
313
- """Return the representation of the instance."""
314
- return '"ServiceMethods instance"'
354
+ def _get_app_repr(self) -> str:
355
+ def f():
356
+ return repr(self._backend.get_app())
315
357
 
316
- @remote_method
317
- def run_python_script(
318
- self, script: str, enable_logging=False, log_level="WARNING", progress_interval=2000
319
- ):
320
- """Run scripts using Internal python engine."""
321
- result = self._app.execute_script(script)
322
- return result
358
+ return self._backend.try_post(f)
323
359
 
324
- @remote_method
325
- def run_python_script_from_file(
326
- self,
327
- file_path: str,
328
- enable_logging=False,
329
- log_level="WARNING",
330
- progress_interval=2000,
331
- ):
332
- """Run scripts using Internal python engine."""
333
- return self._app.execute_script_from_file(file_path)
334
-
335
- @remote_method
336
- def clear(self):
337
- """Clear the current project."""
338
- self._app.new()
339
-
340
- @property
341
- @remote_method
342
- def project_directory(self):
343
- """Get the project directory."""
344
- return self._app.execute_script("""ExtAPI.DataModel.Project.ProjectDirectory""")
345
-
346
- @remote_method
347
- def list_files(self):
348
- """List all files in the project directory."""
349
- list = []
350
- mechdbPath = self._app.execute_script("""ExtAPI.DataModel.Project.FilePath""")
351
- if mechdbPath != "":
352
- list.append(mechdbPath)
353
- rootDir = self._app.execute_script("""ExtAPI.DataModel.Project.ProjectDirectory""")
354
-
355
- for dirPath, dirNames, fileNames in os.walk(rootDir):
356
- for fileName in fileNames:
357
- list.append(os.path.join(dirPath, fileName))
358
- files_out = "\n".join(list).splitlines()
359
- if not files_out: # pragma: no cover
360
- print("No files listed")
361
- return files_out
362
-
363
- @remote_method
364
- def _get_files(self, files, recursive=False):
365
- self_files = self.list_files() # to avoid calling it too much
366
-
367
- if isinstance(files, str):
368
- if files in self_files:
369
- list_files = [files]
370
- elif "*" in files:
371
- list_files = fnmatch.filter(self_files, files)
372
- if not list_files:
373
- raise ValueError(
374
- f"The `'files'` parameter ({files}) didn't match any file using "
375
- f"glob expressions in the remote server."
376
- )
377
- else:
378
- raise ValueError(
379
- f"The `'files'` parameter ('{files}') does not match any file or pattern."
380
- )
381
-
382
- elif isinstance(files, (list, tuple)):
383
- if not all([isinstance(each, str) for each in files]):
384
- raise ValueError(
385
- "The parameter `'files'` can be a list or tuple, but it "
386
- "should only contain strings."
387
- )
388
- list_files = files
360
+ def start(self) -> None:
361
+ """Start server on specified port."""
362
+ print(
363
+ f"Starting mechanical application in server.\n"
364
+ f"Listening on port {self._port}\n{self._get_app_repr()}"
365
+ )
366
+ if isinstance(self._app_instance, BackgroundApp):
367
+ self._start_background_app()
389
368
  else:
390
- raise ValueError(
391
- f"The `file` parameter type ({type(files)}) is not supported."
392
- "Only strings, tuple of strings, or list of strings are allowed."
393
- )
394
-
395
- return list_files
396
-
397
-
398
- class MechanicalDefaultServer(MechanicalEmbeddedServer):
399
- """Default server with default service methods."""
369
+ self._start_foreground_app()
400
370
 
401
- def __init__(self, **kwargs):
402
- """Initialize the MechanicalDefaultServer."""
403
- super().__init__(service=MechanicalService, impl=DefaultServiceMethods, **kwargs)
371
+ def stop(self) -> None:
372
+ """Stop the server."""
373
+ if self._is_stopped():
374
+ raise Exception("already stopped!")
375
+ if isinstance(self._app_instance, BackgroundApp):
376
+ self._stop_background_app()
377
+ else:
378
+ self._stop_foreground_app()
379
+
380
+ def _install_classes(self, impl: typing.Union[typing.Any, typing.List]) -> None:
381
+ app = self._backend.get_app()
382
+ if impl and not isinstance(impl, list):
383
+ impl = [impl]
384
+ self._impl = [i(app) for i in impl] if impl else []
385
+
386
+ def _install_methods(
387
+ self, methods: typing.Union[typing.Callable, typing.List[typing.Callable]]
388
+ ) -> None:
389
+ if methods and not isinstance(methods, list):
390
+ methods = [methods]
391
+ self._methods = methods if methods is not None else []
@@ -22,6 +22,10 @@
22
22
  """Utilities necessary for remote calls."""
23
23
  import typing
24
24
 
25
+ from ansys.mechanical.core.mechanical import port_in_use
26
+
27
+ PYMECHANICAL_DEFAULT_RPC_PORT = 20000
28
+
25
29
 
26
30
  class remote_method:
27
31
  """Decorator for passing remote methods."""
@@ -116,3 +120,17 @@ def get_remote_methods(
116
120
  if result != None:
117
121
  attrname, method = result
118
122
  yield attrname, method, MethodType.METHOD
123
+
124
+
125
+ def get_free_port(port: int = None):
126
+ """Get free port.
127
+
128
+ If port is not given, it will find a free port starting from PYMECHANICAL_DEFAULT_RPC_PORT.
129
+ """
130
+ if port is None:
131
+ port = PYMECHANICAL_DEFAULT_RPC_PORT
132
+
133
+ while port_in_use(port):
134
+ port += 1
135
+
136
+ return port
@@ -50,13 +50,17 @@ def _bind_assembly_for_explicit_interface(assembly_name: str):
50
50
  # if pythonnet is not installed, we can't bind the assembly
51
51
  try:
52
52
  distribution("pythonnet")
53
+ Logger.warning("Cannot bind for explicit interface because pythonnet is installed")
53
54
  return
54
55
  except ModuleNotFoundError:
55
56
  pass
56
57
 
58
+ Logger.debug(f"Binding assembly for explicit interface {assembly_name}")
57
59
  import clr
58
60
 
61
+ Logger.debug(f"Binding assembly for explicit interface, Loading {assembly_name}")
59
62
  assembly = clr.AddReference(assembly_name)
63
+ Logger.debug(f"Binding assembly for explicit interface, Loaded {assembly_name}")
60
64
  from Python.Runtime import BindingManager, BindingOptions
61
65
 
62
66
  binding_options = BindingOptions()
@@ -78,6 +82,8 @@ def initialize(version: int) -> None:
78
82
  if version >= 242 or os.name == "nt":
79
83
  # function codec is distributed with pymechanical on linux only
80
84
  # at version 242 or later
85
+ Logger.debug("Registering function codec")
81
86
  __register_function_codec()
87
+ Logger.debug("Registered function codec")
82
88
 
83
89
  _bind_assembly_for_explicit_interface("Ansys.ACT.WB1")
@@ -93,6 +93,7 @@ def _vscode_impl(
93
93
  If unspecified, it finds the default Mechanical version from ansys-tools-path.
94
94
  """
95
95
  # Update the user or workspace settings
96
+ settings_json = "the settings.json file"
96
97
  if target == "user":
97
98
  # Get the path to the user's settings.json file depending on the platform
98
99
  if "win" in sys.platform:
@@ -34,6 +34,7 @@ import subprocess # nosec: B404
34
34
  import sys
35
35
  import threading
36
36
  import time
37
+ import typing
37
38
  from typing import Optional
38
39
  import warnings
39
40
  import weakref
@@ -460,10 +461,11 @@ class Mechanical(object):
460
461
  else:
461
462
  self.log_info("Mechanical connection is treated as remote.")
462
463
 
464
+ self._error_type = grpc.RpcError
465
+
463
466
  # connect and validate to the channel
464
467
  self._multi_connect(timeout=timeout)
465
468
  self.log_info("Mechanical is ready to accept grpc calls.")
466
- self._rpc_type = "grpc"
467
469
 
468
470
  def __del__(self): # pragma: no cover
469
471
  """Clean up on exit."""
@@ -482,6 +484,11 @@ class Mechanical(object):
482
484
  """Log associated with the current Mechanical instance."""
483
485
  return self._log
484
486
 
487
+ @property
488
+ def backend(self) -> str:
489
+ """Return the backend type."""
490
+ return "mechanical"
491
+
485
492
  @property
486
493
  def version(self) -> str:
487
494
  """Get the Mechanical version based on the instance.
@@ -1204,9 +1211,9 @@ class Mechanical(object):
1204
1211
  if progress_bar:
1205
1212
  if not _HAS_TQDM: # pragma: no cover
1206
1213
  raise ModuleNotFoundError(
1207
- f"To use the keyword argument 'progress_bar', you must have "
1208
- f"installed the 'tqdm' package. To avoid this message, you can "
1209
- f"set 'progress_bar=False'."
1214
+ "To use the keyword argument 'progress_bar', you must have "
1215
+ "installed the 'tqdm' package. To avoid this message, you can "
1216
+ "set 'progress_bar=False'."
1210
1217
  )
1211
1218
 
1212
1219
  n_bytes = os.path.getsize(file_name)
@@ -1951,11 +1958,12 @@ def launch_rpyc(
1951
1958
  additional_switches=None,
1952
1959
  additional_envs=None,
1953
1960
  verbose=False,
1954
- ) -> int:
1961
+ ) -> typing.Tuple[int, subprocess.Popen]:
1955
1962
  """Start Mechanical locally in RPyC mode."""
1956
1963
  _version = atp.version_from_path("mechanical", exec_file)
1957
- if _version < 232:
1958
- raise VersionError("The Mechanical gRPC interface requires Mechanical 2023 R2 or later.")
1964
+
1965
+ if not batch:
1966
+ raise Exception("The rpyc backend does not support graphical mode!")
1959
1967
 
1960
1968
  # get the next available port
1961
1969
  local_ports = pymechanical.LOCAL_PORTS
@@ -1969,21 +1977,21 @@ def launch_rpyc(
1969
1977
  port += 1
1970
1978
  local_ports.append(port)
1971
1979
 
1980
+ # TODO - use multiprocessing
1972
1981
  server_script = """
1973
1982
  import sys
1974
1983
  from ansys.mechanical.core.embedding.rpc import MechanicalDefaultServer
1975
1984
  server = MechanicalDefaultServer(port=int(sys.argv[1]), version=int(sys.argv[2]))
1976
1985
  server.start()
1977
1986
  """
1978
- env_copy = os.environ.copy()
1979
1987
  try:
1980
1988
  embedded_server = subprocess.Popen(
1981
- [sys.executable, "-c", server_script, str(port), str(_version)], env=env_copy
1989
+ [sys.executable, "-c", server_script, str(port), str(_version)]
1982
1990
  ) # nosec: B603
1983
1991
  except:
1984
1992
  raise RuntimeError("Unable to start the embedded server.")
1985
1993
 
1986
- return port
1994
+ return port, embedded_server
1987
1995
 
1988
1996
 
1989
1997
  def launch_remote_mechanical(
@@ -2306,11 +2314,15 @@ def launch_mechanical(
2306
2314
  # pass
2307
2315
  raise exception
2308
2316
  elif backend == "python":
2309
- port = launch_rpyc(port=port, **start_parm)
2317
+ port, process = launch_rpyc(port=port, **start_parm)
2310
2318
  from ansys.mechanical.core.embedding.rpc.client import Client
2311
2319
 
2312
2320
  mechanical = Client(
2313
- "localhost", port, timeout=start_timeout, cleanup_on_exit=cleanup_on_exit
2321
+ "localhost",
2322
+ port,
2323
+ timeout=start_timeout,
2324
+ cleanup_on_exit=cleanup_on_exit,
2325
+ process=process,
2314
2326
  )
2315
2327
 
2316
2328
  return mechanical
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansys-mechanical-core
3
- Version: 0.11.14
3
+ Version: 0.11.16
4
4
  Summary: A python wrapper for Ansys Mechanical
5
5
  Keywords: pymechanical,mechanical,ansys,pyansys
6
6
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
@@ -18,7 +18,7 @@ Classifier: License :: OSI Approved :: MIT License
18
18
  Classifier: Operating System :: OS Independent
19
19
  License-File: LICENSE
20
20
  Requires-Dist: ansys-api-mechanical==0.1.2
21
- Requires-Dist: ansys-mechanical-env==0.1.9
21
+ Requires-Dist: ansys-mechanical-env==0.1.12
22
22
  Requires-Dist: ansys-mechanical-stubs==0.1.6
23
23
  Requires-Dist: ansys-pythonnet>=3.1.0rc6
24
24
  Requires-Dist: ansys-tools-path>=0.3.1
@@ -30,19 +30,19 @@ Requires-Dist: protobuf>=3.12.2,<6
30
30
  Requires-Dist: psutil>=6
31
31
  Requires-Dist: tqdm>=4.45.0
32
32
  Requires-Dist: requests>=2,<3
33
- Requires-Dist: sphinx==8.2.1 ; extra == "doc"
34
- Requires-Dist: ansys-sphinx-theme[autoapi, changelog]==1.3.2 ; extra == "doc"
33
+ Requires-Dist: sphinx==8.2.3 ; extra == "doc"
34
+ Requires-Dist: ansys-sphinx-theme[autoapi, changelog]==1.4.2 ; extra == "doc"
35
35
  Requires-Dist: grpcio==1.70.0 ; extra == "doc"
36
36
  Requires-Dist: imageio-ffmpeg==0.6.0 ; extra == "doc"
37
37
  Requires-Dist: imageio==2.37.0 ; extra == "doc"
38
38
  Requires-Dist: jupyter_sphinx==0.5.3 ; extra == "doc"
39
39
  Requires-Dist: jupyterlab>=3.2.8 ; extra == "doc"
40
- Requires-Dist: matplotlib==3.10.0 ; extra == "doc"
41
- Requires-Dist: numpy==2.2.3 ; extra == "doc"
40
+ Requires-Dist: matplotlib==3.10.1 ; extra == "doc"
41
+ Requires-Dist: numpy==2.2.5 ; extra == "doc"
42
42
  Requires-Dist: numpydoc==1.8.0 ; extra == "doc"
43
43
  Requires-Dist: pandas==2.2.3 ; extra == "doc"
44
44
  Requires-Dist: panel==1.6.1 ; extra == "doc"
45
- Requires-Dist: plotly==6.0.0 ; extra == "doc"
45
+ Requires-Dist: plotly==6.0.1 ; extra == "doc"
46
46
  Requires-Dist: pypandoc==1.15 ; extra == "doc"
47
47
  Requires-Dist: pytest-sphinx==0.6.3 ; extra == "doc"
48
48
  Requires-Dist: pythreejs==2.4.2 ; extra == "doc"
@@ -55,21 +55,24 @@ Requires-Dist: sphinx-gallery==0.19.0 ; extra == "doc"
55
55
  Requires-Dist: sphinx-notfound-page==1.1.0 ; extra == "doc"
56
56
  Requires-Dist: sphinxcontrib-websupport==2.0.0 ; extra == "doc"
57
57
  Requires-Dist: sphinxemoji==0.3.1 ; extra == "doc"
58
+ Requires-Dist: ansys-tools-visualization-interface>=0.2.6 ; extra == "graphics"
59
+ Requires-Dist: usd-core==25.5 ; extra == "graphics"
58
60
  Requires-Dist: ansys-platform-instancemanagement>=1.0.1 ; extra == "pim"
59
- Requires-Dist: rpyc==6.0.1 ; extra == "rpc"
61
+ Requires-Dist: rpyc==6.0.2 ; extra == "rpc"
60
62
  Requires-Dist: toolz==1.0.0 ; extra == "rpc"
61
- Requires-Dist: pytest==8.3.4 ; extra == "tests"
62
- Requires-Dist: pytest-cov==6.0.0 ; extra == "tests"
63
- Requires-Dist: pytest-print==1.0.2 ; extra == "tests"
63
+ Requires-Dist: pytest==8.3.5 ; extra == "tests"
64
+ Requires-Dist: pytest-cov==6.1.1 ; extra == "tests"
65
+ Requires-Dist: pytest-print==1.1.0 ; extra == "tests"
64
66
  Requires-Dist: psutil==7.0.0 ; extra == "tests"
65
67
  Requires-Dist: ansys-tools-visualization-interface>=0.2.6 ; extra == "viz"
66
- Requires-Dist: usd-core==24.11 ; extra == "viz"
68
+ Requires-Dist: usd-core==25.5 ; extra == "viz"
67
69
  Project-URL: Changelog, https://mechanical.docs.pyansys.com/version/stable/changelog.html
68
70
  Project-URL: Documentation, https://mechanical.docs.pyansys.com
69
71
  Project-URL: Homepage, https://github.com/ansys/pymechanical
70
72
  Project-URL: Issues, https://github.com/ansys/pymechanical/issues
71
73
  Project-URL: Repository, https://github.com/ansys/pymechanical
72
74
  Provides-Extra: doc
75
+ Provides-Extra: graphics
73
76
  Provides-Extra: pim
74
77
  Provides-Extra: rpc
75
78
  Provides-Extra: tests