ansys-speos-core 0.6.3__tar.gz → 0.7.1__tar.gz

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 (46) hide show
  1. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/LICENSE +1 -1
  2. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/PKG-INFO +17 -20
  3. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/README.rst +3 -3
  4. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/pyproject.toml +18 -17
  5. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/__init__.py +1 -1
  6. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/body.py +1 -1
  7. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/bsdf.py +5 -5
  8. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/face.py +1 -1
  9. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/generic/constants.py +1 -1
  10. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/generic/general_methods.py +4 -8
  11. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/generic/visualization_methods.py +1 -1
  12. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/geo_ref.py +1 -1
  13. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/intensity.py +1 -1
  14. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/__init__.py +1 -1
  15. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/body.py +3 -2
  16. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/client.py +81 -31
  17. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/crud.py +1 -1
  18. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/face.py +4 -4
  19. ansys_speos_core-0.7.1/src/ansys/speos/core/kernel/grpc/transport_options.py +171 -0
  20. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/intensity_template.py +4 -3
  21. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/job.py +40 -3
  22. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/part.py +3 -2
  23. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/proto_message_utils.py +1 -1
  24. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/scene.py +4 -3
  25. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/sensor_template.py +4 -3
  26. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/simulation_template.py +4 -3
  27. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/sop_template.py +4 -3
  28. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/source_template.py +3 -2
  29. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/spectrum.py +4 -3
  30. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/kernel/vop_template.py +4 -3
  31. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/launcher.py +44 -12
  32. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/logger.py +1 -1
  33. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/lxp.py +2 -1
  34. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/opt_prop.py +1 -1
  35. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/part.py +1 -1
  36. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/project.py +41 -14
  37. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/proto_message_utils.py +1 -1
  38. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/sensor.py +2 -2
  39. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/simulation.py +1395 -127
  40. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/source.py +2 -2
  41. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/spectrum.py +1 -1
  42. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/speos.py +29 -20
  43. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/workflow/__init__.py +1 -1
  44. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/workflow/combine_speos.py +1 -1
  45. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/workflow/open_result.py +1 -1
  46. {ansys_speos_core-0.6.3 → ansys_speos_core-0.7.1}/src/ansys/speos/core/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
3
+ Copyright (c) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansys-speos-core
3
- Version: 0.6.3
3
+ Version: 0.7.1
4
4
  Summary: A Python wrapper for Ansys Speos
5
5
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
6
6
  Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
@@ -21,28 +21,25 @@ Classifier: Topic :: Scientific/Engineering :: Physics
21
21
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
22
22
  License-File: LICENSE
23
23
  Requires-Dist: protobuf>=3.20,<7
24
- Requires-Dist: grpcio>=1.50.0,<1.75
24
+ Requires-Dist: grpcio>=1.50.0,<1.77
25
25
  Requires-Dist: grpcio-health-checking>=1.45.0,<1.68
26
26
  Requires-Dist: ansys-api-speos==0.15.3
27
- Requires-Dist: ansys-tools-path>=0.3.1
27
+ Requires-Dist: ansys-tools-common>=0.3.1
28
28
  Requires-Dist: numpy>=1.20.3,<3
29
29
  Requires-Dist: comtypes>=1.4,<1.5; platform_system=='Windows'
30
- Requires-Dist: ansys-sphinx-theme==1.6.0 ; extra == "doc"
31
- Requires-Dist: numpydoc==1.8.0 ; extra == "doc"
30
+ Requires-Dist: ansys-sphinx-theme[autoapi]==1.6.4 ; extra == "doc"
31
+ Requires-Dist: ansys-tools-visualization-interface>=0.8.3 ; extra == "doc"
32
+ Requires-Dist: numpydoc==1.10.0 ; extra == "doc"
32
33
  Requires-Dist: Sphinx==8.1.3 ; extra == "doc"
33
34
  Requires-Dist: sphinx-copybutton==0.5.2 ; extra == "doc"
