From 8fa50ecde20cdbd027ef5d94e1c220fe37534138 Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Tue, 2 Jan 2024 18:49:06 +0100 Subject: [PATCH 1/3] Retain datatype when listing literals from rdflib --- tests/backends/test_rdflib.py | 27 +++++++++++++++++++++++++++ tripper/utils.py | 10 +++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/backends/test_rdflib.py diff --git a/tests/backends/test_rdflib.py b/tests/backends/test_rdflib.py new file mode 100644 index 00000000..b9915b2b --- /dev/null +++ b/tests/backends/test_rdflib.py @@ -0,0 +1,27 @@ +"""Test rdflib backend. + +Most of the rdflib backend is already tested in tests/test_triplestore.py. +""" +import pytest + +from tripper import Literal, Triplestore + +rdflib = pytest.importorskip("rdflib") + + +# Test for issue #162: Literals are lost when listing triples with rdflib +ts = Triplestore("rdflib") +ts.parse( + format="turtle", + data=( + " " + '"abc"^^ .' + ), +) +assert list(ts.triples()) == [ + ( + "http://ex#s", + "http://ex#p", + Literal("abc", datatype="http://www.w3.org/2001/XMLSchema#string"), + ) +] diff --git a/tripper/utils.py b/tripper/utils.py index 146ff7dc..546cea55 100644 --- a/tripper/utils.py +++ b/tripper/utils.py @@ -128,10 +128,18 @@ def parse_literal(literal: "Any") -> "Literal": if isinstance(literal, Literal): return literal + if hasattr(literal, "lang"): + lang = literal.lang + elif hasattr(literal, "language"): + lang = literal.language + + if hasattr(literal, "datatype"): + datatype = literal.datatype + # This will handle rdflib literals correctly and probably most other # literal representations as well. if hasattr(literal, "value"): - return Literal(literal.value) + return Literal(literal.value, lang=lang, datatype=datatype) if not isinstance(literal, str): if isinstance(literal, tuple(Literal.datatypes)): From bb432ccb02e0538485e5bceb85bbd104518fe786 Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Wed, 3 Jan 2024 12:01:41 +0100 Subject: [PATCH 2/3] Fixed parse_literal() to correctly parse rdflib literals as well --- tripper/mappings/mappings.py | 2 +- tripper/utils.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tripper/mappings/mappings.py b/tripper/mappings/mappings.py index 8cdf9978..6c7b2373 100644 --- a/tripper/mappings/mappings.py +++ b/tripper/mappings/mappings.py @@ -122,7 +122,7 @@ def __repr__(self): args.append(f", property_iri={self.property_iri}") if self.cost: args.append(f", cost={self.cost}") - return f"Value({self._value}{''.join(args)})" + return f"Value({self._value!r}{''.join(args)})" def get_value(self, unit=None, magnitude=False, quantity=None) -> "Any": """Returns the evaluated value of given input route number. diff --git a/tripper/utils.py b/tripper/utils.py index 546cea55..ba11c904 100644 --- a/tripper/utils.py +++ b/tripper/utils.py @@ -133,8 +133,12 @@ def parse_literal(literal: "Any") -> "Literal": elif hasattr(literal, "language"): lang = literal.language - if hasattr(literal, "datatype"): - datatype = literal.datatype + if not lang and hasattr(literal, "datatype"): + datatype = ( + literal.datatype + if literal.__class__ == str + else str(literal.datatype) + ) # This will handle rdflib literals correctly and probably most other # literal representations as well. From 3302157dd0315a2f5d81deb81d51cf9b2b62c25f Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Wed, 10 Jan 2024 23:54:31 +0100 Subject: [PATCH 3/3] Removed unnessesary conditional --- tripper/utils.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tripper/utils.py b/tripper/utils.py index ba11c904..523cf1b5 100644 --- a/tripper/utils.py +++ b/tripper/utils.py @@ -134,11 +134,7 @@ def parse_literal(literal: "Any") -> "Literal": lang = literal.language if not lang and hasattr(literal, "datatype"): - datatype = ( - literal.datatype - if literal.__class__ == str - else str(literal.datatype) - ) + datatype = str(literal.datatype) # This will handle rdflib literals correctly and probably most other # literal representations as well.