Beispiel #1
0
    def create_pids(cls, dump, deposit):
        """Create a persistent identifiers."""
        # Mark deposit deleted if recid is deleted.
        recid = dump.recid_pid
        # Create depid
        depid = PersistentIdentifier.create(pid_type='depid',
                                            pid_value=str(dump.depid),
                                            object_type='rec',
                                            object_uuid=deposit.id,
                                            status=PIDStatus.REGISTERED)
        if recid and recid.status == PIDStatus.DELETED:
            depid.delete()
        if RecordIdentifier.query.get(dump.depid) is None:
            RecordIdentifier.insert(dump.depid)

        # Pre-reserved recid.
        if not recid and dump.recid:
            if dump.has_pid:
                # Published deposit without a recid (this is an upload which
                # never got ingested so we set it back to draft status and
                # reserves the reid).
                pass
            recid = PersistentIdentifier.create(pid_type='recid',
                                                pid_value=str(dump.recid),
                                                status=PIDStatus.RESERVED)
            if RecordIdentifier.query.get(dump.recid) is None:
                RecordIdentifier.insert(dump.recid)

        return depid, recid
Beispiel #2
0
def weko_deposit_minter(record_uuid, data, recid=None):
    """Weko deposit."""
    if not recid:
        id_ = RecordIdentifier.next()
    else:
        if isinstance(recid, int):
            RecordIdentifier.insert(recid)
        id_ = recid
    recid = PersistentIdentifier.create('recid',
                                        str(id_),
                                        object_type='rec',
                                        object_uuid=record_uuid,
                                        status=PIDStatus.REGISTERED)
    data['recid'] = str(recid.pid_value)

    # Create depid with same pid_value of the recid
    depid = PersistentIdentifier.create(
        'depid',
        str(recid.pid_value),
        object_type='rec',
        object_uuid=record_uuid,
        status=PIDStatus.REGISTERED,
    )

    data.update({
        '_deposit': {
            'id': depid.pid_value,
            'status': 'draft',
        },
    })
    return depid
Beispiel #3
0
def create_record_and_pid(data):
    """Create the deposit record metadata and persistent identifier.

    :param data: Raw JSON dump of the deposit.
    :type data: dict
    :returns: A deposit object and its pid
    :rtype: (`invenio_records.api.Record`,
             `invenio_pidstore.models.PersistentIdentifier`)
    """
    from invenio_records.api import Record
    from invenio_pidstore.models import PersistentIdentifier, PIDStatus

    deposit = Record.create(data=data)

    created = arrow.get(data['_p']['created']).datetime
    deposit.model.created = created.replace(tzinfo=None)
    depid = deposit['_p']['id']
    pid = PersistentIdentifier.create(pid_type='depid',
                                      pid_value=str(depid),
                                      object_type='rec',
                                      object_uuid=str(deposit.id),
                                      status=PIDStatus.REGISTERED)
    if RecordIdentifier.query.get(int(depid)) is None:
        RecordIdentifier.insert(int(depid))
    deposit.commit()
    return deposit, pid
Beispiel #4
0
    def create_pids(cls, dump, deposit):
        """Create a persistent identifiers."""
        # Mark deposit deleted if recid is deleted.
        recid = dump.recid_pid
        # Create depid
        depid = PersistentIdentifier.create(
            pid_type='depid',
            pid_value=str(dump.depid),
            object_type='rec',
            object_uuid=deposit.id,
            status=PIDStatus.REGISTERED
        )
        if recid and recid.status == PIDStatus.DELETED:
            depid.delete()
        if RecordIdentifier.query.get(dump.depid) is None:
            RecordIdentifier.insert(dump.depid)

        # Pre-reserved recid.
        if not recid and dump.recid:
            if dump.has_pid:
                # Published deposit without a recid (this is an upload which
                # never got ingested so we set it back to draft status and
                # reserves the reid).
                pass
            recid = PersistentIdentifier.create(
                pid_type='recid',
                pid_value=str(dump.recid),
                status=PIDStatus.RESERVED
            )
            if RecordIdentifier.query.get(dump.recid) is None:
                RecordIdentifier.insert(dump.recid)

        return depid, recid
