# Path: ckan_api_client/objects/base.py
# class BaseField(object):
#     """
#     Pseudo-descriptor, accepting field names along with instance,
#     to allow better retrieving data for the instance itself.
# 
#     .. warning::
#         Beware that fields shouldn't carry state of their own, a part
#         from the one used for generic field configuration, as they
#         are shared between instances.
#     """
# 
#     default = None
#     is_key = False
# 
#     def __init__(self, default=NOTSET, is_key=NOTSET, required=False):
#         """
#         :param default:
#             Default value (if not callable) or function
#             returning default value (if callable).
#         :param is_key:
#             Boolean indicating whether this is a key field
#             or not. Key fields are ignored when comparing
#             using :py:meth:`is_equivalent`
#         """
# 
#         # todo: refactor to use kwargs
# 
#         if default is not NOTSET:
#             self.default = default
#         if is_key is not NOTSET:
#             self.is_key = is_key
#         self.required = required
# 
#         self._conf = {
#             'default': self.default,
#             'is_key': self.is_key,
#             'required': self.required,
#         }
# 
#     def get(self, instance, name):
#         """
#         Get the value for the field from the main instace,
#         by looking at the first found in:
# 
#         - the updated value
#         - the initial value
#         - the default value
#         """
# 
#         if name in instance._updates:
#             return instance._updates[name]
# 
#         if name in instance._values:
#             return instance._values[name]
# 
#         return self.get_default()
# 
#     def get_default(self):
#         if callable(self.default):
#             return self.default()
#         return self.default
# 
#     def validate(self, instance, name, value):
#         """
#         The validate method should be the (updated)
#         value to be used as the field value, or raise
#         an exception in case it is not acceptable at all.
#         """
#         return value
# 
#     def set_initial(self, instance, name, value):
#         """Set the initial value for a field"""
#         value = self.validate(instance, name, value)
#         instance._values[name] = value
# 
#     def set(self, instance, name, value):
#         """Set the modified value for a field"""
#         value = self.validate(instance, name, value)
#         instance._updates[name] = value
# 
#     def delete(self, instance, name):
#         """
#         Delete the modified value for a field (logically
#         restores the original one)
#         """
#         # We don't want an exception here, as we just restore
#         # field to its initial value..
#         instance._updates.pop(name, None)
# 
#     def serialize(self, instance, name):
#         """
#         Returns the "serialized" (json-encodable) version of
#         the object.
#         """
#         return self.get(instance, name)
# 
#     def is_modified(self, instance, name):
#         """
#         Check whether this field has been modified on the
#         main instance.
#         """
#         return name in instance._updates
# 
#     def is_equivalent(self, instance, name, other, ignore_key=True):
#         if ignore_key and self.is_key:
# 
#             # If we want to ignore keys from comparison,
#             # key comparison should always return True
#             # for fields marked as keys.
# 
#             # --------------------------------------------------
#             # NOTE: This should not be needed, as this part
#             # won't even be called in case it is a key **and**
#             # ignore_key=True. Its main purpose is to be
#             # used recursively by fields containing related
#             # objects.
#             # --------------------------------------------------
# 
#             return True
# 
#         # Just perform simple comparison between values
#         myvalue = getattr(instance, name)
#         othervalue = getattr(other, name)
#         if myvalue is None:
#             myvalue = self.get_default()
#         if othervalue is None:
#             othervalue = self.get_default()
#         return myvalue == othervalue
# 
#     def __repr__(self):
#         myname = self.__class__.__name__
#         kwargs = ', '.join('{0}={1!r}'.format(key, value)
#                            for key, value in self._conf.iteritems())
#         return "{0}({1})".format(myname, kwargs)
# 
# MAPPING_TYPES = (dict, collections.Mapping)
# 
# SEQUENCE_TYPES = (list, tuple, collections.Sequence)


import copy
from .base import BaseField, MAPPING_TYPES, SEQUENCE_TYPES
        if name not in instance._updates:
            return False

        # Otherwise, compare values to check whether
        # field has been modified.

        if name in instance._values:
            default = instance._values[name]
        else:
            default = self.get_default()
        return default != instance._updates[name]


class ListField(MutableFieldMixin, BaseField):
    default = staticmethod(lambda: [])

    def validate(self, instance, name, value):
        value = super(ListField, self).validate(instance, name, value)
        if not isinstance(value, SEQUENCE_TYPES):
            raise ValueError("{0} must be a list".format(name))
        return value


class SetField(MutableFieldMixin, BaseField):
    default = staticmethod(lambda: [])

    def validate(self, instance, name, value):
        value = super(SetField, self).validate(instance, name, value)
        if isinstance(value, set):
            return value

