convert¶
Tripper module for converting between RDF and other repetations.
Example use:
from tripper import DCTERMS, Literal, Triplestore from tripper.convert import load_container, save_container
ts = Triplestore("rdflib") dataset = {"a": 1, "b": 2} save_container(ts, dataset, ":data_indv") load_container(ts, ":data_indv")
Add additional context to our data individual¶
ts.add((":data_indv", DCTERMS.title, Literal("My wonderful data")))
load_container(ts, ":data_indv") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ValueError: Unrecognised predicate 'http://purl.org/dc/terms/title' in dict: :data_indv
load_container(ts, ":data_indv", ignore_unrecognised=True)
from_container(container, iri, lang='en', recognised_keys=None, keep=False)
¶
Serialise a basic Python container type (mapping or sequence) as RDF.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
container |
Union[Mapping[str, Any], Sequence[Any]] |
The container to be saved. Should be a mapping or
sequence. The |
required |
iri |
str |
IRI of individual that stands for the container. |
required |
lang |
str |
Language to use for mapping keys. |
'en' |
recognised_keys |
Optional[Union[Dict, str]] |
An optional dict that maps mapping keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
|
None |
keep |
bool |
Whether to keep the key-value pair representation for mapping items serialised with recognised_keys. Note that this may duplicate potential large literal values. |
False |
Returns:
Type | Description |
---|---|
list |
List of RDF triples. |
Note
container
should not be an empty sequence. The reason for this
is that is represented with rdf:nil, which is a single IRI and not
a triple.
Source code in tripper/convert/convert.py
def from_container(
container: "Union[Mapping[str, Any], Sequence[Any]]",
iri: str,
lang: str = "en",
recognised_keys: "Optional[Union[Dict, str]]" = None,
keep: bool = False,
) -> list:
"""Serialise a basic Python container type (mapping or sequence) as RDF.
Arguments:
container: The container to be saved. Should be a mapping or
sequence. The `load_container()` function will deserialise
them as dict and list, respectively.
iri: IRI of individual that stands for the container.
lang: Language to use for mapping keys.
recognised_keys: An optional dict that maps mapping keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
`BASIC_RECOGNISED_KEYS` module will be used.
keep: Whether to keep the key-value pair representation for
mapping items serialised with recognised_keys. Note that this
may duplicate potential large literal values.
Returns:
List of RDF triples.
Note:
`container` should not be an empty sequence. The reason for this
is that is represented with rdf:nil, which is a single IRI and not
a triple.
"""
if recognised_keys == "basic":
recognised_keys = BASIC_RECOGNISED_KEYS
rdf = []
def get_obj_iri(obj, uuid):
"""Return IRI for Python object `obj`. The `uuid` argument is
appended to blank nodes for uniques."""
if isinstance(obj, Mapping):
if not obj:
return OTEIO.Dictionary
obj_iri = f"_:dict_{uuid}"
elif isinstance(obj, Sequence) and not isinstance(obj, str):
if not obj:
return RDF.List
obj_iri = f"_:list_{uuid}"
elif obj is None:
return OWL.Nothing
else:
return parse_literal(obj)
rdf.extend(
from_container(
obj,
obj_iri,
lang=lang,
recognised_keys=recognised_keys,
keep=keep,
)
)
return obj_iri
if isinstance(container, Sequence):
assert not isinstance(container, str) # nosec
if not container:
raise ValueError("empty sequence is not supported")
rdf.append((iri, RDF.type, RDF.List))
for i, element in enumerate(container):
uuid = uuid4()
first_iri = get_obj_iri(element, uuid)
rest_iri = RDF.nil if i >= len(container) - 1 else f"_:rest_{uuid}"
rdf.append((iri, RDF.first, first_iri))
rdf.append((iri, RDF.rest, rest_iri))
iri = rest_iri
elif isinstance(container, Mapping):
rdf.append((iri, RDF.type, OTEIO.Dictionary))
for key, value in container.items():
uuid = uuid4()
recognised = recognised_keys and key in recognised_keys
value_iri = get_obj_iri(value, uuid)
if recognised:
rdf.append(
(iri, recognised_keys[key], value_iri) # type: ignore
)
if not recognised or keep:
key_indv = f"_:key_{uuid}"
value_indv = f"_:value_{uuid}"
pair = f"_:pair_{uuid}"
rdf.extend(
[
(key_indv, RDF.type, OTEIO.DictionaryKey),
(
key_indv,
EMMO.hasStringValue,
Literal(key, lang=lang),
),
(value_indv, RDF.type, OTEIO.DictionaryValue),
(value_indv, EMMO.hasValue, value_iri),
(pair, RDF.type, OTEIO.KeyValuePair),
(pair, OTEIO.hasDictionaryKey, key_indv),
(pair, OTEIO.hasDictionaryValue, value_indv),
(iri, OTEIO.hasKeyValuePair, pair),
]
)
else:
raise TypeError("container must be a mapping or sequence")
return rdf
from_dict(dct, iri, bases=None, lang='en', recognised_keys=None, keep=False)
¶
Serialise a dict as RDF.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
dct |
dict |
The dict to be saved. |
required |
iri |
str |
IRI of individual that stands for the dict. |
required |
bases |
Optional[Sequence] |
Parent class(es) or the dict. Unused. |
None |
lang |
str |
Language to use for keys. |
'en' |
recognised_keys |
Optional[Union[Dict, str]] |
An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
|
None |
keep |
bool |
Whether to keep the key-value pair representation for items serialised with recognised_keys. Note that this will duplicate potential large literal values. |
False |
Returns:
Type | Description |
---|---|
list |
List of RDF triples. |
Source code in tripper/convert/convert.py
def from_dict(
dct: dict,
iri: str,
bases: "Optional[Sequence]" = None,
lang: str = "en",
recognised_keys: "Optional[Union[Dict, str]]" = None,
keep: bool = False,
) -> list:
"""Serialise a dict as RDF.
Arguments:
dct: The dict to be saved.
iri: IRI of individual that stands for the dict.
bases: Parent class(es) or the dict. Unused.
lang: Language to use for keys.
recognised_keys: An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
`BASIC_RECOGNISED_KEYS` module will be used.
keep: Whether to keep the key-value pair representation for
items serialised with recognised_keys. Note that this
will duplicate potential large literal values.
Returns:
List of RDF triples.
"""
del bases # silence pylint about unused variable
warnings.warn(
"from_dict() is deprecated. Use from_container() instead",
DeprecationWarning,
stacklevel=2,
)
return from_container(
dct, iri, lang=lang, recognised_keys=recognised_keys, keep=keep
)
load_container(ts, iri, recognised_keys=None, ignore_unrecognised=False)
¶
Deserialise a Python container object from a triplestore.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ts |
Triplestore |
Triplestore from which to fetch the dict. |
required |
iri |
str |
IRI of individual that stands for the dict to fetch. |
required |
recognised_keys |
Optional[Union[Dict, str]] |
An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
|
None |
ignore_unrecognised |
bool |
Ignore relations that has |
False |
Returns:
Type | Description |
---|---|
Union[dict, list] |
A Python container object corresponding to |
Source code in tripper/convert/convert.py
def load_container(
ts: "Triplestore",
iri: str,
recognised_keys: "Optional[Union[Dict, str]]" = None,
ignore_unrecognised: bool = False,
) -> "Union[dict, list]":
"""Deserialise a Python container object from a triplestore.
Arguments:
ts: Triplestore from which to fetch the dict.
iri: IRI of individual that stands for the dict to fetch.
recognised_keys: An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
`BASIC_RECOGNISED_KEYS` module will be used.
ignore_unrecognised: Ignore relations that has `iri` as subject and
a predicate that is not among the values of `recognised_keys`
or `rdf:type`. The default is to raise an exception.
Returns:
A Python container object corresponding to `iri`.
"""
# pylint: disable=too-many-branches
if iri == RDF.nil:
return []
if recognised_keys == "basic":
recognised_keys = BASIC_RECOGNISED_KEYS
recognised_iris = (
{v: k for k, v in recognised_keys.items()} # type: ignore
if recognised_keys
else {}
)
parents = set(ts.objects(iri, RDF.type))
def get_obj(value):
"""Return Python object for `value`."""
value_type = ts.value(value, RDF.type)
if value_type == OTEIO.Dictionary:
return load_container(ts, value, recognised_keys=recognised_keys)
if value_type == RDF.List:
return load_container(ts, value, recognised_keys=recognised_keys)
if value == OWL.Nothing:
return None
return value.value if isinstance(value, Literal) else value
if OTEIO.Dictionary in parents:
container = {}
for pred, obj in ts.predicate_objects(iri):
if pred == OTEIO.hasKeyValuePair:
key_iri = ts.value(obj, OTEIO.hasDictionaryKey)
key = ts.value(key_iri, EMMO.hasStringValue)
value_iri = ts.value(obj, OTEIO.hasDictionaryValue)
value = ts.value(value_iri, EMMO.hasValue)
container[str(key)] = get_obj(value)
elif pred in recognised_iris:
container[recognised_iris[pred]] = get_obj(obj)
elif not ignore_unrecognised and pred not in (
RDF.type,
RDFS.subClassOf,
):
raise ValueError(
f"Unrecognised predicate '{pred}' in dict: {iri}"
)
# Recognised IRIs
if recognised_keys:
iris = {v: k for k, v in recognised_keys.items()} # type: ignore
for _, p, o in ts.triples(subject=iri):
key = iris.get(p) # type: ignore
if key and p in iris and key not in container:
container[key] = (
o.value
if isinstance(o, Literal) # type: ignore
else o
)
elif RDF.List in parents:
container = [] # type: ignore
while True:
first = ts.value(iri, RDF.first)
rest = ts.value(iri, RDF.rest)
container.append(get_obj(first)) # type: ignore
if rest == RDF.nil:
break
iri = rest
else:
raise TypeError(
f"iri '{iri}' should be either a rdf:List or an oteio:Dictionary"
)
return container
load_dict(ts, iri, recognised_keys=None)
¶
Deserialise a dict from an RDF triplestore.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ts |
Triplestore |
Triplestore from which to fetch the dict. |
required |
iri |
str |
IRI of individual that stands for the dict to fetch. |
required |
recognised_keys |
Optional[Union[Dict, str]] |
An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
|
None |
Returns:
Type | Description |
---|---|
Union[dict, list] |
A dict corresponding to |
Source code in tripper/convert/convert.py
def load_dict(
ts: "Triplestore",
iri: str,
recognised_keys: "Optional[Union[Dict, str]]" = None,
) -> "Union[dict, list]":
"""Deserialise a dict from an RDF triplestore.
Arguments:
ts: Triplestore from which to fetch the dict.
iri: IRI of individual that stands for the dict to fetch.
recognised_keys: An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
`BASIC_RECOGNISED_KEYS` module will be used.
Returns:
A dict corresponding to `iri`.
"""
warnings.warn(
"load_dict() is deprecated. Use load_container() instead",
DeprecationWarning,
stacklevel=2,
)
return load_container(ts, iri, recognised_keys=recognised_keys)
save_container(ts, container, iri, lang='en', recognised_keys=None, keep=False)
¶
Save a basic Python container object to a triplestore.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ts |
Triplestore |
Triplestore to which to write the container object. |
required |
container |
Union[Mapping[str, Any], Sequence[Any]] |
The container object to be saved. |
required |
iri |
str |
IRI of individual that stands for the container object. |
required |
lang |
str |
Language to use for keys. |
'en' |
recognised_keys |
Optional[Union[Dict, str]] |
An optional dict that maps dict mapping that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
|
None |
keep |
bool |
Whether to keep the key-value pair representation for items serialised with recognised_keys. Note that this will duplicate potential large literal values. |
False |
Source code in tripper/convert/convert.py
def save_container(
ts: "Triplestore",
container: "Union[Mapping[str, Any], Sequence[Any]]",
iri: str,
lang: str = "en",
recognised_keys: "Optional[Union[Dict, str]]" = None,
keep: bool = False,
) -> None:
"""Save a basic Python container object to a triplestore.
Arguments:
ts: Triplestore to which to write the container object.
container: The container object to be saved.
iri: IRI of individual that stands for the container object.
lang: Language to use for keys.
recognised_keys: An optional dict that maps dict mapping that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
`BASIC_RECOGNISED_KEYS` module will be used.
keep: Whether to keep the key-value pair representation for
items serialised with recognised_keys. Note that this
will duplicate potential large literal values.
"""
if "rdf" not in ts.namespaces:
ts.bind("rdf", RDF)
if "dcat" not in ts.namespaces:
ts.bind("dcat", DCAT)
if "emmo" not in ts.namespaces:
ts.bind("emmo", EMMO)
if "oteio" not in ts.namespaces:
ts.bind("oteio", OTEIO)
ts.add_triples(
from_container(
container,
iri,
lang=lang,
recognised_keys=recognised_keys,
keep=keep,
)
)
save_dict(ts, dct, iri, bases=None, lang='en', recognised_keys=None, keep=False)
¶
Save a dict to a triplestore.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ts |
Triplestore |
Triplestore to which to write the dict. |
required |
dct |
Mapping[str, Any] |
The dict to be saved. |
required |
iri |
str |
IRI of individual that stands for the dict. |
required |
bases |
Optional[Sequence] |
Parent class(es) or the dict. Unused. |
None |
lang |
str |
Language to use for keys. |
'en' |
recognised_keys |
Optional[Union[Dict, str]] |
An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
|
None |
keep |
bool |
Whether to keep the key-value pair representation for items serialised with recognised_keys. Note that this will duplicate potential large literal values. |
False |
Source code in tripper/convert/convert.py
def save_dict(
ts: "Triplestore",
dct: "Mapping[str, Any]",
iri: str,
bases: "Optional[Sequence]" = None,
lang: str = "en",
recognised_keys: "Optional[Union[Dict, str]]" = None,
keep: bool = False,
) -> None:
"""Save a dict to a triplestore.
Arguments:
ts: Triplestore to which to write the dict.
dct: The dict to be saved.
iri: IRI of individual that stands for the dict.
bases: Parent class(es) or the dict. Unused.
lang: Language to use for keys.
recognised_keys: An optional dict that maps dict keys that
correspond to IRIs of recognised RDF properties.
If set to the special string "basic", the
`BASIC_RECOGNISED_KEYS` module will be used.
keep: Whether to keep the key-value pair representation for
items serialised with recognised_keys. Note that this
will duplicate potential large literal values.
"""
del bases # silence pylint about unused variable
warnings.warn(
"save_dict() is deprecated. Use save_container() instead",
DeprecationWarning,
stacklevel=2,
)
return save_container(
ts, dct, iri, lang=lang, recognised_keys=recognised_keys, keep=keep
)