mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-27 05:37:21 -05:00
Surface gRPC failure context to Python script authors instead of silently returning sentinel values or raising bare gRPC errors. - RipsError now carries code/details/location and a from_rpc_error() helper. Existing single-arg construction stays valid. - Stop swallowing grpc.RpcError in case.__grid_count for non-NOT_FOUND failures and in instance._check_connection_and_version, so the underlying status is propagated. - pdmobject add_method decorator and _call_pdm_method_* attach code/details to the raised RipsError; existing message text is preserved so pytest match=... assertions keep working. - Instance.start_heartbeat / stop_heartbeat / check_alive provide an opt-in background ping that flips a sticky lost-connection flag and raises a readable RipsError from check_alive() if the server dies. - Server side: GetPdmObject in RiaGrpcAppService, RiaGrpcCaseService and RiaGrpcProjectService no longer return Status::OK with an empty reply when the underlying object is missing; they return NOT_FOUND / INTERNAL with a descriptive message. Other RiaGrpc*Service files audited and already return non-OK with text on error paths.
48 lines
1.4 KiB
Python
48 lines
1.4 KiB
Python
from typing import Optional
|
|
|
|
|
|
class RipsError(Exception):
|
|
"""Exception raised by the rips Python client.
|
|
|
|
Carries optional gRPC context so callers can branch on code/details
|
|
when a remote ResInsight call fails. Backwards compatible with the
|
|
legacy ``RipsError("message")`` form.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
message: object,
|
|
*,
|
|
code: Optional[object] = None,
|
|
details: Optional[str] = None,
|
|
location: Optional[str] = None,
|
|
) -> None:
|
|
super().__init__(message)
|
|
self.code = code
|
|
self.details = details
|
|
self.location = location
|
|
|
|
@classmethod
|
|
def from_rpc_error(
|
|
cls, rpc_error: Exception, location: Optional[str] = None
|
|
) -> "RipsError":
|
|
"""Build a RipsError from a grpc.RpcError-like object."""
|
|
code_fn = getattr(rpc_error, "code", None)
|
|
details_fn = getattr(rpc_error, "details", None)
|
|
code = code_fn() if callable(code_fn) else None
|
|
details = details_fn() if callable(details_fn) else ""
|
|
|
|
parts = ["ResInsight gRPC call failed"]
|
|
if code is not None:
|
|
parts.append(f"({code})")
|
|
if details:
|
|
parts.append(f"- {details}")
|
|
if location:
|
|
parts.append(f"[server={location}]")
|
|
return cls(
|
|
" ".join(parts),
|
|
code=code,
|
|
details=details or None,
|
|
location=location,
|
|
)
|