Coverage for src/metador_core/schema/common/rocrate.py: 82%

66 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-08-08 10:29 +0000

1"""RO Crate compatible Metadata. 

2 

3Here we do impose certain constraints (make fields mandatory). 

4 

5See https://www.researchobject.org/ro-crate/1.1/ 

6""" 

7from __future__ import annotations 

8 

9from typing import Set 

10 

11from pydantic import parse_obj_as, root_validator, validator 

12 

13from ..decorators import make_mandatory 

14from ..ld import LDIdRef, ld_decorator 

15from ..types import MimeTypeStr, NonEmptyStr 

16from . import schemaorg 

17 

18CTX_URL_ROCRATE = "https://w3id.org/ro/crate/1.1/context" 

19 

20 

21rocrate = ld_decorator(context=CTX_URL_ROCRATE) 

22 

23 

24@make_mandatory("contentSize", "sha256") 

25@rocrate(type="File") 

26class FileMeta(schemaorg.MediaObject): 

27 class Plugin: 

28 name = "core.file" 

29 version = (0, 1, 0) 

30 

31 # NOTE: We do not use `name` here because `name` is used semantically 

32 # like a title in schema.org, which could also make sense for a file to have. 

33 filename: NonEmptyStr 

34 """Original name of the file in source directory.""" 

35 

36 encodingFormat: MimeTypeStr 

37 """MIME type of the file.""" 

38 

39 

40@rocrate(type="Dataset") 

41class DirMeta(schemaorg.Dataset): 

42 class Plugin: 

43 name = "core.dir" 

44 version = (0, 1, 0) 

45 

46 hasPart: Set[LDIdRef] = set() 

47 """References to (a subset of) contained files and subdirectories.""" 

48 

49 

50@rocrate(type="Organization") 

51class Organization(schemaorg.Organization): 

52 @validator("id_") 

53 def check_id(cls, v): 

54 if not v: 

55 return None 

56 if not v.startswith("https://ror.org/"): 

57 raise ValueError("Person @id must be a valid ROR URL!") 

58 return parse_obj_as(schemaorg.URL, v) 

59 

60 

61@rocrate(type="Person") 

62class Person(schemaorg.Person): 

63 @validator("id_") 

64 def check_id(cls, v): 

65 if not v: 

66 return None 

67 if not v.startswith("https://orcid.org/"): 

68 raise ValueError("Person @id must be a valid ORCID URL!") 

69 return parse_obj_as(schemaorg.URL, v) 

70 

71 @root_validator(pre=True) 

72 def check_name(cls, values): 

73 has_given_or_additional = values.get("givenName") or values.get( 

74 "additionalName" 

75 ) 

76 if has_given_or_additional and not values.get("familyName"): 

77 msg = "givenName and additionalName require also familyName to be provided!" 

78 raise ValueError(msg) 

79 return values 

80 

81 @root_validator 

82 def ensure_name(cls, values): 

83 missing_name = values.get("name") is None 

84 if missing_name: 

85 parts = [] 

86 for k in ["givenName", "additionalName", "familyName"]: 

87 if v := values.get(k): 

88 parts.append(v) 

89 fullname = " ".join(parts) 

90 if not fullname: 

91 msg = "A Person must have name or familyName set!" 

92 raise ValueError(msg) 

93 values["name"] = fullname 

94 return values 

95 

96 

97# required self-description of RO-Crate file 

98rocrate_self_meta = { 

99 "@type": "CreativeWork", 

100 "@id": "ro-crate-metadata.json", 

101 "conformsTo": {"@id": "https://w3id.org/ro/crate/1.1"}, 

102 "about": {"@id": "./"}, 

103}