Files
cleveragents-core/robot/helper_uko_analyzers.py
T
freemo d990fc1b41
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 19s
CI / typecheck (pull_request) Successful in 37s
CI / security (pull_request) Successful in 37s
CI / unit_tests (pull_request) Successful in 2m30s
CI / integration_tests (pull_request) Successful in 2m57s
CI / docker (pull_request) Successful in 38s
CI / coverage (pull_request) Successful in 4m22s
CI / lint (push) Successful in 12s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 33s
CI / typecheck (push) Successful in 33s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m8s
CI / docker (push) Successful in 39s
CI / integration_tests (push) Successful in 3m9s
CI / coverage (push) Successful in 4m35s
CI / benchmark-publish (push) Successful in 15m41s
CI / benchmark-regression (pull_request) Successful in 28m58s
feat(uko): add analyzer plugin framework and initial domain analyzers
Implemented the analyzer plugin framework with AnalyzerProtocol,
AnalyzerRegistry for registration/discovery by file extension,
PythonAnalyzer (AST-based extraction of modules, classes, functions,
imports, docstrings), and MarkdownAnalyzer (section, code block, and
link extraction). Both analyzers produce well-formed UKO triples with
proper URI schemes.

ISSUES CLOSED: #551
2026-03-05 19:20:39 +00:00

242 lines
7.9 KiB
Python

"""Robot Framework helper for UKO Analyzer Plugin Framework smoke tests.
Provides a CLI-style interface for Robot to invoke analyzer creation,
protocol compliance, registry operations, and triple extraction.
Exit code 0 = success, 1 = failure.
Usage:
python robot/helper_uko_analyzers.py <command>
"""
from __future__ import annotations
import sys
from pathlib import Path
# Ensure the src directory is on the import path.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
from cleveragents.domain.models.acms.analyzers import ( # noqa: E402
AnalyzerProtocol,
AnalyzerRegistry,
UKOTriple,
)
from cleveragents.domain.models.acms.markdown_analyzer import ( # noqa: E402
MarkdownAnalyzer,
)
from cleveragents.domain.models.acms.python_analyzer import ( # noqa: E402
PythonAnalyzer,
)
def main() -> int:
"""Entry point called by Robot Framework ``Run Process``."""
if len(sys.argv) < 2:
print("Usage: helper_uko_analyzers.py <command>")
return 1
command: str = sys.argv[1]
if command == "python-protocol":
try:
analyzer = PythonAnalyzer()
assert isinstance(analyzer, AnalyzerProtocol)
assert ".py" in analyzer.supported_extensions
assert analyzer.domain == "python"
print("uko-python-protocol-ok")
return 0
except Exception as exc:
print(f"uko-python-protocol-fail: {exc}")
return 1
if command == "markdown-protocol":
try:
analyzer = MarkdownAnalyzer()
assert isinstance(analyzer, AnalyzerProtocol)
assert ".md" in analyzer.supported_extensions
assert analyzer.domain == "markdown"
print("uko-markdown-protocol-ok")
return 0
except Exception as exc:
print(f"uko-markdown-protocol-fail: {exc}")
return 1
if command == "registry":
try:
registry = AnalyzerRegistry()
py_analyzer = PythonAnalyzer()
md_analyzer = MarkdownAnalyzer()
registry.register(py_analyzer)
registry.register(md_analyzer)
assert registry.get_for_extension(".py") is py_analyzer
assert registry.get_for_extension(".md") is md_analyzer
assert registry.get_for_extension(".rs") is None
assert len(registry) == 2
print("uko-registry-ok")
return 0
except Exception as exc:
print(f"uko-registry-fail: {exc}")
return 1
if command == "python-analyze":
try:
analyzer = PythonAnalyzer()
code = (
'"""Module doc."""\n'
"import os\n"
"from pathlib import Path\n\n"
"class MyClass:\n"
' """Class doc."""\n'
" def method(self):\n"
" pass\n\n"
"def top_func():\n"
' """Function doc."""\n'
" pass\n"
)
triples = analyzer.analyze(code, "src/sample.py")
assert len(triples) > 0
# Check module exists
assert any(
t.predicate == "rdf:type" and t.object_uri == "uko-code:Module"
for t in triples
)
# Check class exists
assert any(
t.predicate == "rdf:type" and t.object_uri == "uko-py:Class"
for t in triples
)
# Check function exists
assert any(
t.predicate == "rdf:type" and t.object_uri == "uko-py:Function"
for t in triples
)
# Check import reference
assert any(
t.predicate == "uko:references" and "os" in t.object_uri
for t in triples
)
print("uko-python-analyze-ok")
return 0
except Exception as exc:
print(f"uko-python-analyze-fail: {exc}")
return 1
if command == "markdown-analyze":
try:
analyzer = MarkdownAnalyzer()
content = (
"# Introduction\n\n"
"Some text with [link](https://example.com).\n\n"
"## Details\n\n"
"```python\nprint('hello')\n```\n"
)
triples = analyzer.analyze(content, "docs/readme.md")
assert len(triples) > 0
# Check document exists
assert any(
t.predicate == "rdf:type" and t.object_uri == "uko-doc:Document"
for t in triples
)
# Check section exists
assert any(
t.predicate == "rdf:type" and t.object_uri == "uko-doc:Section"
for t in triples
)
# Check code block
assert any(
t.predicate == "rdf:type" and t.object_uri == "uko-code:CodeBlock"
for t in triples
)
# Check link reference
assert any(
t.predicate == "uko:references"
and "https://example.com" in t.object_value
for t in triples
)
print("uko-markdown-analyze-ok")
return 0
except Exception as exc:
print(f"uko-markdown-analyze-fail: {exc}")
return 1
if command == "triple-model":
try:
# Valid object-property triple
t1 = UKOTriple(
subject_uri="uko://code/module/foo",
predicate="rdf:type",
object_uri="uko-code:Module",
)
assert t1.confidence == 1.0
# Valid data-property triple
t2 = UKOTriple(
subject_uri="uko://code/class/Bar",
predicate="rdfs:label",
object_value="Bar",
confidence=0.9,
)
assert t2.object_value == "Bar"
# Reject empty subject
try:
UKOTriple(
subject_uri="",
predicate="rdf:type",
object_uri="uko:X",
)
print("uko-triple-model-fail: no ValueError for empty subject")
return 1
except ValueError:
pass
# Reject bad confidence
try:
UKOTriple(
subject_uri="uko://x",
predicate="rdf:type",
object_uri="uko:X",
confidence=2.0,
)
print("uko-triple-model-fail: no ValueError for bad confidence")
return 1
except ValueError:
pass
print("uko-triple-model-ok")
return 0
except Exception as exc:
print(f"uko-triple-model-fail: {exc}")
return 1
if command == "malformed":
try:
py = PythonAnalyzer()
# Syntax error => empty list
result = py.analyze("def (\n broken", "src/bad.py")
assert result == []
# Empty content => ValueError
try:
py.analyze("", "src/test.py")
print("uko-malformed-fail: no ValueError for empty content")
return 1
except ValueError:
pass
md = MarkdownAnalyzer()
try:
md.analyze("", "docs/test.md")
print("uko-malformed-fail: no ValueError for empty md content")
return 1
except ValueError:
pass
print("uko-malformed-ok")
return 0
except Exception as exc:
print(f"uko-malformed-fail: {exc}")
return 1
print(f"Unknown command: {command}")
return 1
if __name__ == "__main__":
sys.exit(main())