summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Car <nicholas.car@surroundaustralia.com>2021-07-03 01:00:38 +1000
committerGitHub <noreply@github.com>2021-07-03 01:00:38 +1000
commit7c86efede775d62f7bc16d08d2ee4af7dde295d7 (patch)
tree759801003d8ff9507d86397d7ec0d67cd08c6794
parenta1e461888a830cbdf8ba178d85e9293522484cb1 (diff)
parent3ad2cdd661dd98bcca2dfd0e19a384ab3abcd71b (diff)
downloadrdflib-7c86efede775d62f7bc16d08d2ee4af7dde295d7.tar.gz
Merge pull request #1296 from RDFLib/docco_clean
Complete clean up of docs for 6.0.0
-rw-r--r--docs/developers.rst18
-rw-r--r--docs/intro_to_sparql.rst15
-rw-r--r--docs/merging.rst30
-rw-r--r--docs/namespaces_and_bindings.rst31
-rw-r--r--docs/persistence.rst4
-rw-r--r--docs/rdf_terms.rst78
-rw-r--r--docs/univrdfstore.rst381
-rw-r--r--docs/utilities.rst6
-rw-r--r--examples/custom_eval.py2
-rw-r--r--examples/film.py2
-rw-r--r--examples/foafpaths.py2
-rw-r--r--examples/slice.py10
-rw-r--r--examples/smushing.py2
-rw-r--r--examples/sparql_query_example.py4
-rw-r--r--examples/sparql_update_example.py14
-rw-r--r--examples/sparqlstore_example.py7
-rw-r--r--examples/swap_primer.py28
-rw-r--r--rdflib/paths.py72
-rw-r--r--rdflib/term.py14
-rw-r--r--rdflib/tools/csv2rdf.py4
-rw-r--r--test/test_csv2rdf.py8
-rw-r--r--test/test_literal.py22
22 files changed, 177 insertions, 577 deletions
diff --git a/docs/developers.rst b/docs/developers.rst
index d31a5e54..b8c8310c 100644
--- a/docs/developers.rst
+++ b/docs/developers.rst
@@ -12,7 +12,7 @@ developing RDFLib code.
Please be as Pythonic as possible (:pep:`8`).
Code should be formatted using `black <https://github.com/psf/black>`_.
-While not yet mandatory it will be required in the future.
+While not yet mandatory, it will be required in the future (6.0.0+).
Any new functionality being added to RDFLib should have doc tests and
unit tests. Tests should be added for any functionality being changed
@@ -45,14 +45,18 @@ Writing documentation
We use sphinx for generating HTML docs, see :ref:`docs`
-Continous Integration
+Continuous Integration
---------------------
-We used Travis for CI, see:
+We used Drone for CI, see:
- https://travis-ci.org/RDFLib/rdflib
+ https://drone.rdflib.ashs.dev/RDFLib/rdflib
-If you make a pull-request to RDFLib on GitHub, travis will automatically test you code.
+If you make a pull-request to RDFLib on GitHub, Drone will automatically test your code and we will only merge code
+passing all tests.
+
+Please do *not* commit tests you know will fail, even if you're just pointing out a bug. If you commit such tests,
+flag them as expecting to fail.
Compatibility
-------------
@@ -82,7 +86,7 @@ If for whatever reason you don't want to take this approach, the old one is::
Tagging the release commit with::
- git tag -a -m 'tagged version' X.X.X
+ git tag -am 'tagged version' X.X.X
When pushing, remember to do::
@@ -106,4 +110,4 @@ Set new dev version number in the above locations, i.e. next release `-dev`: ``5
Tweet, email mailing list and update the topic of #rdflib on freenode irc::
- /msg ChanServ topic #rdflib https://github.com/RDFLib/rdflib | latest stable version: 4.2.0 | docs: http://rdflib.readthedocs.org
+ /msg ChanServ topic #rdflib https://github.com/RDFLib/rdflib | latest stable version: 5.0.0 | docs: http://rdflib.readthedocs.org
diff --git a/docs/intro_to_sparql.rst b/docs/intro_to_sparql.rst
index 834231bf..ef7aab78 100644
--- a/docs/intro_to_sparql.rst
+++ b/docs/intro_to_sparql.rst
@@ -16,23 +16,14 @@ Queries can be evaluated against a graph with the
:meth:`rdflib.graph.Graph.query` method, and updates with
:meth:`rdflib.graph.Graph.update`.
-A query method returns a :class:`rdflib.query.Result` instance. For
-``SELECT`` queries, iterating over this returns
+The query method returns a :class:`rdflib.query.Result` instance. For
+SELECT queries, iterating over this returns
:class:`rdflib.query.ResultRow` instances, each containing a set of
variable bindings. For ``CONSTRUCT``/``DESCRIBE`` queries, iterating over the
result object gives the triples. For ``ASK`` queries, iterating will yield
the single boolean answer, or evaluating the result object in a
boolean-context (i.e. ``bool(result)``)
-The query method returns a :class:`rdflib.query.Result` instance. For
-SELECT queries, iterating over this returns
-:class:`rdflib.query.ResultRow` instances, each containing a set of
-variable bindings. For CONSTRUCT/DESCRIBE queries, iterating over the
-result object yields triples. For ASK queries, the single Boolean
-answer is obtained by iterating over the result object or by
-evaluating the result object in a Boolean context
-(i.e. ``bool(result)``).
-
For example...
.. code-block:: python
@@ -133,6 +124,7 @@ example:
# y: a d:
+
Querying a Remote Service
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -159,6 +151,7 @@ The ``SERVICE`` keyword of SPARQL 1.1 can send a query to a remote SPARQL endpoi
print(row.s)
+
This example sends a query to `DBPedia <https://dbpedia.org/>`_'s SPARQL endpoint service so that it can run the query
and then send back the result:
diff --git a/docs/merging.rst b/docs/merging.rst
index 8448de3c..d0e5f5e5 100644
--- a/docs/merging.rst
+++ b/docs/merging.rst
@@ -4,29 +4,13 @@
Merging graphs
==============
- A merge of a set of RDF graphs is defined as follows. If the graphs in
- the set have no blank nodes in common, then the union of the graphs is
- a merge; if they do share blank nodes, then it is the union of a set
- of graphs that is obtained by replacing the graphs in the set by
- equivalent graphs that share no blank nodes. This is often described
- by saying that the blank nodes have been 'standardized apart'. It is
- easy to see that any two merges are equivalent, so we will refer to
- the merge, following the convention on equivalent graphs. Using the
- convention on equivalent graphs and identity, any graph in the
- original set is considered to be a subgraph of the merge.
-
- One does not, in general, obtain the merge of a set of graphs by
- concatenating their corresponding N-Triples documents and constructing
- the graph described by the merged document. If some of the documents
- use the same node identifiers, the merged document will describe a
- graph in which some of the blank nodes have been 'accidentally'
- identified. To merge N-Triples documents it is necessary to check if
- the same nodeID is used in two or more documents, and to replace it
- with a distinct nodeID in each of them, before merging the
- documents. Similar cautions apply to merging graphs described by
- RDF/XML documents which contain nodeIDs
-
-*(copied directly from http://www.w3.org/TR/rdf-mt/#graphdefs)*
+ Graphs share blank nodes only if they are derived from graphs described by documents or other structures (such as an RDF dataset) that explicitly provide for the sharing of blank nodes between different RDF graphs. Simply downloading a web document does not mean that the blank nodes in a resulting RDF graph are the same as the blank nodes coming from other downloads of the same document or from the same RDF source.
+
+RDF applications which manipulate concrete syntaxes for RDF which use blank node identifiers should take care to keep track of the identity of the blank nodes they identify. Blank node identifiers often have a local scope, so when RDF from different sources is combined, identifiers may have to be changed in order to avoid accidental conflation of distinct blank nodes.
+
+For example, two documents may both use the blank node identifier "_:x" to identify a blank node, but unless these documents are in a shared identifier scope or are derived from a common source, the occurrences of "_:x" in one document will identify a different blank node than the one in the graph described by the other document. When graphs are formed by combining RDF from multiple sources, it may be necessary to standardize apart the blank node identifiers by replacing them by others which do not occur in the other document(s).
+
+*(copied directly from https://www.w3.org/TR/rdf11-mt/#shared-blank-nodes-unions-and-merges)*
In RDFLib, blank nodes are given unique IDs when parsing, so graph merging can be done by simply reading several files into the same graph::
diff --git a/docs/namespaces_and_bindings.rst b/docs/namespaces_and_bindings.rst
index e6885b59..c89b90b0 100644
--- a/docs/namespaces_and_bindings.rst
+++ b/docs/namespaces_and_bindings.rst
@@ -11,15 +11,15 @@ The :mod:`rdflib.namespace` defines the :class:`rdflib.namespace.Namespace` clas
from rdflib import Namespace
n = Namespace("http://example.org/")
- n.Person # as attribute
- # = rdflib.term.URIRef(u'http://example.org/Person')
+ n.Person # as attribute
+ # = rdflib.term.URIRef("http://example.org/Person")
- n['first%20name'] # as item - for things that are not valid python identifiers
- # = rdflib.term.URIRef(u'http://example.org/first%20name')
+ n['first%20name'] # as item - for things that are not valid python identifiers
+ # = rdflib.term.URIRef("http://example.org/first%20name")
Note that if a name string is valid for use in an RDF namespace but not valid as a Python identifier, such as '1234', it must be addressed with the "item" syntax (using the "attribute" syntax will raise a Syntax Error).
-The ``namespace`` module also defines many common namespaces such as RDF, RDFS, OWL, FOAF, SKOS, etc.
+The ``namespace`` module also defines many common namespaces such as RDF, RDFS, OWL, FOAF, SKOS, PROF, etc.
Namespaces can also be associated with prefixes, in a :class:`rdflib.namespace.NamespaceManager`, i.e. using ``foaf`` for ``http://xmlns.com/foaf/0.1/``. Each RDFLib graph has a :attr:`~rdflib.graph.Graph.namespace_manager` that keeps a list of namespace to prefix mappings. The namespace manager is populated when reading in RDF, and these prefixes are used when serialising RDF, or when parsing SPARQL queries. Additional prefixes can be bound with the :meth:`rdflib.graph.bind` method.
@@ -45,43 +45,40 @@ N3 format::
>>> from rdflib import Graph, URIRef, Literal, BNode
>>> from rdflib.namespace import FOAF, NamespaceManager
- >>> person = URIRef('http://xmlns.com/foaf/0.1/Person')
+ >>> person = URIRef("http://xmlns.com/foaf/0.1/Person")
>>> person.n3()
- u'<http://xmlns.com/foaf/0.1/Person>'
+ '<http://xmlns.com/foaf/0.1/Person>'
>>> g = Graph()
>>> g.bind("foaf", FOAF)
>>> person.n3(g.namespace_manager)
- u'foaf:Person'
+ 'foaf:Person'
>>> l = Literal(2)
>>> l.n3()
- u'"2"^^<http://www.w3.org/2001/XMLSchema#integer>'
+ '"2"^^<http://www.w3.org/2001/XMLSchema#integer>'
>>> l.n3(g.namespace_manager)
- u'"2"^^xsd:integer'
+ '"2"^^xsd:integer'
The namespace manage also has a useful method compute_qname
-g.namespace_manager.compute_qname(x) which takes an url and decomposes it into the parts:
+g.namespace_manager.compute_qname(x) which takes an url and decomposes it into the parts::
- self.assertEqual(g.compute_qname(URIRef("http://foo/bar#baz")),
+ self.assertEqual(g.compute_qname(URIRef("http://foo/bar#baz")),
("ns2", URIRef("http://foo/bar#"), "baz"))
__ http://rdflib.net/rdflib-2.4.0/html/public/rdflib.syntax.NamespaceManager.NamespaceManager-class.html
-
-
Namespaces in SPARQL Queries
----------------------------
The ``initNs`` argument supplied to :meth:`~rdflib.graph.Graph.query` is a dictionary of namespaces to be expanded in the query string.
If you pass no ``initNs`` argument, the namespaces registered with the graphs namespace_manager are used::
- ...
- from rdflib.namespace import FOAF
- graph.query('SELECT * WHERE { ?p a foaf:Person }', initNs={ 'foaf': FOAF })
+ from rdflib.namespace import FOAF
+ graph.query('SELECT * WHERE { ?p a foaf:Person }', initNs={ 'foaf': FOAF })
In order to use an empty prefix (e.g. ``?a :knows ?b``), use a ``PREFIX`` directive with no prefix in the SPARQL query to set a default namespace:
diff --git a/docs/persistence.rst b/docs/persistence.rst
index 03f8d955..43c56176 100644
--- a/docs/persistence.rst
+++ b/docs/persistence.rst
@@ -36,8 +36,8 @@ In most cases, passing the name of the store to the Graph constructor is enough:
graph = Graph(store='BerkeleyDB')
-Most store offering on-disk persistence will need to be opened before reading or writing.
-When persisting a triplestore (instead of a ConjuntiveGraph quadstore), you need to specify
+Most stores offering on-disk persistence will need to be opened before reading or writing.
+When peristing a triplestore, rather than a ConjuntiveGraph quadstore, you need to specify
an identifier with which you can open the graph:
.. code-block:: python
diff --git a/docs/rdf_terms.rst b/docs/rdf_terms.rst
index a520bc5c..c8468407 100644
--- a/docs/rdf_terms.rst
+++ b/docs/rdf_terms.rst
@@ -4,43 +4,24 @@
RDF terms in rdflib
===================
-Terms are the kinds of objects that can appear in a quoted/asserted triples. Those that are part of core RDF concepts are: ``Blank Node``, ``URI Reference`` and ``Literal``, the latter consisting of a literal value and either a `datatype <http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#built-in-datatypes>`_ or an :rfc:`3066` language tag.
+Terms are the kinds of objects that can appear in a quoted/asserted triples. Those that are part of core RDF concepts are: ``Blank Node``, ``URI Reference`` and ``Literal``, the latter consisting of a literal value and either a `datatype <https://www.w3.org/TR/xmlschema-2/#built-in-datatypes>`_ or an :rfc:`3066` language tag.
All terms in RDFLib are sub-classes of the :class:`rdflib.term.Identifier` class.
Nodes are a subset of the Terms that the underlying store actually persists.
The set of such Terms depends on whether or not the store is formula-aware.
-Stores that aren't formula-aware would only persist those terms core to the
-RDF Model, and those that are formula-aware would be able to persist the N3
-extensions as well. However, utility terms that only serve the purpose for
-matching nodes by term-patterns probably will only be terms and not nodes.
+Stores that aren't formula-aware only persist those terms core to the
+RDF Model but those that are formula-aware also persist the N3
+extensions. However, utility terms that only serve the purpose of
+matching nodes by term-patterns will probably only be terms and not nodes.
-
-BNodes
-======
-
-In RDF, a blank node (also called BNode) is a node in an RDF graph representing a resource for which a URI or literal is not given. The resource represented by a blank node is also called an anonymous resource. By RDF standard a blank node can only be used as subject or object in an RDF triple, although in some syntaxes like Notation 3 [1] it is acceptable to use a blank node as a predicate. If a blank node has a node ID (not all blank nodes are labelled in all RDF serializations), it is limited in scope to a serialization of a particular RDF graph, i.e. the node p1 in the subsequent example does not represent the same node as a node named p1 in any other graph --`wikipedia`__
-
-
-.. __: http://en.wikipedia.org/wiki/Blank_node
-
-.. autoclass:: rdflib.term.BNode
- :noindex:
-
-.. code-block:: python
-
- >>> from rdflib import BNode
- >>> anode = BNode()
- >>> anode
- rdflib.term.BNode('AFwALAKU0')
- >>> anode.n3()
- u'_:AFwALAKU0'
-
URIRefs
=======
-A URI reference within an RDF graph is a Unicode string that does not contain any control characters ( #x00 - #x1F, #x7F-#x9F) and would produce a valid URI character sequence representing an absolute URI with optional fragment identifier -- `W3 RDF Concepts`__
+A *URI reference* within an RDF graph is a Unicode string that does not contain any control characters ( #x00 - #x1F, #x7F-#x9F)
+and would produce a valid URI character sequence representing an absolute URI with optional fragment
+identifier -- `W3 RDF Concepts`__
.. __: http://www.w3.org/TR/rdf-concepts/#section-Graph-URIref
@@ -50,18 +31,18 @@ A URI reference within an RDF graph is a Unicode string that does not contain an
.. code-block:: python
>>> from rdflib import URIRef
- >>> aref = URIRef()
+ >>> uri = URIRef()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
- TypeError: __new__() takes at least 2 arguments (1 given)
- >>> aref = URIRef('')
- >>> aref
- rdflib.term.URIRef(u'')
- >>> aref = URIRef('http://example.com')
- >>> aref
- rdflib.term.URIRef(u'http://example.com')
- >>> aref.n3()
- u'<http://example.com>'
+ TypeError: __new__() missing 1 required positional argument: 'value'
+ >>> uri = URIRef('')
+ >>> uri
+ rdflib.term.URIRef('')
+ >>> uri = URIRef('http://example.com')
+ >>> uri
+ rdflib.term.URIRef('http://example.com')
+ >>> uri.n3()
+ '<http://example.com>'
.. _rdflibliterals:
@@ -69,7 +50,7 @@ A URI reference within an RDF graph is a Unicode string that does not contain an
Literals
========
-Literals are the attribute values in RDF, for instance, a person's name, the date of birth, height, etc. Literals can have a data-type (i.e. this is a double) or a language tag (this label is in English).
+Literals are attribute values in RDF, for instance, a person's name, the date of birth, height, etc. Literals can have a datatype (i.e. this is a *double*) or a language tag (this label is in *English*).
.. autoclass:: rdflib.term.Literal
:noindex:
@@ -90,6 +71,27 @@ Literals are the attribute values in RDF, for instance, a person's name, the dat
.. __: http://www.w3.org/TR/rdf-concepts/#section-Graph-URIref
+BNodes
+======
+
+In RDF, a blank node (also called BNode) is a node in an RDF graph representing a resource for which a URI or literal is not given. The resource represented by a blank node is also called an anonymous resource. According to the RDF standard, a blank node can only be used as subject or object in a triple, although in some syntaxes like Notation 3 it is acceptable to use a blank node as a predicate. If a blank node has a node ID (not all blank nodes are labelled in all RDF serializations), it is limited in scope to a particular serialization of the RDF graph, i.e. the node p1 in the subsequent example does not represent the same node as a node named p1 in any other graph --`wikipedia`__
+
+
+.. __: http://en.wikipedia.org/wiki/Blank_node
+
+.. autoclass:: rdflib.term.BNode
+ :noindex:
+
+.. code-block:: python
+
+ >>> from rdflib import BNode
+ >>> bn = BNode()
+ >>> bn
+ rdflib.term.BNode('AFwALAKU0')
+ >>> bn.n3()
+ '_:AFwALAKU0'
+
+
Python support
--------------
RDFLib Literals essentially behave like unicode characters with an XML Schema datatype or language attribute.
diff --git a/docs/univrdfstore.rst b/docs/univrdfstore.rst
deleted file mode 100644
index dfb96d81..00000000
--- a/docs/univrdfstore.rst
+++ /dev/null
@@ -1,381 +0,0 @@
-.. _univrdfstore:
-
-===============================
-A Universal RDF Store Interface
-===============================
-
-This document attempts to summarize some fundamental components of an RDF store. The motivation is to outline a standard set of interfaces for providing the support needed to persist an `RDF Graph`_ in a way that is universal and not tied to any specific implementation.
-
-For the most part, the interfaces adhere to the core RDF model and use terminology that is consistent with the RDF Model specifications. However, these suggested interfaces also extends an RDF store with additional requirements necessary to facilitate those aspects of `Notation 3`_ that go beyond the RDF model to provide a framework for `First Order Predicate Logic`_ processing and persistence.
-
-.. _RDF Graph: https://www.w3.org/TR/rdf11-concepts/#data-model
-.. _Notation 3: http://www.w3.org/2000/10/swap/Primer
-.. _First Order Predicate Logic: http://en.wikipedia.org/wiki/First-order_predicate_logic
-
-Terminology
-===========
-
-.. topic:: **Context**
-
- A named, unordered set of statements (that could also be called a sub-graph). The ``named graph`` `literature`__ and `ontology`__ are relevant to this concept. The term ``context`` could be thought of as either the sub-graph itself or the relationship between an RDF triple and a sub-graph in which it is found (this latter is how the term context is used in the `Notation 3 Design Issues page`_).
-
- It is worth noting that the concept of logically grouping `triples`__ within an addressable 'set' or 'subgraph' is just barely beyond the scope of the RDF model. The RDF model defines a graph to be an arbitrary collection of triples and the semantics of these triples --- but doesn't give guidance on how to address such arbitrary collections in a consistent manner. Although a collection of triples can be thought of as a resource itself, the association between a triple and the collection (of which it is a part) is not covered. `Public RDF`_ is an example of an attempt to formally model this relationship - and includes one other unrelated extension: Articulated Text
-
-.. __: http://www.w3.org/2004/03/trix/
-.. __: http://metacognition.info/Triclops/?xslt=Triclops.xslt&query=type(list(rdfs:Class,owl:Class,rdf:Property))&queryType=Graph&remoteGraph=http://www.w3.org/2004/03/trix/rdfg-1/
-.. __: http://www.w3.org/TR/rdf-concepts/#section-triples
-.. _Notation 3 Design Issues page: http://www.w3.org/DesignIssues/Notation3.html
-.. _Public RDF: http://laurentszyster.be/blog/public-rdf/
-
-.. topic:: **Conjunctive Graph**
-
- This refers to the 'top-level' Graph. It is the aggregation of all the contexts within it and is also the appropriate, absolute boundary for `closed world assumptions`__ / models. This distinction is the low-hanging fruit of RDF along the path to the semantic web and most of its value is in (corporate/enterprise) real-world problems:
-
- .. pull-quote::
-
- There are at least two situations where the closed world assumption is used. The first is where it is assumed that a knowledge base contains all relevant facts. This is common in corporate databases. That is, the information it contains is assumed to be complete
-
- From a store perspective, closed world assumptions also provide the benefit of better query response times, due to the explicit closed world boundaries. Closed world boundaries can be made transparent by federated queries that assume each :class:`ConjunctiveGraph` is a section of a larger, unbounded universe. So a closed world assumption does not preclude you from an open world assumption.
-
- For the sake of persistence, Conjunctive Graphs must be distinguished by identifiers (which may not necessarily be RDF `identifiers`__ or may be an RDF identifier normalized - SHA1/MD5 perhaps - for database naming purposes) that could be referenced to indicate conjunctive queries (queries made across the entire conjunctive graph) or appear as nodes in asserted statements. In this latter case, such statements could be interpreted as being made about the entire 'known' universe. For example:
-
- .. code-block:: xml
-
- <urn:uuid:conjunctive-graph-foo> rdf:type :ConjunctiveGraph
- <urn:uuid:conjunctive-graph-foo> rdf:type log:Truth
- <urn:uuid:conjunctive-graph-foo> :persistedBy :MySQL
-
-.. __: http://cs.wwc.edu/~aabyan/Logic/CWA.html
-.. __: http://www.w3.org/2002/07/rdf-identifer-terminology/
-
-.. topic:: **Quoted Statement**
-
- A statement that isn't asserted but is referred to in some manner. Most often, this happens when we want to make a statement about another statement (or set of statements) without necessarily saying these quoted statements (are true). For example:
-
- .. code-block:: text
-
- Chimezie said "higher-order statements are complicated"
-
- Which can be written (in N3) as:
-
- .. code-block:: n3
-
- :chimezie :said {:higherOrderStatements rdf:type :complicated}
-
-.. topic:: **Formula**
-
- A context whose statements are quoted or hypothetical.
-
- Context quoting can be thought of as very similar to `reification`__. The main difference is that quoted statements are not asserted or considered as statements of truth about the universe and can be referenced as a group: a hypothetical RDF Graph
-
-.. __: http://www.w3.org/TR/rdf-mt/#Reif
-
-.. topic:: **Universal Quantifiers / Variables**
-
- (relevant references):
-
- * OWL `Definition`__ of `SWRL`__.
- * SWRL/RuleML `Variable`__
-
-.. __: http://www.w3.org/Submission/SWRL/swrl.owl
-.. __: http://www.w3.org/Submission/SWRL/
-.. __: http://www.w3.org/Submission/SWRL/#owls_Variable
-
-.. topic:: **Terms**
-
- Terms are the kinds of objects that can appear in a quoted/asserted triple.
-
- This includes those that are core to RDF:
-
- * Blank Nodes
- * URI References
- * Literals (which consist of a literal value, datatype and language tag)
-
- Those that extend the RDF model into N3:
-
- * Formulae
- * Universal Quantifications (Variables)
-
- And those that are primarily for matching against 'Nodes' in the underlying Graph:
-
- * REGEX Expressions
- * Date Ranges
- * Numerical Ranges
-
-.. topic:: **Nodes**
-
- Nodes are a subset of the Terms that the underlying store actually persists. The set of such Terms depends on whether or not the store is formula-aware. Stores that aren't formula-aware would only persist those terms core to the RDF Model, and those that are formula-aware would be able to persist the N3 extensions as well. However, utility terms that only serve the purpose for matching nodes by term-patterns probably will only be terms and not nodes.
-
- The set of nodes of an RDF graph is the set of subjects and objects of triples in the graph.
-
-.. topic:: **Context-aware**
-
- An RDF store capable of storing statements within contexts is considered context-aware. Essentially, such a store is able to partition the RDF model it represents into individual, named, and addressable sub-graphs.
-
-.. topic:: **Formula-aware**
-
- An RDF store capable of distinguishing between statements that are asserted and statements that are quoted is considered formula-aware.
-
- Such a store is responsible for maintaining this separation and ensuring that queries against the entire model (the aggregation of all the contexts - specified by not limiting a 'query' to a specifically name context) do not include quoted statements. Also, it is responsible for distinguishing universal quantifiers (variables).
-
- .. note:: These 2 additional concepts (formulae and variables) must be thought of as core extensions and distinguishable from the other terms of a triple (for the sake of the persistence round trip - at the very least). It's worth noting that the 'scope' of universal quantifiers (variables) and existential quantifiers (BNodes) is the formula (or context - to be specific) in which their statements reside. Beyond this, a Formula-aware store behaves the same as a Context-aware store.
-
-.. topic:: **Conjunctive Query**
-
- Any query that doesn't limit the store to search within a named context only. Such a query expects a context-aware store to search the entire asserted universe (the conjunctive graph). A formula-aware store is expected not to include quoted statements when matching such a query.
-
-.. topic:: **N3 Round Trip**
-
- This refers to the requirements on a formula-aware RDF store's persistence mechanism necessary for it to be properly populated by a N3 parser and rendered as syntax by a N3 serializer.
-
-.. topic:: **Transactional Store**
-
- An RDF store capable of providing transactional integrity to the RDF operations performed on it.
-
-Interpreting Syntax
-===================
-
-The following `Notation 3 document`__:
-
-.. code-block:: text
-
- { ?x a :N3Programmer } => { ?x :has [a :Migraine] }
-
-Could cause the following statements to be asserted in the store:
-
-.. code-block:: text
-
- _:a log:implies _:b
-
-This statement would be asserted in the partition associated with quoted statements (in a formula named ``_:a``)
-
-.. code-block:: n3
-
- ?x rdf:type :N3Programmer
-
-Finally, these statements would be asserted in the same partition (in a formula named ``_:b``)
-
-.. code-block:: n3
-
- ?x :has _:c
-
- _:c rdf:type :Migraine
-
-.. __: http://metacognition.info/Triclops/?xslt=Triclops.xslt&query=log:N3Document&queryType=Triple&remoteGraph=http://www.w3.org/2000/10/swap/log#
-
-Formulae and Variables as Terms
-===============================
-Formulae and variables are distinguishable from URI references, Literals, and BNodes by the following syntax:
-
-.. code-block:: text
-
- { .. } - Formula ?x - Variable
-
-They must also be distinguishable in persistence to ensure they can be round-tripped.
-
-.. note:: There are a number of other issues regarding the :doc:`persisting_n3_terms`.
-
-Database Management
-===================
-
-An RDF store should provide standard interfaces for the management of database connections. Such interfaces are standard to most database management systems (Oracle, MySQL, Berkeley DB, Postgres, etc..)
-
-The following methods are defined to provide this capability (see below for description of the *configuration* string):
-
-.. automethod:: rdflib.store.Store.open
- :noindex:
-
-.. automethod:: rdflib.store.Store.close
- :noindex:
-
-.. automethod:: rdflib.store.Store.destroy
- :noindex:
-
-The *configuration* string is understood by the store implementation and represents all the parameters needed to locate an individual instance of a store. This could be similar to an ODBC string or in fact be an ODBC string, if the connection protocol to the underlying database is ODBC.
-
-The :meth:`~rdflib.graph.Graph.open` function needs to fail intelligently in order to clearly express that a store (identified by the given configuration string) already exists or that there is no store (at the location specified by the configuration string) depending on the value of ``create``.
-
-Triple Interfaces
-=================
-An RDF store could provide a standard set of interfaces for the manipulation, management, and/or retrieval of its contained triples (asserted or quoted):
-
-.. module:: rdflib.store
- :noindex:
-
-.. automethod:: rdflib.store.Store.add
- :noindex:
-
-.. automethod:: rdflib.store.Store.remove
- :noindex:
-
-.. automethod:: rdflib.store.Store.triples
- :noindex:
-
- .. note:: The :meth:`~rdflib.store.Store.triples` method can be thought of as the primary mechanism for producing triples with nodes that match the corresponding terms in the ``(s, p, o)`` term pattern provided. The term pattern ``(None, None, None)`` matches *all* nodes.
-
-.. automethod:: rdflib.store.Store.__len__
- :noindex:
-
-Formula / Context Interfaces
-============================
-
-These interfaces work on contexts and formulae (for stores that are formula-aware) interchangeably.
-
-.. automethod:: rdflib.graph.ConjunctiveGraph.contexts
- :noindex:
-
-.. automethod:: rdflib.graph.ConjunctiveGraph.remove_context
- :noindex:
-
-Interface Test Cases
-====================
-
-Basic
--------------------------
-
-Tests parsing, triple patterns, triple pattern removes, size, contextual removes
-
-Source Graph
-^^^^^^^^^^^^^
-
-.. code-block:: n3
-
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
- @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
- @prefix : <http://test/> .
- {:a :b :c; a :foo} => {:a :d :c} .
- _:foo a rdfs:Class .
- :a :d :c .
-
-Test code
-^^^^^^^^^
-
-.. code-block:: python
-
- implies = URIRef("http://www.w3.org/2000/10/swap/log#implies")
- a = URIRef('http://test/a')
- b = URIRef('http://test/b')
- c = URIRef('http://test/c')
- d = URIRef('http://test/d')
- for s,p,o in g.triples((None,implies,None)):
- formulaA = s
- formulaB = o
-
- #contexts test
- assert len(list(g.contexts()))==3
-
- #contexts (with triple) test
- assert len(list(g.contexts((a,d,c))))==2
-
- #triples test cases
- assert type(list(g.triples((None,RDF.type,RDFS.Class)))[0][0]) == BNode
- assert len(list(g.triples((None,implies,None))))==1
- assert len(list(g.triples((None,RDF.type,None))))==3
- assert len(list(g.triples((None,RDF.type,None),formulaA)))==1
- assert len(list(g.triples((None,None,None),formulaA)))==2
- assert len(list(g.triples((None,None,None),formulaB)))==1
- assert len(list(g.triples((None,None,None))))==5
- assert len(list(g.triples((None,URIRef('http://test/d'),None),formulaB)))==1
- assert len(list(g.triples((None,URIRef('http://test/d'),None))))==1
-
- #Remove test cases
- g.remove((None,implies,None))
- assert len(list(g.triples((None,implies,None))))==0
- assert len(list(g.triples((None,None,None),formulaA)))==2
- assert len(list(g.triples((None,None,None),formulaB)))==1
- g.remove((None,b,None),formulaA)
- assert len(list(g.triples((None,None,None),formulaA)))==1
- g.remove((None,RDF.type,None),formulaA)
- assert len(list(g.triples((None,None,None),formulaA)))==0
- g.remove((None,RDF.type,RDFS.Class))
-
- #remove_context tests
- formulaBContext=Context(g,formulaB)
- g.remove_context(formulaB)
- assert len(list(g.triples((None,RDF.type,None))))==2
- assert len(g)==3 assert len(formulaBContext)==0
- g.remove((None,None,None))
- assert len(g)==0
-
-
-Formula and Variables Test
---------------------------
-
-Source Graph
-^^^^^^^^^^^^
-
-.. code-block:: n3
-
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
- @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
- @prefix : <http://test/> .
- {?x a rdfs:Class} => {?x a :Klass} .
-
-Test Code
-^^^^^^^^^
-
-.. code-block:: python
-
- implies = URIRef("http://www.w3.org/2000/10/swap/log#implies")
- klass = URIRef('http://test/Klass')
- for s,p,o in g.triples((None,implies,None)):
- formulaA = s
- formulaB = o
- assert type(formulaA) == Formula
- assert type(formulaB) == Formula
- for s,p,o in g.triples((None,RDF.type,RDFS.Class)),formulaA):
- assert type(s) == Variable
- for s,p,o in g.triples((None,RDF.type,klass)),formulaB):
- assert type(s) == Variable
-
-Transactional Tests
--------------------
-
-To be instantiated.
-
-Additional Terms to Model
-=========================
-These are a list of additional kinds of RDF terms (all of which are special Literals)
-
- * :class:`rdflib.plugins.store.regexmatching.REGEXTerm` - a REGEX string which can be used in any term slot in order to match by applying the Regular Expression to statements in the underlying graph.
- * Date (could provide some utility functions for date manipulation / serialization, etc..)
- * DateRange
-
-Namespace Management Interfaces
-===============================
-
-The following namespace management interfaces (defined in Graph) could be implemented in the RDF store. Currently, they exist as stub methods of :class:`~rdflib.store.Store` and are defined in the store subclasses (e.g. :class:`~rdflib.plugins.store.memory.Memory`):
-
-.. automethod:: rdflib.store.Store.bind
- :noindex:
-
-.. automethod:: rdflib.store.Store.prefix
- :noindex:
-
-.. automethod:: rdflib.store.Store.namespace
- :noindex:
-
-.. automethod:: rdflib.store.Store.namespaces
- :noindex:
-
-Open issues
-===========
-Does the Store interface need to have an identifier property or can we keep that at the Graph level?
-
-The Store implementation needs a mechanism to distinguish between triples (quoted or asserted) in ConjunctiveGraphs (which are mutually exclusive universes in systems that make closed world assumptions - and queried separately). This is the separation that the store identifier provides. This is different from the name of a context within a ConjunctiveGraph (or the default context of a conjunctive graph). I tried to diagram the logical separation of ConjunctiveGraphs, SubGraphs and QuotedGraphs in this diagram
-
-.. image:: _static/ContextHierarchy.png
-
-An identifier of ``None`` can be used to indicate the store (aka `all contexts`) in methods such as :meth:`~rdflib.store.Store.triples`, :meth:`~rdflib.store.Store.__len__`, etc. This works as long as we're only dealing with one Conjunctive Graph at a time -- which may not always be the case.
-
-Is there any value in persisting terms that lie outside N3 (:class:`rdflib.plugins.store.regexmatching.REGEXTerm`, Date, etc..)?
-
-Potentially, not sure yet.
-
-Should a conjunctive query always return quads instead of triples? It would seem so, since knowing the context that produced a triple match is an essential aspect of query construction / optimization. Or if having the triples function yield/produce different length tuples is problematic, could an additional - and slightly redundant - interface be introduced?:
-
-.. automethod:: rdflib.graph.ConjunctiveGraph.quads
- :noindex:
-
-Stores that weren't context-aware could simply return ``None`` as the 4th item in the produced/yielded tuples or simply not support this interface.
-
diff --git a/docs/utilities.rst b/docs/utilities.rst
index af6f1248..e10a5334 100644
--- a/docs/utilities.rst
+++ b/docs/utilities.rst
@@ -1,7 +1,7 @@
Utilities & convenience functions
=================================
-For RDF programming, RDFLib and Python may be the fastest tools,
+For RDF programming, RDFLib and Python may not be the fastest tools,
but we try hard to make them the easiest and most convenient to use and thus the *fastest* overall!
This is a collection of hints and pointers for hassle-free RDF coding.
@@ -160,7 +160,7 @@ You can parse data from a string with the ``data`` param:
print(r)
# prints: (rdflib.term.URIRef('a:'), rdflib.term.URIRef('p:'), rdflib.term.URIRef('p:'))
-Commandline-tools
------------------
+Command Line tools
+------------------
RDFLib includes a handful of commandline tools, see :mod:`rdflib.tools`.
diff --git a/examples/custom_eval.py b/examples/custom_eval.py
index 02bf0d7f..36998087 100644
--- a/examples/custom_eval.py
+++ b/examples/custom_eval.py
@@ -11,7 +11,7 @@ i.e. in your setup.py::
entry_points = {
'rdf.plugins.sparqleval': [
- 'myfunc = mypackage:MyFunction',
+ 'myfunc = mypackage:MyFunction',
],
}
"""
diff --git a/examples/film.py b/examples/film.py
index ae87cd7f..a23a3c0f 100644
--- a/examples/film.py
+++ b/examples/film.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
-film.py: a simple tool to manage your movies review
+film.py: a simple tool to manage your movies reviews
Simon Rozet, http://atonie.org/
- manage directors and writers
diff --git a/examples/foafpaths.py b/examples/foafpaths.py
index 2941345e..6bb21efd 100644
--- a/examples/foafpaths.py
+++ b/examples/foafpaths.py
@@ -23,7 +23,7 @@ for any graph method.
See the docs for :mod:`rdflib.paths` for the details.
-This example shows how to get the name of friends with a single query.
+This example shows how to get the name of friends (i.e values two steps away x knows y, y name z) with a single query.
"""
from rdflib import URIRef, Graph
diff --git a/examples/slice.py b/examples/slice.py
index 33aacf9b..de3bb731 100644
--- a/examples/slice.py
+++ b/examples/slice.py
@@ -1,7 +1,7 @@
"""
RDFLib Graphs (and Resources) can be "sliced" with [] syntax
-This is a short-hand for iterating over triples
+This is a short-hand for iterating over triples.
Combined with SPARQL paths (see ``foafpaths.py``) - quite complex queries
can be realised.
@@ -15,13 +15,11 @@ from rdflib.namespace import FOAF
if __name__ == "__main__":
graph = Graph()
-
graph.load("foaf.n3", format="n3")
- for person in graph[: RDF.type : FOAF.Person]:
-
- friends = list(graph[person : FOAF.knows * "+" / FOAF.name])
+ for person in graph[: RDF.type: FOAF.Person]:
+ friends = list(graph[person: FOAF.knows * "+" / FOAF.name])
if friends:
- print("%s's circle of friends:" % graph.value(person, FOAF.name))
+ print(f"{graph.value(person, FOAF.name)}'s circle of friends:")
for name in friends:
print(name)
diff --git a/examples/smushing.py b/examples/smushing.py
index e9ad8f6f..8cdb13b4 100644
--- a/examples/smushing.py
+++ b/examples/smushing.py
@@ -42,4 +42,4 @@ if __name__ == "__main__":
o = newURI.get(o, o) # might be linked to another person
out.add((s, p, o))
- print(out.serialize(format="n3"))
+ print(out.serialize())
diff --git a/examples/sparql_query_example.py b/examples/sparql_query_example.py
index ce84b17d..99c75351 100644
--- a/examples/sparql_query_example.py
+++ b/examples/sparql_query_example.py
@@ -4,7 +4,7 @@ SPARQL Query using :meth:`rdflib.graph.Graph.query`
The method returns a :class:`~rdflib.query.Result`, iterating over
this yields :class:`~rdflib.query.ResultRow` objects
-The variable bindings can be access as attributes of the row objects
+The variable bindings can be accessed as attributes of the row objects
For variable names that are not valid python identifiers, dict access
(i.e. with ``row[var] / __getitem__``) is also possible.
@@ -18,7 +18,7 @@ if __name__ == "__main__":
g = rdflib.Graph()
g.load("foaf.n3", format="n3")
- # the QueryProcessor knows the FOAF prefix from the graph
+ # The QueryProcessor knows the FOAF prefix from the graph
# which in turn knows it from reading the N3 RDF file
for row in g.query("SELECT ?s WHERE { [] foaf:knows ?s .}"):
print(row.s)
diff --git a/examples/sparql_update_example.py b/examples/sparql_update_example.py
index fd7bce4e..aa591034 100644
--- a/examples/sparql_update_example.py
+++ b/examples/sparql_update_example.py
@@ -9,17 +9,19 @@ if __name__ == "__main__":
g = rdflib.Graph()
g.load("foaf.n3", format="n3")
- print("Initially there are {} triples in the graph".format(len(g)))
+ print(f"Initially there are {len(g)} triples in the graph")
g.update(
"""
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbpedia: <http://dbpedia.org/resource/>
- INSERT
- { ?s a dbpedia:Human . }
- WHERE
- { ?s a foaf:Person . }
+ INSERT {
+ ?s a dbpedia:Human .
+ }
+ WHERE {
+ ?s a foaf:Person .
+ }
"""
)
- print("After the UPDATE, there are {} triples in the graph".format(len(g)))
+ print(f"After the UPDATE, there are {len(g)} triples in the graph")
diff --git a/examples/sparqlstore_example.py b/examples/sparqlstore_example.py
index 986f883c..9d9d3fd4 100644
--- a/examples/sparqlstore_example.py
+++ b/examples/sparqlstore_example.py
@@ -20,6 +20,7 @@ if __name__ == "__main__":
int(pop)
).replace(",", ".")
)
+ print()
# EXAMPLE 2: using a SPARQLStore object directly
st = SPARQLStore(query_endpoint="http://dbpedia.org/sparql")
@@ -27,10 +28,12 @@ if __name__ == "__main__":
for p in st.objects(URIRef("http://dbpedia.org/resource/Brisbane"), dbo.populationTotal):
print(
"According to DBPedia, Brisbane has a population of "
- "{0:,}".format(int(pop))
+ "{0:,}".format(int(p), ",d")
)
+ print()
# EXAMPLE 3: doing RDFlib triple navigation using SPARQLStore as a Graph()
+ print("Triple navigation using SPARQLStore as a Graph():")
graph = Graph("SPARQLStore", identifier="http://dbpedia.org")
graph.open("http://dbpedia.org/sparql")
# we are asking DBPedia for 3 skos:Concept instances
@@ -38,7 +41,7 @@ if __name__ == "__main__":
from rdflib.namespace import RDF, SKOS
for s in graph.subjects(predicate=RDF.type, object=SKOS.Concept):
count += 1
- print(s)
+ print(f"\t- {s}")
if count >= 3:
break
diff --git a/examples/swap_primer.py b/examples/swap_primer.py
index 45327c5f..dad76211 100644
--- a/examples/swap_primer.py
+++ b/examples/swap_primer.py
@@ -5,7 +5,7 @@ example stuff in the Primer on N3:
http://www.w3.org/2000/10/swap/Primer
"""
-from rdflib import ConjunctiveGraph, Namespace, Literal, URIRef
+from rdflib import ConjunctiveGraph, Namespace, Literal
from rdflib.namespace import OWL, DC
if __name__ == "__main__":
@@ -15,7 +15,7 @@ if __name__ == "__main__":
# Think of it as a blank piece of graph paper!
primer = ConjunctiveGraph()
- myNS = Namespace("#")
+ myNS = Namespace("https://example.com/")
primer.add((myNS.pat, myNS.knows, myNS.jo))
# or:
@@ -64,7 +64,7 @@ if __name__ == "__main__":
# Lets start with a verbatim string straight from the primer text:
mySource = """
- @prefix : <#> .
+ @prefix : <https://example.com/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@@ -75,25 +75,25 @@ if __name__ == "__main__":
<> dc:title
"Primer - Getting into the Semantic Web and RDF using N3".
- <#pat> <#knows> <#jo> .
- <#pat> <#age> 24 .
- <#al> is <#child> of <#pat> .
+ :pat :knows :jo .
+ :pat :age 24 .
+ :al :is_child_of :pat .
- <#pat> <#child> <#al>, <#chaz>, <#mo> ;
- <#age> 24 ;
- <#eyecolor> "blue" .
+ :pat :child :al, :chaz, :mo ;
+ :age 24 ;
+ :eyecolor "blue" .
- :Person a rdfs:Class.
+ :Person a rdfs:Class .
- :Pat a :Person.
+ :Pat a :Person .
:Woman a rdfs:Class; rdfs:subClassOf :Person .
- :sister a rdf:Property.
+ :sister a rdf:Property .
- :sister rdfs:domain :Person;
- rdfs:range :Woman.
+ :sister rdfs:domain :Person ;
+ rdfs:range :Woman .
:Woman = foo:FemaleAdult .
:Title a rdf:Property; = dc:title .
diff --git a/rdflib/paths.py b/rdflib/paths.py
index 10706a23..48cb2e7c 100644
--- a/rdflib/paths.py
+++ b/rdflib/paths.py
@@ -46,29 +46,28 @@ In SPARQL the syntax is as follows:
|(elt) | A group path elt, brackets control precedence. |
+--------------------+-------------------------------------------------+
-This module is used internally be the SPARQL engine, but they property paths
+This module is used internally by the SPARQL engine, but the property paths
can also be used to query RDFLib Graphs directly.
-Where possible the SPARQL syntax is mapped to python operators, and property
+Where possible the SPARQL syntax is mapped to Python operators, and property
path objects can be constructed from existing URIRefs.
>>> from rdflib import Graph, Namespace
+>>> from rdflib.namespace import FOAF
->>> foaf=Namespace('http://xmlns.com/foaf/0.1/')
-
->>> ~foaf.knows
+>>> ~FOAF.knows
Path(~http://xmlns.com/foaf/0.1/knows)
->>> foaf.knows/foaf.name
+>>> FOAF.knows/FOAF.name
Path(http://xmlns.com/foaf/0.1/knows / http://xmlns.com/foaf/0.1/name)
->>> foaf.name|foaf.givenName
+>>> FOAF.name|FOAF.givenName
Path(http://xmlns.com/foaf/0.1/name | http://xmlns.com/foaf/0.1/givenName)
Modifiers (?, *, +) are done using * (the multiplication operator) and
the strings '*', '?', '+', also defined as constants in this file.
->>> foaf.knows*OneOrMore
+>>> FOAF.knows*OneOrMore
Path(http://xmlns.com/foaf/0.1/knows+)
The path objects can also be used with the normal graph methods.
@@ -89,17 +88,18 @@ First some example data:
...
... ''', format='n3') # doctest: +ELLIPSIS
->>> e=Namespace('ex:')
+>>> e = Namespace('ex:')
Graph contains:
+
>>> (e.a, e.p1/e.p2, e.e) in g
True
Graph generator functions, triples, subjects, objects, etc. :
>>> list(g.objects(e.c, (e.p3*OneOrMore)/e.p2)) # doctest: +NORMALIZE_WHITESPACE
-[rdflib.term.URIRef(u'ex:j'), rdflib.term.URIRef(u'ex:g'),
- rdflib.term.URIRef(u'ex:f')]
+[rdflib.term.URIRef('ex:j'), rdflib.term.URIRef('ex:g'),
+ rdflib.term.URIRef('ex:f')]
A more complete set of tests:
@@ -129,27 +129,27 @@ True
True
>>> list(evalPath(g, (e.q, e.px*OneOrMore, None)))
-[(rdflib.term.URIRef(u'ex:q'), rdflib.term.URIRef(u'ex:q'))]
+[(rdflib.term.URIRef('ex:q'), rdflib.term.URIRef('ex:q'))]
>>> list(evalPath(g, (None, e.p1|e.p2, e.c)))
-[(rdflib.term.URIRef(u'ex:a'), rdflib.term.URIRef(u'ex:c'))]
+[(rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:c'))]
>>> list(evalPath(g, (None, ~e.p1, e.a))) == [ (e.c, e.a) ]
True
>>> list(evalPath(g, (None, e.p1*ZeroOrOne, e.c))) # doctest: +NORMALIZE_WHITESPACE
-[(rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:c')),
- (rdflib.term.URIRef(u'ex:a'), rdflib.term.URIRef(u'ex:c'))]
+[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:c')),
+ (rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:c'))]
>>> list(evalPath(g, (None, e.p3*OneOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
-[(rdflib.term.URIRef(u'ex:h'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:g'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:a'))]
+[(rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a'))]
>>> list(evalPath(g, (None, e.p3*ZeroOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
-[(rdflib.term.URIRef(u'ex:a'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:h'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:g'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:a'))]
+[(rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a'))]
>>> list(evalPath(g, (None, -e.p1, e.f))) == [(e.a, e.f)]
True
@@ -163,22 +163,20 @@ True
True
>>> list(evalPath(g, (e.q, e.px*OneOrMore, None)))
-[(rdflib.term.URIRef(u'ex:q'), rdflib.term.URIRef(u'ex:q'))]
+[(rdflib.term.URIRef('ex:q'), rdflib.term.URIRef('ex:q'))]
>>> list(evalPath(g, (e.c, (e.p2|e.p3)*ZeroOrMore, e.j)))
-[(rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:j'))]
+[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:j'))]
No vars specified:
>>> sorted(list(evalPath(g, (None, e.p3*OneOrMore, None)))) #doctest: +NORMALIZE_WHITESPACE
-[(rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:g')),
- (rdflib.term.URIRef(u'ex:c'), rdflib.term.URIRef(u'ex:h')),
- (rdflib.term.URIRef(u'ex:g'), rdflib.term.URIRef(u'ex:a')),
- (rdflib.term.URIRef(u'ex:g'), rdflib.term.URIRef(u'ex:h')),
- (rdflib.term.URIRef(u'ex:h'), rdflib.term.URIRef(u'ex:a'))]
-
-.. versionadded:: 4.0
+[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:g')),
+ (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:h')),
+ (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),
+ (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:h')),
+ (rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a'))]
"""
@@ -336,11 +334,11 @@ class MulPath(Path):
if self.zero and first:
if subj and obj:
if subj == obj:
- yield (subj, obj)
+ yield subj, obj
elif subj:
- yield (subj, subj)
+ yield subj, subj
elif obj:
- yield (obj, obj)
+ yield obj, obj
def _fwd(subj=None, obj=None, seen=None):
seen.add(subj)
@@ -393,9 +391,9 @@ class MulPath(Path):
f = list(_fwd(s, None, set()))
for s1, o1 in f:
assert s1 == s
- yield (s1, o1)
+ yield s1, o1
- done = set() # the spec does by defn. not allow duplicates
+ done = set() # the spec does, by defn, not allow duplicates
if subj:
for x in _fwd(subj, obj, set()):
if x not in done:
diff --git a/rdflib/term.py b/rdflib/term.py
index 0a877daa..eb26f44d 100644
--- a/rdflib/term.py
+++ b/rdflib/term.py
@@ -449,7 +449,7 @@ class Literal(Identifier):
__doc__ = """
RDF Literal: http://www.w3.org/TR/rdf-concepts/#section-Graph-Literal
- The lexical value of the literal is the unicode object
+ The lexical value of the literal is the unicode object.
The interpreted, datatyped value is available from .value
Language tags must be valid according to :rfc:5646
@@ -462,17 +462,17 @@ class Literal(Identifier):
>>> from rdflib.namespace import XSD
- >>> Literal('01')!=Literal('1') # clear - strings differ
+ >>> Literal('01') != Literal('1') # clear - strings differ
True
but with data-type they get normalized:
- >>> Literal('01', datatype=XSD.integer)!=Literal('1', datatype=XSD.integer)
+ >>> Literal('01', datatype=XSD.integer) != Literal('1', datatype=XSD.integer)
False
unless disabled:
- >>> Literal('01', datatype=XSD.integer, normalize=False)!=Literal('1', datatype=XSD.integer)
+ >>> Literal('01', datatype=XSD.integer, normalize=False) != Literal('1', datatype=XSD.integer)
True
@@ -1450,7 +1450,7 @@ _XSD_B64BINARY = URIRef(_XSD_PFX + "base64Binary")
_XSD_HEXBINARY = URIRef(_XSD_PFX + "hexBinary")
_XSD_GYEAR = URIRef(_XSD_PFX + "gYear")
_XSD_GYEARMONTH = URIRef(_XSD_PFX + "gYearMonth")
-# TODO: gYearMonth, gYear, gMonthDay, gDay, gMonth
+# TODO: gMonthDay, gDay, gMonth
_NUMERIC_LITERAL_TYPES = (
_XSD_INTEGER,
@@ -1571,8 +1571,8 @@ _GenericPythonToXSDRules = [
]
_SpecificPythonToXSDRules = [
- ((date, _XSD_GYEAR), lambda val: val.strftime("%04Y")),
- ((date, _XSD_GYEARMONTH), lambda val: val.strftime("%04Y-%02m")),
+ ((date, _XSD_GYEAR), lambda val: val.strftime("%Y").zfill(4)),
+ ((date, _XSD_GYEARMONTH), lambda val: val.strftime("%Y-%m").zfill(7)),
((str, _XSD_HEXBINARY), hexlify),
((bytes, _XSD_HEXBINARY), hexlify),
((str, _XSD_B64BINARY), b64encode),
diff --git a/rdflib/tools/csv2rdf.py b/rdflib/tools/csv2rdf.py
index eed77298..5c12e753 100644
--- a/rdflib/tools/csv2rdf.py
+++ b/rdflib/tools/csv2rdf.py
@@ -1,5 +1,7 @@
"""
-A commandline tool for semi-automatically converting CSV to RDF
+A commandline tool for semi-automatically converting CSV to RDF.
+
+See also https://github.com/RDFLib/pyTARQL in the RDFlib family of tools
try: ``csv2rdf --help``
diff --git a/test/test_csv2rdf.py b/test/test_csv2rdf.py
index d0bba696..fee10a31 100644
--- a/test/test_csv2rdf.py
+++ b/test/test_csv2rdf.py
@@ -2,12 +2,16 @@ import subprocess
import unittest
from os import remove
from tempfile import mkstemp
+from pathlib import Path
class CSV2RDFTest(unittest.TestCase):
+ def setUp(self):
+ self.REALESTATE_FILE_PATH = Path(__file__).parent / "csv" / "realestate.csv"
+
def test_csv2rdf_cli(self):
completed = subprocess.run(
- ["csv2rdf", "test/csv/realestate.csv"],
+ ["csv2rdf", str(self.REALESTATE_FILE_PATH)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
@@ -20,7 +24,7 @@ class CSV2RDFTest(unittest.TestCase):
def test_csv2rdf_cli_fileout(self):
_, fname = mkstemp()
- completed = subprocess.run(["csv2rdf", "-o", fname, "test/csv/realestate.csv"],)
+ completed = subprocess.run(["csv2rdf", "-o", fname, str(self.REALESTATE_FILE_PATH)], )
self.assertEqual(completed.returncode, 0)
with open(fname) as f:
self.assertGreater(len(f.readlines()), 0)
diff --git a/test/test_literal.py b/test/test_literal.py
index a7de912b..0c138230 100644
--- a/test/test_literal.py
+++ b/test/test_literal.py
@@ -7,10 +7,6 @@ from rdflib.term import Literal, URIRef, _XSD_DOUBLE, bind, _XSD_BOOLEAN
from rdflib.namespace import XSD
-def uformat(s):
- return s.replace("u'", "'")
-
-
class TestLiteral(unittest.TestCase):
def setUp(self):
pass
@@ -75,20 +71,18 @@ class TestNew(unittest.TestCase):
class TestRepr(unittest.TestCase):
def testOmitsMissingDatatypeAndLang(self):
- self.assertEqual(repr(Literal("foo")), uformat("rdflib.term.Literal(u'foo')"))
+ self.assertEqual(repr(Literal("foo")), "rdflib.term.Literal('foo')")
def testOmitsMissingDatatype(self):
self.assertEqual(
repr(Literal("foo", lang="en")),
- uformat("rdflib.term.Literal(u'foo', lang='en')"),
+ "rdflib.term.Literal('foo', lang='en')",
)
def testOmitsMissingLang(self):
self.assertEqual(
repr(Literal("foo", datatype=URIRef("http://example.com/"))),
- uformat(
- "rdflib.term.Literal(u'foo', datatype=rdflib.term.URIRef(u'http://example.com/'))"
- ),
+ "rdflib.term.Literal('foo', datatype=rdflib.term.URIRef('http://example.com/'))",
)
def testSubclassNameAppearsInRepr(self):
@@ -96,7 +90,7 @@ class TestRepr(unittest.TestCase):
pass
x = MyLiteral("foo")
- self.assertEqual(repr(x), uformat("MyLiteral('foo')"))
+ self.assertEqual(repr(x), "MyLiteral('foo')")
class TestDoubleOutput(unittest.TestCase):
@@ -124,10 +118,10 @@ class TestParseBoolean(unittest.TestCase):
def testNonFalseBoolean(self):
test_value = Literal("abcd", datatype=_XSD_BOOLEAN)
- self.assertRaises(DeprecationWarning)
+ self.assertRaises(UserWarning)
self.assertFalse(test_value.value)
test_value = Literal("10", datatype=_XSD_BOOLEAN)
- self.assertRaises(DeprecationWarning)
+ self.assertRaises(UserWarning)
self.assertFalse(test_value.value)
@@ -197,7 +191,7 @@ class TestXsdLiterals(unittest.TestCase):
Tests literal construction.
"""
inputs = [
- # these literals do not get conerted to python types
+ # these literals do not get converted to Python types
("ABCD", XSD.integer, None),
("ABCD", XSD.gYear, None),
("-10000", XSD.gYear, None),
@@ -260,7 +254,7 @@ class TestXsdLiterals(unittest.TestCase):
def check_make_literals(self, inputs):
for literal_pair in inputs:
(lexical, type, value_cls) = literal_pair
- with self.subTest(f"tesing {literal_pair}"):
+ with self.subTest(f"testing {literal_pair}"):
literal = Literal(lexical, datatype=type)
if value_cls is not None:
self.assertIsInstance(literal.value, value_cls)