aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/sandcrawler/fileset_platforms.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/python/sandcrawler/fileset_platforms.py b/python/sandcrawler/fileset_platforms.py
index 79f4033..73b1676 100644
--- a/python/sandcrawler/fileset_platforms.py
+++ b/python/sandcrawler/fileset_platforms.py
@@ -289,6 +289,105 @@ class FigshareHelper(DatasetPlatformHelper):
extra=dict(version=dataset_version),
)
+class ZenodoHelper(DatasetPlatformHelper):
+
+ def __init__(self):
+ self.platform_name = 'zenodo'
+ self.session = requests.Session()
+
+ def match_request(self, request: dict , resource: Optional[ResourceResult], html_biblio: Optional[BiblioMetadata]) -> bool:
+
+ if resource and resource.terminal_url:
+ url = resource.terminal_url
+ else:
+ url = request['base_url']
+
+ components = urllib.parse.urlparse(url)
+ platform_domain = components.netloc.split(':')[0].lower()
+ if platform_domain == 'zenodo.org' and '/record/' in components.path:
+ return True
+ return False
+
+ def process_request(self, request: dict, resource: Optional[ResourceResult], html_biblio: Optional[BiblioMetadata]) -> DatasetPlatformItem:
+ """
+ Fetch platform-specific metadata for this request (eg, via API calls)
+ """
+
+ if resource and resource.terminal_url:
+ url = resource.terminal_url
+ else:
+ url = request['base_url']
+
+ # 1. extract identifier from URL
+ # eg: https://zenodo.org/record/5230255
+ components = urllib.parse.urlparse(url)
+ platform_domain = components.netloc.split(':')[0].lower()
+ if len(components.path.split('/')) < 2:
+ raise ValueError("Expected a complete, versioned figshare URL")
+
+ platform_id = components.path.split('/')[2]
+ assert platform_id.isdigit(), f"expected numeric: {platform_id}"
+
+ if not 'zenodo.org' in platform_domain:
+ raise ValueError(f"unexpected zenodo.org domain: {platform_domain}")
+
+ # 2. API fetch
+ obj = self.session.get(f"https://zenodo.org/api/records/{platform_id}").json()
+
+ assert obj['id'] == int(platform_id)
+ work_id = obj['conceptdoi']
+ if work_id == obj['id']:
+ raise ValueError("got a work-level zenodo record, not a versioned record: {work_id}")
+
+ zenodo_type = obj['metadata']['resource_type']['type']
+
+ manifest = []
+ for row in obj['files']:
+ mf = FilesetManifestFile(
+ path=row['key'],
+ size=row['size'],
+ platform_url=row['links']['self'],
+ #extra=dict(),
+ )
+ checksum = row['checksum']
+ # eg: md5:35ffcab905f8224556dba76648cb7dad
+ if checksum.startswith('md5:'):
+ mf.md5 = checksum[4:]
+ elif checksum.startswith('sha1:'):
+ mf.sha1 = checksum[45]
+ manifest.append(mf)
+
+ authors = []
+ for author in obj['metadata']['creators']:
+ authors.append(author['name'])
+ archiveorg_item_name = f"{platform_domain}-{platform_id}"
+ archiveorg_item_meta = dict(
+ # XXX: collection=platform_domain,
+ collection="datasets",
+ creator=authors,
+ doi=obj['doi'],
+ title=obj['metadata']['title'],
+ date=obj['metadata']['publication_date'],
+ source=obj['links']['html'],
+ description=obj['metadata']['description'],
+ license=obj['metadata']['license']['id'],
+ version=obj['revision'],
+ # obj['metadata']['version'] is, eg, git version tag
+ )
+
+ return DatasetPlatformItem(
+ platform_name=self.platform_name,
+ platform_status='success',
+ manifest=manifest,
+ platform_domain=platform_domain,
+ platform_id=platform_id,
+ archiveorg_item_name=archiveorg_item_name,
+ archiveorg_item_meta=archiveorg_item_meta,
+ #web_bundle_url=f"https://ndownloader.figshare.com/articles/{platform_id}/versions/{dataset_version}",
+ # TODO: web_base_url= (for GWB downloading, in lieu of platform_url on individual files)
+ extra=dict(version=obj['revision']),
+ )
+
class ArchiveOrgHelper(DatasetPlatformHelper):
@@ -436,5 +535,6 @@ class ArchiveOrgHelper(DatasetPlatformHelper):
DATASET_PLATFORM_HELPER_TABLE = {
'dataverse': DataverseHelper(),
'figshare': FigshareHelper(),
+ 'zenodo': ZenodoHelper(),
'archiveorg': ArchiveOrgHelper(),
}