ad53a659de
CI / lint (pull_request) Successful in 14s
CI / quality (pull_request) Successful in 15s
CI / security (pull_request) Successful in 30s
CI / typecheck (pull_request) Successful in 35s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 14s
CI / unit_tests (pull_request) Successful in 2m8s
CI / integration_tests (pull_request) Successful in 3m36s
CI / docker (pull_request) Successful in 39s
CI / coverage (pull_request) Successful in 5m19s
CI / lint (push) Successful in 14s
CI / typecheck (push) Successful in 49s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 1m15s
CI / build (push) Successful in 14s
CI / unit_tests (push) Successful in 3m25s
CI / integration_tests (push) Successful in 4m53s
CI / benchmark-regression (push) Has been skipped
CI / coverage (push) Successful in 6m6s
CI / benchmark-publish (push) Successful in 15m16s
CI / docker (push) Successful in 39s
CI / benchmark-regression (pull_request) Successful in 34m22s
Add UKO Layer 0-3 ontology skeleton (RDF/TTL) with base URI, version IRI, and prefix conventions. Python loaders handle URI parsing, inheritance resolution, versioning metadata, and validation of undefined prefixes and missing rdf:type. Includes Behave BDD scenarios, Robot Framework integration tests, ASV benchmarks, and reference documentation. - Resolve rdfs:domain and rdfs:range values to full URIs in parser - Fix type: ignore in Robot helper with proper Callable typing - Export UKO models from core/__init__.py - Add parent-URI existence validation in validate() - Rename scenario to clarify parser-skips vs validation-rejects - Add scenario testing validation with injected typeless node - Add Scenario Outline for multi-layer node count assertions - TTL: Layer 0 classes (InformationUnit, Container, Atom, Annotation, Boundary) with contains/references/dependsOn properties. Layer 1 uko-code: classes (Module, Callable, TypeDefinition, TestCase, Import) with hasReturnType/hasParameters/testsCallable. Layer 2 uko-oo: classes (Class, Interface, Method, Attribute) with inheritsFrom/implements and rdfs:subPropertyOf. New URI scheme cleveragents.ai/ontology/uko#. - TTL: uko-oo:Class has dual rdfs:subClassOf (TypeDefinition + Container), uko-oo:Interface has dual rdfs:subClassOf (TypeDefinition + Boundary). - Model: UKONode.parent_uri replaced with parent_uris: tuple[str, ...] to support multi-parent rdfs:subClassOf. - Loader: prefix regex supports hyphenated names (uko-code, uko-oo). Semantic domain prefix maps (_LAYER_PREFIXES, _LAYER_IRI_PREFIXES). Comma-separated rdfs:subClassOf parsing. rdfs:domain/range/subPropertyOf URI resolution. BFS DAG traversal with DFS cycle detection for resolve_inheritance. HTTP URI skip in validation (D-1 fix). Duplicate error guard (B-1 fix). Consistent quoting (M-1 fix). - Services __init__: export UKOLoader and UKOValidationError. - Tests: 24 Behave scenarios (multi-parent, domain/range resolution, non-existent parent validation). 4 Robot smoke tests. Consolidated context attributes (T-3 fix). - Docs: uko.md written for spec-aligned structure. - Namespace prefix match in parent-URI validation includes a delimiter guard (# or /) preventing false positives on URIs that share the UKO prefix string (e.g. ukobogus:, ukoo:). ISSUES CLOSED: #189
133 lines
3.5 KiB
Python
133 lines
3.5 KiB
Python
"""Robot Framework helper for UKO ontology integration tests.
|
|
|
|
Subcommands:
|
|
load-ttl -- load docs/ontology/uko.ttl, print ``uko-load-ok``
|
|
validate -- load and validate, print ``uko-validate-ok``
|
|
resolve-inheritance -- resolve uko-oo:Class chain, print ``uko-inheritance-ok``
|
|
layer-nodes -- get layer 0 nodes, print ``uko-layer-nodes-ok``
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
if _SRC not in sys.path:
|
|
sys.path.insert(0, _SRC)
|
|
|
|
from cleveragents.application.services.uko_loader import UKOLoader # noqa: E402
|
|
|
|
_TTL_PATH = Path(__file__).resolve().parents[1] / "docs" / "ontology" / "uko.ttl"
|
|
|
|
|
|
def _cmd_load_ttl() -> int:
|
|
"""Load the TTL file and verify basic parsing."""
|
|
try:
|
|
loader = UKOLoader()
|
|
ontology = loader.load(_TTL_PATH)
|
|
except Exception as exc:
|
|
print(f"uko-fail: {exc}")
|
|
return 1
|
|
|
|
if not ontology.nodes:
|
|
print("uko-fail: no nodes parsed")
|
|
return 1
|
|
|
|
print(
|
|
f"uko-load-ok: {len(ontology.nodes)} nodes, {len(ontology.prefixes)} prefixes"
|
|
)
|
|
return 0
|
|
|
|
|
|
def _cmd_validate() -> int:
|
|
"""Load and validate the ontology."""
|
|
try:
|
|
loader = UKOLoader()
|
|
ontology = loader.load(_TTL_PATH)
|
|
errors = loader.validate(ontology)
|
|
except Exception as exc:
|
|
print(f"uko-fail: {exc}")
|
|
return 1
|
|
|
|
if errors:
|
|
print(f"uko-fail: validation errors: {errors}")
|
|
return 1
|
|
|
|
print(f"uko-validate-ok: version={ontology.version.version}")
|
|
return 0
|
|
|
|
|
|
def _cmd_resolve_inheritance() -> int:
|
|
"""Resolve uko-oo:Class inheritance chain (Layer 2 -> 1 -> 0)."""
|
|
try:
|
|
loader = UKOLoader()
|
|
ontology = loader.load(_TTL_PATH)
|
|
chain = loader.resolve_inheritance(
|
|
ontology,
|
|
"https://cleveragents.ai/ontology/uko/oo#Class",
|
|
)
|
|
except Exception as exc:
|
|
print(f"uko-fail: {exc}")
|
|
return 1
|
|
|
|
if len(chain) < 3:
|
|
print(f"uko-fail: chain too short ({len(chain)} nodes)")
|
|
return 1
|
|
|
|
print(f"uko-inheritance-ok: {len(chain)} nodes")
|
|
for node in chain:
|
|
print(f" layer={node.layer} label={node.label}")
|
|
return 0
|
|
|
|
|
|
def _cmd_layer_nodes() -> int:
|
|
"""Get all Layer 0 nodes."""
|
|
try:
|
|
loader = UKOLoader()
|
|
ontology = loader.load(_TTL_PATH)
|
|
nodes = loader.get_layer_nodes(ontology, 0)
|
|
except Exception as exc:
|
|
print(f"uko-fail: {exc}")
|
|
return 1
|
|
|
|
if len(nodes) < 18:
|
|
print(f"uko-fail: expected >= 18 layer-0 nodes, got {len(nodes)}")
|
|
return 1
|
|
|
|
print(f"uko-layer-nodes-ok: {len(nodes)} nodes")
|
|
for node in nodes:
|
|
print(f" {node.label} ({node.uri})")
|
|
return 0
|
|
|
|
|
|
_COMMANDS: dict[str, Callable[[], int]] = {
|
|
"load-ttl": _cmd_load_ttl,
|
|
"validate": _cmd_validate,
|
|
"resolve-inheritance": _cmd_resolve_inheritance,
|
|
"layer-nodes": _cmd_layer_nodes,
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
"""Entry point called by Robot Framework ``Run Process``."""
|
|
if len(sys.argv) < 2:
|
|
print(
|
|
"Usage: helper_uko_ontology.py "
|
|
"<load-ttl|validate|resolve-inheritance|layer-nodes>"
|
|
)
|
|
return 1
|
|
|
|
command = sys.argv[1]
|
|
handler = _COMMANDS.get(command)
|
|
if handler is None:
|
|
print(f"Unknown command: {command}")
|
|
return 1
|
|
|
|
return handler()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|