<commit_before>from types import FunctionType
from inspect import getargspec
from collections import Iterable
from decimal import Decimal
from datetime import datetime
from utils import IN, OUT, classproperty
from observable import Observable

__all__ = ['Boolean', 'String', 'Enum', 'Integer', 'Float', 'Numeric', 'DateTime',
           'Array', 'RelOut', 'RelIn', 'RelOutOne', 'RelInOne']

class FieldDescriptor(Observable):

    def __init__(self, name=None, observers=None):
        self._name = None
        self.name = name
        if isinstance(observers, dict):
            self.add_observers(observers)

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        if self._name is None:
            self._name = name

    def fire_event(self, event, target, *args):
        entity, field = target
        if not entity.is_expunged():
            super(FieldDescriptor, self).fire_event(event, target, *args)

class Property(FieldDescriptor):

    __value_type__ = None

    def __init__(self, name=None, default=None, observers=None):
        super(Property, self).__init__(name=name, observers=observers)
        self._default = default

    def __get__(self, instance, owner=None):
        if instance is None:
            return self
        else:
            value = instance.properties.get(self.name)
            return self.normalize(value if value is not None else self.get_default(instance))
    
    def __set__(self, instance, value):
        instance.properties[self.name] = self.normalize(value)
    
    def __delete__(self, instance):
        del instance.properties[self.name]

    def get_default(self, instance):
        if hasattr(self._default, '__call__'):
            if isinstance(self._default, FunctionType) and len(getargspec(self._default).args) == 1:
                return self._default(instance)
            else:
                return self._default()
        else:
            return self._default

    def normalize(self, value):
        if value is not None and self.__value_type__ is not None:
            if not isinstance(value, self.__value_type__):
                value = self.__value_type__(value)
        return value

class Boolean(Property):

    __value_type__ = bool

class String(Property):

    __value_type__ = unicode

class Enum(String):

    def __init__(self, *args, **kwargs):
        super(Enum, self).__init__(name=kwargs.get('name'),
                                   default=kwargs.get('default'),
                                   observers=kwargs.get('observers'))
        self.values = args
    
    def __set__(self, instance, value):
        if value not in self.values:
            raise ValueError(u"Invalid value for Enum: {0}".format(value))
        super(Enum, self).__set__(instance, value)

class Integer(Property):

    __value_type__ = int

class Float(Property):

    __value_type__ = float

class Numeric(Property):

    __value_type__ = Decimal

    def __init__(self, scale=None, name=None, default=None, observers=None):
        super(Numeric, self).__init__(name=name, default=default, observers=observers)
        self.scale = scale
    
    def __set__(self, instance, value):
        if value is not None:
            value = str(value)
        instance.properties[self.name] = value

    def normalize(self, value):
        value = super(Numeric, self).normalize(value)
        if self.scale is not None and isinstance(value, Decimal):
            value = value.quantize(Decimal('1.' + '0' * self.scale))
        return value

class DateTime(Property):

    __value_type__ = datetime

    def __get__(self, instance, owner=None):
        if instance is None:
            return self
        else:
            value = instance.properties.get(self.name)
            if value is not None and not isinstance(value, datetime):
                value = self.parse(value)
            return value if value is not None else self.get_default(instance)
    
    def __set__(self, instance, value):
        if isinstance(value, datetime):
            value = value.strftime("%Y-%m-%d %H:%M:%S")
        instance.properties[self.name] = value

    @classmethod
    def parse(cls, value):
        if isinstance(value, basestring):
            try:
                return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")<commit_msg>adding convenience DateTime.format() method<commit_after>from types import FunctionType
from inspect import getargspec
from collections import Iterable
from decimal import Decimal
from datetime import datetime
from utils import IN, OUT, classproperty
from observable import Observable

__all__ = ['Boolean', 'String', 'Enum', 'Integer', 'Float', 'Numeric', 'DateTime',
           'Array', 'RelOut', 'RelIn', 'RelOutOne', 'RelInOne']

class FieldDescriptor(Observable):

    def __init__(self, name=None, observers=None):
        self._name = None
        self.name = name
        if isinstance(observers, dict):
            self.add_observers(observers)

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        if self._name is None:
            self._name = name

    def fire_event(self, event, target, *args):
        entity, field = target
        if not entity.is_expunged():
            super(FieldDescriptor, self).fire_event(event, target, *args)

class Property(FieldDescriptor):

    __value_type__ = None

    def __init__(self, name=None, default=None, observers=None):
        super(Property, self).__init__(name=name, observers=observers)
        self._default = default

    def __get__(self, instance, owner=None):
        if instance is None:
            return self
        else:
            value = instance.properties.get(self.name)
            return self.normalize(value if value is not None else self.get_default(instance))
    
    def __set__(self, instance, value):
        instance.properties[self.name] = self.normalize(value)
    
    def __delete__(self, instance):
        del instance.properties[self.name]

    def get_default(self, instance):
        if hasattr(self._default, '__call__'):
            if isinstance(self._default, FunctionType) and len(getargspec(self._default).args) == 1:
                return self._default(instance)
            else:
                return self._default()
        else:
            return self._default

    def normalize(self, value):
        if value is not None and self.__value_type__ is not None:
            if not isinstance(value, self.__value_type__):
                value = self.__value_type__(value)
        return value

class Boolean(Property):

    __value_type__ = bool

class String(Property):

    __value_type__ = unicode

class Enum(String):

    def __init__(self, *args, **kwargs):
        super(Enum, self).__init__(name=kwargs.get('name'),
                                   default=kwargs.get('default'),
                                   observers=kwargs.get('observers'))
        self.values = args
    
    def __set__(self, instance, value):
        if value not in self.values:
            raise ValueError(u"Invalid value for Enum: {0}".format(value))
        super(Enum, self).__set__(instance, value)

class Integer(Property):

    __value_type__ = int

class Float(Property):

    __value_type__ = float

class Numeric(Property):

    __value_type__ = Decimal

    def __init__(self, scale=None, name=None, default=None, observers=None):
        super(Numeric, self).__init__(name=name, default=default, observers=observers)
        self.scale = scale
    
    def __set__(self, instance, value):
        if value is not None:
            value = str(value)
        instance.properties[self.name] = value

    def normalize(self, value):
        value = super(Numeric, self).normalize(value)
        if self.scale is not None and isinstance(value, Decimal):
            value = value.quantize(Decimal('1.' + '0' * self.scale))
        return value

class DateTime(Property):

    __value_type__ = datetime

    def __get__(self, instance, owner=None):
        if instance is None:
            return self
        else:
            value = instance.properties.get(self.name)
            if value is not None and not isinstance(value, datetime):
                value = self.parse(value)
            return value if value is not None else self.get_default(instance)
    
    def __set__(self, instance, value):
        if isinstance(value, datetime):
            value = value.strftime("%Y-%m-%d %H:%M:%S")
        instance.properties[self.name] = value

    @classmethod
    def format(cls, value):
        if not isinstance(value, datetime):
            value = cls.parse(value)
        return value.strftime("%Y-%m-%d %H:%M:%S")

    @classmethod
    def parse(cls, value):
        if isinstance(value, basestring):
            try:
                return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
{'fraction_non_alphanumeric': 0.1043254146122815, 'fraction_numerical': 0.0008964589870013447, 'mean_word_length': 2.513779527559055, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3705567', 'n_tokens_mistral': 2507, 'n_tokens_neox': 2447, 'n_words': 677}