Source code for canlib.kvadblib.attributedef

import ctypes as ct

from collections import namedtuple

from . import enums
from .wrapper import dll


MinMaxDefinition = namedtuple('MinMaxDefinition', 'default min max')
"""Attribute definition for attributes defined using default, min and max."""

DefaultDefinition = namedtuple('DefaultDefinition', 'default')
"""Attribute definition for attributes defined using only default."""

EnumDefaultDefinition = namedtuple('EnumDefaultDefinition', 'default enums')
"""Attribute definition for enumeration attributes.

Holds a definition using default and key-value pairs.
"""


class AttributeDefinition(object):
    """Factory for creating different types of attribute definitions.

    This class is also the base class and thus contains all common properties.
    """
    def __new__(cls, db, handle, definition=None):
        """Create attribute definition class depending on type."""
        if cls != AttributeDefinition:
            obj = super(AttributeDefinition, cls).__new__(cls)
            return obj
        type = ct.c_int()
        dll.kvaDbGetAttributeDefinitionType(handle, ct.byref(type))
        if type.value == enums.AttributeType.INTEGER:
            return IntegerDefinition(db, handle, definition)
        elif type.value == enums.AttributeType.FLOAT:
            return FloatDefinition(db, handle, definition)
        elif type.value == enums.AttributeType.STRING:
            return StringDefinition(db, handle, definition)
        elif type.value == enums.AttributeType.ENUM:
            return EnumDefinition(db, handle, definition)
        else:
            type = enums.AttributeType(type.value)
            raise NotImplementedError('{} not implemented'.format(type.name))

    def __init__(self, db, handle):
        self._handle = handle
        self._db = db

    def __repr__(self):
        txt = ("IntegerAttributeDefinition(handle={},"
               " name='{}', definition={}".
               format(self._handle, self.name, self.definition))
        return txt

    @property
    def name(self):
        """Get name of attribute definition."""
        buf = ct.create_string_buffer(255)
        dll.kvaDbGetAttributeDefinitionName(
            self._handle, buf, ct.sizeof(buf))
        return buf.value.decode('utf-8')

    @name.setter
    def name(self, value):
        """Set name on attribute definition (:obj:`str`)."""
        dll.kvaDbSetAttributeDefinitionName(
            self._handle, value.encode('utf-8'))

    @property
    def owner(self):
        """Return attribute owner.

        Returns:
            owner (:obj:`kvadblib.AttributeOwner`)
        """
        owner = ct.c_int(0)
        dll.kvaDbGetAttributeDefinitionOwner(
            self._handle, ct.byref(owner))
        return enums.AttributeOwner(owner.value)

    @owner.setter
    def owner(self, owner):
        """Set attribute owner.

        Args:
            owner (:obj:`kvadblib.AttributeOwner`)
        """
        dll.kvaDbSetAttributeDefinitionOwner(self._handle, owner)


class FloatDefinition(AttributeDefinition):
    """Definition of a float attribute."""

    def __init__(self, db, handle, definition=None):
        """Holds a float attribute definition.

        Args:
            db (:obj:`Dbc`): Database that holds attribute definitions
            definition (:obj:`MinMaxDefinition`): Min, max and default values
        """
        super(FloatDefinition, self).__init__(db, handle)
        # self._ah = None
        if definition is not None:
            self.definition = definition

    @property
    def definition(self):
        """Return attribute definition.

        Returns:
            definition (:obj:`MinMaxDefinition`)
        """
        default = ct.c_float()
        min = ct.c_float()
        max = ct.c_float()
        dll.kvaDbGetAttributeDefinitionFloat(
            self._handle, default, min, max)
        definition = MinMaxDefinition(default=default.value,
                                      min=min.value, max=max.value)
        return definition

    @definition.setter
    def definition(self, value):
        """Set attribute definition.

        Args:
            value (:obj:`MinMaxDefinition`)
        """
        dll.kvaDbSetAttributeDefinitionFloat(
            self._handle, value.default, value.min, value.max)


