# Path: src/rest_toolkit/compat.py
# def add_metaclass(metaclass):
#     """Class decorator for creating a class with a metaclass."""
#     def wrapper(cls):
#         orig_vars = cls.__dict__.copy()
#         orig_vars.pop('__dict__', None)
#         orig_vars.pop('__weakref__', None)
#         slots = orig_vars.get('__slots__')
#         if slots is not None:
#             if isinstance(slots, str):
#                 slots = [slots]
#             for slots_var in slots:
#                 orig_vars.pop(slots_var)
#         return metaclass(cls.__name__, cls.__bases__, orig_vars)
#     return wrapper
# 
# Path: src/rest_toolkit/utils.py
# def merge(base, overlay):
#     """Recursively merge two dictionaries.
# 
#     This function merges two dictionaries. It is intended to be used to
#     (re)create the full new state of a resource based on its current
#     state and any changes passed in via a PATCH request. The merge rules
#     are:
# 
#     * if a key `k` is present in `base` but missing in `overlay` it is
#       untouched.
#     * if a key `k` is present in both `base` and `overlay`:
# 
#       - and `base[k]` and `overlay[k]` are both dictionaries merge is
#         applied recursively,
#       - otherwise to value in `overlay` is used.
# 
#     * if a key `k` is not present in `base`, but is present in `overlay`
#       it the value from `overlay` will be used.
# 
#     .. code-block:: python
# 
#        >>> merge({'foo': 'bar'}, {'foo': 'buz'})
#        {'foo': 'buz'}
#        >>> merge(['foo': 'bar'}, {'buz': True})
#        {'foo': 'bar', 'buz': True}
# 
#     :param dict base: Dictionary with default data.
#     :param dict overlay: Dictioanry with data to overlay on top of `base`.
#     :rtype: dict
#     :return: A copy of `base` with data from `overlay` added.
#     """
#     new_base = base.copy()
#     for (key, new_value) in overlay.items():
#         old_value = new_base.get(key, _marker)
#         if old_value is _marker:
#             new_base[key] = new_value
#         elif isinstance(old_value, dict):
#             if isinstance(new_value, dict):
#                 new_base[key] = merge(old_value, new_value)
#             else:
#                 new_base[key] = new_value
#         else:
#             new_base[key] = new_value
#     return new_base


import abc
from .compat import add_metaclass
from .utils import merge
        the data for the response.
        """
        raise NotImplementedError()

    @abc.abstractmethod
    def update_from_dict(self, data, replace):
        """Update a resource.

        :param dict data: The data to validate. The data is usually taken
            directly from JSON send by a client.
        :param bool replace: Indicates if the provided data should fully
            replace the resource state (as should be done for a PUT request),
            or if only provided keys should be updated (as should be done
            for a PATCH request).
        """
        raise NotImplementedError()

    def complete_partial_data(self, data):
        """
        Complete partial object data.

        This method will be used by the validation extension to create a
        complete data overview from partial information, as submitted in
        a PATCH request, before trying to validate it.

        :param dict data: The partial data to extend. The data is usually taken
            directly from a PATCH request. This dictionary will not be modified.
        :rtype: dict
        :return: a new dictionary with the complete data for the resource.
        """

# Path: src/rest_toolkit/compat.py
# def add_metaclass(metaclass):
#     """Class decorator for creating a class with a metaclass."""
#     def wrapper(cls):
#         orig_vars = cls.__dict__.copy()
#         orig_vars.pop('__dict__', None)
#         orig_vars.pop('__weakref__', None)
#         slots = orig_vars.get('__slots__')
#         if slots is not None:
#             if isinstance(slots, str):
#                 slots = [slots]
#             for slots_var in slots:
#                 orig_vars.pop(slots_var)
#         return metaclass(cls.__name__, cls.__bases__, orig_vars)
#     return wrapper
# 
# Path: src/rest_toolkit/utils.py
# def merge(base, overlay):
#     """Recursively merge two dictionaries.
# 
#     This function merges two dictionaries. It is intended to be used to
#     (re)create the full new state of a resource based on its current
#     state and any changes passed in via a PATCH request. The merge rules
#     are:
# 
#     * if a key `k` is present in `base` but missing in `overlay` it is
#       untouched.
#     * if a key `k` is present in both `base` and `overlay`:
# 
#       - and `base[k]` and `overlay[k]` are both dictionaries merge is
#         applied recursively,
#       - otherwise to value in `overlay` is used.
# 
#     * if a key `k` is not present in `base`, but is present in `overlay`
#       it the value from `overlay` will be used.
# 
#     .. code-block:: python
# 
#        >>> merge({'foo': 'bar'}, {'foo': 'buz'})
#        {'foo': 'buz'}
#        >>> merge(['foo': 'bar'}, {'buz': True})
#        {'foo': 'bar', 'buz': True}
# 
#     :param dict base: Dictionary with default data.
#     :param dict overlay: Dictioanry with data to overlay on top of `base`.
#     :rtype: dict
#     :return: A copy of `base` with data from `overlay` added.
#     """
#     new_base = base.copy()
#     for (key, new_value) in overlay.items():
#         old_value = new_base.get(key, _marker)
#         if old_value is _marker:
#             new_base[key] = new_value
#         elif isinstance(old_value, dict):
#             if isinstance(new_value, dict):
#                 new_base[key] = merge(old_value, new_value)
#             else:
#                 new_base[key] = new_value
#         else:
#             new_base[key] = new_value
#     return new_base


# Path: src/rest_toolkit/abc.py
import abc
from .compat import add_metaclass
from .utils import merge

        the data for the response.
        """
        raise NotImplementedError()

    @abc.abstractmethod
    def update_from_dict(self, data, replace):
        """Update a resource.

        :param dict data: The data to validate. The data is usually taken
            directly from JSON send by a client.
        :param bool replace: Indicates if the provided data should fully
            replace the resource state (as should be done for a PUT request),
            or if only provided keys should be updated (as should be done
            for a PATCH request).
        """
        raise NotImplementedError()

    def complete_partial_data(self, data):
        """
        Complete partial object data.

        This method will be used by the validation extension to create a
        complete data overview from partial information, as submitted in
        a PATCH request, before trying to validate it.

        :param dict data: The partial data to extend. The data is usually taken
            directly from a PATCH request. This dictionary will not be modified.
        :rtype: dict
        :return: a new dictionary with the complete data for the resource.
        """

        return merge(self.to_dict(), data)