Beispiel #5
0
def minter(pid_type, pid_field, record):
    """Mint the given PID for the given record."""
    PersistentIdentifier.create(
        pid_type=pid_type,
        pid_value=record[pid_field],
        object_type="rec",
        object_uuid=record.id,
        status=PIDStatus.REGISTERED,
    )
    RecordIdentifier.next()
Beispiel #6
0
def record_db(db):
    """Load records json."""
    id_ = uuid.uuid4()
    record = Record.create({'title': 'Test record', 'recid': 11782}, id_=id_)
    PersistentIdentifier.create(
        pid_type='recid',
        pid_value='11782',
        status=PIDStatus.REGISTERED,
        object_type='rec',
        object_uuid=id_,
    )
    RecordIdentifier.insert(11782)
    db.session.commit()
    return record
Beispiel #7
0
 def create_record(cls, dump):
     """Create a new record from dump."""
     # Reserve record identifier, create record and recid pid in one
     # operation.
     timestamp, data = dump.pop_first_revision()
     record = Record.create(data)
     record.model.created = timestamp.replace(tzinfo=None)
     RecordIdentifier.insert(dump.recid)
     PersistentIdentifier.create(pid_type='recid',
                                 pid_value=str(dump.recid),
                                 object_type='rec',
                                 object_uuid=str(record.id),
                                 status=PIDStatus.REGISTERED)
     db.session.commit()
     return cls.update_record(dump, record=record)
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier."""
        # Request next integer in recid sequence.
        assert 'pid_value' not in kwargs

        provider_url = current_app.config.get('RECORDS_ID_PROVIDER_ENDPOINT',
                                              None)
        if not provider_url:
            # Don't query external service in DEBUG mode
            kwargs['pid_value'] = str(RecordIdentifier.next())
        else:
            response = requests.get(provider_url,
                                    headers={'User-Agent': 'cernsearch'})

            if not response.ok or response.text.strip().startswith('[ERROR]'):
                raise PersistentIdentifierError(response.text)

            kwargs['pid_value'] = response.text

        kwargs.setdefault('status', cls.default_status)
        if object_type and object_uuid:
            kwargs['status'] = PIDStatus.REGISTERED

        return super(CERNSearchRecordIdProvider,
                     cls).create(object_type=object_type,
                                 object_uuid=object_uuid,
                                 **kwargs)
Beispiel #9
0
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier.

        Note: if the object_type and object_uuid values are passed, then the
        PID status will be automatically setted to
        :attr:`invenio_pidstore.models.PIDStatus.REGISTERED`.
        :param object_type: The object type. (Default: None.)
        :param object_uuid: The object identifier. (Default: None).
        :param kwargs: You specify the pid_value.
        """
        # PID value not already exists, generating a new one
        if not kwargs.get('pid_value'):
            kwargs['pid_value'] = str(RecordIdentifier.next())

        kwargs.setdefault('status', cls.default_status)
        if object_type and object_uuid:
            kwargs['status'] = PIDStatus.REGISTERED

        try:
            # Try to retreive PID
            return cls.get(kwargs['pid_value'], cls.pid_type)
        except PIDDoesNotExistError:
            # Set default status
            kwargs.setdefault('status', cls.default_status)

            # if record is registered, change PID status
            if object_type and object_uuid:
                kwargs['status'] = PIDStatus.REGISTERED

            # Call base provider
            return super(Provider, cls).create(
                object_type=object_type, object_uuid=object_uuid, **kwargs
            )
Beispiel #10
0
def weko_deposit_minter(record_uuid, data):
    """Weko deposit."""
    id_ = RecordIdentifier.next()
    recid = PersistentIdentifier.create('recid',
                                        str(id_),
                                        object_type='rec',
                                        object_uuid=record_uuid,
                                        status=PIDStatus.REGISTERED)

    # Create depid with same pid_value of the recid
    depid = PersistentIdentifier.create(
        'depid',
        str(recid.pid_value),
        object_type='rec',
        object_uuid=record_uuid,
        status=PIDStatus.REGISTERED,
    )

    data.update({
        '_deposit': {
            'id': depid.pid_value,
            'status': 'draft',
        },
    })
    return depid
