Source code for zhinst.toolkit.nodetree.helper
"""Helper functions used in toolkit."""
import typing as t
from contextlib import contextmanager
from functools import lru_cache
from collections.abc import Mapping
# TypedDict is available in the typing module since 3.8
# Ift we only support 3.8 we should switch to t.TypedDict
from typing_extensions import TypedDict
if t.TYPE_CHECKING: # pragma: no cover
from zhinst.toolkit.nodetree.node import Node
T = t.TypeVar("T")
_NodeInfo = TypedDict(
"_NodeInfo",
{
"Node": str,
"Description": str,
"Properties": str,
"Type": str,
"Unit": str,
"Options": t.Dict[str, str],
},
)
NodeDoc = t.Dict[str, _NodeInfo]
[docs]def lazy_property(property_function: t.Callable[..., T]) -> property:
"""Alternative for functools.lazy_property.
functools.lazy_property is only available since python 3.8.
Should be replaced with functools.lazy_property once no version below
python 3.8 is supported.
Args:
property_function (Callable): property function
Returns
Return value of the property function
"""
return property(lru_cache()(property_function))
[docs]@contextmanager
def create_or_append_set_transaction(nodetree) -> t.Generator[None, None, None]:
"""Context manager for a transactional set.
In contrast to the set_transaction from the nodetree this function only
creates a new transaction if no other is in progress.
Should only be called withing the toolkit code.
Warning:
This function will silently fail if the existing transaction is exited
before this function finishes.
Warning:
The set is always performed as deep set if called on device nodes.
Examples:
>>> with nodetree.set_transaction():
nodetree.test[0].a(1)
with create_or_append_set_transaction(nodetree):
nodetree.test[1].a(2)
nodetree.test[2].a(2)
"""
if not nodetree.transaction.in_progress():
with nodetree.set_transaction():
yield
else:
yield
[docs]class NodeDict(Mapping):
"""Mapping of dictionary structure results.
The mapping allows to access data with both the string and the toolkit
node objects.
Args:
result: A dictionary of node/value pairs.
Example:
>>> result = device.demods["*"].enable()
>>> print(result)
{
'/dev1234/demods/0/enable': 0,
'/dev1234/demods/1/enable': 1,
}
>>> result[device.demods[0].enable]
0
>>> result["/dev1234/demods/0/enable"]
0
.. versionadded:: 0.3.5 Renamed from WildcardResult
"""
def __init__(self, result: t.Dict[str, t.Any]):
self._result = result
def __repr__(self):
return repr(self._result)
def __getitem__(self, key: t.Union[str, "Node"]):
return self._result[str(key)]
def __iter__(self):
return iter(self._result)
def __len__(self):
return len(self._result)
[docs] def to_dict(self) -> t.Dict[str, t.Any]:
"""Convert the WildcardResult to a dictionary.
After conversion, :class:`Node` objects cannot be used to get items.
"""
return self._result