2020# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121# SOFTWARE.
2222
23- """Defines a wrapper for interacting with launched product instances."""
23+ """Provides a wrapper for interacting with launched product instances."""
2424
2525from __future__ import annotations
2626
3131import grpc
3232from typing_extensions import Self
3333
34+ from ansys .tools .common .exceptions import ProductInstanceError
35+
3436from .interface import LAUNCHER_CONFIG_T , LauncherProtocol , ServerType
3537
3638__all__ = ["ProductInstance" ]
@@ -42,7 +44,7 @@ class ProductInstance:
4244 """Provides a wrapper for interacting with the launched product instance.
4345
4446 This class allows stopping and starting of the product instance. It also
45- provides access to its server URLs/ channels.
47+ provides access to its server URLs and gRPC channels.
4648
4749 The :class:`ProductInstance` class can be used as a context manager, stopping
4850 the instance when exiting the context.
@@ -58,7 +60,7 @@ def __init__(self, *, launcher: LauncherProtocol[LAUNCHER_CONFIG_T]):
5860 def __enter__ (self ) -> ProductInstance :
5961 """Enter the context manager defined by the product instance."""
6062 if self .stopped :
61- raise RuntimeError ("The product instance is stopped. Cannot enter context." )
63+ raise ProductInstanceError ("The product instance is stopped. Cannot enter context." )
6264 return self
6365
6466 def __exit__ (self , * exc : Any ) -> None :
@@ -70,15 +72,13 @@ def start(self: Self) -> None:
7072
7173 Raises
7274 ------
73- RuntimeError
74- If the instance is already in the started state.
75- RuntimeError
76- If the URLs exposed by the started instance do not match
77- the expected ones defined in the launcher's
78- :attr:`.LauncherProtocol.SERVER_SPEC` attribute.
75+ ProductInstanceError
76+ If the instance is already started or the URLs do not match
77+ the launcher's SERVER_SPEC.
7978 """
8079 if not self .stopped :
81- raise RuntimeError ("Cannot start the server. It has already been started." )
80+ raise ProductInstanceError ("Cannot start the server. It has already been started." )
81+
8282 self ._finalizer = weakref .finalize (self , self ._launcher .stop , timeout = None )
8383 self ._launcher .start ()
8484 self ._channels = dict ()
@@ -92,11 +92,11 @@ def start(self: Self) -> None:
9292 )
9393 elif server_type == ServerType .GENERIC :
9494 if key not in urls :
95- raise RuntimeError (
95+ raise ProductInstanceError (
9696 f"The URL for the generic server with key '{ key } ' was not provided by the launcher."
9797 )
9898 else :
99- raise RuntimeError (f"Unsupported server type: { server_type } " )
99+ raise ProductInstanceError (f"Unsupported server type: { server_type } " )
100100
101101 def stop (self , * , timeout : float | None = None ) -> None :
102102 """Stop the product instance.
@@ -110,11 +110,11 @@ def stop(self, *, timeout: float | None = None) -> None:
110110
111111 Raises
112112 ------
113- RuntimeError
113+ ProductInstanceError
114114 If the instance is already in the stopped state.
115115 """
116116 if self .stopped :
117- raise RuntimeError ("Cannot stop the server. It has already been stopped." )
117+ raise ProductInstanceError ("Cannot stop the server. It has already been stopped." )
118118 self ._launcher .stop (timeout = timeout )
119119 self ._finalizer .detach ()
120120
@@ -130,12 +130,8 @@ def restart(self, stop_timeout: float | None = None) -> None:
130130
131131 Raises
132132 ------
133- RuntimeError
134- If the instance is already in the stopped state.
135- RuntimeError
136- If the URLs exposed by the started instance do not match
137- the expected ones defined in the launcher's
138- :attr:`.LauncherProtocol.SERVER_SPEC` attribute.
133+ ProductInstanceError
134+ If the instance is already stopped or URL keys mismatch.
139135 """
140136 self .stop (timeout = stop_timeout )
141137 self .start ()
@@ -165,7 +161,7 @@ def wait(self, timeout: float) -> None:
165161
166162 Raises
167163 ------
168- RuntimeError
164+ ProductInstanceError
169165 If the server still has not responded after ``timeout`` seconds.
170166 """
171167 start_time = time .time ()
@@ -177,11 +173,11 @@ def wait(self, timeout: float) -> None:
177173 # delay s.t. the server isn't bombarded with requests.
178174 time .sleep (timeout / 100 )
179175 else :
180- raise RuntimeError (f"The product is not running after { timeout } s." )
176+ raise ProductInstanceError (f"The product is not running after { timeout } s." )
181177
182178 @property
183179 def urls (self ) -> dict [str , str ]:
184- """URL and port for the servers of the product instance .
180+ """Read-only mapping of server keys to their URLs .
185181
186182 Only generic server types are listed, gRPC servers should be accessed
187183 via the :attr:`.channels` property.
@@ -200,5 +196,5 @@ def stopped(self) -> bool:
200196
201197 @property
202198 def channels (self ) -> dict [str , grpc .Channel ]:
203- """Channels to the gRPC servers of the product instance ."""
199+ """Read-only mapping of server keys to gRPC channels ."""
204200 return self ._channels
0 commit comments