Beispiel #11
0
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier."""
        # Request next integer in recid sequence.
        assert 'pid_value' not in kwargs

        if current_app.config.get('DEBUG'):
            # Don't query external service in DEBUG mode
            kwargs['pid_value'] = str(RecordIdentifier.next())
        else:
            response = requests.get(
                current_app.config['RECORDS_ID_PROVIDER_ENDPOINT'],
                headers={
                    'User-Agent': 'cdslabs'
                }).text

            if response.strip().lower().startswith('[error]'):
                raise PersistentIdentifierError(response)

            kwargs['pid_value'] = response

        kwargs.setdefault('status', cls.default_status)
        if object_type and object_uuid:
            kwargs['status'] = PIDStatus.REGISTERED
        return super(CDSRecordIdProvider, cls).create(object_type=object_type,
                                                      object_uuid=object_uuid,
                                                      **kwargs)
 def create_record(cls, dump):
     """Create a new record from dump."""
     # Reserve record identifier, create record and recid pid in one
     # operation.
     timestamp, data = dump.pop_first_revision()
     record = Record.create(data)
     record.model.created = timestamp.replace(tzinfo=None)
     RecordIdentifier.insert(dump.recid)
     PersistentIdentifier.create(
         pid_type='recid',
         pid_value=str(dump.recid),
         object_type='rec',
         object_uuid=str(record.id),
         status=PIDStatus.REGISTERED
     )
     db.session.commit()
     return cls.update_record(dump, record=record)
Beispiel #13
0
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier."""
        if "pid_value" not in kwargs:
            if current_app.config.get("LEGACY_PID_PROVIDER"):
                kwargs["pid_value"] = get_next_pid_from_legacy()
                RecordIdentifier.insert(kwargs["pid_value"])
            else:
                kwargs["pid_value"] = RecordIdentifier.next()
        else:
            RecordIdentifier.insert(kwargs["pid_value"])

        kwargs.setdefault("status", cls.default_status)
        if object_type and object_uuid:
            kwargs["status"] = PIDStatus.REGISTERED
        return super(InspireRecordIdProvider, cls).create(
            object_type=object_type, object_uuid=object_uuid, **kwargs
        )
