"""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()