"""Tests for the import surface: an id is a module, `help` is the load.""" from __future__ import annotations import importlib import inspect import json import sys import tempfile import unittest from pathlib import Path import klbr.skills from klbr_runtime import skill_index BODY = "# alpha\n\nOnce you have a workspace you can find code.\n" class SkillsImportTests(unittest.TestCase): """Resolution is lazy, so a test installs first and imports after.""" def setUp(self): self.temporary = tempfile.TemporaryDirectory(prefix="klbr-skill-import-") self.directory = Path(self.temporary.name) self.body_file = self.directory / "SKILL.md" self.body_file.write_text(BODY, encoding="utf-8") self.installed: list[str] = [] def tearDown(self): self.temporary.cleanup() skill_index.install(self.directory / "absent.json") # The import system caches what it resolved; a real worker resolves once per # process, so clearing here only keeps one test's id from answering another's. for skill_id in self.installed: sys.modules.pop(f"klbr.skills.{skill_id}", None) def install(self, skill_id: str, *, refused=()): self.installed.append(skill_id) document = { "revision": "rev-import", "skills": [ { "id": skill_id, "origin": "builtin", "path": str(self.body_file), "digest": "c" * 64, "text": BODY, } ], "refused": [{"id": entry_id, "reason": reason} for entry_id, reason in refused], } path = self.directory / "skills.json" path.write_text(json.dumps(document), encoding="utf-8") skill_index.install(path) def test_an_id_is_an_attribute_and_its_documentation_is_the_body(self): self.install("alpha") self.assertIn("alpha", dir(klbr.skills)) self.assertEqual(klbr.skills.index, ("alpha",)) self.assertEqual(klbr.skills.revision, "rev-import") self.assertEqual(klbr.skills.alpha.__doc__, BODY) self.assertEqual(klbr.skills.alpha.id, "alpha") self.assertEqual(klbr.skills.alpha.digest, "c" * 64) self.assertEqual(klbr.skills.alpha.__file__, str(self.body_file)) self.assertIn("Once you have a workspace", inspect.getdoc(klbr.skills.alpha)) def test_importing_by_name_and_from_import_reach_the_same_module(self): self.install("alpha") imported = importlib.import_module("klbr.skills.alpha") self.assertIs(imported, klbr.skills.alpha) from klbr.skills import alpha # noqa: F401 - the import is the assertion self.assertIs(alpha, klbr.skills.alpha) self.assertEqual(inspect.getsource(imported), BODY) def test_a_refused_id_names_the_reason_however_it_is_asked_for(self): self.install("alpha", refused=[("Beta", "skill id must be lower-case")]) self.assertEqual(klbr.skills.refused[0].id, "Beta") with self.assertRaises(AttributeError) as attribute: klbr.skills.Beta self.assertIn("is not offered: skill id must be lower-case", str(attribute.exception)) with self.assertRaises(ModuleNotFoundError) as imported: importlib.import_module("klbr.skills.Beta") self.assertIn("is not offered: skill id must be lower-case", str(imported.exception)) def test_an_unknown_id_lists_what_is_available(self): self.install("alpha") with self.assertRaises(AttributeError) as raised: klbr.skills.nope self.assertIn("no skill 'nope'; available: alpha", str(raised.exception)) def test_a_generation_without_a_payload_says_so_instead_of_listing_nothing(self): with self.assertRaises(AttributeError) as raised: klbr.skills.alpha self.assertIn("spawned with no skill set", str(raised.exception)) self.assertEqual(klbr.skills.revision, "no-skills") if __name__ == "__main__": unittest.main()