From 873249695f790560ec0163b7340d5b549b8bf747 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 20 May 2026 17:38:16 +0200 Subject: [PATCH 1/6] move files and clean up --- examples/ask_interaction.py | 4 ++-- examples/basic.py | 2 +- examples/binding_models.py | 4 ++-- examples/custom-settings/custom_settings.py | 4 ++-- examples/dependency_injection.py | 4 ++-- examples/legacy/tree-printer/app.py | 2 +- examples/post_measurement.py | 6 ++--- examples/testing/kb.py | 4 ++-- examples/testing/test_kb.py | 13 +++++------ pyproject.toml | 6 +++++ src/{ => knowledge_mapper}/__init__.py | 1 + .../dependency_injection.py | 0 src/{ => knowledge_mapper}/kb/__init__.py | 0 src/{ => knowledge_mapper}/kb/builder.py | 0 .../kb/knowledge_base.py | 18 ++++++++++++--- src/{ => knowledge_mapper}/ke/__init__.py | 0 src/{ => knowledge_mapper}/ke/client.py | 17 ++++++++++++-- src/{ => knowledge_mapper}/ke/errors.py | 0 src/{ => knowledge_mapper}/ke/models.py | 0 .../ke/testing/__init__.py | 0 .../ke/testing/fake_client.py | 4 ++-- .../knowledge_interaction.py | 2 +- src/{ => knowledge_mapper}/legacy/__main__.py | 6 ++--- .../legacy/auth/__init__.py | 0 .../legacy/auth/base_auth.py | 0 .../legacy/auth/sql_auth.py | 0 .../legacy/auth/static_auth.py | 0 .../legacy/data_source.py | 2 +- .../legacy/knowledge_base.py | 2 +- .../legacy/knowledge_interaction.py | 0 .../legacy/knowledge_mapper.py | 4 ++-- .../legacy/sparql_source.py | 0 .../legacy/sql_source.py | 0 .../legacy/tests/__init__.py | 0 .../legacy/tests/legacy_test_tke_client.py | 4 ++-- .../legacy/tke_client.py | 2 +- .../legacy/tke_exceptions.py | 0 src/{ => knowledge_mapper}/legacy/utils.py | 0 .../legacy/wizard_mapper.py | 2 +- src/{ => knowledge_mapper}/settings.py | 2 +- tests/configuration/test_configuration.py | 2 +- tests/test_ask_and_post.py | 22 +++++++++---------- tests/test_bindings.py | 2 +- tests/test_client.py | 4 ++-- tests/test_dependency_injection.py | 6 ++--- tests/test_handlers.py | 4 ++-- tests/test_kb_lifespan.py | 8 +++---- tests/test_ki_registration.py | 8 +++---- tests/test_knowledge_base_builder.py | 4 ++-- 49 files changed, 103 insertions(+), 72 deletions(-) rename src/{ => knowledge_mapper}/__init__.py (89%) rename src/{ => knowledge_mapper}/dependency_injection.py (100%) rename src/{ => knowledge_mapper}/kb/__init__.py (100%) rename src/{ => knowledge_mapper}/kb/builder.py (100%) rename src/{ => knowledge_mapper}/kb/knowledge_base.py (96%) rename src/{ => knowledge_mapper}/ke/__init__.py (100%) rename src/{ => knowledge_mapper}/ke/client.py (95%) rename src/{ => knowledge_mapper}/ke/errors.py (100%) rename src/{ => knowledge_mapper}/ke/models.py (100%) rename src/{ => knowledge_mapper}/ke/testing/__init__.py (100%) rename src/{ => knowledge_mapper}/ke/testing/fake_client.py (97%) rename src/{ => knowledge_mapper}/knowledge_interaction.py (98%) rename src/{ => knowledge_mapper}/legacy/__main__.py (97%) rename src/{ => knowledge_mapper}/legacy/auth/__init__.py (100%) rename src/{ => knowledge_mapper}/legacy/auth/base_auth.py (100%) rename src/{ => knowledge_mapper}/legacy/auth/sql_auth.py (100%) rename src/{ => knowledge_mapper}/legacy/auth/static_auth.py (100%) rename src/{ => knowledge_mapper}/legacy/data_source.py (83%) rename src/{ => knowledge_mapper}/legacy/knowledge_base.py (99%) rename src/{ => knowledge_mapper}/legacy/knowledge_interaction.py (100%) rename src/{ => knowledge_mapper}/legacy/knowledge_mapper.py (97%) rename src/{ => knowledge_mapper}/legacy/sparql_source.py (100%) rename src/{ => knowledge_mapper}/legacy/sql_source.py (100%) rename src/{ => knowledge_mapper}/legacy/tests/__init__.py (100%) rename src/{ => knowledge_mapper}/legacy/tests/legacy_test_tke_client.py (97%) rename src/{ => knowledge_mapper}/legacy/tke_client.py (97%) rename src/{ => knowledge_mapper}/legacy/tke_exceptions.py (100%) rename src/{ => knowledge_mapper}/legacy/utils.py (100%) rename src/{ => knowledge_mapper}/legacy/wizard_mapper.py (99%) rename src/{ => knowledge_mapper}/settings.py (97%) diff --git a/examples/ask_interaction.py b/examples/ask_interaction.py index a597e4d..5390fef 100644 --- a/examples/ask_interaction.py +++ b/examples/ask_interaction.py @@ -1,7 +1,7 @@ from shared import get_example_logger -from src import KnowledgeBase -from src.ke.models import BindingModel, Literal, Uri +from src.knowledge_mapper import KnowledgeBase +from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri EXAMPLE_NAME = "ask-interaction" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/basic.py b/examples/basic.py index 55e83dd..702ae7e 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -1,6 +1,6 @@ from shared import get_example_logger -from src.kb.knowledge_base import KnowledgeBase +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase EXAMPLE_NAME = "basic" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/binding_models.py b/examples/binding_models.py index a423668..1d31aea 100644 --- a/examples/binding_models.py +++ b/examples/binding_models.py @@ -3,8 +3,8 @@ from rdflib import URIRef from shared import get_example_logger -from src.kb.knowledge_base import KnowledgeBase -from src.ke.models import ( +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase +from src.knowledge_mapper.ke.models import ( BindingModel, BindingSet, KnowledgeInteractionInfo, diff --git a/examples/custom-settings/custom_settings.py b/examples/custom-settings/custom_settings.py index 67040f3..df39232 100644 --- a/examples/custom-settings/custom_settings.py +++ b/examples/custom-settings/custom_settings.py @@ -26,8 +26,8 @@ from pydantic_settings import CliSettingsSource, SettingsConfigDict from shared import get_example_logger -from src import KnowledgeBase, KnowledgeBaseSettings -from src.ke.models import BindingSet, KnowledgeInteractionInfo +from src.knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings +from src.knowledge_mapper.ke.models import BindingSet, KnowledgeInteractionInfo EXAMPLE_NAME = "custom-settings" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/dependency_injection.py b/examples/dependency_injection.py index a4d6add..9bf04e1 100644 --- a/examples/dependency_injection.py +++ b/examples/dependency_injection.py @@ -26,8 +26,8 @@ from shared import get_example_logger -from src import Depends, KnowledgeBase -from src.ke.models import BindingModel, KnowledgeInteractionInfo, Literal, Uri +from src.knowledge_mapper import Depends, KnowledgeBase +from src.knowledge_mapper.ke.models import BindingModel, KnowledgeInteractionInfo, Literal, Uri EXAMPLE_NAME = "dependency-injection" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/legacy/tree-printer/app.py b/examples/legacy/tree-printer/app.py index 05e35cd..54ae5c1 100644 --- a/examples/legacy/tree-printer/app.py +++ b/examples/legacy/tree-printer/app.py @@ -1,5 +1,5 @@ from time import sleep -from src.knowledge_interaction import AskKnowledgeInteraction, AskKnowledgeInteractionRegistrationRequest +from src.knowledge_mapper.knowledge_interaction import AskKnowledgeInteraction, AskKnowledgeInteractionRegistrationRequest from src.tke_client import TkeClient from src.knowledge_base import KnowledgeBaseRegistrationRequest diff --git a/examples/post_measurement.py b/examples/post_measurement.py index cf048ee..2141fa4 100644 --- a/examples/post_measurement.py +++ b/examples/post_measurement.py @@ -5,8 +5,8 @@ from rdflib import URIRef from shared import get_example_logger -from src.kb.knowledge_base import KnowledgeBase -from src.ke.models import ( +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase +from src.knowledge_mapper.ke.models import ( BindingModel, Literal, Uri, @@ -46,7 +46,7 @@ class ResultBinding(BindingModel): """, result_graph_pattern=""" ?measurement a ex:Measurement ; - ex:storedBy ?kb ; + ex:storedBy ?kb . """, prefixes={"ex": "http://example.org/knowledge-mapper/post-measurement#"}, result_binding_model=ResultBinding, diff --git a/examples/testing/kb.py b/examples/testing/kb.py index 1d52378..370471f 100644 --- a/examples/testing/kb.py +++ b/examples/testing/kb.py @@ -9,8 +9,8 @@ from shared import get_example_logger -from src import KnowledgeBase -from src.ke.models import BindingModel, Literal, Uri +from src.knowledge_mapper import KnowledgeBase +from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri EXAMPLE_NAME = "testing" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/testing/test_kb.py b/examples/testing/test_kb.py index 67c0a9d..bd0acc9 100644 --- a/examples/testing/test_kb.py +++ b/examples/testing/test_kb.py @@ -1,7 +1,7 @@ import pytest from rdflib import URIRef -from src.ke.testing import TestClient +from src.knowledge_mapper.ke.testing import TestClient # Import the Knowledge Base that you would like to test, along with any relevant binding # models. @@ -40,7 +40,7 @@ def test_ask_ki_with_result(client: TestClient): [ { "s": "", - "value": "test value", + "value": "\"test value\"", } ], ) @@ -48,22 +48,21 @@ def test_ask_ki_with_result(client: TestClient): assert result_binding_set == [ { "s": "", - "value": "test value", + "value": "\"test value\"", } ] # This is a little more useful when you have a binding model, testing the correctness of # the binding model according to the graph pattern. One test per interaction like this -# per interaction is probably a good idea, to isolate issues with the binding model from -# other issues. +# is probably a good idea, to isolate issues with the binding model from other issues. def test_ask_ki_with_binding_model(client: TestClient): client.mock_result_binding_set( "ask-ki-with-binding-model", [ { "s": "", - "value": "test value", + "value": "\"test value\"", } ], ) @@ -99,7 +98,7 @@ def test_function_containing_ask(client: TestClient): ) result = ask_for_values_of_subject("Subject") - assert result == ["test value"] + assert result == ["\"test value\""] # Similar approaches can be taken for POST interactions. diff --git a/pyproject.toml b/pyproject.toml index ac319e3..c81e5fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,3 +66,9 @@ quote-style = "double" [build-system] requires = ["setuptools>=80"] build-backend = "setuptools.build_meta" + +[tool.setuptools] +package-dir = {"" = "src"} + +[tool.setuptools.packages.find] +where = ["src"] diff --git a/src/__init__.py b/src/knowledge_mapper/__init__.py similarity index 89% rename from src/__init__.py rename to src/knowledge_mapper/__init__.py index ac00237..51631d4 100644 --- a/src/__init__.py +++ b/src/knowledge_mapper/__init__.py @@ -3,6 +3,7 @@ from .dependency_injection import Depends from .kb.builder import KnowledgeBaseBuilder from .kb.knowledge_base import KnowledgeBase +from .ke.models import BindingModel, Literal, Uri from .settings import KnowledgeBaseSettings __version__ = "0.1.0a0" diff --git a/src/dependency_injection.py b/src/knowledge_mapper/dependency_injection.py similarity index 100% rename from src/dependency_injection.py rename to src/knowledge_mapper/dependency_injection.py diff --git a/src/kb/__init__.py b/src/knowledge_mapper/kb/__init__.py similarity index 100% rename from src/kb/__init__.py rename to src/knowledge_mapper/kb/__init__.py diff --git a/src/kb/builder.py b/src/knowledge_mapper/kb/builder.py similarity index 100% rename from src/kb/builder.py rename to src/knowledge_mapper/kb/builder.py diff --git a/src/kb/knowledge_base.py b/src/knowledge_mapper/kb/knowledge_base.py similarity index 96% rename from src/kb/knowledge_base.py rename to src/knowledge_mapper/kb/knowledge_base.py index 2e0cbfd..fff75b0 100644 --- a/src/kb/knowledge_base.py +++ b/src/knowledge_mapper/kb/knowledge_base.py @@ -407,7 +407,7 @@ def call(self, binding_set: BindingSet, ki_name: str) -> BindingSet: def post( self, binding_set: Sequence[BindingModel] | BindingSet, ki_name: str ) -> Sequence[BindingModel] | BindingSet: - """... + """Invoke a POST KI by its name. Raises: KeyError: If ``ki_name`` is not found in the local KI registry. @@ -527,10 +527,22 @@ def start_handling_loop(self, loops: int | None = None) -> None: match poll_result, maybe_handle_request: case PollResult.HANDLE, _: assert maybe_handle_request is not None - self.call( + name = next( + ki.info.name + for ki in self.ki_registry.values() + if ki.info.id == maybe_handle_request.knowledge_interaction_id + ) + result_binding_set = self.call( maybe_handle_request.binding_set, - maybe_handle_request.knowledge_interaction_id, + name, + ) + self.client.post_handle_response( + kb_id=self.info.id, + ki_id=maybe_handle_request.knowledge_interaction_id, + handle_request_id=maybe_handle_request.handle_request_id, + binding_set=result_binding_set, ) + case PollResult.REPOLL, None: continue case PollResult.EXIT, None: diff --git a/src/ke/__init__.py b/src/knowledge_mapper/ke/__init__.py similarity index 100% rename from src/ke/__init__.py rename to src/knowledge_mapper/ke/__init__.py diff --git a/src/ke/client.py b/src/knowledge_mapper/ke/client.py similarity index 95% rename from src/ke/client.py rename to src/knowledge_mapper/ke/client.py index 4b85fff..7a018b3 100644 --- a/src/ke/client.py +++ b/src/knowledge_mapper/ke/client.py @@ -33,7 +33,7 @@ class HandleRequest(BaseModel): ) knowledge_interaction_id: str - handle_request_id: str + handle_request_id: int binding_set: list[dict[str, str]] requesting_knowledge_base_id: str @@ -131,6 +131,19 @@ def poll_ki_call(self, kb_id: str) -> tuple[PollResult, HandleRequest | None]: """ ... + def post_handle_response( + self, kb_id: str, ki_id: str, handle_request_id: int, binding_set: BindingSet + ) -> None: + """Post the response to a KI call that was received via ``poll_ki_call``. + + Raises: + SmartConnectorNotFoundError: If no smart connector exists for the given KB + ID. + UnexpectedHttpResponseError: If the KE runtime returns an unexpected HTTP + response. + """ + ... + def ask( self, kb_id: str, @@ -308,7 +321,7 @@ def poll_ki_call(self, kb_id: str) -> tuple[PollResult, HandleRequest | None]: raise UnexpectedHttpResponseError(response) def post_handle_response( - self, kb_id: str, ki_id: str, handle_request_id: str, binding_set: BindingSet + self, kb_id: str, ki_id: str, handle_request_id: int, binding_set: BindingSet ) -> None: logger.debug("Posting handle response for KI call.") response = requests.post( diff --git a/src/ke/errors.py b/src/knowledge_mapper/ke/errors.py similarity index 100% rename from src/ke/errors.py rename to src/knowledge_mapper/ke/errors.py diff --git a/src/ke/models.py b/src/knowledge_mapper/ke/models.py similarity index 100% rename from src/ke/models.py rename to src/knowledge_mapper/ke/models.py diff --git a/src/ke/testing/__init__.py b/src/knowledge_mapper/ke/testing/__init__.py similarity index 100% rename from src/ke/testing/__init__.py rename to src/knowledge_mapper/ke/testing/__init__.py diff --git a/src/ke/testing/fake_client.py b/src/knowledge_mapper/ke/testing/fake_client.py similarity index 97% rename from src/ke/testing/fake_client.py rename to src/knowledge_mapper/ke/testing/fake_client.py index 5a778c1..7143de1 100644 --- a/src/ke/testing/fake_client.py +++ b/src/knowledge_mapper/ke/testing/fake_client.py @@ -2,8 +2,8 @@ from datetime import UTC, datetime -from src.ke.client import ClientProtocol, PollResult -from src.ke.models import ( +from src.knowledge_mapper.ke.client import ClientProtocol, PollResult +from src.knowledge_mapper.ke.models import ( AskResult, BindingSet, ExchangeInfo, diff --git a/src/knowledge_interaction.py b/src/knowledge_mapper/knowledge_interaction.py similarity index 98% rename from src/knowledge_interaction.py rename to src/knowledge_mapper/knowledge_interaction.py index c9ce89b..0e2eccc 100644 --- a/src/knowledge_interaction.py +++ b/src/knowledge_mapper/knowledge_interaction.py @@ -4,7 +4,7 @@ from enum import StrEnum from typing import Any, Concatenate, get_args -from src.ke.models import BindingModel, BindingSet, KiTypes, KnowledgeInteractionInfo +from .ke.models import BindingModel, BindingSet, KiTypes, KnowledgeInteractionInfo type Handler[B, **P] = Callable[ Concatenate[B, KnowledgeInteractionInfo, P], diff --git a/src/legacy/__main__.py b/src/knowledge_mapper/legacy/__main__.py similarity index 97% rename from src/legacy/__main__.py rename to src/knowledge_mapper/legacy/__main__.py index ce7bc4f..2004747 100644 --- a/src/legacy/__main__.py +++ b/src/knowledge_mapper/legacy/__main__.py @@ -7,7 +7,7 @@ import time import signal import requests.exceptions -from src.kb.knowledge_base import KnowledgeBaseUnregistered +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBaseUnregistered from src.knowledge_mapper import KnowledgeMapper from src.auth.sql_auth import SqlAuth @@ -52,7 +52,7 @@ def test_data_source(data_source: DataSource): def main(): - from . import __version__ + from ...legacy import __version__ log.info(f"Running Knowledge Mapper {__version__}") parser = argparse.ArgumentParser( @@ -62,7 +62,7 @@ def main(): parser.add_argument("--wizard", action=argparse.BooleanOptionalAction) args = parser.parse_args() if args.wizard: - from . import wizard_mapper + from ...legacy import wizard_mapper wizard_mapper.start() exit() diff --git a/src/legacy/auth/__init__.py b/src/knowledge_mapper/legacy/auth/__init__.py similarity index 100% rename from src/legacy/auth/__init__.py rename to src/knowledge_mapper/legacy/auth/__init__.py diff --git a/src/legacy/auth/base_auth.py b/src/knowledge_mapper/legacy/auth/base_auth.py similarity index 100% rename from src/legacy/auth/base_auth.py rename to src/knowledge_mapper/legacy/auth/base_auth.py diff --git a/src/legacy/auth/sql_auth.py b/src/knowledge_mapper/legacy/auth/sql_auth.py similarity index 100% rename from src/legacy/auth/sql_auth.py rename to src/knowledge_mapper/legacy/auth/sql_auth.py diff --git a/src/legacy/auth/static_auth.py b/src/knowledge_mapper/legacy/auth/static_auth.py similarity index 100% rename from src/legacy/auth/static_auth.py rename to src/knowledge_mapper/legacy/auth/static_auth.py diff --git a/src/legacy/data_source.py b/src/knowledge_mapper/legacy/data_source.py similarity index 83% rename from src/legacy/data_source.py rename to src/knowledge_mapper/legacy/data_source.py index 90fab37..9d83ec9 100644 --- a/src/legacy/data_source.py +++ b/src/knowledge_mapper/legacy/data_source.py @@ -1,4 +1,4 @@ -from src.kb.knowledge_base import KnowledgeBase +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase class DataSource: def test(self): diff --git a/src/legacy/knowledge_base.py b/src/knowledge_mapper/legacy/knowledge_base.py similarity index 99% rename from src/legacy/knowledge_base.py rename to src/knowledge_mapper/legacy/knowledge_base.py index bb3e8f8..fa547f8 100644 --- a/src/legacy/knowledge_base.py +++ b/src/knowledge_mapper/legacy/knowledge_base.py @@ -3,7 +3,7 @@ import logging as log import requests -import src.knowledge_interaction as knowledge_interaction +import src.knowledge_mapper.knowledge_interaction as knowledge_interaction from src.tke_exceptions import UnexpectedHttpResponseError diff --git a/src/legacy/knowledge_interaction.py b/src/knowledge_mapper/legacy/knowledge_interaction.py similarity index 100% rename from src/legacy/knowledge_interaction.py rename to src/knowledge_mapper/legacy/knowledge_interaction.py diff --git a/src/legacy/knowledge_mapper.py b/src/knowledge_mapper/legacy/knowledge_mapper.py similarity index 97% rename from src/legacy/knowledge_mapper.py rename to src/knowledge_mapper/legacy/knowledge_mapper.py index e165ded..8aac732 100644 --- a/src/legacy/knowledge_mapper.py +++ b/src/knowledge_mapper/legacy/knowledge_mapper.py @@ -2,10 +2,10 @@ import logging as log from src.auth.base_auth import BaseAuth from src.utils import extract_variables -from src.kb.knowledge_base import ( +from src.knowledge_mapper.kb.knowledge_base import ( KnowledgeBaseRegistrationRequest, ) -from src.knowledge_interaction import ( +from src.knowledge_mapper.knowledge_interaction import ( AnswerKnowledgeInteractionRegistrationRequest, AskKnowledgeInteractionRegistrationRequest, PostKnowledgeInteractionRegistrationRequest, diff --git a/src/legacy/sparql_source.py b/src/knowledge_mapper/legacy/sparql_source.py similarity index 100% rename from src/legacy/sparql_source.py rename to src/knowledge_mapper/legacy/sparql_source.py diff --git a/src/legacy/sql_source.py b/src/knowledge_mapper/legacy/sql_source.py similarity index 100% rename from src/legacy/sql_source.py rename to src/knowledge_mapper/legacy/sql_source.py diff --git a/src/legacy/tests/__init__.py b/src/knowledge_mapper/legacy/tests/__init__.py similarity index 100% rename from src/legacy/tests/__init__.py rename to src/knowledge_mapper/legacy/tests/__init__.py diff --git a/src/legacy/tests/legacy_test_tke_client.py b/src/knowledge_mapper/legacy/tests/legacy_test_tke_client.py similarity index 97% rename from src/legacy/tests/legacy_test_tke_client.py rename to src/knowledge_mapper/legacy/tests/legacy_test_tke_client.py index b4e6b0a..930c9b0 100644 --- a/src/legacy/tests/legacy_test_tke_client.py +++ b/src/knowledge_mapper/legacy/tests/legacy_test_tke_client.py @@ -1,5 +1,5 @@ -import src.kb.knowledge_base as tke_kb -import src.knowledge_interaction as tke_ki +import src.knowledge_mapper.kb.knowledge_base as tke_kb +import src.knowledge_mapper.knowledge_interaction as tke_ki import src.tke_client as tke import pytest import asyncio diff --git a/src/legacy/tke_client.py b/src/knowledge_mapper/legacy/tke_client.py similarity index 97% rename from src/legacy/tke_client.py rename to src/knowledge_mapper/legacy/tke_client.py index 811f9d2..5c5e797 100644 --- a/src/legacy/tke_client.py +++ b/src/knowledge_mapper/legacy/tke_client.py @@ -3,7 +3,7 @@ import logging as log import time -import src.kb.knowledge_base as knowledge_base +import src.knowledge_mapper.kb.knowledge_base as knowledge_base from src.tke_exceptions import UnexpectedHttpResponseError diff --git a/src/legacy/tke_exceptions.py b/src/knowledge_mapper/legacy/tke_exceptions.py similarity index 100% rename from src/legacy/tke_exceptions.py rename to src/knowledge_mapper/legacy/tke_exceptions.py diff --git a/src/legacy/utils.py b/src/knowledge_mapper/legacy/utils.py similarity index 100% rename from src/legacy/utils.py rename to src/knowledge_mapper/legacy/utils.py diff --git a/src/legacy/wizard_mapper.py b/src/knowledge_mapper/legacy/wizard_mapper.py similarity index 99% rename from src/legacy/wizard_mapper.py rename to src/knowledge_mapper/legacy/wizard_mapper.py index 750395c..d8dae78 100644 --- a/src/legacy/wizard_mapper.py +++ b/src/knowledge_mapper/legacy/wizard_mapper.py @@ -3,7 +3,7 @@ import os import requests -from src.kb.knowledge_base import ( +from src.knowledge_mapper.kb.knowledge_base import ( KnowledgeEngineTerminated, ) from src.utils import match_bindings diff --git a/src/settings.py b/src/knowledge_mapper/settings.py similarity index 97% rename from src/settings.py rename to src/knowledge_mapper/settings.py index b705d61..e155933 100644 --- a/src/settings.py +++ b/src/knowledge_mapper/settings.py @@ -7,7 +7,7 @@ YamlConfigSettingsSource, ) -from src.ke.models import KnowledgeBaseInfo, KnowledgeInteractionInfo +from .ke.models import KnowledgeBaseInfo, KnowledgeInteractionInfo class KnowledgeBaseSettings(BaseSettings): diff --git a/tests/configuration/test_configuration.py b/tests/configuration/test_configuration.py index dc5063c..0dfcc14 100644 --- a/tests/configuration/test_configuration.py +++ b/tests/configuration/test_configuration.py @@ -1,6 +1,6 @@ from pydantic_settings import SettingsConfigDict -from src import KnowledgeBase, KnowledgeBaseSettings +from src.knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings def test_basic_configuration(): diff --git a/tests/test_ask_and_post.py b/tests/test_ask_and_post.py index abc078b..9a76ad4 100644 --- a/tests/test_ask_and_post.py +++ b/tests/test_ask_and_post.py @@ -1,9 +1,9 @@ import pytest from rdflib import URIRef -from src import KnowledgeBase -from src.ke.models import BindingModel, Literal, Uri -from src.ke.testing import TestClient +from src.knowledge_mapper import KnowledgeBase +from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri +from src.knowledge_mapper.ke.testing import TestClient @pytest.fixture @@ -28,8 +28,8 @@ def test_ask_interaction_no_binding_models(kb: KnowledgeBase, client: TestClient kb.ask_ki( name="ask-ki", graph_pattern=""" - ?person a ex:Person . - ex:hasName ?name . + ?person a ex:Person ; + ex:hasName ?name ; ex:hasAge ?age . """, prefixes={"ex": "http://example.org/test#"}, @@ -74,8 +74,8 @@ class PersonBinding(BindingModel): kb.ask_ki( name="ask-ki", graph_pattern=""" - ?person a ex:Person . - ex:hasName ?name . + ?person a ex:Person ; + ex:hasName ?name ; ex:hasAge ?age . """, binding_model=PersonBinding, @@ -88,8 +88,8 @@ class PersonBinding(BindingModel): binding_set=[ { "person": "", - "name": '"Alice"^^xsd:string', - "age": '"30"^^xsd:integer', + "name": "\"Alice\"^^xsd:string", + "age": "\"30\"^^xsd:integer", } ], ) @@ -125,7 +125,7 @@ def test_post_measurement_no_binding_models(kb: KnowledgeBase, client: TestClien """, result_graph_pattern=""" ?measurement a ex:Measurement ; - ex:storedBy ?kb ; + ex:storedBy ?kb . """, prefixes={"ex": "http://example.org/test#"}, defer_ke_registration=False, @@ -182,7 +182,7 @@ class ResultBinding(BindingModel): """, result_graph_pattern=""" ?measurement a ex:Measurement ; - ex:storedBy ?kb ; + ex:storedBy ?kb . """, prefixes={"ex": "http://example.org/test#"}, argument_binding_model=MeasurementBinding, diff --git a/tests/test_bindings.py b/tests/test_bindings.py index 9c43560..03aa681 100644 --- a/tests/test_bindings.py +++ b/tests/test_bindings.py @@ -1,7 +1,7 @@ from rdflib import Literal as RDFLiteral from rdflib import URIRef -from src.ke.models import ( +from src.knowledge_mapper.ke.models import ( BindingModel, Literal, Uri, diff --git a/tests/test_client.py b/tests/test_client.py index f26325c..6aef0c0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -2,8 +2,8 @@ import pytest -from src.ke import Client -from src.ke.models import ( +from src.knowledge_mapper.ke import Client +from src.knowledge_mapper.ke.models import ( AskAnswerInteractionInfo, KnowledgeBaseInfo, KnowledgeInteractionInfo, diff --git a/tests/test_dependency_injection.py b/tests/test_dependency_injection.py index 32c5274..182c2cf 100644 --- a/tests/test_dependency_injection.py +++ b/tests/test_dependency_injection.py @@ -2,9 +2,9 @@ import pytest -from src import Depends -from src.kb.knowledge_base import KnowledgeBase -from src.ke.models import BindingSet +from src.knowledge_mapper import Depends +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase +from src.knowledge_mapper.ke.models import BindingSet @pytest.fixture diff --git a/tests/test_handlers.py b/tests/test_handlers.py index 5af512d..ab28194 100644 --- a/tests/test_handlers.py +++ b/tests/test_handlers.py @@ -1,8 +1,8 @@ import pytest from rdflib import URIRef -from src.kb.knowledge_base import KnowledgeBase -from src.ke.models import BindingModel, BindingSet, Uri +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase +from src.knowledge_mapper.ke.models import BindingModel, BindingSet, Uri @pytest.fixture diff --git a/tests/test_kb_lifespan.py b/tests/test_kb_lifespan.py index ce565a5..aafdfa6 100644 --- a/tests/test_kb_lifespan.py +++ b/tests/test_kb_lifespan.py @@ -2,10 +2,10 @@ import pytest -from src import KnowledgeBase -from src.kb.knowledge_base import KnowledgeBaseState -from src.ke.errors import KnowledgeEngineNotAvailableError -from src.ke.testing import TestClient +from src.knowledge_mapper import KnowledgeBase +from src.knowledge_mapper.kb.knowledge_base import KnowledgeBaseState +from src.knowledge_mapper.ke.errors import KnowledgeEngineNotAvailableError +from src.knowledge_mapper.ke.testing import TestClient @pytest.fixture diff --git a/tests/test_ki_registration.py b/tests/test_ki_registration.py index 7edfb94..84a950d 100644 --- a/tests/test_ki_registration.py +++ b/tests/test_ki_registration.py @@ -1,14 +1,14 @@ import pytest -from src import KnowledgeBase -from src.ke.models import ( +from src.knowledge_mapper import KnowledgeBase +from src.knowledge_mapper.ke.models import ( AskAnswerInteractionInfo, BindingSet, KiTypes, KnowledgeInteractionInfo, ) -from src.ke.testing import TestClient -from src.knowledge_interaction import ( +from src.knowledge_mapper.ke.testing import TestClient +from src.knowledge_mapper.knowledge_interaction import ( KnowledgeInteractionContext, KnowledgeInteractionStatus, ) diff --git a/tests/test_knowledge_base_builder.py b/tests/test_knowledge_base_builder.py index 0cf6ab8..07d4273 100644 --- a/tests/test_knowledge_base_builder.py +++ b/tests/test_knowledge_base_builder.py @@ -1,7 +1,7 @@ import pytest -from src import KnowledgeBase, KnowledgeBaseSettings -from src.ke.models import ( +from src.knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings +from src.knowledge_mapper.ke.models import ( AskAnswerInteractionInfo, BindingSet, KiTypes, From 4a3015a26228bc1e13d7c3ef5d3004956b5576e8 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 20 May 2026 18:07:30 +0200 Subject: [PATCH 2/6] Improve imports and reorder examples with README --- README.md | 4 + examples/{basic.py => 01-basic.py} | 2 +- ...binding_models.py => 02-binding_models.py} | 4 +- ...k_interaction.py => 03-ask_interaction.py} | 3 +- ..._measurement.py => 04-post_measurement.py} | 7 +- .../05-custom_settings.py} | 8 +- .../settings.yaml | 0 ...njection.py => 06-dependency_injection.py} | 10 ++- examples/{testing => 07-testing}/kb.py | 3 +- examples/{testing => 07-testing}/test_kb.py | 10 +-- examples/README.md | 84 +++++++++++++++++++ pyproject.toml | 2 +- src/knowledge_mapper/__init__.py | 2 +- .../{ke => }/testing/__init__.py | 0 .../{ke => }/testing/fake_client.py | 0 tests/test_ask_and_post.py | 6 +- tests/test_kb_lifespan.py | 2 +- tests/test_ki_registration.py | 2 +- 18 files changed, 120 insertions(+), 29 deletions(-) rename examples/{basic.py => 01-basic.py} (93%) rename examples/{binding_models.py => 02-binding_models.py} (95%) rename examples/{ask_interaction.py => 03-ask_interaction.py} (90%) rename examples/{post_measurement.py => 04-post_measurement.py} (92%) rename examples/{custom-settings/custom_settings.py => 05-custom-settings/05-custom_settings.py} (96%) rename examples/{custom-settings => 05-custom-settings}/settings.yaml (100%) rename examples/{dependency_injection.py => 06-dependency_injection.py} (97%) rename examples/{testing => 07-testing}/kb.py (95%) rename examples/{testing => 07-testing}/test_kb.py (94%) create mode 100644 examples/README.md rename src/knowledge_mapper/{ke => }/testing/__init__.py (100%) rename src/knowledge_mapper/{ke => }/testing/fake_client.py (100%) diff --git a/README.md b/README.md index d333b99..ecf8e79 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,10 @@ The following diagram shows where the Knowledge Mapper operates within the Knowl ![architecture diagram](./docs/img/architecture.png) +## Getting Started with Examples + +The easiest way to learn the Knowledge Mapper is by exploring the [examples](./examples/README.md). They demonstrate key features like creating knowledge bases, defining knowledge interactions, using binding models, dependency injection, and testing. Each example includes inline comments and can be run locally with a Knowledge Engine instance. See the [examples README](./examples/README.md) for setup instructions and an overview of all available examples. + ## How do I use it? 1. Install `knowledge_mapper` in a Python environment with `pip`: diff --git a/examples/basic.py b/examples/01-basic.py similarity index 93% rename from examples/basic.py rename to examples/01-basic.py index 702ae7e..e6d2235 100644 --- a/examples/basic.py +++ b/examples/01-basic.py @@ -1,6 +1,6 @@ from shared import get_example_logger -from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase +from knowledge_mapper import KnowledgeBase EXAMPLE_NAME = "basic" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/binding_models.py b/examples/02-binding_models.py similarity index 95% rename from examples/binding_models.py rename to examples/02-binding_models.py index 1d31aea..b4a8611 100644 --- a/examples/binding_models.py +++ b/examples/02-binding_models.py @@ -3,10 +3,10 @@ from rdflib import URIRef from shared import get_example_logger -from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase -from src.knowledge_mapper.ke.models import ( +from knowledge_mapper import ( BindingModel, BindingSet, + KnowledgeBase, KnowledgeInteractionInfo, Literal, Uri, diff --git a/examples/ask_interaction.py b/examples/03-ask_interaction.py similarity index 90% rename from examples/ask_interaction.py rename to examples/03-ask_interaction.py index 5390fef..e337a59 100644 --- a/examples/ask_interaction.py +++ b/examples/03-ask_interaction.py @@ -1,7 +1,6 @@ from shared import get_example_logger -from src.knowledge_mapper import KnowledgeBase -from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri +from knowledge_mapper import BindingModel, KnowledgeBase, Literal, Uri EXAMPLE_NAME = "ask-interaction" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/post_measurement.py b/examples/04-post_measurement.py similarity index 92% rename from examples/post_measurement.py rename to examples/04-post_measurement.py index 2141fa4..e2aa59c 100644 --- a/examples/post_measurement.py +++ b/examples/04-post_measurement.py @@ -5,12 +5,7 @@ from rdflib import URIRef from shared import get_example_logger -from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase -from src.knowledge_mapper.ke.models import ( - BindingModel, - Literal, - Uri, -) +from knowledge_mapper import BindingModel, KnowledgeBase, Literal, Uri EXAMPLE_NAME = "post-measurement" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/custom-settings/custom_settings.py b/examples/05-custom-settings/05-custom_settings.py similarity index 96% rename from examples/custom-settings/custom_settings.py rename to examples/05-custom-settings/05-custom_settings.py index df39232..18d5477 100644 --- a/examples/custom-settings/custom_settings.py +++ b/examples/05-custom-settings/05-custom_settings.py @@ -26,8 +26,12 @@ from pydantic_settings import CliSettingsSource, SettingsConfigDict from shared import get_example_logger -from src.knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings -from src.knowledge_mapper.ke.models import BindingSet, KnowledgeInteractionInfo +from knowledge_mapper import ( + BindingSet, + KnowledgeBase, + KnowledgeBaseSettings, + KnowledgeInteractionInfo, +) EXAMPLE_NAME = "custom-settings" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/custom-settings/settings.yaml b/examples/05-custom-settings/settings.yaml similarity index 100% rename from examples/custom-settings/settings.yaml rename to examples/05-custom-settings/settings.yaml diff --git a/examples/dependency_injection.py b/examples/06-dependency_injection.py similarity index 97% rename from examples/dependency_injection.py rename to examples/06-dependency_injection.py index 9bf04e1..3403c08 100644 --- a/examples/dependency_injection.py +++ b/examples/06-dependency_injection.py @@ -26,8 +26,14 @@ from shared import get_example_logger -from src.knowledge_mapper import Depends, KnowledgeBase -from src.knowledge_mapper.ke.models import BindingModel, KnowledgeInteractionInfo, Literal, Uri +from knowledge_mapper import ( + BindingModel, + Depends, + KnowledgeBase, + KnowledgeInteractionInfo, + Literal, + Uri, +) EXAMPLE_NAME = "dependency-injection" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/testing/kb.py b/examples/07-testing/kb.py similarity index 95% rename from examples/testing/kb.py rename to examples/07-testing/kb.py index 370471f..c759549 100644 --- a/examples/testing/kb.py +++ b/examples/07-testing/kb.py @@ -9,8 +9,7 @@ from shared import get_example_logger -from src.knowledge_mapper import KnowledgeBase -from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri +from knowledge_mapper import BindingModel, KnowledgeBase, Literal, Uri EXAMPLE_NAME = "testing" logger = get_example_logger(EXAMPLE_NAME) diff --git a/examples/testing/test_kb.py b/examples/07-testing/test_kb.py similarity index 94% rename from examples/testing/test_kb.py rename to examples/07-testing/test_kb.py index bd0acc9..9da0252 100644 --- a/examples/testing/test_kb.py +++ b/examples/07-testing/test_kb.py @@ -1,7 +1,7 @@ import pytest from rdflib import URIRef -from src.knowledge_mapper.ke.testing import TestClient +from knowledge_mapper.testing import TestClient # Import the Knowledge Base that you would like to test, along with any relevant binding # models. @@ -40,7 +40,7 @@ def test_ask_ki_with_result(client: TestClient): [ { "s": "", - "value": "\"test value\"", + "value": '"test value"', } ], ) @@ -48,7 +48,7 @@ def test_ask_ki_with_result(client: TestClient): assert result_binding_set == [ { "s": "", - "value": "\"test value\"", + "value": '"test value"', } ] @@ -62,7 +62,7 @@ def test_ask_ki_with_binding_model(client: TestClient): [ { "s": "", - "value": "\"test value\"", + "value": '"test value"', } ], ) @@ -98,7 +98,7 @@ def test_function_containing_ask(client: TestClient): ) result = ask_for_values_of_subject("Subject") - assert result == ["\"test value\""] + assert result == ['"test value"'] # Similar approaches can be taken for POST interactions. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..7209927 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,84 @@ +# Knowledge Mapper Examples + +The best way to get started with the Knowledge Mapper is by exploring the examples in this folder. Each example demonstrates a specific feature or pattern with detailed comments in the code. + +## Overview + +| Example | Description | +|---------|-------------| +| **01-basic.py** | A minimal knowledge base with a simple answer knowledge interaction | +| **02-binding_models.py** | Demonstrates using Pydantic-style binding models for type-safe bindings | +| **03-ask_interaction.py** | Shows how to handle ASK knowledge interactions | +| **04-post_measurement.py** | Demonstrates POST interactions for ingesting measurements or data | +| **05-custom-settings/** | Shows how to use custom settings to configure your knowledge mapper | +| **06-dependency_injection.py** | Uses dependency injection to inject resources like configs or database connections | +| **07-testing/** | Demonstrates how to write tests for your knowledge base using the fake client | + +## Prerequisites + +Before running the examples, you need to have a Knowledge Engine instance running. The examples expect it to be available at `http://localhost:8280/rest`. + +### Starting the Knowledge Engine + +Use the provided Docker Compose file to start a Knowledge Engine instance: + +```bash +docker-compose up -d +``` + +This starts the Knowledge Engine and related services in the background. To stop them: + +```bash +docker-compose down +``` + +## Running Examples + +### Installation + +First, install the knowledge mapper in your Python environment: + +```bash +pip install knowledge_mapper +``` + +Or, if you're developing locally, install it in editable mode from the project root: + +```bash +pip install -e . +``` + +### Running a Single Example + +To run an example, navigate to the examples folder and execute the Python script: + +```bash +cd examples +python 01-basic.py +``` + +Most examples will start the knowledge mapper and connect to the Knowledge Engine. Press `Ctrl+C` to stop. + +### Running Tests + +The `07-testing/` example includes test examples. Run them with: + +```bash +python -m pytest 07-testing/ +``` + +## Next Steps + +1. Start with **01-basic.py** to understand the minimal setup +2. Explore **02-binding_models.py** to learn about type-safe bindings +3. Look at **03-ask_interaction.py** and **04-post_measurement.py** to see different KI types +4. Check **05-custom-settings/** for configuration patterns +5. Study **06-dependency_injection.py** to see how to manage dependencies +6. Review **07-testing/** to learn testing strategies + +## Tips + +- Each example has inline comments explaining the code +- The `shared.py` module contains utilities used by examples (like logging setup) +- To see detailed logs, check the output when running examples +- The examples use `http://localhost:8280/rest` as the default Knowledge Engine endpoint diff --git a/pyproject.toml b/pyproject.toml index c81e5fd..f7f60b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ addopts = [ exclude = [ ".pytest_cache", ".venv", - "./src/legacy", + "./src/knowledge_mapper/legacy", "./examples/legacy", ] line-length = 88 diff --git a/src/knowledge_mapper/__init__.py b/src/knowledge_mapper/__init__.py index 51631d4..9fc20e7 100644 --- a/src/knowledge_mapper/__init__.py +++ b/src/knowledge_mapper/__init__.py @@ -3,7 +3,7 @@ from .dependency_injection import Depends from .kb.builder import KnowledgeBaseBuilder from .kb.knowledge_base import KnowledgeBase -from .ke.models import BindingModel, Literal, Uri +from .ke.models import BindingModel, BindingSet, KnowledgeInteractionInfo, Literal, Uri from .settings import KnowledgeBaseSettings __version__ = "0.1.0a0" diff --git a/src/knowledge_mapper/ke/testing/__init__.py b/src/knowledge_mapper/testing/__init__.py similarity index 100% rename from src/knowledge_mapper/ke/testing/__init__.py rename to src/knowledge_mapper/testing/__init__.py diff --git a/src/knowledge_mapper/ke/testing/fake_client.py b/src/knowledge_mapper/testing/fake_client.py similarity index 100% rename from src/knowledge_mapper/ke/testing/fake_client.py rename to src/knowledge_mapper/testing/fake_client.py diff --git a/tests/test_ask_and_post.py b/tests/test_ask_and_post.py index 9a76ad4..56476d6 100644 --- a/tests/test_ask_and_post.py +++ b/tests/test_ask_and_post.py @@ -1,9 +1,9 @@ import pytest from rdflib import URIRef +from src.knowledge_mapper.ke.testing import TestClient from src.knowledge_mapper import KnowledgeBase from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri -from src.knowledge_mapper.ke.testing import TestClient @pytest.fixture @@ -88,8 +88,8 @@ class PersonBinding(BindingModel): binding_set=[ { "person": "", - "name": "\"Alice\"^^xsd:string", - "age": "\"30\"^^xsd:integer", + "name": '"Alice"^^xsd:string', + "age": '"30"^^xsd:integer', } ], ) diff --git a/tests/test_kb_lifespan.py b/tests/test_kb_lifespan.py index aafdfa6..df4efac 100644 --- a/tests/test_kb_lifespan.py +++ b/tests/test_kb_lifespan.py @@ -5,7 +5,7 @@ from src.knowledge_mapper import KnowledgeBase from src.knowledge_mapper.kb.knowledge_base import KnowledgeBaseState from src.knowledge_mapper.ke.errors import KnowledgeEngineNotAvailableError -from src.knowledge_mapper.ke.testing import TestClient +from src.knowledge_mapper.testing import TestClient @pytest.fixture diff --git a/tests/test_ki_registration.py b/tests/test_ki_registration.py index 84a950d..3f2d075 100644 --- a/tests/test_ki_registration.py +++ b/tests/test_ki_registration.py @@ -7,11 +7,11 @@ KiTypes, KnowledgeInteractionInfo, ) -from src.knowledge_mapper.ke.testing import TestClient from src.knowledge_mapper.knowledge_interaction import ( KnowledgeInteractionContext, KnowledgeInteractionStatus, ) +from src.knowledge_mapper.testing import TestClient # Not a fixture as a fresh KB instance is needed for each test. From 02f3956470a4c48331aef043d71d8d66ba2deff4 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 21 May 2026 17:47:34 +0200 Subject: [PATCH 3/6] Add comments to examples --- examples/01-basic.py | 10 ++++++++++ examples/02-binding_models.py | 11 +++++++++++ examples/03-ask_interaction.py | 9 +++++++++ examples/04-post_measurement.py | 10 ++++++++++ 4 files changed, 40 insertions(+) diff --git a/examples/01-basic.py b/examples/01-basic.py index e6d2235..eb4acf6 100644 --- a/examples/01-basic.py +++ b/examples/01-basic.py @@ -1,3 +1,9 @@ +"""Basic example: register a simple ANSWER KI and handle incoming requests. + +This is the smallest runnable example and a good starting point to understand the +KnowledgeBase lifecycle: connect -> register -> unregister. +""" + from shared import get_example_logger from knowledge_mapper import KnowledgeBase @@ -13,6 +19,8 @@ ) +# Decorate a function as an ANSWER KI handler. +# The incoming bindings match the graph pattern variables. @kb.answer_ki( name="example-answer-ki", graph_pattern=""" @@ -23,10 +31,12 @@ ) def example_answer_ki(binding_set, info): logger.info("Handling a call to the example answer KI.") + # Echo incoming bindings to demonstrate a minimal handler. return binding_set if __name__ == "__main__": + # Connect to the KE, then register and unregister this KB. kb.connect() kb.register() logger.info("Registered a Knowledge Base in the basic example!") diff --git a/examples/02-binding_models.py b/examples/02-binding_models.py index b4a8611..93fa179 100644 --- a/examples/02-binding_models.py +++ b/examples/02-binding_models.py @@ -1,3 +1,10 @@ +"""Binding models example: compare typed vs raw binding handling. + +This example registers two ANSWER KIs with the same pattern: +1. A typed handler using a BindingModel class. +2. A raw handler using plain BindingSet dictionaries. +""" + from datetime import datetime from rdflib import URIRef @@ -23,6 +30,7 @@ ) +# Define strongly-typed bindings for variables in the graph pattern. class CurrentTemperatureBinding(BindingModel): measurement: Uri value: Literal[float] @@ -47,6 +55,7 @@ def binding_models_answer_ki( f"Handling a call to the binding models answer KI with incoming bindings: " f"{binding_set}" ) + # Return a single current measurement using typed values. return [ CurrentTemperatureBinding( measurement=URIRef( @@ -76,6 +85,7 @@ def binding_models_raw_answer_ki( f"Handling a call to the binding models raw answer KI with incoming bindings: " f"{binding_set}" ) + # Return the same shape as above, but manually encoded as raw strings. return [ { "measurement": "", @@ -87,6 +97,7 @@ def binding_models_raw_answer_ki( if __name__ == "__main__": + # Register both KIs, then cleanly unregister. kb.connect() kb.register() logger.info("Registered the binding models example KB!") diff --git a/examples/03-ask_interaction.py b/examples/03-ask_interaction.py index e337a59..d73792e 100644 --- a/examples/03-ask_interaction.py +++ b/examples/03-ask_interaction.py @@ -1,3 +1,9 @@ +"""ASK interaction example. + +Registers an ASK KI and executes it from this script to show how query bindings +and typed results work end-to-end. +""" + from shared import get_example_logger from knowledge_mapper import BindingModel, KnowledgeBase, Literal, Uri @@ -13,12 +19,14 @@ ) +# Binding model for variables used in the ASK graph pattern. class PersonBinding(BindingModel): person: Uri name: Literal[str] age: Literal[int] +# Register an ASK KI that can be called via kb.ask(...). kb.ask_ki( name="ask-ki", graph_pattern=""" @@ -31,6 +39,7 @@ class PersonBinding(BindingModel): ) if __name__ == "__main__": + # Register this KB, execute one ASK request, and then unregister. kb.register() logger.info("KB registered.") result = kb.ask( diff --git a/examples/04-post_measurement.py b/examples/04-post_measurement.py index e2aa59c..96f9d7f 100644 --- a/examples/04-post_measurement.py +++ b/examples/04-post_measurement.py @@ -1,3 +1,9 @@ +"""POST interaction example for publishing a measurement. + +This script registers a POST KI, then posts one measurement binding set and logs +the result bindings returned by the KE. +""" + import time from datetime import datetime from uuid import uuid4 @@ -19,6 +25,7 @@ ) +# Argument bindings for the POST interaction input pattern. class MeasurementBinding(BindingModel): measurement: Uri value: Literal[float] @@ -26,11 +33,13 @@ class MeasurementBinding(BindingModel): time: Literal[datetime] +# Result bindings for the POST interaction result pattern. class ResultBinding(BindingModel): measurement: Uri kb: Uri +# Register a POST KI with separate argument and result graph patterns. kb.post_ki( name="post-measurement-ki", argument_graph_pattern=""" @@ -50,6 +59,7 @@ class ResultBinding(BindingModel): if __name__ == "__main__": + # Register KB, wait briefly for manual testing, then execute one POST. kb.register() logger.info("KB registered.") time.sleep( From f33399fa9b3cbe6f54b118082586ec22132bb548 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 21 May 2026 17:53:25 +0200 Subject: [PATCH 4/6] Reformat --- tests/test_ask_and_post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ask_and_post.py b/tests/test_ask_and_post.py index 56476d6..7d2fc4e 100644 --- a/tests/test_ask_and_post.py +++ b/tests/test_ask_and_post.py @@ -1,9 +1,9 @@ import pytest from rdflib import URIRef -from src.knowledge_mapper.ke.testing import TestClient from src.knowledge_mapper import KnowledgeBase from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri +from src.knowledge_mapper.ke.testing import TestClient @pytest.fixture From df0d82074839a9582e5c0fdf260951f22a5eb035 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 27 May 2026 10:55:33 +0200 Subject: [PATCH 5/6] Fix test imports --- examples/07-testing/kb.py | 12 ++++++------ examples/07-testing/test_kb.py | 10 +++++----- pyproject.toml | 3 +++ src/knowledge_mapper/testing/fake_client.py | 4 ++-- tests/configuration/test_configuration.py | 2 +- tests/test_ask_and_post.py | 6 +++--- tests/test_bindings.py | 2 +- tests/test_client.py | 4 ++-- tests/test_dependency_injection.py | 6 +++--- tests/test_handlers.py | 4 ++-- tests/test_kb_lifespan.py | 8 ++++---- tests/test_ki_registration.py | 8 ++++---- tests/test_knowledge_base_builder.py | 4 ++-- 13 files changed, 38 insertions(+), 35 deletions(-) diff --git a/examples/07-testing/kb.py b/examples/07-testing/kb.py index c759549..fea31fb 100644 --- a/examples/07-testing/kb.py +++ b/examples/07-testing/kb.py @@ -31,7 +31,7 @@ ) -class TestBinding(BindingModel): +class ExampleBinding(BindingModel): s: Uri value: Literal[str] @@ -42,15 +42,15 @@ class TestBinding(BindingModel): ?s a ex:TestSubject ; ex:hasValue ?value . """, - binding_model=TestBinding, + binding_model=ExampleBinding, prefixes={"ex": "http://example.org/knowledge-mapper/testing#"}, ) def ask_for_values_of_subject(subject_name: str) -> list[str]: - result_binding_set: list[TestBinding] = kb.ask( + result_binding_set: list[ExampleBinding] = kb.ask( [ - TestBinding( + ExampleBinding( s=URIRef(f"http://example.org/knowledge-mapper/testing#{subject_name}"), value=None, ) @@ -79,7 +79,7 @@ class ResultBinding(BindingModel): ?s a ex:TestSubject ; ex:storedBy ?other . """, - argument_binding_model=TestBinding, + argument_binding_model=ExampleBinding, result_binding_model=ResultBinding, prefixes={"ex": "http://example.org/knowledge-mapper/testing#"}, ) @@ -91,7 +91,7 @@ def repeat_value_post(value: str, iterations: int) -> list[URIRef]: result_binding_set.extend( kb.post( [ - TestBinding( + ExampleBinding( s=URIRef( f"http://example.org/knowledge-mapper/testing#Subject-{i}" ), diff --git a/examples/07-testing/test_kb.py b/examples/07-testing/test_kb.py index 9da0252..26fee84 100644 --- a/examples/07-testing/test_kb.py +++ b/examples/07-testing/test_kb.py @@ -5,7 +5,7 @@ # Import the Knowledge Base that you would like to test, along with any relevant binding # models. -from .kb import TestBinding, ask_for_values_of_subject, kb, repeat_value_post +from .kb import ExampleBinding, ask_for_values_of_subject, kb, repeat_value_post # In your tests you likely want to use the TestClient to mock results from the KE. # A Knowledge Base instance is initialized with a real Client that makes HTTP requests @@ -69,7 +69,7 @@ def test_ask_ki_with_binding_model(client: TestClient): result_binding_set = kb.ask( [ - TestBinding( + ExampleBinding( s=URIRef("http://example.org/knowledge-mapper/testing#Subject"), value=None, ) @@ -77,7 +77,7 @@ def test_ask_ki_with_binding_model(client: TestClient): "ask-ki-with-binding-model", ) assert result_binding_set == [ - TestBinding( + ExampleBinding( s=URIRef("http://example.org/knowledge-mapper/testing#Subject"), value="test value", ) @@ -90,7 +90,7 @@ def test_function_containing_ask(client: TestClient): client.mock_result_binding_set( ki_name="ask-ki-with-binding-model", binding_set=[ - TestBinding( + ExampleBinding( s=URIRef("http://example.org/knowledge-mapper/testing#Subject"), value="test value", ).model_dump(), @@ -98,7 +98,7 @@ def test_function_containing_ask(client: TestClient): ) result = ask_for_values_of_subject("Subject") - assert result == ['"test value"'] + assert result == ['test value'] # Similar approaches can be taken for POST interactions. diff --git a/pyproject.toml b/pyproject.toml index f7f60b3..4ffd67e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,9 @@ addopts = [ "-ra", "-q", ] +filterwarnings = [ + "ignore:cannot collect test class 'TestClient':pytest.PytestCollectionWarning", +] # TOOLS - ruff diff --git a/src/knowledge_mapper/testing/fake_client.py b/src/knowledge_mapper/testing/fake_client.py index 7143de1..1eb746d 100644 --- a/src/knowledge_mapper/testing/fake_client.py +++ b/src/knowledge_mapper/testing/fake_client.py @@ -2,8 +2,8 @@ from datetime import UTC, datetime -from src.knowledge_mapper.ke.client import ClientProtocol, PollResult -from src.knowledge_mapper.ke.models import ( +from knowledge_mapper.ke.client import ClientProtocol, PollResult +from knowledge_mapper.ke.models import ( AskResult, BindingSet, ExchangeInfo, diff --git a/tests/configuration/test_configuration.py b/tests/configuration/test_configuration.py index 0dfcc14..d180073 100644 --- a/tests/configuration/test_configuration.py +++ b/tests/configuration/test_configuration.py @@ -1,6 +1,6 @@ from pydantic_settings import SettingsConfigDict -from src.knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings +from knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings def test_basic_configuration(): diff --git a/tests/test_ask_and_post.py b/tests/test_ask_and_post.py index 7d2fc4e..0799685 100644 --- a/tests/test_ask_and_post.py +++ b/tests/test_ask_and_post.py @@ -1,9 +1,9 @@ import pytest from rdflib import URIRef -from src.knowledge_mapper import KnowledgeBase -from src.knowledge_mapper.ke.models import BindingModel, Literal, Uri -from src.knowledge_mapper.ke.testing import TestClient +from knowledge_mapper import KnowledgeBase +from knowledge_mapper.ke.models import BindingModel, Literal, Uri +from knowledge_mapper.testing import TestClient @pytest.fixture diff --git a/tests/test_bindings.py b/tests/test_bindings.py index 03aa681..06f5fb3 100644 --- a/tests/test_bindings.py +++ b/tests/test_bindings.py @@ -1,7 +1,7 @@ from rdflib import Literal as RDFLiteral from rdflib import URIRef -from src.knowledge_mapper.ke.models import ( +from knowledge_mapper.ke.models import ( BindingModel, Literal, Uri, diff --git a/tests/test_client.py b/tests/test_client.py index 6aef0c0..f3ba1ff 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -2,8 +2,8 @@ import pytest -from src.knowledge_mapper.ke import Client -from src.knowledge_mapper.ke.models import ( +from knowledge_mapper.ke import Client +from knowledge_mapper.ke.models import ( AskAnswerInteractionInfo, KnowledgeBaseInfo, KnowledgeInteractionInfo, diff --git a/tests/test_dependency_injection.py b/tests/test_dependency_injection.py index 182c2cf..42570e0 100644 --- a/tests/test_dependency_injection.py +++ b/tests/test_dependency_injection.py @@ -2,9 +2,9 @@ import pytest -from src.knowledge_mapper import Depends -from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase -from src.knowledge_mapper.ke.models import BindingSet +from knowledge_mapper import Depends +from knowledge_mapper.kb.knowledge_base import KnowledgeBase +from knowledge_mapper.ke.models import BindingSet @pytest.fixture diff --git a/tests/test_handlers.py b/tests/test_handlers.py index ab28194..7aa1b2d 100644 --- a/tests/test_handlers.py +++ b/tests/test_handlers.py @@ -1,8 +1,8 @@ import pytest from rdflib import URIRef -from src.knowledge_mapper.kb.knowledge_base import KnowledgeBase -from src.knowledge_mapper.ke.models import BindingModel, BindingSet, Uri +from knowledge_mapper.kb.knowledge_base import KnowledgeBase +from knowledge_mapper.ke.models import BindingModel, BindingSet, Uri @pytest.fixture diff --git a/tests/test_kb_lifespan.py b/tests/test_kb_lifespan.py index df4efac..48a2be4 100644 --- a/tests/test_kb_lifespan.py +++ b/tests/test_kb_lifespan.py @@ -2,10 +2,10 @@ import pytest -from src.knowledge_mapper import KnowledgeBase -from src.knowledge_mapper.kb.knowledge_base import KnowledgeBaseState -from src.knowledge_mapper.ke.errors import KnowledgeEngineNotAvailableError -from src.knowledge_mapper.testing import TestClient +from knowledge_mapper import KnowledgeBase +from knowledge_mapper.kb.knowledge_base import KnowledgeBaseState +from knowledge_mapper.ke.errors import KnowledgeEngineNotAvailableError +from knowledge_mapper.testing import TestClient @pytest.fixture diff --git a/tests/test_ki_registration.py b/tests/test_ki_registration.py index 3f2d075..98b30e5 100644 --- a/tests/test_ki_registration.py +++ b/tests/test_ki_registration.py @@ -1,17 +1,17 @@ import pytest -from src.knowledge_mapper import KnowledgeBase -from src.knowledge_mapper.ke.models import ( +from knowledge_mapper import KnowledgeBase +from knowledge_mapper.ke.models import ( AskAnswerInteractionInfo, BindingSet, KiTypes, KnowledgeInteractionInfo, ) -from src.knowledge_mapper.knowledge_interaction import ( +from knowledge_mapper.knowledge_interaction import ( KnowledgeInteractionContext, KnowledgeInteractionStatus, ) -from src.knowledge_mapper.testing import TestClient +from knowledge_mapper.testing import TestClient # Not a fixture as a fresh KB instance is needed for each test. diff --git a/tests/test_knowledge_base_builder.py b/tests/test_knowledge_base_builder.py index 07d4273..1f35fdc 100644 --- a/tests/test_knowledge_base_builder.py +++ b/tests/test_knowledge_base_builder.py @@ -1,7 +1,7 @@ import pytest -from src.knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings -from src.knowledge_mapper.ke.models import ( +from knowledge_mapper import KnowledgeBase, KnowledgeBaseSettings +from knowledge_mapper.ke.models import ( AskAnswerInteractionInfo, BindingSet, KiTypes, From 221e76c895949a7e769fa795884df55bca5a6aa3 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 27 May 2026 10:56:36 +0200 Subject: [PATCH 6/6] Reformat --- examples/07-testing/test_kb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/07-testing/test_kb.py b/examples/07-testing/test_kb.py index 26fee84..51543c4 100644 --- a/examples/07-testing/test_kb.py +++ b/examples/07-testing/test_kb.py @@ -98,7 +98,7 @@ def test_function_containing_ask(client: TestClient): ) result = ask_for_values_of_subject("Subject") - assert result == ['test value'] + assert result == ["test value"] # Similar approaches can be taken for POST interactions.