caltechdata-api 1.11.0__tar.gz → 2.1.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.
Files changed (37) hide show
  1. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/PKG-INFO +31 -14
  2. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/README.md +17 -5
  3. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/caltechdata_edit.py +57 -64
  4. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/caltechdata_write.py +52 -53
  5. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/cli.py +2 -2
  6. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/customize_schema.py +6 -35
  7. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/get_metadata.py +4 -4
  8. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api.egg-info/PKG-INFO +31 -14
  9. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api.egg-info/SOURCES.txt +0 -2
  10. caltechdata_api-2.1.0/pyproject.toml +69 -0
  11. caltechdata_api-2.1.0/setup.cfg +4 -0
  12. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/tests/test_rdm.py +8 -6
  13. caltechdata_api-2.1.0/tests/test_unit.py +76 -0
  14. caltechdata_api-1.11.0/pyproject.toml +0 -3
  15. caltechdata_api-1.11.0/setup.cfg +0 -55
  16. caltechdata_api-1.11.0/setup.py +0 -3
  17. caltechdata_api-1.11.0/tests/test_unit.py +0 -166
  18. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/LICENSE +0 -0
  19. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/__init__.py +0 -0
  20. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/download_file.py +0 -0
  21. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/get_files.py +0 -0
  22. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/md_to_json.py +0 -0
  23. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/utils.py +0 -0
  24. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/date_types.yaml +0 -0
  25. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/description_types.yaml +0 -0
  26. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/identifier_types.yaml +0 -0
  27. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/licenses.csv +0 -0
  28. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/relation_types.yaml +0 -0
  29. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/resource_types.yaml +0 -0
  30. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/roles.yaml +0 -0
  31. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies/title_types.yaml +0 -0
  32. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api/vocabularies.yaml +0 -0
  33. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api.egg-info/dependency_links.txt +0 -0
  34. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api.egg-info/entry_points.txt +0 -0
  35. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api.egg-info/requires.txt +0 -0
  36. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/caltechdata_api.egg-info/top_level.txt +0 -0
  37. {caltechdata_api-1.11.0 → caltechdata_api-2.1.0}/tests/test_download.py +0 -0
@@ -1,20 +1,25 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: caltechdata_api
3
- Version: 1.11.0
3
+ Version: 2.1.0
4
4
  Summary: Python wrapper for CaltechDATA API.
5
- Home-page: https://github.com/caltechlibrary/caltechdata_api
6
- Author: Thomas E Morrell, Rohan Bhattarai, Elizabeth Won, Alexander A Abakah, Kshemaahna Nagi
7
- Author-email: tmorrell@caltech.edu, aabakah@caltech.edu, knagi@caltech.edu
8
- License: MIT
9
- Classifier: License :: OSI Approved :: MIT License
5
+ Author: Rohan Bhattarai, Elizabeth Won
6
+ Author-email: Thomas E Morrell <tmorrell@caltech.edu>, Alexander A Abakah <aabakah@caltech.edu>, Kshemaahna Nagi <knagi@caltech.edu>
7
+ Maintainer-email: Thomas E Morrell <tmorrell@caltech.edu>
8
+ License-Expression: BSD-3-Clause
9
+ Project-URL: Homepage, https://github.com/caltechlibrary/caltechdata_api
10
+ Project-URL: Repository, https://github.com/caltechlibrary/caltechdata_api
11
+ Project-URL: Issues, https://github.com/caltechlibrary/caltechdata_api/issues
12
+ Keywords: metadata,software,InvenioRDM
10
13
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.7
12
- Classifier: Programming Language :: Python :: 3.8
13
14
  Classifier: Programming Language :: Python :: 3.9
14
15
  Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
15
20
  Classifier: Programming Language :: Python :: Implementation :: CPython
16
21
  Classifier: Operating System :: OS Independent
17
- Requires-Python: >=3.6.0
22
+ Requires-Python: >=3.9
18
23
  Description-Content-Type: text/markdown
19
24
  License-File: LICENSE
20
25
  Requires-Dist: requests
@@ -44,7 +49,7 @@ The `caltechdata_api` Python library provides a convenient interface for interac
44
49
 
