diff --git a/CITATION.cff b/CITATION.cff index fd3acef..c6d6102 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,7 +12,7 @@ authors: country: NL license: BSD-3-Clause repository-code: https://github.com/UUDigitalHumanitieslab/restframework-rdf -version: 1.1.0 +version: 1.2.0 identifiers: - type: doi value: 10.5281/zenodo.8158686 diff --git a/README.md b/README.md index 7d98630..777be84 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Visit the [web interface]( http://localhost:9999), navigate to the `NAMESPACES` 1. Clone this repository 2. Install the required python packages via `pip install -r requirements.txt` -3. Make sure your blazegraph server is running (see above). +3. Make sure your blazegraph server is running and that the `rdf-test` namespace exists in `quads` mode (see above). 4. Run the unit tests with `pytest`. ### Usage during development diff --git a/rdf/renderers.py b/rdf/renderers.py index 369b02d..cfa80f3 100644 --- a/rdf/renderers.py +++ b/rdf/renderers.py @@ -22,7 +22,14 @@ class RDFLibRenderer(BaseRenderer): """ def render(self, graph, media_type=None, renderer_context=None): - return graph.serialize(**self.rdflib_args) + view = None + if renderer_context is not None and 'view' in renderer_context: + view = renderer_context['view'] + rdflib_args = self.get_rdflib_args(view=view) + return graph.serialize(**rdflib_args) + + def get_rdflib_args(self, **kwargs): + return self.rdflib_args class TurtleRenderer(RDFLibRenderer): @@ -44,9 +51,18 @@ class RdfXMLRenderer(RDFLibRenderer): class JsonLdRenderer(RDFLibRenderer): media_type = 'application/ld+json' format = 'jsonld' - rdflib_args = { - 'format': 'json-ld', - } + json_ld_context = None + + def get_rdflib_args(self, view=None): + args = { + 'format': 'json-ld', + } + if ( + hasattr(view, "json_ld_context") + and view.json_ld_context is not None + ): + args['context'] = view.json_ld_context + return args class NTriplesRenderer(RDFLibRenderer): diff --git a/rdf/renderers_test.py b/rdf/renderers_test.py index cc2eb4e..b0ecd51 100644 --- a/rdf/renderers_test.py +++ b/rdf/renderers_test.py @@ -1,12 +1,53 @@ +import json + from rdflib import Graph +from rest_framework.renderers import BaseRenderer -from .renderers import TurtleRenderer +from .renderers import TurtleRenderer, JsonLdRenderer from .ns import * +from .views import RDFView + + +def verify_serialization(serialization, graph: Graph, format: str) -> bool: + parsed = Graph() + parsed.parse(data=serialization, format=format) + return len(parsed ^ graph) == 0 def test_rdflibrenderer(filled_graph): renderer = TurtleRenderer() serialization = renderer.render(filled_graph) - parsed = Graph() - parsed.parse(data=serialization, format='turtle') - assert len(parsed ^ filled_graph) == 0 + assert verify_serialization(serialization, filled_graph, "turtle") + + +def test_jsonldrenderer_no_context_arg(filled_graph): + # Using the JsonLdRenderer with no context argument at all should work + renderer = JsonLdRenderer() + serialization = renderer.render(filled_graph) + assert verify_serialization(serialization, filled_graph, "json-ld") + + +def test_jsonldrenderer_no_jsonld_context(filled_graph): + view = RDFView() + view.json_ld_context = None + renderer = JsonLdRenderer() + context = {"view": view} + serialization = renderer.render(filled_graph, renderer_context=context) + assert verify_serialization(serialization, filled_graph, "json-ld") + + +def test_jsonldrenderer_with_jsonld_context(filled_graph): + # Note that this test does not check if the JSON-LD context is correctly + # applied - we assume that rdflib does this correctly. + view = RDFView() + view.json_ld_context = { + "schema": "https://schema.org/", + } + renderer = JsonLdRenderer() + context = {"view": view} + serialization = renderer.render(filled_graph, renderer_context=context) + ser_dict = json.loads(serialization) + assert isinstance(ser_dict, dict) + assert "@context" in ser_dict + assert verify_serialization(serialization, filled_graph, "json-ld") + diff --git a/rdf/views.py b/rdf/views.py index 8eadaa4..0a6c0fc 100644 --- a/rdf/views.py +++ b/rdf/views.py @@ -90,7 +90,13 @@ class RDFView(APIView): Either set a static `graph` member function or override `get_graph` to compute the graph from the request. - For now, only Turtle output and JSON-LD input is supported. + By default, this view supports Turtle as output and JSON-LD as input, + but this can be overridden by providing custom values for + `renderer_classes` and `parser_classes`. + + Only `JsonLdRenderer` as an alternative renderer class has been tested. + If using this, JSON LD context may be provided by setting the + `json_ld_context` property (generally a `dict`). """ renderer_classes = (TurtleRenderer,) parser_classes = (JSONLDParser,) diff --git a/requirements.in b/requirements.in index 627ceaa..9ecc386 100644 --- a/requirements.in +++ b/requirements.in @@ -4,4 +4,5 @@ rdflib>6 pytest pytest-django mkdocs -mkdocstrings-python \ No newline at end of file +mkdocstrings-python +requests \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2ad41bb..37d51ca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,97 +1,115 @@ # -# This file is autogenerated by pip-compile with python 3.8 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: # -# pip-compile --output-file=requirements.txt requirements.in +# pip-compile requirements.in # -asgiref==3.6.0 +asgiref==3.8.1 # via django -attrs==22.2.0 - # via pytest -click==8.1.3 - # via mkdocs +certifi==2024.7.4 + # via requests +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # mkdocs + # mkdocstrings colorama==0.4.6 # via griffe -django==3.2.20 +django==3.2.25 # via # -r requirements.in # djangorestframework -djangorestframework==3.14.0 +djangorestframework==3.15.1 # via -r requirements.in ghp-import==2.1.0 # via mkdocs -griffe==0.25.5 +griffe==0.48.0 # via mkdocstrings-python +idna==3.7 + # via requests iniconfig==2.0.0 # via pytest isodate==0.6.1 # via rdflib -jinja2==3.1.2 +jinja2==3.1.4 # via # mkdocs # mkdocstrings -markdown==3.3.7 +markdown==3.6 # via # mkdocs # mkdocs-autorefs # mkdocstrings # pymdown-extensions -markupsafe==2.1.2 +markupsafe==2.1.5 # via # jinja2 + # mkdocs + # mkdocs-autorefs # mkdocstrings mergedeep==1.3.4 - # via mkdocs -mkdocs==1.4.2 + # via + # mkdocs + # mkdocs-get-deps +mkdocs==1.6.0 # via # -r requirements.in # mkdocs-autorefs # mkdocstrings -mkdocs-autorefs==0.4.1 +mkdocs-autorefs==1.0.1 # via mkdocstrings -mkdocstrings==0.20.0 +mkdocs-get-deps==0.2.0 + # via mkdocs +mkdocstrings==0.25.1 # via mkdocstrings-python -mkdocstrings-python==0.8.3 +mkdocstrings-python==1.10.5 # via -r requirements.in -packaging==23.0 +packaging==24.1 # via # mkdocs # pytest -pluggy==1.0.0 +pathspec==0.12.1 + # via mkdocs +platformdirs==4.2.2 + # via + # mkdocs-get-deps + # mkdocstrings +pluggy==1.5.0 # via pytest -pymdown-extensions==10.0 +pymdown-extensions==10.8.1 # via mkdocstrings -pyparsing==3.0.9 +pyparsing==3.1.2 # via rdflib -pytest==7.2.1 +pytest==8.2.2 # via # -r requirements.in # pytest-django -pytest-django==4.5.2 +pytest-django==4.8.0 # via -r requirements.in -python-dateutil==2.8.2 +python-dateutil==2.9.0.post0 # via ghp-import -pytz==2022.7.1 - # via - # django - # djangorestframework -pyyaml==6.0 +pytz==2024.1 + # via django +pyyaml==6.0.1 # via # mkdocs + # mkdocs-get-deps # pymdown-extensions # pyyaml-env-tag pyyaml-env-tag==0.1 # via mkdocs -rdflib==6.2.0 +rdflib==7.0.0 + # via -r requirements.in +requests==2.32.3 # via -r requirements.in six==1.16.0 # via # isodate # python-dateutil -sqlparse==0.4.4 +sqlparse==0.5.1 # via django -watchdog==2.3.1 +urllib3==2.2.2 + # via requests +watchdog==4.0.1 # via mkdocs - -# The following packages are considered to be unsafe in a requirements file: -# setuptools