uim.model.base API documentation

# Module `uim.model.base`

Expand source code

    # -*- coding: utf-8 -*-
    # Copyright © 2021 Wacom Authors. All Rights Reserved.
    #
    #  Licensed under the Apache License, Version 2.0 (the "License");
    #  you may not use this file except in compliance with the License.
    #  You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    #  Unless required by applicable law or agreed to in writing, software
    #  distributed under the License is distributed on an "AS IS" BASIS,
    #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #  See the License for the specific language governing permissions and
    #  limitations under the License.

    import hashlib
    import uuid
    from abc import ABC, abstractmethod
    from enum import Enum

    from typing import List, Any

    # Global configuration
    node_registration_debug: bool = False

    class InkModelException(Exception):
        pass

    class IdentifiableMethod(Enum):
        """Different ID encoding methods """
        UUID = 0
        MD5 = 1

    class Identifier(ABC):
        """
        Internal UIM 128bit Identifier (UimID)
        --------------------------------------
        UimID is a 128-bit number used internally by the implementations.

        It can be parsed from strings in the following formats:

        Simple Hexadecimal String Representation (S-Form)
        -------------------------------------------------
        The representation of a UimID value is the hex-decimal string representation of the 128-bit number,
        assuming that it's encoded using Big Endian byte ordering.

        For example: fa70390871c84d91b83c9b56549043ca

        Hyphenated Hexadecimal String Representation (H-Form)
        -----------------------------------------------------
        This representation of a UimID value has the following codec: <part1>-<part2>-<part3>-<part4>-<part5>

        Assuming that the UimID 128-bit value is encoded using Big Endian byte ordering, it is split into 5 groups of
        bytes and each group is formatted as hexadecimal number.

        ---------------------------------------------------------------------------
        |       |  Part 1    | Part 2 | Part 3 | Part 4 | Part 5                  |
        ---------------------------------------------------------------------------
        | Bytes | 0, 1, 2, 3 | 4, 5   | 6,7    | 8, 9   | 10, 11, 12, 13, 14, 15  |
        ---------------------------------------------------------------------------

        -----------------------------------------------------------------------------
        | S  | 32 digits: 00000000000000000000000000000000                          |
        |    | E.g., fa70390871c84d91b83c9b56549043ca                               |
        -----------------------------------------------------------------------------
        | H  | 32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000 |
        |    | E.g.,  fa703908-71c8-4d91-b83c-9b56549043ca                          |
        -----------------------------------------------------------------------------

        The identifier's string representation varies based on the domain:
         - For MD5 hashes - "N" form
         - For Ink Model Internals (Strokes, Nodes, Group Nodes etc.) - "D" form
        """
        SEPARATOR: str = "\n"

        def __init__(self, identifier: uuid.UUID, method: IdentifiableMethod = IdentifiableMethod.MD5):
            self.__identifier: uuid.UUID = identifier
            self.__method: IdentifiableMethod = method
            if identifier is not None and type(identifier) is not uuid.UUID:
                raise TypeError('Identifier must be of type UUID. [Type: {}]'.format(type(identifier)))

        @property
        def id(self) -> uuid.UUID:
            """Identifier of object. (`UUID`, read-only)"""
            if self.__identifier is None:
                self.__identifier = self.__generate_id__()
            return self.__identifier

        @property
        def id_h_form(self) -> str:
            """
            Hyphenated Hexadecimal String Representation (H-Form) (`str`, read-only)

            Examples
            --------
            32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000, e.g., fa703908-71c8-4d91-b83c-9b56549043ca
            """
            return Identifier.uimid_to_h_form(self.id)

        @property
        def id_s_form(self):
            """
            Simple Hexadecimal String Representation (S-Form). (`str`, read-only)

            Examples
            --------
             32 digits: 00000000000000000000000000000000, e.g., fa70390871c84d91b83c9b56549043ca
            """
            return Identifier.uimid_to_s_form(self.id)

        @abstractmethod
        def __generate_id__(self) -> uuid.UUID:
            pass

        @classmethod
        def str_to_uimid(cls, uuid_str: str) -> uuid.UUID:
            """
            Convert from string to UimID (UUID).

            Parameters
            ----------
            uuid_str: `str`
                UimID as s-form

            Returns
            -------
            uuid: `UUID`
                UUID from string

            Raises
            ------
            FormatException
                If UUID string is not valid.
            """
            try:
                return uuid.UUID(uuid_str)
            except ValueError as e:
                raise InkModelException(f'{uuid_str} is not a valid UUID. [Exception:= {str(e)}]')

        @classmethod
        def uimid_to_h_form(cls, uimid: uuid.UUID) -> str:
            """
            Convert Uim-ID in h-form.

            Parameters
            ----------
            uimid: `UUID`
                UUID

            Returns
            -------
            h_form: str
                h-form of UimID

            Raises
            ------
            FormatException
                If UUID string is not valid.
            """
            if uimid is None:
                return ''
            uuid_str: str = uimid.hex
            return f'{uuid_str[:4]}-{uuid_str[4:6]}-{uuid_str[6:8]}-{uuid_str[8:10]}-{uuid_str[10:]}'

        @classmethod
        def uimid_to_s_form(cls, uimid: uuid.UUID) -> str:
            """
            Convert Uim-ID in s-form.

            Parameters
            ----------
            uimid: `UUID`
                UUID

            Returns
            -------
            s_form: `str`
                s-form of UimID
            """
            return uimid.hex

        @classmethod
        def from_bytes(cls, from_bytes: bytes) -> uuid.UUID:
            """
            Convert bytes array to UUID.

            Parameters
            ----------
            from_bytes: `bytes`
                Byte array encoding the UUID

            Returns
            -------
            uuid: `UUID`
                Valid UUID

            Raises
            ------
            InkModelException
                Bytes cannot be converted to UUID
            """
            try:
                return uuid.UUID(bytes_le=from_bytes)
            except ValueError as e:
                raise InkModelException(f'Bytes: {from_bytes} cannot be converted to UUID. [Exception:= {str(e)}]')

    class HashIdentifier(Identifier):
        """
        MD5-hash based Unique Identifier Generation Algorithm
        -----------------------------------------------------
        The described algorithm allows generation of unique identifiers based on a tag (encoded as string value) and
        a collection of components.

        The supported component types are:
            - Integer number
            - Floating-point number
            - String

        List of properties defined as key-value pairs; the key and value of a pair are considered to be of type string.
        The described method takes a tag value and a list of components as arguments and generates a unique MD5 hash as
        an 8-byte array.

        Parameters
        ----------
        identifier: `UUID`
            Identifier

        """

        def __init__(self, identifier: uuid.UUID = None):
            super().__init__(identifier=identifier, method=IdentifiableMethod.MD5)

        @abstractmethod
        def __tokenize__(self) -> List[Any]:
            """
            Generates a list of tokens which are identify the object. The subclass defines the order of tokens.

            Returns
            -------
            tokens: `List[Any]`
                List of tokenized items
            """
            pass

        def __generate_id__(self) -> uuid.UUID:
            token: list = self.__tokenize__()
            message: str = ''
            for t in token:
                if t is None:
                    message += ''
                elif isinstance(t, float):
                    message += '{:.4f}'.format(t)
                elif isinstance(t, int):
                    message += str(t)
                elif isinstance(t, Enum):
                    message += str(t.name)
                elif isinstance(t, uuid.UUID):
                    message += Identifier.uimid_to_s_form(t)
                elif isinstance(t, list):
                    for val in sorted(t, key=lambda value: value[0]):
                        message += val[0]
                        message += Identifier.SEPARATOR
                        message += val[1]
                        message += Identifier.SEPARATOR
                else:
                    message += str(t)
                message += Identifier.SEPARATOR
            md5_hash: str = hashlib.md5(message.encode(encoding='UTF-8', errors='strict')).hexdigest()
            return uuid.UUID(md5_hash)

        def __invalidate__(self):
            """Invalidate the hashed id if an internal value has changed."""
            self.__id = None

    class UUIDIdentifier(Identifier):
        """
        UUID Identifier.

        Parameters
        ----------
        identifier: `UUID`
            Identifier
        """

        def __init__(self, identifier: uuid.UUID):
            super().__init__(identifier=identifier, method=IdentifiableMethod.UUID)

        @staticmethod
        def id_generator() -> uuid.UUID:
            """
            UUID generator function.

            Returns
            -------
            random: UUID
                Random generated UUID
            """
            return uuid.uuid4()

        def __generate_id__(self) -> uuid.UUID:
            return UUIDIdentifier.id_generator()

        def __repr__(self):
            return f'<UUIDIdentifiable : [s-form:={self.id_s_form}, h-form:={self.id_h_form}]>'