Beispiel #14
0
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier."""
        # Request next integer in recid sequence.
        if 'pid_value' not in kwargs:
            if current_app.config.get('LEGACY_PID_PROVIDER'):
                kwargs['pid_value'] = _get_next_pid_from_legacy()
                RecordIdentifier.insert(kwargs['pid_value'])
            else:
                kwargs['pid_value'] = RecordIdentifier.next()
        else:
            RecordIdentifier.insert(kwargs['pid_value'])

        kwargs.setdefault('status', cls.default_status)
        if object_type and object_uuid:
            kwargs['status'] = PIDStatus.REGISTERED
        return super(InspireRecordIdProvider, cls).create(
            object_type=object_type, object_uuid=object_uuid, **kwargs)
Beispiel #15
0
def record_db(db):
    """Load records json."""
    id_ = uuid.uuid4()
    record = Record.create({
        'title': 'Test record',
        'recid': 11782
    }, id_=id_)
    PersistentIdentifier.create(
        pid_type='recid',
        pid_value='11782',
        status=PIDStatus.REGISTERED,
        object_type='rec',
        object_uuid=id_,
    )
    RecordIdentifier.insert(11782)
    db.session.commit()
    return record
Beispiel #16
0
 def create(cls, object_type=None, object_uuid=None, **kwargs):
     # Request next integer in recid sequence.
     kwargs['pid_value'] = str(RecordIdentifier.next())
     kwargs.setdefault('status', cls.default_status)
     return super(RecordIdProvider,
                  cls).create(object_type=object_type,
                              object_uuid=object_uuid,
                              **kwargs)
Beispiel #17
0
def default_parent_minter(record_uuid, data, pid_type, object_type):
    """Basic RecordIdentifier-based minter for parent PIDs."""
    parent_id = RecordIdentifier.next()
    return PersistentIdentifier.create(
        pid_type=pid_type,
        pid_value=str(parent_id),
        object_type=object_type,
        status=PIDStatus.REGISTERED,
    )
Beispiel #18
0
def zenodo_reserved_record_minter(record_uuid=None, data=None):
    """Reserve a recid."""
    id_ = RecordIdentifier.next()
    recid = PersistentIdentifier.create('recid',
                                        str(id_),
                                        status=PIDStatus.RESERVED)
    data['recid'] = int(recid.pid_value)

    return recid
Beispiel #19
0
def zenodo_reserved_record_minter(record_uuid=None, data=None):
    """Reserve a recid."""
    id_ = RecordIdentifier.next()
    recid = PersistentIdentifier.create(
        'recid', id_, status=PIDStatus.RESERVED
    )
    data['recid'] = recid.pid_value

    return recid
def test_record_resolution(app, db):
    """Test resolution of PIDs to records."""
    # OK PID
    pid_ok, record = create_record({'title': 'test'})

    # Deleted PID
    pid_del, record = create_record({'title': 'deleted'})
    pid_del.delete()

    # Missing object PID
    pid_noobj = PersistentIdentifier.create(
        'recid', str(RecordIdentifier.next()), status=PIDStatus.REGISTERED)
    db.session.commit()

    # Redirected PID
    pid_red = PersistentIdentifier.create(
        'recid', '101', status=PIDStatus.REGISTERED)
    pid_red.redirect(pid_ok)

    # Redirect PID - different endpoint
    pid_doi = PersistentIdentifier.create(
        'doi', '10.1234/foo', status=PIDStatus.REGISTERED)
    pid_red_doi = PersistentIdentifier.create(
        'recid', '102', status=PIDStatus.REGISTERED)
    pid_red_doi.redirect(pid_doi)
    db.session.commit()

    headers = [('Accept', 'application/json')]
    with app.test_client() as client:
        # PID deleted
        res = client.get(
            url_for('invenio_records_rest.recid_item',
                    pid_value=pid_del.pid_value),
            headers=headers)
        assert res.status_code == 410

        # PID missing object
        res = client.get(
            url_for('invenio_records_rest.recid_item',
                    pid_value=pid_noobj.pid_value),
            headers=headers)
        assert res.status_code == 500

        # Redirected invalid endpoint
        res = client.get(
            url_for('invenio_records_rest.recid_item',
                    pid_value=pid_red_doi.pid_value),
            headers=headers)
        assert res.status_code == 500

        # Redirected
        res = client.get(
            url_for('invenio_records_rest.recid_item',
                    pid_value=pid_red.pid_value),
            headers=headers)
        assert res.status_code == 301
Beispiel #21
0
def test_record_resolution(app, db):
    """Test resolution of PIDs to records."""
    # OK PID
    pid_ok, record = create_record({'title': 'test'})

    # Deleted PID
    pid_del, record = create_record({'title': 'deleted'})
    pid_del.delete()

    # Missing object PID
    pid_noobj = PersistentIdentifier.create('recid',
                                            str(RecordIdentifier.next()),
                                            status=PIDStatus.REGISTERED)
    db.session.commit()

    # Redirected PID
    pid_red = PersistentIdentifier.create('recid',
                                          '101',
                                          status=PIDStatus.REGISTERED)
    pid_red.redirect(pid_ok)

    # Redirect PID - different endpoint
    pid_doi = PersistentIdentifier.create('doi',
                                          '10.1234/foo',
                                          status=PIDStatus.REGISTERED)
    pid_red_doi = PersistentIdentifier.create('recid',
                                              '102',
                                              status=PIDStatus.REGISTERED)
    pid_red_doi.redirect(pid_doi)
    db.session.commit()

    headers = [('Accept', 'application/json')]
    with app.test_client() as client:
        # PID deleted
        res = client.get(url_for('invenio_records_rest.recid_item',
                                 pid_value=pid_del.pid_value),
                         headers=headers)
        assert res.status_code == 410

        # PID missing object
        res = client.get(url_for('invenio_records_rest.recid_item',
                                 pid_value=pid_noobj.pid_value),
                         headers=headers)
        assert res.status_code == 500

        # Redirected invalid endpoint
        res = client.get(url_for('invenio_records_rest.recid_item',
                                 pid_value=pid_red_doi.pid_value),
                         headers=headers)
        assert res.status_code == 500

        # Redirected
        res = client.get(url_for('invenio_records_rest.recid_item',
                                 pid_value=pid_red.pid_value),
                         headers=headers)
        assert res.status_code == 301
Beispiel #22
0
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier."""
        # Request next integer in recid sequence.
        if 'pid_value' not in kwargs:
            if current_app.config.get('LEGACY_PID_PROVIDER'):
                kwargs['pid_value'] = _get_next_pid_from_legacy()
                RecordIdentifier.insert(kwargs['pid_value'])
            else:
                kwargs['pid_value'] = RecordIdentifier.next()
        else:
            RecordIdentifier.insert(kwargs['pid_value'])

        kwargs.setdefault('status', cls.default_status)
        if object_type and object_uuid:
            kwargs['status'] = PIDStatus.REGISTERED
        return super(InspireRecordIdProvider,
                     cls).create(object_type=object_type,
                                 object_uuid=object_uuid,
                                 **kwargs)
