From 60f601d6d3820ba0b1fa603d5a16a05ea64a05f1 Mon Sep 17 00:00:00 2001 From: Tpt Date: Mon, 4 Jan 2021 22:20:40 +0100 Subject: [PATCH] Python: Implements IntoPy where meaningful --- python/src/model.rs | 137 ++++++++++++++++++++++++++----------------- python/src/sparql.rs | 22 +++---- 2 files changed, 89 insertions(+), 70 deletions(-) diff --git a/python/src/model.rs b/python/src/model.rs index 18d94522..f30e67d0 100644 --- a/python/src/model.rs +++ b/python/src/model.rs @@ -419,8 +419,26 @@ impl From for NamedOrBlankNode { } } +impl From for PyNamedOrBlankNode { + fn from(node: NamedOrBlankNode) -> Self { + match node { + NamedOrBlankNode::NamedNode(node) => PyNamedOrBlankNode::NamedNode(node.into()), + NamedOrBlankNode::BlankNode(node) => PyNamedOrBlankNode::BlankNode(node.into()), + } + } +} + +impl IntoPy for PyNamedOrBlankNode { + fn into_py(self, py: Python<'_>) -> PyObject { + match self { + PyNamedOrBlankNode::NamedNode(node) => node.into_py(py), + PyNamedOrBlankNode::BlankNode(node) => node.into_py(py), + } + } +} + #[derive(FromPyObject)] -enum PyTerm { +pub enum PyTerm { NamedNode(PyNamedNode), BlankNode(PyBlankNode), Literal(PyLiteral), @@ -436,6 +454,26 @@ impl From for Term { } } +impl From for PyTerm { + fn from(term: Term) -> Self { + match term { + Term::NamedNode(node) => PyTerm::NamedNode(node.into()), + Term::BlankNode(node) => PyTerm::BlankNode(node.into()), + Term::Literal(literal) => PyTerm::Literal(literal.into()), + } + } +} + +impl IntoPy for PyTerm { + fn into_py(self, py: Python<'_>) -> PyObject { + match self { + PyTerm::NamedNode(node) => node.into_py(py), + PyTerm::BlankNode(node) => node.into_py(py), + PyTerm::Literal(literal) => literal.into_py(py), + } + } +} + /// An RDF `triple `_ /// /// :param subject: the triple subject @@ -491,8 +529,8 @@ impl PyTriple { /// >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).subject /// #[getter] - fn subject(&self, py: Python<'_>) -> PyObject { - named_or_blank_node_to_python(py, self.inner.subject.clone()) + fn subject(&self) -> PyNamedOrBlankNode { + self.inner.subject.clone().into() } /// :return: the triple predicate @@ -511,8 +549,8 @@ impl PyTriple { /// >>> Triple(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1')).object /// > #[getter] - fn object(&self, py: Python<'_>) -> PyObject { - term_to_python(py, self.inner.object.clone()) + fn object(&self) -> PyTerm { + self.inner.object.clone().into() } } @@ -549,15 +587,11 @@ impl PyMappingProtocol<'p> for PyTriple { 3 } - fn __getitem__(&self, input: usize) -> PyResult { - let gil = Python::acquire_gil(); + fn __getitem__(&self, input: usize) -> PyResult { match input { - 0 => Ok(named_or_blank_node_to_python( - gil.python(), - self.inner.subject.clone(), - )), - 1 => Ok(PyNamedNode::from(self.inner.predicate.clone()).into_py(gil.python())), - 2 => Ok(term_to_python(gil.python(), self.inner.object.clone())), + 0 => Ok(Term::from(self.inner.subject.clone()).into()), + 1 => Ok(Term::from(self.inner.predicate.clone()).into()), + 2 => Ok(self.inner.object.clone().into()), _ => Err(PyIndexError::new_err("A triple has only 3 elements")), } } @@ -593,6 +627,27 @@ impl From for GraphName { } } } + +impl From for PyGraphName { + fn from(graph_name: GraphName) -> Self { + match graph_name { + GraphName::NamedNode(node) => PyGraphName::NamedNode(node.into()), + GraphName::BlankNode(node) => PyGraphName::BlankNode(node.into()), + GraphName::DefaultGraph => PyGraphName::DefaultGraph(PyDefaultGraph::new()), + } + } +} + +impl IntoPy for PyGraphName { + fn into_py(self, py: Python<'_>) -> PyObject { + match self { + PyGraphName::NamedNode(node) => node.into_py(py), + PyGraphName::BlankNode(node) => node.into_py(py), + PyGraphName::DefaultGraph(node) => node.into_py(py), + } + } +} + /// An RDF `triple `_ /// in a `RDF dataset `_ /// @@ -665,8 +720,8 @@ impl PyQuad { /// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).subject /// #[getter] - fn subject(&self, py: Python<'_>) -> PyObject { - named_or_blank_node_to_python(py, self.inner.subject.clone()) + fn subject(&self) -> PyNamedOrBlankNode { + self.inner.subject.clone().into() } /// :return: the quad predicate @@ -685,8 +740,8 @@ impl PyQuad { /// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).object /// > #[getter] - fn object(&self, py: Python<'_>) -> PyObject { - term_to_python(py, self.inner.object.clone()) + fn object(&self) -> PyTerm { + self.inner.object.clone().into() } /// :return: the quad graph name @@ -695,8 +750,8 @@ impl PyQuad { /// >>> Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g')).graph_name /// #[getter] - fn graph_name(&self, py: Python<'_>) -> PyObject { - graph_name_to_python(py, self.inner.graph_name.clone()) + fn graph_name(&self) -> PyGraphName { + self.inner.graph_name.clone().into() } /// :return: the quad underlying triple @@ -747,17 +802,12 @@ impl PyMappingProtocol<'p> for PyQuad { fn __getitem__(&self, input: usize) -> PyResult { let gil = Python::acquire_gil(); + let py = gil.python(); match input { - 0 => Ok(named_or_blank_node_to_python( - gil.python(), - self.inner.subject.clone(), - )), - 1 => Ok(PyNamedNode::from(self.inner.predicate.clone()).into_py(gil.python())), - 2 => Ok(term_to_python(gil.python(), self.inner.object.clone())), - 3 => Ok(graph_name_to_python( - gil.python(), - self.inner.graph_name.clone(), - )), + 0 => Ok(PyNamedOrBlankNode::from(self.inner.subject.clone()).into_py(py)), + 1 => Ok(PyNamedNode::from(self.inner.predicate.clone()).into_py(py)), + 2 => Ok(PyTerm::from(self.inner.object.clone()).into_py(py)), + 3 => Ok(PyGraphName::from(self.inner.graph_name.clone()).into_py(py)), _ => Err(PyIndexError::new_err("A quad has only 4 elements")), } } @@ -910,13 +960,6 @@ impl<'a> TryFrom<&'a PyAny> for PyNamedOrBlankNodeRef<'a> { } } -pub fn named_or_blank_node_to_python(py: Python<'_>, node: NamedOrBlankNode) -> PyObject { - match node { - NamedOrBlankNode::NamedNode(node) => PyNamedNode::from(node).into_py(py), - NamedOrBlankNode::BlankNode(node) => PyBlankNode::from(node).into_py(py), - } -} - pub enum PyTermRef<'a> { NamedNode(PyRef<'a, PyNamedNode>), BlankNode(PyRef<'a, PyBlankNode>), @@ -958,14 +1001,6 @@ impl<'a> TryFrom<&'a PyAny> for PyTermRef<'a> { } } -pub fn term_to_python(py: Python<'_>, term: Term) -> PyObject { - match term { - Term::NamedNode(node) => PyNamedNode::from(node).into_py(py), - Term::BlankNode(node) => PyBlankNode::from(node).into_py(py), - Term::Literal(literal) => PyLiteral::from(literal).into_py(py), - } -} - pub enum PyGraphNameRef<'a> { NamedNode(PyRef<'a, PyNamedNode>), BlankNode(PyRef<'a, PyBlankNode>), @@ -1007,14 +1042,6 @@ impl<'a> TryFrom<&'a PyAny> for PyGraphNameRef<'a> { } } -pub fn graph_name_to_python(py: Python<'_>, name: GraphName) -> PyObject { - match name { - GraphName::NamedNode(node) => PyNamedNode::from(node).into_py(py), - GraphName::BlankNode(node) => PyBlankNode::from(node).into_py(py), - GraphName::DefaultGraph => PyDefaultGraph::new().into_py(py), - } -} - fn eq_compare(a: &T, b: &T, op: CompareOp) -> PyResult { match op { CompareOp::Eq => Ok(a == b), @@ -1104,8 +1131,8 @@ impl PyIterProtocol for TripleComponentsIter { slf.into() } - fn __next__(mut slf: PyRefMut) -> Option { - slf.inner.next().map(move |t| term_to_python(slf.py(), t)) + fn __next__(mut slf: PyRefMut) -> Option { + slf.inner.next().map(PyTerm::from) } } @@ -1123,7 +1150,7 @@ impl PyIterProtocol for QuadComponentsIter { fn __next__(mut slf: PyRefMut) -> Option { slf.inner.next().map(move |t| { if let Some(t) = t { - term_to_python(slf.py(), t) + PyTerm::from(t).into_py(slf.py()) } else { PyDefaultGraph {}.into_py(slf.py()) } diff --git a/python/src/sparql.rs b/python/src/sparql.rs index 44112667..f3dafd1a 100644 --- a/python/src/sparql.rs +++ b/python/src/sparql.rs @@ -7,7 +7,7 @@ use pyo3::prelude::{ pyclass, pymethods, pyproto, FromPyObject, IntoPy, Py, PyAny, PyCell, PyErr, PyObject, PyRef, PyRefMut, PyResult, Python, }; -use pyo3::{PyIterProtocol, PyMappingProtocol, PyNativeType, PyObjectProtocol}; +use pyo3::{PyIterProtocol, PyMappingProtocol, PyObjectProtocol}; use std::vec::IntoIter; pub fn parse_query( @@ -112,23 +112,17 @@ impl PyMappingProtocol for PyQuerySolution { self.inner.len() } - fn __getitem__(&self, input: &PyAny) -> PyResult> { + fn __getitem__(&self, input: &PyAny) -> PyResult> { if let Ok(key) = usize::extract(input) { - Ok(self - .inner - .get(key) - .map(|term| term_to_python(input.py(), term.clone()))) + Ok(self.inner.get(key).map(|term| PyTerm::from(term.clone()))) } else if let Ok(key) = <&str>::extract(input) { - Ok(self - .inner - .get(key) - .map(|term| term_to_python(input.py(), term.clone()))) + Ok(self.inner.get(key).map(|term| PyTerm::from(term.clone()))) } else if let Ok(key) = input.downcast::>() { let key = &*key.borrow(); Ok(self .inner .get(<&Variable>::from(key)) - .map(|term| term_to_python(input.py(), term.clone()))) + .map(|term| PyTerm::from(term.clone()))) } else { Err(PyTypeError::new_err(format!( "{} is not an integer of a string", @@ -163,10 +157,8 @@ impl PyIterProtocol for SolutionValueIter { slf.into() } - fn __next__(mut slf: PyRefMut) -> Option> { - slf.inner - .next() - .map(|v| v.map(|v| term_to_python(slf.py(), v))) + fn __next__(mut slf: PyRefMut) -> Option> { + slf.inner.next().map(|v| v.map(PyTerm::from)) } }