## Classes

`class HashIdentifier (identifier: uuid.UUID = None)`

  ## MD5-hash based Unique Identifier Generation Algorithm

  The described algorithm allows generation of unique identifiers based on a tag (encoded as string value) and a collection of components.

  The supported component types are: - Integer number - Floating-point number - String

  List of properties defined as key-value pairs; the key and value of a pair are considered to be of type string. The described method takes a tag value and a list of components as arguments and generates a unique MD5 hash as an 8-byte array.

  ## Parameters

  `identifier` :`UUID`
    Identifier
  Expand source code

      class HashIdentifier(Identifier):
          """
          MD5-hash based Unique Identifier Generation Algorithm
          -----------------------------------------------------
          The described algorithm allows generation of unique identifiers based on a tag (encoded as string value) and
          a collection of components.

          The supported component types are:
              - Integer number
              - Floating-point number
              - String

          List of properties defined as key-value pairs; the key and value of a pair are considered to be of type string.
          The described method takes a tag value and a list of components as arguments and generates a unique MD5 hash as
          an 8-byte array.

          Parameters
          ----------
          identifier: `UUID`
              Identifier

          """

          def __init__(self, identifier: uuid.UUID = None):
              super().__init__(identifier=identifier, method=IdentifiableMethod.MD5)

          @abstractmethod
          def __tokenize__(self) -> List[Any]:
              """
              Generates a list of tokens which are identify the object. The subclass defines the order of tokens.

              Returns
              -------
              tokens: `List[Any]`
                  List of tokenized items
              """
              pass

          def __generate_id__(self) -> uuid.UUID:
              token: list = self.__tokenize__()
              message: str = ''
              for t in token:
                  if t is None:
                      message += ''
                  elif isinstance(t, float):
                      message += '{:.4f}'.format(t)
                  elif isinstance(t, int):
                      message += str(t)
                  elif isinstance(t, Enum):
                      message += str(t.name)
                  elif isinstance(t, uuid.UUID):
                      message += Identifier.uimid_to_s_form(t)
                  elif isinstance(t, list):
                      for val in sorted(t, key=lambda value: value[0]):
                          message += val[0]
                          message += Identifier.SEPARATOR
                          message += val[1]
                          message += Identifier.SEPARATOR
                  else:
                      message += str(t)
                  message += Identifier.SEPARATOR
              md5_hash: str = hashlib.md5(message.encode(encoding='UTF-8', errors='strict')).hexdigest()
              return uuid.UUID(md5_hash)

          def __invalidate__(self):
              """Invalidate the hashed id if an internal value has changed."""
              self.__id = None

  ### Ancestors

  - Identifier
  - abc.ABC

  ### Subclasses

  - PathPointProperties
  - Environment
  - InkInputProvider
  - InputContext
  - InputDevice
  - SensorChannel
  - SensorChannelsContext
  - SensorContext

  ### Class variables

  `var SEPARATOR : str`

  ### Inherited members

  - `Identifier`:
    - `from_bytes`
    - `id`
    - `id_h_form`
    - `id_s_form`
    - `str_to_uimid`
    - `uimid_to_h_form`
    - `uimid_to_s_form`
