Datatypes and Type Conversions ============================== SHC's *Connectable* objects are designed to work with simple ("scalar") Python types, basic structured types, specifically NamedTuples, and Enums. Basically, thanks to Python's dynamic nature, any Python type can be used as a value type by connectable objects. However, some of SHC's features work much better with simple types, e.g. the :ref:`dynamic type checking and automatic type conversions ` and the builtin :ref:`JSON serialization` (e.g. for the :ref:`REST API ` and :meth:`MQTT `). Examples for well supported Python builtin types and standard-library types: - :class:`bool` - :class:`int` - :class:`float` - :class:`str` - :class:`datetime.datetime` - :class:`datetime.date` - :class:`datetime.time` - :class:`datetime.timedelta` In addition, SHC specifies some derived types of these builtin types with addtional semantics (see next section) and some NamedTuples for commonly used and interface-specific data structures: - :class:`shc.datatypes.RGBUInt8` - :class:`shc.datatypes.RGBFloat1` - :class:`shc.datatypes.HSVFloat1` - :class:`shc.datatypes.RGBWUInt8` - :class:`shc.datatypes.CCTUInt8` - :class:`shc.datatypes.RGBCCTUInt8` - :class:`shc.interfaces.knx.KNXHVACMode` - :class:`shc.interfaces.knx.KNXUpDown` - :class:`shc.interfaces.knx.KNXControlDimming` - :class:`shc.interfaces.pulse.PulseVolumeRaw` - :class:`shc.interfaces.pulse.PulseVolumeComponents` .. _datatypes.semantic_derivation: Inherited semantic types in SHC ------------------------------- To make :ref:`type checking and automatic type conversions ` more useful, SHC makes use of type inheritance for semantic purposes. This is similar to how the "Newtype" paradigm is used in `Haskell `_ or `Rust `_: When a Connectable object's values have special additional semantics, a derived type is used instead of the plain scalar type to specify these semantics. This allows the type checking to check for mismatched value semantics of connected objects (even with the same scalar type) and to chose the correct type conversion automatically. A good example for this method are the different integer types for 0-100% ranges provided by SHC: * :class:`RangeUInt8 ` is derived from `int` and its instances shall be values from 0 (0%) to 255 (100%) * :class:`RangeInt0To100 ` is derived from `int` and its instances shall be values from 0 (0%) to 100 (100%) Obviously, values of these two types are compatible on a syntactic level, but not on a semantic level. SHC provides default converters for converting both of these types into plain :class:`int`, as well as default converters to convert them to :class:`RangeFloat1` and into each other (with the appropriate scaling). List of New Types included with SHC: - :class:`shc.datatypes.RangeFloat1` - :class:`shc.datatypes.RangeUInt8` - :class:`shc.datatypes.RangeInt0To100` - :class:`shc.datatypes.AngleUInt8` - :class:`shc.datatypes.Balance` - :class:`shc.datatypes.FadeStep` .. _datatypes.default_converters: Default converters ------------------ SHC maintains a global dict of default conversion functions for pairs of types to convert values from the one type into the other type. These default converters are used by :meth:`.subscribe() `, :meth:`.set_provider() ` and :meth:`.connect() `, when `convert=True` is given. See :ref:`base.typing` for more information. To retrieve a default converter from that global dict, use :func:`shc.conversion.get_converter`. Reasonable default converters for the scalar builtin Python types and the additional New Types and NamedTuples provided by SHC are already included with SHC. To add additional default converters, e.g. for custom types to be used with SHC, use :func:`shc.conversion.register_converter`. .. _datatypes.json: JSON conversion --------------- Different modules of SHC require to serialize values into JSON data or deserialize them back into objects of the respective value type. Similar to the default converters, the :mod:`shc.conversion` module provides a global uniform and extensible way to do this: - For encoding, the :class:`shc.conversion.SHCJsonEncoder` class can be used as an `encoderclass` with Python's builtin JSON module:: serialized_value = json.dumps(value, cls=shc.conversion.SHCJsonEncoder) This also allows to convert lists, dicts, etc. of supported values to the respective JSON representation. - For decoding, use the usual JSON deserialization methods and afterwards apply :func:`shc.conversion.from_json` to the resulting object to convert it to the expected value type, e.g.:: value = shc.conversion.from_json(json.loads(serialized_value), shc.datatypes.RangeFloat1) The two converters natively support simple builtin types, Enums and NamedTuples by default, as well as any derived types from these (e.g. for :ref:`semantic derived types `). To add support for further types, :func:`shc.conversion.register_json_conversion` can be used to register the required converter functions. ``shc.datatypes`` Module Reference ---------------------------------- .. automodule:: shc.datatypes :members: :exclude-members: RGBUInt8, RGBFloat1, HSVFloat1, RGBWUInt8, CCTUInt8, RGBCCTUInt8 :member-order: bysource .. autonamedtuple:: RGBUInt8 .. autonamedtuple:: RGBFloat1 .. autonamedtuple:: HSVFloat1 .. autonamedtuple:: RGBWUInt8 .. autonamedtuple:: CCTUInt8 .. autonamedtuple:: RGBCCTUInt8 ``shc.conversion`` Module Reference ----------------------------------- .. py:module:: shc.conversion .. autofunction:: register_converter .. autofunction:: get_converter .. autofunction:: register_json_conversion .. autoclass:: SHCJsonEncoder .. autofunction:: from_json