45
50
  ## Requirements
46
51
 
47
- - Python 3.6+
52
+ - Python 3.9+
48
53
 
49
54
  ## Installation
50
55
 
@@ -54,6 +59,18 @@ Install the library via pip:
54
59
  pip install caltechdata_api
55
60
  ```
56
61
 
62
+ Or add it to a [uv](https://docs.astral.sh/uv/) project:
63
+
64
+ ```shell
65
+ uv add caltechdata_api
66
+ ```
67
+
68
+ You can also run a script using uv:
69
+
70
+ ```shell
71
+ uv run write.py
72
+ ```
73
+
57
74
  ## Examples
58
75
 
59
76
  There are some example python scripts in the GitHub repository.
@@ -61,7 +78,7 @@ There are some example python scripts in the GitHub repository.
61
78
  ### Create a record:
62
79
 
63
80
  ```shell
64
- python write.py example.json -fnames logo.gif
81
+ uv run write.py example.json -fnames logo.gif
65
82
  # Output: pbkn6-m9y63 (unique identifier)
66
83
  ```
67
84
  > The response will be the unique identifier for the record. You can put this at
@@ -71,7 +88,7 @@ https://data.caltechlibrary.dev/records/pbkn6-m9y63)
71
88
  ### Edit a record
72
89
  Make changes to the example.json file to see a change)
73
90
  ```
74
- python edit.py example.json -id pbkn6-m9y63
91
+ uv run edit.py example.json -id pbkn6-m9y63
75
92
  10.33569/pbkn6-m9y63
76
93
  ```
77
94
  > The response is the DOI for the record, which includes the unique identifier
@@ -82,13 +99,13 @@ Some groups have worked with the library to create custom DOIs. These can be
82
99
  passed in the metadata like:
83
100
 
84
101
  ```shell
85
- python write.py example_custom.json -fnames logo.gif
102
+ uv run write.py example_custom.json -fnames logo.gif
86
103
  m6zxz-p4j22
87
104
  ```
88
105
 
89
106
  And then you can edit with
90
107
  ```
91
- python edit.py example_custom.json -id m6zxz-p4j22
108
+ uv run edit.py example_custom.json -id m6zxz-p4j22
92
109
  10.5281/inveniordm.1234
93
110
  ```
94
111
 
@@ -15,7 +15,7 @@ The `caltechdata_api` Python library provides a convenient interface for interac
15
15
 
16
16
  ## Requirements
17
17
 
18
- - Python 3.6+
18
+ - Python 3.9+
19
19
 
20
20
  ## Installation
21
21
 
@@ -25,6 +25,18 @@ Install the library via pip:
25
25
  pip install caltechdata_api
26
26
  ```
27
27
 
28
+ Or add it to a [uv](https://docs.astral.sh/uv/) project:
29
+
30
+ ```shell
31
+ uv add caltechdata_api
32
+ ```
33
+
34
+ You can also run a script using uv:
35
+
36
+ ```shell
37
+ uv run write.py
38
+ ```
39
+
28
40
  ## Examples
29
41
 
30
42
  There are some example python scripts in the GitHub repository.
@@ -32,7 +44,7 @@ There are some example python scripts in the GitHub repository.
32
44
  ### Create a record:
33
45
 
34
46
  ```shell
35
- python write.py example.json -fnames logo.gif
47
+ uv run write.py example.json -fnames logo.gif
36
48
  # Output: pbkn6-m9y63 (unique identifier)
37
49
  ```
38
50
  > The response will be the unique identifier for the record. You can put this at
@@ -42,7 +54,7 @@ https://data.caltechlibrary.dev/records/pbkn6-m9y63)
42
54
  ### Edit a record
43
55
  Make changes to the example.json file to see a change)
44
56
  ```
45
- python edit.py example.json -id pbkn6-m9y63
57
+ uv run edit.py example.json -id pbkn6-m9y63
46
58
  10.33569/pbkn6-m9y63
47
59
  ```
48
60
  > The response is the DOI for the record, which includes the unique identifier
