hydra / hydra /

# -*- coding: utf-8 -*-
# Copyright (C) 2013 Alexander Shorin
# All rights reserved.
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.

from couchdb.mapping import (
    Mapping as _Mapping,
    Document as _Document,
    DateField as _DateField,
    DateTimeField as _DateTimeField,
    Field, TextField, FloatField,
    IntegerField, LongField, BooleanField, DecimalField,
    TimeField, DictField, ListField,
from .lib.dateutils import parse_iso_datetime, datetime_iso

__all__ = ['Field', 'Mapping', 'Document',
           'TextField', 'BooleanField', 'ConstantField',
           'IntegerField', 'LongField', 'FloatField', 'DecimalField',
           'DateField', 'TimeField', 'DateTimeField',
           'ListField', 'SetField', 'DictField',

class Mapping(_Mapping):
    """Improved :class:`couchdb.mapping.Mapping` with support of extra fields,
    that wasn't defined explicitly via :class:`couchdb.mapping.Field` properties

    >>> class Thing(Mapping):
    ...     foo = TextField()
    >>> thing = Thing(foo='bar', bar='baz')
    >>> thing['foo']
    >>> thing['bar']
    >>> getattr(thing, 'bar', None) is None
    def __init__(self, **values):
        self._data = {}
        for attrname, field in self._fields.items():
            if attrname in values:
                setattr(self, attrname, values.pop(attrname))
                setattr(self, attrname, getattr(self, attrname))

class Document(Mapping, _Document):
    __doc__ = _Document.__doc__

class DateField(_DateField):
    __doc__ = _DateField.__doc__

    def _to_python(self, value):
        return parse_iso_datetime(value).date()

    def _to_json(self, value):
        return datetime_iso(value)

class DateTimeField(_DateTimeField):
    __doc__ = _DateTimeField.__doc__

    def _to_python(self, value):
        return parse_iso_datetime(value)

    def _to_json(self, value):
        return datetime_iso(value)

class ConstantField(Field):

    def __init__(self, value, name=None, field=TextField()):
        self.value = value
        self.field = field
        super(ConstantField, self).__init__(name, value)

    def _to_python(self, value):
        return self.field._to_python(value)

    def _to_json(self, value):
        if value != self.value:
            raise ValueError('Invalid value %r, expected %r'
                             '' % (value, self.value))
        return self.field._to_json(value)

class SetField(Field):

    def __init__(self, values, name=None, default=None, field=TextField()):
        self.values = frozenset(values)
        self.field = field
        super(SetField, self).__init__(name, default)

    def _to_python(self, value):
        return self.field._to_python(value)

    def _to_json(self, value):
        if value not in self.values:
            raise ValueError('Invalid value %r, expected one of: %s'
                             '' % (value, self.values))
        return self.field._to_json(value)