plesty.lib.device.funcs ======================= .. py:module:: plesty.lib.device.funcs .. autoapi-nested-parse:: Function system for registering and dispatching device operations. Attributes ---------- .. autoapisummary:: plesty.lib.device.funcs._FUNC_META_DTYPE_MAP plesty.lib.device.funcs._DOC_ARG_SECTIONS plesty.lib.device.funcs._DOC_RETURN_SECTIONS plesty.lib.device.funcs._KNOWN_DOC_SECTIONS plesty.lib.device.funcs._DOC_SECTION_RE plesty.lib.device.funcs._DOC_ARG_RE plesty.lib.device.funcs._PARAMS_REPR plesty.lib.device.funcs._FRAMEWORK_DOC_MODULES plesty.lib.device.funcs._STANDARD_METHOD_NAMES Classes ------- .. autoapisummary:: plesty.lib.device.funcs.FuncMeta plesty.lib.device.funcs.FuncParam plesty.lib.device.funcs.FuncOutput plesty.lib.device.funcs.FuncDoc plesty.lib.device.funcs.FunctionSystem Functions --------- .. autoapisummary:: plesty.lib.device.funcs._parse_google_docstring plesty.lib.device.funcs._parse_arg_lines plesty.lib.device.funcs._first_paragraph plesty.lib.device.funcs._compact_repr Module Contents --------------- .. py:data:: _FUNC_META_DTYPE_MAP :type: dict[str, type] .. py:data:: _DOC_ARG_SECTIONS :value: ('args', 'arguments', 'parameters') .. py:data:: _DOC_RETURN_SECTIONS :value: ('returns', 'return', 'yields') .. py:data:: _KNOWN_DOC_SECTIONS .. py:data:: _DOC_SECTION_RE .. py:data:: _DOC_ARG_RE .. py:function:: _parse_google_docstring(docstring: str) -> tuple[dict[str, str], str] Parse a Google-style docstring into per-argument and return descriptions. :param docstring: A normalized (dedented) docstring. :returns: A ``({argument_name: description}, return_description)`` tuple. Both are empty when the docstring has no ``Args``/``Returns`` sections. .. py:function:: _parse_arg_lines(lines: list[str]) -> dict[str, str] Parse the body lines of a Google ``Args:`` section into ``{name: desc}``. .. py:function:: _first_paragraph(lines: list[str]) -> str Return the first non-empty paragraph of a docstring section, collapsed. .. py:class:: FuncMeta Link a PLESTY operation to its device-protocol command. ``FuncMeta`` carries the minimum information needed for a generic solver (e.g. :class:`~plesty.lib.solver.scpi.SCPISolver`) to dispatch a single-command, single-scalar-output operation without any hand-written dispatch logic. It is built automatically from a ``"command"`` field in ``schema_func.json`` and injected into the request dictionary by the :class:`FunctionSystem`. Complex operations that require multi-step exchanges or custom response parsing should omit ``"command"`` from their schema entry and implement the logic inside a custom :class:`~plesty.lib.solver.OpSolver`. :ivar name: Operation name as registered in the function schema. :ivar command: Raw device command string to send (e.g. ``"MEAS:POW?"``). :ivar output_key: Key under which the parsed value is returned in the response dictionary (e.g. ``"power"``). :ivar output_dtype: Python type used to cast the raw string response. Defaults to :class:`float` for scalar measurement operations. .. py:attribute:: name :type: str .. py:attribute:: command :type: str .. py:attribute:: output_key :type: str .. py:attribute:: output_dtype :type: type .. py:class:: FuncParam Data class to hold function argument metadata. .. py:attribute:: name :type: str .. py:attribute:: dtype :type: Any .. py:attribute:: unit :type: str :value: '' .. py:attribute:: default :type: Any :value: None .. py:attribute:: required :type: bool :value: True .. py:attribute:: options :type: list[Any] | None :value: None .. py:attribute:: range :type: tuple[Any, Any] | None :value: None .. py:attribute:: shape :type: tuple[Any, Ellipsis] | None :value: None .. py:attribute:: item_dtype :type: Any :value: None .. py:attribute:: description :type: str :value: '' .. py:class:: FuncOutput Data class to hold function output metadata. .. py:attribute:: name :type: str .. py:attribute:: dtype :type: Any .. py:attribute:: unit :type: str :value: '' .. py:attribute:: required :type: bool :value: True .. py:attribute:: code_mapping :type: dict[Any, str] | None :value: None .. py:attribute:: range :type: tuple[Any, Any] | None :value: None .. py:attribute:: shape :type: tuple[Any, Ellipsis] | None :value: None .. py:attribute:: item_dtype :type: Any :value: None .. py:attribute:: headers :type: list[plesty.lib.data.TableHeader] | None :value: None .. py:attribute:: description :type: str :value: '' .. py:class:: FuncDoc One documented operation, regardless of how it is implemented. Unifies schema-registered operations and ``@expose_to_api`` custom methods into a single shape so documentation renders them identically. :ivar name: Operation / method name. :ivar source: ``"schema"`` for a registered operation, ``"custom"`` for an ``@expose_to_api`` (or public child) method. :ivar description: Human-readable description (from the schema or docstring). :ivar iparams: Input parameters. :ivar oparams: Output values. :ivar kind: What the operation does to the world (see :class:`~plesty.lib.device.device_utils.OpKind`); ``read`` when the module declared nothing. .. py:attribute:: name :type: str .. py:attribute:: source :type: str .. py:attribute:: description :type: str .. py:attribute:: iparams :type: list[FuncParam] .. py:attribute:: oparams :type: list[FuncOutput] .. py:attribute:: kind :type: plesty.lib.device.device_utils.OpKind .. py:data:: _PARAMS_REPR .. py:data:: _FRAMEWORK_DOC_MODULES .. py:data:: _STANDARD_METHOD_NAMES :value: ('connect', 'disconnect', 'identity', 'check_errors', 'check_operatability', 'write', 'query',... .. py:function:: _compact_repr(value: Any) -> str Return a size-bounded repr of *value* for log lines. .. py:class:: FunctionSystem(op_schema=None, solver: Callable[[dict[str, Any]], dict[str, Any]] | None = None) Dynamic operation-to-function adapter for TCP message-based APIs. This class allows developers to register operations as Python callables, where: - ``iparams`` is a list of ``FuncParam`` objects describing input schema. - ``oparams`` is a list of ``FuncOutput`` objects describing output schema. - the runtime request format is ``{'op': , 'parameters': }``. Registered functions can be called with a parameter dictionary, keyword arguments, or positional arguments (mapped by ``iparams`` order). Each call returns a response dictionary from the configured executor. Initialize the function system. :param op_schema: Optional operation schema (path or dict) to register. :param solver: Callable used to send a message dictionary and return a response dictionary. .. py:attribute:: _functions :type: dict[str, Any] .. py:attribute:: _op_solver :value: None .. py:method:: bind_op_solver(solver: Callable[[dict[str, Any]], dict[str, Any]]) -> None Bind or replace the callable used to execute operation requests. :param solver: Callable receiving request dictionary and returning response dictionary. .. py:method:: bind_op_response_parser(op_name: str, parser: plesty.lib.device.device_utils.ResponseParser) -> None Bind a response parser to a registered operation. :param op_name: Name of the registered operation. :param parser: ResponseParser instance to apply to the operation's raw response. .. py:method:: register_func(func_name: str, iparams: list[FuncParam] | None = None, oparams: list[FuncOutput] | None = None, resp_parser: plesty.lib.device.device_utils.ResponseParser | None = None, func_meta: FuncMeta | None = None, **kwargs) -> None Register an operation as a callable function on this instance. :param func_name: Operation name and exported function name. :param iparams: Input schema as ``[FuncParam(...), ...]``. :param oparams: Output schema as ``[FuncOutput(...), ...]``. :param resp_parser: Optional parser applied to executor response. :param func_meta: Optional :class:`FuncMeta` built from a ``"command"`` field in the schema. When present it is injected into the request dictionary so that a generic solver can dispatch the operation without hand-written dispatch logic. :param kwargs: Registration options for future extension. These options are stored as metadata and are not sent in runtime requests. ``description`` is read back by :meth:`function_docs`, so an operation registered by hand documents itself the same way a schema-registered one does. .. py:method:: _parse_iparams_from_schema(iparams_schema: Any) -> list[FuncParam] Parse operation input schema into FuncParam objects. .. py:method:: _parse_oparams_from_schema(oparams_schema: Any) -> list[FuncOutput] Parse operation output schema into FuncOutput objects. .. py:method:: function_docs() -> list[FuncDoc] Return the device's callable operations as a unified :class:`FuncDoc` list. Combines schema-registered operations (``source="schema"``) with the device's own ``@expose_to_api`` methods (``source="custom"``). Framework plumbing declared on the plesty base classes (``connect``, ``write``, ``query``, ``identity``, ...) is excluded — this is the device's API surface, not the framework's. Registered operations come first. :returns: One :class:`FuncDoc` per documented operation. .. py:method:: standard_method_docs() -> list[FuncDoc] Return the common device API (``connect``, ``write``, ``query``, ...). These framework methods are shared by every device and are documented as their own "standard methods" section, separate from the device's own operations (:meth:`function_docs`). :returns: One :class:`FuncDoc` (``source="standard"``) per available standard method, in a stable order. .. py:method:: _method_doc(name: str, func: Any, source: str) -> FuncDoc Build a :class:`FuncDoc` for a plain method from its signature/docstring. .. py:method:: register_from_op_schema(schema_path: str, resp_parsers: dict[str, plesty.lib.device.device_utils.ResponseParser] | None = None, **registration_options) -> list[str] Register multiple operations from a JSON schema file. Expected schema format: .. code-block:: json { "operation_name": { "iparams": {"arg_name": {"type": "float"}}, "oparams": {"out_name": {"type": "str"}} } } :param schema_path: Path to JSON schema file. :param resp_parsers: Optional map {operation_name: ResponseParser}. :param \*\*registration_options: Additional options forwarded to register_func. :returns: Names of registered operations. :rtype: list[str] .. py:method:: _parse_func_meta(op_name: str, op_cfg: dict, oparams: list[FuncOutput]) -> FuncMeta | None :staticmethod: Build a :class:`FuncMeta` from a schema operation entry, or ``None``. Returns ``None`` when no ``"command"`` key is present, indicating the operation requires custom solver logic. .. py:method:: _normalize_iparams(iparams: list[Any]) -> list[FuncParam] Normalize input schema into ``FuncParam`` objects. .. py:method:: _normalize_oparams(oparams: list[Any]) -> list[FuncOutput] Normalize output schema into ``FuncOutput`` objects. .. py:method:: _type_name(dtype: Any) -> str :staticmethod: Return a human-readable type name. .. py:method:: _annotation_name(annotation: Any) -> str :staticmethod: Return a stable name for a function annotation. .. py:method:: _callable_description(func: Any) -> str :staticmethod: Return a normalized docstring for a callable when available. .. py:method:: _resolved_signature(func: Any) -> inspect.Signature :staticmethod: Resolve a callable signature with evaluated type hints when possible. .. py:method:: _signature_output_docs(signature: inspect.Signature, default_type: str | None = None) -> list[dict[str, Any]] Build summary output metadata from a function return annotation. .. py:method:: _output_signature(op_doc: dict[str, Any]) -> str :staticmethod: Render operation outputs for a one-line function signature. .. py:method:: _collect_child_public_methods(existing_names: set[str]) -> dict[str, dict[str, Any]] Collect public methods defined on child classes and not registered as operations. .. py:method:: _collect_exposed_api_methods(existing_names: set[str]) -> dict[str, dict[str, Any]] Collect methods marked with expose_to_api and not already documented. .. py:method:: _is_plesty_array_dtype(dtype: Any) -> bool :staticmethod: .. py:method:: _is_plesty_table2d_dtype(dtype: Any) -> bool :staticmethod: .. py:method:: _parse_table_headers(headers_cfg: Any) -> list[plesty.lib.data.TableHeader] | None .. py:method:: _cast_plesty_array(value: Any) -> plesty.lib.data.PlestyArray .. py:method:: _cast_table_value(value: Any, dtype: Any) .. py:method:: _cast_plesty_table2d(value: Any, output_meta: FuncOutput) -> plesty.lib.data.PlestyTable2D .. py:method:: _build_operation_doc(func_name, iparams, oparams, resp_parser) -> str Build detailed user-facing documentation text for a registered operation. .. py:method:: func_summary(style: str = 'short', include_title: bool = True, filename=None) -> str | dict[str, dict[str, Any]] Summarize all registered operations. :param style: One of ``short``, ``md``, ``dict``, or ``google``. :param include_title: Whether to include a title header in the output. :param filename: Optional path to save the summary text. :returns: Operation documentation. :rtype: str | dict[str, dict[str, Any]] .. rubric:: Notes The summary is built from registration metadata and can be used as user-facing documentation for available operations. .. py:method:: _normalize_args(func_name: str, iparams: list[FuncParam], args, kwargs) -> dict[str, Any] Normalize incoming call arguments into a single parameters dictionary. Accepts one dictionary positional argument, keyword arguments, or positional arguments mapped by ``iparams`` order. .. py:method:: _validate_input(func_name: str, iparams: list[FuncParam], params: dict[str, Any]) -> dict[str, Any] Validate and cast input values based on registered ``iparams`` schema. :raises KeyError: If unexpected keys are provided. :raises ValueError: If type casting fails. .. py:method:: _validate_output(func_name: str, oparams: list[FuncOutput], response: dict[str, Any]) -> dict[str, Any] Validate and cast response fields against registered ``oparams`` schema. :raises KeyError: If expected response keys are missing. :raises ValueError: If type casting fails. .. py:method:: _create_func(func_name, iparams, oparams) Create the executable operation function for a registered operation.