|
2 | 2 |
|
3 | 3 | lokf new my-kb # scaffold a knowledge base |
4 | 4 | lokf convert path/to/concept.md --format ttl # markdown -> RDF |
| 5 | + lokf validate knowledge # assemble + validate a bundle |
5 | 6 | lokf query examples/acme-knowledge "SELECT ..." # SPARQL over a bundle |
6 | 7 | lokf serve examples/acme-knowledge # local SPARQL endpoint + viz |
7 | 8 | lokf propose examples/acme-knowledge --apply # typed relations from links |
@@ -94,6 +95,62 @@ def convert( |
94 | 95 | typer.echo(data, nl=False) |
95 | 96 |
|
96 | 97 |
|
| 98 | +# --------------------------------------------------------------------------- |
| 99 | +# validate |
| 100 | +# --------------------------------------------------------------------------- |
| 101 | +@app.command() |
| 102 | +def validate( |
| 103 | + bundle_dir: Path = typer.Argument( |
| 104 | + Path("knowledge"), exists=True, file_okay=False, |
| 105 | + help="A LOKF bundle directory to assemble and validate.", |
| 106 | + ), |
| 107 | + schema: Optional[Path] = typer.Option( |
| 108 | + None, "--schema", "-s", |
| 109 | + help="Schema file (default: a local lokf.yaml checkout, else the copy " |
| 110 | + "packaged with lokf).", |
| 111 | + ), |
| 112 | +) -> None: |
| 113 | + """Assemble a bundle and validate it against the LOKF schema. |
| 114 | +
|
| 115 | + Works on any bundle directory. The schema is resolved from ``--schema`` if |
| 116 | + passed, otherwise from a ``lokf.yaml`` found in the current directory or an |
| 117 | + ancestor, otherwise from the copy shipped inside the installed ``lokf`` |
| 118 | + package - so a bundle needs no schema file of its own to be validated. |
| 119 | + """ |
| 120 | + import os |
| 121 | + import subprocess |
| 122 | + import tempfile |
| 123 | + |
| 124 | + from lokf.model import load_bundle |
| 125 | + from lokf.schema import schema_path |
| 126 | + |
| 127 | + try: |
| 128 | + sch = schema_path(schema) |
| 129 | + except FileNotFoundError as exc: |
| 130 | + _err(str(exc)) |
| 131 | + raise typer.Exit(1) |
| 132 | + |
| 133 | + bundle = load_bundle(bundle_dir) |
| 134 | + doc = dict(bundle.meta) |
| 135 | + doc["concepts"] = bundle.docs() |
| 136 | + |
| 137 | + fd, tmp = tempfile.mkstemp(suffix=".bundle.json") |
| 138 | + try: |
| 139 | + with os.fdopen(fd, "w", encoding="utf-8") as f: |
| 140 | + json.dump(doc, f) |
| 141 | + proc = subprocess.run( |
| 142 | + ["linkml-validate", "-s", str(sch), "-C", "KnowledgeBundle", tmp] |
| 143 | + ) |
| 144 | + finally: |
| 145 | + os.remove(tmp) |
| 146 | + if proc.returncode != 0: |
| 147 | + raise typer.Exit(proc.returncode) |
| 148 | + typer.echo( |
| 149 | + f"OK — {len(bundle.concepts)} concepts in {bundle_dir} validate " |
| 150 | + "against KnowledgeBundle." |
| 151 | + ) |
| 152 | + |
| 153 | + |
97 | 154 | # --------------------------------------------------------------------------- |
98 | 155 | # tables |
99 | 156 | # --------------------------------------------------------------------------- |
|
0 commit comments