Improves pyoxigraph documentation

pull/173/head
Tpt 3 years ago
parent ad4dd2832e
commit d6d88b074c
  1. 7
      lib/src/store.rs
  2. 5
      python/docs/index.rst
  3. 22
      python/src/io.rs
  4. 74
      python/src/model.rs
  5. 3
      python/src/sparql.rs
  6. 171
      python/src/store.rs

@ -45,8 +45,9 @@ use std::{fmt, io, str};
/// Allows to query and update it using SPARQL.
/// It is based on the [RocksDB](https://rocksdb.org/) key-value store.
///
/// This store ensure the "repeatable read" isolation level.
/// All operations are not able to read the result of concurrent
/// This store ensure the "repeatable read" isolation level: the store only exposes changes that have
/// been "committed" (i.e. no partial writes) and the exposed state does not change for the complete duration
/// of a read operation (e.g. a SPARQL query) or a read/write operation (e.g. a SPARQL update).
///
/// Usage example:
/// ```
@ -721,7 +722,7 @@ impl Store {
impl fmt::Display for Store {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.iter() {
writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?;
writeln!(f, "{} .", t.map_err(|_| fmt::Error)?)?;
}
Ok(())
}

@ -16,9 +16,6 @@ Pyoxigraph is a Python graph database library implementing the `SPARQL <https://
It is built on top of `Oxigraph <https://crates.io/crates/oxigraph>`_ using `PyO3 <https://pyo3.rs/>`_.
It offers two stores with `SPARQL 1.1 <https://www.w3.org/TR/sparql11-overview/>`_ capabilities.
One of the store is in-memory, and the other one is disk based.
It also provides a set of utility functions for reading, writing and processing RDF files in
`Turtle <https://www.w3.org/TR/turtle/>`_,
`TriG <https://www.w3.org/TR/trig/>`_,
@ -28,7 +25,7 @@ It also provides a set of utility functions for reading, writing and processing
Pyoxigraph is `distributed on Pypi <https://pypi.org/project/pyoxigraph/>`_.
There exists also a small library providing `rdflib <https://rdflib.readthedocs.io>`_ stores using pyoxigraph: `oxrdflib <https://github.com/oxigraph/oxrdflib>`_.
There is also a small library providing an `rdflib <https://rdflib.readthedocs.io>`_ store using pyoxigraph: `oxrdflib <https://github.com/oxigraph/oxrdflib>`_.
Oxigraph and pyoxigraph source code are on `GitHub <https://github.com/oxigraph/oxigraph/tree/master/python>`_.

@ -16,7 +16,7 @@ pub fn add_to_module(module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_pyfunction!(serialize))
}
/// Parses RDF graph and dataset serialization formats
/// Parses RDF graph and dataset serialization formats.
///
/// It currently supports the following formats:
///
@ -32,14 +32,14 @@ pub fn add_to_module(module: &PyModule) -> PyResult<()> {
///
/// :param input: The binary I/O object to read from. For example, it could be a file opened in binary mode with ``open('my_file.ttl', 'rb')``.
/// :type input: io.RawIOBase or io.BufferedIOBase
/// :param mime_type: the MIME type of the RDF serialization
/// :param mime_type: the MIME type of the RDF serialization.
/// :type mime_type: str
/// :param base_iri: the base IRI used to resolve the relative IRIs in the file or :py:const:`None` if relative IRI resolution should not be done
/// :param base_iri: the base IRI used to resolve the relative IRIs in the file or :py:const:`None` if relative IRI resolution should not be done.
/// :type base_iri: str or None, optional
/// :return: an iterator of RDF triples or quads depending on the format
/// :return: an iterator of RDF triples or quads depending on the format.
/// :rtype: iter(Triple) or iter(Quad)
/// :raises ValueError: if the MIME type is not supported
/// :raises SyntaxError: if the provided data is invalid
/// :raises ValueError: if the MIME type is not supported.
/// :raises SyntaxError: if the provided data is invalid.
///
/// >>> input = io.BytesIO(b'<foo> <p> "1" .')
/// >>> list(parse(input, "text/turtle", base_iri="http://example.com/"))
@ -83,7 +83,7 @@ pub fn parse(
}
}
/// Serializes an RDF graph or dataset
/// Serializes an RDF graph or dataset.
///
/// It currently supports the following formats:
///
@ -97,14 +97,14 @@ pub fn parse(
/// For example ``application/turtle`` could also be used for `Turtle <https://www.w3.org/TR/turtle/>`_
/// and ``application/xml`` for `RDF/XML <https://www.w3.org/TR/rdf-syntax-grammar/>`_.
///
/// :param input: the RDF triples and quads to serialize
/// :param input: the RDF triples and quads to serialize.
/// :type input: iter(Triple) or iter(Quad)
/// :param output: The binary I/O object to write to. For example, it could be a file opened in binary mode with ``open('my_file.ttl', 'wb')``.
/// :type output: io.RawIOBase or io.BufferedIOBase
/// :param mime_type: the MIME type of the RDF serialization
/// :param mime_type: the MIME type of the RDF serialization.
/// :type mime_type: str
/// :raises ValueError: if the MIME type is not supported
/// :raises TypeError: if a triple is given during a quad format serialization or reverse
/// :raises ValueError: if the MIME type is not supported.
/// :raises TypeError: if a triple is given during a quad format serialization or reverse.
///
/// >>> output = io.BytesIO()
/// >>> serialize([Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'))], output, "text/turtle")

@ -9,11 +9,11 @@ use std::hash::Hash;
use std::hash::Hasher;
use std::vec::IntoIter;
/// An RDF `node identified by an IRI <https://www.w3.org/TR/rdf11-concepts/#dfn-iri>`_
/// An RDF `node identified by an IRI <https://www.w3.org/TR/rdf11-concepts/#dfn-iri>`_.
///
/// :param value: the IRI as a string
/// :param value: the IRI as a string.
/// :type value: str
/// :raises ValueError: if the IRI is not valid according to `RFC 3987 <https://tools.ietf.org/rfc/rfc3987>`_
/// :raises ValueError: if the IRI is not valid according to `RFC 3987 <https://tools.ietf.org/rfc/rfc3987>`_.
///
/// The :py:func:`str` function provides a serialization compatible with NTriples, Turtle and SPARQL:
///
@ -71,7 +71,7 @@ impl PyNamedNode {
.into())
}
/// :return: the named node IRI
/// :return: the named node IRI.
/// :rtype: str
///
/// >>> NamedNode("http://example.com").value
@ -111,7 +111,7 @@ impl PyNamedNode {
}
}
/// An RDF `blank node <https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node>`_
/// An RDF `blank node <https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node>`_.
///
/// :param value: the `blank node ID <https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier>`_ (if not present, a random blank node ID is automatically generated).
/// :type value: str, optional
@ -176,7 +176,7 @@ impl PyBlankNode {
.into())
}
/// :return: the `blank node ID <https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier>`_
/// :return: the `blank node ID <https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node-identifier>`_.
/// :rtype: str
///
/// >>> BlankNode("ex").value
@ -216,15 +216,15 @@ impl PyBlankNode {
}
}
/// An RDF `literal <https://www.w3.org/TR/rdf11-concepts/#dfn-literal>`_
/// An RDF `literal <https://www.w3.org/TR/rdf11-concepts/#dfn-literal>`_.
///
/// :param value: the literal value or `lexical form <https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form>`_
/// :param value: the literal value or `lexical form <https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form>`_.
/// :type value: str
/// :param datatype: the literal `datatype IRI <https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri>`_.
/// :type datatype: NamedNode, optional
/// :param language: the literal `language tag <https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag>`_
/// :param language: the literal `language tag <https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag>`_.
/// :type language: str, optional
/// :raises ValueError: if the language tag is not valid according to `RFC 5646 <https://tools.ietf.org/rfc/rfc5646>`_ (`BCP 47 <https://tools.ietf.org/rfc/bcp/bcp47>`_)
/// :raises ValueError: if the language tag is not valid according to `RFC 5646 <https://tools.ietf.org/rfc/rfc5646>`_ (`BCP 47 <https://tools.ietf.org/rfc/bcp/bcp47>`_).
///
/// The :py:func:`str` function provides a serialization compatible with NTriples, Turtle and SPARQL:
///
@ -286,7 +286,7 @@ impl PyLiteral {
.into())
}
/// :return: the literal value or `lexical form <https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form>`_
/// :return: the literal value or `lexical form <https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form>`_.
/// :rtype: str
///
/// >>> Literal("example").value
@ -296,7 +296,7 @@ impl PyLiteral {
self.inner.value()
}
/// :return: the literal `language tag <https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag>`_
/// :return: the literal `language tag <https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag>`_.
/// :rtype: str or None
///
/// >>> Literal('example', language='en').language
@ -308,7 +308,7 @@ impl PyLiteral {
self.inner.language()
}
/// :return: the literal `datatype IRI <https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri>`_
/// :return: the literal `datatype IRI <https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri>`_.
/// :rtype: NamedNode
///
/// >>> Literal('11', datatype=NamedNode('http://www.w3.org/2001/XMLSchema#integer')).datatype
@ -352,7 +352,7 @@ impl PyLiteral {
}
}
/// The RDF `default graph name <https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph>`_
/// The RDF `default graph name <https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph>`_.
#[pyclass(name = "DefaultGraph", module = "oxigraph")]
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct PyDefaultGraph {}
@ -514,19 +514,19 @@ impl IntoPy<PyObject> for PyTerm {
}
}
/// An RDF `triple <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple>`_
/// An RDF `triple <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple>`_.
///
/// :param subject: the triple subject
/// :param subject: the triple subject.
/// :type subject: NamedNode or BlankNode
/// :param predicate: the triple predicate
/// :param predicate: the triple predicate.
/// :type predicate: NamedNode
/// :param object: the triple object
/// :param object: the triple object.
/// :type object: NamedNode or BlankNode or Literal
///
/// The :py:func:`str` function provides a serialization compatible with NTriples, Turtle and SPARQL:
///
/// >>> str(Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')))
/// '<http://example.com> <http://example.com/p> "1" .'
/// '<http://example.com> <http://example.com/p> "1"'
///
/// A triple could also be easily destructed into its components:
///
@ -575,7 +575,7 @@ impl PyTriple {
Triple::new(subject, predicate, object).into()
}
/// :return: the triple subject
/// :return: the triple subject.
/// :rtype: NamedNode or BlankNode
///
/// >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).subject
@ -585,7 +585,7 @@ impl PyTriple {
self.inner.subject.clone().into()
}
/// :return: the triple predicate
/// :return: the triple predicate.
/// :rtype: NamedNode
///
/// >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).predicate
@ -595,7 +595,7 @@ impl PyTriple {
self.inner.predicate.clone().into()
}
/// :return: the triple object
/// :return: the triple object.
/// :rtype: NamedNode or BlankNode or Literal
///
/// >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).object
@ -685,14 +685,14 @@ impl IntoPy<PyObject> for PyGraphName {
}
}
/// An RDF `triple <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple>`_
/// in a `RDF dataset <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset>`_
/// An RDF `triple <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple>`_.
/// in a `RDF dataset <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset>`_.
///
/// :param subject: the quad subject
/// :param subject: the quad subject.
/// :type subject: NamedNode or BlankNode
/// :param predicate: the quad predicate
/// :param predicate: the quad predicate.
/// :type predicate: NamedNode
/// :param object: the quad object
/// :param object: the quad object.
/// :type object: NamedNode or BlankNode or Literal
/// :param graph: the quad graph name. If not present, the default graph is assumed.
/// :type graph: NamedNode or BlankNode or DefaultGraph or None, optional
@ -700,10 +700,10 @@ impl IntoPy<PyObject> for PyGraphName {
/// The :py:func:`str` function provides a serialization compatible with NTriples, Turtle and SPARQL:
///
/// >>> str(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')))
/// '<http://example.com> <http://example.com/p> "1" <http://example.com/g> .'
/// '<http://example.com> <http://example.com/p> "1" <http://example.com/g>'
///
/// >>> str(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), DefaultGraph()))
/// '<http://example.com> <http://example.com/p> "1" .'
/// '<http://example.com> <http://example.com/p> "1"'
///
/// A quad could also be easily destructed into its components:
///
@ -751,7 +751,7 @@ impl PyQuad {
.into()
}
/// :return: the quad subject
/// :return: the quad subject.
/// :rtype: NamedNode or BlankNode
///
/// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).subject
@ -761,7 +761,7 @@ impl PyQuad {
self.inner.subject.clone().into()
}
/// :return: the quad predicate
/// :return: the quad predicate.
/// :rtype: NamedNode
///
/// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).predicate
@ -771,7 +771,7 @@ impl PyQuad {
self.inner.predicate.clone().into()
}
/// :return: the quad object
/// :return: the quad object.
/// :rtype: NamedNode or BlankNode or Literal
///
/// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).object
@ -781,7 +781,7 @@ impl PyQuad {
self.inner.object.clone().into()
}
/// :return: the quad graph name
/// :return: the quad graph name.
/// :rtype: NamedNode or BlankNode or DefaultGraph
///
/// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).graph_name
@ -791,7 +791,7 @@ impl PyQuad {
self.inner.graph_name.clone().into()
}
/// :return: the quad underlying triple
/// :return: the quad underlying triple.
/// :rtype: Triple
///
/// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).triple
@ -860,9 +860,9 @@ impl PyQuad {
}
}
/// A SPARQL query variable
/// A SPARQL query variable.
///
/// :param value: the variable name as a string
/// :param value: the variable name as a string.
/// :type value: str
/// :raises ValueError: if the variable name is invalid according to the SPARQL grammar.
///
@ -904,7 +904,7 @@ impl PyVariable {
.into())
}
/// :return: the variable name
/// :return: the variable name.
/// :rtype: str
///
/// >>> Variable("foo").value