Beispiel #23
0
 def create(cls, object_type=None, object_uuid=None, **kwargs):
     """Create a new record identifier."""
     # Request next integer in recid sequence.
     if 'pid_value' not in kwargs:
         kwargs['pid_value'] = str(RecordIdentifier.next())
     kwargs.setdefault('status', cls.default_status)
     if object_type and object_uuid:
         kwargs['status'] = PIDStatus.REGISTERED
     return super(SCOAP3RecordIdProvider, cls).create(
         object_type=object_type, object_uuid=object_uuid, **kwargs)
Beispiel #24
0
def zenodo_deposit_minter(record_uuid, data):
    """Mint a deposit identifier."""
    provider = ZenodoDepositProvider.create(
        object_type='rec',
        object_uuid=record_uuid,
        pid_value=RecordIdentifier.next(),
    )
    data['_deposit'] = {
        'id': provider.pid.pid_value,
        'status': 'draft',
    }
    return provider.pid
Beispiel #25
0
 def create(cls, object_type=None, object_uuid=None, **kwargs):
     """Create a new record identifier."""
     # Request next integer in recid sequence.
     if 'pid_value' not in kwargs:
         kwargs['pid_value'] = str(RecordIdentifier.next())
     kwargs.setdefault('status', cls.default_status)
     if object_type and object_uuid:
         kwargs['status'] = PIDStatus.REGISTERED
     return super(SCOAP3RecordIdProvider,
                  cls).create(object_type=object_type,
                              object_uuid=object_uuid,
                              **kwargs)
Beispiel #26
0
def zenodo_concept_recid_minter(record_uuid=None, data=None):
    """Mint the Concept RECID.

    Reserves the Concept RECID for the record.
    """
    parent_id = RecordIdentifier.next()
    conceptrecid = PersistentIdentifier.create(
        pid_type='recid',
        pid_value=str(parent_id),
        status=PIDStatus.RESERVED,
    )
    data['conceptrecid'] = conceptrecid.pid_value
    return conceptrecid
Beispiel #27
0
def zenodo_concept_recid_minter(record_uuid=None, data=None):
    """Mint the Concept RECID.

    Reserves the Concept RECID for the record.
    """
    parent_id = RecordIdentifier.next()
    conceptrecid = PersistentIdentifier.create(
        pid_type='recid',
        pid_value=str(parent_id),
        status=PIDStatus.RESERVED,
    )
    data['conceptrecid'] = conceptrecid.pid_value
    return conceptrecid
Beispiel #28
0
    def create(cls, object_type=None, object_uuid=None, **kwargs):
        """Create a new record identifier."""
        pid_value = kwargs.get("pid_value")
        if pid_value is None:
            if current_app.config.get("LEGACY_PID_PROVIDER"):
                kwargs["pid_value"] = get_next_pid_from_legacy()
                LOGGER.info("Control number from legacy",
                            recid=kwargs["pid_value"])
                RecordIdentifier.insert(kwargs["pid_value"])
            else:
                kwargs["pid_value"] = str(RecordIdentifier.next())
                LOGGER.info("Control number from RecordIdentifier",
                            recid=kwargs["pid_value"])
        else:
            LOGGER.info("Control number provided", recid=kwargs["pid_value"])
            RecordIdentifier.insert(kwargs["pid_value"])

        kwargs.setdefault("status", cls.default_status)
        if object_type and object_uuid:
            kwargs["status"] = PIDStatus.REGISTERED
        return super().create(object_type=object_type,
                              object_uuid=object_uuid,
                              **kwargs)