class IntegerDefinition(AttributeDefinition):
    """Definition of an integer attribute."""

    def __init__(self, db, handle, definition=None):
        """Define an integer attribute.

        Args:
            db (:obj:`Dbc`): Database that holds attribute definitions
            definition (:obj:`MinMaxDefinition`): Min, max and default values
        """
        super(IntegerDefinition, self).__init__(db, handle)
        if definition is not None:
            self.definition = definition

    @property
    def definition(self):
        """Return attribute definition.

        Returns:
            definition (:obj:`MinMaxDefinition`)
        """
        default = ct.c_int()
        min = ct.c_int()
        max = ct.c_int()
        dll.kvaDbGetAttributeDefinitionInt(
            self._handle, default, min, max)
        definition = MinMaxDefinition(default=default.value,
                                      min=min.value, max=max.value)
        return definition

    @definition.setter
    def definition(self, value):
        """Set attribute definition.

        Args:
            value (:obj:`MinMaxDefinition`)
        """
        dll.kvaDbSetAttributeDefinitionInt(
            self._handle, value.default, value.min, value.max)


class StringDefinition(AttributeDefinition):
    """Definition of a string attribute."""

    def __init__(self, db, handle, definition=None):
        """Define a string attribute.

        Args:
            db (:obj:`Dbc`): Database that holds attribute definitions
            definition (:obj:`DefaultDefinition`): default value
        """
        super(StringDefinition, self).__init__(db, handle)
        if definition is not None:
            self.definition = definition

    @property
    def definition(self):
        """Return attribute definition.

        Returns:
            definition (:obj:`DefaultDefinition`) where definition.default is a str
        """
        c_default = ct.create_string_buffer(255)
        dll.kvaDbGetAttributeDefinitionString(
            self._handle, c_default, ct.sizeof(c_default))
        definition = DefaultDefinition(default=c_default.value.decode('utf-8'))
        return definition

    @definition.setter
    def definition(self, value):
        """Set attribute definition.

        Args:
            value (:obj:`DefaultDefinition`) where value.default is a str
        """
        c_default = ct.create_string_buffer(value.default.encode('utf-8'))
        dll.kvaDbSetAttributeDefinitionString(self._handle, c_default)


class EnumDefinition(AttributeDefinition):
    """Definition of an enum attribute."""

    def __init__(self, db, handle, definition=None):
        """Define an enum attribute.

        Args:
            db (:obj:`Dbc`): Database that holds attribute definitions
            definition (:obj:`EnumDefaultDefinition`): default value and enums
        """
        super(EnumDefinition, self).__init__(db, handle)
        if definition is not None:
            self.definition = definition

    def add_enum_definition(self, enums):
        """Add enum definitions.

        Args:
            enums (dict): key - value pair(s), example: {'empty': 0}
        """
        for key, value in enums.items():
            c_key = ct.create_string_buffer(key.encode('utf-8'))
            c_value = ct.c_int(value)
            dll.kvaDbAddAttributeDefinitionEnum(
                self._handle, c_key, c_value)

    @property
    def definition(self):
        """Return attribute definition.

        Note: definition.enums will always be {} since the API does not support
        reading enum definitions.

        Returns:
            definition (:obj:`EnumDefaultDefinition`)

        """
        c_default = ct.c_int()
        dll.kvaDbGetAttributeDefinitionEnumeration(
            self._handle, ct.byref(c_default))
        # qqqmac enums is empty since we can't read enum pairs.
        definition = EnumDefaultDefinition(default=c_default.value, enums={})
        return definition

    @definition.setter
    def definition(self, value):
        """Set attribute definition.

        Args:
            value (:obj:`EnumDefaultDefinition`)
        """
        dll.kvaDbSetAttributeDefinitionEnumDefault(self._handle, value.default)
        self.add_enum_definition(value.enums)