Source code for goblin.properties

"""Classes to handle properties and data type definitions"""

import logging

from gremlin_python.statics import long

from goblin import abc, exception

logger = logging.getLogger(__name__)


[docs]def noop_factory(x, y): return None
[docs]class PropertyDescriptor: """ Descriptor that validates user property input and gets/sets properties as instance attributes. Not instantiated by user. """ def __init__(self, name, prop): self._prop_name = name self._name = '_' + name self._data_type = prop.data_type self._default = prop.default def __get__(self, obj, objtype): if obj is None: return getattr(objtype.__mapping__, self._prop_name) return getattr(obj, self._name, self._default) def __set__(self, obj, val): val = self._data_type.validate(val) setattr(obj, self._name, val) def __delete__(self, obj): # hmmm what is the best approach here attr = getattr(obj, self._name, None) if attr: del attr
[docs]class Property(abc.BaseProperty): """ API class used to define properties. Replaced with :py:class:`PropertyDescriptor` by :py:class:`goblin.element.ElementMeta`. :param goblin.abc.DataType data_type: Str or class of data type :param str db_name: User defined custom name for property in db :param default: Default value for this property. """ __descriptor__ = PropertyDescriptor def __init__(self, data_type, *, db_name=None, default=None, db_name_factory=None): if not db_name_factory: db_name_factory = noop_factory # noop if isinstance(data_type, type): data_type = data_type() self._db_name_factory = db_name_factory self._data_type = data_type self._db_name = db_name self._default = default @property def data_type(self): return self._data_type
[docs] def getdb_name(self): return self._db_name
[docs] def setgetdb_name(self, val): self._db_name = val
db_name = property(getdb_name, setgetdb_name) @property def db_name_factory(self): return self._db_name_factory @property def default(self): return self._default
[docs]class IdPropertyDescriptor: def __init__(self, name, prop): assert name == 'id', 'ID properties must be named "id"' self._data_type = prop.data_type self._name = '_' + name self._serializer = prop.serializer def __get__(self, obj, objtype=None): if obj is None: raise exception.ElementError( "Only instantiated elements have ID property") return obj._id def __set__(self, obj, val): if self._serializer: val = self._serializer(val) val = self._data_type.validate(val) setattr(obj, self._name, val)
[docs]def default_id_serializer(val): if isinstance(val, int): val = long(val) return val
[docs]class IdProperty(abc.BaseProperty): __descriptor__ = IdPropertyDescriptor def __init__(self, data_type, *, serializer=None): if not serializer: serializer = default_id_serializer if isinstance(data_type, type): data_type = data_type() self._data_type = data_type self._serializer = serializer @property def data_type(self): return self._data_type @property def serializer(self): return self._serializer
# Data types
[docs]class Generic(abc.DataType):
[docs] def validate(self, val): return super().validate(val)
[docs] def to_db(self, val=None): return super().to_db(val=val)
[docs] def to_ogm(self, val): return super().to_ogm(val)
[docs]class String(abc.DataType): """Simple string datatype"""
[docs] def validate(self, val): if val is not None: try: return str(val) except ValueError as e: raise exception.ValidationError( 'Not a valid string: {}'.format(val)) from e
[docs] def to_db(self, val=None): return super().to_db(val=val)
[docs] def to_ogm(self, val): return super().to_ogm(val)
[docs]class Integer(abc.DataType): """Simple integer datatype"""
[docs] def validate(self, val): if val is not None: try: if isinstance(val, long): return long(val) return int(val) except (ValueError, TypeError) as e: raise exception.ValidationError( 'Not a valid integer: {}'.format(val)) from e
[docs] def to_db(self, val=None): return super().to_db(val=val)
[docs] def to_ogm(self, val): return super().to_ogm(val)
[docs]class Float(abc.DataType): """Simple float datatype"""
[docs] def validate(self, val): try: val = float(val) except ValueError: raise exception.ValidationError( "Not a valid float: {}".format(val)) from e return val
[docs] def to_db(self, val=None): return super().to_db(val=val)
[docs] def to_ogm(self, val): return super().to_ogm(val)
[docs]class Boolean(abc.DataType): """Simple boolean datatype"""
[docs] def validate(self, val): try: val = bool(val) except ValueError: raise exception.ValidationError( "Not a valid boolean: {val}".format(val)) from e return val
[docs] def to_db(self, val=None): return super().to_db(val=val)
[docs] def to_ogm(self, val): return super().to_ogm(val)