Skip to content

Commit c1d8094

Browse files
committed
Add the ability to pass a custom identifierIssuer to to_rdf
1 parent d2cd732 commit c1d8094

6 files changed

Lines changed: 41 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- `pyld.FileDocumentLoader`: a document loader for local `file:` URLs with optional root confinement.
77
- `pyld.SchemeDirectedDocumentLoader`: a document loader that dispatches URL
88
strings to per-scheme loaders.
9+
- `jsonld.to_rdf()` now accepts an `identifierIssuer` option with an
10+
`IdentifierIssuer` instance for blank node identifiers. Defaults to `IdentifierIssuer('_:b')`,
11+
which preserves the previous behaviour.
912

1013
## 3.2.0 - 2026-08-17
1114

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Here are some quick examples to get started:
6565

6666
```python
6767
from pyld import jsonld
68+
from pyld.identifier_issuer import IdentifierIssuer
6869
import json
6970

7071
doc = {
@@ -126,6 +127,12 @@ normalized = jsonld.normalize(
126127
doc, {'algorithm': 'URDNA2015', 'format': 'application/n-quads'})
127128
# normalized is a string that is a canonical representation of the document
128129
# that can be used for hashing, comparison, etc.
130+
131+
# convert a document to RDF with a custom blank node issuer
132+
issuer = IdentifierIssuer('_:doc')
133+
rdf = jsonld.to_rdf(
134+
doc,
135+
{'identifierIssuer': issuer, 'format': 'application/n-quads'})
129136
```
130137

131138
## Features & conformance
@@ -421,4 +428,4 @@ See [`LICENSE`](./LICENSE) file for details.
421428
The PyLD library is maintained by [Miel Vander
422429
Sande](https://github.com/mielvds), [Anatoly
423430
Scherbakov](https://github.com/anatoly-scherbakov) and [Digital
424-
Bazaar](https://github.com/digitalbazaar) (Original authors of `PyLD`).
431+
Bazaar](https://github.com/digitalbazaar) (Original authors of `PyLD`).

docs/reference/to_rdf.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
show_bases: false
1313
heading_level: 3
1414

15+
Pass an `IdentifierIssuer` instance as the `identifierIssuer` option to control
16+
blank node identifiers generated during RDF conversion.
17+
1518
## Example
1619

1720
{{ example('to_rdf.py') }}

lib/pyld/jsonld.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,8 @@ def to_rdf(self, input_, options):
10071007
to produce only standard RDF (default: false).
10081008
[documentLoader(url, options)] the document loader
10091009
(default: _default_document_loader).
1010+
[identifierIssuer] an IdentifierIssuer instance to use for blank node
1011+
identifiers (default: IdentifierIssuer('_:b')).
10101012
[rdfDirection] Either 'i18n-datatype' or 'compound-literal'
10111013
(default: None).
10121014
@@ -1023,6 +1025,7 @@ def to_rdf(self, input_, options):
10231025
)
10241026
options.setdefault('extractAllScripts', True)
10251027
options.setdefault('processingMode', 'json-ld-1.1')
1028+
options.setdefault('identifierIssuer', IdentifierIssuer('_:b'))
10261029

10271030
try:
10281031
# expand input
@@ -1033,7 +1036,7 @@ def to_rdf(self, input_, options):
10331036
) from cause
10341037

10351038
# create node map for default graph (and any named graphs)
1036-
issuer = IdentifierIssuer('_:b')
1039+
issuer = options['identifierIssuer']
10371040
node_map = {'@default': {}}
10381041
self._create_node_map(expanded, node_map, '@default', issuer)
10391042
# output RDF dataset

lib/pyld/options.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import Any, Literal, TypedDict
1010

1111
from .documentloader.base import DocumentLoader, RemoteDocument
12+
from .identifier_issuer import IdentifierIssuer
1213

1314
ContextObject = dict[str, Any]
1415
Context = str | ContextObject | list[str | ContextObject]
@@ -175,6 +176,9 @@ class ToRdfOptions(ProcessingOptions, total=False):
175176
produceGeneralizedRdf: bool
176177
"""`True` to output generalized RDF, `False` to produce only standard RDF (default: `False`)."""
177178

179+
identifierIssuer: IdentifierIssuer
180+
"""An identifier issuer to use for blank node identifiers (default: `IdentifierIssuer('_:b')`)."""
181+
178182
rdfDirection: Literal['i18n-datatype']
179183
"""Only `i18n-datatype` supported."""
180184

tests/test_jsonld.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
import pyld.jsonld as jsonld
4+
from pyld.identifier_issuer import IdentifierIssuer
45

56

67
def raise_this(value):
@@ -998,6 +999,24 @@ def test_large_integer_to_rdf_double_conversion_processing_mode(self):
998999
'^^<http://www.w3.org/2001/XMLSchema#integer> .\n'
9991000
)
10001001

1002+
def test_to_rdf_uses_identifier_issuer_option(self):
1003+
input = {'http://example.org/p': [{'@list': ['a', 'b']}]}
1004+
issuer = IdentifierIssuer('_:custom')
1005+
1006+
nquads = jsonld.to_rdf(
1007+
input,
1008+
options={'format': 'application/n-quads', 'identifierIssuer': issuer},
1009+
)
1010+
1011+
assert nquads == (
1012+
'_:custom0 <http://example.org/p> _:custom1 .\n'
1013+
'_:custom1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "a" .\n'
1014+
'_:custom1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:custom2 .\n'
1015+
'_:custom2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "b" .\n'
1016+
'_:custom2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> '
1017+
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .\n'
1018+
)
1019+
10011020
def test_compound_literal_direction_without_language(self):
10021021
"""
10031022
Values with @direction should become compound literals during to_rdf

0 commit comments

Comments
 (0)