caltechdata-api 1.10.6__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/PKG-INFO +2 -1
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/caltechdata_edit.py +78 -69
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/caltechdata_write.py +52 -53
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/cli.py +12 -22
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/customize_schema.py +6 -35
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/get_metadata.py +4 -4
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/PKG-INFO +2 -1
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/requires.txt +1 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/setup.cfg +2 -1
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/tests/test_rdm.py +2 -4
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/LICENSE +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/README.md +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/__init__.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/download_file.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/get_files.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/md_to_json.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/utils.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/date_types.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/description_types.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/identifier_types.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/licenses.csv +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/relation_types.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/resource_types.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/roles.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/title_types.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies.yaml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/SOURCES.txt +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/dependency_links.txt +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/entry_points.txt +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/top_level.txt +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/pyproject.toml +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/setup.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/tests/test_download.py +0 -0
- {caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/tests/test_unit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: caltechdata_api
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Python wrapper for CaltechDATA API.
|
|
5
5
|
Home-page: https://github.com/caltechlibrary/caltechdata_api
|
|
6
6
|
Author: Thomas E Morrell, Rohan Bhattarai, Elizabeth Won, Alexander A Abakah, Kshemaahna Nagi
|
|
@@ -24,6 +24,7 @@ Requires-Dist: pyyaml
|
|
|
24
24
|
Requires-Dist: s3fs
|
|
25
25
|
Requires-Dist: cryptography
|
|
26
26
|
Requires-Dist: s3cmd
|
|
27
|
+
Requires-Dist: jsonschema-specifications
|
|
27
28
|
Dynamic: license-file
|
|
28
29
|
|
|
29
30
|
# CaltechDATA API Python Library
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import copy, os, json
|
|
1
|
+
import copy, os, json, time
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
4
|
from requests import session
|
|
@@ -7,7 +7,6 @@ from caltechdata_api import (
|
|
|
7
7
|
customize_schema,
|
|
8
8
|
write_files_rdm,
|
|
9
9
|
add_file_links,
|
|
10
|
-
send_to_community,
|
|
11
10
|
)
|
|
12
11
|
|
|
13
12
|
|
|
@@ -16,7 +15,8 @@ def caltechdata_unembargo(token, ids, production=False):
|
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
def caltechdata_accept(ids, token=None, production=False):
|
|
19
|
-
# Accept a record into a community
|
|
18
|
+
# Accept a record into a community. Only accepts the first community
|
|
19
|
+
# request
|
|
20
20
|
|
|
21
21
|
# If no token is provided, get from RDMTOK environment variable
|
|
22
22
|
if not token:
|
|
@@ -36,8 +36,15 @@ def caltechdata_accept(ids, token=None, production=False):
|
|
|
36
36
|
result = requests.get(
|
|
37
37
|
url + "/api/records/" + idv + "/draft/review", headers=headers
|
|
38
38
|
)
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
if result.status_code != 200:
|
|
40
|
+
result = requests.get(
|
|
41
|
+
url + "/api/records/" + idv + "/requests", headers=headers
|
|
42
|
+
)
|
|
43
|
+
if result.status_code != 200:
|
|
44
|
+
raise Exception(result.text)
|
|
45
|
+
accept_link = result.json()["hits"]["hits"][0]["links"]["actions"]["accept"]
|
|
46
|
+
else:
|
|
47
|
+
accept_link = result.json()["links"]["actions"]["accept"]
|
|
41
48
|
data = comment = {
|
|
42
49
|
"payload": {
|
|
43
50
|
"content": "This record is accepted automatically with the CaltechDATA API",
|
|
@@ -97,7 +104,7 @@ def caltechdata_edit(
|
|
|
97
104
|
token=None,
|
|
98
105
|
files={},
|
|
99
106
|
production=False,
|
|
100
|
-
schema=
|
|
107
|
+
schema=None,
|
|
101
108
|
publish=False,
|
|
102
109
|
file_links=[],
|
|
103
110
|
s3=None,
|
|
@@ -122,41 +129,6 @@ def caltechdata_edit(
|
|
|
122
129
|
if isinstance(files, str) == True:
|
|
123
130
|
files = [files]
|
|
124
131
|
|
|
125
|
-
# Check if file links were provided in the metadata
|
|
126
|
-
descriptions = []
|
|
127
|
-
ex_file_links = []
|
|
128
|
-
ex_file_descriptions = []
|
|
129
|
-
if "descriptions" in metadata:
|
|
130
|
-
for d in metadata["descriptions"]:
|
|
131
|
-
if d["description"].startswith("Files available via S3"):
|
|
132
|
-
file_text = d["description"]
|
|
133
|
-
file_list = file_text.split('href="')
|
|
134
|
-
# Check if we have file_descriptions
|
|
135
|
-
split_comma = file_list[0].split(", ")
|
|
136
|
-
if len(split_comma) == 3:
|
|
137
|
-
ex_file_descriptions.append(split_comma[1])
|
|
138
|
-
# Loop over links in description, skip header text
|
|
139
|
-
for file in file_list[1:]:
|
|
140
|
-
ex_file_links.append(file.split('"\n')[0])
|
|
141
|
-
split_comma = file.split(", ")
|
|
142
|
-
if len(split_comma) == 3:
|
|
143
|
-
ex_file_descriptions.append(split_comma[1])
|
|
144
|
-
else:
|
|
145
|
-
descriptions.append(d)
|
|
146
|
-
# We remove file link descriptions, and re-add below
|
|
147
|
-
metadata["descriptions"] = descriptions
|
|
148
|
-
|
|
149
|
-
# If user has provided file links as a cli option, we add those
|
|
150
|
-
if file_links:
|
|
151
|
-
metadata = add_file_links(
|
|
152
|
-
metadata, file_links, file_descriptions, s3_link=s3_link
|
|
153
|
-
)
|
|
154
|
-
# Otherwise we add file links found in the mtadata file
|
|
155
|
-
elif ex_file_links:
|
|
156
|
-
metadata = add_file_links(
|
|
157
|
-
metadata, ex_file_links, ex_file_descriptions, s3_link=s3_link
|
|
158
|
-
)
|
|
159
|
-
|
|
160
132
|
if authors == False:
|
|
161
133
|
if production == True:
|
|
162
134
|
url = "https://data.caltech.edu/"
|
|
@@ -181,6 +153,18 @@ def caltechdata_edit(
|
|
|
181
153
|
"Content-type": "application/octet-stream",
|
|
182
154
|
}
|
|
183
155
|
|
|
156
|
+
# Add to community if provided:
|
|
157
|
+
if community:
|
|
158
|
+
result = requests.post(
|
|
159
|
+
url + "/api/records/" + idv + "/communities",
|
|
160
|
+
headers=headers,
|
|
161
|
+
data=json.dumps({"communities": [{"id": community}]}),
|
|
162
|
+
)
|
|
163
|
+
if result.status_code != 200:
|
|
164
|
+
print(result.url)
|
|
165
|
+
raise Exception(result.text)
|
|
166
|
+
caltechdata_accept([idv], token, production)
|
|
167
|
+
|
|
184
168
|
# Check status
|
|
185
169
|
existing = requests.get(
|
|
186
170
|
url + "/api/records/" + idv,
|
|
@@ -193,7 +177,14 @@ def caltechdata_edit(
|
|
|
193
177
|
headers=headers,
|
|
194
178
|
)
|
|
195
179
|
if existing.status_code != 200:
|
|
196
|
-
|
|
180
|
+
# Try back again to the record
|
|
181
|
+
existing = requests.get(
|
|
182
|
+
url + "/api/records/" + idv,
|
|
183
|
+
headers=headers,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if existing.status_code != 200:
|
|
187
|
+
raise Exception(f"Record {idv} does not exist, cannot edit")
|
|
197
188
|
|
|
198
189
|
existing = existing.json()
|
|
199
190
|
status = existing["status"]
|
|
@@ -287,10 +278,19 @@ def caltechdata_edit(
|
|
|
287
278
|
# We want to have the system set new DOIs
|
|
288
279
|
data["pids"] = {}
|
|
289
280
|
else:
|
|
290
|
-
if authors == False:
|
|
281
|
+
if authors == False and schema == "43":
|
|
291
282
|
metadata["pids"] = pids
|
|
292
283
|
data = customize_schema.customize_schema(metadata, schema=schema)
|
|
293
|
-
|
|
284
|
+
elif authors == False:
|
|
285
|
+
# Data using RDM schema, force oai PID
|
|
286
|
+
if "pids" not in metadata:
|
|
287
|
+
metadata["pids"] = {}
|
|
288
|
+
metadata["pids"]["oai"] = {
|
|
289
|
+
"identifier": f"oai:data.caltech.edu:{idv}",
|
|
290
|
+
"provider": "oai",
|
|
291
|
+
}
|
|
292
|
+
data = metadata
|
|
293
|
+
if authors == True:
|
|
294
294
|
# Authors, force oai PID
|
|
295
295
|
if "pids" not in metadata:
|
|
296
296
|
metadata["pids"] = {}
|
|
@@ -300,7 +300,21 @@ def caltechdata_edit(
|
|
|
300
300
|
}
|
|
301
301
|
data = metadata
|
|
302
302
|
|
|
303
|
-
|
|
303
|
+
# Check for existing draft
|
|
304
|
+
result = requests.get(
|
|
305
|
+
url + "/api/records/" + idv + "/draft",
|
|
306
|
+
headers=headers,
|
|
307
|
+
)
|
|
308
|
+
if result.status_code != 200:
|
|
309
|
+
# We make a draft
|
|
310
|
+
result = requests.post(
|
|
311
|
+
url + "/api/records/" + idv + "/draft",
|
|
312
|
+
headers=headers,
|
|
313
|
+
)
|
|
314
|
+
if result.status_code != 201:
|
|
315
|
+
raise Exception(result.text)
|
|
316
|
+
|
|
317
|
+
if files or file_links:
|
|
304
318
|
if default_preview:
|
|
305
319
|
data["files"] = {"enabled": True, "default_preview": default_preview}
|
|
306
320
|
else:
|
|
@@ -313,30 +327,15 @@ def caltechdata_edit(
|
|
|
313
327
|
)
|
|
314
328
|
if result.status_code != 200:
|
|
315
329
|
raise Exception(result.text)
|
|
316
|
-
|
|
317
|
-
|
|
330
|
+
file_upload_link = result.json()["links"]["files"]
|
|
331
|
+
if files:
|
|
332
|
+
write_files_rdm(
|
|
333
|
+
files, file_upload_link, headers, f_headers, keepfiles=keepfiles
|
|
334
|
+
)
|
|
335
|
+
if file_links:
|
|
336
|
+
add_file_links(file_upload_link, file_links, headers, keepfiles=keepfiles)
|
|
318
337
|
|
|
319
338
|
else:
|
|
320
|
-
# Check for existing draft
|
|
321
|
-
result = requests.get(
|
|
322
|
-
url + "/api/records/" + idv + "/draft",
|
|
323
|
-
headers=headers,
|
|
324
|
-
)
|
|
325
|
-
if result.status_code != 200:
|
|
326
|
-
# We make a draft
|
|
327
|
-
result = requests.post(
|
|
328
|
-
url + "/api/records/" + idv + "/draft",
|
|
329
|
-
json=data,
|
|
330
|
-
headers=headers,
|
|
331
|
-
)
|
|
332
|
-
if result.status_code != 201:
|
|
333
|
-
raise Exception(result.text)
|
|
334
|
-
result = requests.get(
|
|
335
|
-
url + "/api/records/" + idv,
|
|
336
|
-
headers=headers,
|
|
337
|
-
)
|
|
338
|
-
if result.status_code != 200:
|
|
339
|
-
raise Exception(result.text)
|
|
340
339
|
# We want files to stay the same as the existing record
|
|
341
340
|
data["files"] = existing["files"]
|
|
342
341
|
if default_preview:
|
|
@@ -348,13 +347,23 @@ def caltechdata_edit(
|
|
|
348
347
|
json=data,
|
|
349
348
|
)
|
|
350
349
|
if result.status_code != 200:
|
|
351
|
-
|
|
350
|
+
time.sleep(3)
|
|
351
|
+
result = requests.put(
|
|
352
|
+
url + "/api/records/" + idv + "/draft",
|
|
353
|
+
headers=headers,
|
|
354
|
+
json=data,
|
|
355
|
+
)
|
|
356
|
+
if result.status_code != 200:
|
|
357
|
+
raise Exception(result.text)
|
|
352
358
|
|
|
353
359
|
if publish:
|
|
354
360
|
publish_link = f"{url}/api/records/{idv}/draft/actions/publish"
|
|
355
361
|
result = requests.post(publish_link, headers=headers)
|
|
356
362
|
if result.status_code != 202:
|
|
357
|
-
|
|
363
|
+
time.sleep(3)
|
|
364
|
+
result = requests.post(publish_link, headers=headers)
|
|
365
|
+
if result.status_code != 202:
|
|
366
|
+
raise Exception(result.text)
|
|
358
367
|
if return_id:
|
|
359
368
|
return result.json()["id"]
|
|
360
369
|
else:
|
|
@@ -67,45 +67,40 @@ def write_files_rdm(
|
|
|
67
67
|
raise Exception(result.text)
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
def add_file_links(
|
|
71
|
-
metadata, file_links, file_descriptions=[], additional_descriptions="", s3_link=None
|
|
72
|
-
):
|
|
70
|
+
def add_file_links(file_upload_link, file_links, headers, keepfiles=False):
|
|
73
71
|
# Currently configured for S3 links, assuming all are at the same endpoint
|
|
74
72
|
link_string = ""
|
|
75
73
|
endpoint = "https://" + file_links[0].split("/")[2]
|
|
76
74
|
s3 = s3fs.S3FileSystem(anon=True, client_kwargs={"endpoint_url": endpoint})
|
|
77
75
|
index = 0
|
|
76
|
+
file_json = []
|
|
77
|
+
f_list = []
|
|
78
78
|
for link in file_links:
|
|
79
79
|
file = link.split("/")[-1]
|
|
80
|
+
f_list.append(file)
|
|
80
81
|
path = link.split(endpoint)[1]
|
|
81
82
|
size = s3.info(path)["size"]
|
|
82
|
-
size = humanbytes(size)
|
|
83
|
-
try:
|
|
84
|
-
description = file_descriptions[index]
|
|
85
|
-
if description != " ":
|
|
86
|
-
desc = description + ","
|
|
87
|
-
else:
|
|
88
|
-
desc = ""
|
|
89
|
-
except IndexError:
|
|
90
|
-
desc = ""
|
|
91
|
-
if link_string == "":
|
|
92
|
-
if s3_link:
|
|
93
|
-
link_string = f"Files available via S3 at {s3_link}</p></p>"
|
|
94
|
-
else:
|
|
95
|
-
cleaned = link.strip(file)
|
|
96
|
-
link_string = f"Files available via S3 at {cleaned}</p></p>"
|
|
97
|
-
link_string += f"""{file}, {desc} {size}
|
|
98
|
-
<p><a role="button" class="ui compact mini button" href="{link}"
|
|
99
|
-
> <i class="download icon"></i> Download </a></p></p></p>
|
|
100
|
-
"""
|
|
101
|
-
index += 1
|
|
102
|
-
# Tack on any additional descriptions
|
|
103
|
-
if additional_descriptions != "":
|
|
104
|
-
link_string += additional_descriptions
|
|
105
83
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
84
|
+
file_json.append(
|
|
85
|
+
{"key": file, "size": size, "transfer": {"type": "R", "url": link}}
|
|
86
|
+
)
|
|
87
|
+
# Now we see if any existing files need to be replaced
|
|
88
|
+
result = requests.get(file_upload_link, headers=headers)
|
|
89
|
+
if result.status_code == 200:
|
|
90
|
+
ex_files = result.json()["entries"]
|
|
91
|
+
for ex in ex_files:
|
|
92
|
+
if ex["key"] in f_list:
|
|
93
|
+
result = requests.delete(ex["links"]["self"], headers=headers)
|
|
94
|
+
if result.status_code != 204:
|
|
95
|
+
raise Exception(result.text)
|
|
96
|
+
else:
|
|
97
|
+
if keepfiles == False:
|
|
98
|
+
result = requests.delete(ex["links"]["self"], headers=headers)
|
|
99
|
+
if result.status_code != 204:
|
|
100
|
+
raise Exception(result.text)
|
|
101
|
+
result = requests.post(file_upload_link, headers=headers, json=file_json)
|
|
102
|
+
if result.status_code != 201:
|
|
103
|
+
raise Exception(result.text)
|
|
109
104
|
|
|
110
105
|
|
|
111
106
|
def send_to_community(
|
|
@@ -155,14 +150,13 @@ def caltechdata_write(
|
|
|
155
150
|
token=None,
|
|
156
151
|
files=[],
|
|
157
152
|
production=False,
|
|
158
|
-
schema=
|
|
153
|
+
schema=None,
|
|
159
154
|
publish=False,
|
|
160
155
|
file_links=[],
|
|
161
156
|
s3=None,
|
|
162
157
|
community=None,
|
|
163
158
|
authors=False,
|
|
164
159
|
file_descriptions=[],
|
|
165
|
-
s3_link=None,
|
|
166
160
|
default_preview=None,
|
|
167
161
|
review_message=None,
|
|
168
162
|
verify=True,
|
|
@@ -181,15 +175,25 @@ def caltechdata_write(
|
|
|
181
175
|
if not token:
|
|
182
176
|
token = os.environ["RDMTOK"]
|
|
183
177
|
|
|
178
|
+
if authors == False:
|
|
179
|
+
if production == True:
|
|
180
|
+
url = "https://data.caltech.edu/"
|
|
181
|
+
elif local == True:
|
|
182
|
+
url = "https://127.0.0.1:5000/"
|
|
183
|
+
else:
|
|
184
|
+
url = "https://data.caltechlibrary.dev/"
|
|
185
|
+
else:
|
|
186
|
+
if production == True:
|
|
187
|
+
url = "https://authors.library.caltech.edu/"
|
|
188
|
+
elif local == True:
|
|
189
|
+
url = "https://127.0.0.1:5000/"
|
|
190
|
+
else:
|
|
191
|
+
url = "https://authors.caltechlibrary.dev/"
|
|
192
|
+
|
|
184
193
|
# If files is a string - change to single value array
|
|
185
194
|
if isinstance(files, str) == True:
|
|
186
195
|
files = [files]
|
|
187
196
|
|
|
188
|
-
if file_links:
|
|
189
|
-
metadata = add_file_links(
|
|
190
|
-
metadata, file_links, file_descriptions, s3_link=s3_link
|
|
191
|
-
)
|
|
192
|
-
|
|
193
197
|
# Pull out pid information
|
|
194
198
|
if production == True:
|
|
195
199
|
repo_prefix = "10.22002"
|
|
@@ -235,22 +239,11 @@ def caltechdata_write(
|
|
|
235
239
|
if "pids" not in metadata:
|
|
236
240
|
metadata["pids"] = pids
|
|
237
241
|
|
|
238
|
-
if authors == False:
|
|
242
|
+
if authors == False and schema == "43":
|
|
239
243
|
data = customize_schema.customize_schema(metadata, schema=schema)
|
|
240
|
-
if production == True:
|
|
241
|
-
url = "https://data.caltech.edu/"
|
|
242
|
-
elif local == True:
|
|
243
|
-
url = "https://127.0.0.1:5000/"
|
|
244
|
-
else:
|
|
245
|
-
url = "https://data.caltechlibrary.dev/"
|
|
246
244
|
else:
|
|
245
|
+
# Using RDM schema, no customization
|
|
247
246
|
data = metadata
|
|
248
|
-
if production == True:
|
|
249
|
-
url = "https://authors.library.caltech.edu/"
|
|
250
|
-
elif local == True:
|
|
251
|
-
url = "https://127.0.0.1:5000/"
|
|
252
|
-
else:
|
|
253
|
-
url = "https://authors.caltechlibrary.dev/"
|
|
254
247
|
|
|
255
248
|
headers = {
|
|
256
249
|
"Authorization": "Bearer %s" % token,
|
|
@@ -261,10 +254,13 @@ def caltechdata_write(
|
|
|
261
254
|
"Content-type": "application/octet-stream",
|
|
262
255
|
}
|
|
263
256
|
|
|
264
|
-
if
|
|
257
|
+
if files or file_links:
|
|
258
|
+
if default_preview:
|
|
259
|
+
data["files"] = {"enabled": True, "default_preview": default_preview}
|
|
260
|
+
else:
|
|
261
|
+
data["files"] = {"enabled": True}
|
|
262
|
+
else:
|
|
265
263
|
data["files"] = {"enabled": False}
|
|
266
|
-
elif default_preview:
|
|
267
|
-
data["files"] = {"enabled": True, "default_preview": default_preview}
|
|
268
264
|
|
|
269
265
|
# Make draft and publish
|
|
270
266
|
result = requests.post(
|
|
@@ -277,11 +273,14 @@ def caltechdata_write(
|
|
|
277
273
|
raise Exception(result.text)
|
|
278
274
|
idv = result.json()["id"]
|
|
279
275
|
publish_link = result.json()["links"]["publish"]
|
|
276
|
+
file_link = result.json()["links"]["files"]
|
|
280
277
|
|
|
281
278
|
if files:
|
|
282
|
-
file_link = result.json()["links"]["files"]
|
|
283
279
|
write_files_rdm(files, file_link, headers, f_headers, s3, verify=verify)
|
|
284
280
|
|
|
281
|
+
if file_links:
|
|
282
|
+
add_file_links(file_link, file_links, headers)
|
|
283
|
+
|
|
285
284
|
if community:
|
|
286
285
|
review_link = result.json()["links"]["review"]
|
|
287
286
|
send_to_community(
|
|
@@ -173,11 +173,9 @@ def get_funding_details():
|
|
|
173
173
|
award_number = get_user_input("Enter the award number for funding: ")
|
|
174
174
|
award_exists = check_award_number(award_number)
|
|
175
175
|
if not award_exists:
|
|
176
|
-
print(
|
|
177
|
-
f"""Error: No award with number '{award_number}' found in
|
|
176
|
+
print(f"""Error: No award with number '{award_number}' found in
|
|
178
177
|
CaltechDATA. You will need to provide more details about the
|
|
179
|
-
funding."""
|
|
180
|
-
)
|
|
178
|
+
funding.""")
|
|
181
179
|
award_title = get_user_input("Enter the award title for funding: ")
|
|
182
180
|
while True:
|
|
183
181
|
funder_identifier = get_user_input("Enter the funder ROR (https://ror.org): ")
|
|
@@ -185,11 +183,9 @@ def get_funding_details():
|
|
|
185
183
|
if name:
|
|
186
184
|
break
|
|
187
185
|
else:
|
|
188
|
-
print(
|
|
189
|
-
"""This funder identifier is not a ROR. Please enter a valid
|
|
186
|
+
print("""This funder identifier is not a ROR. Please enter a valid
|
|
190
187
|
ROR identifier (without the url). For example the ROR for the
|
|
191
|
-
NSF is 021nxhr62."""
|
|
192
|
-
)
|
|
188
|
+
NSF is 021nxhr62.""")
|
|
193
189
|
print("-" * 10)
|
|
194
190
|
return {
|
|
195
191
|
"awardNumber": award_number,
|
|
@@ -349,14 +345,12 @@ def write_s3cmd_config(endpoint):
|
|
|
349
345
|
access_key = get_user_input("Enter the access key: ")
|
|
350
346
|
secret_key = get_user_input("Enter the secret key: ")
|
|
351
347
|
with open(configf, "w") as file:
|
|
352
|
-
file.write(
|
|
353
|
-
f"""[default]
|
|
348
|
+
file.write(f"""[default]
|
|
354
349
|
access_key = {access_key}
|
|
355
350
|
host_base = {endpoint}
|
|
356
351
|
host_bucket = %(bucket).{endpoint}
|
|
357
352
|
secret_key = {secret_key}
|
|
358
|
-
"""
|
|
359
|
-
)
|
|
353
|
+
""")
|
|
360
354
|
|
|
361
355
|
|
|
362
356
|
def upload_supporting_file(record_id=None):
|
|
@@ -370,8 +364,8 @@ def upload_supporting_file(record_id=None):
|
|
|
370
364
|
"Do you want to upload or link data files? (upload/link/n): "
|
|
371
365
|
).lower()
|
|
372
366
|
if choice == "link":
|
|
373
|
-
endpoint = "
|
|
374
|
-
path = "
|
|
367
|
+
endpoint = "caltech2.osn.mghpcc.org"
|
|
368
|
+
path = "caltechdata-public/"
|
|
375
369
|
if not record_id:
|
|
376
370
|
write_s3cmd_config(endpoint)
|
|
377
371
|
print("""S3 connection configured.""")
|
|
@@ -431,11 +425,9 @@ def upload_supporting_file(record_id=None):
|
|
|
431
425
|
elif filename in files:
|
|
432
426
|
file_size = os.path.getsize(filename)
|
|
433
427
|
if file_size > 1024 * 1024 * 1024:
|
|
434
|
-
print(
|
|
435
|
-
"""The file is greater than 1 GB. Please upload the
|
|
428
|
+
print("""The file is greater than 1 GB. Please upload the
|
|
436
429
|
metadata to CaltechDATA, and you'll be provided
|
|
437
|
-
instructions to upload the files to S3 directly."""
|
|
438
|
-
)
|
|
430
|
+
instructions to upload the files to S3 directly.""")
|
|
439
431
|
else:
|
|
440
432
|
filepath = os.path.abspath(filename)
|
|
441
433
|
filepaths.append(filepath)
|
|
@@ -643,12 +635,10 @@ def print_upload_message(rec_id, production):
|
|
|
643
635
|
if production
|
|
644
636
|
else "https://data.caltechlibrary.dev/uploads/"
|
|
645
637
|
)
|
|
646
|
-
print(
|
|
647
|
-
f"""You can view and publish this record at
|
|
638
|
+
print(f"""You can view and publish this record at
|
|
648
639
|
{base_url}{rec_id}
|
|
649
640
|
If you need to upload large files to S3, you can type
|
|
650
|
-
`s3cmd put DATA_FILE s3://ini230004-bucket01/{rec_id}/`"""
|
|
651
|
-
)
|
|
641
|
+
`s3cmd put DATA_FILE s3://ini230004-bucket01/{rec_id}/`""")
|
|
652
642
|
|
|
653
643
|
|
|
654
644
|
def edit_record(production):
|
|
@@ -7,28 +7,6 @@ from pathlib import Path
|
|
|
7
7
|
import requests
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def grid_to_ror(grid):
|
|
11
|
-
# Temporary until InvenioRDM stops spitting out GRIDS
|
|
12
|
-
# We manually handle some incorrect/redundant GRID Ids
|
|
13
|
-
if grid == "grid.451078.f":
|
|
14
|
-
ror = "00hm6j694"
|
|
15
|
-
elif grid == "grid.5805.8":
|
|
16
|
-
ror = "02en5vm52"
|
|
17
|
-
elif grid == "grid.465477.3":
|
|
18
|
-
ror = "00em52312"
|
|
19
|
-
else:
|
|
20
|
-
url = (
|
|
21
|
-
f"https://api.ror.org/organizations?query.advanced=external_ids.all:{grid}"
|
|
22
|
-
)
|
|
23
|
-
results = requests.get(url).json()
|
|
24
|
-
if len(results["items"]) == 0:
|
|
25
|
-
print(url + "doesn't have a valid ROR")
|
|
26
|
-
exit()
|
|
27
|
-
ror = results["items"][0]["id"]
|
|
28
|
-
ror = ror.split("ror.org/")[1]
|
|
29
|
-
return ror
|
|
30
|
-
|
|
31
|
-
|
|
32
10
|
def get_vocabularies():
|
|
33
11
|
"""Returns dictionary of vocabularies"""
|
|
34
12
|
path = Path(__file__).parent
|
|
@@ -297,7 +275,7 @@ def customize_schema_rdm(json_record):
|
|
|
297
275
|
if "geoLocationPoint" in location:
|
|
298
276
|
lat = location["geoLocationPoint"]["pointLatitude"]
|
|
299
277
|
lon = location["geoLocationPoint"]["pointLongitude"]
|
|
300
|
-
new["geometry"] = {"type": "Point", "coordinates": [
|
|
278
|
+
new["geometry"] = {"type": "Point", "coordinates": [lon, lat]}
|
|
301
279
|
if "geoLocationBox" in location:
|
|
302
280
|
south = float(location["geoLocationBox"]["southBoundLatitude"])
|
|
303
281
|
north = float(location["geoLocationBox"]["northBoundLatitude"])
|
|
@@ -307,11 +285,11 @@ def customize_schema_rdm(json_record):
|
|
|
307
285
|
"type": "Polygon",
|
|
308
286
|
"coordinates": [
|
|
309
287
|
[
|
|
310
|
-
[
|
|
311
|
-
[
|
|
312
|
-
[
|
|
313
|
-
[
|
|
314
|
-
[
|
|
288
|
+
[east, north],
|
|
289
|
+
[west, north],
|
|
290
|
+
[west, south],
|
|
291
|
+
[east, south],
|
|
292
|
+
[east, north],
|
|
315
293
|
]
|
|
316
294
|
],
|
|
317
295
|
}
|
|
@@ -335,11 +313,6 @@ def customize_schema_rdm(json_record):
|
|
|
335
313
|
ror = ror.split("ror.org/")[1]
|
|
336
314
|
funder["id"] = ror
|
|
337
315
|
fund.pop("funderIdentifierType")
|
|
338
|
-
elif fund["funderIdentifierType"] == "GRID":
|
|
339
|
-
# We need this temporarily to round-trip data
|
|
340
|
-
ror = grid_to_ror(fund.pop("funderIdentifier"))
|
|
341
|
-
funder["id"] = ror
|
|
342
|
-
fund.pop("funderIdentifierType")
|
|
343
316
|
else:
|
|
344
317
|
print(f'Unknown Type mapping {fund["funderIdentifierType"]}')
|
|
345
318
|
if "awardTitle" in fund:
|
|
@@ -568,8 +541,6 @@ def validate_metadata(json_record):
|
|
|
568
541
|
else:
|
|
569
542
|
|
|
570
543
|
for geo_loc in json_record["geoLocations"]:
|
|
571
|
-
if not isinstance(geo_loc, dict) or "geoLocationPlace" not in geo_loc:
|
|
572
|
-
errors.append("Each 'geoLocation' must have 'geoLocationPlace'.")
|
|
573
544
|
if "geoLocationPoint" in geo_loc:
|
|
574
545
|
point = geo_loc["geoLocationPoint"]
|
|
575
546
|
if (
|
|
@@ -12,11 +12,11 @@ def get_metadata(
|
|
|
12
12
|
production=True,
|
|
13
13
|
validate=True,
|
|
14
14
|
emails=False,
|
|
15
|
-
schema=
|
|
15
|
+
schema=None,
|
|
16
16
|
token=False,
|
|
17
17
|
authors=False,
|
|
18
18
|
):
|
|
19
|
-
# Returns just DataCite metadata or DataCite metadata with emails
|
|
19
|
+
# Returns InvenioRDM metadata, or just DataCite metadata, or DataCite metadata with emails
|
|
20
20
|
|
|
21
21
|
if production == True:
|
|
22
22
|
if authors:
|
|
@@ -35,7 +35,7 @@ def get_metadata(
|
|
|
35
35
|
"accept": "application/json",
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
if authors:
|
|
38
|
+
if authors or schema == None:
|
|
39
39
|
headers = base_headers
|
|
40
40
|
validate = False
|
|
41
41
|
else:
|
|
@@ -114,7 +114,7 @@ if __name__ == "__main__":
|
|
|
114
114
|
action="store_true",
|
|
115
115
|
help="skip validation of metadata",
|
|
116
116
|
)
|
|
117
|
-
parser.add_argument("-schema", default=
|
|
117
|
+
parser.add_argument("-schema", default=None, help="Schema Version")
|
|
118
118
|
|
|
119
119
|
args = parser.parse_args()
|
|
120
120
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: caltechdata_api
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Python wrapper for CaltechDATA API.
|
|
5
5
|
Home-page: https://github.com/caltechlibrary/caltechdata_api
|
|
6
6
|
Author: Thomas E Morrell, Rohan Bhattarai, Elizabeth Won, Alexander A Abakah, Kshemaahna Nagi
|
|
@@ -24,6 +24,7 @@ Requires-Dist: pyyaml
|
|
|
24
24
|
Requires-Dist: s3fs
|
|
25
25
|
Requires-Dist: cryptography
|
|
26
26
|
Requires-Dist: s3cmd
|
|
27
|
+
Requires-Dist: jsonschema-specifications
|
|
27
28
|
Dynamic: license-file
|
|
28
29
|
|
|
29
30
|
# CaltechDATA API Python Library
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[metadata]
|
|
6
6
|
name = caltechdata_api
|
|
7
|
-
version =
|
|
7
|
+
version = 2.0.0
|
|
8
8
|
author = Thomas E Morrell, Rohan Bhattarai, Elizabeth Won, Alexander A Abakah, Kshemaahna Nagi
|
|
9
9
|
author_email = tmorrell@caltech.edu, aabakah@caltech.edu, knagi@caltech.edu
|
|
10
10
|
description = Python wrapper for CaltechDATA API.
|
|
@@ -33,6 +33,7 @@ install_requires =
|
|
|
33
33
|
s3fs
|
|
34
34
|
cryptography
|
|
35
35
|
s3cmd
|
|
36
|
+
jsonschema-specifications
|
|
36
37
|
include_package_data = True
|
|
37
38
|
|
|
38
39
|
[options.packages.find]
|
|
@@ -68,8 +68,7 @@ def test_datacite_rdm_create_edit(full_datacite43_record):
|
|
|
68
68
|
|
|
69
69
|
assert doi.startswith("10.33569")
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
new_metadata = get_metadata(recid, production=False, validate=False)
|
|
71
|
+
new_metadata = get_metadata(recid, production=False, schema="43")
|
|
73
72
|
|
|
74
73
|
assert new_metadata["publisher"] == "Edited"
|
|
75
74
|
|
|
@@ -89,7 +88,6 @@ def test_datacite_rdm_create_edit(full_datacite43_record):
|
|
|
89
88
|
|
|
90
89
|
recid = new_doi.split("/")[1]
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
new_metadata = get_metadata(recid, production=False, validate=False)
|
|
91
|
+
new_metadata = get_metadata(recid, production=False, schema="43")
|
|
94
92
|
|
|
95
93
|
assert new_metadata["publisher"] == "Again!"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/date_types.yaml
RENAMED
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/description_types.yaml
RENAMED
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/identifier_types.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/relation_types.yaml
RENAMED
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/resource_types.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api/vocabularies/title_types.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caltechdata_api-1.10.6 → caltechdata_api-2.0.0}/caltechdata_api.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|