Beispiel #29
0
def _migrate_recid(d):
    """Migrate the recid information."""
    depid = d['_n']['_deposit']['id']
    pid = d['_n']['_deposit'].get('pid')
    if pid:
        d['_n']['recid'] = int(pid['value'])
    else:
        # Create a recid if we don't have one - try to reserve identical
        # number.
        try:
            PersistentIdentifier.get('recid', depid)
            id_ = str(RecordIdentifier.next())
        except PIDDoesNotExistError:
            id_ = str(depid)
        PersistentIdentifier.create('recid', id_, status=PIDStatus.RESERVED)
        d['_n']['recid'] = int(id_)
    return d
Beispiel #30
0
 def create(cls, object_type=None, object_uuid=None, **kwargs):
     """Create a new record identifier.
     Note: if the object_type and object_uuid values are passed, then the
     PID status will be automatically setted to
     :attr:`invenio_pidstore.models.PIDStatus.REGISTERED`.
     :param object_type: The object type. (Default: None.)
     :param object_uuid: The object identifier. (Default: None).
     :param kwargs: You specify the pid_value.
     """
     # Request next integer in recid sequence.
     assert 'pid_value' not in kwargs
     kwargs['pid_value'] = str(RecordIdentifier.next())
     kwargs.setdefault('status', cls.default_status)
     if object_type and object_uuid:
         kwargs['status'] = PIDStatus.REGISTERED
     return super(DepositUUIDProvider, cls).create(
         object_type=object_type, object_uuid=object_uuid, **kwargs)
Beispiel #31
0
def _migrate_recid(d):
    """Migrate the recid information."""
    depid = d['_n']['_deposit']['id']
    pid = d['_n']['_deposit'].get('pid')
    if pid:
        d['_n']['recid'] = int(pid['value'])
    else:
        # Create a recid if we don't have one - try to reserve identical
        # number.
        try:
            PersistentIdentifier.get('recid', depid)
            id_ = str(RecordIdentifier.next())
        except PIDDoesNotExistError:
            id_ = str(depid)
        PersistentIdentifier.create('recid', id_, status=PIDStatus.RESERVED)
        d['_n']['recid'] = int(id_)
    return d
Beispiel #32
0
def zenodo_deposit_minter(record_uuid, data):
    """Mint deposit identifier."""
    id_ = RecordIdentifier.next()
    depid = PersistentIdentifier.create(
        'depid',
        str(id_),
        object_type='rec',
        object_uuid=record_uuid,
        status=PIDStatus.REGISTERED,
    )
    # Reserve recid with same number.
    PersistentIdentifier.create('recid',
                                depid.pid_value,
                                status=PIDStatus.RESERVED)
    data.update({
        '_deposit': {
            'id': depid.pid_value,
            'status': 'draft',
        },
        'recid': id_,
    })
    return depid
Beispiel #33
0
def zenodo_deposit_minter(record_uuid, data):
    """Mint deposit identifier."""
    id_ = RecordIdentifier.next()
    depid = PersistentIdentifier.create(
        'depid',
        str(id_),
        object_type='rec',
        object_uuid=record_uuid,
        status=PIDStatus.REGISTERED,
    )
    # Reserve recid with same number.
    PersistentIdentifier.create(
        'recid', depid.pid_value,
        status=PIDStatus.RESERVED
    )
    data.update({
        '_deposit': {
            'id': depid.pid_value,
            'status': 'draft',
        },
        'recid': id_,
    })
    return depid
def test_record_identifier(app, db):
    """Test base provider."""
    with app.app_context():
        assert RecordIdentifier.next() == 1
        assert RecordIdentifier.next() == 2
        assert RecordIdentifier.max() == 2

        # Mess up the sequence
        with db.session.begin_nested():
            obj = RecordIdentifier(recid=3)
            db.session.add(obj)

        assert RecordIdentifier.max() == 3

        # This tests a particular problem on PostgreSQL which is using
        # sequences to generate auto incrementing columns and doesn't deal
        # nicely with having values inserted in the table.
        assert RecordIdentifier.next() == 4

        RecordIdentifier.insert(10)
        assert RecordIdentifier.next() == 11
        assert RecordIdentifier.max() == 11

        RecordIdentifier.insert(7)
        assert RecordIdentifier.max() == 11
        assert RecordIdentifier.next() == 12
