# Path: invenio_deposit/errors.py
# class MergeConflict(RESTException):
#     """Error on merging a deposit."""
# 
#     code = 409
#     description = 'Deposit merge conflicts.'
# 
# Path: invenio_deposit/fetchers.py
# def deposit_fetcher(record_uuid, data):
#     """Fetch a deposit identifier.
# 
#     :param record_uuid: Record UUID.
#     :param data: Record content.
#     :returns: A :class:`invenio_pidstore.fetchers.FetchedPID` that contains
#         data['_deposit']['id'] as pid_value.
#     """
#     return FetchedPID(
#         provider=DepositProvider,
#         pid_type=DepositProvider.pid_type,
#         pid_value=str(data['_deposit']['id']),
#     )
# 
# Path: invenio_deposit/minters.py
# def deposit_minter(record_uuid, data):
#     """Mint a deposit identifier.
# 
#     A PID with the following characteristics is created:
# 
#     .. code-block:: python
# 
#         {
#             "object_type": "rec",
#             "object_uuid": record_uuid,
#             "pid_value": "<new-pid-value>",
#             "pid_type": "depid",
#         }
# 
#     The following deposit meta information are updated:
# 
#     .. code-block:: python
# 
#         deposit['_deposit'] = {
#             "id": "<new-pid-value>",
#             "status": "draft",
#         }
# 
#     :param record_uuid: Record UUID.
#     :param data: Record content.
#     :returns: A :class:`invenio_pidstore.models.PersistentIdentifier` object.
#     """
#     provider = DepositProvider.create(
#         object_type='rec',
#         object_uuid=record_uuid,
#         pid_value=uuid.uuid4().hex,
#     )
#     data['_deposit'] = {
#         'id': provider.pid.pid_value,
#         'status': 'draft',
#     }
#     return provider.pid
# 
# Path: invenio_deposit/utils.py
# def mark_as_action(f):
#     """Decorator for marking method as deposit action.
# 
#     Allows creation of new REST API action on ``Deposit`` subclass.
#     Following example shows possible `cloning` of a deposit instance.
# 
#     .. code-block:: python
# 
#         from invenio_deposit.api import Deposit
# 
#         class CustomDeposit(Deposit):
#             @mark_as_action
#             def clone(self, pid=None):
#                 new_bucket = self.files.bucket.clone()
#                 new_deposit = Deposit.create(self.dumps())
#                 new_deposit.files.bucket = new_bucket
#                 new_deposit.commit()
# 
#             @mark_as_action
#             def edit(self, pid=None):
#                 # Extend existing action.
#                 self['_last_editor'] = current_user.get_id()
#                 return super(CustomDeposit, self).edit(pid=pid)
# 
#             # Disable publish action from REST API.
#             def publish(self, pid=None):
#                 return super(CustomDeposit, self).publish(pid=pid)
# 
#     :param f: Decorated method.
#     """
#     f.__deposit_action__ = True
#     return f


