Commit 129e0519 authored by Enrique Garcia's avatar Enrique Garcia
Browse files

add all the components of the .zenodoci library

parent 159ae226
{
"metadata": {
"title": "template repository ESCAPE",
"upload_type": "software",
"description": "A template repository for the ESCAPE project",
"creators": [{"name": "Garcia, Enrique",
"affiliation": "LAPP, CNRS"},
{"name": "Vuillaume, Thomas",
"affiliation": "LAPP, CNRS",
"orcid": "0000-0002-5686-2078"}],
"access_right": "open",
"license": "GPL-3.0+",
"communities": [{"identifier": "escape2020"}],
"keywords": [],
"language": "eng",
"notes": "(This will appear as a subtitle)",
"version": "2.0",
"grants": [{"id": "10.13039/501100000780::824064"}]
}
}
\ No newline at end of file
# -*- coding: utf-8 -*-
import os
import json
import argparse
from distutils.util import strtobool
from .zenodoapi import ZenodoAPI
parser = argparse.ArgumentParser(description="Upload new deposit entry to Zenodo")
# Required arguments
parser.add_argument('--token', '-t', type=str,
dest='zenodo_token',
help='Personal access token to (sandbox)Zenodo')
parser.add_argument('--sandbox_zenodo', '-s', action='store',
type=lambda x: bool(strtobool(x)),
dest='sandbox_flag',
help='Set the Zenodo environment.'
'If True connects with Zenodo. If False with Sanbox Zenodo',
default=False)
parser.add_argument('--input-directory', '-i', type=str,
dest='input_directory',
help='Path to the directory containing the files to upload.'
'ALL files will be uploaded.',
required=True)
args = parser.parse_args()
if __name__ == '__main__':
z = ZenodoAPI(access_token=args.zenodo_token,
sandbox=args.sandbox_flag # True for sandbox.zenodo.org !! False for zenodo.org
)
# 1 - create empty deposit
new_entry = z.create_new_entry()
if new_entry.status_code < 399:
deposition_id = new_entry.json()['id']
doi = new_entry.json()['metadata']['prereserve_doi']['doi']
print(f"Status {new_entry.status_code}. New entry to Zenodo created ! Deposition id {deposition_id}")
else:
print(new_entry.json())
# 2 - upload files
for file in os.listdir(args.input_directory):
full_path_file = args.input_directory + '/' + file
new_upload = z.upload_files_entry(deposition_id,
name_file=file,
path_file=full_path_file)
print(f"File {file} correctly uploaded !\n", new_upload)
# 3 - Upload repository information - that you must have filled before the json file !
with open('.zenodoci/repository_information.json') as json_file:
entry_info = json.load(json_file)
# entry_info['metadata']['doi'] = doi # In the new version of the API the doi is updated automatically.
update_entry = z.update_info_entry(deposition_id,
data=entry_info)
if update_entry.status_code < 399:
print(f"Status {update_entry.status_code}. Repository information correctly uploaded !")
else:
print(f"Repository information NOT correctly uploaded ! Status {update_entry.status_code}\n",
update_entry.json())
# 4 - publish entry - to publish the entry, uncomment the two lone below
# publish = z.publish_entry(deposition_id)
# print(publish.json())
print("New deposit correctly published !")
print(f"The new doi should look like 10.5281/{deposition_id}. However please")
print(f" ** Check the upload at {z.zenodo_api_url[:-4]}deposit/{deposition_id} **")
# -*- coding: utf-8 -*-
import os
import json
import argparse
from distutils.util import strtobool
from .zenodoapi import ZenodoAPI
parser = argparse.ArgumentParser(description="Upload a new version of an existing deposit to Zenodo")
# Required arguments
parser.add_argument('--token', '-t', type=str,
dest='zenodo_token',
help='Personal access token to (sandbox)Zenodo',
required=True)
parser.add_argument('--sandbox_zenodo', '-s', action='store',
type=lambda x: bool(strtobool(x)),
dest='sandbox_flag',
help='Set the Zenodo environment.'
'If True connects with Zenodo. If False with Sanbox Zenodo',
default=False)
parser.add_argument('--input-directory', '-i', type=str,
dest='input_directory',
help='Path to the directory containing the files to upload.'
'ALL files will be uploaded.',
required=True)
parser.add_argument('--deposit_id', '-id', type=str,
dest='deposit_id',
help='deposit_id of the deposit that is going to be updated by a new version',
required=True)
args = parser.parse_args()
if __name__ == '__main__':
z = ZenodoAPI(access_token=args.zenodo_token,
sandbox=args.sandbox_flag # True for sandbox.zenodo.org !! False for zenodo.org
)
# 1 - request a new version of an existing deposit
new_version = z.new_version_entry(args.deposit_id)
if new_version.status_code < 399:
print(f"Status {new_version.status_code}. New version of the {args.deposit_id} entry correctly created !")
else:
print(new_version.json())
new_deposition_id = new_version.json()['links']['latest_draft'].rsplit('/')[-1]
# # If you DO NOT want to erase the old files, comment the following lines
# old_files_ids = [file['id'] for file in new_version.json()['files']]
# for file_id in old_files_ids:
# z.deposition_files_delete(new_deposition_id,
# file_id)
# 2 - Upload new version of file(s)
for file in os.listdir(args.input_directory):
full_path_file = args.input_directory + '/' + file
new_upload = z.upload_files_entry(new_deposition_id,
name_file=file,
path_file=full_path_file)
print(f"File {file} correctly uploaded !\n", new_upload)
# 3 - Update metadata info
with open('.zenodoci/repository_information.json') as json_file:
update_entry_info = json.load(json_file)
# update_entry_info['metadata']['doi'] = doi # In the new version of the API the doi is updated automatically.
update_entry = z.update_info_entry(new_deposition_id,
data=update_entry_info)
if update_entry.status_code < 399:
print(f"Status {update_entry.status_code}. Repository information correctly uploaded !\n")
else:
print(f"Repository information NOT correctly uploaded ! Status {update_entry.status_code}\n",
update_entry.json())
# 4 - publish entry - to publish the entry, uncomment the two lone below
# publish = z.publish_entry(new_deposition_id)
# print(publish.json())
print("New version of the old deposition correctly published !")
print(f"Old deposition id {args.deposit_id}, new deposition id {new_deposition_id}")
print(f"The new doi should look like 10.5281/{new_deposition_id}. However please")
print(f" ** Check the upload at {z.zenodo_api_url[:-4]}deposit/{new_deposition_id} **")
# -*- coding: utf-8 -*-
import json
import requests
class ZenodoAPI:
def __init__(self, access_token, sandbox=True):
"""
Manages the communication with the (sandbox.)zenodo REST API.
This class is **EXCLUSIVELY** developed to be used within a CI/CD pipeline and to **EXCLUSIVELY PERFORM**
five tasks within the (sandbox.)zenodo api environment:
- Create a new deposit,
- Create a new version of an existing deposit,
- Upload files to a specific Zenodo entry,
- Upload information to the entry (Zenodo compulsory deposit information)
- Publish an entry
:param access_token: str
Personal access token to (sandbox.)zenodo.org/api
:param sandbox: bool
Communicates with either zenodo or sandbox.zenodo api
"""
if sandbox:
zenodo_api_url = "https://sandbox.zenodo.org/api/"
else:
zenodo_api_url = "https://zenodo.org/api/"
self.zenodo_api_url = zenodo_api_url
self.access_token = access_token
def create_new_entry(self):
"""
Create a new entry / deposition in (sandbox.)zenodo
POST method to {zenodo_api_url}/deposit/depositions
:return: request.put answer
"""
url = f"{self.zenodo_api_url}/deposit/depositions"
headers = {"Content-Type": "application/json"}
parameters = {'access_token': self.access_token}
return requests.post(url, headers=headers, params=parameters)
def upload_files_entry(self, entry_id, name_file, path_file):
"""
Upload a file to a Zenodo entry. If first retrieve the entry by a GET method to the
{zenodo_api_url}/deposit/depositions/{entry_id}.
PUT method to {bucket_url}/{filename}. The full api url is recovered when the entry is firstly retrieved.
:param entry_id: str
deposition_id of the Zenodo entry
:param name_file: str
File name of the file when uploaded
:param path_file: str
Path to the file to be uploaded
:return: json request.put object
"""
# 1 - Retrieve and recover information of an existing deposit
parameters = {'access_token': self.access_token}
fetch = requests.get(f"{self.zenodo_api_url}/deposit/depositions/{entry_id}",
params=parameters)
# 2 - Upload the files
bucket_url = fetch.json()['links']['bucket'] # full url is recovered from fetch (GET) method
url = f"{bucket_url}/{name_file}"
with open(path_file, 'rb') as upload_file:
upload = requests.put(url, data=upload_file)
return upload.json()
def update_info_entry(self, entry_id, data):
"""
Update an entry resource. Data should be the entry information that will be shown when a deposition is visited
at the Zenodo site.
PUT method to {zenodo_api_url}/deposit/depositions/{entry_id}. `data` MUST be included as json.dump(data)
:param entry_id: str
deposition_id of the Zenodo entry
:param data: object
json object containing the metadata (compulsory fields) that are enclosed when a new entry is created.
:return: request.put answer
"""
url = f"{self.zenodo_api_url}/deposit/depositions/{entry_id}"
headers = {"Content-Type": "application/json"}
parameters = {'access_token': self.access_token}
return requests.put(url, data=json.dump(data), headers=headers, params=parameters)
def publish_entry(self, entry_id):
"""
Publishes an entry in (sandbox.)zenodo
POST method to {zenodo_api_url}/deposit/depositions/{entry_id}/actions/publish
:param entry_id: str
deposition_id of the Zenodo entry
:return: request.put answer
"""
url = f"{self.zenodo_api_url}/deposit/depositions/{entry_id}/actions/publish"
parameters = {'access_token': self.access_token}
return requests.post(url, params=parameters)
def new_version_entry(self, entry_id):
"""
Creates a new version of AN EXISTING entry resource.
POST method to {zenodo_api_url}/deposit/depositions/{entry_id}/actions/newversion
:param entry_id: str
deposition_id of the Zenodo entry
:return: request.post answer
"""
url = f"{self.zenodo_api_url}deposit/depositions/{entry_id}/actions/newversion"
parameters = {'access_token': self.access_token}
return requests.post(url, params=parameters)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment