commonmeta-py 0.126__py3-none-any.whl → 0.128__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 +2 -1
- commonmeta/utils.py +66 -0
- commonmeta/writers/inveniordm_writer.py +44 -42
- {commonmeta_py-0.126.dist-info → commonmeta_py-0.128.dist-info}/METADATA +1 -1
- {commonmeta_py-0.126.dist-info → commonmeta_py-0.128.dist-info}/RECORD +8 -8
- {commonmeta_py-0.126.dist-info → commonmeta_py-0.128.dist-info}/WHEEL +0 -0
- {commonmeta_py-0.126.dist-info → commonmeta_py-0.128.dist-info}/entry_points.txt +0 -0
- {commonmeta_py-0.126.dist-info → commonmeta_py-0.128.dist-info}/licenses/LICENSE +0 -0
commonmeta/__init__.py
CHANGED
@@ -10,7 +10,7 @@ commonmeta-py is a Python library to convert scholarly metadata
|
|
10
10
|
"""
|
11
11
|
|
12
12
|
__title__ = "commonmeta-py"
|
13
|
-
__version__ = "0.
|
13
|
+
__version__ = "0.128"
|
14
14
|
__author__ = "Martin Fenner"
|
15
15
|
__license__ = "MIT"
|
16
16
|
|
@@ -96,6 +96,7 @@ from .utils import (
|
|
96
96
|
normalize_url,
|
97
97
|
pages_as_string,
|
98
98
|
replace_curie,
|
99
|
+
string_to_slug,
|
99
100
|
to_csl,
|
100
101
|
validate_orcid,
|
101
102
|
validate_ror,
|
commonmeta/utils.py
CHANGED
@@ -128,6 +128,57 @@ FOS_MAPPINGS = {
|
|
128
128
|
"Other humanities": "http://www.oecd.org/science/inno/38235147.pdf?6.5",
|
129
129
|
}
|
130
130
|
|
131
|
+
FOS_TO_STRING_MAPPINGS = {
|
132
|
+
"Natural sciences": "naturalSciences",
|
133
|
+
"Mathematics": "mathematics",
|
134
|
+
"Computer and information sciences": "computerAndInformationSciences",
|
135
|
+
"Physical sciences": "physicalSciences",
|
136
|
+
"Chemical sciences": "chemicalSciences",
|
137
|
+
"Earth and related environmental sciences": "earthAndRelatedEnvironmentalSciences",
|
138
|
+
"Biological sciences": "biologicalSciences",
|
139
|
+
"Other natural sciences": "otherNaturalSciences",
|
140
|
+
"Engineering and technology": "engineeringAndTechnology",
|
141
|
+
"Civil engineering": "civilEngineering",
|
142
|
+
"Electrical engineering, electronic engineering, information engineering": "electricalEngineering",
|
143
|
+
"Mechanical engineering": "mechanicalEngineering",
|
144
|
+
"Chemical engineering": "chemicalEngineering",
|
145
|
+
"Materials engineering": "materialsEngineering",
|
146
|
+
"Medical engineering": "medicalEngineering",
|
147
|
+
"Environmental engineering": "environmentalEngineering",
|
148
|
+
"Environmental biotechnology": "environmentalBiotechnology",
|
149
|
+
"Industrial biotechnology": "industrialBiotechnology",
|
150
|
+
"Nano technology": "nanoTechnology",
|
151
|
+
"Other engineering and technologies": "otherEngineeringAndTechnologies",
|
152
|
+
"Medical and health sciences": "medicalAndHealthSciences",
|
153
|
+
"Basic medicine": "basicMedicine",
|
154
|
+
"Clinical medicine": "clinicalMedicine",
|
155
|
+
"Health sciences": "healthSciences",
|
156
|
+
"Health biotechnology": "healthBiotechnology",
|
157
|
+
"Other medical sciences": "otherMedicalSciences",
|
158
|
+
"Agricultural sciences": "agriculturalSciences",
|
159
|
+
"Agriculture, forestry, and fisheries": "agricultureForestryAndFisheries",
|
160
|
+
"Animal and dairy science": "animalAndDairyScience",
|
161
|
+
"Veterinary science": "veterinaryScience",
|
162
|
+
"Agricultural biotechnology": "agriculturalBiotechnology",
|
163
|
+
"Other agricultural sciences": "otherAgriculturalSciences",
|
164
|
+
"Social science": "socialScience",
|
165
|
+
"Psychology": "psychology",
|
166
|
+
"Economics and business": "economicsAndBusiness",
|
167
|
+
"Educational sciences": "educationalSciences",
|
168
|
+
"Sociology": "sociology",
|
169
|
+
"Law": "law",
|
170
|
+
"Political science": "politicalScience",
|
171
|
+
"Social and economic geography": "socialAndEconomicGeography",
|
172
|
+
"Media and communications": "mediaAndCommunications",
|
173
|
+
"Other social sciences": "otherSocialSciences",
|
174
|
+
"Humanities": "humanities",
|
175
|
+
"History and archaeology": "historyAndArchaeology",
|
176
|
+
"Languages and literature": "languagesAndLiterature",
|
177
|
+
"Philosophy, ethics and religion": "philosophyEthicsAndReligion",
|
178
|
+
"Arts (arts, history of arts, performing arts, music)": "artsArtsHistoryOfArtsPerformingArtsMusic",
|
179
|
+
"Other humanities": "otherHumanities",
|
180
|
+
}
|
181
|
+
|
131
182
|
|
132
183
|
def normalize_id(pid: Optional[str], **kwargs) -> Optional[str]:
|
133
184
|
"""Check for valid DOI or HTTP(S) URL"""
|
@@ -1274,6 +1325,21 @@ def subjects_as_string(subjects):
|
|
1274
1325
|
return ", ".join(keywords)
|
1275
1326
|
|
1276
1327
|
|
1328
|
+
def string_to_slug(text: str) -> str:
|
1329
|
+
"""Makes a string lowercase and removes non-alphanumeric characters"""
|
1330
|
+
|
1331
|
+
# Remove optional FOS (Fields of Science) prefix
|
1332
|
+
text = text.removeprefix("FOS: ")
|
1333
|
+
|
1334
|
+
# Convert to lowercase and keep only letters and numbers
|
1335
|
+
result = ""
|
1336
|
+
for char in text:
|
1337
|
+
if char.isalnum():
|
1338
|
+
result += char.lower()
|
1339
|
+
|
1340
|
+
return result
|
1341
|
+
|
1342
|
+
|
1277
1343
|
# def reverse():
|
1278
1344
|
# return { 'citation': wrap(related_identifiers).select do |ri|
|
1279
1345
|
# ri['relationType'] == 'IsReferencedBy'
|
@@ -1,7 +1,6 @@
|
|
1
1
|
"""InvenioRDM writer for commonmeta-py"""
|
2
2
|
|
3
3
|
import logging
|
4
|
-
import re
|
5
4
|
from time import time
|
6
5
|
from typing import Dict, Optional
|
7
6
|
|
@@ -18,13 +17,14 @@ from ..constants import (
|
|
18
17
|
Commonmeta,
|
19
18
|
)
|
20
19
|
from ..date_utils import get_iso8601_date
|
21
|
-
from ..doi_utils import
|
20
|
+
from ..doi_utils import doi_from_url, normalize_doi
|
22
21
|
from ..utils import (
|
23
22
|
FOS_MAPPINGS,
|
24
23
|
get_language,
|
25
24
|
id_from_url,
|
26
25
|
normalize_url,
|
27
26
|
pages_as_string,
|
27
|
+
string_to_slug,
|
28
28
|
validate_orcid,
|
29
29
|
validate_ror,
|
30
30
|
)
|
@@ -399,28 +399,17 @@ def push_inveniordm(metadata: Commonmeta, host: str, token: str, **kwargs) -> Di
|
|
399
399
|
"doi": doi,
|
400
400
|
}
|
401
401
|
|
402
|
-
# extract optional information needed
|
403
|
-
#
|
404
|
-
#
|
405
|
-
#
|
402
|
+
# extract optional information needed
|
403
|
+
# uuid is the Rogue Scholar uuid
|
404
|
+
# community_id is the id of the primary community of the record,
|
405
|
+
# in the case of Rogue Scholar the blog community
|
406
|
+
|
406
407
|
if hasattr(metadata, "identifiers") and metadata.identifiers:
|
407
|
-
rid_index = None
|
408
|
-
uuid_index = None
|
409
408
|
for i, identifier in enumerate(metadata.identifiers):
|
410
|
-
if identifier.get("identifierType") == "
|
411
|
-
"identifier"
|
412
|
-
):
|
413
|
-
record["id"] = identifier.get("identifier")
|
414
|
-
rid_index = i
|
415
|
-
elif identifier.get("identifierType") == "UUID" and identifier.get(
|
409
|
+
if identifier.get("identifierType") == "UUID" and identifier.get(
|
416
410
|
"identifier"
|
417
411
|
):
|
418
412
|
record["uuid"] = identifier.get("identifier")
|
419
|
-
uuid_index = i
|
420
|
-
if rid_index is not None:
|
421
|
-
metadata.identifiers.pop(rid_index)
|
422
|
-
if uuid_index is not None:
|
423
|
-
metadata.identifiers.pop(uuid_index)
|
424
413
|
|
425
414
|
if hasattr(metadata, "relations") and metadata.relations:
|
426
415
|
community_index = None
|
@@ -434,6 +423,7 @@ def push_inveniordm(metadata: Commonmeta, host: str, token: str, **kwargs) -> Di
|
|
434
423
|
record["community"] = slug
|
435
424
|
record["community_id"] = community_id
|
436
425
|
community_index = i
|
426
|
+
break
|
437
427
|
|
438
428
|
if community_index is not None:
|
439
429
|
metadata.relations.pop(community_index)
|
@@ -496,8 +486,14 @@ def add_record_to_communities(
|
|
496
486
|
) -> dict:
|
497
487
|
"""Add record to one or more InvenioRDM communities"""
|
498
488
|
|
489
|
+
communities = get_record_communities(record, host, token)
|
490
|
+
community_ids = [c.get("id") for c in communities] if communities else []
|
491
|
+
|
499
492
|
# Add record to primary community if primary community is specified
|
500
|
-
if
|
493
|
+
if (
|
494
|
+
record.get("community_id", None) is not None
|
495
|
+
and record.get("community_id") not in community_ids
|
496
|
+
):
|
501
497
|
record = add_record_to_community(record, host, token, record["community_id"])
|
502
498
|
|
503
499
|
# Add record to subject area community if subject area community is specified
|
@@ -509,9 +505,8 @@ def add_record_to_communities(
|
|
509
505
|
slug = string_to_slug(subject_name)
|
510
506
|
if slug in COMMUNITY_TRANSLATIONS:
|
511
507
|
slug = COMMUNITY_TRANSLATIONS[slug]
|
512
|
-
|
513
508
|
community_id = search_by_slug(slug, "topic", host, token)
|
514
|
-
if community_id:
|
509
|
+
if community_id and community_id not in community_ids:
|
515
510
|
record = add_record_to_community(record, host, token, community_id)
|
516
511
|
|
517
512
|
# Add record to communities defined as IsPartOf relation in InvenioRDM RelatedIdentifiers
|
@@ -522,7 +517,7 @@ def add_record_to_communities(
|
|
522
517
|
).startswith(f"https://{host}/api/communities/"):
|
523
518
|
slug = identifier.get("identifier").split("/")[5]
|
524
519
|
community_id = search_by_slug(slug, "topic", host, token)
|
525
|
-
if community_id:
|
520
|
+
if community_id and community_id not in community_ids:
|
526
521
|
record = add_record_to_community(record, host, token, community_id)
|
527
522
|
|
528
523
|
return record
|
@@ -664,8 +659,6 @@ def publish_draft_record(record, host, token):
|
|
664
659
|
record["status"] = "error_publish_draft_record"
|
665
660
|
return record
|
666
661
|
data = response.json()
|
667
|
-
record["uuid"] = py_.get(data, "metadata.identifiers.0.identifier")
|
668
|
-
record["doi"] = (doi_as_url(py_.get(data, "pids.doi.identifier")),)
|
669
662
|
record["created"] = data.get("created", None)
|
670
663
|
record["updated"] = data.get("updated", None)
|
671
664
|
record["status"] = "published"
|
@@ -676,17 +669,39 @@ def publish_draft_record(record, host, token):
|
|
676
669
|
return record
|
677
670
|
|
678
671
|
|
672
|
+
def get_record_communities(record, host, token):
|
673
|
+
"""Get record communities by id"""
|
674
|
+
headers = {
|
675
|
+
"Authorization": f"Bearer {token}",
|
676
|
+
"Content-Type": "application/json",
|
677
|
+
}
|
678
|
+
try:
|
679
|
+
response = requests.get(
|
680
|
+
f"https://{host}/api/records/{record['id']}/communities",
|
681
|
+
headers=headers,
|
682
|
+
)
|
683
|
+
response.raise_for_status()
|
684
|
+
data = response.json()
|
685
|
+
if py_.get(data, "hits.total", 0) > 0:
|
686
|
+
return py_.get(data, "hits.hits")
|
687
|
+
return None
|
688
|
+
except requests.exceptions.RequestException as e:
|
689
|
+
logger.error(f"Error getting communities: {str(e)}", exc_info=True)
|
690
|
+
return None
|
691
|
+
|
692
|
+
|
679
693
|
def add_record_to_community(record, host, token, community_id):
|
680
|
-
"""Add a record to a community
|
694
|
+
"""Add a record to a community"""
|
681
695
|
headers = {
|
682
696
|
"Authorization": f"Bearer {token}",
|
683
697
|
"Content-Type": "application/json",
|
684
698
|
}
|
699
|
+
json = {"communities": [{"id": community_id}]}
|
685
700
|
try:
|
686
701
|
response = requests.post(
|
687
702
|
f"https://{host}/api/records/{record['id']}/communities",
|
688
703
|
headers=headers,
|
689
|
-
json=
|
704
|
+
json=json,
|
690
705
|
)
|
691
706
|
response.raise_for_status()
|
692
707
|
return record
|
@@ -744,13 +759,13 @@ def update_legacy_record(record, legacy_key: str, field: str = None) -> dict:
|
|
744
759
|
return record
|
745
760
|
|
746
761
|
|
747
|
-
def search_by_slug(slug: str,
|
762
|
+
def search_by_slug(slug: str, type: str, host: str, token: str) -> Optional[str]:
|
748
763
|
"""Search for a community by slug in InvenioRDM"""
|
749
764
|
headers = {
|
750
765
|
"Authorization": f"Bearer {token}",
|
751
766
|
"Content-Type": "application/json",
|
752
767
|
}
|
753
|
-
params =
|
768
|
+
params = [("q", f"slug:{slug}"), ("type", type), ("type", "subject"), ("size", 1)]
|
754
769
|
try:
|
755
770
|
response = requests.get(
|
756
771
|
f"https://{host}/api/communities", headers=headers, params=params
|
@@ -765,18 +780,5 @@ def search_by_slug(slug: str, type_value: str, host: str, token: str) -> Optiona
|
|
765
780
|
return None
|
766
781
|
|
767
782
|
|
768
|
-
def string_to_slug(text):
|
769
|
-
"""makes a string lowercase and removes non-alphanumeric characters"""
|
770
|
-
# Replace spaces with hyphens
|
771
|
-
slug = re.sub(r"\s+", "-", text.lower())
|
772
|
-
# Remove special characters
|
773
|
-
slug = re.sub(r"[^a-z0-9-]", "", slug)
|
774
|
-
# Remove multiple consecutive hyphens
|
775
|
-
slug = re.sub(r"-+", "-", slug)
|
776
|
-
# Remove leading and trailing hyphens
|
777
|
-
slug = slug.strip("-")
|
778
|
-
return slug
|
779
|
-
|
780
|
-
|
781
783
|
class InvenioRDMError(Exception):
|
782
784
|
"""Custom exception for InvenioRDM API errors"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: commonmeta-py
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.128
|
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
|
@@ -1,4 +1,4 @@
|
|
1
|
-
commonmeta/__init__.py,sha256=
|
1
|
+
commonmeta/__init__.py,sha256=xyW49190_8VsMvwhkGXYHBt4mg3KIclELe5Le3a1Ubs,2118
|
2
2
|
commonmeta/api_utils.py,sha256=P8LMHHYiF4OTi97_5k4KstcBreooMkOAKZ4ebxsAv4o,2691
|
3
3
|
commonmeta/author_utils.py,sha256=3lYW5s1rOUWNTKs1FP6XLfEUY3yCLOe_3L_VdJTDMp0,8585
|
4
4
|
commonmeta/base_utils.py,sha256=-MGy9q2uTiJEkPWQUYOJMdq-3tRpNnvBwlLjvllQ5g8,11164
|
@@ -10,7 +10,7 @@ commonmeta/file_utils.py,sha256=eFYDWyR8Gr722nvFmp542hCm-TGmO_q4ciZ85IPHpjA,2893
|
|
10
10
|
commonmeta/metadata.py,sha256=90aTe47d071wHxwcNsOqU5lSVPKP8wAPnPHhddj3Fuo,18443
|
11
11
|
commonmeta/schema_utils.py,sha256=zn3gqAHciUOQmrw9okR68weFs-yqPPyORFt-Zl1D3Lw,1924
|
12
12
|
commonmeta/translators.py,sha256=CBMK4jrXRmGZiAhCh6wsJjhbDJWbcsda8UvXFXxccAw,1363
|
13
|
-
commonmeta/utils.py,sha256=
|
13
|
+
commonmeta/utils.py,sha256=1Q6vh1mhQRTcPsEEymAPPJxBgDfNOR1ZXF_UaaW9ZoM,53612
|
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=HMFK6QIg_XIlhmYIWL4EfIyuidYl5L_0TAwyG78XPlU,6244
|
@@ -80,11 +80,11 @@ commonmeta/writers/commonmeta_writer.py,sha256=QpfyhG__7o_XpsOTCPWxGymO7YKwZi2LQ
|
|
80
80
|
commonmeta/writers/crossref_xml_writer.py,sha256=rcPOfrGxU4mX7_fFywYWDW2FFUoKW9wD-JzW8nX1ipI,33915
|
81
81
|
commonmeta/writers/csl_writer.py,sha256=4gDYs1EzK4_L2UIRTfs25wgHmYRwdRP2zmfxF9387oU,2779
|
82
82
|
commonmeta/writers/datacite_writer.py,sha256=bcinpwhq7XnVthKHH8-sdXA34dSlvFH4ImYH768iaQU,6428
|
83
|
-
commonmeta/writers/inveniordm_writer.py,sha256=
|
83
|
+
commonmeta/writers/inveniordm_writer.py,sha256=tiuq9JEkz02l615yVe9wUcJQqiIPJLUqNDyofEE8Aus,26726
|
84
84
|
commonmeta/writers/ris_writer.py,sha256=3SdyEvMRaPRP1SV1MB-MXBlunE7x6og7RF1zuWtetPc,2094
|
85
85
|
commonmeta/writers/schema_org_writer.py,sha256=s18_x0ReXwAGBoEAwp2q-HCgFQ-h5qRg6JyAlqCoSFE,5871
|
86
|
-
commonmeta_py-0.
|
87
|
-
commonmeta_py-0.
|
88
|
-
commonmeta_py-0.
|
89
|
-
commonmeta_py-0.
|
90
|
-
commonmeta_py-0.
|
86
|
+
commonmeta_py-0.128.dist-info/METADATA,sha256=aggchv6KLQbyfB1-NnInl13Ly-PlxLeSI3kVk1usD5k,7656
|
87
|
+
commonmeta_py-0.128.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
88
|
+
commonmeta_py-0.128.dist-info/entry_points.txt,sha256=U4w4BoRuS3rN5t5Y-uYSyOeU5Lh_VRVMS9OIDzIgw4w,50
|
89
|
+
commonmeta_py-0.128.dist-info/licenses/LICENSE,sha256=wsIvxF9Q9GC9vA_s79zTWP3BkXJdfUNRmALlU8GbW1s,1074
|
90
|
+
commonmeta_py-0.128.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|