Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#78] Handle HydroShare Collection Resources #191

Merged
merged 10 commits into from
Sep 12, 2023
7 changes: 3 additions & 4 deletions dspback/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from fastapi import FastAPI, status
from fastapi.openapi.utils import get_openapi
from fastapi.staticfiles import StaticFiles
from pydantic import ValidationError
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import PlainTextResponse
from pydantic import ValidationError


from dspback.config import get_settings
from dspback.dependencies import RepositoryException
Expand Down Expand Up @@ -52,10 +51,10 @@
async def http_exception_handler(request, exc):
return PlainTextResponse(f"Repository exception response[{str(exc.detail)}]", status_code=exc.status_code)


@app.exception_handler(ValidationError)
async def validation_exception_handler(request, exc: ValidationError):
return PlainTextResponse(f"Request data validation errors: {str(exc)}",
status_code=status.HTTP_400_BAD_REQUEST)
return PlainTextResponse(f"Request data validation errors: {str(exc)}", status_code=status.HTTP_400_BAD_REQUEST)


@app.on_event("startup")
Expand Down
4 changes: 4 additions & 0 deletions dspback/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Settings(BaseSettings):
zenodo_file_delete_url: HttpUrl
zenodo_file_read_url: HttpUrl
zenodo_view_url: HttpUrl
zenodo_public_view_url: HttpUrl
zenodo_move_or_rename_url: HttpUrl
zenodo_health_url: HttpUrl

Expand Down Expand Up @@ -145,6 +146,7 @@ def get_settings():
"file_read": settings.zenodo_file_read_url,
"move_or_rename_url": settings.zenodo_move_or_rename_url,
"view_url": settings.zenodo_view_url,
"public_view_url": settings.zenodo_public_view_url,
"schema": "/api/schema/zenodo/schema.json",
"uischema": "/api/schema/zenodo/uischema.json",
"schema_defaults": "/api/schema/zenodo/defaults.json",
Expand All @@ -164,6 +166,7 @@ def get_settings():
"folder_delete": settings.hydroshare_folder_read_url,
"move_or_rename_url": settings.hydroshare_move_or_rename_url,
"view_url": settings.hydroshare_view_url,
"public_view_url": settings.hydroshare_view_url,
"schema": "/api/schema/hydroshare/schema.json",
"uischema": "/api/schema/hydroshare/uischema.json",
"schema_defaults": "/api/schema/hydroshare/defaults.json",
Expand All @@ -179,6 +182,7 @@ def get_settings():
"file_delete": settings.earthchem_file_delete_url,
"file_read": settings.earthchem_file_read_url,
"view_url": settings.earthchem_view_url,
"public_view_url": settings.earthchem_public_view_url,
"schema": "/api/schema/earthchem/schema.json",
"uischema": "/api/schema/earthchem/uischema.json",
"schema_defaults": "/api/schema/earthchem/defaults.json",
Expand Down
12 changes: 10 additions & 2 deletions dspback/pydantic_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ def parse_publication_date(cls, value):