@@ -53,13 +65,13 @@ Some groups have worked with the library to create custom DOIs. These can be
53
65
  passed in the metadata like:
54
66
 
55
67
  ```shell
56
- python write.py example_custom.json -fnames logo.gif
68
+ uv run write.py example_custom.json -fnames logo.gif
57
69
  m6zxz-p4j22
58
70
  ```
59
71
 
60
72
  And then you can edit with
61
73
  ```
62
- python edit.py example_custom.json -id m6zxz-p4j22
74
+ uv run edit.py example_custom.json -id m6zxz-p4j22
63
75
  10.5281/inveniordm.1234
64
76
  ```
65
77
 
@@ -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
- accept_link = result.json()["links"]["actions"]["accept"]
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="43",
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,
@@ -294,10 +278,19 @@ def caltechdata_edit(
294
278
  # We want to have the system set new DOIs
295
279
  data["pids"] = {}
296
280
  else:
297
- if authors == False:
281
+ if authors == False and schema == "43":
298
282
  metadata["pids"] = pids
299
283
  data = customize_schema.customize_schema(metadata, schema=schema)
300
- else:
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:
301
294
  # Authors, force oai PID
302
295
  if "pids" not in metadata:
303
296
  metadata["pids"] = {}
@@ -307,7 +300,21 @@ def caltechdata_edit(
307
300
  }
308
301
  data = metadata
309
302
 
310
- if files:
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:
311
318
  if default_preview:
312
319
  data["files"] = {"enabled": True, "default_preview": default_preview}
313
320
  else:
@@ -320,29 +327,15 @@ def caltechdata_edit(
320
327
  )
321
328
  if result.status_code != 200:
322
329
  raise Exception(result.text)
323
- file_link = result.json()["links"]["files"]
324
- write_files_rdm(files, file_link, headers, f_headers, keepfiles=keepfiles)
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)
325
337
 
326
338
  else:
327
- # Check for existing draft
328
- result = requests.get(
329
- url + "/api/records/" + idv + "/draft",
330
- headers=headers,
331
- )
332
- if result.status_code != 200:
333
- # We make a draft
334
- result = requests.post(
335
- url + "/api/records/" + idv + "/draft",
336
- headers=headers,
337
- )
338
- if result.status_code != 201:
339
- time.sleep(3)
340
- result = requests.post(
341
- url + "/api/records/" + idv + "/draft",
342
- headers=headers,
343
- )
344
- if result.status_code != 201:
345
- raise Exception(result.text)
346
339
  # We want files to stay the same as the existing record
347
340
  data["files"] = existing["files"]
348
341
  if default_preview:
@@ -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}&lt;/p&gt;</p>"
94
- else:
95
- cleaned = link.strip(file)
96
- link_string = f"Files available via S3 at {cleaned}&lt;/p&gt;</p>"
97
- link_string += f"""{file}, {desc} {size}
98
- <p>&lt;a role="button" class="ui compact mini button" href="{link}"
99
- &gt; &lt;i class="download icon"&gt;&lt;/i&gt; Download &lt;/a&gt;</p>&lt;/p&gt;</p>
100
- """
101
- index += 1
102
- # Tack on any additional descriptions
103
- if additional_descriptions != "":
104
- link_string += additional_descriptions
105
83
 
106
- description = {"description": link_string, "descriptionType": "files"}
107
- metadata["descriptions"].append(description)
108
- return metadata
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="43",
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 not files:
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(
@@ -364,8 +364,8 @@ def upload_supporting_file(record_id=None):
364
364
  "Do you want to upload or link data files? (upload/link/n): "
365
365
  ).lower()
366
366
  if choice == "link":
367
- endpoint = "sdsc.osn.xsede.org"
368
- path = "ini230004-bucket01/"
367
+ endpoint = "caltech2.osn.mghpcc.org"
368
+ path = "caltechdata-public/"
369
369
  if not record_id:
370
370
  write_s3cmd_config(endpoint)
371
371
  print("""S3 connection configured.""")
@@ -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": [lat, lon]}
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
- [north, east],
311
- [north, west],
312
- [south, west],
313
- [south, east],
314
- [north, east],
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="43",
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="43", help="Schema Version")
117
+ parser.add_argument("-schema", default=None, help="Schema Version")
118
118
 