Beispiel #35
0
def get_loans_for_items(items,
                        location,
                        patron_ids=None,
                        librarian_id="",
                        n_loans=100):
    """Return random loans."""
    loc_pid = location[Location.pid_field]
    len_patron_ids = len(patron_ids) - 1
    len_items = len(items) - 1
    LEN_LOAN_STATUSES = len(LOAN_STATUSES) - 1
    current_year = datetime.now().year

    def _get_loanable_item(items):
        """Return an item that is loanable."""
        item = items[randint(1, len_items)]
        if item["status"] != "LOANABLE":
            return _get_loanable_item(items)
        return item

    def _get_valid_status(item, items_on_loans):
        """Return valid loan status for the item to avoid inconsistencies."""
        # cannot have 2 loans in the same item
        if item[Item.pid_field] in items_on_loans:
            status = LOAN_STATUSES[0]
        else:
            status = LOAN_STATUSES[randint(0, LEN_LOAN_STATUSES)]
        return status

    loans = []
    items_on_loans = []
    for i in range(1, n_loans):
        item = _get_loanable_item(items)
        status = _get_valid_status(item, items_on_loans)
        patron_id = randint(1, len_patron_ids)
        transaction_date = datetime(current_year, randint(1, 12),
                                    randint(1, 28))
        expire_date = transaction_date + timedelta(days=10)
        start_date = transaction_date + timedelta(days=3)
        end_date = transaction_date + timedelta(days=13)

        loan = {
            Document.pid_field:
            "{}".format(ITEM_DOCUMENT_MAPPING[item[Item.pid_field]]),
            Item.pid_field:
            "{}".format(item[Item.pid_field]),
            Loan.pid_field:
            "{}".format(i),
            "patron_pid":
            "{}".format(patron_id),
            "pickup_location_pid":
            "{}".format(loc_pid),
            "request_expire_date":
            expire_date.strftime("%Y-%m-%d"),
            "state":
            "{}".format(status),
            "start_date":
            start_date.strftime("%Y-%m-%d"),
            "end_date":
            end_date.strftime("%Y-%m-%d"),
            "transaction_date":
            transaction_date.strftime("%Y-%m-%d"),
            "transaction_location_pid":
            "{}".format(loc_pid),
            "transaction_user_pid":
            "{}".format(librarian_id),
        }

        if status == "PENDING":
            loan[Item.pid_field] = ""
        else:
            loan[Item.pid_field] = "{}".format(item[Item.pid_field])
            items_on_loans.append(item[Item.pid_field])

        loans.append(loan)
    RecordIdentifier.insert(len(loans))

    return loans
