# Path: doodle/common/errors.py
# class PropertyError(BaseError):
#     pass
# 
# Path: doodle/core/property.py
# class BooleanProperty(Property):
#     def validate(self, value):
#         if value is not None:
#             return bool(value)
# 
# class IntegerProperty(Property):
#     def validate(self, value):
#         if value is not None:
#             try:
#                 return int(value)
#             except ValueError:
#                 raise ValueError('Property %s must be an int or long, not a %s'
#                                  % (self.name, value.__class__.__name__))
# 
# class PropertiedClass(type):
#     def __init__(cls, name, bases, dct):
#         super(PropertiedClass, cls).__init__(name, bases, dct)
# 
#         if 'KEY' not in cls.__dict__:
#             cls.KEY = cls.__name__
# 
#         if hasattr(cls, '_properties'):
#             cls._properties = cls._properties.copy()
#         else:
#             cls._properties = {}  # stores Property instances
# 
#         for prop_name, prop in dct.iteritems():
#             if isinstance(prop, Property):
#                 cls._properties[prop_name] = prop
#                 prop.name = prop_name
# 
# Path: doodle/core/redis_client.py



import logging
import json
from redis.client import Pipeline
from doodle.common.errors import PropertyError
from doodle.core.property import BooleanProperty, IntegerProperty, PropertiedClass
from doodle.core.redis_client import redis_main_client
        return self._attributes.copy()

    def __eq__(self, other):
        if type(self) is type(other) and self._attributes == other._attributes:
            return True
        return False


class JSONModel(PropertiedModel):
    def __init__(self, **kwargs):
        super(JSONModel, self).__init__(**kwargs)
        self._origin_data = {}  # stores origin data from Redis

    def to_json(self, ensure_ascii=False):
        none_empty_attributes = {}
        for key, value in self._attributes.iteritems():
            prop = self._properties.get(key)
            if prop and not prop.is_empty(value):
                if isinstance(property, BooleanProperty):
                    value = 1 if value else 0  # save space
                none_empty_attributes[key] = value
        return json.dumps(none_empty_attributes, ensure_ascii=ensure_ascii)

    @classmethod
    def from_json(cls, json_content):
        if json_content:
            try:
                json_dict = json.loads(json_content)
                if isinstance(json_dict, dict):
                    entity = cls(**json_dict)

# Path: doodle/common/errors.py
# class PropertyError(BaseError):
#     pass
# 
# Path: doodle/core/property.py
# class BooleanProperty(Property):
#     def validate(self, value):
#         if value is not None:
#             return bool(value)
# 
# class IntegerProperty(Property):
#     def validate(self, value):
#         if value is not None:
#             try:
#                 return int(value)
#             except ValueError:
#                 raise ValueError('Property %s must be an int or long, not a %s'
#                                  % (self.name, value.__class__.__name__))
# 
# class PropertiedClass(type):
#     def __init__(cls, name, bases, dct):
#         super(PropertiedClass, cls).__init__(name, bases, dct)
# 
#         if 'KEY' not in cls.__dict__:
#             cls.KEY = cls.__name__
# 
#         if hasattr(cls, '_properties'):
#             cls._properties = cls._properties.copy()
#         else:
#             cls._properties = {}  # stores Property instances
# 
#         for prop_name, prop in dct.iteritems():
#             if isinstance(prop, Property):
#                 cls._properties[prop_name] = prop
#                 prop.name = prop_name
# 
# Path: doodle/core/redis_client.py



# Path: doodle/core/models/base_model.py
import logging
import json
from redis.client import Pipeline
from doodle.common.errors import PropertyError
from doodle.core.property import BooleanProperty, IntegerProperty, PropertiedClass
from doodle.core.redis_client import redis_main_client

        return self._attributes.copy()

    def __eq__(self, other):
        if type(self) is type(other) and self._attributes == other._attributes:
            return True
        return False


class JSONModel(PropertiedModel):
    def __init__(self, **kwargs):
        super(JSONModel, self).__init__(**kwargs)
        self._origin_data = {}  # stores origin data from Redis

    def to_json(self, ensure_ascii=False):
        none_empty_attributes = {}
        for key, value in self._attributes.iteritems():
            prop = self._properties.get(key)
            if prop and not prop.is_empty(value):
                if isinstance(property, BooleanProperty):
                    value = 1 if value else 0  # save space
                none_empty_attributes[key] = value
        return json.dumps(none_empty_attributes, ensure_ascii=ensure_ascii)

    @classmethod
    def from_json(cls, json_content):
        if json_content:
            try:
                json_dict = json.loads(json_content)
                if isinstance(json_dict, dict):
                    entity = cls(**json_dict)

                    entity._origin_data = entity.to_dict()