From 6c8b2394edbc8d83229f70e3ce74b32ddf32a993 Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:15:18 +0100 Subject: [PATCH 01/16] feat: Add bluepints import from modules --- tdd/__init__.py | 17 +++++++++++------ tdd/common.py | 8 ++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/tdd/__init__.py b/tdd/__init__.py index 9d2734c..33ef8d9 100644 --- a/tdd/__init__.py +++ b/tdd/__init__.py @@ -7,6 +7,8 @@ import httpx import toml +from importlib_metadata import entry_points + from tdd.errors import ( AppException, JSONDecodeError, @@ -27,6 +29,7 @@ ) from tdd.common import ( delete_id, + get_check_schema_from_url_params, ) from tdd.sparql import query, sparql_query from tdd.utils import ( @@ -79,6 +82,14 @@ def create_app(): register_error_handler(app) register_routes(app) + # import all blueprints from imported modules + for entry_point in entry_points(group="tdd_api.plugins"): + try: + app.register_blueprint(entry_point.load()) + except Exception as exc: + print(f"ERROR ({entry_point.name}): {exc}") + print(f"Tried to load bluepints from {entry_point.value} but an error occured, module not loaded") + # Launch thread to clear expired TDs periodically if CONFIG["PERIOD_CLEAR_EXPIRE_TD"] != 0: t = Thread(target=thread_clear_expire_td) @@ -113,12 +124,6 @@ def add_cors_headers(response): ) return response - def get_check_schema_from_url_params(request): - check_schema_param = request.args.get("check-schema") - check_schema = CONFIG["CHECK_SCHEMA"] - if check_schema_param in ["false", "False", "0"]: - check_schema = False - return check_schema @app.route("/", methods=["GET"]) def directory_description(): diff --git a/tdd/common.py b/tdd/common.py index d173089..3164bcb 100644 --- a/tdd/common.py +++ b/tdd/common.py @@ -12,10 +12,18 @@ ) from tdd.metadata import insert_metadata, delete_metadata from tdd.errors import IDNotFound +from tdd.config import CONFIG import re +def get_check_schema_from_url_params(request): + check_schema_param = request.args.get("check-schema") + check_schema = CONFIG["CHECK_SCHEMA"] + if check_schema_param in ["false", "False", "0"]: + check_schema = False + return check_schema + def delete_id(uri): resp = query( GET_NAMED_GRAPHS.format(uri=uri), From bbf0e5fb827940a2f41246c53198078db73fa55a Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:24:28 +0100 Subject: [PATCH 02/16] tests: Allow SparqlGraph to use a specified data_path This is helpful to define data from another plugin --- tests/conftest.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 193b7fc..b67a897 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,7 +26,6 @@ tdd.CONFIG["PERIOD_CLEAR_EXPIRE_TD"] = 0 tdd.CONFIG["OVERWRITE_DISCOVERY"] = True - @pytest.fixture(autouse=True) def patch_datetime_now(monkeypatch): class mydatetime(datetime.datetime): @@ -47,12 +46,11 @@ def test_client(httpx_mock): with app.test_client() as test_client: return test_client - class SparqlGraph: - def __init__(self, filename=None, format="nquads"): + def __init__(self, filename=None, format="nquads", data_path = DATA_PATH): self.graph = ConjunctiveGraph() if filename is not None: - self.graph.parse(DATA_PATH / filename, format=format) + self.graph.parse(data_path / filename, format=format) def sparql_get_query(self, query, content_type): if "json" not in content_type or content_type == "application/ld+json": From 9e1f6324de5b21c90f1aa5f48838272360b583fb Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:25:50 +0100 Subject: [PATCH 03/16] tests: Move tests to tdd module this is necessary to avoid conflict when define tests in plugin --- {tests => tdd/tests}/conftest.py | 0 {tests => tdd/tests}/data/17_things.nquads | 0 {tests => tdd/tests}/data/bad-json-schema.td.jsonld | 0 {tests => tdd/tests}/data/bad-json.td.jsonld | 0 {tests => tdd/tests}/data/registration-data.ttl | 0 {tests => tdd/tests}/data/smart-coffee-machine.n3 | 0 {tests => tdd/tests}/data/smart-coffee-machine.td.jsonld | 0 {tests => tdd/tests}/data/smart-coffee-machine.ttl | 0 {tests => tdd/tests}/data/smart-coffee-machine.xml | 0 {tests => tdd/tests}/data/smart-coffee-machine_shacl_nok.ttl | 0 {tests => tdd/tests}/data/smart-coffee-machine_shacl_ok.ttl | 0 {tests => tdd/tests}/data/smart_coffe_machine_expired.nquads | 0 {tests => tdd/tests}/data/smart_coffe_machine_init.nquads | 0 .../tests}/data/td/17_TD_RAW/actions-events-thing.td.jsonld | 0 .../tests}/data/td/17_TD_RAW/air-quality-sensor.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/alarm.td.jsonld | 0 .../data/td/17_TD_RAW/barmometric-pressure-sensor.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/binary-sensor.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/camera.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/color-control.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/color-sensor.td.jsonld | 0 .../tests}/data/td/17_TD_RAW/dimmable-color-light.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/dimmable-light.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/tum-daylight.td.jsonld | 0 .../tests}/data/td/17_TD_RAW/tum-dimmer-switch.td.jsonld | 0 .../tests}/data/td/17_TD_RAW/tum-hue-indoor-sensor1.td.jsonld | 0 .../tests}/data/td/17_TD_RAW/tum-hue-indoor-sensor2.td.jsonld | 0 .../tests}/data/td/17_TD_RAW/tum-hue-outdoor-sensor1.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/tum-light1.td.jsonld | 0 {tests => tdd/tests}/data/td/17_TD_RAW/tum-light2.td.jsonld | 0 {tests => tdd/tests}/data/tdd-description.json | 0 {tests => tdd/tests}/test_discovery.py | 0 {tests => tdd/tests}/test_modify.py | 0 {tests => tdd/tests}/test_registration.py | 0 {tests => tdd/tests}/test_routes.py | 0 35 files changed, 0 insertions(+), 0 deletions(-) rename {tests => tdd/tests}/conftest.py (100%) rename {tests => tdd/tests}/data/17_things.nquads (100%) rename {tests => tdd/tests}/data/bad-json-schema.td.jsonld (100%) rename {tests => tdd/tests}/data/bad-json.td.jsonld (100%) rename {tests => tdd/tests}/data/registration-data.ttl (100%) rename {tests => tdd/tests}/data/smart-coffee-machine.n3 (100%) rename {tests => tdd/tests}/data/smart-coffee-machine.td.jsonld (100%) rename {tests => tdd/tests}/data/smart-coffee-machine.ttl (100%) rename {tests => tdd/tests}/data/smart-coffee-machine.xml (100%) rename {tests => tdd/tests}/data/smart-coffee-machine_shacl_nok.ttl (100%) rename {tests => tdd/tests}/data/smart-coffee-machine_shacl_ok.ttl (100%) rename {tests => tdd/tests}/data/smart_coffe_machine_expired.nquads (100%) rename {tests => tdd/tests}/data/smart_coffe_machine_init.nquads (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/actions-events-thing.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/air-quality-sensor.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/alarm.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/barmometric-pressure-sensor.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/binary-sensor.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/camera.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/color-control.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/color-sensor.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/dimmable-color-light.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/dimmable-light.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-daylight.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-dimmer-switch.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-hue-indoor-sensor1.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-hue-indoor-sensor2.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-hue-outdoor-sensor1.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-light1.td.jsonld (100%) rename {tests => tdd/tests}/data/td/17_TD_RAW/tum-light2.td.jsonld (100%) rename {tests => tdd/tests}/data/tdd-description.json (100%) rename {tests => tdd/tests}/test_discovery.py (100%) rename {tests => tdd/tests}/test_modify.py (100%) rename {tests => tdd/tests}/test_registration.py (100%) rename {tests => tdd/tests}/test_routes.py (100%) diff --git a/tests/conftest.py b/tdd/tests/conftest.py similarity index 100% rename from tests/conftest.py rename to tdd/tests/conftest.py diff --git a/tests/data/17_things.nquads b/tdd/tests/data/17_things.nquads similarity index 100% rename from tests/data/17_things.nquads rename to tdd/tests/data/17_things.nquads diff --git a/tests/data/bad-json-schema.td.jsonld b/tdd/tests/data/bad-json-schema.td.jsonld similarity index 100% rename from tests/data/bad-json-schema.td.jsonld rename to tdd/tests/data/bad-json-schema.td.jsonld diff --git a/tests/data/bad-json.td.jsonld b/tdd/tests/data/bad-json.td.jsonld similarity index 100% rename from tests/data/bad-json.td.jsonld rename to tdd/tests/data/bad-json.td.jsonld diff --git a/tests/data/registration-data.ttl b/tdd/tests/data/registration-data.ttl similarity index 100% rename from tests/data/registration-data.ttl rename to tdd/tests/data/registration-data.ttl diff --git a/tests/data/smart-coffee-machine.n3 b/tdd/tests/data/smart-coffee-machine.n3 similarity index 100% rename from tests/data/smart-coffee-machine.n3 rename to tdd/tests/data/smart-coffee-machine.n3 diff --git a/tests/data/smart-coffee-machine.td.jsonld b/tdd/tests/data/smart-coffee-machine.td.jsonld similarity index 100% rename from tests/data/smart-coffee-machine.td.jsonld rename to tdd/tests/data/smart-coffee-machine.td.jsonld diff --git a/tests/data/smart-coffee-machine.ttl b/tdd/tests/data/smart-coffee-machine.ttl similarity index 100% rename from tests/data/smart-coffee-machine.ttl rename to tdd/tests/data/smart-coffee-machine.ttl diff --git a/tests/data/smart-coffee-machine.xml b/tdd/tests/data/smart-coffee-machine.xml similarity index 100% rename from tests/data/smart-coffee-machine.xml rename to tdd/tests/data/smart-coffee-machine.xml diff --git a/tests/data/smart-coffee-machine_shacl_nok.ttl b/tdd/tests/data/smart-coffee-machine_shacl_nok.ttl similarity index 100% rename from tests/data/smart-coffee-machine_shacl_nok.ttl rename to tdd/tests/data/smart-coffee-machine_shacl_nok.ttl diff --git a/tests/data/smart-coffee-machine_shacl_ok.ttl b/tdd/tests/data/smart-coffee-machine_shacl_ok.ttl similarity index 100% rename from tests/data/smart-coffee-machine_shacl_ok.ttl rename to tdd/tests/data/smart-coffee-machine_shacl_ok.ttl diff --git a/tests/data/smart_coffe_machine_expired.nquads b/tdd/tests/data/smart_coffe_machine_expired.nquads similarity index 100% rename from tests/data/smart_coffe_machine_expired.nquads rename to tdd/tests/data/smart_coffe_machine_expired.nquads diff --git a/tests/data/smart_coffe_machine_init.nquads b/tdd/tests/data/smart_coffe_machine_init.nquads similarity index 100% rename from tests/data/smart_coffe_machine_init.nquads rename to tdd/tests/data/smart_coffe_machine_init.nquads diff --git a/tests/data/td/17_TD_RAW/actions-events-thing.td.jsonld b/tdd/tests/data/td/17_TD_RAW/actions-events-thing.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/actions-events-thing.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/actions-events-thing.td.jsonld diff --git a/tests/data/td/17_TD_RAW/air-quality-sensor.td.jsonld b/tdd/tests/data/td/17_TD_RAW/air-quality-sensor.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/air-quality-sensor.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/air-quality-sensor.td.jsonld diff --git a/tests/data/td/17_TD_RAW/alarm.td.jsonld b/tdd/tests/data/td/17_TD_RAW/alarm.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/alarm.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/alarm.td.jsonld diff --git a/tests/data/td/17_TD_RAW/barmometric-pressure-sensor.td.jsonld b/tdd/tests/data/td/17_TD_RAW/barmometric-pressure-sensor.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/barmometric-pressure-sensor.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/barmometric-pressure-sensor.td.jsonld diff --git a/tests/data/td/17_TD_RAW/binary-sensor.td.jsonld b/tdd/tests/data/td/17_TD_RAW/binary-sensor.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/binary-sensor.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/binary-sensor.td.jsonld diff --git a/tests/data/td/17_TD_RAW/camera.td.jsonld b/tdd/tests/data/td/17_TD_RAW/camera.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/camera.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/camera.td.jsonld diff --git a/tests/data/td/17_TD_RAW/color-control.td.jsonld b/tdd/tests/data/td/17_TD_RAW/color-control.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/color-control.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/color-control.td.jsonld diff --git a/tests/data/td/17_TD_RAW/color-sensor.td.jsonld b/tdd/tests/data/td/17_TD_RAW/color-sensor.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/color-sensor.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/color-sensor.td.jsonld diff --git a/tests/data/td/17_TD_RAW/dimmable-color-light.td.jsonld b/tdd/tests/data/td/17_TD_RAW/dimmable-color-light.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/dimmable-color-light.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/dimmable-color-light.td.jsonld diff --git a/tests/data/td/17_TD_RAW/dimmable-light.td.jsonld b/tdd/tests/data/td/17_TD_RAW/dimmable-light.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/dimmable-light.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/dimmable-light.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-daylight.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-daylight.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-daylight.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-daylight.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-dimmer-switch.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-dimmer-switch.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-dimmer-switch.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-dimmer-switch.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-hue-indoor-sensor1.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-hue-indoor-sensor1.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-hue-indoor-sensor1.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-hue-indoor-sensor1.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-hue-indoor-sensor2.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-hue-indoor-sensor2.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-hue-indoor-sensor2.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-hue-indoor-sensor2.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-hue-outdoor-sensor1.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-hue-outdoor-sensor1.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-hue-outdoor-sensor1.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-hue-outdoor-sensor1.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-light1.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-light1.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-light1.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-light1.td.jsonld diff --git a/tests/data/td/17_TD_RAW/tum-light2.td.jsonld b/tdd/tests/data/td/17_TD_RAW/tum-light2.td.jsonld similarity index 100% rename from tests/data/td/17_TD_RAW/tum-light2.td.jsonld rename to tdd/tests/data/td/17_TD_RAW/tum-light2.td.jsonld diff --git a/tests/data/tdd-description.json b/tdd/tests/data/tdd-description.json similarity index 100% rename from tests/data/tdd-description.json rename to tdd/tests/data/tdd-description.json diff --git a/tests/test_discovery.py b/tdd/tests/test_discovery.py similarity index 100% rename from tests/test_discovery.py rename to tdd/tests/test_discovery.py diff --git a/tests/test_modify.py b/tdd/tests/test_modify.py similarity index 100% rename from tests/test_modify.py rename to tdd/tests/test_modify.py diff --git a/tests/test_registration.py b/tdd/tests/test_registration.py similarity index 100% rename from tests/test_registration.py rename to tdd/tests/test_registration.py diff --git a/tests/test_routes.py b/tdd/tests/test_routes.py similarity index 100% rename from tests/test_routes.py rename to tdd/tests/test_routes.py From 15cdd97dccc9e39742003604fa0837598fdee209 Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:26:47 +0100 Subject: [PATCH 04/16] tests: Use proper import now tests have been move to tdd folder --- tdd/tests/__init__.py | 0 tdd/tests/test_discovery.py | 2 +- tdd/tests/test_modify.py | 2 +- tdd/tests/test_registration.py | 2 +- tdd/tests/test_routes.py | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 tdd/tests/__init__.py diff --git a/tdd/tests/__init__.py b/tdd/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tdd/tests/test_discovery.py b/tdd/tests/test_discovery.py index e4202f3..f7e7500 100644 --- a/tdd/tests/test_discovery.py +++ b/tdd/tests/test_discovery.py @@ -3,7 +3,7 @@ from tdd.utils import get_collection_etag -from tests.conftest import ( +from tdd.tests.conftest import ( DATA_PATH, assert_only_on_known_errors, ) diff --git a/tdd/tests/test_modify.py b/tdd/tests/test_modify.py index f426e7e..5ee977c 100644 --- a/tdd/tests/test_modify.py +++ b/tdd/tests/test_modify.py @@ -1,6 +1,6 @@ import json -from tests.conftest import ( +from tdd.tests.conftest import ( DATA_PATH, ) diff --git a/tdd/tests/test_registration.py b/tdd/tests/test_registration.py index 1871b00..6530b6f 100644 --- a/tdd/tests/test_registration.py +++ b/tdd/tests/test_registration.py @@ -9,7 +9,7 @@ update_registration, validate_ttl, ) -from tests.conftest import DATA_PATH +from tdd.tests.conftest import DATA_PATH def test_get_registration_dict_from_rdf(): diff --git a/tdd/tests/test_routes.py b/tdd/tests/test_routes.py index 07acad2..5146c22 100644 --- a/tdd/tests/test_routes.py +++ b/tdd/tests/test_routes.py @@ -4,7 +4,7 @@ from rdflib.compare import graph_diff from tdd.td import clear_expired_td -from tests.conftest import ( +from tdd.tests.conftest import ( DATA_PATH, add_registration_to_td, assert_only_on_known_errors, From 1d6afdfc89164a5d9ff3df8f40632b9d5dbf2b7c Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:35:00 +0100 Subject: [PATCH 05/16] fix: Use DATA_PATH and LIB_PATH predefined to get files this is useful to be sure the files are fetched from tdd-api module --- tdd/common.py | 6 ++++-- tdd/config.py | 7 ++++--- tdd/context.py | 5 +++-- tdd/paths.py | 3 +++ 4 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 tdd/paths.py diff --git a/tdd/common.py b/tdd/common.py index 3164bcb..72d2872 100644 --- a/tdd/common.py +++ b/tdd/common.py @@ -1,5 +1,6 @@ import subprocess import json +from pathlib import Path from flask import Response @@ -13,6 +14,7 @@ from tdd.metadata import insert_metadata, delete_metadata from tdd.errors import IDNotFound from tdd.config import CONFIG +from tdd.paths import LIB_PATH import re @@ -38,7 +40,7 @@ def delete_id(uri): def json_ld_to_ntriples(ld_content): p = subprocess.Popen( - ["node", "tdd/lib/transform-to-nt.js", json.dumps(ld_content)], + ["node", LIB_PATH / "transform-to-nt.js", json.dumps(ld_content)], stdout=subprocess.PIPE, ) nt_content = p.stdout.read() @@ -81,7 +83,7 @@ def put_rdf_in_sparql(g, uri, context, delete_if_exists, ontology, forced_type=N def frame_nt_content(id, nt_content, frame): p = subprocess.Popen( - ["node", "tdd/lib/frame-jsonld.js", nt_content, json.dumps(frame)], + ["node", LIB_PATH / "frame-jsonld.js", nt_content, json.dumps(frame)], stdout=subprocess.PIPE, ) json_ld_compacted = p.stdout.read() diff --git a/tdd/config.py b/tdd/config.py index 817b47e..f8059d8 100644 --- a/tdd/config.py +++ b/tdd/config.py @@ -1,13 +1,14 @@ from config import config_from_env, config_from_toml, config_from_dict from config.configuration_set import ConfigurationSet +from tdd.paths import DATA_PATH _default_config = { "TD_REPO_URL": "http://localhost:5000", "SPARQLENDPOINT_URL": "http://127.0.0.1:3030/things", - "TD_JSONSCHEMA": "./tdd/data/td-json-schema-validation.json", - "TD_ONTOLOGY": "./tdd/data/td.ttl", - "TD_SHACL_VALIDATOR": "./tdd/data/td-validation.ttl", + "TD_JSONSCHEMA": DATA_PATH / "td-json-schema-validation.json", + "TD_ONTOLOGY": DATA_PATH / "td.ttl", + "TD_SHACL_VALIDATOR": DATA_PATH / "td-validation.ttl", "ENDPOINT_TYPE": None, "LIMIT_BATCH_TDS": 25, "CHECK_SCHEMA": False, diff --git a/tdd/context.py b/tdd/context.py index afc469b..91ae3c1 100644 --- a/tdd/context.py +++ b/tdd/context.py @@ -2,6 +2,7 @@ import json from tdd.config import CONFIG +from tdd.paths import DATA_PATH from tdd.utils import DEFAULT_THING_CONTEXT_URI, DEFAULT_DISCOVERY_CONTEXT_URI from tdd.sparql import ( INSERT_GRAPH, @@ -28,7 +29,7 @@ def overwrite_thing_context(ld_content): return if type(ld_content["@context"]) not in (tuple, list): return - with open("tdd/data/fixed-ctx.json") as fp: + with open(DATA_PATH / "fixed-ctx.json") as fp: fixed_ctx = fp.read() try: index_wot_ctx = ld_content["@context"].index(DEFAULT_THING_CONTEXT_URI) @@ -44,7 +45,7 @@ def overwrite_discovery_context(ld_content): return if type(ld_content["@context"]) not in (tuple, list): return - with open("tdd/data/fixed-discovery-ctx.json") as fp: + with open(DATA_PATH / "fixed-discovery-ctx.json") as fp: fixed_discovery_ctx = fp.read() try: index_discovery_ctx = ld_content["@context"].index( diff --git a/tdd/paths.py b/tdd/paths.py new file mode 100644 index 0000000..b8bec9c --- /dev/null +++ b/tdd/paths.py @@ -0,0 +1,3 @@ +from pathlib import Path +DATA_PATH = Path(__file__).parent / "data" +LIB_PATH = Path(__file__).parent / "lib" From 5c6f5deda1a4009ac635d6af6d2d03ac30e0a6f4 Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:40:58 +0100 Subject: [PATCH 06/16] feat: Import transformers from plugins using entrypoints --- tdd/__init__.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tdd/__init__.py b/tdd/__init__.py index 33ef8d9..c2b23a4 100644 --- a/tdd/__init__.py +++ b/tdd/__init__.py @@ -45,6 +45,8 @@ LIMIT_SPARQLENDPOINT_TEST = 10 +TD_TRANSFORMERS = [] + def wait_for_sparqlendpoint(): test_num = 0 while test_num < LIMIT_SPARQLENDPOINT_TEST: @@ -83,12 +85,19 @@ def create_app(): register_routes(app) # import all blueprints from imported modules - for entry_point in entry_points(group="tdd_api.plugins"): + for entry_point in entry_points(group="tdd_api.plugins.blueprints"): try: app.register_blueprint(entry_point.load()) except Exception as exc: print(f"ERROR ({entry_point.name}): {exc}") - print(f"Tried to load bluepints from {entry_point.value} but an error occured, module not loaded") + print(f"Tried to {entry_point.value} but an error occured, blueprint not loaded") + # import all transformers from imported modules + for entry_point in entry_points(group="tdd_api.plugins.transformers"): + try: + TD_TRANSFORMERS.append(entry_point.load()) + except Exception as exc: + print(f"ERROR ({entry_point.name}): {exc}") + print(f"Tried to load {entry_point.value} but an error occured, transformer not loaded") # Launch thread to clear expired TDs periodically if CONFIG["PERIOD_CLEAR_EXPIRE_TD"] != 0: @@ -152,6 +161,8 @@ def create_td(id): ) else: raise WrongMimeType(mimetype) + for transformer in TD_TRANSFORMERS: + transformer(id) update_collection_etag() return Response(status=201 if not updated else 204, headers={"Location": uri}) @@ -172,6 +183,8 @@ def update_td(id): if not validated: raise JSONSchemaError(errors, td_id=id) put_td_json_in_sparql(td_updated) + for transformer in TD_TRANSFORMERS: + transformer(id) update_collection_etag() return Response(status=204) @@ -192,6 +205,8 @@ def create_anonymous_td(): ) else: # wrong mimetype raise WrongMimeType(mimetype) + for transformer in TD_TRANSFORMERS: + transformer(uri) update_collection_etag() return Response(status=201 if not updated else 204, headers={"Location": uri}) From b32b4210529de5ed3370d83d297d91560b5c4b52 Mon Sep 17 00:00:00 2001 From: Fabien Amarger <881739+Murloc6@users.noreply.github.com> Date: Mon, 12 Feb 2024 16:21:50 +0100 Subject: [PATCH 07/16] doc: Add documentation about plugin --- README.md | 11 +++++ doc/plugin.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 doc/plugin.md diff --git a/README.md b/README.md index fb370c5..04c4384 100644 --- a/README.md +++ b/README.md @@ -176,3 +176,14 @@ black . flake8 pytests tests ``` + +## Plugin + +To use a specific plugin you can juste pip install the module and relaunch your +TDD-API server. The new plugins routes and transformers will then been available. + +### Develop your own plugin + +You can develop your own plugin to add features to your TDD-API server. +To do so you can create a new project and follow the instructions defined in the +[Plugin Documentation](doc/plugin.md) to add it to the TDD-API. diff --git a/doc/plugin.md b/doc/plugin.md new file mode 100644 index 0000000..266c6aa --- /dev/null +++ b/doc/plugin.md @@ -0,0 +1,127 @@ +# TDD-API Plugin + +You can find a plugin example here [https://github.com/wiresio/tdd-api-plugin-example](https://github.com/wiresio/tdd-api-plugin-example). + +To develop your own plugin, the first thing to do is to create a `setup.py` file containing the common information, +then add the entrypoints needed bu TDD-AI to consider it as a plugin. + +```python +#!/usr/bin/env python +from setuptools import setup, find_packages + +setup( + name="TDD API plugin Example", + version="1.0", + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=[ + "tdd-api", + ], + extras_require={ + 'dev': [ + 'pytest', + 'mock', + ] + }, + entry_points={ + "tdd_api.plugins.blueprints": [ + "example=tdd_api_plugin_example:blueprint", + ], + "tdd_api.plugins.transformers": [ + "example=tdd_api_plugin_example.example:td_to_example", + ], + }, +) +``` + +We have defined two entrypoints. The first one is `tdd_api.plugins.blueprints` which is used to +define where to find the [Flask blueprint](https://flask.palletsprojects.com/en/3.0.x/blueprints/) for +the plugin. +The second one is `tdd_api.plugins.transformers` to specify the function to use to transform a TD to +what you want, here an `Example`. + +Then you can develop the function for the routes using the blueprint and the transformer feature. + +## Blueprint + +As we defined in the [`tdd_api_plugin_example/__init__.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/__init__.py) we define the blueprint +as follow: + +```python +blueprint = Blueprint("tdd_api_plugin_example", __name__, url_prefix="/example") +``` + +We could have name the variable as we prefere since we have defined in the `setup.py` the right +variable name in the entrypoint. + +The first parameter `"tdd_api_plugin_example"` is the name of the blueprint, the second parameter is the +import module (here `__name__` since this is the same module) and we define a `url_prefix` to not redeclare it +on each route. +This `url_prefix` will be what distinguish the plugin routes to other. Be sure to not redefine an already imported +prefix. + +This blueprint can be used to define all the routes you want to add to the TDD-API server regarding to +this plugin. +For example to add a `GET` route for the `Example` plugin you can add the route like this: + +```python +@blueprint.route("/", methods=["GET"]) +def describe_example(id): + return ... +``` + +We use the blueprint as decorator to add the route, the path is defined regarding the `url_prefix` and we +specify a dedicated method to match. +You can look at the [`tdd_api_plugin_example/__init__.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/__init__.py) file to see +other examples. + +## Transformer + +We have defined a transformer to be sure, each time a TD is uploaded to transform it to our `Example` format +and store in the SparqlEndpoint. To do, we declare the function to use in the entrypoint (here +`tdd_api_plugin_example.example:td_to_example` since we use the function `td_to_example` which is define in the +`tdd_api_plugin_example/example.py` file. + +This method is declared like this: + +```python +def td_to_example(uri): + ... +``` + +The parameter must be only the TD URI as a string since we want to be the most generic as possible. Then the first +thing to do can be fetching the TD content, which can be done with: + +```python +content = get_id_description(uri, "application/n-triples", {"prefix": "td"}) +``` + +Using this content we can do whatever is needed to transform one format to another. +Then we can store the result using the helper method `put_json_in_sparql` or `put_rdf_in_sparql` from the +`tdd.common` module. +You can look at the [`tdd_api_plugin_example/example.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/example.py) file to see how it +is defined. + +## Tests + +This example plugin come with some tests example to present how it can be done. +You can find it in the folder [`tdd_api_plugin_example/tests`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/tests). +The `test_example.py` define some tests for the `example.py` module, where the `test_td_to_example.py` +define tests for the routes. + +These tests simulate the existence of a real SparqlEndpoint using a RDFLib Graph abstraction. Then you +can specify a mock SparqlEndpoint prefilled with some data as it is defined with: + +```python +@pytest.fixture +def mock_sparql_example_and_td(httpx_mock): + graph = SparqlGraph("td_example.trig", format="trig", data_path=DATA_PATH) + httpx_mock.add_callback(graph.custom) +``` + +Where `DATA_PATH` is where the tests data are stored and `td_example.trig` the data to fill the SparqlEndpoint. + +There are some generic mock defined in the `TDD-API` module. You have to import them to use them in your tests. +You can find for example the `mock_sparql_empty_endpoint` from `tdd.tests.conftest` module. This mock can be used +to simulate an empty SparqlEndpoint at the begining of your test. From 199c21acc4caf1e6c5dde3e44e37c3a345f094c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 10:51:32 +0100 Subject: [PATCH 08/16] doc: fix typos --- README.md | 2 +- doc/plugin.md | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 04c4384..04fe30f 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ pytests tests ## Plugin To use a specific plugin you can juste pip install the module and relaunch your -TDD-API server. The new plugins routes and transformers will then been available. +TDD-API server. The new plugins routes and transformers will then be available. ### Develop your own plugin diff --git a/doc/plugin.md b/doc/plugin.md index 266c6aa..ef0e5a0 100644 --- a/doc/plugin.md +++ b/doc/plugin.md @@ -2,8 +2,9 @@ You can find a plugin example here [https://github.com/wiresio/tdd-api-plugin-example](https://github.com/wiresio/tdd-api-plugin-example). -To develop your own plugin, the first thing to do is to create a `setup.py` file containing the common information, -then add the entrypoints needed bu TDD-AI to consider it as a plugin. +To develop your own plugin, the first thing to do is to create a `setup.py` file +at the root of your new python project containing the usual python project information, +then add the entrypoints needed for TDD-API to consider it as a plugin. ```python #!/usr/bin/env python @@ -39,7 +40,7 @@ We have defined two entrypoints. The first one is `tdd_api.plugins.blueprints` w define where to find the [Flask blueprint](https://flask.palletsprojects.com/en/3.0.x/blueprints/) for the plugin. The second one is `tdd_api.plugins.transformers` to specify the function to use to transform a TD to -what you want, here an `Example`. +what you want, here an `example`. Then you can develop the function for the routes using the blueprint and the transformer feature. @@ -52,14 +53,13 @@ as follow: blueprint = Blueprint("tdd_api_plugin_example", __name__, url_prefix="/example") ``` -We could have name the variable as we prefere since we have defined in the `setup.py` the right -variable name in the entrypoint. +We can give any name to the variable since the `setup.py` links it to the `tdd_api.plugins.blueprints`. The first parameter `"tdd_api_plugin_example"` is the name of the blueprint, the second parameter is the import module (here `__name__` since this is the same module) and we define a `url_prefix` to not redeclare it on each route. -This `url_prefix` will be what distinguish the plugin routes to other. Be sure to not redefine an already imported -prefix. +This `url_prefix` make sure that if we use different plugins, the routes they declare will be unique `/plugin1/route1`, `/plugin2/route1`. +This requires that all plugins have _different prefix_. This blueprint can be used to define all the routes you want to add to the TDD-API server regarding to this plugin. @@ -78,7 +78,7 @@ other examples. ## Transformer -We have defined a transformer to be sure, each time a TD is uploaded to transform it to our `Example` format +We have defined a transformer to be sure, each time a TD is uploaded to transform it to our `example` format and store in the SparqlEndpoint. To do, we declare the function to use in the entrypoint (here `tdd_api_plugin_example.example:td_to_example` since we use the function `td_to_example` which is define in the `tdd_api_plugin_example/example.py` file. @@ -97,17 +97,17 @@ thing to do can be fetching the TD content, which can be done with: content = get_id_description(uri, "application/n-triples", {"prefix": "td"}) ``` -Using this content we can do whatever is needed to transform one format to another. +Using this content we can do whatever is needed to manipulate the data : transform it, +change its format, etc. Then we can store the result using the helper method `put_json_in_sparql` or `put_rdf_in_sparql` from the `tdd.common` module. -You can look at the [`tdd_api_plugin_example/example.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/example.py) file to see how it -is defined. +You can look at the [`tdd_api_plugin_example/example.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/example.py) file to see how it is defined. ## Tests This example plugin come with some tests example to present how it can be done. You can find it in the folder [`tdd_api_plugin_example/tests`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/tests). -The `test_example.py` define some tests for the `example.py` module, where the `test_td_to_example.py` +`test_example.py` defines some tests for the `example.py` module, where the `test_td_to_example.py` define tests for the routes. These tests simulate the existence of a real SparqlEndpoint using a RDFLib Graph abstraction. Then you @@ -122,6 +122,6 @@ def mock_sparql_example_and_td(httpx_mock): Where `DATA_PATH` is where the tests data are stored and `td_example.trig` the data to fill the SparqlEndpoint. -There are some generic mock defined in the `TDD-API` module. You have to import them to use them in your tests. +There are some generic mocks defined in the `TDD-API` module. You have to import them to use them in your tests. You can find for example the `mock_sparql_empty_endpoint` from `tdd.tests.conftest` module. This mock can be used -to simulate an empty SparqlEndpoint at the begining of your test. +to simulate an empty SparqlEndpoint at the beginning of your test. From 192c23d1f71fb0c76c9536f2e993c446dd5041f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 11:32:40 +0100 Subject: [PATCH 09/16] chore: add importlib-metadata dependency\n\n needed for entrypoints --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index bd1bfdd..af9118c 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,7 @@ "json-merge-patch", "python-configuration[toml]", "pyshacl", + "importlib-metadata", ], extras_require={ "prod": [ From 923d677b288a6a0839f2e88624ed0039cc23ae3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 11:40:18 +0100 Subject: [PATCH 10/16] fix: update MANIFEST.in --- MANIFEST.in | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index dad66e3..32f1212 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -26,13 +26,8 @@ exclude .gitlab-ci.yml exclude .gitlab-ci-extended.yml exclude pytest.ini -recursive-exclude tests *.json -recursive-exclude tests *.py -recursive-exclude tests *.jsonld -recursive-exclude tests *.ttl -recursive-exclude tests *.nquads -exclude tests/data/smart-coffee-machine.n3 -exclude tests/data/smart-coffee-machine.xml +recursive-include tdd/tests/data *.json *.jsonld *.nquads *.ttl *.xml *.n3 +recursive-include tdd/tests *.py prune doc prune node_modules From b2fd24bba3cfe592658136627388e03fd49dae6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 11:41:32 +0100 Subject: [PATCH 11/16] ilint: fix black and flake8 --- tdd/__init__.py | 22 +++++++++++++--------- tdd/common.py | 3 +-- tdd/paths.py | 1 + tdd/td.py | 8 +++++--- tdd/tests/conftest.py | 4 +++- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/tdd/__init__.py b/tdd/__init__.py index c2b23a4..455a6c4 100644 --- a/tdd/__init__.py +++ b/tdd/__init__.py @@ -47,6 +47,7 @@ TD_TRANSFORMERS = [] + def wait_for_sparqlendpoint(): test_num = 0 while test_num < LIMIT_SPARQLENDPOINT_TEST: @@ -90,14 +91,18 @@ def create_app(): app.register_blueprint(entry_point.load()) except Exception as exc: print(f"ERROR ({entry_point.name}): {exc}") - print(f"Tried to {entry_point.value} but an error occured, blueprint not loaded") + print( + f"Tried to {entry_point.value} but an error occurred, blueprint not loaded" + ) # import all transformers from imported modules for entry_point in entry_points(group="tdd_api.plugins.transformers"): try: TD_TRANSFORMERS.append(entry_point.load()) except Exception as exc: print(f"ERROR ({entry_point.name}): {exc}") - print(f"Tried to load {entry_point.value} but an error occured, transformer not loaded") + print( + f"Tried to load {entry_point.value} but an error occurred, transformer not loaded" + ) # Launch thread to clear expired TDs periodically if CONFIG["PERIOD_CLEAR_EXPIRE_TD"] != 0: @@ -133,7 +138,6 @@ def add_cors_headers(response): ) return response - @app.route("/", methods=["GET"]) def directory_description(): with open("tdd/data/tdd-description.json", "r") as f: @@ -270,9 +274,9 @@ def generate(): response = Response( stream_with_context(generate()), content_type="application/ld+json" ) - response.headers[ - "Link" - ] = f'; rel="canonical"; etag="{get_collection_etag()}"' + response.headers["Link"] = ( + f'; rel="canonical"; etag="{get_collection_etag()}"' + ) return response elif format == "collection": @@ -298,9 +302,9 @@ def generate(): next_offset = params["offset"] + params["limit"] if next_offset < number_total: new_params = {**params, "offset": next_offset} - response[ - "next" - ] = f"/things?{create_link_params(new_params)}&format=collection" + response["next"] = ( + f"/things?{create_link_params(new_params)}&format=collection" + ) response = Response( json.dumps(response), content_type="application/ld+json" ) diff --git a/tdd/common.py b/tdd/common.py index 72d2872..861628e 100644 --- a/tdd/common.py +++ b/tdd/common.py @@ -1,7 +1,5 @@ import subprocess import json -from pathlib import Path - from flask import Response from tdd.sparql import ( @@ -26,6 +24,7 @@ def get_check_schema_from_url_params(request): check_schema = False return check_schema + def delete_id(uri): resp = query( GET_NAMED_GRAPHS.format(uri=uri), diff --git a/tdd/paths.py b/tdd/paths.py index b8bec9c..596c9d5 100644 --- a/tdd/paths.py +++ b/tdd/paths.py @@ -1,3 +1,4 @@ from pathlib import Path + DATA_PATH = Path(__file__).parent / "data" LIB_PATH = Path(__file__).parent / "lib" diff --git a/tdd/td.py b/tdd/td.py index 4dffe23..6c73523 100644 --- a/tdd/td.py +++ b/tdd/td.py @@ -327,13 +327,15 @@ def send_request(id, context): offset=offset, ontology=ONTOLOGY["base"], orderby_variable=f"?{sort_by}" if sort_by else "?id", - orderby_sparql=f""" + orderby_sparql=( + f""" OPTIONAL {{ GRAPH ?graph {{ {ORDERBY[sort_by]} }}}} """ - if sort_by - else "", + if sort_by + else "" + ), orderby_direction=sort_order if sort_order else "ASC", ), ) diff --git a/tdd/tests/conftest.py b/tdd/tests/conftest.py index b67a897..566eef5 100644 --- a/tdd/tests/conftest.py +++ b/tdd/tests/conftest.py @@ -26,6 +26,7 @@ tdd.CONFIG["PERIOD_CLEAR_EXPIRE_TD"] = 0 tdd.CONFIG["OVERWRITE_DISCOVERY"] = True + @pytest.fixture(autouse=True) def patch_datetime_now(monkeypatch): class mydatetime(datetime.datetime): @@ -46,8 +47,9 @@ def test_client(httpx_mock): with app.test_client() as test_client: return test_client + class SparqlGraph: - def __init__(self, filename=None, format="nquads", data_path = DATA_PATH): + def __init__(self, filename=None, format="nquads", data_path=DATA_PATH): self.graph = ConjunctiveGraph() if filename is not None: self.graph.parse(data_path / filename, format=format) From df4a2a9ac3bb1bb30300dda18934574a2c4d9a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 11:50:08 +0100 Subject: [PATCH 12/16] chore: update manifest --- MANIFEST.in | 8 -------- 1 file changed, 8 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 32f1212..14dac13 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,7 +2,6 @@ include ./tdd/*.py include ./tdd/data/*.ttl include ./tdd/data/*.json include ./tdd/lib/*.js -recursive-include tdd/jsonld *.js include ./scripts/*.py @@ -16,16 +15,9 @@ include package.json include package-lock.json include config.toml -include deployment/*.yaml - include fuseki-docker/**/*.ttl include fuseki-docker/*.ttl -include fuseki-docker/databases/.hg_keep - -exclude .gitlab-ci.yml -exclude .gitlab-ci-extended.yml -exclude pytest.ini recursive-include tdd/tests/data *.json *.jsonld *.nquads *.ttl *.xml *.n3 recursive-include tdd/tests *.py From 18f655bd9e74e67824919b9fd748b02c5500da0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 11:50:31 +0100 Subject: [PATCH 13/16] config: update py3 testing folder --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 85a74ad..4bb7d24 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,7 @@ deps = pytest extras = dev commands = - {envpython} -m pytest {posargs:tests} + {envpython} -m pytest {posargs:tdd/tests} [testenv:flake8] basepython = python3 From cb455e662ac0bb067056b50071582bcda9e4d94c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 11:55:37 +0100 Subject: [PATCH 14/16] chore: add toml dependency --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index af9118c..cccae0d 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ "python-configuration[toml]", "pyshacl", "importlib-metadata", + "toml", ], extras_require={ "prod": [ From 477754e7eb2b20db2d8c75e63f63bdae7db36658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elodie=20Thi=C3=A9blin?= Date: Wed, 21 Feb 2024 12:09:17 +0100 Subject: [PATCH 15/16] doc: update plugin doc --- doc/plugin.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/plugin.md b/doc/plugin.md index ef0e5a0..0429a3a 100644 --- a/doc/plugin.md +++ b/doc/plugin.md @@ -46,7 +46,7 @@ Then you can develop the function for the routes using the blueprint and the tra ## Blueprint -As we defined in the [`tdd_api_plugin_example/__init__.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/__init__.py) we define the blueprint +As we defined in the [`tdd_api_plugin_example/__init__.py`](https://github.com/wiresio/tdd-api-plugin/blob/main/tdd_api_plugin_example/__init__.py) we define the blueprint as follow: ```python @@ -73,14 +73,21 @@ def describe_example(id): We use the blueprint as decorator to add the route, the path is defined regarding the `url_prefix` and we specify a dedicated method to match. -You can look at the [`tdd_api_plugin_example/__init__.py`](https://github.com/wiresio/blobl/main/tdd_api_plugin_example/__init__.py) file to see +You can look at the [`tdd_api_plugin_example/__init__.py`](https://github.com/wiresio/tdd-api-plugin/blob/main/tdd_api_plugin_example/__init__.py) file to see other examples. ## Transformer +Transformers are functions that will be called each time a thing is created/updated on the /things routes, +you can find the calls to these transformers in the [`tdd/__init__.py`](../tdd/__init__.py) file, in the functions: + +- `create_td` +- `update_td` +- `create_anonymous_td` + We have defined a transformer to be sure, each time a TD is uploaded to transform it to our `example` format -and store in the SparqlEndpoint. To do, we declare the function to use in the entrypoint (here -`tdd_api_plugin_example.example:td_to_example` since we use the function `td_to_example` which is define in the +and store in the SparqlEndpoint. To do, we declare the function to use in the entrypoint: here +`tdd_api_plugin_example.example:td_to_example` since we use the function `td_to_example` which is defined in the `tdd_api_plugin_example/example.py` file. This method is declared like this: From b07872ffd0147dfbe2348a6a51a42f321c7fb023 Mon Sep 17 00:00:00 2001 From: Christian Glomb Date: Wed, 20 Mar 2024 11:58:08 +0100 Subject: [PATCH 16/16] Change link --- doc/plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/plugin.md b/doc/plugin.md index 0429a3a..9a18baa 100644 --- a/doc/plugin.md +++ b/doc/plugin.md @@ -1,6 +1,6 @@ # TDD-API Plugin -You can find a plugin example here [https://github.com/wiresio/tdd-api-plugin-example](https://github.com/wiresio/tdd-api-plugin-example). +You can find a plugin example here [https://github.com/wiresio/domus-tdd-api-plugin-example](https://github.com/wiresio/domus-tdd-api-plugin-example). To develop your own plugin, the first thing to do is to create a `setup.py` file at the root of your new python project containing the usual python project information,