feat(okf): add okf_validate; harden YAML parser for block lists + folded scalars
Verified conformant against Google reference bundles (crypto_bitcoin, ga4, stackoverflow). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import sys, tempfile, unittest
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from okf_validate import validate_bundle
|
||||
|
||||
FIX = Path(__file__).resolve().parent / "fixtures" / "mini_bundle"
|
||||
GOOGLE = Path.home() / "Documents/reference-library/open-knowledge-format/okf/bundles"
|
||||
|
||||
|
||||
def write_bundle(root, files):
|
||||
for rel, content in files.items():
|
||||
p = Path(root) / rel
|
||||
p.parent.mkdir(parents=True, exist_ok=True)
|
||||
p.write_text(content, encoding="utf-8")
|
||||
|
||||
|
||||
class TestValidate(unittest.TestCase):
|
||||
def test_mini_fixture_conformant(self):
|
||||
report = validate_bundle(FIX)
|
||||
self.assertTrue(report["conformant"], report["errors"])
|
||||
self.assertGreaterEqual(report["concepts"], 3)
|
||||
|
||||
def test_missing_type_is_error(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
write_bundle(d, {"tables/x.md": "---\ntitle: X\n---\nbody"})
|
||||
report = validate_bundle(d)
|
||||
self.assertFalse(report["conformant"])
|
||||
self.assertTrue(any(e["rule"] == "type" for e in report["errors"]))
|
||||
|
||||
def test_missing_frontmatter_is_error(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
write_bundle(d, {"tables/x.md": "# no frontmatter\n"})
|
||||
self.assertFalse(validate_bundle(d)["conformant"])
|
||||
|
||||
def test_reserved_files_not_required_to_have_type(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
write_bundle(d, {"index.md": "# Index\n* [x](/tables/x.md)\n",
|
||||
"tables/x.md": "---\ntype: T\n---\nb"})
|
||||
self.assertTrue(validate_bundle(d)["conformant"])
|
||||
|
||||
def test_broken_link_is_warning_not_error(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
write_bundle(d, {"tables/x.md": "---\ntype: T\n---\nSee [y](/tables/y.md)."})
|
||||
report = validate_bundle(d)
|
||||
self.assertTrue(report["conformant"])
|
||||
self.assertTrue(any(w["rule"] == "broken_link" for w in report["warnings"]))
|
||||
|
||||
|
||||
class TestGoogleBundles(unittest.TestCase):
|
||||
@unittest.skipUnless(GOOGLE.exists(), "Google reference bundles not present")
|
||||
def test_google_sample_bundles_conformant(self):
|
||||
for name in ("crypto_bitcoin", "ga4", "stackoverflow"):
|
||||
bundle = GOOGLE / name
|
||||
if not bundle.exists():
|
||||
continue
|
||||
report = validate_bundle(bundle)
|
||||
self.assertTrue(
|
||||
report["conformant"],
|
||||
"%s non-conformant; first errors: %s" % (name, report["errors"][:3]),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user