import ctypes as ct
from collections import namedtuple
from . import enums
from .exceptions import KvdNoAttribute
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.
"""
[docs]class AttributeDefinition:
"""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().__new__(cls)
return obj
type = ct.c_int()
dll.kvaDbGetAttributeDefinitionType(handle, ct.byref(type))
if type.value == enums.AttributeType.INTEGER:
cls_ = IntegerDefinition
elif type.value == enums.AttributeType.FLOAT:
cls_ = FloatDefinition
elif type.value == enums.AttributeType.STRING:
cls_ = StringDefinition
elif type.value == enums.AttributeType.ENUM:
cls_ = EnumDefinition
else:
type = enums.AttributeType(type.value)
raise NotImplementedError(f'{type.name} not implemented')
return cls_.__new__(cls_, db, handle, definition)
def __init__(self, db, handle):
self._handle = handle
self._db = db
def __repr__(self):
txt = "<{}(name='{}', definition={}, owner={!r})>".format(
self.__class__.__name__, self.name, self.definition, self.owner
)
return txt
@property
def name(self):
"""`str`: 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):
dll.kvaDbSetAttributeDefinitionName(self._handle, value.encode('utf-8'))
@property
def owner(self):
"""`AttributeOwner`: Return attribute owner"""
owner = ct.c_int(0)
dll.kvaDbGetAttributeDefinitionOwner(self._handle, ct.byref(owner))
return enums.AttributeOwner(owner.value)
@owner.setter
def owner(self, owner):
dll.kvaDbSetAttributeDefinitionOwner(self._handle, owner)
[docs]class FloatDefinition(AttributeDefinition):
"""Definition of a float attribute.
Args:
db (`Dbc`): Database that holds attribute definitions
definition (`MinMaxDefinition`): Min, max and default values
"""
def __init__(self, db, handle, definition=None):
super().__init__(db, handle)
# self._ah = None
if definition is not None:
self.definition = definition
@property
def definition(self):
"""`MinMaxDefinition`: Attribute definition"""
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):
dll.kvaDbSetAttributeDefinitionFloat(self._handle, value.default, value.min, value.max)
[docs]class IntegerDefinition(AttributeDefinition):
"""Definition of an integer attribute.
Args:
db (`Dbc`): Database that holds attribute definitions
definition (`MinMaxDefinition`): Min, max and default values
"""
def __init__(self, db, handle, definition=None):
super().__init__(db, handle)
if definition is not None:
self.definition = definition
@property
def definition(self):
"""`MinMaxDefinition`: Return attribute definition"""
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):
dll.kvaDbSetAttributeDefinitionInt(self._handle, value.default, value.min, value.max)
[docs]class StringDefinition(AttributeDefinition):
"""Definition of a string attribute.
Args:
db (`Dbc`): Database that holds attribute definitions
definition (`DefaultDefinition`): default value
"""
def __init__(self, db, handle, definition=None):
super().__init__(db, handle)
if definition is not None:
self.definition = definition
@property
def definition(self):
"""`DefaultDefinition`: Return attribute definition"""
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):
c_default = ct.create_string_buffer(value.default.encode('utf-8'))
dll.kvaDbSetAttributeDefinitionString(self._handle, c_default)
[docs]class EnumDefinition(AttributeDefinition):
"""Definition of an enum attribute.
Args:
db (`Dbc`): Database that holds attribute definitions
definition (`EnumDefaultDefinition`): default value and enums
"""
def __init__(self, db, handle, definition=None):
super().__init__(db, handle)
if definition is not None:
self.definition = definition
[docs] 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)
def _enums(self):
"""Return a generator of all enum key - value pair(s)
.. versionadded:: 1.6
"""
buf = ct.create_string_buffer(255)
c_value = ct.c_int()
c_buf_size = ct.c_size_t(ct.sizeof(buf))
try:
dll.kvaDbGetAttributeDefinitionEnumFirst(
self._handle, ct.byref(c_value), buf, ct.byref(c_buf_size)
)
except KvdNoAttribute:
return
while True:
yield (buf.value.decode('utf-8'), c_value.value)
try:
dll.kvaDbGetAttributeDefinitionEnumNext(
self._handle, ct.byref(c_value), buf, ct.byref(c_buf_size)
)
except KvdNoAttribute:
return
@property
def definition(self):
"""`EnumDefaultDefinition`: Return attribute definition
.. versionchanged:: 1.6
"""
c_default = ct.c_int()
dll.kvaDbGetAttributeDefinitionEnumeration(self._handle, ct.byref(c_default))
enums = dict(list(self._enums()))
definition = EnumDefaultDefinition(default=c_default.value, enums=enums)
return definition
@definition.setter
def definition(self, value):
dll.kvaDbSetAttributeDefinitionEnumDefault(self._handle, value.default)
self.add_enum_definition(value.enums)