This is an example project to present how to develop a plugin for the Domus TDD API. This plugin does not do anything except implementing the basic features to have a functional plugin.
First, specify into the setup.py
the plugins entrypoints regarding
what needs to be added to the TDD server that will add your plugin.
Here we have:
setup(
...
entry_points={
"tdd_api.plugins.blueprints": [
"example=domus_tdd_api_plugin_example:blueprint",
],
"tdd_api.plugins.transformers": [
"example=domus_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 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
.
As we defined in the domus_tdd_api_plugin_example/__init__.py
we define the blueprint
as follow:
blueprint = Blueprint("domus_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 "domus_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:
@blueprint.route("/<id>", 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 domus_tdd_api_plugin_example/__init__.py
file to see
other examples.
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
domus_tdd_api_plugin_example.example:td_to_example
since we use the function td_to_example
which is define in the
domus_tdd_api_plugin_example/example.py
file.
This method is declared like this:
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:
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 domus_tdd_api_plugin_example/example.py
file to see how it
is defined.
This example plugin come with some tests example to present how it can be done.
You can find it in the folder domus_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:
@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.