34
- Requires-Dist: sphinx-autoapi==3.6.0 ; extra == "doc"
35
- Requires-Dist: sphinx_design==0.6.1 ; extra == "doc"
36
- Requires-Dist: sphinx-jinja==2.0.2 ; extra == "doc"
37
- Requires-Dist: sphinxcontrib-mermaid==1.0.0 ; extra == "doc"
35
+ Requires-Dist: sphinxcontrib-mermaid==1.2.3 ; extra == "doc"
38
36
  Requires-Dist: myst-parser==4.0.1 ; extra == "doc"
39
- Requires-Dist: nbsphinx==0.9.7 ; extra == "doc"
40
- Requires-Dist: jupytext==1.17.3 ; extra == "doc"
41
- Requires-Dist: jupyterlab==4.4.7 ; extra == "doc"
37
+ Requires-Dist: nbsphinx==0.9.8 ; extra == "doc"
38
+ Requires-Dist: jupytext==1.18.1 ; extra == "doc"
39
+ Requires-Dist: jupyterlab==4.5.1 ; extra == "doc"
42
40
  Requires-Dist: jupyter-server==2.17.0 ; extra == "doc"
43
41
  Requires-Dist: nbconvert==7.16.6 ; extra == "doc"
44
42
  Requires-Dist: pyvista[jupyter]>=0.43,<0.47 ; extra == "doc"
45
- Requires-Dist: ansys-tools-visualization-interface>=0.8.3 ; extra == "doc"
46
43
  Requires-Dist: pyvista>=0.40.0,<0.47 ; extra == "graphics"
47
44
  Requires-Dist: ansys-tools-visualization-interface>=0.8.3 ; extra == "graphics"
48
45
  Requires-Dist: matplotlib ; extra == "jupyter"
@@ -50,13 +47,13 @@ Requires-Dist: jupyterlab>=3 ; extra == "jupyter"
50
47
  Requires-Dist: ipywidgets ; extra == "jupyter"
51
48
  Requires-Dist: pyvista[jupyter]>=0.43,<0.47 ; extra == "jupyter"
52
49
  Requires-Dist: ansys-tools-visualization-interface>=0.8.3 ; extra == "jupyter"
53
- Requires-Dist: notebook==7.4.5 ; extra == "jupyter"
54
- Requires-Dist: psutil==7.0.0 ; extra == "tests"
55
- Requires-Dist: pytest==8.4.2 ; extra == "tests"
50
+ Requires-Dist: notebook==7.5.1 ; extra == "jupyter"
51
+ Requires-Dist: psutil==7.2.1 ; extra == "tests"
52
+ Requires-Dist: pytest==9.0.2 ; extra == "tests"
56
53
  Requires-Dist: pyvista>=0.40.0,<0.47 ; extra == "tests"
57
54
  Requires-Dist: ansys-tools-visualization-interface>=0.8.3 ; extra == "tests"
58
55
  Requires-Dist: ansys-platform-instancemanagement>=1.0.3 ; extra == "tests"
59
- Requires-Dist: pytest-cov==6.3.0 ; extra == "tests"
56
+ Requires-Dist: pytest-cov==7.0.0 ; extra == "tests"
60
57
  Project-URL: Changelog, https://github.com/ansys/pyspeos/blob/main/doc/source/changelog.rst
61
58
  Project-URL: Discussions, https://github.com/ansys/pyspeos/discussions
62
59
  Project-URL: Documentation, https://speos.docs.pyansys.com/
@@ -143,7 +140,7 @@ All sources are located in `<src/>`_ folder.
143
140
 
144
141
  from ansys.speos.core.speos import Speos
145
142
 
146
- speos = Speos(host="localhost", port=50098)
143
+ speos = Speos()
147
144
 
148
145
  Documentation and issues
149
146
  ------------------------
@@ -213,11 +210,11 @@ Then, to launch SpeosRPC server with product version 2025.1, you can run:
213
210
 
214
211
  cat GH_TOKEN.txt | docker login ghcr.io -u "$GH_USERNAME" --password-stdin
215
212
  docker pull ghcr.io/ansys/speos-rpc:252
