Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions tests/datadoc/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,36 @@
pytest.importorskip("requests")


def test_normalise_context():
"""Test normalise_context()."""
from tripper.datadoc.dataset import CONTEXT_URL, normalise_context

assert not normalise_context(None)
assert normalise_context({"a": "ex:a"}) == {"a": "ex:a"}
assert normalise_context([{"a": "ex:a"}]) == {"a": "ex:a"}
assert normalise_context([{"a": "ex:a"}, {"b": "ex:b"}]) == {
"a": "ex:a",
"b": "ex:b",
}
assert normalise_context([{"a": "ex:a"}, {"b": "ex:b"}, None]) == {
"a": "ex:a",
"b": "ex:b",
}
assert normalise_context([{"a": "ex:a"}, [{"b": "ex:b"}]]) == {
"a": "ex:a",
"b": "ex:b",
}
assert normalise_context([{"a": "ex:a"}, {"b": "ex:b"}, []]) == {
"a": "ex:a",
"b": "ex:b",
}
context = normalise_context([CONTEXT_URL, {"a": "ex:a"}, {"b": "ex:b"}])
assert context["@version"] == 1.1
assert context["status"] == "adms:status"
assert context["a"] == "ex:a"
assert context["b"] == "ex:b"


def test_get_jsonld_context():
"""Test get_jsonld_context()."""
from tripper.datadoc import get_jsonld_context
Expand Down Expand Up @@ -36,8 +66,8 @@ def test_get_jsonld_context():
context3 = get_jsonld_context(context={"newkey": "onto:newkey"})
assert context3["newkey"] == "onto:newkey"

with pytest.raises(TypeError):
get_jsonld_context(context=[None])
context4 = get_jsonld_context(context=[None])
assert context4 == context


def test_get_prefixes():
Expand Down Expand Up @@ -137,7 +167,6 @@ def test_as_jsonld():
"""Test as_jsonld()."""
from tripper import DCAT, EMMO, Namespace
from tripper.datadoc import as_jsonld
from tripper.datadoc.dataset import CONTEXT_URL

with pytest.raises(ValueError):
as_jsonld({})
Expand All @@ -148,9 +177,11 @@ def test_as_jsonld():
context = {"ex": EX, "a": "ex:a"}

d = as_jsonld(dct, _context=context)
assert len(d["@context"]) == 2
assert d["@context"][0] == CONTEXT_URL
assert d["@context"][1] == context
ctx = d["@context"]
assert ctx["dcat"] == DCAT
assert ctx["emmo"] == EMMO
assert ctx["ex"] == EX
assert ctx["a"] == "ex:a"
assert d["@id"] == EX.indv
assert d["@type"] == "owl:NamedIndividual"
assert d.a == "val"
Expand Down
100 changes: 72 additions & 28 deletions tripper/datadoc/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
if keywords is None:
keywords = Keywords()

if "@id" not in dct:
if "@id" not in dct and "@graph" not in dct:
raise ValueError("`dct` must have an '@id' key")

all_prefixes = get_prefixes()
Expand Down Expand Up @@ -338,6 +338,39 @@
return values


def normalise_context(
context: "Union[str, dict, Sequence[Union[str, dict]]]",
timeout: float = 5,
) -> dict:
"""Return `context` as a normalised dict.

Arguments:
context: Context to normalise.
timeout: Timeout in seconds when downloading from the web.

"""
if isinstance(context, (str, dict, None.__class__)):
context = [context]
ctx = {}
for token in context:
if token is None:
pass
elif isinstance(token, str):
with openfile(token, timeout=timeout, mode="rt") as f:
content = f.read()
ctx.update(normalise_context(json.loads(content)["@context"]))
elif isinstance(token, dict):
ctx.update(token)
elif isinstance(token, list):
ctx.update(normalise_context(token))
else:
raise TypeError(

Check warning on line 367 in tripper/datadoc/dataset.py

View check run for this annotation

Codecov / codecov/patch

tripper/datadoc/dataset.py#L367

Added line #L367 was not covered by tests
"`context` must be a string (URL), dict or a sequence of "
f"strings and dicts. Not '{type(token)}'"
)
return ctx


def get_jsonld_context(
context: "Optional[Union[str, dict, Sequence[Union[str, dict]]]]" = None,
timeout: float = 5,
Expand All @@ -362,27 +395,15 @@

if fromfile:
with open(CONTEXT_PATH, "r", encoding="utf-8") as f:
ctx = json.load(f)["@context"]
ctx = normalise_context(json.load(f)["@context"], timeout=timeout)
else:
r = requests.get(CONTEXT_URL, allow_redirects=True, timeout=timeout)
ctx = json.loads(r.content)["@context"]

if isinstance(context, (str, dict)):
context = [context]
ctx = normalise_context(
json.loads(r.content)["@context"], timeout=timeout
)

if context:
for token in context:
if isinstance(token, str):
with openfile(token, timeout=timeout, mode="rt") as f:
content = f.read()
ctx.update(json.loads(content)["@context"])
elif isinstance(token, dict):
ctx.update(token)
else:
raise TypeError(
"`context` must be a string (URL), dict or a sequence of "
f"strings and dicts. Not '{type(token)}'"
)
ctx.update(normalise_context(context, timeout=timeout))

return ctx

Expand Down Expand Up @@ -669,23 +690,42 @@
if keywords is None:
keywords = Keywords()

d = AttrDict()
dct = dct.copy()

# Id of base entry that is documented
_entryid = kwargs.pop("_entryid", None)

d = AttrDict()
dct = dct.copy()
# Marks that the top-level dict contains a @graph keyword
_graph = kwargs.pop("_graph", None)

if not _entryid:
if "@context" in dct:
d["@context"] = dct.pop("@context")
else:
d["@context"] = CONTEXT_URL
if "_context" in kwargs and kwargs["_context"]:
add(d, "@context", kwargs.pop("_context"))
# The context
context = get_jsonld_context(dct.pop("@context", {}))
if "_context" in kwargs:
context.update(normalise_context(kwargs.pop("_context")))

if not _entryid and not _graph:
d["@context"] = context

if "@graph" in dct:
d["@graph"] = []
for subdict in dct["@graph"]:
d["@graph"].append(

Check warning on line 713 in tripper/datadoc/dataset.py

View check run for this annotation

Codecov / codecov/patch

tripper/datadoc/dataset.py#L711-L713

Added lines #L711 - L713 were not covered by tests
as_jsonld(
dct=subdict,
type=type,
keywords=keywords,
prefixes=prefixes,
_graph=True,
_context=context,
**kwargs,
)
)
return d

Check warning on line 724 in tripper/datadoc/dataset.py

View check run for this annotation

Codecov / codecov/patch

tripper/datadoc/dataset.py#L724

Added line #L724 was not covered by tests

all_prefixes = {}
if not _entryid:
all_prefixes = get_prefixes(context=d["@context"])
all_prefixes = get_prefixes(context=context)
all_prefixes.update(keywords.data.get("prefixes", {}))
if prefixes:
all_prefixes.update(prefixes)
Expand Down Expand Up @@ -761,6 +801,8 @@
keywords=keywords,
prefixes=all_prefixes,
_entryid=_entryid,
_context=context,
_graph=_graph,
)
elif isinstance(v, dict):
if "datatype" in keywords[k]:
Expand All @@ -772,6 +814,8 @@
keywords=keywords,
prefixes=all_prefixes,
_entryid=_entryid,
_context=context,
_graph=_graph,
)

return d
Expand Down
Loading