Source code for qupulse.utils.types
import typing
import abc
import inspect
import numbers
import fractions
import warnings
import numpy
__all__ = ["MeasurementWindow", "ChannelID", "HashableNumpyArray", "TimeType", "time_from_float", "DocStringABCMeta",
"SingletonABCMeta"]
MeasurementWindow = typing.Tuple[str, numbers.Real, numbers.Real]
ChannelID = typing.Union[str, int]
try:
import gmpy2
TimeType = gmpy2.mpq
def time_from_float(time: float, absolute_error: float=1e-12) -> TimeType:
# gmpy2 is at least an order of magnitude faster than fractions.Fraction
return gmpy2.mpq(gmpy2.f2q(time, absolute_error))
except ImportError:
warnings.warn('gmpy2 not found. Using fractions.Fraction as fallback. Install gmpy2 for better performance.')
TimeType = fractions.Fraction
[docs] def time_from_float(time: float, absolute_error: float = 1e-12) -> TimeType:
return fractions.Fraction(time).limit_denominator(int(1/absolute_error))
[docs]class DocStringABCMeta(abc.ABCMeta):
"""Metaclass that copies/refers to docstrings of the super class."""
def __new__(mcls, classname, bases, cls_dict):
cls = super().__new__(mcls, classname, bases, cls_dict)
abstract_bases = tuple(base
for base in reversed(inspect.getmro(cls))
if hasattr(base, '__abstractmethods__'))[:-1]
for name, member in cls_dict.items():
if not getattr(member, '__doc__'):
if isinstance(member, property):
member_type = ':py:attr:'
else:
member_type = ':func:'
for base in abstract_bases:
if name in base.__dict__ and name in base.__abstractmethods__:
base_member = getattr(base, name)
if member is base_member or not base_member.__doc__:
continue
base_member_name = '.'.join([base.__module__, base.__qualname__, name])
member.__doc__ = 'Implements {}`~{}`.'.format(member_type, base_member_name)
break
return cls
T = typing.TypeVar('T')
[docs]class SingletonABCMeta(DocStringABCMeta):
"""Metaclass that enforces singletons"""
def __call__(cls: typing.Type[T]) -> T:
return cls._instance
def __init__(cls, name, bases, dct):
super().__init__(name, bases, dct)
cls._instance = super(SingletonABCMeta, cls).__call__()
[docs]class HashableNumpyArray(numpy.ndarray):
"""Make numpy arrays hashable.
Example usage:
my_array = np.zeros([1, 2, 3, 4])
hashable = my_array.view(HashableNumpyArray)
"""
def __hash__(self):
return hash(self.tobytes())