Skip to content

Commit

Permalink
Added a fix for parsing rdflib literals. (#229)
Browse files Browse the repository at this point in the history
# Description
We cannot use the `value` attribute of an `rdflib.Literal` to access its value, since it is `None` for some datatypes (at least for rdf:JSON).
Seems more robust to use the existence of the `n3()` method to test for a literal and the string representation to access its value.

## Type of change
- [x] Bug fix and code cleanup
- [ ] New feature
- [ ] Documentation update
- [ ] Testing

---------

Co-authored-by: Francesca L. Bleken <48128015+francescalb@users.noreply.github.com>
  • Loading branch information
jesper-friis and francescalb authored Jul 4, 2024
1 parent 225fc78 commit f76cdd5
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
32 changes: 32 additions & 0 deletions tests/test_literals.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,45 @@ def test_parse_literal() -> None:
assert literal.lang is None
assert literal.datatype == RDF.HTML

literal = parse_literal(f'"""["a", 1, 2]"""^^<{RDF.JSON}>')
assert literal.value == '["a", 1, 2]'
assert literal.lang is None
assert literal.datatype == RDF.JSON

with pytest.warns(UserWarning, match="unknown datatype"):
literal = parse_literal('"value"^^http://example.com/vocab#mytype')
assert literal.value == "value"
assert literal.lang is None
assert literal.datatype == "http://example.com/vocab#mytype"


def test_rdflib_literal():
"""Test parsing rdflib literals."""
import pytest

rdflib = pytest.importorskip("rdflib")
from tripper import RDF, XSD
from tripper.utils import parse_literal

rdflib_literal = rdflib.Literal(1, datatype=rdflib.XSD.integer)
literal = parse_literal(rdflib_literal)
assert literal.value == 1
assert literal.lang is None
assert literal.datatype == XSD.integer

rdflib_literal = rdflib.Literal("abc", datatype=rdflib.XSD.string)
literal = parse_literal(rdflib_literal)
assert literal.value == "abc"
assert literal.lang is None
assert literal.datatype == XSD.string

rdflib_literal = rdflib.Literal('["a", 1, 2]', datatype=rdflib.RDF.JSON)
literal = parse_literal(rdflib_literal)
assert literal.value == '["a", 1, 2]'
assert literal.lang is None
assert literal.datatype == RDF.JSON


def test_equality() -> None:
"""Test equality."""
from tripper import RDF, XSD, Literal
Expand Down
12 changes: 9 additions & 3 deletions tripper/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,16 @@ def parse_literal(literal: "Any") -> "Any":
):
datatype = str(literal.datatype)

# This will handle rdflib literals correctly and probably most other
# literal representations as well.
# This should handle rdflib literals correctly (and probably most other
# literal representations as well)
if hasattr(literal, "value"):
return Literal(literal.value, lang=lang, datatype=datatype)
# Note that in rdflib 6.3, the `value` attribute may be None for some
# datatypes (like rdf:JSON) even though a non-empty value exists.
# As a workaround, we use the string representation if the value
# attribute is None.
if literal.value is not None:
return Literal(literal.value, lang=lang, datatype=datatype)
return Literal(str(literal), lang=lang, datatype=datatype)

if not isinstance(literal, str):
if isinstance(literal, tuple(Literal.datatypes)):
Expand Down

0 comments on commit f76cdd5

Please sign in to comment.