Skip to main content

A set of runtime extensions of Invenio repository

Project description

OARepo Runtime

Runtime extensions for Invenio framework.

Overview

This package extends Invenio with:

  • Model registry for unified record type configuration
  • Typed system fields with dynamic OpenSearch mapping
  • Nested and date-range facets with permission-based filtering
  • Service component dependency ordering
  • Multilingual schema support (I18N)
  • FAIR Signposting implementation (HTTP Link headers and linksets)
  • Repository information endpoints
  • Custom field mapping updates
  • CLI extensions for search initialization

Installation

pip install oarepo-runtime

Requirements

  • Python 3.13+
  • Invenio 14.x
  • OpenSearch/Elasticsearch compatible search backend

Key Features

1. Model Registry and Management

Source: oarepo_runtime/api.py, oarepo_runtime/ext.py, oarepo_runtime/config.py

The Model class provides a unified configuration structure for record types in your repository:

from oarepo_runtime import Model
from flask_babel import lazy_gettext as _

model = Model(
    code="my_record",
    name=_("My Record Type"),
    version="1.0.0",
    service="my_records",
    resource_config="my_app.resources.config.MyRecordResourceConfig",
    description=_("Custom record type for my repository"),
    exports=[
        Export(
            code="datacite",
            name=_("DataCite JSON"),
            mimetype="application/vnd.datacite.datacite+json",
            serializer=DataCiteSerializer()
        )
    ],
    records_alias_enabled=True
)

Normally, it is created automatically when using the oarepo-model library.

The OARepoRuntime extension manages all registered models:

from oarepo_runtime import current_runtime

# Access models by code
model = current_runtime.models["my_record"]

# Get service for a record instance
service = current_runtime.get_record_service_for_record(record)

# Find records by PID type
record_class = current_runtime.record_class_by_pid_type["recid"]

# Get all RDM-compatible models
rdm_models = list(current_runtime.rdm_models)

Key capabilities:

  • Centralized model registration via OAREPO_MODELS configuration
  • Automatic service and resource resolution
  • PID type to record class mapping
  • Schema to model mapping for serialization
  • Support for draft/published record workflows
  • File service integration

2. Enhanced System Fields

Source: oarepo_runtime/records/systemfields/

Typed System Fields

Base class for system fields with type hints and proper typing support:

from oarepo_runtime.records.systemfields import TypedSystemField

class MyCustomField(TypedSystemField[MyRecord, str]):
    def obj_get(self, record: MyRecord) -> str:
        # Implementation
        pass

Mapping System Fields

Dynamic OpenSearch mapping support for system fields that need custom indexing:

from oarepo_runtime.records.systemfields import MappingSystemFieldMixin

class DynamicField(MappingSystemFieldMixin, TypedSystemField):
    def mapping_settings(self, record_class):
        return {
            "type": "keyword",
            "eager_global_ordinals": True
        }

Publication Status System Field

Built-in field for tracking record publication status:

from oarepo_runtime.records.systemfields import PublicationStatusSystemField

class MyRecord(Record):
    publication_status = PublicationStatusSystemField()

3. Advanced Faceting System

Source: oarepo_runtime/services/facets/

Date Range Facets

Support for date-based faceting with configurable intervals:

from oarepo_runtime.services.facets.date import DateRangeFacet

facets = {
    "created": DateRangeFacet(
        field="created",
        label="Created Date",
        interval="year"
    )
}

Nested Facets

Faceting on nested objects with label resolution:

from oarepo_runtime.services.facets.nested_facet import NestedLabeledFacet

facets = {
    "contributors": NestedLabeledFacet(
        field="metadata.contributors.person.id",
        nested_path="metadata.contributors",
        value_labels={
            "person123": {"cs": "Jan Novák", "en": "Jan Novak"}
        }
    )
}

Grouped Facets with Permissions

Permission-based facet grouping for different user roles:

from oarepo_runtime.services.facets.params import GroupedFacetsParam

search_config = {
    "facets": base_facets,
    "facet_groups": {
        "admin": {
            "label": "Admin Facets",
            "facets": ["internal_status", "workflow_state"],
            "provides_needs": [AdminNeed()]
        }
    }
}

4. Service Component Ordering

Source: oarepo_runtime/services/config/components.py

Deterministic ordering of service components with dependency resolution:

class ComponentOrderingMixin:
    """Mixin that ensures service components execute in the correct order."""
    
    @property
    def components(self):
        # Components are automatically ordered based on:
        # - depends_on declarations
        # - affects declarations  
        # - wildcard semantics (*)
        # - input order preservation where possible
        return self._ordered_components

Components can declare dependencies:

class MyComponent(ServiceComponent):
    depends_on = [ValidationComponent]  # Runs after ValidationComponent
    affects = "*"  # Affects all subsequent components

5. Multilingual Support

Source: oarepo_runtime/services/schema/

I18N UI Schema Support

Marshmallow schemas with multilingual field support:

from oarepo_runtime.services.schema.i18n_ui import I18nUISchema, MultilingualUIField

class MyUISchema(I18nUISchema):
    title = MultilingualUIField()
    description = MultilingualUIField(ui_params={
        "widget": "textarea",
        "placeholder": {"en": "Enter description", "cs": "Zadejte popis"}
    })

Locale Handling