def to_submission(self, identifier) -> Submission:
settings = get_settings()
view_url = settings.zenodo_view_url % identifier
view_url = (
settings.zenodo_public_view_url % identifier
if self.publication_date
else settings.zenodo_view_url % identifier
)
return Submission(
title=self.title,
authors=[creator.name for creator in self.creators],
Expand Down Expand Up @@ -264,7 +268,11 @@ class License(BaseModel):

def to_submission(self, identifier) -> Submission:
settings = get_settings()
view_url = settings.earthchem_public_view_url % identifier
view_url = (
settings.earthchem_public_view_url % identifier
if self.datePublished
else settings.earthchem_view_url % identifier
)
authors = [contributor.name for contributor in self.contributors]
authors.insert(0, self.leadAuthor.name)
return Submission(
Expand Down
10 changes: 10 additions & 0 deletions dspback/routers/earthchem.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ async def get_metadata_repository(self, request: Request, identifier) -> respons
await self.submit(request, identifier=identifier, json_metadata=json_metadata)
return json_metadata

@router.get(
'/submission/earthchem/{identifier}',
tags=["EarthChem"],
summary="Update and get an EarthChem record Submission",
description="Retrieves the metadata for the EarthChem record and returns the updated Submission in the database.",
)
async def update_and_get_submission(self, request: Request, identifier):
await self.get_metadata_repository(request, identifier)
return self.user.submission(identifier)

@router.delete(
'/metadata/earthchem/{identifier}',
tags=["EarthChem"],
Expand Down
20 changes: 20 additions & 0 deletions dspback/routers/hydroshare.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ async def _retrieve_metadata_from_repository(self, request: Request, identifier)
if response.status_code >= 300:
raise RepositoryException(status_code=response.status_code, detail=response.text)

"""
HydroShare maintenance mode
Parsing the response can fail if HydroShare is in maintenance mode.
The request to HydroShare will return status code 200, but contain an HTML response.
"""
try:
json_metadata = json.loads(response.text)
except:
raise RepositoryException(status_code=500, detail="Failed to parse JSON response")

json_metadata = json.loads(response.text)
json_metadata = from_hydroshare_format(json_metadata)
return self.wrap_metadata(json_metadata, exists_and_is("published", json_metadata))
Expand All @@ -159,6 +169,16 @@ async def get_metadata_repository(self, request: Request, identifier):
await self.submit(request, identifier=identifier, json_metadata=json_metadata)
return json_metadata

@router.get(
'/submission/hydroshare/{identifier}',
tags=["HydroShare"],
summary="Update and get a HydroShare resource Submission",
description="Retrieves the metadata for the HydroShare resource and returns the updated Submission in the database.",
)
async def update_and_get_submission(self, request: Request, identifier):
await self.get_metadata_repository(request, identifier)
return self.user.submission(identifier)

@router.delete(
'/metadata/hydroshare/{identifier}',
tags=["HydroShare"],
Expand Down
10 changes: 10 additions & 0 deletions dspback/routers/zenodo.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ async def get_metadata_repository(self, request: Request, identifier):

return json_metadata

@router.get(
'/submission/zenodo/{identifier}',
tags=["Zenodo"],
summary="Update and get a Zenodo record Submission",
description="Retrieves the metadata for the Zenodo record and returns the updated Submission in the database.",
)
async def update_and_get_submission(self, request: Request, identifier):
await self.get_metadata_repository(request, identifier)
return self.user.submission(identifier)

@router.delete(
'/metadata/zenodo/{identifier}',
tags=["Zenodo"],
Expand Down
3 changes: 1 addition & 2 deletions dspback/schemas/earthchem/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
"description": {
"title": "Abstract or Description",
"type": "string",
"description": "Describe measurements, location, and purpose of the dataset",
"maxLength": 250
"description": "Describe measurements, location, and purpose of the dataset"
},
"community": {
"title": "Community",
Expand Down
3 changes: 0 additions & 3 deletions dspback/schemas/external/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,6 @@
"format": "date-time",
"options": {
"placeholder": "YYYY-MM-DDTHH:MM"
},
"formatMinimum": {
"$data": "1/start"
}
}
},
Expand Down
26 changes: 25 additions & 1 deletion dspback/schemas/external/uischema.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,31 @@
{
"type": "Control",
"label": "Temporal coverage",
"scope": "#/properties/temporalCoverage"
"scope": "#/properties/temporalCoverage",
"options": {
"detail": {
"type": "VerticalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/name"
},
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/start"
},
{
"type": "Control",
"scope": "#/properties/end"
}
]
}
]
}
}
},
{
"type": "Control",
Expand Down
3 changes: 0 additions & 3 deletions dspback/schemas/hydroshare/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -624,9 +624,6 @@
"format": "date-time",
"options": {
"placeholder": "YYYY-MM-DDTHH:MM"
},
"formatMinimum": {
"$data": "1/start"
}
}
},
Expand Down
1 change: 1 addition & 0 deletions dspback/schemas/hydroshare/uischema.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@
"scope": "#/properties/relations",
"options": {
"showSortButtons": true,
"collapsed": true,
"elementLabelProp": [
"type",
"value"
Expand Down
28 changes: 28 additions & 0 deletions tests/test_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ async def test_hydroshare_to_submission(hydroshare):

async def test_zenodo_to_submission(zenodo):
zenodo_record = ZenodoRecord(**zenodo)
zenodo_record.publication_date = None
zenodo_submission = zenodo_record.to_submission("947940")

assert zenodo_submission.title == zenodo_record.title
Expand All @@ -34,6 +35,18 @@ async def test_zenodo_to_submission(zenodo):
assert zenodo_submission.url == get_settings().zenodo_view_url % zenodo_record.record_id


async def test_zenodo_published_to_submission(zenodo):
zenodo_record = ZenodoRecord(**zenodo)
zenodo_submission = zenodo_record.to_submission("947940")

assert zenodo_submission.title == zenodo_record.title
assert zenodo_submission.authors == [creator.name for creator in zenodo_record.creators]
assert zenodo_submission.repo_type == RepositoryType.ZENODO
assert zenodo_submission.submitted <= datetime.utcnow()
assert zenodo_submission.identifier == zenodo_record.record_id
assert zenodo_submission.url == get_settings().zenodo_public_view_url % zenodo_record.record_id


async def test_external_to_submission(external):
external_record = ExternalRecord(**external)
external_submission = external_record.to_submission("947940")
Expand Down Expand Up @@ -71,6 +84,21 @@ async def test_external_to_jsonld(external):


async def test_earthchem_to_submission(earthchem):
earthchem_record = EarthChemRecord(**earthchem)
earthchem_record.datePublished = None
earthchem_submission = earthchem_record.to_submission("947940")

assert earthchem_submission.title == earthchem_record.title
authors = [f"{contributor.familyName}, {contributor.givenName}" for contributor in earthchem_record.contributors]
authors.insert(0, f"{earthchem_record.leadAuthor.familyName}, {earthchem_record.leadAuthor.givenName}")
assert earthchem_submission.authors == authors
assert earthchem_submission.repo_type == RepositoryType.EARTHCHEM
assert earthchem_submission.submitted <= datetime.utcnow()
assert earthchem_submission.identifier == "947940"
assert earthchem_submission.url == get_settings().earthchem_view_url % "947940"


async def test_earthchem_published_to_submission(earthchem):
earthchem_record = EarthChemRecord(**earthchem)
earthchem_submission = earthchem_record.to_submission("947940")

Expand Down