caltechdata-api 2.2.0__tar.gz → 2.2.2__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 (33) hide show
  1. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/PKG-INFO +1 -1
  2. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/caltechdata_edit.py +6 -6
  3. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/caltechdata_write.py +6 -6
  4. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/download_from_record.py +66 -6
  5. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api.egg-info/PKG-INFO +1 -1
  6. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/pyproject.toml +1 -1
  7. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/LICENSE +0 -0
  8. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/README.md +0 -0
  9. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/__init__.py +0 -0
  10. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/cli.py +0 -0
  11. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/customize_schema.py +0 -0
  12. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/download_file.py +0 -0
  13. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/get_metadata.py +0 -0
  14. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/md_to_json.py +0 -0
  15. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/utils.py +0 -0
  16. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/date_types.yaml +0 -0
  17. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/description_types.yaml +0 -0
  18. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/identifier_types.yaml +0 -0
  19. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/licenses.csv +0 -0
  20. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/relation_types.yaml +0 -0
  21. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/resource_types.yaml +0 -0
  22. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/roles.yaml +0 -0
  23. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies/title_types.yaml +0 -0
  24. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api/vocabularies.yaml +0 -0
  25. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api.egg-info/SOURCES.txt +0 -0
  26. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api.egg-info/dependency_links.txt +0 -0
  27. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api.egg-info/entry_points.txt +0 -0
  28. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api.egg-info/requires.txt +0 -0
  29. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/caltechdata_api.egg-info/top_level.txt +0 -0
  30. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/setup.cfg +0 -0
  31. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/tests/test_download.py +0 -0
  32. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/tests/test_rdm.py +0 -0
  33. {caltechdata_api-2.2.0 → caltechdata_api-2.2.2}/tests/test_unit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: caltechdata_api
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Python wrapper for CaltechDATA API.
5
5
  Author: Rohan Bhattarai, Elizabeth Won
6
6
  Author-email: Thomas E Morrell <tmorrell@caltech.edu>, Alexander A Abakah <aabakah@caltech.edu>, Kshemaahna Nagi <knagi@caltech.edu>
