Skip to content

Commit b02760e

Browse files
authored
Merge pull request #15 from linkml/issue-14
issue 14
2 parents 6c3b38d + 03b58b5 commit b02760e

File tree

6 files changed

+53
-24
lines changed

6 files changed

+53
-24
lines changed

schemasheets/conf/configschema.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Auto generated from configschema.yaml by pythongen.py version: 0.9.0
2-
# Generation date: 2022-01-03T11:25:54
2+
# Generation date: 2022-02-02T11:11:10
33
# Schema: configschema
44
#
55
# id: https://w3id.org/linkml/configschema
@@ -70,6 +70,7 @@ class ColumnSettings(YAMLRoot):
7070
suffix: Optional[str] = None
7171
template: Optional[str] = None
7272
vmap: Optional[Union[Dict[Union[str, ValueMapMapKey], Union[dict, "ValueMap"]], List[Union[dict, "ValueMap"]]]] = empty_dict()
73+
inner_key: Optional[str] = None
7374
applies_to_class: Optional[str] = None
7475
applies_to_slot: Optional[str] = None
7576
tag: Optional[str] = None
@@ -89,6 +90,9 @@ def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
8990

9091
self._normalize_inlined_as_dict(slot_name="vmap", slot_type=ValueMap, key_name="map_key", keyed=True)
9192

93+
if self.inner_key is not None and not isinstance(self.inner_key, str):
94+
self.inner_key = str(self.inner_key)
95+
9296
if self.applies_to_class is not None and not isinstance(self.applies_to_class, str):
9397
self.applies_to_class = str(self.applies_to_class)
9498

@@ -225,6 +229,9 @@ class slots:
225229
slots.columnSettings__vmap = Slot(uri=THIS.vmap, name="columnSettings__vmap", curie=THIS.curie('vmap'),
226230
model_uri=THIS.columnSettings__vmap, domain=None, range=Optional[Union[Dict[Union[str, ValueMapMapKey], Union[dict, ValueMap]], List[Union[dict, ValueMap]]]])
227231

232+
slots.columnSettings__inner_key = Slot(uri=THIS.inner_key, name="columnSettings__inner_key", curie=THIS.curie('inner_key'),
233+
model_uri=THIS.columnSettings__inner_key, domain=None, range=Optional[str])
234+
228235
slots.columnSettings__applies_to_class = Slot(uri=THIS.applies_to_class, name="columnSettings__applies_to_class", curie=THIS.curie('applies_to_class'),
229236
model_uri=THIS.columnSettings__applies_to_class, domain=None, range=Optional[str])
230237

schemasheets/conf/configschema.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ classes:
5454
range: ValueMap
5555
multivalued: true
5656
inlined: true
57+
inner_key:
58+
range: string
59+
description: |-
60+
for complex fields such as annotations that are modeled as dicts, this is used to specify which key in the dict the value should be applied to
5761
applies_to_class:
5862
description: |-
5963
if a value C is specified, then this column in the relevant row is interpreted as

schemasheets/schemamaker.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
SlotDefinition, EnumDefinition, PermissibleValue, SubsetDefinition, TypeDefinition, Element
1717
from linkml_runtime.utils.schemaview import SchemaView
1818

19-
from schemasheets.utils.configschema import ColumnSettings, Shortcuts, Cardinality
19+
from schemasheets.conf.configschema import ColumnSettings, Shortcuts, Cardinality
2020
from schemasheets.utils.prefixtool import guess_prefix_expansion
2121

2222