`class IdentifiableMethod (value, names=None, *, module=None, qualname=None, type=None, start=1)`

  Different ID encoding methods

  Expand source code

      class IdentifiableMethod(Enum):
          """Different ID encoding methods """
          UUID = 0
          MD5 = 1

  ### Ancestors

  - enum.Enum

  ### Class variables

  `var MD5`
  `var UUID`
`class Identifier (identifier: uuid.UUID, method: IdentifiableMethod = IdentifiableMethod.MD5)`

  ## Internal UIM 128bit Identifier (UimID)

  UimID is a 128-bit number used internally by the implementations.

  It can be parsed from strings in the following formats:

  ## Simple Hexadecimal String Representation (S-Form)

  The representation of a UimID value is the hex-decimal string representation of the 128-bit number, assuming that it's encoded using Big Endian byte ordering.

  For example: fa70390871c84d91b83c9b56549043ca

  ## Hyphenated Hexadecimal String Representation (H-Form)

  This representation of a UimID value has the following codec: ----

  Assuming that the UimID 128-bit value is encoded using Big Endian byte ordering, it is split into 5 groups of bytes and each group is formatted as hexadecimal number.

  ## | | Part 1 | Part 2 | Part 3 | Part 4 | Part 5 |

  ## | Bytes | 0, 1, 2, 3 | 4, 5 | 6,7 | 8, 9 | 10, 11, 12, 13, 14, 15 |

  | S | 32 digits: 00000000000000000000000000000000 | | | E.g., fa70390871c84d91b83c9b56549043ca |

  | H | 32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000 | | | E.g., fa703908-71c8-4d91-b83c-9b56549043ca |

  The identifier's string representation varies based on the domain: - For MD5 hashes - "N" form - For Ink Model Internals (Strokes, Nodes, Group Nodes etc.) - "D" form

  Expand source code

      class Identifier(ABC):
          """
          Internal UIM 128bit Identifier (UimID)
          --------------------------------------
          UimID is a 128-bit number used internally by the implementations.

          It can be parsed from strings in the following formats:

          Simple Hexadecimal String Representation (S-Form)
          -------------------------------------------------
          The representation of a UimID value is the hex-decimal string representation of the 128-bit number,
          assuming that it's encoded using Big Endian byte ordering.

          For example: fa70390871c84d91b83c9b56549043ca

          Hyphenated Hexadecimal String Representation (H-Form)
          -----------------------------------------------------
          This representation of a UimID value has the following codec: <part1>-<part2>-<part3>-<part4>-<part5>

          Assuming that the UimID 128-bit value is encoded using Big Endian byte ordering, it is split into 5 groups of
          bytes and each group is formatted as hexadecimal number.

          ---------------------------------------------------------------------------
          |       |  Part 1    | Part 2 | Part 3 | Part 4 | Part 5                  |
          ---------------------------------------------------------------------------
          | Bytes | 0, 1, 2, 3 | 4, 5   | 6,7    | 8, 9   | 10, 11, 12, 13, 14, 15  |
          ---------------------------------------------------------------------------

          -----------------------------------------------------------------------------
          | S  | 32 digits: 00000000000000000000000000000000                          |
          |    | E.g., fa70390871c84d91b83c9b56549043ca                               |
          -----------------------------------------------------------------------------
          | H  | 32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000 |
          |    | E.g.,  fa703908-71c8-4d91-b83c-9b56549043ca                          |
          -----------------------------------------------------------------------------

          The identifier's string representation varies based on the domain:
           - For MD5 hashes - "N" form
           - For Ink Model Internals (Strokes, Nodes, Group Nodes etc.) - "D" form
          """
          SEPARATOR: str = "\n"

          def __init__(self, identifier: uuid.UUID, method: IdentifiableMethod = IdentifiableMethod.MD5):
              self.__identifier: uuid.UUID = identifier
              self.__method: IdentifiableMethod = method
              if identifier is not None and type(identifier) is not uuid.UUID:
                  raise TypeError('Identifier must be of type UUID. [Type: {}]'.format(type(identifier)))

          @property
          def id(self) -> uuid.UUID:
              """Identifier of object. (`UUID`, read-only)"""
              if self.__identifier is None:
                  self.__identifier = self.__generate_id__()
              return self.__identifier

          @property
          def id_h_form(self) -> str:
              """
              Hyphenated Hexadecimal String Representation (H-Form) (`str`, read-only)

              Examples
              --------
              32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000, e.g., fa703908-71c8-4d91-b83c-9b56549043ca
              """
              return Identifier.uimid_to_h_form(self.id)

          @property
          def id_s_form(self):
              """
              Simple Hexadecimal String Representation (S-Form). (`str`, read-only)

              Examples
              --------
               32 digits: 00000000000000000000000000000000, e.g., fa70390871c84d91b83c9b56549043ca
              """
              return Identifier.uimid_to_s_form(self.id)

          @abstractmethod
          def __generate_id__(self) -> uuid.UUID:
              pass

          @classmethod
          def str_to_uimid(cls, uuid_str: str) -> uuid.UUID:
              """
              Convert from string to UimID (UUID).

              Parameters
              ----------
              uuid_str: `str`
                  UimID as s-form

              Returns
              -------
              uuid: `UUID`
                  UUID from string

              Raises
              ------
              FormatException
                  If UUID string is not valid.
              """
              try:
                  return uuid.UUID(uuid_str)
              except ValueError as e:
                  raise InkModelException(f'{uuid_str} is not a valid UUID. [Exception:= {str(e)}]')

          @classmethod
          def uimid_to_h_form(cls, uimid: uuid.UUID) -> str:
              """
              Convert Uim-ID in h-form.

              Parameters
              ----------
              uimid: `UUID`
                  UUID

              Returns
              -------
              h_form: str
                  h-form of UimID

              Raises
              ------
              FormatException
                  If UUID string is not valid.
              """
              if uimid is None:
                  return ''
              uuid_str: str = uimid.hex
              return f'{uuid_str[:4]}-{uuid_str[4:6]}-{uuid_str[6:8]}-{uuid_str[8:10]}-{uuid_str[10:]}'

          @classmethod
          def uimid_to_s_form(cls, uimid: uuid.UUID) -> str:
              """
              Convert Uim-ID in s-form.

              Parameters
              ----------
              uimid: `UUID`
                  UUID

              Returns
              -------
              s_form: `str`
                  s-form of UimID
              """
              return uimid.hex

          @classmethod
          def from_bytes(cls, from_bytes: bytes) -> uuid.UUID:
              """
              Convert bytes array to UUID.

              Parameters
              ----------
              from_bytes: `bytes`
                  Byte array encoding the UUID

              Returns
              -------
              uuid: `UUID`
                  Valid UUID

              Raises
              ------
              InkModelException
                  Bytes cannot be converted to UUID
              """
              try:
                  return uuid.UUID(bytes_le=from_bytes)
              except ValueError as e:
                  raise InkModelException(f'Bytes: {from_bytes} cannot be converted to UUID. [Exception:= {str(e)}]')

  ### Ancestors

  - abc.ABC

  ### Subclasses

  - HashIdentifier
  - UUIDIdentifier

  ### Class variables

  `var SEPARATOR : str`

  ### Static methods

  `def from_bytes(from_bytes: bytes) ‑> uuid.UUID`

    Convert bytes array to UUID.

    ## Parameters

    `from_bytes` :`bytes`
      Byte array encoding the UUID

    ## Returns

    `uuid` :`UUID`
      Valid UUID

    ## Raises

    `InkModelException`
      Bytes cannot be converted to UUID
    Expand source code

        @classmethod
        def from_bytes(cls, from_bytes: bytes) -> uuid.UUID:
            """
            Convert bytes array to UUID.

            Parameters
            ----------
            from_bytes: `bytes`
                Byte array encoding the UUID

            Returns
            -------
            uuid: `UUID`
                Valid UUID

            Raises
            ------
            InkModelException
                Bytes cannot be converted to UUID
            """
            try:
                return uuid.UUID(bytes_le=from_bytes)
            except ValueError as e:
                raise InkModelException(f'Bytes: {from_bytes} cannot be converted to UUID. [Exception:= {str(e)}]')

  `def str_to_uimid(uuid_str: str) ‑> uuid.UUID`

    Convert from string to UimID (UUID).

    ## Parameters

    `uuid_str` :`str`
      UimID as s-form

    ## Returns

    `uuid` :`UUID`
      UUID from string

    ## Raises

    `FormatException`
      If UUID string is not valid.
    Expand source code

        @classmethod
        def str_to_uimid(cls, uuid_str: str) -> uuid.UUID:
            """
            Convert from string to UimID (UUID).

            Parameters
            ----------
            uuid_str: `str`
                UimID as s-form

            Returns
            -------
            uuid: `UUID`
                UUID from string

            Raises
            ------
            FormatException
                If UUID string is not valid.
            """
            try:
                return uuid.UUID(uuid_str)
            except ValueError as e:
                raise InkModelException(f'{uuid_str} is not a valid UUID. [Exception:= {str(e)}]')

  `def uimid_to_h_form(uimid: uuid.UUID) ‑> str`

    Convert Uim-ID in h-form.

    ## Parameters

    `uimid` :`UUID`
      UUID

    ## Returns

    `h_form` :`str`
      h-form of UimID

    ## Raises

    `FormatException`
      If UUID string is not valid.
    Expand source code

        @classmethod
        def uimid_to_h_form(cls, uimid: uuid.UUID) -> str:
            """
            Convert Uim-ID in h-form.

            Parameters
            ----------
            uimid: `UUID`
                UUID

            Returns
            -------
            h_form: str
                h-form of UimID

            Raises
            ------
            FormatException
                If UUID string is not valid.
            """
            if uimid is None:
                return ''
            uuid_str: str = uimid.hex
            return f'{uuid_str[:4]}-{uuid_str[4:6]}-{uuid_str[6:8]}-{uuid_str[8:10]}-{uuid_str[10:]}'

  `def uimid_to_s_form(uimid: uuid.UUID) ‑> str`

    Convert Uim-ID in s-form.

    ## Parameters

    `uimid` :`UUID`
      UUID

    ## Returns

    `s_form` :`str`
      s-form of UimID
    Expand source code

        @classmethod
        def uimid_to_s_form(cls, uimid: uuid.UUID) -> str:
            """
            Convert Uim-ID in s-form.

            Parameters
            ----------
            uimid: `UUID`
                UUID

            Returns
            -------
            s_form: `str`
                s-form of UimID
            """
            return uimid.hex

  ### Instance variables

  `var id : uuid.UUID`

    Identifier of object. (`UUID`, read-only)

    Expand source code

        @property
        def id(self) -> uuid.UUID:
            """Identifier of object. (`UUID`, read-only)"""
            if self.__identifier is None:
                self.__identifier = self.__generate_id__()
            return self.__identifier

  `var id_h_form : str`

    Hyphenated Hexadecimal String Representation (H-Form) (`str`, read-only)

    ## Examples

    32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000, e.g., fa703908-71c8-4d91-b83c-9b56549043ca

    Expand source code

        @property
        def id_h_form(self) -> str:
            """
            Hyphenated Hexadecimal String Representation (H-Form) (`str`, read-only)

            Examples
            --------
            32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000, e.g., fa703908-71c8-4d91-b83c-9b56549043ca
            """
            return Identifier.uimid_to_h_form(self.id)

  `var id_s_form`

    Simple Hexadecimal String Representation (S-Form). (`str`, read-only)

    ## Examples

    32 digits: 00000000000000000000000000000000, e.g., fa70390871c84d91b83c9b56549043ca

    Expand source code

        @property
        def id_s_form(self):
            """
            Simple Hexadecimal String Representation (S-Form). (`str`, read-only)

            Examples
            --------
             32 digits: 00000000000000000000000000000000, e.g., fa70390871c84d91b83c9b56549043ca
            """
            return Identifier.uimid_to_s_form(self.id)

