Skip to content

Commit 9f6ffee

Browse files
authored
templated all SchemaDefinition slots including settings (#122)
* tempalted all SchemaDefinition slots... except settings * handles schema Settings * add slot class assignments
1 parent 51a2845 commit 9f6ffee

File tree

13 files changed

+218
-19
lines changed

13 files changed

+218
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.DS_Store
2+
target
23

34
examples/output
45

schemasheets/schemamaker.py

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
from linkml_runtime.dumpers import yaml_dumper
1616
from linkml_runtime.linkml_model import Annotation, Example
1717
from linkml_runtime.linkml_model.meta import SchemaDefinition, ClassDefinition, Prefix, \
18-
SlotDefinition, EnumDefinition, PermissibleValue, SubsetDefinition, TypeDefinition, Element
18+
SlotDefinition, EnumDefinition, PermissibleValue, SubsetDefinition, TypeDefinition, Element, Setting
1919
from linkml_runtime.utils.schema_as_dict import schema_as_dict
2020
from linkml_runtime.utils.schemaview import SchemaView, re
2121

2222
from schemasheets.schemasheet_datamodel import ColumnConfig, TableConfig, get_configmodel, get_metamodel, COL_NAME, \
2323
DESCRIPTOR, \
24-
tmap, T_CLASS, T_PV, T_SLOT, T_SUBSET, T_SCHEMA, T_ENUM, T_PREFIX, T_TYPE, SchemaSheet
24+
tmap, T_CLASS, T_PV, T_SLOT, T_SUBSET, T_SCHEMA, T_ENUM, T_PREFIX, T_TYPE, SchemaSheet, T_SETTING
2525
from schemasheets.conf.configschema import Cardinality
2626
from schemasheets.utils.google_sheets import gsheets_download_url
2727
from schemasheets.utils.prefixtool import guess_prefix_expansion
@@ -83,7 +83,6 @@ def _tidy_slot_usage(self):
8383
c.slots.remove(sn)
8484
del c.slot_usage[sn]
8585

86-
8786
def merge_sheet(self, file_name: str, delimiter='\t') -> None:
8887
"""
8988
Merge information from the given schema sheet into the current schema
@@ -93,15 +92,15 @@ def merge_sheet(self, file_name: str, delimiter='\t') -> None:
9392
:return:
9493
"""
9594
logging.info(f'READING {file_name} D={delimiter}')
96-
#with self.ensure_file(file_name) as tsv_file:
95+
# with self.ensure_file(file_name) as tsv_file:
9796
# reader = csv.DictReader(tsv_file, delimiter=delimiter)
9897
with self.ensure_csvreader(file_name, delimiter=delimiter) as reader:
9998
schemasheet = SchemaSheet.from_dictreader(reader)
10099
if self.table_config_path:
101100
schemasheet.load_table_config(self.table_config_path)
102101
line_num = schemasheet.start_line_number
103102
# TODO: check why this doesn't work
104-
#while rows and all(x for x in rows[-1] if not x):
103+
# while rows and all(x for x in rows[-1] if not x):
105104
# print(f'TRIMMING: {rows[-1]}')
106105
# rows.pop()
107106
logging.info(f'ROWS={len(schemasheet.rows)}')
@@ -118,21 +117,29 @@ def add_row(self, row: Dict[str, Any], table_config: TableConfig):
118117
name = element.prefix_prefix
119118
elif isinstance(element, PermissibleValue):
120119
name = element.text
120+
elif isinstance(element, Setting):
121+
# print(f"\n{element = }")
122+
name = element.setting_key
121123
else:
122124
logging.debug(f'EL={element} in {row}')
123125
name = element.name
124126
logging.debug(f'ADDING: {row} // {name}')
125127
for k, v in row.items():
128+
# print(f"\n{k = }")
126129
if k not in table_config.columns:
127130
raise ValueError(f'Expected to find {k} in {table_config.columns.keys()}')
128131
cc = table_config.columns[k]
132+
# print(f"{cc = }")
129133
v = self.normalize_value(v, cc)
130134
if v:
135+
# print(f"{v = }")
131136
# special case: class-context provided by settings
132137
if cc.settings.applies_to_class:
133138
actual_element = list(self.row_focal_element(row, table_config, column=k))[0]
134139
else:
135140
actual_element = element
141+
# print(f"{cc.maps_to = }")
142+
# print(f"{cc = }")
136143
logging.debug(f'SETTING {name} {cc.maps_to} = {v}')
137144
if cc.maps_to == 'cardinality':
138145
self.set_cardinality(actual_element, v)
@@ -172,9 +179,13 @@ def add_row(self, row: Dict[str, Any], table_config: TableConfig):
172179
curr_val = getattr(curr_obj, cc.settings.inner_key, None)
173180
else:
174181
curr_val = getattr(actual_element, cc.maps_to)
182+
# print(f"{curr_val = }")
183+
# print(f"{v = }")
184+
175185
if curr_val and curr_val != 'TEMP' and curr_val != v and \
176186
not isinstance(actual_element, SchemaDefinition) and \
177-
not isinstance(actual_element, Prefix):
187+
not isinstance(actual_element, Prefix) and \
188+
not isinstance(actual_element, Setting):
178189
logging.warning(f'Overwriting value for {k}, was {curr_val}, now {v}')
179190
raise ValueError(f'Cannot reset value for {k}, was {curr_val}, now {v}')
180191
if cc.settings.inner_key:
@@ -288,17 +299,25 @@ def row_focal_element(self, row: Dict[str, Any], table_config: TableConfig,
288299
pfx = Prefix(vs[0], 'TODO')
289300
self.schema.prefixes[pfx.prefix_prefix] = pfx
290301
vmap[k] = [pfx]
302+
elif elt_cls == Setting:
303+
if len(vs) != 1:
304+
raise ValueError(f'Cardinality of setting col must be 1; got: {vs}')
305+
stg = Setting(vs[0], 'TODO')
306+
self.schema.settings[stg.setting_key] = stg
307+
vmap[k] = [stg]
291308
elif elt_cls == SchemaDefinition:
292309
if len(vs) != 1:
293310
raise ValueError(f'Cardinality of schema col must be 1; got: {vs}')
294311
self.schema.name = vs[0]
295312
vmap[k] = [self.schema]
296313
else:
297314
vmap[k] = [self.get_current_element(elt_cls(v)) for v in vs]
315+
298316
def check_excess(descriptors):
299317
diff = set(vmap.keys()) - set(descriptors + [T_SCHEMA])
300318
if len(diff) > 0:
301319
raise ValueError(f'Excess slots: {diff}')
320+
302321
if column:
303322
cc = table_config.columns[column]
304323
if cc.settings.applies_to_class:
@@ -351,7 +370,7 @@ def check_excess(descriptors):
351370
this_enum: EnumDefinition = vmap[T_ENUM][0]
352371
if T_PV in vmap:
353372
for pv in vmap[T_PV]:
354-
#pv = PermissibleValue(text=v)
373+
# pv = PermissibleValue(text=v)
355374
this_enum.permissible_values[pv.text] = pv
356375
yield pv
357376
else:
@@ -368,6 +387,9 @@ def check_excess(descriptors):
368387
elif T_SCHEMA in vmap:
369388
for main_elt in vmap[T_SCHEMA]:
370389
yield main_elt
390+
elif T_SETTING in vmap:
391+
for main_elt in vmap[T_SETTING]:
392+
yield main_elt
371393
else:
372394
raise ValueError(f'Could not find a focal element for {row}')
373395

@@ -419,7 +441,8 @@ def normalize_value(self, v: str, column_config: ColumnConfig = None) -> Any:
419441
v = None
420442
if column_config.settings.curie_prefix:
421443
if ':' in v:
422-
logging.warning(f'Will not prefix {v} with {column_config.settings.curie_prefix} as it is already prefixed')
444+
logging.warning(
445+
f'Will not prefix {v} with {column_config.settings.curie_prefix} as it is already prefixed')
423446
else:
424447
v = f'{column_config.settings.curie_prefix}:{v}'
425448
if column_config.settings.prefix:
@@ -537,8 +560,8 @@ def repair_schema(self, schema: SchemaDefinition) -> SchemaDefinition:
537560
:return:
538561
"""
539562
sv = SchemaView(schema)
540-
#pfx = schema.default_prefix
541-
#if pfx not in schema.prefixes:
563+
# pfx = schema.default_prefix
564+
# if pfx not in schema.prefixes:
542565
# schema.prefixes[pfx] = Prefix(pfx, f'http://example.org/{pfx}/')
543566
# logging.info(f'Set default prefix: {schema.prefixes[pfx]}')
544567
prefixes = set()
@@ -622,7 +645,8 @@ def ensure_csvreader(self, file_name: str, delimiter=None) -> str:
622645
help="Google sheets ID. If this is specified then the arguments MUST be sheet names")
623646
@click.option("-v", "--verbose", count=True)
624647
@click.argument('tsv_files', nargs=-1)
625-
def convert(tsv_files, gsheet_id, output: TextIO, name, repair, table_config_path: str, use_attributes: bool, unique_slots: bool, verbose: int, sort_keys: bool):
648+
def convert(tsv_files, gsheet_id, output: TextIO, name, repair, table_config_path: str, use_attributes: bool,
649+
unique_slots: bool, verbose: int, sort_keys: bool):
626650
"""
627651
Convert schemasheets to a LinkML schema
628652
@@ -653,14 +677,8 @@ def convert(tsv_files, gsheet_id, output: TextIO, name, repair, table_config_pat
653677
schema = sm.repair_schema(schema)
654678
schema_dict = schema_as_dict(schema)
655679
output.write(yaml.dump(schema_dict, sort_keys=sort_keys))
656-
#output.write(yaml_dumper.dumps(schema))
680+
# output.write(yaml_dumper.dumps(schema))
657681

658682

659683
if __name__ == '__main__':
660684
convert()
661-
662-
663-
664-
665-
666-

schemasheets/schemasheet_datamodel.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import yaml
99
from linkml_runtime.linkml_model import SlotDefinition, ClassDefinition, SchemaDefinition, \
1010
PermissibleValue, EnumDefinition, TypeDefinition, SubsetDefinition, Prefix
11+
from linkml_runtime.linkml_model.meta import Setting
12+
1113
from linkml_runtime.utils.schemaview import SchemaView
1214

1315
from schemasheets.conf.configschema import ColumnSettings, Shortcuts
@@ -26,6 +28,7 @@
2628
T_TYPE = 'type'
2729
T_SUBSET = 'subset'
2830
T_PREFIX = 'prefix'
31+
T_SETTING = 'setting'
2932

3033
tmap = {
3134
T_SCHEMA: SchemaDefinition,
@@ -35,7 +38,8 @@
3538
T_PV: PermissibleValue,
3639
T_TYPE: TypeDefinition,
3740
T_SUBSET: SubsetDefinition,
38-
T_PREFIX: Prefix
41+
T_PREFIX: Prefix,
42+
T_SETTING: Setting,
3943
}
4044

4145

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class description
2+
>class description
3+
Vehicle A machine, with or wihtout its own power source, that eases the transportation of people, materials, etc.
4+
Airplane "A vehicle which flies through the air, obtaining lif from air flowing acoss fixed wings"
5+
Boat A vehicle which moves through water
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
prefix URI
2+
> prefix prefix_reference
3+
some_schema http://example.com/some_schema_path/
4+
data_prefix_1 http://example.com/data_prefix_1/
5+
data_prefix_2 http://example.com/data_prefix_2/
6+
non_data_prefix http://example.com/non_data_prefix/
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
id schema name aliases broad_mappings categories close_mappings comments conforms_to contributors created_by created_on date default_prefix default_range deprecated deprecated_element_has_exact_replacement deprecated_element_has_possible_replacement description exact_mappings implements imports in_language instantiates last_updated_on dat license mappings modified_by narrow_mappings notes rank related_mappings see_also slot_names_unique source status title todos version alt_description_source alt_description_text flavor annotation local name source local name value structured_aliases literal_form structured_aliases alias_predicate structured_aliases categories in subset id_prefixes emit_prefixes default_curi_maps
2+
>id schema aliases broad_mappings categories close_mappings comments conforms_to contributors created_by ignore default_prefix default_range deprecated deprecated_element_has_exact_replacement deprecated_element_has_possible_replacement description exact_mappings implements ignore in_language ignore ignore license mappings modified_by narrow_mappings notes rank related_mappings see_also slot_names_unique source status title todos version alt_descriptions alt_descriptions annotations local_names local_names structured_aliases structured_aliases structured_aliases in_subset id_prefixes emit_prefixes default_curi_maps
3+
> internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|' internal_separator: '|'
4+
> inner_key: source inner_key: text inner_key: flavor inner_key: source inner_key: value inner_key: literal_form inner_key: alias_predicate inner_key: categories ""
5+
http://example.com/some_schema some schema text1|text2 some_schema:1|some_schema:2 some_schema:1|some_schema:2 some_schema:1|some_schema:2 the overall usefulness of default_curi_maps is debatable|there may be some improper modeling in here like illegal ranges. what software will detect that?|what about numeric, date and booleans that get converted to strings?|what are implements and instantiates good for?|how well does including an imports statement in a schemsheets TSV work?|todo what about multivalued slots with multiple inner keys?|what does the schema repair method do? LinkML some_schema:1|some_schema:2 some_schema:1 some_schema float we all feel deprecated some times some_schema:1 some_schema:1 A schema that tests as many elements as possible. For use in testing YAML <-> sheets some_schema:1|some_schema:2 some_schema:1|some_schema:2 some_schema:1|some_schema:2 English some_schema:1|some_schema:2 MIT some_schema:1|some_schema:2 some_schema:1 some_schema:1|some_schema:2 text1|text2 3 some_schema:1|some_schema:2 some_schema:1|some_schema:2 TRUE some_schema:1 some_schema:1 See description SETTINGS! v0.0.1 wiktionary "An outline or image universally applicable to a general conception, under which it is likely to be presented to the mind" raspberry logic format schema_definition EXACT_SYNONYM some_schema:1|some_schema:2 main_subset|secret_subset data_prefix_1|data_prefix_2 data_prefix_1|data_prefix_2|non_data_prefix semweb_context|idot_context
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
setting name setting expansion
2+
>setting setting_value
3+
vowels [aeiouAEIOU]+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
setting name setting expansion
2+
>setting setting_value
3+
vowels [aeiouAEIOU]+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class slot
2+
>class slot
3+
Vehicle exterior_color
4+
Vehicle max_passengers

tests/test_121/input/slot_defs.tsv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
slot description
2+
>slot description
3+
exterior_color the primary color, using crayola names, of the exterior of the vehicle
4+
max_passengers That maximum number of human passengers that can be safely transported by the vehicle

0 commit comments

Comments
 (0)