Beispiel #36
0
def create_files_and_sip(deposit, dep_pid):
    """Create deposit Bucket, Files and SIPs."""
    from invenio_pidstore.errors import PIDDoesNotExistError
    from invenio_pidstore.models import PersistentIdentifier, PIDStatus
    from invenio_sipstore.errors import SIPUserDoesNotExist
    from invenio_sipstore.models import SIP, RecordSIP, SIPFile
    from invenio_files_rest.models import Bucket, FileInstance, ObjectVersion
    from invenio_records_files.models import RecordsBuckets
    from invenio_db import db
    buc = Bucket.create()
    recbuc = RecordsBuckets(record_id=deposit.id, bucket_id=buc.id)
    db.session.add(recbuc)
    deposit.setdefault('_deposit', dict())
    deposit.setdefault('_buckets', dict(deposit=str(buc.id)))
    deposit.setdefault('_files', list())
    files = deposit.get('files', [])
    sips = deposit.get('sips', [])

    # Look for prereserved DOI (and recid)
    if 'drafts' in deposit:
        drafts = list(deposit['drafts'].items())
        if len(drafts) != 1:
            logger.exception('Deposit {dep_pid} has multiple drafts'.format(
                dep_pid=dep_pid))
        if len(drafts) == 1:
            draft_type, draft = drafts[0]
            draft_v = draft['values']
            if 'prereserve_doi' in draft_v:
                pre_recid = str(draft_v['prereserve_doi']['recid'])
                pre_doi = str(draft_v['prereserve_doi']['doi'])

                # If pre-reserve info available, try to reserve 'recid'
                try:
                    pid = PersistentIdentifier.get(pid_type='recid',
                                                   pid_value=str(pre_recid))
                except PIDDoesNotExistError:
                    # Reserve recid
                    pid = PersistentIdentifier.create(
                        pid_type='recid',
                        pid_value=str(pre_recid),
                        object_type='rec',
                        status=PIDStatus.RESERVED)

                # If pre-reserve info available, try to reserve 'doi'
                try:
                    pid = PersistentIdentifier.get(pid_type='doi',
                                                   pid_value=str(pre_doi))
                except PIDDoesNotExistError:
                    # Reserve DOI
                    pid = PersistentIdentifier.create(
                        pid_type='doi',
                        pid_value=str(pre_doi),
                        object_type='rec',
                        status=PIDStatus.RESERVED)

                if RecordIdentifier.query.get(int(pre_recid)) is None:
                    RecordIdentifier.insert(int(pre_recid))

    # Store the path -> FileInstance mappings for SIPFile creation later
    dep_file_instances = list()

    for file_ in files:
        size = file_['size']
        key = file_['name']
        # Warning: Assumes all checksums are MD5!
        checksum = 'md5:{0}'.format(file_['checksum'])
        fi = FileInstance.create()
        fi.set_uri(file_['path'], size, checksum)
        ov = ObjectVersion.create(buc, key, _file_id=fi.id)
        ext = splitext(ov.key)[1].lower()
        if ext.startswith('.'):
            ext = ext[1:]
        file_meta = dict(
            bucket=str(ov.bucket.id),
            key=ov.key,
            checksum=ov.file.checksum,
            size=ov.file.size,
            version_id=str(ov.version_id),
            type=ext,
        )
        deposit['_files'].append(file_meta)
        dep_file_instances.append((file_['path'], fi))

    # Get a recid from SIP information
    recid = None
    if sips:
        recids = [int(sip['metadata']['recid']) for sip in sips]
        if len(set(recids)) > 1:
            logger.error('Multiple recids ({recids}) found in deposit {depid}'
                         ' does not exists.'.format(recids=recids,
                                                    depid=dep_pid.pid_value))
            raise DepositMultipleRecids(dep_pid.pid_value, list(set(recids)))
        elif recids:  # If only one recid
            recid = recids[0]

    for idx, sip in enumerate(sips):
        agent = None
        user_id = None
        if sip['agents']:
            agent = dict(
                ip_address=empty_str_if_none(sip['agents'][0].get(
                    'ip_address', "")),
                email=empty_str_if_none(sip['agents'][0].get(
                    'email_address', "")),
            )
            user_id = sip['agents'][0]['user_id']
        if user_id == 0:
            user_id = None
        content = sip['package']
        sip_format = 'marcxml'
        try:
            sip = SIP.create(sip_format, content, user_id=user_id, agent=agent)
        except SIPUserDoesNotExist:
            logger.exception('User ID {user_id} referred in deposit {depid} '
                             'does not exists.'.format(
                                 user_id=user_id, depid=dep_pid.pid_value))
            sip = SIP.create(sip_format, content, agent=agent)

        # Attach recid to SIP
        if recid:
            try:
                pid = PersistentIdentifier.get(pid_type='recid',
                                               pid_value=str(recid))
                record_sip = RecordSIP(sip_id=sip.id, pid_id=pid.id)
                db.session.add(record_sip)
            except PIDDoesNotExistError:
                logger.exception('Record {recid} referred in '
                                 'Deposit {depid} does not exists.'.format(
                                     recid=recid, depid=dep_pid.pid_value))
                if deposit['_p']['submitted'] == True:
                    logger.exception('Pair {recid}/{depid} was submitted,'
                                     ' (should it be unpublished?).'.format(
                                         recid=recid, depid=dep_pid.pid_value))
                else:
                    logger.exception(
                        'Pair {recid}/{depid} was not submitted.'.format(
                            recid=recid, depid=dep_pid.pid_value))

                # Reserve recid
                pid = PersistentIdentifier.create(pid_type='recid',
                                                  pid_value=str(recid),
                                                  object_type='rec',
                                                  status=PIDStatus.RESERVED)

                if RecordIdentifier.query.get(int(recid)) is None:
                    RecordIdentifier.insert(int(recid))
        if idx == 0:
            for fp, fi in dep_file_instances:
                sipf = SIPFile(sip_id=sip.id, filepath=fp, file_id=fi.id)
                db.session.add(sipf)
    deposit.commit()
    return deposit