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
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
242 lines
7.9 KiB
Python
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())
|