216
- docker run --detach --name speos-rpc -p 127.0.0.1:50098:50098 -e ANSYSLMD_LICENSE_FILE=$LICENSE_SERVER --entrypoint /app/SpeosRPC_Server.x ghcr.io/ansys/speos-rpc:252 --host 0.0.0.0
213
+ docker run --detach --name speos-rpc -p 127.0.0.1:50098:50098 -e ANSYSLMD_LICENSE_FILE=$LICENSE_SERVER --entrypoint /app/SpeosRPC_Server.x ghcr.io/ansys/speos-rpc:252 --transport_insecure --host 0.0.0.0
217
214
 
218
215
  .. note::
219
216
 
220
- To use the latest image in development, you can use `ghcr.io/ansys/speos-rpc:252`.
217
+ To use the latest image in development, you can use `ghcr.io/ansys/speos-rpc:dev`.
221
218
 
222
219
  On the other hand, the SpeosRPC server can be started locally.
223
220
 
@@ -73,7 +73,7 @@ All sources are located in `<src/>`_ folder.
73
73
 
74
74
  from ansys.speos.core.speos import Speos
75
75
 
76
- speos = Speos(host="localhost", port=50098)
76
+ speos = Speos()
77
77
 
78
78
  Documentation and issues
79
79
  ------------------------
@@ -143,11 +143,11 @@ Then, to launch SpeosRPC server with product version 2025.1, you can run:
143
143
 
144
144
  cat GH_TOKEN.txt | docker login ghcr.io -u "$GH_USERNAME" --password-stdin
145
145
  docker pull ghcr.io/ansys/speos-rpc:252
146
- docker run --detach --name speos-rpc -p 127.0.0.1:50098:50098 -e ANSYSLMD_LICENSE_FILE=$LICENSE_SERVER --entrypoint /app/SpeosRPC_Server.x ghcr.io/ansys/speos-rpc:252 --host 0.0.0.0
146
+ docker run --detach --name speos-rpc -p 127.0.0.1:50098:50098 -e ANSYSLMD_LICENSE_FILE=$LICENSE_SERVER --entrypoint /app/SpeosRPC_Server.x ghcr.io/ansys/speos-rpc:252 --transport_insecure --host 0.0.0.0
147
147
 
148
148
  .. note::
149
149
 
150
- To use the latest image in development, you can use `ghcr.io/ansys/speos-rpc:252`.
150
+ To use the latest image in development, you can use `ghcr.io/ansys/speos-rpc:dev`.
151
151
 
152
152
  On the other hand, the SpeosRPC server can be started locally.
153
153
 
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
4
4
 
5
5
  [project]
6
6
  name = "ansys-speos-core"
7
- version = "0.6.3"
7
+ version = "0.7.1"
8
8
  description = "A Python wrapper for Ansys Speos"
9
9
  readme = "README.rst"
10
10
  requires-python = ">=3.10"
@@ -28,10 +28,10 @@ classifiers=[
28
28
  ]
29
29
  dependencies=[
30
30
  "protobuf>=3.20,<7",
31
- "grpcio>=1.50.0,<1.75",
31
+ "grpcio>=1.50.0,<1.77",
32
32
  "grpcio-health-checking>=1.45.0,<1.68",
33
33
  "ansys-api-speos==0.15.3",
34
- "ansys-tools-path>=0.3.1",
34
+ "ansys-tools-common>=0.3.1",
35
35
  "numpy>=1.20.3,<3",
36
36
  "comtypes>=1.4,<1.5; platform_system=='Windows'",
37
37
  ]
@@ -42,12 +42,12 @@ graphics = [
42
42
  "ansys-tools-visualization-interface>=0.8.3",
43
43
  ]
44
44
  tests = [
45
- "psutil==7.0.0",
46
- "pytest==8.4.2",
45
+ "psutil==7.2.1",
46
+ "pytest==9.0.2",
47
47
  "pyvista>=0.40.0,<0.47",
48
48
  "ansys-tools-visualization-interface>=0.8.3",
49
49
  "ansys-platform-instancemanagement>=1.0.3",
50
- "pytest-cov==6.3.0",
50
+ "pytest-cov==7.0.0",
51
51
  ]
