Skip to content

Commit 332c4e2

Browse files
committed
feat: deterministic longturtle serialisation using RDF canonicalization + n-triples sort (#3008)
* feat: use the RGDA1 canonicalization algorithm + lexical n-triples sort to produce deterministic longturtle serialisation * chore: normalise usage of format * chore: apply black * fix: double up of semicolons when subject is a blank node
1 parent bd9ebff commit 332c4e2

File tree

2 files changed

+40
-69
lines changed

2 files changed

+40
-69
lines changed

rdflib/plugins/serializers/longturtle.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -304,34 +304,7 @@ def predicateList(self, subject, newline=False):
304304
def verb(self, node, newline=False):
305305
self.path(node, VERB, newline)
306306

307-
def sortObjects(
308-
self, values: list[URIRef | BNode | Literal]
309-
) -> list[URIRef | BNode | Literal]:
310-
"""
311-
Perform a sort on the values where each value is a blank node. Grab the CBD of the
312-
blank node and sort it by its longturtle serialization value.
313-
314-
Identified nodes come first and the sorted blank nodes are tacked on after.
315-
"""
316-
bnode_map: dict[BNode, list[str]] = {}
317-
objects = []
318-
for value in values:
319-
if isinstance(value, BNode):
320-
bnode_map[value] = []
321-
else:
322-
objects.append(value)
323-
324-
for bnode in bnode_map:
325-
cbd = self.store.cbd(bnode).serialize(format="longturtle")
326-
bnode_map[bnode].append(cbd)
327-
328-
sorted_bnodes = sorted(
329-
[(k, v) for k, v in bnode_map.items()], key=lambda x: x[1]
330-
)
331-
return objects + [x[0] for x in sorted_bnodes]
332-
333307
def objectList(self, objects):
334-
objects = self.sortObjects(objects)
335308
count = len(objects)
336309
if count == 0:
337310
return
Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,72 @@
1-
PREFIX cn: <https://linked.data.gov.au/def/cn/>
2-
PREFIX ex: <http://example.com/>
31
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
42
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
5-
PREFIX sdo: <https://schema.org/>
3+
PREFIX schema: <https://schema.org/>
64
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
75

8-
ex:nicholas
9-
a sdo:Person ;
10-
sdo:age 41 ;
11-
sdo:alternateName
12-
"N.J. Car" ,
13-
"Nick Car" ,
6+
<http://example.com/nicholas>
7+
a schema:Person ;
8+
schema:age 41 ;
9+
schema:alternateName
1410
[
15-
sdo:name "Dr N.J. Car" ;
16-
] ;
17-
sdo:name
11+
schema:name "Dr N.J. Car" ;
12+
] ,
13+
"N.J. Car" ,
14+
"Nick Car" ;
15+
schema:name
1816
[
19-
a cn:CompoundName ;
20-
sdo:hasPart
21-
[
22-
a cn:CompoundName ;
23-
rdf:value "John" ;
24-
] ,
17+
a <https://linked.data.gov.au/def/cn/CompoundName> ;
18+
schema:hasPart
2519
[
26-
a cn:CompoundName ;
27-
rdf:value "Nicholas" ;
28-
] ,
29-
[
30-
a cn:CompoundName ;
31-
sdo:hasPart
20+
a <https://linked.data.gov.au/def/cn/CompoundName> ;
21+
schema:hasPart
3222
[
33-
a cn:CompoundName ;
23+
a <https://linked.data.gov.au/def/cn/CompoundName> ;
3424
rdf:value "Car" ;
3525
] ,
3626
[
37-
a cn:CompoundName ;
27+
a <https://linked.data.gov.au/def/cn/CompoundName> ;
3828
rdf:value "Maxov" ;
3929
] ;
30+
] ,
31+
[
32+
a <https://linked.data.gov.au/def/cn/CompoundName> ;
33+
rdf:value "Nicholas" ;
34+
] ,
35+
[
36+
a <https://linked.data.gov.au/def/cn/CompoundName> ;
37+
rdf:value "John" ;
4038
] ;
4139
] ;
42-
sdo:worksFor <https://kurrawong.ai> ;
40+
schema:worksFor <https://kurrawong.ai> ;
4341
.
4442

4543
<https://kurrawong.ai>
46-
a sdo:Organization ;
47-
sdo:location <https://kurrawong.ai/hq> ;
44+
a schema:Organization ;
45+
schema:location <https://kurrawong.ai/hq> ;
4846
.
4947

5048
<https://kurrawong.ai/hq>
51-
a sdo:Place ;
52-
sdo:address
49+
a schema:Place ;
50+
schema:address
5351
[
54-
a sdo:PostalAddress ;
55-
sdo:addressCountry
52+
a schema:PostalAddress ;
53+
schema:addressCountry
5654
[
57-
sdo:identifier "au" ;
58-
sdo:name "Australia" ;
55+
schema:identifier "au" ;
56+
schema:name "Australia" ;
5957
] ;
60-
sdo:addressLocality "Shorncliffe" ;
61-
sdo:addressRegion "QLD" ;
62-
sdo:postalCode 4017 ;
63-
sdo:streetAddress (
58+
schema:addressLocality "Shorncliffe" ;
59+
schema:addressRegion "QLD" ;
60+
schema:postalCode 4017 ;
61+
schema:streetAddress (
6462
72
6563
"Yundah"
6664
"Street"
6765
) ;
6866
] ;
69-
sdo:geo
67+
schema:geo
7068
[
71-
sdo:polygon "POLYGON((153.082403 -27.325801, 153.08241 -27.32582, 153.082943 -27.325612, 153.083010 -27.325742, 153.083543 -27.325521, 153.083456 -27.325365, 153.082403 -27.325801))"^^geo:wktLiteral ;
69+
schema:polygon "POLYGON((153.082403 -27.325801, 153.08241 -27.32582, 153.082943 -27.325612, 153.083010 -27.325742, 153.083543 -27.325521, 153.083456 -27.325365, 153.082403 -27.325801))"^^geo:wktLiteral ;
7270
] ;
73-
sdo:name "KurrawongAI HQ" ;
71+
schema:name "KurrawongAI HQ" ;
7472
.

0 commit comments

Comments
 (0)