Validate the codemeta.json file against the codemeta.jsonld schema.
Parameters:
| Name |
Type |
Description |
Default |
codemeta
|
dict
|
codemeta.json file as a dictionary.
|
required
|
Returns:
| Name | Type |
Description |
invalid_fields |
list
|
|
Source code in src/somesy/codemeta/utils.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 | def validate_codemeta(codemeta: dict) -> list:
"""Validate the codemeta.json file against the codemeta.jsonld schema.
Args:
codemeta (dict): codemeta.json file as a dictionary.
Returns:
invalid_fields (list): List of invalid fields.
"""
schema_path = Path(__file__).parent / "schema-3.jsonld"
invalid_fields = []
# Check for required fields
required_fields = {"@context", "@type", "name"}
missing_fields = [field for field in required_fields if field not in codemeta]
if missing_fields:
invalid_fields.extend(missing_fields)
# Validate @context
codemeta_context = codemeta.get("@context", [])
if isinstance(codemeta_context, str):
codemeta_context = [codemeta_context]
if V3_CONTEXT not in codemeta_context:
invalid_fields.append("@context")
logger.warning(
"The @context field in codemeta.json does not contain the Codemeta v3.1 context."
)
try:
# Load Codemeta JSON-LD Schema
with open(schema_path, "r", encoding="utf-8") as f:
schema = json.load(f)
# Use schema's context to avoid network fetch issues
schema_context = schema["@context"]
codemeta_copy = copy.deepcopy(codemeta)
codemeta_copy["@context"] = schema_context
# Expand and compact to validate terms
expanded = jsonld.expand(codemeta_copy)
compacted = jsonld.compact(expanded, schema_context)
if not isinstance(compacted, dict):
raise TypeError("Codemeta compaction did not produce an object")
# Check for unmapped prefixes while allowing prefixes declared by CodeMeta.
compacted_keys = set(compacted)
for key in compacted_keys:
if ":" in key and key.split(":", 1)[0] not in schema_context:
logger.error(f"Invalid schema reference found: {key}")
invalid_fields.append(key)
# Check for unsupported terms by comparing original and compacted keys.
# Only top-level keys are checked on purpose: nested objects may use any
# valid schema.org term, which the CodeMeta context does not list, so
# recursing would report false positives.
original_keys = set(codemeta.keys())
compacted_keys = set(compacted)
# Remove @type from comparison as it might be handled differently in compaction
original_keys.discard("@type")
if "@type" in compacted_keys:
compacted_keys.remove("@type")
unsupported_terms = original_keys - compacted_keys
if unsupported_terms:
logger.warning(f"Unsupported terms found: {sorted(unsupported_terms)}")
invalid_fields.extend(unsupported_terms)
except Exception as e: # noqa: BLE001 - validation must report all JSON-LD failures
logger.error(f"Codemeta validation failed: {e}")
return ["Validation error"]
return list(set(invalid_fields)) # Remove duplicates
|