52
52
  jupyter = [
53
53
  "matplotlib",
@@ -55,25 +55,22 @@ jupyter = [
55
55
  "ipywidgets",
56
56
  "pyvista[jupyter]>=0.43,<0.47",
57
57
  "ansys-tools-visualization-interface>=0.8.3",
58
- "notebook==7.4.5",
58
+ "notebook==7.5.1",
59
59
  ]
60
60
  doc = [
61
- "ansys-sphinx-theme==1.6.0",
62
- "numpydoc==1.8.0",
61
+ "ansys-sphinx-theme[autoapi]==1.6.4",
62
+ "ansys-tools-visualization-interface>=0.8.3",
63
+ "numpydoc==1.10.0",
63
64
  "Sphinx==8.1.3",
64
65
  "sphinx-copybutton==0.5.2",
65
- "sphinx-autoapi==3.6.0",
66
- "sphinx_design==0.6.1",
67
- "sphinx-jinja==2.0.2",
68
- "sphinxcontrib-mermaid==1.0.0",
66
+ "sphinxcontrib-mermaid==1.2.3",
69
67
  "myst-parser==4.0.1",
70
- "nbsphinx==0.9.7",
71
- "jupytext==1.17.3",
72
- "jupyterlab==4.4.7",
68
+ "nbsphinx==0.9.8",
69
+ "jupytext==1.18.1",
70
+ "jupyterlab==4.5.1",
73
71
  "jupyter-server==2.17.0",
74
72
  "nbconvert==7.16.6",
75
73
  "pyvista[jupyter]>=0.43,<0.47",
76
- "ansys-tools-visualization-interface>=0.8.3",
77
74
  ]
78
75
 
79
76
  [project.urls]
@@ -147,6 +144,10 @@ show_missing = true
147
144
  minversion = "7.1"
148
145
  addopts = "-vvv --color=yes -ra --durations=25 --cov=ansys.speos --cov-report html:.cov/html --cov-report xml:.cov/xml --cov-report term"
149
146
  testpaths = ["tests"]
147
+ markers = [
148
+ "all_speos_versions: Supported on all Speos versions.",
149
+ "supported_speos_versions(min, max): Feature only supported from minimal to maximal Speos versions."
150
+ ]
150
151
 
151
152
  [tool.mypy]
152
153
  python_version = "3.10"
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -30,16 +30,16 @@ from pathlib import Path
30
30
  from typing import Union
31
31
  import warnings
32
32
 
33
- from google.protobuf.empty_pb2 import Empty
34
- import grpc
35
- import numpy as np
36
-
37
33
  import ansys.api.speos.bsdf.v1.anisotropic_bsdf_pb2 as anisotropic_bsdf__v1__pb2
38
34
  import ansys.api.speos.bsdf.v1.anisotropic_bsdf_pb2_grpc as anisotropic_bsdf__v1__pb2_grpc
39
35
  import ansys.api.speos.bsdf.v1.bsdf_creation_pb2 as bsdf_creation__v1__pb2
40
36
  import ansys.api.speos.bsdf.v1.bsdf_creation_pb2_grpc as bsdf_creation__v1__pb2_grpc
41
37
  import ansys.api.speos.bsdf.v1.spectral_bsdf_pb2 as spectral_bsdf__v1__pb2
42
38
  import ansys.api.speos.bsdf.v1.spectral_bsdf_pb2_grpc as spectral_bsdf__v1__pb2_grpc
39
+ from google.protobuf.empty_pb2 import Empty
40
+ import grpc
41
+ import numpy as np
42
+
43
43
  import ansys.speos.core
44
44
  from ansys.speos.core.speos import Speos
45
45
 
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -34,10 +34,10 @@ from pathlib import Path
34
34
  from typing import List, Optional, Union, cast
35
35
  import warnings
36
36
 
37
+ from ansys.tools.common.path import get_available_ansys_installations
37
38
  import numpy as np
38
39
 
39
40
  from ansys.speos.core.generic.constants import DEFAULT_VERSION
40
- from ansys.tools.path import get_available_ansys_installations
41
41
 
42
42
  _GRAPHICS_AVAILABLE = None
43
43
 
@@ -90,9 +90,8 @@ def run_if_graphics_required(warning=False):
90
90
  global _GRAPHICS_AVAILABLE
91
91
  if _GRAPHICS_AVAILABLE is None:
92
92
  try:
93
- import pyvista as pv # noqa: F401
94
-
95
93
  from ansys.tools.visualization_interface import Plotter # noqa: F401
94
+ import pyvista as pv # noqa: F401
96
95
 
97
96
  _GRAPHICS_AVAILABLE = True
98
97
  except ImportError: # pragma: no cover
@@ -179,11 +178,8 @@ def error_no_install(install_path: Union[Path, str], version: Union[int, str]):
179
178
  version : Union[int, str]
180
179
  Version
181
180
  """
182
- install_loc_msg = ""
183
- if install_path:
184
- install_loc_msg = f"at {Path(install_path).parent}"
185
181
  raise FileNotFoundError(
186
- f"Ansys Speos RPC server installation not found{install_loc_msg}. "
182
+ f"Ansys Speos RPC server installation not found at {install_path}. "
187
183
  f"Please define AWP_ROOT{version} environment variable"
188
184
  )
189
185
 
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -28,6 +28,7 @@ from ansys.api.speos.part.v1 import (
28
28
  body_pb2 as messages,
29
29
  body_pb2_grpc as service,
30
30
  )
31
+
31
32
  from ansys.speos.core.kernel.crud import CrudItem, CrudStub
32
33
  from ansys.speos.core.kernel.proto_message_utils import protobuf_message_to_str
33
34
 
@@ -94,7 +95,7 @@ class BodyStub(CrudStub):
94
95
  Like in the following example:
95
96
 
96
97
  >>> from ansys.speos.core.speos import Speos
97
- >>> speos = Speos(host="localhost", port=50098)
98
+ >>> speos = Speos()
98
99
  >>> body_db = speos.client.bodies()
99
100
 
100
101
  """
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -25,14 +25,15 @@
25
25
  import logging
26
26
  import os
27
27
  from pathlib import Path
28
- import subprocess
28
+ import subprocess # nosec
29
+ import tempfile
29
30
  import time
30
31
  from typing import TYPE_CHECKING, List, Optional, Union
31
32
 
33
+ from ansys.api.speos.part.v1 import body_pb2, face_pb2, part_pb2
32
34
  import grpc
33
35
  from grpc._channel import _InactiveRpcError
34
36
 
35
- from ansys.api.speos.part.v1 import body_pb2, face_pb2, part_pb2
36
37
  from ansys.speos.core.generic.constants import (
37
38
  DEFAULT_HOST,
38
39
  DEFAULT_PORT,
@@ -42,6 +43,13 @@ from ansys.speos.core.generic.constants import (
42
43
  from ansys.speos.core.generic.general_methods import retrieve_speos_install_dir
43
44
  from ansys.speos.core.kernel.body import BodyLink, BodyStub
44
45
  from ansys.speos.core.kernel.face import FaceLink, FaceStub
46
+ from ansys.speos.core.kernel.grpc.transport_options import (
47
+ InsecureOptions,
48
+ TransportMode,
49
+ TransportOptions,
50
+ UDSOptions,
51
+ WNUAOptions,
52
+ )
45
53
  from ansys.speos.core.kernel.intensity_template import (
46
54
  IntensityTemplateLink,
47
55
  IntensityTemplateStub,
@@ -82,7 +90,7 @@ def wait_until_healthy(channel: grpc.Channel, timeout: float):
82
90
 
83
91
  Parameters
84
92
  ----------
85
- channel : ~grpc.Channel
93
+ channel : grpc.Channel
86
94
  Channel to wait until established and healthy.
87
95
  timeout : float
88
96
  Timeout in seconds. One attempt will be made each 100 milliseconds
@@ -107,24 +115,45 @@ def wait_until_healthy(channel: grpc.Channel, timeout: float):
107
115
  )
108
116
 
109
117
 
118
+ def default_docker_channel(
119
+ host: Optional[str] = DEFAULT_HOST,
120
+ port: Union[str, int] = DEFAULT_PORT,
121
+ message_size: int = MAX_CLIENT_MESSAGE_SIZE,
122
+ ) -> grpc.Channel:
123
+ """Create default transport options for docker on CI."""
124
+ return TransportOptions(
125
+ mode=TransportMode.INSECURE,
126
+ options=InsecureOptions(host=host, port=port, allow_remote_host=True),
127
+ ).create_channel(grpc_options=[("grpc.max_receive_message_length", message_size)])
128
+
129
+
130
+ def default_local_channel(
131
+ port: Union[str, int] = DEFAULT_PORT, message_size: int = MAX_CLIENT_MESSAGE_SIZE
132
+ ) -> grpc.Channel:
133
+ """Create default transport options, WNUA on Windows, UDS on Linux."""
134
+ if os.name == "nt":
135
+ transport = TransportOptions(
136
+ mode=TransportMode.WNUA, options=WNUAOptions(host=DEFAULT_HOST, port=port)
137
+ )
138
+ else:
139
+ sock_file = Path(tempfile.gettempdir()) / f"speosrpc_sock_{port}"
140
+ transport = TransportOptions(
141
+ mode=TransportMode.UDS, options=UDSOptions(uds_fullpath=str(sock_file))
142
+ )
143
+ return transport.create_channel(
144
+ grpc_options=[("grpc.max_receive_message_length", message_size)]
145
+ )
146
+
147
+
110
148
  class SpeosClient:
111
149
  """
112
150
  Wraps a speos gRPC connection.
113
151
 
114
152
  Parameters
115
153
  ----------
116
- host : str, optional
117
- Host where the server is running.
118
- By default, ``DEFAULT_HOST``.
119
- port : Union[str, int], optional
120
- Port number where the server is running.
121
- By default, ``DEFAULT_PORT``.
122
- channel : ~grpc.Channel, optional
154
+ channel : grpc.Channel, optional
123
155
  gRPC channel for server communication.
124
156
  By default, ``None``.
125
- message_size: int
126
- Maximum Message size of a newly generated channel
127
- By default, ``MAX_CLIENT_MESSAGE_SIZE``.
128
157
  remote_instance : ansys.platform.instancemanagement.Instance
129
158
  The corresponding remote instance when the Speos Service
130
159
  is launched through PyPIM. This instance will be deleted when calling
@@ -143,11 +172,8 @@ class SpeosClient:
143
172
 
144
173
  def __init__(
145
174
  self,
146
- host: Optional[str] = DEFAULT_HOST,
147
- port: Union[str, int] = DEFAULT_PORT,
148
175
  version: str = DEFAULT_VERSION,
149
176
  channel: Optional[grpc.Channel] = None,
150
- message_size: int = MAX_CLIENT_MESSAGE_SIZE,
151
177
  remote_instance: Optional["Instance"] = None,
152
178
  timeout: Optional[int] = 60,
153
179
  logging_level: Optional[int] = logging.INFO,
@@ -170,23 +196,17 @@ class SpeosClient:
170
196
  else:
171
197
  self._version = version
172
198
  if channel:
173
- # Used for PyPIM when directly providing a channel
199
+ # grpc channel is provided by caller, used by PyPIM or Docker server
174
200
  self._channel = channel
175
- self._target = str(channel)
176
201
  else:
177
- self._host = host
178
- self._port = port
179
- self._target = f"{host}:{port}"
180
- self._channel = grpc.insecure_channel(
181
- self._target,
182
- options=[("grpc.max_receive_message_length", message_size)],
183
- )
202
+ self._channel = default_local_channel()
203
+
184
204
  # do not finish initialization until channel is healthy
185
205
  wait_until_healthy(self._channel, timeout)
186
206
 
187
207
  # once connection with the client is established, create a logger
188
208
  self._log = LOGGER.add_instance_logger(
189
- name=self._target, client_instance=self, level=logging_level
209
+ name=self.target(), client_instance=self, level=logging_level
190
210
  )
191
211
  if logging_file:
192
212
  if isinstance(logging_file, Path):
@@ -492,7 +512,7 @@ List[ansys.speos.core.kernel.face.FaceLink]]
492
512
  """Represent the client as a string."""
493
513
  lines = []
494
514
  lines.append(f"Ansys Speos client ({hex(id(self))})")
495
- lines.append(f" Target: {self._target}")
515
+ lines.append(f" Target: {self.target()}")
496
516
  if self._closed:
497
517
  lines.append(" Connection: Closed")
498
518
  elif self.healthy:
@@ -504,6 +524,11 @@ List[ansys.speos.core.kernel.face.FaceLink]]
504
524
  def close(self):
505
525
  """Close the channel.
506
526
 
527
+ .. warning::
528
+
529
+ Do not execute this function with untrusted environment variables.
530
+ See the :ref:`security guide<ref_security_consideration>` for details.
531
+
507
532
  Returns
508
533
  -------
509
534
  bool
@@ -517,7 +542,7 @@ List[ansys.speos.core.kernel.face.FaceLink]]
517
542
  wait_time = 0
518
543
  if self._remote_instance:
519
544
  self._remote_instance.delete()
520
- elif self._host in ["localhost", "0.0.0.0", "127.0.0.1"] and self.__speos_exec:
545
+ elif self.__speos_exec:
521
546
  self.__close_local_speos_rpc_server()
522
547
  while self.healthy and wait_time < 15:
523
548
  time.sleep(1)
@@ -543,5 +568,30 @@ List[ansys.speos.core.kernel.face.FaceLink]]
543
568
  return self._closed
544
569
 
545
570
  def __close_local_speos_rpc_server(self):
546
- command = [self.__speos_exec, "-s{}".format(self._port)]
547
- subprocess.run(command, check=True)
571
+ """Close a locally started Speos RPC server.
572
+
573
+ .. warning::
574
+ Do not execute this function after modifying protected or private
575
+ attributes of the SpeosClient class or in a context with untrusted
576
+ environment variables.
577
+ See the :ref:`security guide<ref_security_consideration>` for details.
578
+
579
+ """
580
+ try:
581
+ # Extract port number at end of target string
582
+ target = self.target()
583
+ if ":" in target:
584
+ port = target.split(":")[-1]
585
+ else:
586
+ port = target.split("_")[-1]
587
+ int(port)
588
+ except ValueError:
589
+ raise RuntimeError("The port of the local server is not a valid integer.")
590
+ if (
591
+ not Path(self.__speos_exec).is_file()
592
+ or Path(self.__speos_exec).stem != "SpeosRPC_Server"
593
+ ):
594
+ raise RuntimeError("Unexpected executable path for Speos rpc executable.")
595
+
596
+ command = [self.__speos_exec, f"-s{port}"]
597
+ subprocess.run(command, check=True) # nosec
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2021 - 2026 ANSYS, Inc. and/or its affiliates.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -24,12 +24,12 @@
24
24
 
25
25
  from typing import Iterator, List
26
26
 
27
- from grpc import RpcError
28
-
29
27
  from ansys.api.speos.part.v1 import (
30
28
  face_pb2 as messages,
31
29
  face_pb2_grpc as service,
32
30
  )
31
+ from grpc import RpcError
32
+
33
33
  from ansys.speos.core.generic.general_methods import min_speos_version
34
34
  from ansys.speos.core.kernel.crud import CrudItem, CrudStub
35
35
  from ansys.speos.core.kernel.proto_message_utils import protobuf_message_to_str
@@ -97,7 +97,7 @@ class FaceStub(CrudStub):
97
97
  Like in the following example:
98
98
 
99
99
  >>> from ansys.speos.core.speos import Speos
100
- >>> speos = Speos(host="localhost", port=50098)
100
+ >>> speos = Speos()
101
101
  >>> face_db = speos.client.faces()
102
102
 
103
103
  """