@ -9,11 +9,12 @@ use std::vec::IntoIter;
pub fn parse_query(
query: &str,
base_iri: Option<&str>,
use_default_graph_as_union: bool,
default_graph: Option<&PyAny>,
named_graphs: Option<&PyAny>,
) -> PyResult<Query> {
let mut query = Query::parse(query, None).map_err(|e| map_evaluation_error(e.into()))?;
let mut query = Query::parse(query, base_iri).map_err(|e| map_evaluation_error(e.into()))?;
if use_default_graph_as_union && default_graph.is_some() {
return Err(PyValueError::new_err(

@ -5,6 +5,7 @@ use crate::model::*;
use crate::sparql::*;
use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::GraphNameRef;
use oxigraph::sparql::Update;
use oxigraph::store::{self, Store};
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
@ -14,11 +15,15 @@ use std::io::BufReader;
/// Disk-based RDF store.
///
/// It encodes a `RDF dataset <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset>`_ and allows to query it using SPARQL.
/// It is based on the `RocksDB <https://rocksdb.org/>`_ key-value database
/// It is based on the `RocksDB <https://rocksdb.org/>`_ key-value database.
///
/// This store ensure the "repeatable read" isolation level: the store only exposes changes that have
/// been "committed" (i.e. no partial writes) and the exposed state does not change for the complete duration
/// of a read operation (e.g. a SPARQL query) or a read/write operation (e.g. a SPARQL update).
///
/// :param path: the path of the directory in which the store should read and write its data. If the directory does not exist, it is created. If no directory is provided a temporary one is created and removed when the Python garbage collector removes the store.
/// :type path: str or None, optional
/// :raises IOError: if the target directory contains invalid data or could not be accessed
/// :type path: str or None, optional.
/// :raises IOError: if the target directory contains invalid data or could not be accessed.
///
/// The :py:func:`str` function provides a serialization of the store in NQuads:
///
@ -47,11 +52,11 @@ impl PyStore {
})
}
/// Adds a quad to the store
/// Adds a quad to the store.
///
/// :param quad: the quad to add
/// :param quad: the quad to add.
/// :type quad: Quad
/// :raises IOError: if an I/O error happens during the quad insertion
/// :raises IOError: if an I/O error happens during the quad insertion.
///
/// >>> store = Store()
/// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')))
@ -63,11 +68,11 @@ impl PyStore {
Ok(())
}
/// Removes a quad from the store
/// Removes a quad from the store.
///
/// :param quad: the quad to remove
/// :param quad: the quad to remove.
/// :type quad: Quad
/// :raises IOError: if an I/O error happens during the quad removal
/// :raises IOError: if an I/O error happens during the quad removal.
///
/// >>> store = Store()
/// >>> quad = Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))
@ -81,7 +86,7 @@ impl PyStore {
Ok(())
}
/// Looks for the quads matching a given pattern
/// Looks for the quads matching a given pattern.
///
/// :param subject: the quad subject or :py:const:`None` to match everything.
/// :type subject: NamedNode or BlankNode or None
@ -91,9 +96,9 @@ impl PyStore {
/// :type object: NamedNode or BlankNode or Literal or None
/// :param graph: the quad graph name. To match only the default graph, use :py:class:`DefaultGraph`. To match everything use :py:const:`None`.
/// :type graph: NamedNode or BlankNode or DefaultGraph or None
/// :return: an iterator of the quads matching the pattern
/// :return: an iterator of the quads matching the pattern.
/// :rtype: iter(Quad)
/// :raises IOError: if an I/O error happens during the quads lookup
/// :raises IOError: if an I/O error happens during the quads lookup.
///
/// >>> store = Store()
/// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')))
@ -121,8 +126,10 @@ impl PyStore {
/// Executes a `SPARQL 1.1 query <https://www.w3.org/TR/sparql11-query/>`_.
///
/// :param query: the query to execute
/// :param query: the query to execute.
/// :type query: str
/// :param base_iri: the base IRI used to resolve the relative IRIs in the SPARQL query or :py:const:`None` if relative IRI resolution should not be done.
/// :type base_iri: str or None, optional
/// :param use_default_graph_as_union: if the SPARQL query should look for triples in all the dataset graphs by default (i.e. without `GRAPH` operations). Disabled by default.
/// :type use_default_graph_as_union: bool, optional
/// :param default_graph: list of the graphs that should be used as the query default graph. By default, the store default graph is used.
@ -131,8 +138,8 @@ impl PyStore {
/// :type named_graphs: list(NamedNode or BlankNode) or None, optional
/// :return: a :py:class:`bool` for ``ASK`` queries, an iterator of :py:class:`Triple` for ``CONSTRUCT`` and ``DESCRIBE`` queries and an iterator of :py:class:`QuerySolution` for ``SELECT`` queries.
/// :rtype: QuerySolutions or QueryTriples or bool
/// :raises SyntaxError: if the provided query is invalid
/// :raises IOError: if an I/O error happens while reading the store
/// :raises SyntaxError: if the provided query is invalid.
/// :raises IOError: if an I/O error happens while reading the store.
///
/// ``SELECT`` query:
///
@ -155,11 +162,12 @@ impl PyStore {
/// >>> store.query('ASK { ?s ?p ?o }')
/// True
#[pyo3(
text_signature = "($self, query, *, use_default_graph_as_union, default_graph, named_graphs)"
text_signature = "($self, query, *, base_iri, use_default_graph_as_union, default_graph, named_graphs)"
)]
#[args(
query,
"*",
base_iri = "None",
use_default_graph_as_union = "false",
default_graph = "None",
named_graphs = "None"
@ -167,6 +175,7 @@ impl PyStore {
fn query(
&self,
query: &str,
base_iri: Option<&str>,
use_default_graph_as_union: bool,
default_graph: Option<&PyAny>,
named_graphs: Option<&PyAny>,
@ -174,6 +183,7 @@ impl PyStore {
) -> PyResult<PyObject> {
let query = parse_query(
query,
base_iri,
use_default_graph_as_union,
default_graph,
named_graphs,
@ -184,10 +194,14 @@ impl PyStore {
/// Executes a `SPARQL 1.1 update <https://www.w3.org/TR/sparql11-update/>`_.
///
/// :param update: the update to execute
/// Updates are applied in a transactional manner: either the full operation succeeds or nothing is written to the database.
///
/// :param update: the update to execute.
/// :type update: str
/// :raises SyntaxError: if the provided update is invalid
/// :raises IOError: if an I/O error happens while reading the store
/// :param base_iri: the base IRI used to resolve the relative IRIs in the SPARQL update or :py:const:`None` if relative IRI resolution should not be done.
/// :type base_iri: str or None, optional
/// :raises SyntaxError: if the provided update is invalid.
/// :raises IOError: if an I/O error happens while reading the store.
///
/// The store does not track the existence of empty named graphs.
/// This method has no ACID guarantees.
@ -214,12 +228,19 @@ impl PyStore {
/// >>> store.update('DELETE WHERE { <http://example.com> ?p ?o }')
/// >>> list(store)
/// []
#[pyo3(text_signature = "($self, update)")]
fn update(&self, update: &str) -> PyResult<()> {
#[pyo3(text_signature = "($self, update, *, base_iri)")]
#[args(update, "*", base_iri = "None")]
fn update(&self, update: &str, base_iri: Option<&str>) -> PyResult<()> {
let update = Update::parse(update, base_iri).map_err(|e| map_evaluation_error(e.into()))?;
self.inner.update(update).map_err(map_evaluation_error)
}
/// Loads an RDF serialization into the store
/// Loads an RDF serialization into the store.
///
/// Loads are applied in a transactional manner: either the full operation succeeds or nothing is written to the database.
/// The :py:func:`bulk_load` method is also available for much faster loading of big files but without transactional guarantees.
///
/// Beware, the full file is loaded into memory.
///
/// It currently supports the following formats:
///
@ -235,15 +256,15 @@ impl PyStore {
///
/// :param input: The binary I/O object to read from. For example, it could be a file opened in binary mode with ``open('my_file.ttl', 'rb')``.
/// :type input: io.RawIOBase or io.BufferedIOBase
/// :param mime_type: the MIME type of the RDF serialization
/// :param mime_type: the MIME type of the RDF serialization.
/// :type mime_type: str
/// :param base_iri: the base IRI used to resolve the relative IRIs in the file or :py:const:`None` if relative IRI resolution should not be done
/// :param base_iri: the base IRI used to resolve the relative IRIs in the file or :py:const:`None` if relative IRI resolution should not be done.
/// :type base_iri: str or None, optional
/// :param to_graph: if it is a file composed of triples, the graph in which store the triples. By default, the default graph is used.
/// :type to_graph: NamedNode or BlankNode or DefaultGraph or None, optional
/// :raises ValueError: if the MIME type is not supported or the `to_graph` parameter is given with a quad file.
/// :raises SyntaxError: if the provided data is invalid
/// :raises IOError: if an I/O error happens during a quad insertion
/// :raises SyntaxError: if the provided data is invalid.
/// :raises IOError: if an I/O error happens during a quad insertion.
///
/// >>> store = Store()
/// >>> store.load(io.BytesIO(b'<foo> <p> "1" .'), "text/turtle", base_iri="http://example.com/", to_graph=NamedNode("http://example.com/g"))
@ -290,7 +311,83 @@ impl PyStore {
}
}
/// Dumps the store quads or triples into a file
/// Loads an RDF serialization into the store.
///
/// This function is designed to be as fast as possible on big files without transactional guarantees.
/// If the file is invalid only a piece of it might be written to the store.
///
/// The :py:func:`load` method is also available for loads with transactional guarantees.
///
/// It currently supports the following formats:
///
/// * `N-Triples <https://www.w3.org/TR/n-triples/>`_ (``application/n-triples``)
/// * `N-Quads <https://www.w3.org/TR/n-quads/>`_ (``application/n-quads``)
/// * `Turtle <https://www.w3.org/TR/turtle/>`_ (``text/turtle``)
/// * `TriG <https://www.w3.org/TR/trig/>`_ (``application/trig``)
/// * `RDF/XML <https://www.w3.org/TR/rdf-syntax-grammar/>`_ (``application/rdf+xml``)
///
/// It supports also some MIME type aliases.
/// For example ``application/turtle`` could also be used for `Turtle <https://www.w3.org/TR/turtle/>`_
/// and ``application/xml`` for `RDF/XML <https://www.w3.org/TR/rdf-syntax-grammar/>`_.
///
/// :param input: The binary I/O object to read from. For example, it could be a file opened in binary mode with ``open('my_file.ttl', 'rb')``.
/// :type input: io.RawIOBase or io.BufferedIOBase
/// :param mime_type: the MIME type of the RDF serialization.
/// :type mime_type: str
/// :param base_iri: the base IRI used to resolve the relative IRIs in the file or :py:const:`None` if relative IRI resolution should not be done.
/// :type base_iri: str or None, optional
/// :param to_graph: if it is a file composed of triples, the graph in which store the triples. By default, the default graph is used.
/// :type to_graph: NamedNode or BlankNode or DefaultGraph or None, optional
/// :raises ValueError: if the MIME type is not supported or the `to_graph` parameter is given with a quad file.
/// :raises SyntaxError: if the provided data is invalid.
/// :raises IOError: if an I/O error happens during a quad insertion.
///
/// >>> store = Store()
/// >>> store.bulk_load(io.BytesIO(b'<foo> <p> "1" .'), "text/turtle", base_iri="http://example.com/", to_graph=NamedNode("http://example.com/g"))
/// >>> list(store)
/// [<Quad subject=<NamedNode value=http://example.com/foo> predicate=<NamedNode value=http://example.com/p> object=<Literal value=1 datatype=<NamedNode value=http://www.w3.org/2001/XMLSchema#string>> graph_name=<NamedNode value=http://example.com/g>>]
#[pyo3(text_signature = "($self, data, /, mime_type, *, base_iri = None, to_graph = None)")]
#[args(input, mime_type, "*", base_iri = "None", to_graph = "None")]
fn bulk_load(
&mut self,
input: PyObject,
mime_type: &str,
base_iri: Option<&str>,
to_graph: Option<&PyAny>,
) -> PyResult<()> {
let to_graph_name = if let Some(graph_name) = to_graph {
Some(PyGraphNameRef::try_from(graph_name)?)
} else {
None
};
let input = BufReader::new(PyFileLike::new(input));
if let Some(graph_format) = GraphFormat::from_media_type(mime_type) {
self.inner
.bulk_load_graph(
input,
graph_format,
&to_graph_name.unwrap_or(PyGraphNameRef::DefaultGraph),
base_iri,
)
.map_err(map_io_err)
} else if let Some(dataset_format) = DatasetFormat::from_media_type(mime_type) {
if to_graph_name.is_some() {
return Err(PyValueError::new_err(
"The target graph name parameter is not available for dataset formats",
));
}
self.inner
.bulk_load_dataset(input, dataset_format, base_iri)
.map_err(map_io_err)
} else {
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
}
}
/// Dumps the store quads or triples into a file.
///
/// It currently supports the following formats:
///
@ -306,7 +403,7 @@ impl PyStore {
///
/// :param output: The binary I/O object to write to. For example, it could be a file opened in binary mode with ``open('my_file.ttl', 'wb')``.
/// :type input: io.RawIOBase or io.BufferedIOBase
/// :param mime_type: the MIME type of the RDF serialization
/// :param mime_type: the MIME type of the RDF serialization.
/// :type mime_type: str
/// :param from_graph: if a triple based format is requested, the store graph from which dump the triples. By default, the default graph is used.
/// :type from_graph: NamedNode or BlankNode or DefaultGraph or None, optional
@ -353,11 +450,11 @@ impl PyStore {
}
}
/// Returns an iterator over all the store named graphs
/// Returns an iterator over all the store named graphs.
///
/// :return: an iterator of the store graph names
/// :return: an iterator of the store graph names.
/// :rtype: iter(NamedNode or BlankNode)
/// :raises IOError: if an I/O error happens during the named graphs lookup
/// :raises IOError: if an I/O error happens during the named graphs lookup.
///
/// >>> store = Store()
/// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')))
@ -370,11 +467,11 @@ impl PyStore {
}
}
/// Adds a named graph to the store
/// Adds a named graph to the store.
///
/// :param graph_name: the name of the name graph to add
/// :param graph_name: the name of the name graph to add.
/// :type graph_name: NamedNode or BlankNode
/// :raises IOError: if an I/O error happens during the named graph insertion
/// :raises IOError: if an I/O error happens during the named graph insertion.
///
/// >>> store = Store()
/// >>> store.add_graph(NamedNode('http://example.com/g'))
@ -396,13 +493,13 @@ impl PyStore {
.map_err(map_io_err)
}
/// Removes a graph from the store
/// Removes a graph from the store.
///
/// The default graph will not be remove but just cleared.
///
/// :param graph_name: the name of the name graph to remove
/// :param graph_name: the name of the name graph to remove.
/// :type graph_name: NamedNode or BlankNode or DefaultGraph
/// :raises IOError: if an I/O error happens during the named graph removal
/// :raises IOError: if an I/O error happens during the named graph removal.
///
/// >>> store = Store()
/// >>> quad = Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))

Loading…
Cancel
Save