Skip to content

Commit 4b96e9d

Browse files
authored
BREAKING CHANGE: Don't use publicID as the name for the default graph. (#2406)
When parsing data into a `ConjunctiveGraph` or `Dataset`, the triples in the default graphs in the sources were loaded into a graph named `publicID`. This behaviour has been changed, and now the triples from the default graph in source RDF documents will be loaded into `ConjunctiveGraph.default_context` or `Dataset.default_context`. The `publicID` parameter to `ConjunctiveGraph.parse` and `Dataset.parse` constructors will now only be used as the base URI for relative URI resolution. - Fixes #2404 - Fixes #2375 - Fixes #436 - Fixes #1804
1 parent ace4acd commit 4b96e9d

26 files changed

+448
-167
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Help with maintenance of all of the RDFLib family of packages is always welcome
4343

4444
## Versions & Releases
4545

46-
* `6.4.0a0` current `main` branch
46+
* `7.0.0a0` current `main` branch
4747
* `6.x.y` current release and support Python 3.7+ only. Many improvements over 5.0.0
4848
* see [Releases](https://github.com/RDFLib/rdflib/releases)
4949
* `5.x.y` supports Python 2.7 and 3.4+ and is [mostly backwards compatible with 4.2.2](https://rdflib.readthedocs.io/en/stable/upgrade4to5.html).

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
5757
autodoc_default_options = {"special-members": True}
58+
autodoc_inherit_docstrings = True
5859

5960
# https://github.com/tox-dev/sphinx-autodoc-typehints
6061
always_document_param_types = True

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ If you are familiar with RDF and are looking for details on how RDFLib handles i
6666
namespaces_and_bindings
6767
persistence
6868
merging
69+
upgrade6to7
6970
upgrade5to6
7071
upgrade4to5
7172
security_considerations

docs/upgrade6to7.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
.. _upgrade4to5: Upgrading from RDFLib version 6 to 7
2+
3+
============================================
4+
Upgrading 6 to 7
5+
============================================
6+
7+
New behaviour for ``publicID`` in ``parse`` methods.
8+
----------------------------------------------------
9+
10+
Before version 7, the ``publicID`` argument to the
11+
:meth:`~rdflib.graph.ConjunctiveGraph.parse` and
12+
:meth:`~rdflib.graph.Dataset.parse` methods was used as the name for the default
13+
graph, and triples from the default graph in a source were loaded into the graph
14+
named ``publicID``.
15+
16+
In version 7, the ``publicID`` argument is only used as the base URI for relative
17+
URI resolution as defined in `IETF RFC 3986
18+
<https://datatracker.ietf.org/doc/html/rfc3986#section-5.1.4>`_.
19+
20+
To accommodate this change, ensure that use of the ``publicID`` argument is
21+
consistent with the new behaviour.
22+
23+
If you want to load triples from a format that does not support named graphs
24+
into a named graph, use the following code:
25+
26+
.. code-block:: python
27+
28+
from rdflib import ConjunctiveGraph
29+
30+
cg = ConjunctiveGraph()
31+
cg.get_context("example:graph_name").parse("http://example.com/source.ttl", format="turtle")
32+
33+
If you want to move triples from the default graph into a named graph, use the
34+
following code:
35+
36+
.. code-block:: python
37+
38+
from rdflib import ConjunctiveGraph
39+
40+
cg = ConjunctiveGraph()
41+
cg.parse("http://example.com/source.trig", format="trig")
42+
destination_graph = cg.get_context("example:graph_name")
43+
for triple in cg.default_context.triples((None, None, None)):
44+
destination_graph.add(triple)
45+
cg.default_context.remove(triple)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "rdflib"
3-
version = "6.4.0a0"
3+
version = "7.0.0a0"
44
description = """RDFLib is a Python library for working with RDF, \
55
a simple yet powerful language for representing information."""
66
authors = ["Daniel 'eikeon' Krech <eikeon@eikeon.com>"]

rdflib/graph.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,26 +1400,26 @@ def parse(
14001400
:doc:`Security Considerations </security_considerations>`
14011401
documentation.
14021402
1403-
:Parameters:
1404-
1405-
- ``source``: An InputSource, file-like object, or string. In the case
1406-
of a string the string is the location of the source.
1407-
- ``location``: A string indicating the relative or absolute URL of
1408-
the source. Graph's absolutize method is used if a relative location
1403+
:param source: An `InputSource`, file-like object, `Path` like object,
1404+
or string. In the case of a string the string is the location of the
1405+
source.
1406+
:param location: A string indicating the relative or absolute URL of the
1407+
source. `Graph`'s absolutize method is used if a relative location
14091408
is specified.
1410-
- ``file``: A file-like object.
1411-
- ``data``: A string containing the data to be parsed.
1412-
- ``format``: Used if format can not be determined from source, e.g.
1409+
:param file: A file-like object.
1410+
:param data: A string containing the data to be parsed.
1411+
:param format: Used if format can not be determined from source, e.g.
14131412
file extension or Media Type. Defaults to text/turtle. Format
14141413
support can be extended with plugins, but "xml", "n3" (use for
14151414
turtle), "nt" & "trix" are built in.
1416-
- ``publicID``: the logical URI to use as the document base. If None
1415+
:param publicID: the logical URI to use as the document base. If None
14171416
specified the document location is used (at least in the case where
1418-
there is a document location).
1419-
1420-
:Returns:
1421-
1422-
- self, the graph instance.
1417+
there is a document location). This is used as the base URI when
1418+
resolving relative URIs in the source document, as defined in `IETF
1419+
RFC 3986
1420+
<https://datatracker.ietf.org/doc/html/rfc3986#section-5.1.4>`_,
1421+
given the source document does not define a base URI.
1422+
:return: ``self``, i.e. the :class:`~rdflib.graph.Graph` instance.
14231423
14241424
Examples:
14251425
@@ -2206,15 +2206,18 @@ def parse(
22062206
**args: Any,
22072207
) -> "Graph":
22082208
"""
2209-
Parse source adding the resulting triples to its own context
2210-
(sub graph of this graph).
2209+
Parse source adding the resulting triples to its own context (sub graph
2210+
of this graph).
22112211
22122212
See :meth:`rdflib.graph.Graph.parse` for documentation on arguments.
22132213
2214+
If the source is in a format that does not support named graphs it's triples
2215+
will be added to the default graph (i.e. `Dataset.default_context`).
2216+
22142217
:Returns:
22152218
2216-
The graph into which the source was parsed. In the case of n3
2217-
it returns the root context.
2219+
The graph into which the source was parsed. In the case of n3 it returns
2220+
the root context.
22182221
22192222
.. caution::
22202223
@@ -2228,6 +2231,14 @@ def parse(
22282231
For information on available security measures, see the RDFLib
22292232
:doc:`Security Considerations </security_considerations>`
22302233
documentation.
2234+
2235+
*Changed in 7.0*: The ``publicID`` argument is no longer used as the
2236+
identifier (i.e. name) of the default graph as was the case before
2237+
version 7.0. In the case of sources that do not support named graphs,
2238+
the ``publicID`` parameter will also not be used as the name for the
2239+
graph that the data is loaded into, and instead the triples from sources
2240+
that do not support named graphs will be loaded into the default graph
2241+
(i.e. `ConjunctionGraph.default_context`).
22312242
"""
22322243

22332244
source = create_input_source(
@@ -2246,12 +2257,8 @@ def parse(
22462257
# create_input_source will ensure that publicId is not None, though it
22472258
# would be good if this guarantee was made more explicit i.e. by type
22482259
# hint on InputSource (TODO/FIXME).
2249-
g_id: str = publicID and publicID or source.getPublicId()
2250-
if not isinstance(g_id, Node):
2251-
g_id = URIRef(g_id)
22522260

2253-
context = Graph(store=self.store, identifier=g_id)
2254-
context.remove((None, None, None)) # hmm ?
2261+
context = self.default_context
22552262
context.parse(source, publicID=publicID, format=format, **args)
22562263
# TODO: FIXME: This should not return context, but self.
22572264
return context
@@ -2459,6 +2466,14 @@ def parse(
24592466
**args: Any,
24602467
) -> "Graph":
24612468
"""
2469+
Parse an RDF source adding the resulting triples to the Graph.
2470+
2471+
See :meth:`rdflib.graph.Graph.parse` for documentation on arguments.
2472+
2473+
The source is specified using one of source, location, file or data.
2474+
2475+
If the source is in a format that does not support named graphs it's triples
2476+
will be added to the default graph (i.e. `Dataset.default_context`).
24622477
24632478
.. caution::
24642479
@@ -2472,6 +2487,14 @@ def parse(
24722487
For information on available security measures, see the RDFLib
24732488
:doc:`Security Considerations </security_considerations>`
24742489
documentation.
2490+
2491+
*Changed in 7.0*: The ``publicID`` argument is no longer used as the
2492+
identifier (i.e. name) of the default graph as was the case before
2493+
version 7.0. In the case of sources that do not support named graphs,
2494+
the ``publicID`` parameter will also not be used as the name for the
2495+
graph that the data is loaded into, and instead the triples from sources
2496+
that do not support named graphs will be loaded into the default graph
2497+
(i.e. `ConjunctionGraph.default_context`).
24752498
"""
24762499

24772500
c = ConjunctiveGraph.parse(

rdflib/plugins/sparql/sparql.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,17 @@ def dataset(self) -> ConjunctiveGraph:
312312
return self._dataset
313313

314314
def load(self, source: URIRef, default: bool = False, **kwargs: Any) -> None:
315+
"""
316+
Load data from the source into the query context's.
317+
318+
:param source: The source to load from.
319+
:param default: If `True`, triples from the source will be added to the
320+
default graph, otherwise it will be loaded into a graph with
321+
``source`` URI as its name.
322+
:param kwargs: Keyword arguments to pass to
323+
:meth:`rdflib.graph.Graph.parse`.
324+
"""
325+
315326
def _load(graph, source):
316327
try:
317328
return graph.parse(source, format="turtle", **kwargs)
@@ -342,7 +353,7 @@ def _load(graph, source):
342353
if default:
343354
_load(self.graph, source)
344355
else:
345-
_load(self.dataset, source)
356+
_load(self.dataset.get_context(source), source)
346357

347358
def __getitem__(self, key: Union[str, Path]) -> Optional[Union[str, Path]]:
348359
# in SPARQL BNodes are just labels
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"quad_count": 6,
2+
"quad_count": 8,
33
"exact_match": true
44
}

test/data/variants/more_quads.jsonld

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,65 @@
11
{
2-
"@graph": [
3-
{
4-
"@graph": [
2+
"@graph": [
53
{
6-
"@id": "example:s20",
7-
"example:p20": {
8-
"@id": "example:o20"
9-
}
4+
"@id": "example:s10",
5+
"example:p10": {
6+
"@id": "example:o10"
7+
}
108
},
119
{
12-
"@id": "example:s21",
13-
"example:p21": {
14-
"@id": "example:o21"
15-
}
10+
"@id": "example:s01",
11+
"example:p01": {
12+
"@id": "example:o01"
13+
}
14+
},
15+
{
16+
"@id": "example:s00",
17+
"example:p00": {
18+
"@id": "example:o02"
19+
}
20+
},
21+
{
22+
"@id": "example:s11",
23+
"example:p11": {
24+
"@id": "example:o11"
25+
}
26+
},
27+
{
28+
"@id": "example:g3",
29+
"@graph": [
30+
{
31+
"@id": "example:s31",
32+
"example:p31": {
33+
"@id": "example:o31"
34+
}
35+
},
36+
{
37+
"@id": "example:s30",
38+
"example:p30": {
39+
"@id": "example:o30"
40+
}
41+
}
42+
]
43+
},
44+
{
45+
"@id": "example:g2",
46+
"@graph": [
47+
{
48+
"@id": "example:s21",
49+
"example:p21": {
50+
"@id": "example:o21"
51+
}
52+
},
53+
{
54+
"@id": "example:s20",
55+
"example:p20": {
56+
"@id": "example:o20"
57+
}
58+
}
59+
]
1660
}
17-
],
18-
"@id": "example:g2"
19-
},
20-
{
21-
"@id": "example:s00",
22-
"p00": "example:o02"
23-
},
24-
{
25-
"@id": "example:s01",
26-
"p01": "example:o01"
27-
},
28-
{
29-
"@id": "example:s10",
30-
"p10": "example:o10"
31-
},
32-
{
33-
"@id": "example:s11",
34-
"p11": "example:o11"
61+
],
62+
"@context": {
63+
"example": "http://example.org/"
3564
}
36-
],
37-
"@context": {
38-
"p10": {
39-
"@id": "http://example.org/p10",
40-
"@type": "@id"
41-
},
42-
"p01": {
43-
"@id": "http://example.org/p01",
44-
"@type": "@id"
45-
},
46-
"p00": {
47-
"@id": "http://example.org/p00",
48-
"@type": "@id"
49-
},
50-
"p11": {
51-
"@id": "http://example.org/p11",
52-
"@type": "@id"
53-
},
54-
"example": "http://example.org/"
55-
}
5665
}

test/data/variants/more_quads.nq

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
<http://example.org/s00> <http://example.org/p00> <http://example.org/o02> .
2-
<http://example.org/s01> <http://example.org/p01> <http://example.org/o01> .
31
<http://example.org/s10> <http://example.org/p10> <http://example.org/o10> .
2+
<http://example.org/s01> <http://example.org/p01> <http://example.org/o01> .
3+
<http://example.org/s00> <http://example.org/p00> <http://example.org/o02> .
44
<http://example.org/s11> <http://example.org/p11> <http://example.org/o11> .
5-
<http://example.org/s20> <http://example.org/p20> <http://example.org/o20> <http://example.org/g2> .
65
<http://example.org/s21> <http://example.org/p21> <http://example.org/o21> <http://example.org/g2> .
6+
<http://example.org/s20> <http://example.org/p20> <http://example.org/o20> <http://example.org/g2> .
7+
<http://example.org/s31> <http://example.org/p31> <http://example.org/o31> <http://example.org/g3> .
8+
<http://example.org/s30> <http://example.org/p30> <http://example.org/o30> <http://example.org/g3> .

test/data/variants/more_quads.trig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ example:g2 {
1313
example:s20 example:p20 example:o20 .
1414
example:s21 example:p21 example:o21 .
1515
}
16+
17+
example:g3 {
18+
example:s30 example:p30 example:o30 .
19+
example:s31 example:p31 example:o31 .
20+
}

test/data/variants/simple_triple.n3

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<http://example.org/subject> <http://example.org/predicate> <http://example.org/object> .

test/data/variants/simple_triple.trig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<http://example.org/subject>
2+
<http://example.org/predicate> <http://example.org/object> .

test/test_conjunctivegraph/test_conjunctive_graph.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_bnode_publicid():
2222
b = BNode()
2323
data = "<d:d> <e:e> <f:f> ."
2424
print("Parsing %r into %r" % (data, b))
25-
g.parse(data=data, format="turtle", publicID=b)
25+
g.get_context(b).parse(data=data, format="turtle", publicID=b)
2626

2727
triples = list(g.get_context(b).triples((None, None, None)))
2828
if not triples:

0 commit comments

Comments
 (0)