summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Car <nicholas.car@surroundaustralia.com>2021-05-17 09:48:03 +1000
committerNicholas Car <nicholas.car@surroundaustralia.com>2021-05-17 09:48:03 +1000
commit88a353649c92da6903ea53b7396d9c1365c1b1ee (patch)
tree68cfef44d34a53d99e020bf3f8b5b8e342c8fc02
parentbb03d810ffd0504c86476f3fd5f9ee31026376f9 (diff)
parenta9aaef18c86f4bb645ee791a50c805bf0d9cecd0 (diff)
downloadrdflib-88a353649c92da6903ea53b7396d9c1365c1b1ee.tar.gz
Merge branch 'master' into docco_clean
-rw-r--r--.github/dependabot.yml12
-rw-r--r--docs/sphinx-requirements.txt2
-rw-r--r--rdflib/graph.py16
-rw-r--r--rdflib/plugins/sparql/results/txtresults.py2
-rw-r--r--rdflib/plugins/stores/sparqlstore.py2
-rw-r--r--rdflib/term.py7
-rw-r--r--setup.py2
-rw-r--r--test/test_b64_binary.py29
-rw-r--r--test/test_graph.py41
-rw-r--r--test/test_sparql.py39
-rw-r--r--test/test_sparqlstore.py13
11 files changed, 150 insertions, 15 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..62f2d35d
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 2
+updates:
+- package-ecosystem: pip
+ directory: "/"
+ schedule:
+ interval: weekly
+ open-pull-requests-limit: 10
+ ignore:
+ - dependency-name: sphinx
+ versions:
+ - 3.4.3
+ - 3.5.2
diff --git a/docs/sphinx-requirements.txt b/docs/sphinx-requirements.txt
index 403eec52..48ba7549 100644
--- a/docs/sphinx-requirements.txt
+++ b/docs/sphinx-requirements.txt
@@ -1,3 +1,3 @@
-sphinx==3.5.4
+sphinx==4.0.1
sphinxcontrib-apidoc
git+https://github.com/gniezen/n3pygments.git
diff --git a/rdflib/graph.py b/rdflib/graph.py
index 9d4431bc..d2a5e872 100644
--- a/rdflib/graph.py
+++ b/rdflib/graph.py
@@ -879,11 +879,11 @@ class Graph(Node):
for rt_2 in self.transitiveClosure(func, rt, seen):
yield rt_2
- def transitive_objects(self, subject, property, remember=None):
- """Transitively generate objects for the ``property`` relationship
+ def transitive_objects(self, subject, predicate, remember=None):
+ """Transitively generate objects for the ``predicate`` relationship
Generated objects belong to the depth first transitive closure of the
- ``property`` relationship starting at ``subject``.
+ ``predicate`` relationship starting at ``subject``.
"""
if remember is None:
remember = {}
@@ -891,15 +891,15 @@ class Graph(Node):
return
remember[subject] = 1
yield subject
- for object in self.objects(subject, property):
- for o in self.transitive_objects(object, property, remember):
+ for object in self.objects(subject, predicate):
+ for o in self.transitive_objects(object, predicate, remember):
yield o
def transitive_subjects(self, predicate, object, remember=None):
- """Transitively generate objects for the ``property`` relationship
+ """Transitively generate subjects for the ``predicate`` relationship
- Generated objects belong to the depth first transitive closure of the
- ``property`` relationship starting at ``subject``.
+ Generated subjects belong to the depth first transitive closure of the
+ ``predicate`` relationship starting at ``object``.
"""
if remember is None:
remember = {}
diff --git a/rdflib/plugins/sparql/results/txtresults.py b/rdflib/plugins/sparql/results/txtresults.py
index 426dd9a1..baa5316b 100644
--- a/rdflib/plugins/sparql/results/txtresults.py
+++ b/rdflib/plugins/sparql/results/txtresults.py
@@ -43,7 +43,7 @@ class TXTResultSerializer(ResultSerializer):
return "(no results)\n"
else:
- keys = sorted(self.result.vars)
+ keys = self.result.vars
maxlen = [0] * len(keys)
b = [
[_termString(r[k], namespace_manager) for k in keys]
diff --git a/rdflib/plugins/stores/sparqlstore.py b/rdflib/plugins/stores/sparqlstore.py
index e021e5df..26436f20 100644
--- a/rdflib/plugins/stores/sparqlstore.py
+++ b/rdflib/plugins/stores/sparqlstore.py
@@ -167,7 +167,7 @@ class SPARQLStore(SPARQLConnector, Store):
self.debug = DEBUG
assert isinstance(query, str)
- if initNs is not None:
+ if initNs is not None and len(initNs) > 0:
query = self._inject_prefixes(query, initNs)
if initBindings:
diff --git a/rdflib/term.py b/rdflib/term.py
index 3a822158..0f627e69 100644
--- a/rdflib/term.py
+++ b/rdflib/term.py
@@ -38,7 +38,6 @@ import logging
import warnings
import math
-import base64
import xml.dom.minidom
from datetime import date, time, datetime, timedelta
@@ -53,6 +52,7 @@ from isodate import (
parse_duration,
duration_isoformat,
)
+from base64 import b64decode, b64encode
from binascii import hexlify, unhexlify
import rdflib
@@ -1435,6 +1435,7 @@ _XSD_DAYTIMEDURATION = URIRef(_XSD_PFX + "dayTimeDuration")
_XSD_YEARMONTHDURATION = URIRef(_XSD_PFX + "yearMonthDuration")
_OWL_RATIONAL = URIRef("http://www.w3.org/2002/07/owl#rational")
+_XSD_B64BINARY = URIRef(_XSD_PFX + "base64Binary")
_XSD_HEXBINARY = URIRef(_XSD_PFX + "hexBinary")
# TODO: gYearMonth, gYear, gMonthDay, gDay, gMonth
@@ -1559,6 +1560,8 @@ _GenericPythonToXSDRules = [
_SpecificPythonToXSDRules = [
((str, _XSD_HEXBINARY), hexlify),
((bytes, _XSD_HEXBINARY), hexlify),
+ ((str, _XSD_B64BINARY), b64encode),
+ ((bytes, _XSD_B64BINARY), b64encode),
]
XSDToPython = {
@@ -1593,7 +1596,7 @@ XSDToPython = {
URIRef(_XSD_PFX + "unsignedByte"): int,
URIRef(_XSD_PFX + "float"): float,
URIRef(_XSD_PFX + "double"): float,
- URIRef(_XSD_PFX + "base64Binary"): lambda s: base64.b64decode(s),
+ URIRef(_XSD_PFX + "base64Binary"): b64decode,
URIRef(_XSD_PFX + "anyURI"): None,
_RDF_XMLLITERAL: _parseXML,
_RDF_HTMLLITERAL: _parseHTML,
diff --git a/setup.py b/setup.py
index 8dd82c2b..e2edc084 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@ kwargs["test_suite"] = "nose.collector"
kwargs["extras_require"] = {
"html": ["html5lib"],
"tests": kwargs["tests_require"],
- "docs": ["sphinx < 4", "sphinxcontrib-apidoc"],
+ "docs": ["sphinx < 5", "sphinxcontrib-apidoc"],
}
diff --git a/test/test_b64_binary.py b/test/test_b64_binary.py
new file mode 100644
index 00000000..b512f29d
--- /dev/null
+++ b/test/test_b64_binary.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+import base64
+from rdflib import Literal, XSD
+
+
+class B64BinaryTestCase(unittest.TestCase):
+
+ def test_unicode(self):
+ str1 = "Test utf-8 string éàë"
+ # u b64string
+ b64_str1 = base64.b64encode(str1.encode("utf-8")).decode()
+ l1 = Literal(b64_str1, datatype=XSD.base64Binary)
+ b_str1 = l1.toPython()
+ self.assertEqual(b_str1.decode("utf-8"), str1)
+ self.assertEqual(str(l1), b64_str1)
+
+ # b b64string
+ b64_str1b = base64.b64encode(str1.encode("utf-8"))
+ l1b = Literal(b64_str1b, datatype=XSD.base64Binary)
+ b_str1b = l1b.toPython()
+ self.assertEqual(b_str1, b_str1b)
+ self.assertEqual(b_str1b.decode("utf-8"), str1)
+ self.assertEqual(str(l1b), b64_str1)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/test/test_graph.py b/test/test_graph.py
index 93a81df3..9f6d5d9b 100644
--- a/test/test_graph.py
+++ b/test/test_graph.py
@@ -319,6 +319,47 @@ class GraphTestCase(unittest.TestCase):
# this endpoint is currently not available, ignore this test.
pass
+ def testTransitive(self):
+ person = URIRef("ex:person")
+ dad = URIRef("ex:dad")
+ mom = URIRef("ex:mom")
+ mom_of_dad = URIRef("ex:mom_o_dad")
+ mom_of_mom = URIRef("ex:mom_o_mom")
+ dad_of_dad = URIRef("ex:dad_o_dad")
+ dad_of_mom = URIRef("ex:dad_o_mom")
+
+ parent = URIRef("ex:parent")
+
+ g = Graph()
+ g.add((person, parent, dad))
+ g.add((person, parent, mom))
+ g.add((dad, parent, mom_of_dad))
+ g.add((dad, parent, dad_of_dad))
+ g.add((mom, parent, mom_of_mom))
+ g.add((mom, parent, dad_of_mom))
+
+ # transitive parents of person
+ self.assertEqual(
+ set(g.transitive_objects(subject=person, predicate=parent)),
+ {person, dad, mom_of_dad, dad_of_dad, mom, mom_of_mom, dad_of_mom},
+ )
+ # transitive parents of dad
+ self.assertEqual(
+ set(g.transitive_objects(dad, parent)), {dad, mom_of_dad, dad_of_dad}
+ )
+ # transitive parents of dad_of_dad
+ self.assertEqual(set(g.transitive_objects(dad_of_dad, parent)), {dad_of_dad})
+
+ # transitive children (inverse of parents) of mom_of_mom
+ self.assertEqual(
+ set(g.transitive_subjects(predicate=parent, object=mom_of_mom)),
+ {mom_of_mom, mom, person},
+ )
+ # transitive children (inverse of parents) of mom
+ self.assertEqual(set(g.transitive_subjects(parent, mom)), {mom, person})
+ # transitive children (inverse of parents) of person
+ self.assertEqual(set(g.transitive_subjects(parent, person)), {person})
+
# dynamically create classes for each registered Store
diff --git a/test/test_sparql.py b/test/test_sparql.py
index fa548146..6454e7ef 100644
--- a/test/test_sparql.py
+++ b/test/test_sparql.py
@@ -1,8 +1,8 @@
from rdflib.plugins.sparql import sparql, prepareQuery
from rdflib import Graph, URIRef, Literal, BNode, ConjunctiveGraph
from rdflib.namespace import Namespace, RDF, RDFS
-from rdflib.plugins.sparql import prepareQuery
from rdflib.compare import isomorphic
+from rdflib.term import Variable
from nose.tools import eq_
@@ -163,6 +163,43 @@ def test_named_filter_graph_query():
initNs={'ex': ex})) == [(Literal('Susan'),)]
+def test_txtresult():
+ data = f"""\
+ @prefix rdfs: <{str(RDFS)}> .
+ rdfs:Class a rdfs:Class ;
+ rdfs:isDefinedBy <http://www.w3.org/2000/01/rdf-schema#> ;
+ rdfs:label "Class" ;
+ rdfs:comment "The class of classes." ;
+ rdfs:subClassOf rdfs:Resource .
+ """
+ graph = Graph()
+ graph.parse(data=data, format="turtle")
+ result = graph.query(
+ """\
+ SELECT ?class ?superClass ?label ?comment WHERE {
+ ?class rdf:type rdfs:Class.
+ ?class rdfs:label ?label.
+ ?class rdfs:comment ?comment.
+ ?class rdfs:subClassOf ?superClass.
+ }
+ """
+ )
+ vars = [
+ Variable("class"),
+ Variable("superClass"),
+ Variable("label"),
+ Variable("comment"),
+ ]
+ assert result.type == "SELECT"
+ assert len(result) == 1
+ assert result.vars == vars
+ txtresult = result.serialize(format="txt")
+ lines = txtresult.decode().splitlines()
+ assert len(lines) == 3
+ vars_check = [Variable(var.strip()) for var in lines[0].split("|")]
+ assert vars_check == vars
+
+
if __name__ == "__main__":
import nose
diff --git a/test/test_sparqlstore.py b/test/test_sparqlstore.py
index 8154b10c..8d720de3 100644
--- a/test/test_sparqlstore.py
+++ b/test/test_sparqlstore.py
@@ -67,6 +67,19 @@ class SPARQLStoreDBPediaTestCase(unittest.TestCase):
for i in res:
assert type(i[0]) == Literal, i[0].n3()
+ def test_query_with_added_rdf_prolog(self):
+ prologue = """\
+ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+ PREFIX xyzzy: <http://www.w3.org/2004/02/skos/core#>
+ """
+ query = """\
+ SELECT ?label WHERE
+ { ?s a xyzzy:Concept ; xyzzy:prefLabel ?label . } LIMIT 10
+ """
+ res = helper.query_with_retry(self.graph, prologue + query)
+ for i in res:
+ assert type(i[0]) == Literal, i[0].n3()
+
def test_counting_graph_and_store_queries(self):
query = """
SELECT ?s