def test_validity():
    input_schema = catalog.get_schema(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/iso19115'))
    input_json = catalog.load_json(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/iso19115-example'))
    output_schema = catalog.get_schema(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/datacite4'))
    output_json = catalog.load_json(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/datacite4-example-translated'
            ))

    assert input_schema.validate().valid
    assert input_schema.evaluate(JSON(input_json)).valid
    assert output_schema.validate().valid
    assert output_schema.evaluate(JSON(output_json)).valid
def test_translate_iso19115_to_datacite():
    input_schema = catalog.get_schema(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/iso19115'))
    input_json = catalog.load_json(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/iso19115-example.json'
            ))
    output_json = catalog.load_json(
        URI('https://odp.saeon.ac.za/schema/metadata/saeon/datacite4-example-translated.json'
            ))

    result = input_schema.evaluate(JSON(input_json))
    patch = result.output('patch', scheme='saeon/datacite4')
    translation = result.output('translation', scheme='saeon/datacite4')

    assert JSONPatch(*patch).evaluate(None) == translation

    # work in progress
    # assert translation == output_json
    assert translation.keys() == output_json.keys()
    for k in translation:
        if k == 'contributors':
            # todo: resolve leftover empty arrays/objects when there are
            #  no source values to fill them
            continue
        assert translation[k] == output_json[k]
Example #3
0
async def list_catalogs(paginator: Paginator = Depends(), ):
    return paginator.paginate(
        select(Catalog), lambda row: CatalogModel(
            id=row.Catalog.id,
            schema_id=row.Catalog.schema_id,
            schema_uri=row.Catalog.schema.uri,
            schema_=schema_catalog.get_schema(URI(row.Catalog.schema.uri)).
            value,
        ))
Example #4
0
async def list_tags(paginator: Paginator = Depends(), ):
    return paginator.paginate(
        select(Tag), lambda row: TagModel(
            id=row.Tag.id,
            cardinality=row.Tag.cardinality,
            public=row.Tag.public,
            scope_id=row.Tag.scope_id,
            schema_id=row.Tag.schema_id,
            schema_uri=row.Tag.schema.uri,
            schema_=schema_catalog.get_schema(URI(row.Tag.schema.uri)).value,
        ))
Example #5
0
async def get_tag(tag_id: str, ):
    tag = Session.execute(
        select(Tag).where(Tag.id == tag_id)).scalar_one_or_none()

    if not tag:
        raise HTTPException(HTTP_404_NOT_FOUND)

    return TagModel(
        id=tag.id,
        cardinality=tag.cardinality,
        public=tag.public,
        scope_id=tag.scope_id,
        schema_id=tag.schema_id,
        schema_uri=tag.schema.uri,
        schema_=schema_catalog.get_schema(URI(tag.schema.uri)).value,
    )
Example #6
0
async def get_schema(
        schema_id: str,
):
    schema = Session.execute(
        select(Schema).
        where(Schema.id == schema_id)
    ).scalar_one_or_none()

    if not schema:
        raise HTTPException(HTTP_404_NOT_FOUND)

    return SchemaModel(
        id=schema.id,
        type=schema.type,
        uri=schema.uri,
        schema_=schema_catalog.get_schema(URI(schema.uri)).value,
    )
Example #7
0
async def list_schemas(
        schema_type: SchemaType = None,
        paginator: Paginator = Depends(),
):
    stmt = select(Schema)
    if schema_type:
        stmt = stmt.where(Schema.type == schema_type)

    return paginator.paginate(
        stmt,
        lambda row: SchemaModel(
            id=row.Schema.id,
            type=row.Schema.type,
            uri=row.Schema.uri,
            schema_=schema_catalog.get_schema(URI(row.Schema.uri)).value,
        )
    )
Example #8
0
    def _evaluate_record(self, record_id: str, timestamp: datetime) -> bool:
        """Evaluate a record model (API) against the publication schema for
        a catalog, and commit the result to the catalog_record table.

        The catalog_record entry is stamped with the `timestamp` of the latest
        contributing change (from catalog/record/record_tag/collection_tag).
        """
        catalog = Session.get(Catalog, self.catalog_id)
        record = Session.get(Record, record_id)
        catalog_record = (Session.get(CatalogRecord, (self.catalog_id, record_id)) or
                          CatalogRecord(catalog_id=self.catalog_id, record_id=record_id))

        record_model = output_record_model(record)
        record_json = JSON(record_model.dict())

        publication_schema = schema_catalog.get_schema(URI(catalog.schema.uri))

        if (result := publication_schema.evaluate(record_json)).valid:
            catalog_record.validity = result.output('flag')
            catalog_record.published = True
            catalog_record.published_record = self._create_published_record(record_model).dict()
            self._save_published_doi(record_model)
Example #9
0
from fastapi import HTTPException
from jschon import JSONSchema, URI
from sqlalchemy import select
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY

from odp.api.models import RecordModelIn, TagInstanceModelIn
from odp.db import Session
from odp.db.models import Schema, SchemaType, Tag
from odp.lib.schema import schema_catalog


async def get_tag_schema(tag_instance_in: TagInstanceModelIn) -> JSONSchema:
    if not (tag := Session.execute(
            select(Tag).where(
                Tag.id == tag_instance_in.tag_id)).scalar_one_or_none()):
        raise HTTPException(HTTP_422_UNPROCESSABLE_ENTITY, 'Invalid tag id')

    schema = Session.get(Schema, (tag.schema_id, SchemaType.tag))
    return schema_catalog.get_schema(URI(schema.uri))


async def get_metadata_schema(record_in: RecordModelIn) -> JSONSchema:
    if not (schema := Session.get(Schema,
                                  (record_in.schema_id, SchemaType.metadata))):
        raise HTTPException(HTTP_422_UNPROCESSABLE_ENTITY, 'Invalid schema id')

    return schema_catalog.get_schema(URI(schema.uri))
Example #10
0

@router.get(
    '/{catalog_id}',
    response_model=CatalogModel,
    dependencies=[Depends(Authorize(ODPScope.CATALOG_READ))],
)
async def get_catalog(catalog_id: str, ):
    if not (catalog := Session.get(Catalog, catalog_id)):
        raise HTTPException(HTTP_404_NOT_FOUND)

    return CatalogModel(
        id=catalog.id,
        schema_id=catalog.schema_id,
        schema_uri=catalog.schema.uri,
        schema_=schema_catalog.get_schema(URI(catalog.schema.uri)).value,
    )


@router.get(
    '/{catalog_id}/records',
    response_model=Page[PublishedRecordModel],
    dependencies=[Depends(Authorize(ODPScope.CATALOG_READ))],
)
async def list_published_records(
        catalog_id: str,
        paginator: Paginator = Depends(),
):
    if not Session.get(Catalog, catalog_id):
        raise HTTPException(HTTP_404_NOT_FOUND)