@@ -245,9 +245,7 @@ def merge_sheet(self, file_name: str, delimiter='\t') -> None:
245245
if v is not None and v.startswith('>'):
246246
v = v.replace('>', '')
247247
if v:
248-
#print(f'PARSING: {v}')
249248
meta_obj = yaml.safe_load(v)
250-
#print(f'PARSING: {v} => {meta_obj}')
251249
table_config.add_info(k, meta_obj)
252250
else:
253251
logging.debug(f'Empty val {v} for {k} in {row}')
@@ -286,16 +284,31 @@ def add_row(self, row: Dict[str, Any], table_config: TableConfig):
286284
if cc.maps_to == 'cardinality':
287285
self.set_cardinality(actual_element, v)
288286
elif cc.metaslot:
289-
if isinstance(v, list):
287+
if cc.maps_to == 'annotations' and not cc.settings.inner_key:
288+
anns = yaml.load(v[0])
289+
for ann_key, ann_val in anns.items():
290+
actual_element.annotations[ann_key] = ann_val
291+
elif isinstance(v, list):
292+
#print(f'SETTING {k} to {v}')
290293
setattr(actual_element, cc.maps_to, getattr(actual_element, cc.maps_to, []) + v)
294+
elif isinstance(v, dict):
295+
for v_k, v_v in v.items():
296+
curr_dict = getattr(actual_element, cc.maps_to)
297+
curr_dict[v_k] = v_v
291298
else:
292-
curr_val = getattr(actual_element, cc.maps_to)
299+
if cc.settings.inner_key:
300+
curr_val = getattr(actual_element, cc.maps_to).get(cc.settings.inner_key, None)
301+
else:
302+
curr_val = getattr(actual_element, cc.maps_to)
293303
if curr_val and curr_val != 'TEMP' and curr_val != v and \
294304
not isinstance(actual_element, SchemaDefinition) and \
295305
not isinstance(actual_element, Prefix):
296306
logging.warning(f'Overwriting value for {k}, was {curr_val}, now {v}')
297307
raise ValueError(f'Cannot reset value for {k}, was {curr_val}, now {v}')
298-
setattr(actual_element, cc.maps_to, v)
308+
if cc.settings.inner_key:
309+
getattr(actual_element, cc.maps_to)[cc.settings.inner_key] = v
310+
else:
311+
setattr(actual_element, cc.maps_to, v)
299312
elif cc.is_element_type:
300313
logging.debug(f'Already accounted for {k}')
301314
elif cc.maps_to == 'metatype':
@@ -493,7 +506,7 @@ def normalize_value(self, v: str, column_config: ColumnConfig = None) -> Any:
493506
v = bmap[v.lower()]
494507
else:
495508
v = bool(v)
496-
if metaslot and metaslot.multivalued:
509+
if metaslot and metaslot.multivalued and not column_config.settings.inner_key:
497510
if not isinstance(v, list):
498511
if v is None:
499512
v = []

tests/input/personinfo.tsv

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
record field key multiplicity range parents desc schema.org wikidata belongs status notes
2-
> class slot identifier cardinality range is_a description exact_mappings: {curie_prefix: sdo} exact_mappings: {curie_prefix: wikidata} in_subset status ignore
3-
> curie_prefix: wikidata vmap: {T: testing, R: release}
4-
id yes 1 string any identifier identifier
5-
description no 0..1 string a textual description description
6-
Person n/a n/a n/a a person,living or dead Person Q215627 R
7-
Person id yes 1 string identifier for a person identifier
8-
Person|Organization name no 1 string full name name
9-
Person age no 0..1 decimal age in years
10-
Person gender no 0..1 decimal age in years
11-
Person has medical history no 0..* MedicalEvent medical history T
12-
Event grouping class for events Q1656682 a R
13-
MedicalEvent n/a n/a n/a Event a medical encounter b T
14-
ForProfit Organization
15-
NonProfit Organization Q163740 foo
1+
record field key multiplicity range parents desc schema.org wikidata belongs status special special2 notes
2+
> class slot identifier cardinality range is_a description exact_mappings: {curie_prefix: sdo} exact_mappings: {curie_prefix: wikidata} in_subset status annotations annotations ignore
3+
> curie_prefix: wikidata vmap: {T: testing, R: release} inner_key: special inner_key: special2
4+
id yes 1 string any identifier identifier
5+
description no 0..1 string a textual description description my_val my_val2
6+
Person n/a n/a n/a a person,living or dead Person Q215627 R
7+
Person id yes 1 string identifier for a person identifier
8+
Person|Organization name no 1 string full name name my_val
9+
Person age no 0..1 decimal age in years
10+
Person gender no 0..1 decimal age in years
11+
Person has medical history no 0..* MedicalEvent medical history T
12+
Event grouping class for events Q1656682 a R
13+
MedicalEvent n/a n/a n/a Event a medical encounter b T
14+
ForProfit Organization
15+
NonProfit Organization Q163740 foo

tests/input/personinfo_with_types.tsv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ F age Person no 0..1 decimal age in years
99
F gender Person no 0..1 decimal age in years
1010
F has medical history Person no 0..* MedicalEvent medical history T
1111
C Person a person,living or dead Person Q215627 R
12-
C Event grouping class for events Q1656682 a R
12+
C Event grouping class for events Q1656682 a R
1313
C MedicalEvent Event a medical encounter b T
1414
C ForProfit Organization
1515
C NonProfit Organization Q163740 foo

tests/test_schemamaker.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ def test_classes_slots():
3737
assert person_cls.slot_usage['id'].identifier
3838
assert person_cls.slot_usage['has medical history'].multivalued
3939
assert person_cls.status == 'release'
40+
anns = schema.slots['description'].annotations
41+
assert anns
42+
assert anns['special']
43+
assert anns['special'] == 'my_val'
44+
assert anns['special2'] == 'my_val2'
4045
assert not person_cls.slot_usage['has medical history'].required
4146
assert person_cls.slot_usage['has medical history'].status == 'testing'
4247
assert 'name' in organization_cls.slots

0 commit comments

Comments
 (0)