caltechdata-api 1.8.2__tar.gz → 1.9.1__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 (21) hide show
  1. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/PKG-INFO +3 -1
  2. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/README.md +2 -0
  3. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/caltechdata_write.py +4 -1
  4. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/cli.py +2 -1
  5. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/customize_schema.py +156 -42
  6. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api.egg-info/PKG-INFO +3 -1
  7. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/LICENSE +0 -0
  8. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/__init__.py +0 -0
  9. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/caltechdata_edit.py +0 -0
  10. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/download_file.py +0 -0
  11. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/get_files.py +0 -0
  12. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/get_metadata.py +0 -0
  13. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/md_to_json.py +0 -0
  14. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api/utils.py +0 -0
  15. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api.egg-info/SOURCES.txt +0 -0
  16. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api.egg-info/dependency_links.txt +0 -0
  17. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api.egg-info/entry_points.txt +0 -0
  18. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api.egg-info/requires.txt +0 -0
  19. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/caltechdata_api.egg-info/top_level.txt +0 -0
  20. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/setup.cfg +0 -0
  21. {caltechdata_api-1.8.2 → caltechdata_api-1.9.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: caltechdata_api
3
- Version: 1.8.2
3
+ Version: 1.9.1
4
4
  Summary: Python wrapper for CaltechDATA API.
5
5
  Home-page: https://github.com/caltechlibrary/caltechdata_api
6
6
  Author: Thomas E Morrell, Bhattarai Rohan , Won Elizabeth
@@ -20,6 +20,8 @@ License-File: LICENSE
20
20
 
21
21
  # CaltechDATA API Python Library
22
22
 
23
+ [![DOI](https://img.shields.io/badge/dynamic/json.svg?label=DOI&query=$.pids.doi.identifier&uri=https://data.caltech.edu/api/records/wfjr5-kw507/versions/latest)](https://data.caltech.edu/records/wfjr5-kw507/latest)
24
+
23
25
  The `caltechdata_api` Python library provides a convenient interface for interacting with the CaltechDATA API. It allows users to write files, create DataCite 4 standard JSON records, edit existing records, and retrieve metadata from the CaltechDATA repository.
24
26
 
25
27
  ## Features
@@ -1,5 +1,7 @@
1
1
  # CaltechDATA API Python Library
2
2
 
3
+ [![DOI](https://img.shields.io/badge/dynamic/json.svg?label=DOI&query=$.pids.doi.identifier&uri=https://data.caltech.edu/api/records/wfjr5-kw507/versions/latest)](https://data.caltech.edu/records/wfjr5-kw507/latest)
4
+
3
5
  The `caltechdata_api` Python library provides a convenient interface for interacting with the CaltechDATA API. It allows users to write files, create DataCite 4 standard JSON records, edit existing records, and retrieve metadata from the CaltechDATA repository.
4
6
 
5
7
  ## Features
@@ -248,7 +248,10 @@ def caltechdata_write(
248
248
  # Make draft and publish
249
249
  result = requests.post(url + "/api/records", headers=headers, json=data)
250
250
  if result.status_code != 201:
251
- raise Exception(result.text)
251
+ if result.status_code == 400 and "Referer checking failed" in result.text:
252
+ raise Exception("Token is incorrect or missing referer.")
253
+ else:
254
+ raise Exception(result.text)
252
255
  idv = result.json()["id"]
253
256
  publish_link = result.json()["links"]["publish"]
254
257
 
@@ -2,7 +2,7 @@ import argparse
2
2
  import requests
3
3
  import s3fs
4
4
  from caltechdata_api import caltechdata_write, caltechdata_edit
5
- from .md_to_json import parse_readme_to_json
5
+ from md_to_json import parse_readme_to_json
6
6
  import json
7
7
  import os
8
8
  from cryptography.fernet import Fernet
@@ -469,6 +469,7 @@ def create_record(production):
469
469
  "descriptions": [
470
470
  {"description": args["description"], "descriptionType": "Abstract"}
471
471
  ],
472
+ "publisher": "CaltechDATA",
472
473
  "creators": [
473
474
  {
474
475
  "affiliation": [
@@ -80,7 +80,7 @@ def rdm_creators_contributors(person_list, peopleroles):
80
80
  else:
81
81
  print(f"Name type {ntype} not known")
82
82
  else:
83
- # We default to organizational if not known
83
+ # We default to personal if not known
84
84
  cre["type"] = "personal"
85
85
  change_label(cre, "givenName", "given_name")
86
86
  change_label(cre, "familyName", "family_name")
@@ -252,7 +252,7 @@ def customize_schema_rdm(json_record):
252
252
 
253
253
  if "identifiers" in json_record:
254
254
  identifiers = []
255
- system_pids = ["DOI", "oai"]
255
+ system_pids = ["oai"]
256
256
  for identifier in json_record["identifiers"]:
257
257
  if identifier["identifierType"] not in system_pids:
258
258
  identifier["scheme"] = identifiertypes[identifier.pop("identifierType")]
@@ -393,20 +393,12 @@ def validate_metadata(json_record):
393
393
  """
394
394
  errors = []
395
395
 
396
- # Check for 'types' and 'resourceTypeGeneral'
397
- if "types" not in json_record:
398
- errors.append("'types' field is missing.")
399
- elif not isinstance(json_record["types"], dict):
400
- errors.append("'types' field should be a dictionary.")
401
- elif "resourceTypeGeneral" not in json_record["types"]:
402
- errors.append("'resourceTypeGeneral' field is missing in 'types'.")
403
-
404
- # Check for 'title'
405
396
  if "titles" not in json_record:
406
397
  errors.append("'titles' field is missing.")
407
398
  elif not isinstance(json_record["titles"], list) or len(json_record["titles"]) == 0:
408
399
  errors.append("'titles' should be a non-empty list.")
409
400
  else:
401
+
410
402
  # Ensure each title is a dictionary with 'title' field
411
403
  for title in json_record["titles"]:
412
404
  if not isinstance(title, dict) or "title" not in title:
@@ -416,32 +408,6 @@ def validate_metadata(json_record):
416
408
 
417
409
  # Publication date is handled by customize function
418
410
 
419
- # Check for 'creators'
420
- if "creators" not in json_record:
421
- errors.append("'creators' field is missing.")
422
- elif (
423
- not isinstance(json_record["creators"], list)
424
- or len(json_record["creators"]) == 0
425
- ):
426
- errors.append("'creators' should be a non-empty list.")
427
- else:
428
- for creator in json_record["creators"]:
429
- if not isinstance(creator, dict) or "name" not in creator:
430
- errors.append(
431
- "Each creator in 'creators' must be a dictionary with a 'name' key."
432
- )
433
-
434
- # Check for 'contributors'
435
- if "contributors" in json_record:
436
- if not isinstance(json_record["contributors"], list):
437
- errors.append("'contributors' should be a list.")
438
- else:
439
- for contributor in json_record["contributors"]:
440
- if not isinstance(contributor, dict) or "name" not in contributor:
441
- errors.append(
442
- "Each contributor must be a dictionary with a 'name' key."
443
- )
444
-
445
411
  # Check for 'resourceType'
446
412
  if "resourceType" not in json_record["types"]:
447
413
  errors.append("'resourceType' field is missing in 'types'.")
@@ -450,8 +416,11 @@ def validate_metadata(json_record):
450
416
 
451
417
  # Check for 'identifiers'
452
418
  if "identifiers" in json_record:
453
- if not isinstance(json_record["identifiers"], list):
454
- errors.append("'identifiers' should be a list.")
419
+ if (
420
+ not isinstance(json_record["identifiers"], list)
421
+ or len(json_record["identifiers"]) == 0
422
+ ):
423
+ errors.append("'identifiers' should be a non-empty list.")
455
424
  else:
456
425
  for identifier in json_record["identifiers"]:
457
426
  if (
@@ -480,6 +449,7 @@ def validate_metadata(json_record):
480
449
  errors.append("'relatedIdentifiers' should be a list.")
481
450
  else:
482
451
  for related_id in json_record["relatedIdentifiers"]:
452
+
483
453
  if (
484
454
  not isinstance(related_id, dict)
485
455
  or "relatedIdentifier" not in related_id
@@ -493,17 +463,161 @@ def validate_metadata(json_record):
493
463
  if not isinstance(json_record["rightsList"], list):
494
464
  errors.append("'rightsList' should be a list.")
495
465
  else:
496
- for rights in json_record["rightsList"]:
497
- if not isinstance(rights, dict) or "rights" not in rights:
466
+
467
+ for right in json_record["rightsList"]:
468
+ if not isinstance(right, dict) or "rights" not in right:
469
+ errors.append("Each 'rightsList' entry must have 'rights'.")
470
+ if "rightsURI" in right and not isinstance(right["rightsURI"], str):
471
+ errors.append("'rightsURI' should be a string.")
472
+
473
+ # Check for 'subjects'
474
+ if "subjects" in json_record:
475
+ if not isinstance(json_record["subjects"], list):
476
+ errors.append("'subjects' should be a list.")
477
+ else:
478
+ for subject in json_record["subjects"]:
479
+ if not isinstance(subject, dict) or "subject" not in subject:
480
+ errors.append("Each 'subject' must have a 'subject' key.")
481
+
482
+ # Check for 'dates'
483
+ if "dates" not in json_record:
484
+ errors.append("'dates' field is missing.")
485
+ elif not isinstance(json_record["dates"], list) or len(json_record["dates"]) == 0:
486
+ errors.append("'dates' should be a non-empty list.")
487
+ else:
488
+ for date in json_record["dates"]:
489
+ if (
490
+ not isinstance(date, dict)
491
+ or "date" not in date
492
+ or "dateType" not in date
493
+ ):
494
+ errors.append("Each 'date' must have 'date' and 'dateType'.")
495
+
496
+ # Check for 'creators'
497
+ if "creators" not in json_record:
498
+ errors.append("'creators' field is missing.")
499
+ elif (
500
+ not isinstance(json_record["creators"], list)
501
+ or len(json_record["creators"]) == 0
502
+ ):
503
+ errors.append("'creators' should be a non-empty list.")
504
+ else:
505
+ for creator in json_record["creators"]:
506
+ if not isinstance(creator, dict):
507
+ errors.append("Each 'creator' must be a dictionry")
508
+ if "nameType" in creator:
509
+ if creator["nameType"] == "Organizational":
510
+ if "name" not in creator:
511
+ errors.append("Each organizational 'creator' must have 'name'.")
512
+ else:
513
+ if "familyName" not in creator:
498
514
  errors.append(
499
- "Each entry in 'rightsList' must be a dictionary with a 'rights' key."
515
+ "Each 'creator' must have a 'familyName' or have type Organizational"
500
516
  )
517
+ if "affiliation" in creator:
518
+ if not isinstance(creator["affiliation"], list):
519
+ errors.append("'affiliation' in 'creators' should be a list.")
520
+ for affiliation in creator["affiliation"]:
521
+ if not isinstance(affiliation, dict) or "name" not in affiliation:
522
+ errors.append(
523
+ "Each 'affiliation' in 'creators' must have a 'name'."
524
+ )
525
+
526
+ # Check for 'contributors'
527
+ if "contributors" in json_record:
528
+ if (
529
+ not isinstance(json_record["contributors"], list)
530
+ or len(json_record["contributors"]) == 0
531
+ ):
532
+ errors.append("'creators' should be a non-empty list.")
533
+ else:
534
+ for contributor in json_record["contributors"]:
535
+ if not isinstance(contributor, dict):
536
+ errors.append("Each 'contributor' must be a dictionry")
537
+ if "nameType" in contributor:
538
+ if contributor["nameType"] == "Organizational":
539
+ if "name" not in creator:
540
+ errors.append(
541
+ "Each organizational 'contributor' must have 'name'."
542
+ )
543
+ else:
544
+ if "familyName" not in contributor:
545
+ errors.append(
546
+ "Each 'contributor' must have a 'familyName' or have type Organizational"
547
+ )
548
+ if "affiliation" in contributor:
549
+ if not isinstance(contributor["affiliation"], list):
550
+ errors.append(
551
+ "'affiliation' in 'contributors' should be a list."
552
+ )
553
+ for affiliation in contributor["affiliation"]:
554
+ if (
555
+ not isinstance(affiliation, dict)
556
+ or "name" not in affiliation
557
+ ):
558
+ errors.append(
559
+ "Each 'affiliation' in 'contributors' must have a 'name'."
560
+ )
501
561
 
502
562
  # Check for 'geoLocations'
503
563
  if "geoLocations" in json_record:
504
564
  if not isinstance(json_record["geoLocations"], list):
505
565
  errors.append("'geoLocations' should be a list.")
506
566
  else:
567
+
568
+ for geo_loc in json_record["geoLocations"]:
569
+ if not isinstance(geo_loc, dict) or "geoLocationPlace" not in geo_loc:
570
+ errors.append("Each 'geoLocation' must have 'geoLocationPlace'.")
571
+ if "geoLocationPoint" in geo_loc:
572
+ point = geo_loc["geoLocationPoint"]
573
+ if (
574
+ not isinstance(point, dict)
575
+ or "pointLatitude" not in point
576
+ or "pointLongitude" not in point
577
+ ):
578
+ errors.append(
579
+ "'geoLocationPoint' must have 'pointLatitude' and 'pointLongitude'."
580
+ )
581
+
582
+ # Check for 'formats'
583
+ if "formats" in json_record and (
584
+ not isinstance(json_record["formats"], list) or len(json_record["formats"]) == 0
585
+ ):
586
+ errors.append("'formats' should be a non-empty list.")
587
+
588
+ # Check for 'language'
589
+ if "language" in json_record:
590
+ if not isinstance(json_record["language"], str):
591
+ errors.append("'language' should be a string.")
592
+
593
+ # Check for 'version'
594
+ if "version" in json_record and not isinstance(json_record["version"], str):
595
+ errors.append("'version' should be a string.")
596
+
597
+ # Check for 'publisher'
598
+ if "publisher" not in json_record:
599
+ errors.append("'publisher' field is missing.")
600
+ elif not isinstance(json_record["publisher"], str):
601
+ errors.append("'publisher' should be a string.")
602
+
603
+ # Check for 'publicationYear'
604
+ if "publicationYear" not in json_record:
605
+ errors.append("'publicationYear' field is missing.")
606
+ elif not isinstance(json_record["publicationYear"], str):
607
+ errors.append("'publicationYear' should be a string.")
608
+
609
+ # Check for 'types'
610
+ if "types" not in json_record:
611
+ errors.append("'types' field is missing.")
612
+ elif not isinstance(json_record["types"], dict):
613
+ errors.append("'types' should be a dictionary.")
614
+ else:
615
+ if "resourceTypeGeneral" not in json_record["types"]:
616
+ errors.append("'types' must have 'resourceTypeGeneral'.")
617
+ if "resourceType" in json_record["types"] and not isinstance(
618
+ json_record["types"]["resourceType"], str
619
+ ):
620
+ errors.append("'resourceType' should be a string if provided.")
507
621
  for location in json_record["geoLocations"]:
508
622
  if not isinstance(location, dict):
509
623
  errors.append("Each entry in 'geoLocations' must be a dictionary.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: caltechdata-api
3
- Version: 1.8.2
3
+ Version: 1.9.1
4
4
  Summary: Python wrapper for CaltechDATA API.
5
5
  Home-page: https://github.com/caltechlibrary/caltechdata_api
6
6
  Author: Thomas E Morrell, Bhattarai Rohan , Won Elizabeth
@@ -20,6 +20,8 @@ License-File: LICENSE
20
20
 
21
21
  # CaltechDATA API Python Library
22
22
 
23
+ [![DOI](https://img.shields.io/badge/dynamic/json.svg?label=DOI&query=$.pids.doi.identifier&uri=https://data.caltech.edu/api/records/wfjr5-kw507/versions/latest)](https://data.caltech.edu/records/wfjr5-kw507/latest)
24
+
23
25
  The `caltechdata_api` Python library provides a convenient interface for interacting with the CaltechDATA API. It allows users to write files, create DataCite 4 standard JSON records, edit existing records, and retrieve metadata from the CaltechDATA repository.
24
26
 
25
27
  ## Features
File without changes