`class InkModelException (*args, **kwargs)`

  Common base class for all non-exit exceptions.

  Expand source code

      class InkModelException(Exception):
          pass

  ### Ancestors

  - builtins.Exception
  - builtins.BaseException
`class UUIDIdentifier (identifier: uuid.UUID)`

  UUID Identifier.

  ## Parameters

  `identifier` :`UUID`
    Identifier
  Expand source code

      class UUIDIdentifier(Identifier):
          """
          UUID Identifier.

          Parameters
          ----------
          identifier: `UUID`
              Identifier
          """

          def __init__(self, identifier: uuid.UUID):
              super().__init__(identifier=identifier, method=IdentifiableMethod.UUID)

          @staticmethod
          def id_generator() -> uuid.UUID:
              """
              UUID generator function.

              Returns
              -------
              random: UUID
                  Random generated UUID
              """
              return uuid.uuid4()

          def __generate_id__(self) -> uuid.UUID:
              return UUIDIdentifier.id_generator()

          def __repr__(self):
              return f'<UUIDIdentifiable : [s-form:={self.id_s_form}, h-form:={self.id_h_form}]>'

  ### Ancestors

  - Identifier
  - abc.ABC

  ### Subclasses

  - Stroke
  - ChannelData
  - SensorData
  - InkNode

  ### Class variables

  `var SEPARATOR : str`

  ### Static methods

  `def id_generator() ‑> uuid.UUID`

    UUID generator function.

    ## Returns

    `random` :`UUID`
      Random generated UUID
    Expand source code

        @staticmethod
        def id_generator() -> uuid.UUID:
            """
            UUID generator function.

            Returns
            -------
            random: UUID
                Random generated UUID
            """
            return uuid.uuid4()

  ### Inherited members

  - `Identifier`:
    - `from_bytes`
    - `id`
    - `id_h_form`
    - `id_s_form`
    - `str_to_uimid`
    - `uimid_to_h_form`
    - `uimid_to_s_form`