Skip to content

Commit

Permalink
chore: use importlib to refer to datafiles and create entrypoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Elodie Thiéblin committed May 15, 2024
1 parent 0bb2a8d commit b462594
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 38 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ According to [World History Encyclopedia](https://www.worldhistory.org/article/7
In the same way the Domus TDD API does not just offer a standards-conformant interface as specified in the link above, but also allows for flexible and scalable deployment, and has the possibility for extensions to carry out a bit more than just store & retrieve operations.

## Install from pypi

```
pip install domus-tdd-api
domus-tdd-api run
```

## Configuration

The TDD API can be configured using two methods.
Expand All @@ -26,7 +33,7 @@ The TDD API can be configured using two methods.
export TDD__CHECK_SCHEMA=True
```

2. Editing the `config.toml` file using the direct name of the variable
2. Create and edit a `config.toml` file at the root of the folder where you run the API using the direct name of the variable

```
SPARQLENDPOINT_URL="http://my-new-sparql.endpoint/address"
Expand Down Expand Up @@ -55,9 +62,6 @@ The `config.toml` file can also be used to define FLask server configuration (c.
| [TDD__]MANDATE_TTL | False | Boolean value, if set to True, it will only upload TDs having a time-to-live (ttl) value. The server will send a 400 HTTP code if the TD does not contain one. |
| [TDD__]LIMIT_BATCH_TDS | 25 | Default limit of returned TDs by batch (used for pagination) |
| [TDD__]ENDPOINT_TYPE | None | Special configuration to workaround SPARQL endpoints which do not follow the SPARQL standard. Possible values: `GRAPHDB` or `VIRTUOSO` |
| [TDD__]TD_JSONSCHEMA | ./tdd/data/td-json-schema-validation.json | The path to the file containing JSON-Schema to validate the TDs |
| [TDD__]TD_ONTOLOGY | ./tdd/data/td.ttl | The path to the file containing the TD OWL Ontology (only used for SHACL validation) |
| [TDD__]TD_SHACL_VALIDATOR | ./tdd/data/td-validation.ttl | The path to the file containing the SHACL shapes (only used for SHACL validation) |
| [TDD__]PERIOD_CLEAR_EXPIRE_TD | 3600 | The number of seconds between each clearing of expired TDs (0 to disable clearing expired TD) |
| [TDD__]OVERWRITE_DISCOVERY | False | Use custom discovery context (for offline purposes) |

Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,7 @@
"requests",
],
},
entry_points={
"console_scripts": ["domus-tdd-api = tdd:cli"],
},
)
14 changes: 12 additions & 2 deletions tdd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@
* SPDX-License-Identifier: EPL-2.0 OR W3C-20150513
********************************************************************************"""

from importlib import resources
import sys
import time
from threading import Thread
import click
from flask import Flask, request, Response, stream_with_context
import json
from flask.cli import FlaskGroup
import json_merge_patch
import httpx
import toml
from importlib_metadata import entry_points
from pathlib import Path


from tdd.errors import (
Expand Down Expand Up @@ -95,7 +99,8 @@ def thread_clear_expire_td():

def create_app():
app = Flask(__name__)
app.config.from_file("../config.toml", load=toml.load)
if Path("config.toml").is_file():
app.config.from_file("../config.toml", load=toml.load)
wait_for_sparqlendpoint()
register_error_handler(app)
register_routes(app)
Expand Down Expand Up @@ -127,6 +132,11 @@ def create_app():
return app


@click.group(cls=FlaskGroup, create_app=create_app)
def cli():
"""Management script for the API application."""


def register_error_handler(app):
@app.errorhandler(AppException)
def error_response(e):
Expand Down Expand Up @@ -155,7 +165,7 @@ def add_cors_headers(response):

@app.route("/", methods=["GET"])
def directory_description():
with open("tdd/data/tdd-description.json", "r") as f:
with resources.open_text("tdd.data", "tdd-description.json") as f:
tdd_description = json.loads(f.read())
tdd_description["base"] = CONFIG["TD_REPO_URL"]
return Response(
Expand Down
33 changes: 22 additions & 11 deletions tdd/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* SPDX-License-Identifier: EPL-2.0 OR W3C-20150513
********************************************************************************"""

from importlib import resources
import subprocess
import json
import re
Expand All @@ -29,7 +30,6 @@
from tdd.metadata import insert_metadata, delete_metadata
from tdd.errors import IDNotFound
from tdd.config import CONFIG
from tdd.paths import LIB_PATH


def get_check_schema_from_url_params(request):
Expand All @@ -53,11 +53,16 @@ def delete_id(uri):


