Migrates pyo3 to 0.12

pull/60/head
Tpt 4 years ago
parent 56bdf21c4c
commit 55f1152f35
  1. 2
      python/Cargo.toml
  2. 14
      python/src/io.rs
  3. 14
      python/src/memory_store.rs
  4. 129
      python/src/model.rs
  5. 12
      python/src/sled_store.rs
  6. 27
      python/src/sparql.rs
  7. 8
      python/src/store_utils.rs

@ -16,7 +16,7 @@ doctest = false
[dependencies]
oxigraph = {version = "0.1.1", path="../lib", features = ["sled", "http_client"]}
pyo3 = {version = "0.11", features = ["extension-module"]}
pyo3 = {version = "0.12", features = ["extension-module"]}
[package.metadata.maturin]
classifier = [

@ -4,7 +4,7 @@ use oxigraph::io::read::{QuadReader, TripleReader};
use oxigraph::io::{
DatasetFormat, DatasetParser, DatasetSerializer, GraphFormat, GraphParser, GraphSerializer,
};
use pyo3::exceptions::ValueError;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::PyBytes;
use pyo3::wrap_pyfunction;
@ -59,7 +59,7 @@ pub fn parse(
if let Some(base_iri) = base_iri {
parser = parser
.with_base_iri(base_iri)
.map_err(|e| ValueError::py_err(e.to_string()))?;
.map_err(|e| PyValueError::new_err(e.to_string()))?;
}
Ok(PyTripleReader {
inner: parser.read_triples(input).map_err(map_io_err)?,
@ -70,14 +70,14 @@ pub fn parse(
if let Some(base_iri) = base_iri {
parser = parser
.with_base_iri(base_iri)
.map_err(|e| ValueError::py_err(e.to_string()))?;
.map_err(|e| PyValueError::new_err(e.to_string()))?;
}
Ok(PyQuadReader {
inner: parser.read_quads(input).map_err(map_io_err)?,
}
.into_py(py))
} else {
Err(ValueError::py_err(format!(
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
@ -138,14 +138,14 @@ pub fn serialize(input: &PyAny, output: &PyAny, mime_type: &str, py: Python<'_>)
writer.finish().map_err(map_io_err)?;
Ok(())
} else {
Err(ValueError::py_err(format!(
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
}
}
#[pyclass(unsendable, name= TripleReader)]
#[pyclass(name = TripleReader)]
pub struct PyTripleReader {
inner: TripleReader<BufReader<PyFileLike>>,
}
@ -164,7 +164,7 @@ impl PyIterProtocol for PyTripleReader {
}
}
#[pyclass(unsendable, name= QuadReader)]
#[pyclass(name = QuadReader)]
pub struct PyQuadReader {
inner: QuadReader<BufReader<PyFileLike>>,
}

@ -5,7 +5,7 @@ use crate::store_utils::*;
use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::store::memory::*;
use pyo3::basic::CompareOp;
use pyo3::exceptions::{NotImplementedError, ValueError};
use pyo3::exceptions::{PyNotImplementedError, PyValueError};
use pyo3::prelude::{
pyclass, pymethods, pyproto, Py, PyAny, PyCell, PyObject, PyRef, PyRefMut, PyResult, Python,
ToPyObject,
@ -257,7 +257,7 @@ impl PyMemoryStore {
.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(ValueError::py_err(
return Err(PyValueError::new_err(
"The target graph name parameter is not available for dataset formats",
));
}
@ -265,7 +265,7 @@ impl PyMemoryStore {
.load_dataset(input, dataset_format, base_iri)
.map_err(map_io_err)
} else {
Err(ValueError::py_err(format!(
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
@ -325,7 +325,7 @@ impl PyMemoryStore {
.map_err(map_io_err)
} else if let Some(dataset_format) = DatasetFormat::from_media_type(mime_type) {
if from_graph_name.is_some() {
return Err(ValueError::py_err(
return Err(PyValueError::new_err(
"The target graph name parameter is not available for dataset formats",
));
}
@ -333,7 +333,7 @@ impl PyMemoryStore {
.dump_dataset(output, dataset_format)
.map_err(map_io_err)
} else {
Err(ValueError::py_err(format!(
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
@ -352,7 +352,9 @@ impl PyObjectProtocol for PyMemoryStore {
match op {
CompareOp::Eq => Ok(self == other),
CompareOp::Ne => Ok(self != other),
_ => Err(NotImplementedError::py_err("Ordering is not implemented")),
_ => Err(PyNotImplementedError::new_err(
"Ordering is not implemented",
)),
}
}

@ -1,7 +1,7 @@
use oxigraph::model::*;
use oxigraph::sparql::Variable;
use pyo3::basic::CompareOp;
use pyo3::exceptions::{IndexError, NotImplementedError, TypeError, ValueError};
use pyo3::exceptions::{PyIndexError, PyNotImplementedError, PyTypeError, PyValueError};
use pyo3::prelude::*;
use pyo3::{PyIterProtocol, PyMappingProtocol, PyObjectProtocol, PyTypeInfo};
use std::collections::hash_map::DefaultHasher;
@ -62,7 +62,7 @@ impl PyNamedNode {
#[new]
fn new(value: String) -> PyResult<Self> {
Ok(NamedNode::new(value)
.map_err(|e| ValueError::py_err(e.to_string()))?
.map_err(|e| PyValueError::new_err(e.to_string()))?
.into())
}
@ -102,7 +102,7 @@ impl PyObjectProtocol for PyNamedNode {
{
eq_compare_other_type(op)
} else {
Err(TypeError::py_err(
Err(PyTypeError::new_err(
"NamedNode could only be compared with RDF terms",
))
}
@ -161,7 +161,7 @@ impl PyBlankNode {
#[new]
fn new(value: Option<String>) -> PyResult<Self> {
Ok(if let Some(value) = value {
BlankNode::new(value).map_err(|e| ValueError::py_err(e.to_string()))?
BlankNode::new(value).map_err(|e| PyValueError::new_err(e.to_string()))?
} else {
BlankNode::default()
}
@ -204,7 +204,7 @@ impl PyObjectProtocol for PyBlankNode {
{
eq_compare_other_type(op)
} else {
Err(TypeError::py_err(
Err(PyTypeError::new_err(
"BlankNode could only be compared with RDF terms",
))
}
@ -266,13 +266,13 @@ impl PyLiteral {
Ok(if let Some(language) = language {
if let Some(datatype) = datatype {
if datatype.value() != "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" {
return Err(ValueError::py_err(
return Err(PyValueError::new_err(
"The literals with a language tag must use the rdf:langString datatype",
));
}
}
Literal::new_language_tagged_literal(value, language)
.map_err(|e| ValueError::py_err(e.to_string()))?
.map_err(|e| PyValueError::new_err(e.to_string()))?
} else if let Some(datatype) = datatype {
Literal::new_typed_literal(value, datatype)
} else {
@ -343,7 +343,7 @@ impl PyObjectProtocol for PyLiteral {
{
eq_compare_other_type(op)
} else {
Err(TypeError::py_err(
Err(PyTypeError::new_err(
"Literal could only be compared with RDF terms",
))
}
@ -397,13 +397,45 @@ impl PyObjectProtocol for PyDefaultGraph {
{
eq_compare_other_type(op)
} else {
Err(TypeError::py_err(
Err(PyTypeError::new_err(
"DefaultGraph could only be compared with RDF terms",
))
}
}
}
#[derive(FromPyObject)]
pub enum PyNamedOrBlankNode {
NamedNode(PyNamedNode),
BlankNode(PyBlankNode),
}
impl From<PyNamedOrBlankNode> for NamedOrBlankNode {
fn from(node: PyNamedOrBlankNode) -> Self {
match node {
PyNamedOrBlankNode::NamedNode(node) => node.into(),
PyNamedOrBlankNode::BlankNode(node) => node.into(),
}
}
}
#[derive(FromPyObject)]
enum PyTerm {
NamedNode(PyNamedNode),
BlankNode(PyBlankNode),
Literal(PyLiteral),
}
impl From<PyTerm> for Term {
fn from(term: PyTerm) -> Self {
match term {
PyTerm::NamedNode(node) => node.into(),
PyTerm::BlankNode(node) => node.into(),
PyTerm::Literal(literal) => literal.into(),
}
}
}
/// An RDF `triple <https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple>`_
///
/// :param subject: the triple subject
@ -449,13 +481,8 @@ impl<'a> From<&'a PyTriple> for TripleRef<'a> {
#[pymethods]
impl PyTriple {
#[new]
fn new(subject: &PyAny, predicate: PyNamedNode, object: &PyAny) -> PyResult<Self> {
Ok(Triple::new(
&PyNamedOrBlankNodeRef::try_from(subject)?,
predicate,
&PyTermRef::try_from(object)?,
)
.into())
fn new(subject: PyNamedOrBlankNode, predicate: PyNamedNode, object: PyTerm) -> Self {
Triple::new(subject, predicate, object).into()
}
/// :return: the triple subject
@ -531,7 +558,7 @@ impl PyMappingProtocol<'p> for PyTriple {
)),
1 => Ok(PyNamedNode::from(self.inner.predicate.clone()).into_py(gil.python())),
2 => Ok(term_to_python(gil.python(), self.inner.object.clone())),
_ => Err(IndexError::py_err("A triple has only 3 elements")),
_ => Err(PyIndexError::new_err("A triple has only 3 elements")),
}
}
}
@ -550,6 +577,22 @@ impl PyIterProtocol for PyTriple {
}
}
#[derive(FromPyObject)]
pub enum PyGraphName {
NamedNode(PyNamedNode),
BlankNode(PyBlankNode),
DefaultGraph(PyDefaultGraph),
}
impl From<PyGraphName> for GraphName {
fn from(graph_name: PyGraphName) -> Self {
match graph_name {
PyGraphName::NamedNode(node) => node.into(),
PyGraphName::BlankNode(node) => node.into(),
PyGraphName::DefaultGraph(default_graph) => default_graph.into(),
}
}
}
/// 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>`_
///
@ -602,22 +645,18 @@ impl<'a> From<&'a PyQuad> for QuadRef<'a> {
impl PyQuad {
#[new]
fn new(
subject: &PyAny,
subject: PyNamedOrBlankNode,
predicate: PyNamedNode,
object: &PyAny,
graph_name: Option<&PyAny>,
) -> PyResult<Self> {
Ok(Quad::new(
&PyNamedOrBlankNodeRef::try_from(subject)?,
object: PyTerm,
graph_name: Option<PyGraphName>,
) -> Self {
Quad::new(
subject,
predicate,
&PyTermRef::try_from(object)?,
&if let Some(graph_name) = graph_name {
PyGraphNameRef::try_from(graph_name)?
} else {
PyGraphNameRef::DefaultGraph
},
object,
graph_name.unwrap_or_else(|| PyGraphName::DefaultGraph(PyDefaultGraph {})),
)
.into())
.into()
}
/// :return: the quad subject
@ -719,7 +758,7 @@ impl PyMappingProtocol<'p> for PyQuad {
gil.python(),
self.inner.graph_name.clone(),
)),
_ => Err(IndexError::py_err("A quad has only 4 elements")),
_ => Err(PyIndexError::new_err("A quad has only 4 elements")),
}
}
}
@ -783,7 +822,7 @@ impl PyVariable {
#[new]
fn new(value: String) -> PyResult<Self> {
Ok(Variable::new(value)
.map_err(|e| ValueError::py_err(e.to_string()))?
.map_err(|e| PyValueError::new_err(e.to_string()))?
.into())
}
@ -832,7 +871,7 @@ impl<'a> TryFrom<&'a PyAny> for PyNamedNodeRef<'a> {
if let Ok(node) = value.downcast::<PyCell<PyNamedNode>>() {
Ok(Self(node.borrow()))
} else {
Err(TypeError::py_err(format!(
Err(PyTypeError::new_err(format!(
"{} is not an RDF named node",
value.get_type().name(),
)))
@ -854,12 +893,6 @@ impl<'a> From<&'a PyNamedOrBlankNodeRef<'a>> for NamedOrBlankNodeRef<'a> {
}
}
impl<'a> From<&'a PyNamedOrBlankNodeRef<'a>> for NamedOrBlankNode {
fn from(value: &'a PyNamedOrBlankNodeRef<'a>) -> Self {
NamedOrBlankNodeRef::from(value).into()
}
}
impl<'a> TryFrom<&'a PyAny> for PyNamedOrBlankNodeRef<'a> {
type Error = PyErr;
@ -869,7 +902,7 @@ impl<'a> TryFrom<&'a PyAny> for PyNamedOrBlankNodeRef<'a> {
} else if let Ok(node) = value.downcast::<PyCell<PyBlankNode>>() {
Ok(Self::BlankNode(node.borrow()))
} else {
Err(TypeError::py_err(format!(
Err(PyTypeError::new_err(format!(
"{} is not an RDF named or blank node",
value.get_type().name(),
)))
@ -917,7 +950,7 @@ impl<'a> TryFrom<&'a PyAny> for PyTermRef<'a> {
} else if let Ok(node) = value.downcast::<PyCell<PyLiteral>>() {
Ok(Self::Literal(node.borrow()))
} else {
Err(TypeError::py_err(format!(
Err(PyTypeError::new_err(format!(
"{} is not an RDF term",
value.get_type().name(),
)))
@ -966,7 +999,7 @@ impl<'a> TryFrom<&'a PyAny> for PyGraphNameRef<'a> {
} else if value.downcast::<PyCell<PyDefaultGraph>>().is_ok() {
Ok(Self::DefaultGraph)
} else {
Err(TypeError::py_err(format!(
Err(PyTypeError::new_err(format!(
"{} is not an RDF graph name",
value.get_type().name(),
)))
@ -986,7 +1019,9 @@ fn eq_compare<T: Eq>(a: &T, b: &T, op: CompareOp) -> PyResult<bool> {
match op {
CompareOp::Eq => Ok(a == b),
CompareOp::Ne => Ok(a != b),
_ => Err(NotImplementedError::py_err("Ordering is not implemented")),
_ => Err(PyNotImplementedError::new_err(
"Ordering is not implemented",
)),
}
}
@ -994,7 +1029,9 @@ fn eq_compare_other_type(op: CompareOp) -> PyResult<bool> {
match op {
CompareOp::Eq => Ok(false),
CompareOp::Ne => Ok(true),
_ => Err(NotImplementedError::py_err("Ordering is not implemented")),
_ => Err(PyNotImplementedError::new_err(
"Ordering is not implemented",
)),
}
}
@ -1056,7 +1093,7 @@ fn graph_name_repr(term: GraphNameRef<'_>, buffer: &mut String) {
}
}
#[pyclass(unsendable)]
#[pyclass]
pub struct TripleComponentsIter {
inner: IntoIter<Term>,
}
@ -1072,7 +1109,7 @@ impl PyIterProtocol for TripleComponentsIter {
}
}
#[pyclass(unsendable)]
#[pyclass]
pub struct QuadComponentsIter {
inner: IntoIter<Option<Term>>,
}

@ -4,7 +4,7 @@ use crate::sparql::*;
use crate::store_utils::*;
use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::store::sled::*;
use pyo3::exceptions::ValueError;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::{
pyclass, pymethods, pyproto, Py, PyAny, PyObject, PyRef, PyRefMut, PyResult, Python, ToPyObject,
};
@ -273,7 +273,7 @@ impl PySledStore {
.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(ValueError::py_err(
return Err(PyValueError::new_err(
"The target graph name parameter is not available for dataset formats",
));
}
@ -281,7 +281,7 @@ impl PySledStore {
.load_dataset(input, dataset_format, base_iri)
.map_err(map_io_err)
} else {
Err(ValueError::py_err(format!(
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
@ -342,7 +342,7 @@ impl PySledStore {
.map_err(map_io_err)
} else if let Some(dataset_format) = DatasetFormat::from_media_type(mime_type) {
if from_graph_name.is_some() {
return Err(ValueError::py_err(
return Err(PyValueError::new_err(
"The target graph name parameter is not available for dataset formats",
));
}
@ -350,7 +350,7 @@ impl PySledStore {
.dump_dataset(output, dataset_format)
.map_err(map_io_err)
} else {
Err(ValueError::py_err(format!(
Err(PyValueError::new_err(format!(
"Not supported MIME type: {}",
mime_type
)))
@ -389,7 +389,7 @@ impl PyIterProtocol for PySledStore {
}
}
#[pyclass(unsendable)]
#[pyclass]
pub struct QuadIter {
inner: SledQuadIter,
}

@ -2,13 +2,12 @@ use crate::model::*;
use crate::store_utils::*;
use oxigraph::model::Term;
use oxigraph::sparql::*;
use pyo3::exceptions::{RuntimeError, SyntaxError, TypeError, ValueError};
use pyo3::exceptions::{PyRuntimeError, PySyntaxError, PyTypeError, PyValueError};
use pyo3::prelude::{
pyclass, pymethods, pyproto, FromPyObject, IntoPy, Py, PyAny, PyCell, PyErr, PyObject, PyRef,
PyRefMut, PyResult, Python,
};
use pyo3::{PyIterProtocol, PyMappingProtocol, PyNativeType, PyObjectProtocol};
use std::convert::TryFrom;
use std::vec::IntoIter;
pub fn build_query_options(
@ -24,17 +23,17 @@ pub fn build_query_options(
if let Some(default_graph) = default_graph {
if let Ok(default_graphs) = default_graph.iter() {
if default_graph.is_empty()? {
return Err(ValueError::py_err(
return Err(PyValueError::new_err(
"The query() method default_graph argument cannot be empty list",
));
}
for default_graph in default_graphs {
options = options.with_default_graph(&PyGraphNameRef::try_from(default_graph?)?);
options = options.with_default_graph(default_graph?.extract::<PyGraphName>()?);
}
} else if let Ok(default_graph) = PyGraphNameRef::try_from(default_graph) {
options = options.with_default_graph(&default_graph);
} else if let Ok(default_graph) = default_graph.extract::<PyGraphName>() {
options = options.with_default_graph(default_graph);
} else {
return Err(ValueError::py_err(
return Err(PyValueError::new_err(
format!("The query() method default_graph argument should be a NamedNode, a BlankNode, the DefaultGraph or a not empty list of them. {} found", default_graph.get_type()
)));
}
@ -42,12 +41,12 @@ pub fn build_query_options(
if let Some(named_graphs) = named_graphs {
if named_graphs.is_empty()? {
return Err(ValueError::py_err(
return Err(PyValueError::new_err(
"The query() method named_graphs argument cannot be empty",
));
}
for named_graph in named_graphs.iter()? {
options = options.with_named_graph(&PyNamedOrBlankNodeRef::try_from(named_graph?)?);
options = options.with_named_graph(named_graph?.extract::<PyNamedOrBlankNode>()?);
}
}
@ -126,7 +125,7 @@ impl PyMappingProtocol for PyQuerySolution {
.get(<&Variable>::from(key))
.map(|term| term_to_python(input.py(), term.clone())))
} else {
Err(TypeError::py_err(format!(
Err(PyTypeError::new_err(format!(
"{} is not an integer of a string",
input.get_type().name(),
)))
@ -148,7 +147,7 @@ impl PyIterProtocol for PyQuerySolution {
}
}
#[pyclass(unsendable)]
#[pyclass]
pub struct SolutionValueIter {
inner: IntoIter<Option<Term>>,
}
@ -240,9 +239,9 @@ impl PyIterProtocol for PyQueryTriples {
pub fn map_evaluation_error(error: EvaluationError) -> PyErr {
match error {
EvaluationError::Parsing(error) => SyntaxError::py_err(error.to_string()),
EvaluationError::Parsing(error) => PySyntaxError::new_err(error.to_string()),
EvaluationError::Io(error) => map_io_err(error),
EvaluationError::Query(error) => ValueError::py_err(error.to_string()),
_ => RuntimeError::py_err(error.to_string()),
EvaluationError::Query(error) => PyValueError::new_err(error.to_string()),
_ => PyRuntimeError::new_err(error.to_string()),
}
}

@ -1,5 +1,5 @@
use crate::model::*;
use pyo3::exceptions::{IOError, SyntaxError, ValueError};
use pyo3::exceptions::{PyIOError, PySyntaxError, PyValueError};
use pyo3::{PyAny, PyErr, PyResult};
use std::convert::TryInto;
use std::io;
@ -45,10 +45,10 @@ pub fn extract_quads_pattern<'a>(
pub fn map_io_err(error: io::Error) -> PyErr {
match error.kind() {
io::ErrorKind::InvalidInput => ValueError::py_err(error.to_string()),
io::ErrorKind::InvalidInput => PyValueError::new_err(error.to_string()),
io::ErrorKind::InvalidData | io::ErrorKind::UnexpectedEof => {
SyntaxError::py_err(error.to_string())
PySyntaxError::new_err(error.to_string())
}
_ => IOError::py_err(error.to_string()),
_ => PyIOError::new_err(error.to_string()),
}
}

Loading…
Cancel
Save