- from dataclasses import dataclass
- from typing import TypedDict, List
- import numpy as np
- import grpc
- class resultNISTdetail(TypedDict):
- """
- Dictionary containing detailed results from NIST-STS returned within
- :class:`.resultNIST` generated by either
- :meth:`.UqrngClient.FetchHealthTest` or
- :meth:`.UqrngClient.HealthTest`.
-
- :param test_name: a list of names for randomness tests
- :param p_value: a list of p_values associated with the tests.
- :param proportion: a list of proportion of pass vs fail for test.
- :param passed: list of bools with passing tests indicated by True
- and failing tests returning False.
- :param elapsed_time_mins: returns time in fractional mins since
- last health check was completed.
- """
- test_name: List[str]
- p_value: List[float]
- proportion: List[float]
- passed: List[bool]
- elapsed_time_mins: float
- class resultNIST(TypedDict):
- """
- Dictionary containing results summary from NIST-STS generated by
- :meth:`.UqrngClient.FetchHealthTest` or
- :meth:`.UqrngClient.HealthTest`.
-
- :param all_pass: indicates whether all tests in health check
- passed if any test failed then returns False.
- :param tests_detail: detailed test results of form
- :class:`.resultNISTdetail`
- :param summary_table: a string formatted to print as a table which
- summarizes the randomness test detailed results.
- """
- all_pass: bool
- tests_detail: resultNISTdetail
- summary_table: str
- class SystemInfoDict(TypedDict):
- """
- Dictionary structure for :meth:`.client.UqrngClient.SystemInfo`
- :param device_name: the type of device
- :param server_version: the current semantic version for the
- device server
- :param test_interval_mins: current number of
- minutes between consecutive health test for server. For
- information on how this value is set see
- :meth:`.client.UqrngClient.ScheduleHealthTest`.
- """
- device_type: str
- server_version: str
- test_interval_mins: int
- @dataclass
- class SysStatus:
- """
- Status codes for system paired with their descriptions.
- """
- IDLE = {"status_code": 0, "status_desc": "IDLE"}
- SAMPLING = {"status_code": 1, "status_desc": "SAMPLING"}
- class StatusDict(TypedDict):
- """
- Status message
-
- :param status_code: integer code for response
- :param status_desc: description for status code
- """
- status_code: int
- status_desc: str
- def message_to_dict(grpc_message) -> dict:
- """Convert a gRPC message to a dictionary."""
- result = {}
- for descriptor in grpc_message.DESCRIPTOR.fields:
- field = getattr(grpc_message, descriptor.name)
- if descriptor.type == descriptor.TYPE_MESSAGE:
- if descriptor.label == descriptor.LABEL_REPEATED:
- if field:
- result[descriptor.name] = [message_to_dict(item) for item in field]
- else:
- result[descriptor.name] = []
- else:
- if field:
- result[descriptor.name] = message_to_dict(field)
- else:
- result[descriptor.name] = {}
- else:
- result[descriptor.name] = field
- return result
- def create_summary_table(detail_result: resultNISTdetail) -> str:
- column_names = ["STATISTICAL_TEST", "P-VALUE", "PROPORTION", "PASS"]
- prop_pass_print = np.round(detail_result["proportion_pass"], 6)
- pval_print = np.round(detail_result["p_value"],6)
- prop_col_width = max(len("PROPORTION"),max([len(str(num)) for num in prop_pass_print]))
- test_col_width = max(len("STATISTICAL TEST"),
- max([len(str(num)) for num in detail_result["test_name"]]))
- pval_col_width = max(len("P-VALUE"),max([len(str(num)) for num in pval_print]))
- pass_col_width = max(len("PASS"),max([len(str(num)) for num in detail_result["passed"]]))
- col_widths = [test_col_width, pval_col_width, prop_col_width, pass_col_width]
-
- for i in range(len(column_names)):
- header = " | ".join(f"{col:{col_widths[i]}}" for i, col in enumerate(column_names))
- str_table = header + "\n"
- str_table += ("-" * len(header)+"\n")
-
- for t_name, p_val, p_pass, pass_val in zip(detail_result["test_name"],
- pval_print,
- prop_pass_print,
- detail_result["passed"]):
- entry = " | ".join(f"{str(val):{col_widths[i]}}" for i, val in enumerate([t_name,
- p_val,
- p_pass,
- pass_val]))
- str_table += (entry+"\n")
- return str_table
- def check_qrng_busy_error(rpc_err: grpc.RpcError):
- """
- Utility function used in waiting loop to determine if error is from
- busy or another RPC error which can't be handled
-
- :param rpc_error: RpcError to check
- :return: bool whether error is from QRNG is in use
- """
- if rpc_err.code() == grpc.StatusCode.UNAVAILABLE:
- error_details = rpc_err.details()
- return True
- else:
- return False