@@ -131,18 +131,18 @@ def caltechdata_edit(
131
131
 
132
132
  if authors == False:
133
133
  if production == True:
134
- url = "https://data.caltech.edu/"
134
+ url = "https://data.caltech.edu"
135
135
  elif local == True:
136
- url = "https://127.0.0.1:5000/"
136
+ url = "https://127.0.0.1:5000"
137
137
  else:
138
- url = "https://data.caltechlibrary.dev/"
138
+ url = "https://data.caltechlibrary.dev"
139
139
  else:
140
140
  if production == True:
141
- url = "https://authors.library.caltech.edu/"
141
+ url = "https://authors.library.caltech.edu"
142
142
  elif local == True:
143
- url = "https://127.0.0.1:5000/"
143
+ url = "https://127.0.0.1:5000"
144
144
  else:
145
- url = "https://authors.caltechlibrary.dev/"
145
+ url = "https://authors.caltechlibrary.dev"
146
146
 
147
147
  headers = {
148
148
  "Authorization": "Bearer %s" % token,
@@ -177,18 +177,18 @@ def caltechdata_write(
177
177
 
178
178
  if authors == False:
179
179
  if production == True:
180
- url = "https://data.caltech.edu/"
180
+ url = "https://data.caltech.edu"
181
181
  elif local == True:
182
- url = "https://127.0.0.1:5000/"
182
+ url = "https://127.0.0.1:5000"
183
183
  else:
184
- url = "https://data.caltechlibrary.dev/"
184
+ url = "https://data.caltechlibrary.dev"
185
185
  else:
186
186
  if production == True:
187
- url = "https://authors.library.caltech.edu/"
187
+ url = "https://authors.library.caltech.edu"
188
188
  elif local == True:
189
- url = "https://127.0.0.1:5000/"
189
+ url = "https://127.0.0.1:5000"
190
190
  else:
191
- url = "https://authors.caltechlibrary.dev/"
191
+ url = "https://authors.caltechlibrary.dev"
192
192
 
193
193
  # If files is a string - change to single value array
194
194
  if isinstance(files, str) == True:
@@ -14,6 +14,7 @@ import argparse
14
14
  import os
15
15
  import requests
16
16
  from tqdm.auto import tqdm
17
+ from urllib.parse import urlsplit
17
18
 
18
19
  from typing import Any, Dict, Optional, Sequence
19
20
 
@@ -46,7 +47,10 @@ def get_base_url(production: bool = True, authors: bool = False) -> str:
46
47
 
47
48
 
48
49
  def get_files_from_record(
49
- record_id: str, production: bool = True, authors: bool = False
50
+ record_id: str,
51
+ production: bool = True,
52
+ authors: bool = False,
53
+ token: Optional[str] = None,
50
54
  ) -> Dict[str, Any]:
51
55
  """Get a dictionary of files associated with a record.
52
56
 
@@ -63,6 +67,13 @@ def get_files_from_record(
63
67
  authors
64
68
  Whether to query CaltechAUTHORS instead of CaltechDATA.
65
69
 
70
+ token
71
+ A personal access token for the repository, used to access
72
+ restricted records. If omitted, the request is made without
73
+ authentication and only public records are available. When a
74
+ token is given and the published record is not found, the
75
+ record's draft is tried as well.
76
+
66
77
  Returns
67
78
  -------
68
79
  dict
@@ -70,7 +81,20 @@ def get_files_from_record(
70
81
  associated with those files as values.
71
82
  """
72
83
  base_url = get_base_url(production=production, authors=authors)
73
- with requests.get(f"{base_url}/api/records/{record_id}/files") as r:
84
+ headers = {}
85
+ if token is not None:
86
+ headers["Authorization"] = "Bearer %s" % token
87
+
88
+ r = requests.get(f"{base_url}/api/records/{record_id}/files", headers=headers)
89
+ try:
90
+ if r.status_code == 404 and token is not None:
91
+ # An unpublished record has no published version to return,
92
+ # so fall back to its draft, which requires authentication.
93
+ r.close()
94
+ r = requests.get(
95
+ f"{base_url}/api/records/{record_id}/draft/files", headers=headers
96
+ )
97
+
74
98
  r.raise_for_status()
75
99
  files = dict()
76
100
  for entry in r.json().get("entries", []):
@@ -78,6 +102,8 @@ def get_files_from_record(
78
102
  files[key] = entry
79
103
 
80
104
  return files
105
+ finally:
106
+ r.close()
81
107
 
82
108
 
83
109
  def download_files_from_record(
@@ -87,6 +113,7 @@ def download_files_from_record(
87
113
  max_redirects: int = 5,
88
114
  production: bool = True,
89
115
  authors: bool = False,
116
+ token: Optional[str] = None,
90
117
  ):
91
118
  """Download one or more files from a record.
92
119
 
@@ -124,11 +151,19 @@ def download_files_from_record(
124
151
 
125
152
  authors
126
153
  Whether to download from CaltechAUTHORS instead of CaltechDATA.
154
+
155
+ token
156
+ A personal access token for the repository, used to download
157
+ files from restricted records. If omitted, the requests are
158
+ made without authentication and only public records are
159
+ available.
127
160
  """
128
161
  if not os.path.isdir(output_path):
129
162
  raise IOError(f"{output_path} is not an extant directory")
130
163
 
131
- files = get_files_from_record(record_id, production=production, authors=authors)
164
+ files = get_files_from_record(
165
+ record_id, production=production, authors=authors, token=token
166
+ )
132
167
  if filenames is None:
133
168
  filenames = sorted(files.keys())
134
169
 
@@ -145,10 +180,17 @@ def download_files_from_record(
145
180
  )
146
181
 
147
182
  content_url = entry["links"]["content"]
148
- download_content(content_url, output_file, max_redirects=max_redirects)
183
+ download_content(
184
+ content_url, output_file, max_redirects=max_redirects, token=token
185
+ )
149
186
 
150
187
 
151
- def download_content(content_url: str, fname: os.PathLike, max_redirects=5):
188
+ def download_content(
189
+ content_url: str,
190
+ fname: os.PathLike,
191
+ max_redirects=5,
192
+ token: Optional[str] = None,
193
+ ):
152
194
  """Download the contents of a file.
153
195
 
154
196
  Parameters
@@ -168,14 +210,25 @@ def download_content(content_url: str, fname: os.PathLike, max_redirects=5):
168
210
  the maximum number of hops that the function can take. Usually,
169
211
  only a single redirection should be necessary (from the record to
170
212
  the file provider), but the default allows for a few extra hops.
213
+
214
+ token
215
+ A personal access token for the repository, used to download
216
+ content from restricted records. If omitted, the request is
217
+ made without authentication. The token is only sent to the
218
+ host of ``content_url``, not to hosts we are redirected to.
171
219
  """
172
220
  url = content_url
221
+ host = urlsplit(content_url).netloc
173
222
  # If max_redirects == 0, then this loop will never run. Since the
174
223
  # likely expected behavior for ``max_redirects = 0`` is to only
175
224
  # look at the link directly given back by the record, we add 1
176
225
  # for the loop to ensure it runs once in that case.
177
226
  for _ in range(max_redirects + 1):
178
- with requests.get(url, stream=True) as r:
227
+ headers = {}
228
+ if token is not None and urlsplit(url).netloc == host:
229
+ headers["Authorization"] = "Bearer %s" % token
230
+
231
+ with requests.get(url, stream=True, headers=headers) as r:
179
232
  r.raise_for_status()
180
233
  if "Location" in r.headers:
181
234
  # Redirection - follow to the next URL
@@ -223,6 +276,12 @@ if __name__ == "__main__":
223
276
  )
224
277
  parser.add_argument("-test", dest="production", action="store_false")
225
278
  parser.add_argument("-authors", dest="authors", action="store_true")
279
+ parser.add_argument(
280
+ "-token",
281
+ default=os.environ.get("RDMTOK"),
282
+ help="Personal access token, needed to download restricted records. "
283
+ "Defaults to the RDMTOK environment variable, if set.",
284
+ )
226
285
 
227
286
  args = parser.parse_args()
228
287
 
@@ -233,4 +292,5 @@ if __name__ == "__main__":
233
292
  max_redirects=args.max_redirects,
234
293
  production=args.production,
235
294
  authors=args.authors,
295
+ token=args.token,
236
296
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: caltechdata_api
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Python wrapper for CaltechDATA API.
5
5
  Author: Rohan Bhattarai, Elizabeth Won
6
6
  Author-email: Thomas E Morrell <tmorrell@caltech.edu>, Alexander A Abakah <aabakah@caltech.edu>, Kshemaahna Nagi <knagi@caltech.edu>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "caltechdata_api"
7
- version = "2.2.0"
7
+ version = "2.2.2"
8
8
  description = "Python wrapper for CaltechDATA API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes