-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcli.py
131 lines (114 loc) · 5.54 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""Command line interface for WoTIS."""
import click
import logging
from pathlib import Path
import subprocess
import yaml
from linkml.generators.jsonschemagen import JsonSchemaGenerator
from linkml.generators.shaclgen import ShaclGenerator
from linkml.generators.owlgen import OwlSchemaGenerator
from linkml.generators.jsonldcontextgen import ContextGenerator
from linkml.generators.docgen import DocGenerator
from linkml.generators.linkmlgen import LinkmlGenerator
from linkml_runtime.utils.schemaview import SchemaView
from src.wotis import YAML_SCHEMA_PATH, GENS_PATH, GENERATORS, DOCDIR
from src.wotis.post_processors.jsonld_context_postprocessor import post_process_jsonld_context
input_option = click.option('-i', '--input_schema',
type=str,
show_default=True,
help="Path to the input schema specified as LinkML yaml.",
default=YAML_SCHEMA_PATH)
docs_option = click.option('-d',
'--generate_docs',
type=bool,
is_flag=True,
default=False,
show_default=True,
help="Boolean for local documentation generation.")
serve_docs_option = click.option('-s',
'--serve_docs',
type=bool,
is_flag=True,
default=False,
show_default=True,
help="Boolean for serving the generated documentation.")
def serve_documentation():
subprocess.run(['mkdocs', 'serve'], check=True)
def generate_documentation():
DOCDIR.mkdir(parents=True, exist_ok=True)
doc_generator = DocGenerator(YAML_SCHEMA_PATH, mergeimports=False)
doc_generator.serialize(directory=str(DOCDIR))
# Main generation function
def run_generator(schema_view, generator, output_dir):
if generator == 'jsonschema':
logging.info(f"Proceeding with LinkML to JSON Schema convertion")
json_schema_generator = JsonSchemaGenerator(schema_view.schema, mergeimports=True)
(output_dir / 'jsonschema.json').write_text(json_schema_generator.serialize())
elif generator == 'shacl':
logging.info(f"Proceeding with LinkML to SHACL convertion")
shacl_generator = ShaclGenerator(schema_view.schema, mergeimports=False, closed=True, suffix='Shape')
(output_dir / 'shapes.shacl.ttl').write_text(shacl_generator.serialize())
elif generator == 'owl':
logging.info(f"Proceeding with LinkML to OWL convertion")
owl_generator = OwlSchemaGenerator(schema_view.schema, )
(output_dir / 'ontology.owl.ttl').write_text(owl_generator.serialize())
elif generator == 'jsonldcontext':
logging.info(f"Proceeding with LinkML to JSON-LD Context convertion")
context_generator = ContextGenerator(schema_view.schema, mergeimports=True)
(output_dir / 'context.jsonld').write_text(post_process_jsonld_context(schema_view,
context_generator.serialize()))
elif generator == 'linkml':
linkml_generator = LinkmlGenerator(schema_view.schema, mergeimports=True, format='yaml', output='linkml.yaml')
(output_dir / 'linkml.yaml').write_text(linkml_generator.serialize())
else:
print(f"Unknown generator: {generator}")
@click.group()
@click.option("-v", "--verbose", count=True)
@click.option("-q", "--quiet")
def main(verbose: int, quiet: bool):
"""CLI for WOTIS (Web of Things Integrated Schemas) toolchain.
:param verbose: Verbosity while running.
:param quiet: Boolean to be quiet or verbose.
"""
logger = logging.getLogger()
if verbose >= 2:
logger.setLevel(level=logging.DEBUG)
elif verbose == 1:
logger.setLevel(level=logging.INFO)
else:
logger.setLevel(level=logging.WARNING)
if quiet:
logger.setLevel(level=logging.ERROR)
logger.info(f"Logger {logger.name} set to level {logger.level}")
@main.command()
@input_option
@docs_option
@serve_docs_option
def generate_wot_resources(input_schema: str, generate_docs: bool, serve_docs: bool):
"""
Generating WoT resources (RDF, JSON-LD Context, SHACL Shapes, and JSON Schema) from manually constructed
LinkML-based schemas.
"""
if input_schema and not Path(input_schema).exists():
raise FileNotFoundError(f"Cannot find input LinkML schema file {input_schema}.")
elif not input_schema and not YAML_SCHEMA_PATH.exists():
raise FileNotFoundError(f"Cannot find the default LinkML schema file {YAML_SCHEMA_PATH}.")
else:
try:
linkml_schema_view = SchemaView(input_schema, merge_imports=True)
logging.info(f"Input schema {input_schema} loaded successfully!")
for generator in GENERATORS:
output_dir = GENS_PATH / generator
output_dir.mkdir(parents=True, exist_ok=True)
logging.info(f"Proceeding with WoT resource generation")
run_generator(linkml_schema_view, generator, output_dir)
except yaml.YAMLError as e:
logging.info(f"LinkML schema validation failed: {e}")
if generate_docs:
logging.info(f"Generating documentation locally as markdown files...")
generate_documentation()
if serve_docs:
logging.info(f"Serving documentation...")
serve_documentation()
if __name__ == "__main__":
main()