Source code for scrutiny.sdk.pending_request

#    pending_request.py
#        A base class for Future objects given to the suer
#
#   - License : MIT - See LICENSE file.
#   - Project :  Scrutiny Debugger (github.com/scrutinydebugger/scrutiny-python)
#
#   Copyright (c) 2021 Scrutiny Debugger

from scrutiny.tools import validation
from scrutiny import sdk
from datetime import datetime
import threading
import time

from typing import Optional, TYPE_CHECKING
if TYPE_CHECKING:
    from scrutiny.sdk.client import ScrutinyClient

[docs] class PendingRequest: _client: "ScrutinyClient" _success: bool # If the request has been successfully completed _completion_datetime: Optional[datetime] # datetime of the completion. None if incomplete _completed_event: threading.Event # Event that gets set upon completion of the request _failure_reason: str # Textual description of the reason of the failure to complete. Empty string if incomplete or succeeded _monotonic_creation_timestamp: float def __init__(self, client: "ScrutinyClient") -> None: self._client = client self._completed = False self._success = False self._completion_datetime = None self._completed_event = threading.Event() self._failure_reason = "" self._monotonic_creation_timestamp = time.monotonic() def _is_expired(self, timeout:float) -> bool: return time.monotonic() - self._monotonic_creation_timestamp > timeout def _mark_complete(self, success: bool, failure_reason: str = "", server_time_us: Optional[float] = None) -> None: # Put a request in "completed" state. Expected to be called by the client worker thread self._success = success self._failure_reason = failure_reason if server_time_us is None: self._completion_datetime = datetime.now() else: self._completion_datetime = self._client._server_timebase.micro_to_dt(server_time_us) self._completed = True self._completed_event.set() def _timeout_exception_msg(self, timeout:float) -> str: return f"Request did not complete in {timeout} seconds" def _failure_exception_msg(self) -> str: return f"Request failed to complete. {self._failure_reason}"
[docs] def wait_for_completion(self, timeout: Optional[float] = None) -> None: """Wait for the request to complete :params timeout: Maximum wait time in seconds. Waits forever if ``None`` :raise TimeoutException: If the request does not complete in less than the specified timeout value :raise OperationFailure: If an error happened that prevented the request to successfully complete """ timeout = validation.assert_float_range_if_not_none(timeout, 'timeout', minval=0) self._completed_event.wait(timeout=timeout) if not self._completed: assert timeout is not None raise sdk.exceptions.TimeoutException(self._timeout_exception_msg(timeout)) assert self._completed_event.is_set() if not self._success: raise sdk.exceptions.OperationFailure(self._failure_exception_msg())
@property def completed(self) -> bool: """Indicates whether the request has completed or not""" return self._completed_event.is_set() @property def is_success(self) -> bool: """Indicates whether the request has successfully completed or not""" return self._success @property def completion_datetime(self) -> Optional[datetime]: """The time at which the request has been completed. ``None`` if not completed yet""" return self._completion_datetime @property def failure_reason(self) -> str: """When the request failed, this property contains the reason for the failure. Empty string if not completed or succeeded""" return self._failure_reason