Skip to content
Open
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
### Fixed

- Preserved RDF literal lexical forms when converting through RDFLib, including canonical double output, large numeric values, and compound literal handling.
- Fixed the active context clone dropping the default base direction: `@direction` now survives context layers like `@language`. Fixes [issue #337](https://github.com/digitalbazaar/pyld/issues/337).
- Fixed `KeyError` when a context sets `@direction: null` and no default base direction is in effect.
- Fixed `iri_resolver.unresolve()` query/fragment reconstruction while cleaning up the resolver docstring.
- Invalid IRI base values within lists are now skipped when serializing to RDF. Fixes [toRdf#tli12](https://w3c.github.io/json-ld-api/tests/toRdf-manifest#tli12) and [toRdf#tli14](https://w3c.github.io/json-ld-api/tests/toRdf-manifest#tli14).
- Literals with invalid `@language` no longer output triples. Fixes [toRdf#twf05](https://w3c.github.io/json-ld-api/tests/toRdf-manifest#twf05).
Expand Down
5 changes: 4 additions & 1 deletion lib/pyld/jsonld.py
Original file line number Diff line number Diff line change
Expand Up @@ -3536,7 +3536,8 @@ def _process_context(
code='invalid context entry',
)
if value is None:
del rval['@direction']
# mirror JS `delete`: a no-op when no direction is set
rval.pop('@direction', None)
elif value != 'ltr' and value != 'rtl':
raise JsonLdError(
'Invalid JSON-LD syntax; @direction value must be null, "ltr", or "rtl".',
Expand Down Expand Up @@ -6310,6 +6311,8 @@ def _clone_active_context(self, active_ctx):
child['previousContext'] = active_ctx['previousContext']
if '@language' in active_ctx:
child['@language'] = active_ctx['@language']
if '@direction' in active_ctx:
child['@direction'] = active_ctx['@direction']
if '@vocab' in active_ctx:
child['@vocab'] = active_ctx['@vocab']
return child
Expand Down
106 changes: 106 additions & 0 deletions tests/jsonld/test_expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,3 +568,109 @@ def test_blank_node_prefixes():
expanded = jsonld.expand(input)

assert expanded == expected


# Issue 337
def test_default_direction_survives_context_layers():
"""
The default @direction should be kept across context layers, like the
default @language.
"""
input = {
"@context": [
{"@language": "en", "@direction": "rtl"},
{"dummy": "http://example.com/dummy"},
],
"http://example.com/p": "v",
}

expected = [
{
"http://example.com/p": [
{"@language": "en", "@direction": "rtl", "@value": "v"}
],
}
]

expanded = jsonld.expand(input)

assert expanded == expected

# Issue 337
def test_default_direction_inherited_into_scoped_context():
"""
A property-scoped context should inherit the default @direction.
"""
input = {
"@context": {
"@language": "en",
"@direction": "rtl",
"thing": {
"@id": "http://example.com/thing",
"@context": {"other": "http://example.com/other"},
},
},
"thing": {"http://example.com/label": "hello"},
}

expected = [
{
"http://example.com/thing": [
{
"http://example.com/label": [
{
"@language": "en",
"@direction": "rtl",
"@value": "hello",
}
],
}
],
}
]

expanded = jsonld.expand(input)

assert expanded == expected

# Issue 337
def test_scoped_context_can_override_or_clear_default_direction():
"""
A scoped @direction entry should still override or clear the default.
"""
input = {
"@context": {
"@direction": "rtl",
"ltr": {
"@id": "http://example.com/ltr",
"@context": {"@direction": "ltr"},
},
"none": {
"@id": "http://example.com/none",
"@context": {"@direction": None},
},
},
"ltr": {"http://example.com/label": "a"},
"none": {"http://example.com/label": "b"},
}

expected = [
{
"http://example.com/ltr": [
{
"http://example.com/label": [
{"@direction": "ltr", "@value": "a"}
],
}
],
"http://example.com/none": [
{
"http://example.com/label": [{"@value": "b"}],
}
],
}
]

expanded = jsonld.expand(input)

assert expanded == expected