import uuid
from contextlib import contextmanager
from copy import deepcopy
from functools import partial, wraps
from dictdiffer import patch
from dictdiffer.merge import Merger, UnresolvedConflictsException
from elasticsearch.exceptions import RequestError
from flask import current_app
from flask_login import current_user
from invenio_db import db
from invenio_files_rest.models import Bucket
from invenio_indexer.api import RecordIndexer
from invenio_pidstore import current_pidstore
from invenio_pidstore.errors import PIDInvalidAction
from invenio_pidstore.models import PersistentIdentifier, PIDStatus
from invenio_pidstore.resolver import Resolver
from invenio_records.signals import after_record_update, before_record_update
from invenio_records_files.api import Record
from invenio_records_files.models import RecordsBuckets
from sqlalchemy.orm.attributes import flag_modified
from werkzeug.local import LocalProxy
from .errors import MergeConflict
from .fetchers import deposit_fetcher as default_deposit_fetcher
from .minters import deposit_minter as default_deposit_minter
from .utils import mark_as_action
    :param result: If `True` returns the result of method execution,
        otherwise `self`. (Default: ``True``)
    :param fields: List of fields to preserve (default: ``('_deposit',)``).
    """
    if method is None:
        return partial(preserve, result=result, fields=fields)

    fields = fields or ('_deposit', )

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        """Check current deposit status."""
        data = {field: self[field] for field in fields if field in self}
        result_ = method(self, *args, **kwargs)
        replace = result_ if result else self
        for field in data:
            replace[field] = data[field]
        return result_
    return wrapper


class Deposit(Record):
    """Define API for changing deposit state."""

    indexer = RecordIndexer()
    """Default deposit indexer."""

    published_record_class = Record
    """The Record API class used for published records."""


# Path: invenio_deposit/errors.py
# class MergeConflict(RESTException):
#     """Error on merging a deposit."""
# 
#     code = 409
#     description = 'Deposit merge conflicts.'
# 
# Path: invenio_deposit/fetchers.py
# def deposit_fetcher(record_uuid, data):
#     """Fetch a deposit identifier.
# 
#     :param record_uuid: Record UUID.
#     :param data: Record content.
#     :returns: A :class:`invenio_pidstore.fetchers.FetchedPID` that contains
#         data['_deposit']['id'] as pid_value.
#     """
#     return FetchedPID(
#         provider=DepositProvider,
#         pid_type=DepositProvider.pid_type,
#         pid_value=str(data['_deposit']['id']),
#     )
# 
# Path: invenio_deposit/minters.py
# def deposit_minter(record_uuid, data):
#     """Mint a deposit identifier.
# 
#     A PID with the following characteristics is created:
# 
#     .. code-block:: python
# 
#         {
#             "object_type": "rec",
#             "object_uuid": record_uuid,
#             "pid_value": "<new-pid-value>",
#             "pid_type": "depid",
#         }
# 
#     The following deposit meta information are updated:
# 
#     .. code-block:: python
# 
#         deposit['_deposit'] = {
#             "id": "<new-pid-value>",
#             "status": "draft",
#         }
# 
#     :param record_uuid: Record UUID.
#     :param data: Record content.
#     :returns: A :class:`invenio_pidstore.models.PersistentIdentifier` object.
#     """
#     provider = DepositProvider.create(
#         object_type='rec',
#         object_uuid=record_uuid,
#         pid_value=uuid.uuid4().hex,
#     )
#     data['_deposit'] = {
#         'id': provider.pid.pid_value,
#         'status': 'draft',
#     }
#     return provider.pid
# 
# Path: invenio_deposit/utils.py
# def mark_as_action(f):
#     """Decorator for marking method as deposit action.
# 
#     Allows creation of new REST API action on ``Deposit`` subclass.
#     Following example shows possible `cloning` of a deposit instance.
# 
#     .. code-block:: python
# 
#         from invenio_deposit.api import Deposit
# 
#         class CustomDeposit(Deposit):
#             @mark_as_action
#             def clone(self, pid=None):
#                 new_bucket = self.files.bucket.clone()
#                 new_deposit = Deposit.create(self.dumps())
#                 new_deposit.files.bucket = new_bucket
#                 new_deposit.commit()
# 
#             @mark_as_action
#             def edit(self, pid=None):
#                 # Extend existing action.
#                 self['_last_editor'] = current_user.get_id()
#                 return super(CustomDeposit, self).edit(pid=pid)
# 
#             # Disable publish action from REST API.
#             def publish(self, pid=None):
#                 return super(CustomDeposit, self).publish(pid=pid)
# 
#     :param f: Decorated method.
#     """
#     f.__deposit_action__ = True
#     return f


# Path: invenio_deposit/api.py
import uuid
from contextlib import contextmanager
from copy import deepcopy
from functools import partial, wraps
from dictdiffer import patch
from dictdiffer.merge import Merger, UnresolvedConflictsException
from elasticsearch.exceptions import RequestError
from flask import current_app
from flask_login import current_user
from invenio_db import db
from invenio_files_rest.models import Bucket
from invenio_indexer.api import RecordIndexer
from invenio_pidstore import current_pidstore
from invenio_pidstore.errors import PIDInvalidAction
from invenio_pidstore.models import PersistentIdentifier, PIDStatus
from invenio_pidstore.resolver import Resolver
from invenio_records.signals import after_record_update, before_record_update
from invenio_records_files.api import Record
from invenio_records_files.models import RecordsBuckets
from sqlalchemy.orm.attributes import flag_modified
from werkzeug.local import LocalProxy
from .errors import MergeConflict
from .fetchers import deposit_fetcher as default_deposit_fetcher
from .minters import deposit_minter as default_deposit_minter
from .utils import mark_as_action

    :param result: If `True` returns the result of method execution,
        otherwise `self`. (Default: ``True``)
    :param fields: List of fields to preserve (default: ``('_deposit',)``).
    """
    if method is None:
        return partial(preserve, result=result, fields=fields)

    fields = fields or ('_deposit', )

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        """Check current deposit status."""
        data = {field: self[field] for field in fields if field in self}
        result_ = method(self, *args, **kwargs)
        replace = result_ if result else self
        for field in data:
            replace[field] = data[field]
        return result_
    return wrapper


class Deposit(Record):
    """Define API for changing deposit state."""

    indexer = RecordIndexer()
    """Default deposit indexer."""

    published_record_class = Record
    """The Record API class used for published records."""


    deposit_fetcher = staticmethod(default_deposit_fetcher)