def json_ld_to_ntriples(ld_content):
p = subprocess.Popen(
["node", LIB_PATH / "transform-to-nt.js", json.dumps(ld_content)],
stdout=subprocess.PIPE,
)
nt_content = p.stdout.read()
with resources.path("tdd.lib", "transform-to-nt.js") as transform_lib_path:
p = subprocess.Popen(
[
"node",
transform_lib_path,
json.dumps(ld_content),
],
stdout=subprocess.PIPE,
)
nt_content = p.stdout.read()
return nt_content.decode("utf-8")


Expand Down Expand Up @@ -96,11 +101,17 @@ 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", LIB_PATH / "frame-jsonld.js", nt_content, json.dumps(frame)],
stdout=subprocess.PIPE,
)
json_ld_compacted = p.stdout.read()
with resources.path("tdd.lib", "frame-jsonld.js") as frame_lib_path:
p = subprocess.Popen(
[
"node",
frame_lib_path,
nt_content,
json.dumps(frame),
],
stdout=subprocess.PIPE,
)
json_ld_compacted = p.stdout.read()
return json_ld_compacted


Expand Down
22 changes: 13 additions & 9 deletions tdd/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,12 @@

from config import config_from_env, config_from_toml, config_from_dict
from config.configuration_set import ConfigurationSet
from pathlib import Path

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": 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,
Expand All @@ -33,11 +30,18 @@
"OVERWRITE_DISCOVERY": False,
}

CONFIG = ConfigurationSet(
config_from_env(prefix="TDD", interpolate=True),
config_from_toml("config.toml", read_from_file=True),
config_from_dict(_default_config),
)

if Path("config.toml").is_file():
CONFIG = ConfigurationSet(
config_from_env(prefix="TDD", interpolate=True),
config_from_toml("config.toml", read_from_file=True),
config_from_dict(_default_config),
)
else:
CONFIG = ConfigurationSet(
config_from_env(prefix="TDD", interpolate=True),
config_from_dict(_default_config),
)

# Remove trailing /
if CONFIG["SPARQLENDPOINT_URL"][-1] == "/":
Expand Down
6 changes: 3 additions & 3 deletions tdd/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import json


from tdd.paths import DATA_PATH
from tdd.config import CONFIG
from tdd.utils import DEFAULT_THING_CONTEXT_URI, DEFAULT_DISCOVERY_CONTEXT_URI
from tdd.sparql import (
Expand All @@ -26,6 +25,7 @@
GET_ALL_CONTEXTS,
query,
)
from importlib import resources


def convert_context_to_array(ld_content):
Expand All @@ -45,7 +45,7 @@ def overwrite_thing_context(ld_content):
return
if type(ld_content["@context"]) not in (tuple, list):
return
with open(DATA_PATH / "fixed-ctx.json") as fp:
with resources.open_text("tdd.data", "fixed-ctx.json") as fp:
fixed_ctx = fp.read()
try:
index_wot_ctx = ld_content["@context"].index(DEFAULT_THING_CONTEXT_URI)
Expand All @@ -61,7 +61,7 @@ def overwrite_discovery_context(ld_content):
return
if type(ld_content["@context"]) not in (tuple, list):
return
with open(DATA_PATH / "fixed-discovery-ctx.json") as fp:
with resources.open_text("tdd.data", "fixed-discovery-ctx.json") as fp:
fixed_discovery_ctx = fp.read()
try:
index_discovery_ctx = ld_content["@context"].index(
Expand Down
4 changes: 0 additions & 4 deletions tdd/paths.py
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
from pathlib import Path

DATA_PATH = Path(__file__).parent / "data"
LIB_PATH = Path(__file__).parent / "lib"
12 changes: 7 additions & 5 deletions tdd/td.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import concurrent.futures
from copy import copy
from datetime import datetime
from importlib import resources
import json
from jsonschema import Draft7Validator
import uuid
Expand Down Expand Up @@ -71,7 +72,7 @@
)


with open(CONFIG["TD_JSONSCHEMA"]) as fp:
with resources.open_text("tdd.data", "td-json-schema-validation.json") as fp:
schema = json.load(fp)

validator = Draft7Validator(schema=schema)
Expand Down Expand Up @@ -183,10 +184,11 @@ def put_td_rdf_in_sparql(

if check_schema:
ontology_graph = create_binded_graph()
ontology_graph.parse(location=CONFIG["TD_ONTOLOGY"], format="turtle")

shacl_shapes_graph = create_binded_graph()
shacl_shapes_graph.parse(location=CONFIG["TD_SHACL_VALIDATOR"], format="turtle")
with resources.path("tdd.data", "td.ttl") as onto_path:
ontology_graph.parse(location=onto_path, format="turtle")
with resources.path("tdd.data", "td-validation.ttl") as shacl_path:
shacl_shapes_graph = create_binded_graph()
shacl_shapes_graph.parse(location=shacl_path, format="turtle")

conforms, graph_reports, text_reports = pyshacl.validate(
g,
Expand Down

0 comments on commit b462594

Please sign in to comment.