From a09e1c7c6243d8619367e2746c5a39714b9769e7 Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 16:20:40 +0200 Subject: [PATCH 1/9] package initialization added --- src/__init__.py | 10 ++++++++++ src/cli.py | 0 src/data/examples/Thing-001.yaml | 7 ------- src/utils/jsonld-context-processing.py | 0 4 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/__init__.py create mode 100644 src/cli.py delete mode 100644 src/data/examples/Thing-001.yaml create mode 100644 src/utils/jsonld-context-processing.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..af1ef53 --- /dev/null +++ b/src/__init__.py @@ -0,0 +1,10 @@ +from pathlib import Path + + +RESOURCES_PATH = Path('resources') +GENS_PATH = RESOURCES_PATH / 'gens' +SCHEMA_PATH = RESOURCES_PATH / 'schemas' +YAML_SCHEMA_PATH = SCHEMA_PATH / 'thing_description.yaml' +DOCDIR = GENS_PATH / 'docs' / 'ontology' + +GENERATORS = ['jsonschema', 'shacl', 'jsonldcontext', 'linkml'] diff --git a/src/cli.py b/src/cli.py new file mode 100644 index 0000000..e69de29 diff --git a/src/data/examples/Thing-001.yaml b/src/data/examples/Thing-001.yaml deleted file mode 100644 index e904b23..0000000 --- a/src/data/examples/Thing-001.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# Example data object ---- -entries: - - id: example:Thing001 - name: foo bar - primary_email: foo.bar@example.com - age_in_years: 33 diff --git a/src/utils/jsonld-context-processing.py b/src/utils/jsonld-context-processing.py new file mode 100644 index 0000000..e69de29 From 1924c2e5f298d6223bd1d804edaa927388996261 Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 16:21:07 +0200 Subject: [PATCH 2/9] WoT toolchain CLI updated with click library --- src/cli.py | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/cli.py b/src/cli.py index e69de29..857d97f 100644 --- a/src/cli.py +++ b/src/cli.py @@ -0,0 +1,112 @@ +"""Command line interface for WoT toolchain.""" + +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 linkml_runtime.linkml_model.meta import AnonymousSlotExpression + +from src import YAML_SCHEMA_PATH, GENS_PATH, GENERATORS, DOCDIR + + +input_option = click.option('i', '--input_schema', help="Path to the input schema specified as LinkML yaml.", default=YAML_SCHEMA_PATH) +docs_option = click.option('-d', '--generate_docs', help="Boolean for local documentation generation.") +serve_docs_option = click.option('-s', '--serve_docs', help="Boolean for serving the generated documentation.") + + +# Documentation serving function +def serve_docs(): + subprocess.run(['mkdocs', 'serve'], check=True) + + +def generate_docs(): + 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): + logging.info(f"Input file directory") + if generator == 'jsonschema': + # json_schema_generator = JsonSchemaGenerator(yaml_content, top_class="Thing") + json_schema_generator = JsonSchemaGenerator(schema_view.schema, mergeimports=True) + (output_dir / 'jsonschema.json').write_text(json_schema_generator.serialize()) + elif generator == 'shacl': + 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': + owl_generator = OwlSchemaGenerator(schema_view.schema, ) + (output_dir / 'ontology.owl.ttl').write_text(owl_generator.serialize()) + elif generator == 'jsonldcontext': + context_generator = ContextGenerator(schema_view.schema, mergeimports=True) + # (output_dir / 'context.jsonld').write_text(post_process_jsonld_context(linkml_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 WoT 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, generate_docs, serve_docs): + """ + WoT TD toolchain CLI for automating WoT resources generation + """ + 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) + run_generator(linkml_schema_view, generator, output_dir) + except yaml.YAMLError as e: + logging.info(f"Error in LinkML schema validation: {e}") + if generate_docs: + generate_docs() + if serve_docs: + serve_docs() + + +if __name__ == "__main__": + main() From 025e4faf63ec9b6e64a9a0a0f3cc38b51ccf37bf Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 18:30:21 +0200 Subject: [PATCH 3/9] wotis package created --- pyproject.toml | 26 +++++++++++++------ src/__init__.py | 10 ------- .../__init__.py} | 0 src/{ => wotis}/cli.py | 13 +++++----- src/{ => wotis}/docs/about.md | 0 src/wotis/utils/__init__.py | 0 src/wotis/utils/jsonld-context-processing.py | 0 7 files changed, 25 insertions(+), 24 deletions(-) delete mode 100644 src/__init__.py rename src/{utils/jsonld-context-processing.py => wotis/__init__.py} (100%) rename src/{ => wotis}/cli.py (90%) rename src/{ => wotis}/docs/about.md (100%) create mode 100644 src/wotis/utils/__init__.py create mode 100644 src/wotis/utils/jsonld-context-processing.py diff --git a/pyproject.toml b/pyproject.toml index 70f0a21..3afe258 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,21 +1,25 @@ [project] -name = "thing_description_schema" +name = "wotis" version = "0.1.0" -description = "Thing Description Information Model as a LinkML schema" +description = "A CLI for Web of Things Integrated Schemas (WOTIS)" authors = [ - { name = "Mahda Noura", email = "mahdanoura@gmail.com" } + { name = "Mahda Noura", email = "mahda.noura@siemens.com" } ] license = "MIT" readme = "README.md" -include = ["README.md", "src/thing_description_schema/schema", "project"] - -requires-python = ">=3.12" +include = ["README.md", "resources/schemas/*"] +requires-python = ">=3.11" dependencies = [ "linkml-runtime>=1.8.2", "linkml>=1.8.2", "mkdocs-mermaid2-plugin>=1.1.1", "mkdocs-material>=9.5.32", - "schemasheets>=0.3.1", + "schemasheets>=0.3.1" +] + +[project.optional-dependencies] +cli = [ + "click>=8.1.7" ] [build-system] @@ -23,4 +27,10 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build] -only-include = ["main.py"] \ No newline at end of file +only-include = ["src/wotis/cli.py"] + +[tool.hatch.metadata] +root = "src" + +[project.scripts] +wotis = "src.wotis.cli:main" \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index af1ef53..0000000 --- a/src/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from pathlib import Path - - -RESOURCES_PATH = Path('resources') -GENS_PATH = RESOURCES_PATH / 'gens' -SCHEMA_PATH = RESOURCES_PATH / 'schemas' -YAML_SCHEMA_PATH = SCHEMA_PATH / 'thing_description.yaml' -DOCDIR = GENS_PATH / 'docs' / 'ontology' - -GENERATORS = ['jsonschema', 'shacl', 'jsonldcontext', 'linkml'] diff --git a/src/utils/jsonld-context-processing.py b/src/wotis/__init__.py similarity index 100% rename from src/utils/jsonld-context-processing.py rename to src/wotis/__init__.py diff --git a/src/cli.py b/src/wotis/cli.py similarity index 90% rename from src/cli.py rename to src/wotis/cli.py index 857d97f..81ad1a1 100644 --- a/src/cli.py +++ b/src/wotis/cli.py @@ -1,4 +1,4 @@ -"""Command line interface for WoT toolchain.""" +"""Command line interface for WoTIS.""" import click import logging @@ -13,7 +13,6 @@ from linkml.generators.docgen import DocGenerator from linkml.generators.linkmlgen import LinkmlGenerator from linkml_runtime.utils.schemaview import SchemaView -from linkml_runtime.linkml_model.meta import AnonymousSlotExpression from src import YAML_SCHEMA_PATH, GENS_PATH, GENERATORS, DOCDIR @@ -36,8 +35,8 @@ def generate_docs(): # Main generation function def run_generator(schema_view, generator, output_dir): - logging.info(f"Input file directory") if generator == 'jsonschema': + logging.info(f"JSON Schema generation") # json_schema_generator = JsonSchemaGenerator(yaml_content, top_class="Thing") json_schema_generator = JsonSchemaGenerator(schema_view.schema, mergeimports=True) (output_dir / 'jsonschema.json').write_text(json_schema_generator.serialize()) @@ -63,7 +62,7 @@ def run_generator(schema_view, generator, output_dir): @click.option("-v", "--verbose", count=True) @click.option("-q", "--quiet") def main(verbose: int, quiet: bool): - """CLI for WoT toolchain. + """CLI for WOTIS (Web of Things Integrated Schemas) toolchain. :param verbose: Verbosity while running. :param quiet: Boolean to be quiet or verbose. @@ -86,7 +85,8 @@ def main(verbose: int, quiet: bool): @serve_docs_option def generate_wot_resources(input_schema, generate_docs, serve_docs): """ - WoT TD toolchain CLI for automating WoT resources generation + Toolchain for 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}.") @@ -99,9 +99,10 @@ def generate_wot_resources(input_schema, generate_docs, serve_docs): 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"Error in LinkML schema validation: {e}") + logging.info(f"LinkML schema validation failed: {e}") if generate_docs: generate_docs() if serve_docs: diff --git a/src/docs/about.md b/src/wotis/docs/about.md similarity index 100% rename from src/docs/about.md rename to src/wotis/docs/about.md diff --git a/src/wotis/utils/__init__.py b/src/wotis/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/wotis/utils/jsonld-context-processing.py b/src/wotis/utils/jsonld-context-processing.py new file mode 100644 index 0000000..e69de29 From 5a86944b0b8119e7fb9a2935ab28723a95bdb1d9 Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 18:30:51 +0200 Subject: [PATCH 4/9] CLI interface changed to click and refractoring --- main.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 31027e5..ecb2d12 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,8 @@ import argparse +import click import json import subprocess +from pathlib import Path from linkml.generators.jsonschemagen import JsonSchemaGenerator from linkml.generators.shaclgen import ShaclGenerator @@ -10,10 +12,7 @@ from linkml.generators.linkmlgen import LinkmlGenerator from linkml_runtime.utils.schemaview import SchemaView from linkml_runtime.linkml_model.meta import AnonymousSlotExpression -from pathlib import Path -from pyld import jsonld -from linkml_runtime.linkml_model.meta import SlotDefinition RESOURCES_PATH = Path('resources') GENS_PATH = RESOURCES_PATH / 'gens' From 2f49283ad3f3ae35e83f2d1df802bbc7b12a2b4d Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 18:31:22 +0200 Subject: [PATCH 5/9] CLI interface changed to click and refractoring --- src/wotis/cli.py | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/wotis/cli.py b/src/wotis/cli.py index 81ad1a1..27734a0 100644 --- a/src/wotis/cli.py +++ b/src/wotis/cli.py @@ -14,20 +14,36 @@ from linkml.generators.linkmlgen import LinkmlGenerator from linkml_runtime.utils.schemaview import SchemaView -from src import YAML_SCHEMA_PATH, GENS_PATH, GENERATORS, DOCDIR - - -input_option = click.option('i', '--input_schema', help="Path to the input schema specified as LinkML yaml.", default=YAML_SCHEMA_PATH) -docs_option = click.option('-d', '--generate_docs', help="Boolean for local documentation generation.") -serve_docs_option = click.option('-s', '--serve_docs', help="Boolean for serving the generated documentation.") +from src.wotis import YAML_SCHEMA_PATH, GENS_PATH, GENERATORS, DOCDIR + + +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.") # Documentation serving function -def serve_docs(): +def serve_documentation(): subprocess.run(['mkdocs', 'serve'], check=True) -def generate_docs(): +def generate_documentation(): DOCDIR.mkdir(parents=True, exist_ok=True) doc_generator = DocGenerator(YAML_SCHEMA_PATH, mergeimports=False) doc_generator.serialize(directory=str(DOCDIR)) @@ -37,7 +53,6 @@ def generate_docs(): def run_generator(schema_view, generator, output_dir): if generator == 'jsonschema': logging.info(f"JSON Schema generation") - # json_schema_generator = JsonSchemaGenerator(yaml_content, top_class="Thing") json_schema_generator = JsonSchemaGenerator(schema_view.schema, mergeimports=True) (output_dir / 'jsonschema.json').write_text(json_schema_generator.serialize()) elif generator == 'shacl': @@ -83,10 +98,10 @@ def main(verbose: int, quiet: bool): @input_option @docs_option @serve_docs_option -def generate_wot_resources(input_schema, generate_docs, serve_docs): +def generate_wot_resources(input_schema: str, generate_docs: bool, serve_docs: bool): """ - Toolchain for generating WoT resources (RDF, JSON-LD Context, SHACL Shapes, and JSON Schema) from manually - constructed LinkML-based schemas. + 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}.") @@ -104,9 +119,11 @@ def generate_wot_resources(input_schema, generate_docs, serve_docs): except yaml.YAMLError as e: logging.info(f"LinkML schema validation failed: {e}") if generate_docs: - generate_docs() + logging.info(f"Generating documentation locally as markdown files...") + generate_documentation() if serve_docs: - serve_docs() + logging.info(f"GServing documentation...") + serve_documentation() if __name__ == "__main__": From af886e4b264afe7c64b8fb168a0e74dc8e299594 Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 18:31:44 +0200 Subject: [PATCH 6/9] configs added to initiation --- src/wotis/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/wotis/__init__.py b/src/wotis/__init__.py index e69de29..a430a5e 100644 --- a/src/wotis/__init__.py +++ b/src/wotis/__init__.py @@ -0,0 +1,10 @@ +from pathlib import Path + + +RESOURCES_PATH = Path('resources') +GENS_PATH = RESOURCES_PATH / 'gens' +SCHEMA_PATH = RESOURCES_PATH / 'schemas' +YAML_SCHEMA_PATH = SCHEMA_PATH / 'thing_description.yaml' +DOCDIR = GENS_PATH / 'docs' / 'ontology' + +GENERATORS = ['jsonschema', 'shacl', 'jsonldcontext', 'linkml'] \ No newline at end of file From b71f78ea48363d9fe5976c33a774c4ae4c94cdac Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 20:01:47 +0200 Subject: [PATCH 7/9] gitattributes added --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fb3ee9f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.html linguist-detectable=false \ No newline at end of file From f3658bc5e20cede7244b00c767824d2315c41897 Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 21:08:29 +0200 Subject: [PATCH 8/9] json-ld context postprocessing refractored --- src/{wotis/utils => }/__init__.py | 0 .../__init__.py} | 0 .../json_schema_postprocessor.py | 0 .../jsonld_context_postprocessor.py | 93 +++++++++++++++++++ .../post_processors/shacl_postprocessor.py | 0 5 files changed, 93 insertions(+) rename src/{wotis/utils => }/__init__.py (100%) rename src/wotis/{utils/jsonld-context-processing.py => post_processors/__init__.py} (100%) create mode 100644 src/wotis/post_processors/json_schema_postprocessor.py create mode 100644 src/wotis/post_processors/jsonld_context_postprocessor.py create mode 100644 src/wotis/post_processors/shacl_postprocessor.py diff --git a/src/wotis/utils/__init__.py b/src/__init__.py similarity index 100% rename from src/wotis/utils/__init__.py rename to src/__init__.py diff --git a/src/wotis/utils/jsonld-context-processing.py b/src/wotis/post_processors/__init__.py similarity index 100% rename from src/wotis/utils/jsonld-context-processing.py rename to src/wotis/post_processors/__init__.py diff --git a/src/wotis/post_processors/json_schema_postprocessor.py b/src/wotis/post_processors/json_schema_postprocessor.py new file mode 100644 index 0000000..e69de29 diff --git a/src/wotis/post_processors/jsonld_context_postprocessor.py b/src/wotis/post_processors/jsonld_context_postprocessor.py new file mode 100644 index 0000000..ce31372 --- /dev/null +++ b/src/wotis/post_processors/jsonld_context_postprocessor.py @@ -0,0 +1,93 @@ +import json +import logging + +from linkml_runtime.linkml_model.meta import AnonymousSlotExpression +from linkml_runtime.utils.schemaview import SchemaView + +XSD_NS = "http://www.w3.org/2001/XMLSchema#" + + +def process_langstring_conditions(slot, context_entry): + """ + Handles 'langString' and 'exactly_one_of' language conditions for a slot. + """ + is_langstring = slot.range == 'langString' + is_exactly_one_language = ( + slot.range is None and + any( + expr.range == 'langString' + for expr in slot.exactly_one_of if isinstance(expr, AnonymousSlotExpression) + ) + ) + if is_langstring or (is_exactly_one_language and isinstance(context_entry, dict)): + context_entry['@container'] = '@language' + context_entry.pop('@type', None) + return context_entry + + +def process_multivalued_slots(slot, context_entry): + """ + Handles multivalued slots and applies the '@set' container. + """ + if slot.multivalued and isinstance(context_entry, dict) and '@container' not in context_entry: + context_entry['@container'] = '@set' + context_entry.pop('@type', None) + return context_entry + + +def process_inlined_slot(slot, context_entry): + """ + Processes slots that are both inlined, multi-valued and have a instantiates fields. + """ + if slot.inlined and slot.multivalued and not slot.inlined_as_list and isinstance(context_entry, dict): + context_entry['@container'] = '@index' + context_entry['@type'] = '@id' + if slot.instantiates: + context_entry['@index'] = slot.instantiates + return context_entry + + +def process_exactly_one_of(slot, context_entry): + """ + Handles the 'exactly_one_of' condition for a slot, determining its type. + """ + if hasattr(slot, 'exactly_one_of') and slot.exactly_one_of: + ranges = [opt['range'] for opt in slot.exactly_one_of if 'range' in opt] + if len(set(ranges)) == 1: + context_entry["@type"] = f"{XSD_NS}:{ranges[0]}" + else: + logging.warning(f"Warning: Slot {slot.name} has different ranges") + return context_entry + + +def post_process_jsonld_context(schema_view: SchemaView, serialized_schema: str) -> str: + """ + Post-processes a JSON-LD context generated from the default LinkML generators. + """ + logging.info(f"Proceeding with JSON-LD Context postprocessor") + serialized_schema_json = json.loads(serialized_schema) + generated_context = serialized_schema_json.get('@context', {}) + default_range = schema_view.schema.default_range if schema_view.schema.default_range else "string" + for slot in schema_view.all_slots().values(): + slot_name = slot.name + context_entry = generated_context.get(slot_name, {}) + # Process language conditions + context_entry = process_langstring_conditions(slot, context_entry) + # Add @language for LinkML in_language slot + if slot.in_language and isinstance(context_entry, dict): + context_entry['@language'] = slot.in_language + # Handle slots that are dict objects + context_entry = process_inlined_slot(slot, context_entry) + # Handle the @id for slots with exactly_one_of field + context_entry = process_exactly_one_of(slot, context_entry) + # Handles default range type + if slot.range == default_range: + context_entry["@type"] = f"{XSD_NS}:{default_range}" + generated_context[slot_name] = context_entry + + # Intentionally handle multivalued slots separately after other processing + for slot in schema_view.all_slots().values(): + context_entry = generated_context.get(slot.name, {}) + context_entry = process_multivalued_slots(slot, context_entry) + generated_context[slot.name] = context_entry + return json.dumps(serialized_schema_json, indent=3) diff --git a/src/wotis/post_processors/shacl_postprocessor.py b/src/wotis/post_processors/shacl_postprocessor.py new file mode 100644 index 0000000..e69de29 From f307f2c19e348925af18612f0b461312f23c99a7 Mon Sep 17 00:00:00 2001 From: mahdanoura Date: Mon, 16 Sep 2024 21:08:47 +0200 Subject: [PATCH 9/9] package update --- src/wotis/__init__.py | 1 - src/wotis/cli.py | 17 +++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/wotis/__init__.py b/src/wotis/__init__.py index a430a5e..7c6c83a 100644 --- a/src/wotis/__init__.py +++ b/src/wotis/__init__.py @@ -1,6 +1,5 @@ from pathlib import Path - RESOURCES_PATH = Path('resources') GENS_PATH = RESOURCES_PATH / 'gens' SCHEMA_PATH = RESOURCES_PATH / 'schemas' diff --git a/src/wotis/cli.py b/src/wotis/cli.py index 27734a0..4455a29 100644 --- a/src/wotis/cli.py +++ b/src/wotis/cli.py @@ -1,5 +1,4 @@ """Command line interface for WoTIS.""" - import click import logging from pathlib import Path @@ -15,6 +14,7 @@ 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', @@ -38,7 +38,6 @@ help="Boolean for serving the generated documentation.") -# Documentation serving function def serve_documentation(): subprocess.run(['mkdocs', 'serve'], check=True) @@ -52,22 +51,24 @@ def generate_documentation(): # Main generation function def run_generator(schema_view, generator, output_dir): if generator == 'jsonschema': - logging.info(f"JSON Schema generation") + 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(linkml_schema_view, - # context_generator.serialize())) + (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') + 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}") @@ -122,7 +123,7 @@ def generate_wot_resources(input_schema: str, generate_docs: bool, serve_docs: b logging.info(f"Generating documentation locally as markdown files...") generate_documentation() if serve_docs: - logging.info(f"GServing documentation...") + logging.info(f"Serving documentation...") serve_documentation()