commonmeta-py 0.106__py3-none-any.whl → 0.108__py3-none-any.whl
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.
- commonmeta/__init__.py +12 -3
- commonmeta/api_utils.py +3 -2
- commonmeta/base_utils.py +186 -3
- commonmeta/cli.py +114 -34
- commonmeta/constants.py +20 -0
- commonmeta/file_utils.py +112 -0
- commonmeta/metadata.py +102 -42
- commonmeta/readers/codemeta_reader.py +1 -1
- commonmeta/readers/crossref_reader.py +23 -10
- commonmeta/readers/crossref_xml_reader.py +1 -1
- commonmeta/readers/datacite_reader.py +6 -4
- commonmeta/readers/{json_feed_reader.py → jsonfeed_reader.py} +12 -12
- commonmeta/resources/crossref/common5.4.0.xsd +1264 -0
- commonmeta/resources/crossref/{crossref5.3.1.xsd → crossref5.4.0.xsd} +286 -88
- commonmeta/resources/crossref/doi_resources5.4.0.xsd +117 -0
- commonmeta/resources/crossref/fundingdata5.4.0.xsd +59 -0
- commonmeta/resources/crossref/fundref.xsd +29 -19
- commonmeta/resources/crossref/languages5.4.0.xsd +8119 -0
- commonmeta/resources/crossref/mediatypes5.4.0.xsd +2207 -0
- commonmeta/resources/crossref/module-ali.xsd +14 -6
- commonmeta/resources/crossref/standard-modules/mathml3/mathml3-common.xsd +101 -0
- commonmeta/resources/crossref/standard-modules/mathml3/mathml3-content.xsd +683 -0
- commonmeta/resources/crossref/standard-modules/mathml3/mathml3-presentation.xsd +2092 -0
- commonmeta/resources/crossref/standard-modules/mathml3/mathml3-strict-content.xsd +186 -0
- commonmeta/resources/crossref/standard-modules/mathml3/mathml3.xsd +9 -0
- commonmeta/resources/crossref/standard-modules/mathml3/module-ali.xsd +47 -0
- commonmeta/resources/crossref/standard-modules/module-ali.xsd +47 -0
- commonmeta/resources/crossref/standard-modules/xlink.xsd +100 -0
- commonmeta/resources/crossref/standard-modules/xml.xsd +287 -0
- commonmeta/resources/crossref/xml.xsd +287 -0
- commonmeta/schema_utils.py +25 -0
- commonmeta/utils.py +90 -15
- commonmeta/writers/bibtex_writer.py +5 -5
- commonmeta/writers/citation_writer.py +10 -5
- commonmeta/writers/commonmeta_writer.py +5 -17
- commonmeta/writers/crossref_xml_writer.py +1032 -4
- commonmeta/writers/csl_writer.py +6 -6
- commonmeta/writers/datacite_writer.py +11 -6
- commonmeta/writers/inveniordm_writer.py +286 -10
- commonmeta/writers/ris_writer.py +3 -3
- commonmeta/writers/schema_org_writer.py +10 -5
- {commonmeta_py-0.106.dist-info → commonmeta_py-0.108.dist-info}/METADATA +5 -2
- {commonmeta_py-0.106.dist-info → commonmeta_py-0.108.dist-info}/RECORD +46 -32
- commonmeta/crossref_utils.py +0 -583
- commonmeta/resources/crossref/common5.3.1.xsd +0 -1538
- {commonmeta_py-0.106.dist-info → commonmeta_py-0.108.dist-info}/WHEEL +0 -0
- {commonmeta_py-0.106.dist-info → commonmeta_py-0.108.dist-info}/entry_points.txt +0 -0
- {commonmeta_py-0.106.dist-info → commonmeta_py-0.108.dist-info}/licenses/LICENSE +0 -0
commonmeta/writers/csl_writer.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
"""CSL-JSON writer for commonmeta-py"""
|
2
2
|
|
3
|
-
import orjson as json
|
4
3
|
from typing import Optional
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
import orjson as json
|
6
|
+
|
7
|
+
from ..base_utils import compact, parse_attributes, presence, wrap
|
8
|
+
from ..constants import CM_TO_CSL_TRANSLATIONS, Commonmeta
|
8
9
|
from ..date_utils import get_date_parts
|
9
10
|
from ..doi_utils import doi_from_url
|
10
|
-
from ..
|
11
|
+
from ..utils import pages_as_string, to_csl
|
11
12
|
|
12
13
|
|
13
14
|
def write_csl(metadata: Commonmeta) -> Optional[str]:
|
@@ -78,5 +79,4 @@ def write_csl_list(metalist):
|
|
78
79
|
"""Write CSL-JSON list"""
|
79
80
|
if metalist is None:
|
80
81
|
return None
|
81
|
-
|
82
|
-
return json.dumps(items)
|
82
|
+
return [write_csl_item(item) for item in metalist.items]
|
@@ -1,19 +1,18 @@
|
|
1
1
|
"""DataCite writer for commonmeta-py"""
|
2
2
|
|
3
|
-
import orjson as json
|
4
3
|
from typing import Optional, Union
|
5
4
|
|
6
|
-
from ..base_utils import
|
7
|
-
from ..doi_utils import doi_from_url, normalize_doi
|
5
|
+
from ..base_utils import compact, wrap
|
8
6
|
from ..constants import (
|
9
7
|
CM_TO_BIB_TRANSLATIONS,
|
10
|
-
CM_TO_CSL_TRANSLATIONS,
|
11
8
|
CM_TO_CR_TRANSLATIONS,
|
9
|
+
CM_TO_CSL_TRANSLATIONS,
|
12
10
|
CM_TO_DC_TRANSLATIONS,
|
13
11
|
CM_TO_RIS_TRANSLATIONS,
|
14
12
|
CM_TO_SO_TRANSLATIONS,
|
15
13
|
Commonmeta,
|
16
14
|
)
|
15
|
+
from ..doi_utils import doi_from_url, normalize_doi
|
17
16
|
|
18
17
|
|
19
18
|
def write_datacite(metadata: Commonmeta) -> Optional[Union[str, dict]]:
|
@@ -114,7 +113,7 @@ def write_datacite(metadata: Commonmeta) -> Optional[Union[str, dict]]:
|
|
114
113
|
for i in wrap(metadata.descriptions)
|
115
114
|
]
|
116
115
|
|
117
|
-
|
116
|
+
return compact(
|
118
117
|
{
|
119
118
|
"id": metadata.id,
|
120
119
|
"doi": doi_from_url(metadata.id),
|
@@ -138,7 +137,6 @@ def write_datacite(metadata: Commonmeta) -> Optional[Union[str, dict]]:
|
|
138
137
|
"schemaVersion": "http://datacite.org/schema/kernel-4",
|
139
138
|
}
|
140
139
|
)
|
141
|
-
return json.dumps(data)
|
142
140
|
|
143
141
|
|
144
142
|
def to_datacite_creator(creator: dict) -> dict:
|
@@ -194,3 +192,10 @@ def to_datacite_related_identifier(reference: dict) -> dict:
|
|
194
192
|
"relationType": "References",
|
195
193
|
}
|
196
194
|
)
|
195
|
+
|
196
|
+
|
197
|
+
def write_datacite_list(metalist):
|
198
|
+
"""Write DataCite list"""
|
199
|
+
if metalist is None:
|
200
|
+
return None
|
201
|
+
return [write_datacite(item) for item in metalist.items]
|
@@ -1,23 +1,29 @@
|
|
1
1
|
"""InvenioRDM writer for commonmeta-py"""
|
2
2
|
|
3
|
-
import
|
3
|
+
import re
|
4
4
|
from typing import Optional
|
5
|
+
from urllib.parse import urlparse
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
import orjson as json
|
8
|
+
import pydash as py_
|
9
|
+
import requests
|
10
|
+
|
11
|
+
from ..base_utils import compact, parse_attributes, presence, wrap
|
9
12
|
from ..constants import (
|
10
13
|
CM_TO_INVENIORDM_TRANSLATIONS,
|
11
|
-
|
14
|
+
COMMUNITY_TRANSLATIONS,
|
12
15
|
CROSSREF_FUNDER_ID_TO_ROR_TRANSLATIONS,
|
16
|
+
INVENIORDM_IDENTIFIER_TYPES,
|
13
17
|
)
|
18
|
+
from ..date_utils import get_iso8601_date
|
19
|
+
from ..doi_utils import doi_from_url, normalize_doi
|
14
20
|
from ..utils import (
|
21
|
+
FOS_MAPPINGS,
|
15
22
|
get_language,
|
16
|
-
validate_orcid,
|
17
|
-
validate_ror,
|
18
23
|
id_from_url,
|
19
24
|
normalize_url,
|
20
|
-
|
25
|
+
validate_orcid,
|
26
|
+
validate_ror,
|
21
27
|
)
|
22
28
|
|
23
29
|
|
@@ -89,7 +95,7 @@ def write_inveniordm(metadata):
|
|
89
95
|
)
|
90
96
|
|
91
97
|
subjects = [to_inveniordm_subject(i) for i in wrap(metadata.subjects)]
|
92
|
-
|
98
|
+
return compact(
|
93
99
|
{
|
94
100
|
"pids": {
|
95
101
|
"doi": {
|
@@ -142,7 +148,6 @@ def write_inveniordm(metadata):
|
|
142
148
|
),
|
143
149
|
}
|
144
150
|
)
|
145
|
-
return json.dumps(data, option=json.OPT_INDENT_2)
|
146
151
|
|
147
152
|
|
148
153
|
def to_inveniordm_creator(creator: dict) -> dict:
|
@@ -356,3 +361,274 @@ def to_inveniordm_funding(funding: dict) -> Optional[dict]:
|
|
356
361
|
),
|
357
362
|
}
|
358
363
|
)
|
364
|
+
|
365
|
+
|
366
|
+
def write_inveniordm_list(metalist):
|
367
|
+
"""Write InvenioRDM list"""
|
368
|
+
if metalist is None:
|
369
|
+
return None
|
370
|
+
return [write_inveniordm(item) for item in metalist.items]
|
371
|
+
|
372
|
+
|
373
|
+
def push_inveniordm(metadata, host: str, token: str):
|
374
|
+
"""Push record to InvenioRDM"""
|
375
|
+
|
376
|
+
record = {}
|
377
|
+
input = write_inveniordm(metadata)
|
378
|
+
|
379
|
+
try:
|
380
|
+
# Remove IsPartOf relation with InvenioRDM community identifier after storing it
|
381
|
+
community_index = None
|
382
|
+
if hasattr(metadata, "relations") and metadata.relations:
|
383
|
+
for i, relation in enumerate(metadata.relations):
|
384
|
+
if (relation.get("type") == "IsPartOf" and
|
385
|
+
relation.get("id", "").startswith("https://rogue-scholar.org/api/communities/")):
|
386
|
+
slug = relation.get("id").split("/")[5]
|
387
|
+
community_id, _ = search_by_slug(slug, "blog", host, token)
|
388
|
+
if community_id:
|
389
|
+
record["community"] = slug
|
390
|
+
record["community_id"] = community_id
|
391
|
+
community_index = i
|
392
|
+
|
393
|
+
# Remove the relation if we found and processed it
|
394
|
+
if community_index is not None and hasattr(metadata, "relations"):
|
395
|
+
metadata.relations.pop(community_index)
|
396
|
+
|
397
|
+
# Remove InvenioRDM rid after storing it
|
398
|
+
# rid_index = None
|
399
|
+
# if hasattr(metadata, "identifiers") and metadata.identifiers:
|
400
|
+
# for i, identifier in enumerate(metadata.identifiers):
|
401
|
+
# if identifier.get("identifierType") == "RID" and identifier.get("identifier"):
|
402
|
+
# record["id"] = identifier.get("identifier")
|
403
|
+
# rid_index = i
|
404
|
+
# elif identifier.get("identifierType") == "UUID" and identifier.get("identifier"):
|
405
|
+
# record["uuid"] = identifier.get("identifier")
|
406
|
+
|
407
|
+
# # Remove the identifier if we found and processed it
|
408
|
+
# if rid_index is not None and hasattr(metadata, "identifiers"):
|
409
|
+
# metadata.identifiers.pop(rid_index)
|
410
|
+
|
411
|
+
# Check if record already exists in InvenioRDM
|
412
|
+
record["id"] = search_by_doi(doi_from_url(metadata.id), host, token)
|
413
|
+
|
414
|
+
if record["id"] is not None:
|
415
|
+
|
416
|
+
# Create draft record from published record
|
417
|
+
record = edit_published_record(record, host, token)
|
418
|
+
|
419
|
+
# Update draft record
|
420
|
+
record = update_draft_record(record, host, token, input)
|
421
|
+
else:
|
422
|
+
# Create draft record
|
423
|
+
record = create_draft_record(record, host, token, input)
|
424
|
+
|
425
|
+
# Publish draft record
|
426
|
+
record = publish_draft_record(record, host, token)
|
427
|
+
|
428
|
+
# Add record to blog community if blog community is specified and exists
|
429
|
+
if record.get("community_id", None) is not None:
|
430
|
+
record = add_record_to_community(
|
431
|
+
record, host, token, record["community_id"]
|
432
|
+
)
|
433
|
+
|
434
|
+
# Add record to subject area community if subject area community is specified and exists
|
435
|
+
# Subject area communities should exist for all subjects in the FOSMappings
|
436
|
+
|
437
|
+
if hasattr(metadata, "subjects"):
|
438
|
+
for subject in metadata.subjects:
|
439
|
+
slug = string_to_slug(subject.get("subject", ""))
|
440
|
+
if slug in COMMUNITY_TRANSLATIONS:
|
441
|
+
slug = COMMUNITY_TRANSLATIONS[slug]
|
442
|
+
|
443
|
+
community_id = search_by_slug(slug, "topic", host, token)
|
444
|
+
if community_id:
|
445
|
+
record = add_record_to_community(
|
446
|
+
record, host, token, community_id
|
447
|
+
)
|
448
|
+
|
449
|
+
# Add record to communities defined as IsPartOf relation in inveniordm metadata's RelatedIdentifiers
|
450
|
+
related_identifiers = py_.get(input, "metadata.related_identifiers")
|
451
|
+
|
452
|
+
for identifier in wrap(related_identifiers):
|
453
|
+
if py_.get(identifier, "relation_type.id") == "ispartof":
|
454
|
+
parsed_url = urlparse(identifier.get("identifier", ""))
|
455
|
+
path_parts = parsed_url.path.split("/")
|
456
|
+
|
457
|
+
if (
|
458
|
+
parsed_url.netloc == urlparse(host).netloc
|
459
|
+
and len(path_parts) == 3
|
460
|
+
and path_parts[1] == "communities"
|
461
|
+
):
|
462
|
+
record = add_record_to_community(
|
463
|
+
record, host, token, path_parts[2]
|
464
|
+
)
|
465
|
+
except Exception as e:
|
466
|
+
raise InvenioRDMError(f"Unexpected error: {str(e)}")
|
467
|
+
|
468
|
+
return record
|
469
|
+
|
470
|
+
|
471
|
+
def push_inveniordm_list(metalist, host: str, token: str) -> list:
|
472
|
+
"""Push inveniordm list to InvenioRDM, returns list of push results."""
|
473
|
+
|
474
|
+
if metalist is None:
|
475
|
+
return None
|
476
|
+
items = [push_inveniordm(item, host, token) for item in metalist.items]
|
477
|
+
return json.dumps(items, option=json.OPT_INDENT_2)
|
478
|
+
|
479
|
+
|
480
|
+
def search_by_doi(doi, host, token) -> Optional[str]:
|
481
|
+
"""Search for a record by DOI in InvenioRDM"""
|
482
|
+
headers = {
|
483
|
+
"Authorization": f"Bearer {token}",
|
484
|
+
"Content-Type": "application/json",
|
485
|
+
}
|
486
|
+
params = {"q": f"doi:{doi}", "size": 1}
|
487
|
+
try:
|
488
|
+
response = requests.get(f"https://{host}/api/records", headers=headers, params=params)
|
489
|
+
response.raise_for_status()
|
490
|
+
data = response.json()
|
491
|
+
if py_.get(data, "hits.total") or 0 > 0:
|
492
|
+
return py_.get(data, "hits.hits.0.id")
|
493
|
+
return None
|
494
|
+
except requests.exceptions.RequestException as e:
|
495
|
+
raise InvenioRDMError(f"Error searching for DOI: {str(e)}")
|
496
|
+
|
497
|
+
|
498
|
+
def create_draft_record(record, host, token, input):
|
499
|
+
"""Create a new draft record in InvenioRDM"""
|
500
|
+
headers = {
|
501
|
+
"Authorization": f"Bearer {token}",
|
502
|
+
"Content-Type": "application/json",
|
503
|
+
}
|
504
|
+
try:
|
505
|
+
response = requests.post(f"https://{host}/api/records", headers=headers, json=input)
|
506
|
+
response.raise_for_status()
|
507
|
+
data = response.json()
|
508
|
+
return {
|
509
|
+
"id": data.get("id", None),
|
510
|
+
"created": data.get("created", None),
|
511
|
+
"updated": data.get("updated", None),
|
512
|
+
"status": "updated"
|
513
|
+
}
|
514
|
+
except requests.exceptions.RequestException as e:
|
515
|
+
raise InvenioRDMError(f"Error creating draft record: {str(e)}")
|
516
|
+
|
517
|
+
|
518
|
+
def edit_published_record(record, host, token):
|
519
|
+
"""Create a draft from a published record in InvenioRDM"""
|
520
|
+
headers = {
|
521
|
+
"Authorization": f"Bearer {token}",
|
522
|
+
"Content-Type": "application/json",
|
523
|
+
}
|
524
|
+
try:
|
525
|
+
response = requests.post(
|
526
|
+
f"https://{host}/api/records/{record['id']}/draft", headers=headers
|
527
|
+
)
|
528
|
+
response.raise_for_status()
|
529
|
+
data = response.json()
|
530
|
+
record["doi"] = py_.get(data, "pids.doi.identifier")
|
531
|
+
record["created"] = data.get("created", None)
|
532
|
+
record["updated"] = data.get("updated", None)
|
533
|
+
record["status"] = "edited"
|
534
|
+
return record
|
535
|
+
except requests.exceptions.RequestException as e:
|
536
|
+
raise InvenioRDMError(f"Error creating draft from published record: {str(e)}")
|
537
|
+
|
538
|
+
|
539
|
+
def update_draft_record(record, host, token, inveniordm_data):
|
540
|
+
"""Update a draft record in InvenioRDM"""
|
541
|
+
headers = {
|
542
|
+
"Authorization": f"Bearer {token}",
|
543
|
+
"Content-Type": "application/json",
|
544
|
+
}
|
545
|
+
try:
|
546
|
+
response = requests.put(
|
547
|
+
f"https://{host}/api/records/{record['id']}/draft",
|
548
|
+
headers=headers,
|
549
|
+
json=inveniordm_data,
|
550
|
+
)
|
551
|
+
response.raise_for_status()
|
552
|
+
data = response.json()
|
553
|
+
record["created"] = data.get("created", None)
|
554
|
+
record["updated"] = data.get("updated", None)
|
555
|
+
record["status"] = "updated"
|
556
|
+
return record
|
557
|
+
except requests.exceptions.RequestException as e:
|
558
|
+
raise InvenioRDMError(f"Error updating draft record: {str(e)}")
|
559
|
+
|
560
|
+
|
561
|
+
def publish_draft_record(record, host, token):
|
562
|
+
"""Publish a draft record in InvenioRDM"""
|
563
|
+
headers = {
|
564
|
+
"Authorization": f"Bearer {token}",
|
565
|
+
"Content-Type": "application/json",
|
566
|
+
}
|
567
|
+
try:
|
568
|
+
response = requests.post(
|
569
|
+
f"https://{host}/api/records/{record['id']}/draft/actions/publish",
|
570
|
+
headers=headers,
|
571
|
+
)
|
572
|
+
response.raise_for_status()
|
573
|
+
data = response.json()
|
574
|
+
record["created"] = data.get("created", None)
|
575
|
+
record["updated"] = data.get("updated", None)
|
576
|
+
record["status"] = "published"
|
577
|
+
return record
|
578
|
+
except requests.exceptions.RequestException as e:
|
579
|
+
raise InvenioRDMError(f"Error publishing draft record: {str(e)}")
|
580
|
+
|
581
|
+
|
582
|
+
def add_record_to_community(record, host, token, community_id):
|
583
|
+
"""Add a record to a community in InvenioRDM"""
|
584
|
+
headers = {
|
585
|
+
"Authorization": f"Bearer {token}",
|
586
|
+
"Content-Type": "application/json",
|
587
|
+
}
|
588
|
+
try:
|
589
|
+
response = requests.post(
|
590
|
+
f"https://{host}/api/records/{record['id']}/communities",
|
591
|
+
headers=headers,
|
592
|
+
json={"id": community_id},
|
593
|
+
)
|
594
|
+
response.raise_for_status()
|
595
|
+
return record
|
596
|
+
except requests.exceptions.RequestException as e:
|
597
|
+
raise InvenioRDMError(f"Error adding record to community: {str(e)}")
|
598
|
+
|
599
|
+
|
600
|
+
def search_by_slug(slug, type_value, host, token) -> Optional[str]:
|
601
|
+
"""Search for a community by slug in InvenioRDM"""
|
602
|
+
headers = {
|
603
|
+
"Authorization": f"Bearer {token}",
|
604
|
+
"Content-Type": "application/json",
|
605
|
+
}
|
606
|
+
params = {"q": f"slug:{slug} AND type:{type_value}", "size": 1}
|
607
|
+
try:
|
608
|
+
response = requests.get(
|
609
|
+
f"https://{host}/api/communities", headers=headers, params=params
|
610
|
+
)
|
611
|
+
response.raise_for_status()
|
612
|
+
data = response.json()
|
613
|
+
if py_.get(data, "hits.total") or 0 > 0:
|
614
|
+
return py_.get(data, "hits.hits.0.id")
|
615
|
+
return None
|
616
|
+
except requests.exceptions.RequestException as e:
|
617
|
+
raise InvenioRDMError(f"Error searching for community: {str(e)}")
|
618
|
+
|
619
|
+
|
620
|
+
def string_to_slug(text):
|
621
|
+
"""Convert a string to a slug format"""
|
622
|
+
# Replace spaces with hyphens
|
623
|
+
slug = re.sub(r"\s+", "-", text.lower())
|
624
|
+
# Remove special characters
|
625
|
+
slug = re.sub(r"[^a-z0-9-]", "", slug)
|
626
|
+
# Remove multiple consecutive hyphens
|
627
|
+
slug = re.sub(r"-+", "-", slug)
|
628
|
+
# Remove leading and trailing hyphens
|
629
|
+
slug = slug.strip("-")
|
630
|
+
return slug
|
631
|
+
|
632
|
+
|
633
|
+
class InvenioRDMError(Exception):
|
634
|
+
"""Custom exception for InvenioRDM API errors"""
|
commonmeta/writers/ris_writer.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
"""RIS writer for commonmeta-py"""
|
2
2
|
|
3
|
-
from ..
|
4
|
-
from ..base_utils import compact, wrap, presence, parse_attributes
|
5
|
-
from ..doi_utils import doi_from_url
|
3
|
+
from ..base_utils import compact, parse_attributes, presence, wrap
|
6
4
|
from ..constants import CM_TO_RIS_TRANSLATIONS
|
5
|
+
from ..doi_utils import doi_from_url
|
6
|
+
from ..utils import to_ris
|
7
7
|
|
8
8
|
|
9
9
|
def write_ris(metadata):
|
@@ -1,9 +1,8 @@
|
|
1
1
|
"""Schema.org writer for commonmeta-py"""
|
2
2
|
|
3
|
-
import
|
4
|
-
from ..utils import to_schema_org_creators, github_as_repo_url, get_language
|
5
|
-
from ..base_utils import compact, wrap, presence, parse_attributes
|
3
|
+
from ..base_utils import compact, parse_attributes, presence, wrap
|
6
4
|
from ..constants import CM_TO_SO_TRANSLATIONS
|
5
|
+
from ..utils import get_language, github_as_repo_url, to_schema_org_creators
|
7
6
|
|
8
7
|
|
9
8
|
def write_schema_org(metadata):
|
@@ -97,7 +96,7 @@ def write_schema_org(metadata):
|
|
97
96
|
else:
|
98
97
|
code_repository = None
|
99
98
|
|
100
|
-
|
99
|
+
return compact(
|
101
100
|
{
|
102
101
|
"@context": "http://schema.org",
|
103
102
|
"@id": metadata.id,
|
@@ -144,4 +143,10 @@ def write_schema_org(metadata):
|
|
144
143
|
else None,
|
145
144
|
}
|
146
145
|
)
|
147
|
-
|
146
|
+
|
147
|
+
|
148
|
+
def write_schema_org_list(metalist):
|
149
|
+
"""Write Schema.org list"""
|
150
|
+
if metalist is None:
|
151
|
+
return None
|
152
|
+
return [write_schema_org(item) for item in metalist.items]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: commonmeta-py
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.108
|
4
4
|
Summary: Library for conversions to/from the Commonmeta scholarly metadata format
|
5
5
|
Project-URL: Homepage, https://python.commonmeta.org
|
6
6
|
Project-URL: Repository, https://github.com/front-matter/commonmeta-py
|
@@ -22,6 +22,7 @@ Requires-Dist: edtf<6,>=5.0.0
|
|
22
22
|
Requires-Dist: furl<3,>=2.1.3
|
23
23
|
Requires-Dist: jsonschema~=4.21
|
24
24
|
Requires-Dist: lxml>=4.8
|
25
|
+
Requires-Dist: marshmallow-utils>=0.10.0
|
25
26
|
Requires-Dist: nameparser<2,>=1.1.1
|
26
27
|
Requires-Dist: nh3<0.3,>=0.2.14
|
27
28
|
Requires-Dist: orjson<4,>=3.9.14
|
@@ -32,6 +33,7 @@ Requires-Dist: pydash<9,>=6
|
|
32
33
|
Requires-Dist: pyjwt<3,>=2.8.0
|
33
34
|
Requires-Dist: python-dateutil<3,>=2.8.2
|
34
35
|
Requires-Dist: pyyaml>=5.4
|
36
|
+
Requires-Dist: requests-toolbelt>=1.0.0
|
35
37
|
Requires-Dist: requests>=2.31.0
|
36
38
|
Requires-Dist: requests>=2.32.3
|
37
39
|
Requires-Dist: simplejson~=3.18
|
@@ -39,6 +41,7 @@ Requires-Dist: types-beautifulsoup4<5,>=4.11
|
|
39
41
|
Requires-Dist: types-dateparser~=1.1
|
40
42
|
Requires-Dist: types-pyyaml>=5.4
|
41
43
|
Requires-Dist: types-xmltodict<0.20,>=0.13
|
44
|
+
Requires-Dist: xmlschema>=4.0.1
|
42
45
|
Requires-Dist: xmltodict<0.20,>=0.12
|
43
46
|
Description-Content-Type: text/markdown
|
44
47
|
|
@@ -84,7 +87,7 @@ Commometa-py reads and/or writes these metadata formats:
|
|
84
87
|
| [BibTex](http://en.wikipedia.org/wiki/BibTeX) | bibtex | application/x-bibtex | later | yes |
|
85
88
|
| [RIS](http://en.wikipedia.org/wiki/RIS_(file_format)) | ris | application/x-research-info-systems | yes | yes |
|
86
89
|
| [InvenioRDM](https://inveniordm.docs.cern.ch/reference/metadata/) | inveniordm | application/vnd.inveniordm.v1+json | yes | yes |
|
87
|
-
| [JSON Feed](https://www.jsonfeed.org/) |
|
90
|
+
| [JSON Feed](https://www.jsonfeed.org/) | jsonfeed | application/feed+json | yes | later |
|
88
91
|
| [OpenAlex](https://www.openalex.org/) | openalex | | yes | no |
|
89
92
|
|
90
93
|
_commonmeta_: the Commonmeta format is the native format for the library and used internally.
|
@@ -1,28 +1,28 @@
|
|
1
|
-
commonmeta/__init__.py,sha256=
|
2
|
-
commonmeta/api_utils.py,sha256=
|
1
|
+
commonmeta/__init__.py,sha256=7kDKE1h51jYNNQSQyUDc0iF2H0Wd0ElrZqAxGJeoUIg,2098
|
2
|
+
commonmeta/api_utils.py,sha256=y5KLfIOWOjde7LXZ36u-eneQJ-Q53yXUZg3hWpCBS2E,2685
|
3
3
|
commonmeta/author_utils.py,sha256=3lYW5s1rOUWNTKs1FP6XLfEUY3yCLOe_3L_VdJTDMp0,8585
|
4
|
-
commonmeta/base_utils.py,sha256
|
5
|
-
commonmeta/cli.py,sha256=
|
6
|
-
commonmeta/constants.py,sha256=
|
7
|
-
commonmeta/crossref_utils.py,sha256=mEXNP7LQXcJyEmCqcpWxi_VI3GU1ZD_XvarYjUMxPL0,22284
|
4
|
+
commonmeta/base_utils.py,sha256=-MGy9q2uTiJEkPWQUYOJMdq-3tRpNnvBwlLjvllQ5g8,11164
|
5
|
+
commonmeta/cli.py,sha256=OALbEqHaLO2L8KdzKqW4N1VpKqvtCKbfQkCTPevQWxA,8449
|
6
|
+
commonmeta/constants.py,sha256=wSTEUiHeRdXLwjXEQD9AU2hxFyEKi5OTX2iHOKO6nF0,19844
|
8
7
|
commonmeta/date_utils.py,sha256=H2cCobX0JREIUOT_cCigGd3MG7prGiQpXk1m4ZNrFwU,6318
|
9
8
|
commonmeta/doi_utils.py,sha256=ZztajfOLtnASk1BbQ1Y2Q4B_xxlnbujn7Opx5a1U5vY,9582
|
10
|
-
commonmeta/
|
11
|
-
commonmeta/
|
9
|
+
commonmeta/file_utils.py,sha256=tGvXxScjh-PPo5YvLDyk4sqwY5Q50N0zAmBHVaUOLeU,3268
|
10
|
+
commonmeta/metadata.py,sha256=TF1BHS7R56xBNc84JhKE5-sysNNgd-n_cX4pXGG75sE,18778
|
11
|
+
commonmeta/schema_utils.py,sha256=WGpmMj9cfNMg_55hhgwY9qpO0A1HSvTLQC2equjBftI,1770
|
12
12
|
commonmeta/translators.py,sha256=CBMK4jrXRmGZiAhCh6wsJjhbDJWbcsda8UvXFXxccAw,1363
|
13
|
-
commonmeta/utils.py,sha256=
|
13
|
+
commonmeta/utils.py,sha256=pJnh3EzOU1E2nutnAZsopY_NsUX6zYmxoj5bIYqqWvE,50574
|
14
14
|
commonmeta/readers/__init__.py,sha256=vOf7UsOKNoh_ZCuyexxhAmPMt8wjB-pF_CfpWRaN8pk,45
|
15
15
|
commonmeta/readers/bibtex_reader.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
commonmeta/readers/cff_reader.py,sha256=kIG-OKGQz37oWL6cU3Cz7HQ83DnRCmQ2PKSjIDodSp8,6152
|
17
|
-
commonmeta/readers/codemeta_reader.py,sha256=
|
17
|
+
commonmeta/readers/codemeta_reader.py,sha256=fF0bIYf3J2mpgfdtM0C1lbDexUuoVO7JS1cFf7P--2E,3655
|
18
18
|
commonmeta/readers/commonmeta_reader.py,sha256=46XrCr2whkUP4uiaNiFXS7ABwowcRdWcLG-3OcfhVdk,303
|
19
|
-
commonmeta/readers/crossref_reader.py,sha256=
|
20
|
-
commonmeta/readers/crossref_xml_reader.py,sha256=
|
19
|
+
commonmeta/readers/crossref_reader.py,sha256=qdHI7PV2rHcwxxnL-xlpF_U-4Tedwolm0SiHWp2mEhQ,13138
|
20
|
+
commonmeta/readers/crossref_xml_reader.py,sha256=A2iAFT2IbhTNcfL-Dx4xO2SFSNOu_HNyPisus0u4UJI,18719
|
21
21
|
commonmeta/readers/csl_reader.py,sha256=OxzC2AZKfv43BCah4XGYvlK_LUK-5mxXFcjdzB5vv_o,3216
|
22
|
-
commonmeta/readers/datacite_reader.py,sha256=
|
22
|
+
commonmeta/readers/datacite_reader.py,sha256=M6gznf1kisR1WzDZaoR0pLJC6Q4Rtnerodfs8lU2khI,12094
|
23
23
|
commonmeta/readers/datacite_xml_reader.py,sha256=zJSuN9pnWplYFH7V1eneh0OjKTFCNkOLmEMf6fU6_xg,13048
|
24
24
|
commonmeta/readers/inveniordm_reader.py,sha256=6LkT6R20jSFqDdZqAzcREHbdAcIPHiYJvxKsK_mpDdw,8374
|
25
|
-
commonmeta/readers/
|
25
|
+
commonmeta/readers/jsonfeed_reader.py,sha256=jn7ux79jGD_ChsBH7zU8_CeCEObIbDh3NDjMhHIzE64,14470
|
26
26
|
commonmeta/readers/kbase_reader.py,sha256=KH3loJvuq2bm8zAYIUG7hTsr5-2Anj3NQvoJUDiqmss,6764
|
27
27
|
commonmeta/readers/openalex_reader.py,sha256=4HUkBsut_iUjhUcC5c1GHgxnKsYQc-fgY43QILgVZEg,12826
|
28
28
|
commonmeta/readers/ris_reader.py,sha256=oQ3G7qQmNwhr4cNp-Gv5UW28J2K1oKpBlPh-tjRtnpQ,3678
|
@@ -46,12 +46,26 @@ commonmeta/resources/crossref/JATS-journalpublishing1-mathml3-elements.xsd,sha25
|
|
46
46
|
commonmeta/resources/crossref/JATS-journalpublishing1-mathml3.xsd,sha256=qEbOzW0gcoXDH2Q964vvTx18dGKFe9Gq7tMJlVvCRsU,2154
|
47
47
|
commonmeta/resources/crossref/JATS-journalpublishing1.xsd,sha256=ZfGOCPqmikVScNlZYa9Gnv3PMJ8bG6YCGWozzlUeueE,227271
|
48
48
|
commonmeta/resources/crossref/clinicaltrials.xsd,sha256=zFQJR6uTOj3zc9enEbzP-1d4GFskXac_8TbHPsIsuJk,2766
|
49
|
-
commonmeta/resources/crossref/common5.
|
50
|
-
commonmeta/resources/crossref/crossref5.
|
49
|
+
commonmeta/resources/crossref/common5.4.0.xsd,sha256=A176KMudM23vFMPznhdBe2GDAmv0l6dX92694t2lzG0,50643
|
50
|
+
commonmeta/resources/crossref/crossref5.4.0.xsd,sha256=c4SuKbEhSv6qkW-v128atK9ZCntqlDJxnE-M_IexUn4,82608
|
51
51
|
commonmeta/resources/crossref/crossref_query_output3.0.xsd,sha256=sL1xvIq_1cqHANp5kIRGClo2eh78-Vld4KIcZS_Oz4k,43457
|
52
|
-
commonmeta/resources/crossref/
|
53
|
-
commonmeta/resources/crossref/
|
52
|
+
commonmeta/resources/crossref/doi_resources5.4.0.xsd,sha256=RNU3NKtgdjo-RtJMTwOSbHq0Eayr15aGPljrqkyo_yo,4137
|
53
|
+
commonmeta/resources/crossref/fundingdata5.4.0.xsd,sha256=aBBg0gaA4hbeH8pwkij57G7lUdshXG9Ks2KREmGm3CA,2848
|
54
|
+
commonmeta/resources/crossref/fundref.xsd,sha256=bloCtt7nqkBNEKviDcEt9RtDAqHTgz3KXWQmZl_7CdU,2816
|
55
|
+
commonmeta/resources/crossref/languages5.4.0.xsd,sha256=Y1CYCxM77ZO0sRsW2pfcqZPF31zI7jEWLv1qBX_rgcs,413886
|
56
|
+
commonmeta/resources/crossref/mediatypes5.4.0.xsd,sha256=HwT_wgf5dHMlHlSuH3YVcsw2qK-GUyL8M3o3I8JLkVM,162554
|
57
|
+
commonmeta/resources/crossref/module-ali.xsd,sha256=c_uliEYCsQHRmKPAv2xTSRsI7LVJQPEQnEahLx_dUjQ,2066
|
54
58
|
commonmeta/resources/crossref/relations.xsd,sha256=f2EJeWHdPWfHLsPgCQdNFryamBw64OA4s3CweQWxsNU,14552
|
59
|
+
commonmeta/resources/crossref/xml.xsd,sha256=YZYPsxMeOAIsqtU2Di8zozgleKs8gM1YvXQyDt5hsgw,8836
|
60
|
+
commonmeta/resources/crossref/standard-modules/module-ali.xsd,sha256=c_uliEYCsQHRmKPAv2xTSRsI7LVJQPEQnEahLx_dUjQ,2066
|
61
|
+
commonmeta/resources/crossref/standard-modules/xlink.xsd,sha256=hLPKD7orYiavWTbBPs2XAaLH1EyTl64MNeSIn5jYD0A,3809
|
62
|
+
commonmeta/resources/crossref/standard-modules/xml.xsd,sha256=YZYPsxMeOAIsqtU2Di8zozgleKs8gM1YvXQyDt5hsgw,8836
|
63
|
+
commonmeta/resources/crossref/standard-modules/mathml3/mathml3-common.xsd,sha256=PwuoibFtuy7Dnu63med3InxR0xKWlzFmEPKx0YWtHbY,4079
|
64
|
+
commonmeta/resources/crossref/standard-modules/mathml3/mathml3-content.xsd,sha256=fyxnn4rCI81Zg1r2LfsGOxj1uOwpGeChhB-PAiVFWj0,28408
|
65
|
+
commonmeta/resources/crossref/standard-modules/mathml3/mathml3-presentation.xsd,sha256=SRmQY4G_8WDQgYayjgo1XNK7POoastQTlYD2Nf2lRfY,81819
|
66
|
+
commonmeta/resources/crossref/standard-modules/mathml3/mathml3-strict-content.xsd,sha256=4IjURTWndMND3qUbjLXyBXt5rwSyrf67lepDhyj3Z2U,6845
|
67
|
+
commonmeta/resources/crossref/standard-modules/mathml3/mathml3.xsd,sha256=9-A8FqxQV05ySALMZ-QjALQE15djBtVqOAkRFWMOLZ4,435
|
68
|
+
commonmeta/resources/crossref/standard-modules/mathml3/module-ali.xsd,sha256=c_uliEYCsQHRmKPAv2xTSRsI7LVJQPEQnEahLx_dUjQ,2066
|
55
69
|
commonmeta/resources/spdx/licenses.json,sha256=acWuaiWFY35GOht9uXgX20vdG-QH7ISrqTL_D0mf2bY,172114
|
56
70
|
commonmeta/resources/styles/apa.csl,sha256=2KSBL2rUz55nJj5ulA9w9E-GLSL8dX0nfCBVUdRP45o,63244
|
57
71
|
commonmeta/resources/styles/chicago-author-date.csl,sha256=e577X6ZqwhajOsrJLXMiOALuwk5_wkLb-Y5BeBB8gW8,23208
|
@@ -60,17 +74,17 @@ commonmeta/resources/styles/ieee.csl,sha256=DfuN__z8FZ5Rcdaj_Myc5y_FmB-fHwfRVTeS
|
|
60
74
|
commonmeta/resources/styles/modern-language-association.csl,sha256=HI2iU4krze1aHYc9VSQCUyw_2I6fEQYnA9xIWo-xNus,11594
|
61
75
|
commonmeta/resources/styles/vancouver.csl,sha256=lun3_i2oTilgsANk4LjFao2UDPQlGj_hgFgKAWC_DF8,12878
|
62
76
|
commonmeta/writers/__init__.py,sha256=47-snms6xBHkoEXKYV1DBtH1npAtlVtvY29Z4Zr45qI,45
|
63
|
-
commonmeta/writers/bibtex_writer.py,sha256=
|
64
|
-
commonmeta/writers/citation_writer.py,sha256=
|
65
|
-
commonmeta/writers/commonmeta_writer.py,sha256=
|
66
|
-
commonmeta/writers/crossref_xml_writer.py,sha256=
|
67
|
-
commonmeta/writers/csl_writer.py,sha256=
|
68
|
-
commonmeta/writers/datacite_writer.py,sha256=
|
69
|
-
commonmeta/writers/inveniordm_writer.py,sha256=
|
70
|
-
commonmeta/writers/ris_writer.py,sha256=
|
71
|
-
commonmeta/writers/schema_org_writer.py,sha256=
|
72
|
-
commonmeta_py-0.
|
73
|
-
commonmeta_py-0.
|
74
|
-
commonmeta_py-0.
|
75
|
-
commonmeta_py-0.
|
76
|
-
commonmeta_py-0.
|
77
|
+
commonmeta/writers/bibtex_writer.py,sha256=doAdyl1NEp60mPkHPo3GMH8B-HA6MzLAdlyNsIecTzU,4972
|
78
|
+
commonmeta/writers/citation_writer.py,sha256=qs_4X3BjrSqHexmJFPvPDTp0mRIqzb0F70_Wuc7S9x0,2343
|
79
|
+
commonmeta/writers/commonmeta_writer.py,sha256=QpfyhG__7o_XpsOTCPWxGymO7YKwZi2LQh8Zic44bdc,1365
|
80
|
+
commonmeta/writers/crossref_xml_writer.py,sha256=d-Rb2Vd_g3UW8GM4APIT7fivSQ5GMssZ6Ubi3OykHaw,33479
|
81
|
+
commonmeta/writers/csl_writer.py,sha256=4gDYs1EzK4_L2UIRTfs25wgHmYRwdRP2zmfxF9387oU,2779
|
82
|
+
commonmeta/writers/datacite_writer.py,sha256=bcinpwhq7XnVthKHH8-sdXA34dSlvFH4ImYH768iaQU,6428
|
83
|
+
commonmeta/writers/inveniordm_writer.py,sha256=eflpF45PGLkA6K2zhaYWS6Y93a3yiHSG8OIUtpocYx8,21791
|
84
|
+
commonmeta/writers/ris_writer.py,sha256=3SdyEvMRaPRP1SV1MB-MXBlunE7x6og7RF1zuWtetPc,2094
|
85
|
+
commonmeta/writers/schema_org_writer.py,sha256=s18_x0ReXwAGBoEAwp2q-HCgFQ-h5qRg6JyAlqCoSFE,5871
|
86
|
+
commonmeta_py-0.108.dist-info/METADATA,sha256=V3w8hPlmCISkGPyKh-fG7vD1BgbevEER-qniG4iFK-w,7618
|
87
|
+
commonmeta_py-0.108.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
88
|
+
commonmeta_py-0.108.dist-info/entry_points.txt,sha256=U4w4BoRuS3rN5t5Y-uYSyOeU5Lh_VRVMS9OIDzIgw4w,50
|
89
|
+
commonmeta_py-0.108.dist-info/licenses/LICENSE,sha256=wsIvxF9Q9GC9vA_s79zTWP3BkXJdfUNRmALlU8GbW1s,1074
|
90
|
+
commonmeta_py-0.108.dist-info/RECORD,,
|