119
119
  args = parser.parse_args()
120
120
 
@@ -1,20 +1,25 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: caltechdata_api
3
- Version: 1.11.0
3
+ Version: 2.1.0
4
4
  Summary: Python wrapper for CaltechDATA API.
5
- Home-page: https://github.com/caltechlibrary/caltechdata_api
6
- Author: Thomas E Morrell, Rohan Bhattarai, Elizabeth Won, Alexander A Abakah, Kshemaahna Nagi
7
- Author-email: tmorrell@caltech.edu, aabakah@caltech.edu, knagi@caltech.edu
8
- License: MIT
9
- Classifier: License :: OSI Approved :: MIT License
5
+ Author: Rohan Bhattarai, Elizabeth Won
6
+ Author-email: Thomas E Morrell <tmorrell@caltech.edu>, Alexander A Abakah <aabakah@caltech.edu>, Kshemaahna Nagi <knagi@caltech.edu>
7
+ Maintainer-email: Thomas E Morrell <tmorrell@caltech.edu>
8
+ License-Expression: BSD-3-Clause
9
+ Project-URL: Homepage, https://github.com/caltechlibrary/caltechdata_api
10
+ Project-URL: Repository, https://github.com/caltechlibrary/caltechdata_api
11
+ Project-URL: Issues, https://github.com/caltechlibrary/caltechdata_api/issues
12
+ Keywords: metadata,software,InvenioRDM
10
13
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.7
12
- Classifier: Programming Language :: Python :: 3.8
13
14
  Classifier: Programming Language :: Python :: 3.9
14
15
  Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
15
20
  Classifier: Programming Language :: Python :: Implementation :: CPython
16
21
  Classifier: Operating System :: OS Independent
17
- Requires-Python: >=3.6.0
22
+ Requires-Python: >=3.9
18
23
  Description-Content-Type: text/markdown
19
24
  License-File: LICENSE
20
25
  Requires-Dist: requests
@@ -44,7 +49,7 @@ The `caltechdata_api` Python library provides a convenient interface for interac
44
49
 
45
50
  ## Requirements
46
51
 
47
- - Python 3.6+
52
+ - Python 3.9+
48
53
 
49
54
  ## Installation
50
55
 
@@ -54,6 +59,18 @@ Install the library via pip:
54
59
  pip install caltechdata_api
55
60
  ```
56
61
 
62
+ Or add it to a [uv](https://docs.astral.sh/uv/) project:
63
+
64
+ ```shell
65
+ uv add caltechdata_api
66
+ ```
67
+
68
+ You can also run a script using uv:
69
+
70
+ ```shell
71
+ uv run write.py
72
+ ```
73
+
57
74
  ## Examples
58
75
 
59
76
  There are some example python scripts in the GitHub repository.
@@ -61,7 +78,7 @@ There are some example python scripts in the GitHub repository.
61
78
  ### Create a record:
62
79
 
63
80
  ```shell
64
- python write.py example.json -fnames logo.gif
81
+ uv run write.py example.json -fnames logo.gif
65
82
  # Output: pbkn6-m9y63 (unique identifier)
66
83
  ```
67
84
  > The response will be the unique identifier for the record. You can put this at
@@ -71,7 +88,7 @@ https://data.caltechlibrary.dev/records/pbkn6-m9y63)
71
88
  ### Edit a record
72
89
  Make changes to the example.json file to see a change)
73
90
  ```
74
- python edit.py example.json -id pbkn6-m9y63
91
+ uv run edit.py example.json -id pbkn6-m9y63
75
92
  10.33569/pbkn6-m9y63
76
93
  ```
77
94
  > The response is the DOI for the record, which includes the unique identifier
@@ -82,13 +99,13 @@ Some groups have worked with the library to create custom DOIs. These can be
82
99
  passed in the metadata like:
83
100
 
84
101
  ```shell
85
- python write.py example_custom.json -fnames logo.gif
102
+ uv run write.py example_custom.json -fnames logo.gif
86
103
  m6zxz-p4j22