# Path: ckan_api_client/objects/base.py
# class BaseField(object):
#     """
#     Pseudo-descriptor, accepting field names along with instance,
#     to allow better retrieving data for the instance itself.
# 
#     .. warning::
#         Beware that fields shouldn't carry state of their own, a part
#         from the one used for generic field configuration, as they
#         are shared between instances.
#     """
# 
#     default = None
#     is_key = False
# 
#     def __init__(self, default=NOTSET, is_key=NOTSET, required=False):
#         """
#         :param default:
#             Default value (if not callable) or function
#             returning default value (if callable).
#         :param is_key:
#             Boolean indicating whether this is a key field
#             or not. Key fields are ignored when comparing
#             using :py:meth:`is_equivalent`
#         """
# 
#         # todo: refactor to use kwargs
# 
#         if default is not NOTSET:
#             self.default = default
#         if is_key is not NOTSET:
#             self.is_key = is_key
#         self.required = required
# 
#         self._conf = {
#             'default': self.default,
#             'is_key': self.is_key,
#             'required': self.required,
#         }
# 
#     def get(self, instance, name):
#         """
#         Get the value for the field from the main instace,
#         by looking at the first found in:
# 
#         - the updated value
#         - the initial value
#         - the default value
#         """
# 
#         if name in instance._updates:
#             return instance._updates[name]
# 
#         if name in instance._values:
#             return instance._values[name]
# 
#         return self.get_default()
# 
#     def get_default(self):
#         if callable(self.default):
#             return self.default()
#         return self.default
# 
#     def validate(self, instance, name, value):
#         """
#         The validate method should be the (updated)
#         value to be used as the field value, or raise
#         an exception in case it is not acceptable at all.
#         """
#         return value
# 
#     def set_initial(self, instance, name, value):
#         """Set the initial value for a field"""
#         value = self.validate(instance, name, value)
#         instance._values[name] = value
# 
#     def set(self, instance, name, value):
#         """Set the modified value for a field"""
#         value = self.validate(instance, name, value)
#         instance._updates[name] = value
# 
#     def delete(self, instance, name):
#         """
#         Delete the modified value for a field (logically
#         restores the original one)
#         """
#         # We don't want an exception here, as we just restore
#         # field to its initial value..
#         instance._updates.pop(name, None)
# 
#     def serialize(self, instance, name):
#         """
#         Returns the "serialized" (json-encodable) version of
#         the object.
#         """
#         return self.get(instance, name)
# 
#     def is_modified(self, instance, name):
#         """
#         Check whether this field has been modified on the
#         main instance.
#         """
#         return name in instance._updates
# 
#     def is_equivalent(self, instance, name, other, ignore_key=True):
#         if ignore_key and self.is_key:
# 
#             # If we want to ignore keys from comparison,
#             # key comparison should always return True
#             # for fields marked as keys.
# 
#             # --------------------------------------------------
#             # NOTE: This should not be needed, as this part
#             # won't even be called in case it is a key **and**
#             # ignore_key=True. Its main purpose is to be
#             # used recursively by fields containing related
#             # objects.
#             # --------------------------------------------------
# 
#             return True
# 
#         # Just perform simple comparison between values
#         myvalue = getattr(instance, name)
#         othervalue = getattr(other, name)
#         if myvalue is None:
#             myvalue = self.get_default()
#         if othervalue is None:
#             othervalue = self.get_default()
#         return myvalue == othervalue
# 
#     def __repr__(self):
#         myname = self.__class__.__name__
#         kwargs = ', '.join('{0}={1!r}'.format(key, value)
#                            for key, value in self._conf.iteritems())
#         return "{0}({1})".format(myname, kwargs)
# 
# MAPPING_TYPES = (dict, collections.Mapping)
# 
# SEQUENCE_TYPES = (list, tuple, collections.Sequence)


# Path: ckan_api_client/objects/fields.py
import copy
from .base import BaseField, MAPPING_TYPES, SEQUENCE_TYPES

        if name not in instance._updates:
            return False

        # Otherwise, compare values to check whether
        # field has been modified.

        if name in instance._values:
            default = instance._values[name]
        else:
            default = self.get_default()
        return default != instance._updates[name]


class ListField(MutableFieldMixin, BaseField):
    default = staticmethod(lambda: [])

    def validate(self, instance, name, value):
        value = super(ListField, self).validate(instance, name, value)
        if not isinstance(value, SEQUENCE_TYPES):
            raise ValueError("{0} must be a list".format(name))
        return value


class SetField(MutableFieldMixin, BaseField):
    default = staticmethod(lambda: [])

    def validate(self, instance, name, value):
        value = super(SetField, self).validate(instance, name, value)
        if isinstance(value, set):
            return value

        if not isinstance(value, SEQUENCE_TYPES):