caltechdata-api 1.8.2__tar.gz → 1.9.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 (21) hide show
  1. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/PKG-INFO +3 -1
  2. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/README.md +2 -0
  3. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/caltechdata_write.py +4 -1
  4. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/cli.py +2 -1
  5. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/customize_schema.py +170 -40
  6. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api.egg-info/PKG-INFO +3 -1
  7. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/LICENSE +0 -0
  8. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/__init__.py +0 -0
  9. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/caltechdata_edit.py +0 -0
  10. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/download_file.py +0 -0
  11. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/get_files.py +0 -0
  12. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/get_metadata.py +0 -0
  13. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/md_to_json.py +0 -0
  14. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api/utils.py +0 -0
  15. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api.egg-info/SOURCES.txt +0 -0
  16. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api.egg-info/dependency_links.txt +0 -0
  17. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api.egg-info/entry_points.txt +0 -0
  18. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api.egg-info/requires.txt +0 -0
  19. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/caltechdata_api.egg-info/top_level.txt +0 -0
  20. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/setup.cfg +0 -0
  21. {caltechdata_api-1.8.2 → caltechdata_api-1.9.0}/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.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, 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'.")
@@ -480,6 +446,7 @@ def validate_metadata(json_record):
480
446
  errors.append("'relatedIdentifiers' should be a list.")
481
447
  else:
482
448
  for related_id in json_record["relatedIdentifiers"]:
