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]
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, ))
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, ))
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, )
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, )
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, ) )
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)
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))
@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)