from oarepo_runtime.services.schema.i18n import LocalizedDateTime

class RecordSchema(Schema):
    created = LocalizedDateTime()  # Automatically formats dates per locale

6. Signposting and FAIR Data

Source: oarepo_runtime/resources/signposting/

Full implementation of FAIR Signposting for machine-readable links:

from oarepo_runtime.resources.signposting import (
    landing_page_signpost_links_list,
    create_linkset,
    create_linkset_json
)

# Generate signposting links for a landing page
links = landing_page_signpost_links_list(datacite_dict, record_dict, short=False)

# Create HTTP Link header
header = list_of_signpost_links_to_http_header(links)

# Create application/linkset format
linkset = create_linkset(datacite_dict, record_dict)

# Create application/linkset+json format  
linkset_json = create_linkset_json(datacite_dict, record_dict)

Supported relation types:

  • author - Links to author identifiers
  • cite-as - Persistent identifier (DOI)
  • describedby - Metadata export formats
  • item - File contents
  • license - License URIs
  • type - Resource type (schema.org)

7. Repository Information API

Source: oarepo_runtime/info/views.py

Machine-readable endpoint for repository metadata:

# GET /.well-known/repository
{
    "models": {
        "my_record": {
            "code": "my_record",
            "name": "My Record Type",
            "version": "1.0.0",
            "links": {
                "search": "/api/my-records/",
                "ui": "/my-records/"
            },
            "jsonschemas": {
                "record": "https://localhost/schemas/my-records-1.0.0.json"
            },
            "exports": [
                {
                    "code": "datacite",
                    "mimetype": "application/vnd.datacite.datacite+json"
                }
            ]
        }
    }
}

8. CLI Extensions

Source: oarepo_runtime/cli/

Enhanced search index initialization:

# Initialize search indices with custom field mapping updates
invenio index init

# The init command automatically runs registered hooks from:
# - oarepo.cli.search.init entry point
# - Updates dynamic mappings for all registered models

Extension point for custom initialization:

# In your package's entry points:
[project.entry-points."oarepo.cli.search.init"]
my_init = "my_app.init:update_custom_mappings"

9. Custom Fields and Relations

Source: oarepo_runtime/services/records/

Support for updating record mappings with custom fields:

from oarepo_runtime.services.records.custom_fields import (
    update_all_records_mappings_relation_fields
)

# Update OpenSearch mappings for all records with relation fields
update_all_records_mappings_relation_fields()

10. Permission Generators

Source: oarepo_runtime/services/config/permissions.py

Pre-configured permission policy for open access repositories:

from oarepo_runtime.services.config.permissions import EveryonePermissionPolicy

class MyServiceConfig(RecordServiceConfig):
    permission_policy_cls = EveryonePermissionPolicy
    # Grants all permissions to any authenticated or anonymous user

Development

Setup

# Clone repository
git clone https://github.com/oarepo/oarepo-runtime.git
cd oarepo-runtime

./run.sh venv

Running Tests

./run.sh test

Entry Points

The package registers several Invenio entry points:

[project.entry-points."invenio_base.api_apps"]
oarepo_runtime = "oarepo_runtime.ext:OARepoRuntime"

[project.entry-points."invenio_base.apps"]
oarepo_runtime = "oarepo_runtime.ext:OARepoRuntime"

[project.entry-points."flask.commands"]
oarepo = "oarepo_runtime.cli:oarepo"

[project.entry-points."oarepo.cli.search.init"]
runtime_update_mappings = "oarepo_runtime.services.records.mapping:update_all_records_mappings"

[project.entry-points."invenio_base.blueprints"]
oarepo_runtime_info = "oarepo_runtime.info.views:create_wellknown_blueprint"

License

Copyright (c) 2020-2025 CESNET z.s.p.o.

OARepo Runtime is free software; you can redistribute it and/or modify it under the terms of the MIT License. See LICENSE file for more details.

Links

Acknowledgments

This project builds upon Invenio Framework and is developed as part of the OARepo ecosystem.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oarepo_runtime-4.1.0.tar.gz (48.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oarepo_runtime-4.1.0-py3-none-any.whl (72.2 kB view details)

Uploaded Python 3

File details

Details for the file oarepo_runtime-4.1.0.tar.gz.

File metadata

  • Download URL: oarepo_runtime-4.1.0.tar.gz
  • Upload date:
  • Size: 48.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for oarepo_runtime-4.1.0.tar.gz
Algorithm Hash digest
SHA256 6b1eb7b6935980b42e6a46d9b29d647fceddc93c22826fc6f02bfe303ad7a3a4
MD5 6799d9871ee0e110fd4d2e16887db742
BLAKE2b-256 a52ae471921355705b4c6ace954d566004a9351e6d1f30fc8cb12d2bcc168865

See more details on using hashes here.

File details

Details for the file oarepo_runtime-4.1.0-py3-none-any.whl.

File metadata

  • Download URL: oarepo_runtime-4.1.0-py3-none-any.whl
  • Upload date:
  • Size: 72.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for oarepo_runtime-4.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a210d47bd91e607ac87b8a6d498260b65723dfd02f1224252777333f277fdd67
MD5 7052d15b9aeaf403e3c18b322d586870
BLAKE2b-256 374bac481d1ef912d1ebed336f718ef361bbc250a1c38c570b49485e0d04946e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page