449
+
483
450
  if (
484
451
  not isinstance(related_id, dict)
485
452
  or "relatedIdentifier" not in related_id
@@ -493,17 +460,180 @@ def validate_metadata(json_record):
493
460
  if not isinstance(json_record["rightsList"], list):
494
461
  errors.append("'rightsList' should be a list.")
495
462
  else:
496
- for rights in json_record["rightsList"]:
497
- if not isinstance(rights, dict) or "rights" not in rights:
463
+
464
+ for right in json_record["rightsList"]:
465
+ if not isinstance(right, dict) or "rights" not in right:
466
+ errors.append("Each 'rightsList' entry must have 'rights'.")
467
+ if "rightsURI" in right and not isinstance(right["rightsURI"], str):
468
+ errors.append("'rightsURI' should be a string.")
469
+
470
+ # Check for 'subjects'
471
+ if "subjects" in json_record:
472
+ if not isinstance(json_record["subjects"], list):
473
+ errors.append("'subjects' should be a list.")
474
+ else:
475
+ for subject in json_record["subjects"]:
476
+ if not isinstance(subject, dict) or "subject" not in subject:
477
+ errors.append("Each 'subject' must have a 'subject' key.")
478
+
479
+ # Check for 'dates'
480
+ if "dates" not in json_record:
481
+ errors.append("'dates' field is missing.")
482
+ elif not isinstance(json_record["dates"], list) or len(json_record["dates"]) == 0:
483
+ errors.append("'dates' should be a non-empty list.")
484
+ else:
485
+ for date in json_record["dates"]:
486
+ if (
487
+ not isinstance(date, dict)
488
+ or "date" not in date
489
+ or "dateType" not in date
490
+ ):
491
+ errors.append("Each 'date' must have 'date' and 'dateType'.")
492
+
493
+ # Check for 'identifiers'
494
+ if "identifiers" not in json_record:
495
+ errors.append("'identifiers' field is missing.")
496
+ elif (
497
+ not isinstance(json_record["identifiers"], list)
498
+ or len(json_record["identifiers"]) == 0
499
+ ):
500
+ errors.append("'identifiers' should be a non-empty list.")
501
+ else:
502
+ for identifier in json_record["identifiers"]:
503
+ if (
504
+ not isinstance(identifier, dict)
505
+ or "identifier" not in identifier
506
+ or "identifierType" not in identifier
507
+ ):
508
+ errors.append(
509
+ "Each 'identifier' must have 'identifier' and 'identifierType'."
510
+ )
511
+
512
+ # Check for 'creators'
513
+ if "creators" not in json_record:
514
+ errors.append("'creators' field is missing.")
515
+ elif (
516
+ not isinstance(json_record["creators"], list)
517
+ or len(json_record["creators"]) == 0
518
+ ):
519
+ errors.append("'creators' should be a non-empty list.")
520
+ else:
521
+ for creator in json_record["creators"]:
522
+ if not isinstance(creator, dict):
523
+ errors.append("Each 'creator' must be a dictionry")
524
+ if "nameType" in creator:
525
+ if creator["nameType"] == "Organizational":
526
+ if "name" not in creator:
527
+ errors.append("Each organizational 'creator' must have 'name'.")
528
+ else:
529
+ if "familyName" not in creator:
498
530
  errors.append(
499
- "Each entry in 'rightsList' must be a dictionary with a 'rights' key."
531
+ "Each 'creator' must have a 'familyName' or have type Organizational"
500
532
  )
533
+ if "affiliation" in creator:
534
+ if not isinstance(creator["affiliation"], list):
535
+ errors.append("'affiliation' in 'creators' should be a list.")
536
+ for affiliation in creator["affiliation"]:
537
+ if not isinstance(affiliation, dict) or "name" not in affiliation:
538
+ errors.append(
539
+ "Each 'affiliation' in 'creators' must have a 'name'."
540
+ )
541
+
542
+ # Check for 'contributors'
543
+ if "contributors" in json_record:
544
+ if (
545
+ not isinstance(json_record["contributors"], list)
546
+ or len(json_record["contributors"]) == 0
547
+ ):
548
+ errors.append("'creators' should be a non-empty list.")
549
+ else:
550
+ for contributor in json_record["contributors"]:
551
+ if not isinstance(contributor, dict):
552
+ errors.append("Each 'contributor' must be a dictionry")
553
+ if "nameType" in contributor:
554
+ if contributor["nameType"] == "Organizational":
555
+ if "name" not in creator:
556
+ errors.append(
557
+ "Each organizational 'contributor' must have 'name'."
558
+ )
559
+ else:
560
+ if "familyName" not in contributor:
561
+ errors.append(
562
+ "Each 'contributor' must have a 'familyName' or have type Organizational"
563
+ )
564
+ if "affiliation" in contributor:
565
+ if not isinstance(contributor["affiliation"], list):
566
+ errors.append(
567
+ "'affiliation' in 'contributors' should be a list."
568
+ )
569
+ for affiliation in contributor["affiliation"]:
570
+ if (
571
+ not isinstance(affiliation, dict)
572
+ or "name" not in affiliation
573
+ ):
574
+ errors.append(
575
+ "Each 'affiliation' in 'contributors' must have a 'name'."
576
+ )
501
577
 
502
578
  # Check for 'geoLocations'
503
579
  if "geoLocations" in json_record:
504
580
  if not isinstance(json_record["geoLocations"], list):
505
581
  errors.append("'geoLocations' should be a list.")
506
582
  else:
583
+
584
+ for geo_loc in json_record["geoLocations"]:
585
+ if not isinstance(geo_loc, dict) or "geoLocationPlace" not in geo_loc:
586
+ errors.append("Each 'geoLocation' must have 'geoLocationPlace'.")
587
+ if "geoLocationPoint" in geo_loc:
588
+ point = geo_loc["geoLocationPoint"]
589
+ if (
590
+ not isinstance(point, dict)
591
+ or "pointLatitude" not in point
592
+ or "pointLongitude" not in point
593
+ ):
594
+ errors.append(
595
+ "'geoLocationPoint' must have 'pointLatitude' and 'pointLongitude'."
596
+ )
597
+
598
+ # Check for 'formats'
599
+ if "formats" in json_record and (
600
+ not isinstance(json_record["formats"], list) or len(json_record["formats"]) == 0
601
+ ):
602
+ errors.append("'formats' should be a non-empty list.")
603
+
604
+ # Check for 'language'
605
+ if "language" in json_record:
606
+ if not isinstance(json_record["language"], str):
607
+ errors.append("'language' should be a string.")
608
+
609
+ # Check for 'version'
610
+ if "version" in json_record and not isinstance(json_record["version"], str):
611
+ errors.append("'version' should be a string.")
612
+
613
+ # Check for 'publisher'
614
+ if "publisher" not in json_record:
615
+ errors.append("'publisher' field is missing.")
616
+ elif not isinstance(json_record["publisher"], str):
617
+ errors.append("'publisher' should be a string.")
618
+
619
+ # Check for 'publicationYear'
620
+ if "publicationYear" not in json_record:
621
+ errors.append("'publicationYear' field is missing.")
622
+ elif not isinstance(json_record["publicationYear"], str):
623
+ errors.append("'publicationYear' should be a string.")
624
+
625
+ # Check for 'types'
626
+ if "types" not in json_record:
627
+ errors.append("'types' field is missing.")
628
+ elif not isinstance(json_record["types"], dict):
629
+ errors.append("'types' should be a dictionary.")
630
+ else:
631
+ if "resourceTypeGeneral" not in json_record["types"]:
632
+ errors.append("'types' must have 'resourceTypeGeneral'.")
633
+ if "resourceType" in json_record["types"] and not isinstance(
634
+ json_record["types"]["resourceType"], str
635
+ ):
636
+ errors.append("'resourceType' should be a string if provided.")
507
637
  for location in json_record["geoLocations"]:
508
638
  if not isinstance(location, dict):
509
639
  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.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, 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