87
104
  ```
88
105
 
89
106
  And then you can edit with
90
107
  ```
91
- python edit.py example_custom.json -id m6zxz-p4j22
108
+ uv run edit.py example_custom.json -id m6zxz-p4j22
92
109
  10.5281/inveniordm.1234
93
110
  ```
94
111
 
@@ -1,8 +1,6 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
- setup.cfg
5
- setup.py
6
4
  caltechdata_api/__init__.py
7
5
  caltechdata_api/caltechdata_edit.py
8
6
  caltechdata_api/caltechdata_write.py
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "caltechdata_api"
7
+ version = "2.1.0"
8
+ description = "Python wrapper for CaltechDATA API."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "BSD-3-Clause"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ {name = "Thomas E Morrell", email = "tmorrell@caltech.edu"},
15
+ {name = "Rohan Bhattarai"},
16
+ {name = "Elizabeth Won"},
17
+ {name = "Alexander A Abakah", email = "aabakah@caltech.edu"},
18
+ {name = "Kshemaahna Nagi", email = "knagi@caltech.edu"},
19
+ ]
20
+ maintainers = [
21
+ {name = "Thomas E Morrell", email = "tmorrell@caltech.edu"},
22
+ ]
23
+ keywords = ["metadata", "software", "InvenioRDM"]
24
+ classifiers = [
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.9",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ "Programming Language :: Python :: 3.13",
31
+ "Programming Language :: Python :: 3.14",
32
+ "Programming Language :: Python :: Implementation :: CPython",
33
+ "Operating System :: OS Independent",
34
+ ]
35
+ dependencies = [
36
+ "requests",
37
+ "datacite>1.1.0",
38
+ "tqdm>=4.62.3",
39
+ "pyyaml",
40
+ "s3fs",
41
+ "cryptography",
42
+ "s3cmd",
43
+ "jsonschema-specifications",
44
+ ]
45
+
46
+ [project.urls]
47
+ Homepage = "https://github.com/caltechlibrary/caltechdata_api"
48
+ Repository = "https://github.com/caltechlibrary/caltechdata_api"
49
+ Issues = "https://github.com/caltechlibrary/caltechdata_api/issues"
50
+
51
+ [project.scripts]
52
+ caltechdata_api = "caltechdata_api.cli:main"
53
+
54
+ [dependency-groups]
55
+ dev = [
56
+ "pytest>=7.0",
57
+ "black",
58
+ ]
59
+
60
+ [tool.setuptools.packages.find]
61
+ include = ["caltechdata_api*"]
62
+
63
+ [tool.setuptools.package-data]
64
+ caltechdata_api = ["vocabularies.yaml", "vocabularies/*"]
65
+
66
+ [tool.pytest.ini_options]
67
+ addopts = "--verbose"
68
+ testpaths = ["tests"]
69
+ pythonpath = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -7,6 +7,10 @@ from caltechdata_api import (
7
7
  import json
8
8
  import os
9
9
 
10
+ # Any file will do here, we just need something to attach to the test records
11
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
12
+ UPLOAD_FILE = os.path.join(BASE_DIR, "helpers.py")
13
+
10
14
 
11
15
  def test_datacite_rdm_conversion(full_datacite43_record, full_rdm_record):
12
16
 
@@ -48,7 +52,7 @@ def test_datacite_rdm_create_edit(full_datacite43_record):
48
52
  full_datacite43_record,
49
53
  schema="43",
50
54
  production=False,
51
- files=["helpers.py"],
55
+ files=[UPLOAD_FILE],
52
56
  publish=True,
53
57
  token=env_token,
54
58
  )
@@ -68,8 +72,7 @@ def test_datacite_rdm_create_edit(full_datacite43_record):
68
72
 
69
73
  assert doi.startswith("10.33569")
70
74
 
71
- # Validate is false until geolocation points are fixed/we move to 4.6
72
- new_metadata = get_metadata(recid, production=False, validate=False)
75
+ new_metadata = get_metadata(recid, production=False, schema="43")
73
76
 
74
77
  assert new_metadata["publisher"] == "Edited"
75
78
 
@@ -78,7 +81,7 @@ def test_datacite_rdm_create_edit(full_datacite43_record):
78
81
  new_doi = caltechdata_edit(
79
82
  recid,
80
83
  full_datacite43_record,
81
- files=["helpers.py"],
84
+ files=[UPLOAD_FILE],
82
85
  schema="43",
83
86
  production=False,
84
87
  publish=True,
@@ -89,7 +92,6 @@ def test_datacite_rdm_create_edit(full_datacite43_record):
89
92
 
90
93
  recid = new_doi.split("/")[1]
91
94
 
92
- # Validate is false until geolocation points are fixed/we move to 4.6
93
- new_metadata = get_metadata(recid, production=False, validate=False)
95
+ new_metadata = get_metadata(recid, production=False, schema="43")
94
96
 
95
97
  assert new_metadata["publisher"] == "Again!"
@@ -0,0 +1,76 @@
1
+ import os
2
+ import pytest
3
+ import logging
4
+ from caltechdata_api import validate_metadata as validator43
5
+ from helpers import load_json_path
6
+
7
+ # Configure logging
8
+ logging.basicConfig(level=logging.DEBUG)
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # Dynamically determine the base path
12
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13
+ INVALID_DATACITE43_DIR = os.path.join(BASE_DIR, "data", "invalid_datacite43")
14
+
15
+
16
+ # Function to get all JSON files in the directory
17
+ def get_all_json_files(directory):
18
+ return [
19
+ os.path.join(directory, f) for f in os.listdir(directory) if f.endswith(".json")
20
+ ]
21
+
22
+
23
+ # Get list of all valid and invalid JSON files
24
+ VALID_DATACITE43_FILES = get_all_json_files(
25
+ os.path.join(BASE_DIR, "data", "datacite43")
26
+ )
27
+ INVALID_DATACITE43_FILES = get_all_json_files(INVALID_DATACITE43_DIR)
28
+
29
+
30
+ @pytest.mark.parametrize("valid_file", VALID_DATACITE43_FILES)
31
+ def test_valid_json(valid_file):
32
+ """Test that valid example files validate successfully."""
33
+ print(f"\nValidating file: {valid_file}")
34
+ json_data = load_json_path(valid_file)
35
+ validation_errors = None
36
+ try:
37
+ validation_errors = validator43(json_data)
38
+ except ValueError as e:
39
+ pytest.fail(f"Validation failed for: {valid_file}\nErrors: {str(e)}")
40
+
41
+ assert (
42
+ not validation_errors
43
+ ), f"Validation failed for: {valid_file}\nErrors: {validation_errors}"
44
+ print(f"Validation passed for: {valid_file}")
45
+
46
+
47
+ @pytest.mark.parametrize("invalid_file", INVALID_DATACITE43_FILES)
48
+ def test_invalid_json(invalid_file):
49
+ """Test that invalid example files do not validate successfully."""
50
+ logger.debug(f"Attempting to validate invalid file: {invalid_file}")
51
+
52
+ json_data = load_json_path(invalid_file)
53
+
54
+ def validate_wrapper():
55
+ try:
56
+ validation_errors = validator43(json_data)
57
+
58
+ logger.debug(f"Validation result for {invalid_file}: {validation_errors}")
59
+
60
+ if validation_errors:
61
+ logger.debug(f"Found validation errors in {invalid_file}")
62
+ return
63
+
64
+ logger.error(
65
+ f"No validation errors found for supposedly invalid file: {invalid_file}"
66
+ )
67
+ raise ValueError(
68
+ f"Validation did not fail for invalid file: {invalid_file}"
69
+ )
70
+
71
+ except Exception as e:
72
+ logger.error(f"Validation exception for {invalid_file}: {str(e)}")
73
+ raise
74
+
75
+ with pytest.raises((ValueError, KeyError, AssertionError, TypeError)):
76
+ validate_wrapper()
@@ -1,3 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
@@ -1,55 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=64.0","wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [metadata]
6
- name = caltechdata_api
7
- version = 1.11.0
8
- author = Thomas E Morrell, Rohan Bhattarai, Elizabeth Won, Alexander A Abakah, Kshemaahna Nagi
9
- author_email = tmorrell@caltech.edu, aabakah@caltech.edu, knagi@caltech.edu
10
- description = Python wrapper for CaltechDATA API.
11
- long_description = file: README.md
12
- long_description_content_type = text/markdown
13
- url = https://github.com/caltechlibrary/caltechdata_api
14
- license = MIT
15
- classifiers =
16
- License :: OSI Approved :: MIT License
17
- Programming Language :: Python :: 3
18
- Programming Language :: Python :: 3.7
19
- Programming Language :: Python :: 3.8
20
- Programming Language :: Python :: 3.9
21
- Programming Language :: Python :: 3.10
22
- Programming Language :: Python :: Implementation :: CPython
23
- Operating System :: OS Independent
24
-
25
- [options]
26
- packages = find:
27
- python_requires = >=3.6.0
28
- install_requires =
29
- requests
30
- datacite>1.1.0
31
- tqdm>=4.62.3
32
- pyyaml
33
- s3fs
34
- cryptography
35
- s3cmd
36
- jsonschema-specifications
37
- include_package_data = True
38
-
39
- [options.packages.find]
40
- exclude = tests
41
-
42
- [options.package_data]
43
- caltechdata_api = vocabularies.yaml, vocabularies/*
44
-
45
- [options.entry_points]
46
- console_scripts =
47
- caltechdata_api=caltechdata_api.cli:main
48
-
49
- [tool:pytest]
50
- addopts = --verbose
51
-
52
- [egg_info]
53
- tag_build =
54
- tag_date = 0
55
-
@@ -1,3 +0,0 @@
1
- from setuptools import setup
2
-
3
- setup()
@@ -1,166 +0,0 @@
1
- import os
2
- import pytest
3
- import logging
4
- from caltechdata_api import validate_metadata as validator43
5
- from helpers import load_json_path
6
-
7
- # Configure logging
8
- logging.basicConfig(level=logging.DEBUG)
9
- logger = logging.getLogger(__name__)
10
-
11
- # Dynamically determine the base path
12
- BASE_DIR = os.path.dirname(os.path.abspath(__file__))
13
- INVALID_DATACITE43_DIR = os.path.join(BASE_DIR, "data", "invalid_datacite43")
14
- DATACITE43_DIR = os.path.join(BASE_DIR, "data")
15
-
16
-
17
- # Function to get all JSON files in the directory
18
- def get_all_json_files(directory):
19
- return [
20
- os.path.join(directory, f) for f in os.listdir(directory) if f.endswith(".json")
21
- ]
22
-
23
-
24
- # Get list of all valid and invalid JSON files
25
- VALID_DATACITE43_FILES = get_all_json_files(
26
- os.path.join(BASE_DIR, "data", "datacite43")
27
- )
28
- INVALID_DATACITE43_FILES = get_all_json_files(INVALID_DATACITE43_DIR)
29
-
30
-
31
- @pytest.mark.parametrize("valid_file", VALID_DATACITE43_FILES)
32
- def test_valid_json(valid_file):
33
- """Test that valid example files validate successfully."""
34
- print(f"\nValidating file: {valid_file}")
35
- json_data = load_json_path(valid_file)
36
- validation_errors = None
37
- try:
38
- validation_errors = validator43(json_data)
39
- except ValueError as e:
40
- pytest.fail(f"Validation failed for: {valid_file}\nErrors: {str(e)}")
41
-
42
- assert (
43
- not validation_errors
44
- ), f"Validation failed for: {valid_file}\nErrors: {validation_errors}"
45
- print(f"Validation passed for: {valid_file}")
46
-
47
-
48
- @pytest.mark.parametrize("invalid_file", INVALID_DATACITE43_FILES)
49
- def test_invalid_json(invalid_file):
50
- """Test that invalid example files do not validate successfully."""
51
- logger.debug(f"Attempting to validate invalid file: {invalid_file}")
52
-
53
- json_data = load_json_path(invalid_file)
54
-
55
- def validate_wrapper():
56
- try:
57
- validation_errors = validator43(json_data)
58
-
59
- logger.debug(f"Validation result for {invalid_file}: {validation_errors}")
60
-
61
- if validation_errors:
62
- logger.debug(f"Found validation errors in {invalid_file}")
63
- return
64
-
65
- logger.error(
66
- f"No validation errors found for supposedly invalid file: {invalid_file}"
67
- )
68
- raise ValueError(
69
- f"Validation did not fail for invalid file: {invalid_file}"
70
- )
71
-
72
- except Exception as e:
73
- logger.error(f"Validation exception for {invalid_file}: {str(e)}")
74
- raise
75
-
76
- with pytest.raises((ValueError, KeyError, AssertionError, TypeError)):
77
- validate_wrapper()
78
-
79
-
80
- @pytest.mark.parametrize(
81
- "missing_field_file",
82
- [
83
- {
84
- "file": os.path.join(DATACITE43_DIR, "missing_creators.json"),
85
- "missing_field": "creators",
86
- },
87
- {
88
- "file": os.path.join(DATACITE43_DIR, "missing_titles.json"),
89
- "missing_field": "titles",
90
- },
91
- ],
92
- )
93
- def test_missing_required_fields(missing_field_file):
94
- """Test that JSON files missing required fields fail validation."""
95
- print(
96
- f"\nTesting missing field: {missing_field_file['missing_field']} in file: {missing_field_file['file']}"
97
- )
98
-
99
- # Skip the test if the file doesn't exist
100
- if not os.path.exists(missing_field_file["file"]):
101
- pytest.skip(f"Test file not found: {missing_field_file['file']}")
102
-
103
- json_data = load_json_path(missing_field_file["file"])
104
- with pytest.raises(
105
- ValueError,
106
- match=f"Missing required metadata field: {missing_field_file['missing_field']}",
107
- ):
108
- validator43(json_data)
109
-
110
-
111
- @pytest.mark.parametrize(
112
- "type_error_file",
113
- [
114
- {
115
- "file": os.path.join(DATACITE43_DIR, "type_error_creators.json"),
116
- "field": "creators",
117
- },
118
- {
119
- "file": os.path.join(DATACITE43_DIR, "type_error_dates.json"),
120
- "field": "dates",
121
- },
122
- ],
123
- )
124
- def test_incorrect_field_types(type_error_file):
125
- """Test that JSON files with incorrect field types fail validation."""
126
- print(
127
- f"\nTesting incorrect type in field: {type_error_file['field']} for file: {type_error_file['file']}"
128
- )
129
-
130
- # Skip the test if the file doesn't exist
131
- if not os.path.exists(type_error_file["file"]):
132
- pytest.skip(f"Test file not found: {type_error_file['file']}")
133
-
134
- json_data = load_json_path(type_error_file["file"])
135
- with pytest.raises(
136
- ValueError, match=f"Incorrect type for field: {type_error_file['field']}"
137
- ):
138
- validator43(json_data)
139
-
140
-
141
- def test_multiple_errors():
142
- """Test JSON file with multiple issues to check all errors are raised."""
143
- multiple_errors_file = os.path.join(DATACITE43_DIR, "multiple_errors.json")
144
-
145
- # Skip the test if the file doesn't exist
146
- if not os.path.exists(multiple_errors_file):
147
- pytest.skip(f"Test file not found: {multiple_errors_file}")
148
-
149
- json_data = load_json_path(multiple_errors_file)
150
- with pytest.raises(ValueError, match="Multiple validation errors"):
151
- validator43(json_data)
152
-
153
-
154
- def test_error_logging(caplog):
155
- """Test that errors are logged correctly during validation."""
156
- some_invalid_file = os.path.join(INVALID_DATACITE43_DIR, "some_invalid_file.json")
157
-
158
- # Skip the test if the file doesn't exist
159
- if not os.path.exists(some_invalid_file):
160
- pytest.skip(f"Test file not found: {some_invalid_file}")
161
-
162
- json_data = load_json_path(some_invalid_file)
163
- with caplog.at_level(logging.ERROR):
164
- with pytest.raises(ValueError):
165
- validator43(json_data)
166
- assert "Validation failed" in caplog.text