generated from coulomb/repo-seed
Extensible canonical internal processing refactoring
This commit is contained in:
112
tests/test_extension_registry.py
Normal file
112
tests/test_extension_registry.py
Normal file
@@ -0,0 +1,112 @@
|
||||
import pytest
|
||||
|
||||
from markitect_tool.extension import (
|
||||
ExtensionDescriptor,
|
||||
ExtensionRegistry,
|
||||
ExtensionRegistryError,
|
||||
OptionalDependency,
|
||||
ProcessingCapability,
|
||||
)
|
||||
|
||||
|
||||
def test_extension_descriptor_serializes_contract_metadata():
|
||||
descriptor = ExtensionDescriptor(
|
||||
id="query.selector",
|
||||
kind="query-engine",
|
||||
summary="Small selector query engine.",
|
||||
capabilities=[ProcessingCapability(id="ast", kind="read")],
|
||||
input_contract="Document + selector",
|
||||
output_contract="QueryMatch[]",
|
||||
diagnostics_namespace="query",
|
||||
provenance_prefix="query.selector",
|
||||
cli={"command": "mkt query"},
|
||||
docs=["docs/query-extraction.md"],
|
||||
)
|
||||
|
||||
data = descriptor.to_dict()
|
||||
|
||||
assert data["id"] == "query.selector"
|
||||
assert data["kind"] == "query-engine"
|
||||
assert data["capabilities"][0]["id"] == "ast"
|
||||
assert data["cli"]["command"] == "mkt query"
|
||||
|
||||
|
||||
def test_extension_registry_lists_by_kind_and_capability():
|
||||
selector = ExtensionDescriptor(
|
||||
id="query.selector",
|
||||
kind="query-engine",
|
||||
capabilities=[ProcessingCapability(id="ast")],
|
||||
)
|
||||
local = ExtensionDescriptor(
|
||||
id="backend.local-sqlite",
|
||||
kind="backend",
|
||||
capabilities=[ProcessingCapability(id="snapshots"), ProcessingCapability(id="fts")],
|
||||
)
|
||||
registry = ExtensionRegistry([local, selector])
|
||||
|
||||
assert [descriptor.id for descriptor in registry.list()] == [
|
||||
"backend.local-sqlite",
|
||||
"query.selector",
|
||||
]
|
||||
assert [descriptor.id for descriptor in registry.list(kind="query-engine")] == [
|
||||
"query.selector"
|
||||
]
|
||||
assert [descriptor.id for descriptor in registry.require_capability("fts")] == [
|
||||
"backend.local-sqlite"
|
||||
]
|
||||
|
||||
|
||||
def test_extension_registry_rejects_duplicate_ids():
|
||||
descriptor = ExtensionDescriptor(id="query.selector", kind="query-engine")
|
||||
registry = ExtensionRegistry([descriptor])
|
||||
|
||||
with pytest.raises(ExtensionRegistryError, match="Duplicate extension id"):
|
||||
registry.register(descriptor)
|
||||
|
||||
|
||||
def test_extension_registry_checks_optional_dependencies():
|
||||
registry = ExtensionRegistry(
|
||||
[
|
||||
ExtensionDescriptor(
|
||||
id="query.jsonpath",
|
||||
kind="query-engine",
|
||||
optional_dependencies=[
|
||||
OptionalDependency(
|
||||
name="jsonpath_ng",
|
||||
package="jsonpath-ng",
|
||||
extra="query",
|
||||
required=True,
|
||||
),
|
||||
OptionalDependency(name="tabulate"),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
missing = registry.check_dependencies("query.jsonpath", available_modules=set())
|
||||
available = registry.check_dependencies(
|
||||
"query.jsonpath",
|
||||
available_modules={"jsonpath_ng", "tabulate"},
|
||||
)
|
||||
|
||||
assert not missing.compatible
|
||||
assert missing.missing == ["jsonpath_ng"]
|
||||
assert missing.optional_missing == ["tabulate"]
|
||||
assert available.compatible
|
||||
|
||||
|
||||
def test_extension_descriptor_instantiates_factory():
|
||||
descriptor = ExtensionDescriptor(
|
||||
id="fake.extension",
|
||||
kind="test",
|
||||
factory=lambda: {"ready": True},
|
||||
)
|
||||
|
||||
assert descriptor.instantiate() == {"ready": True}
|
||||
|
||||
|
||||
def test_extension_descriptor_requires_factory_to_instantiate():
|
||||
descriptor = ExtensionDescriptor(id="fake.extension", kind="test")
|
||||
|
||||
with pytest.raises(ExtensionRegistryError, match="has no factory"):
|
||||
descriptor.instantiate()
|
||||
Reference in New Issue
Block a user