From 4a798ed3eac99ec230a159e12a15289c665350ab Mon Sep 17 00:00:00 2001 From: Tpt Date: Thu, 17 Aug 2023 18:47:16 +0200 Subject: [PATCH] Python: use OSError instead of IOError to map io::Error --- python/src/io.rs | 13 +++++++----- python/src/store.rs | 50 ++++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/python/src/io.rs b/python/src/io.rs index f6661474..97bee867 100644 --- a/python/src/io.rs +++ b/python/src/io.rs @@ -3,7 +3,7 @@ use crate::model::{PyQuad, PyTriple}; use oxigraph::io::{FromReadQuadReader, ParseError, RdfFormat, RdfParser, RdfSerializer}; use oxigraph::model::QuadRef; -use pyo3::exceptions::{PyIOError, PySyntaxError, PyValueError}; +use pyo3::exceptions::{PySyntaxError, PyValueError}; use pyo3::prelude::*; use pyo3::types::PyBytes; use pyo3::{intern, wrap_pyfunction}; @@ -272,14 +272,17 @@ impl Write for PyIo { fn flush(&mut self) -> io::Result<()> { Python::with_gil(|py| { - self.0.as_ref(py).call_method0(intern!(py, "flush"))?; + self.0 + .as_ref(py) + .call_method0(intern!(py, "flush")) + .map_err(to_io_err)?; Ok(()) }) } } -fn to_io_err(error: impl Into) -> io::Error { - io::Error::new(io::ErrorKind::Other, error.into()) +fn to_io_err(error: PyErr) -> io::Error { + io::Error::new(io::ErrorKind::Other, error) } pub fn map_io_err(error: io::Error) -> PyErr { @@ -289,7 +292,7 @@ pub fn map_io_err(error: io::Error) -> PyErr { { *error.into_inner().unwrap().downcast().unwrap() } else { - PyIOError::new_err(error.to_string()) + error.into() } } diff --git a/python/src/store.rs b/python/src/store.rs index cfb10a3a..d689c997 100644 --- a/python/src/store.rs +++ b/python/src/store.rs @@ -7,7 +7,7 @@ use oxigraph::io::RdfFormat; use oxigraph::model::{GraphName, GraphNameRef}; use oxigraph::sparql::Update; use oxigraph::store::{self, LoaderError, SerializerError, StorageError, Store}; -use pyo3::exceptions::{PyIOError, PyRuntimeError, PyValueError}; +use pyo3::exceptions::{PyRuntimeError, PyValueError}; use pyo3::prelude::*; use std::path::PathBuf; @@ -28,7 +28,7 @@ use std::path::PathBuf; /// If no directory is provided a temporary one is created and removed when the Python garbage collector removes the store. /// In this case, the store data are kept in memory and never written on disk. /// :type path: str or pathlib.Path or None, optional -/// :raises IOError: if the target directory contains invalid data or could not be accessed. +/// :raises OSError: 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: /// @@ -68,7 +68,7 @@ impl PyStore { /// :type path: str /// :return: the opened store. /// :rtype: Store - /// :raises IOError: if the target directory contains invalid data or could not be accessed. + /// :raises OSError: if the target directory contains invalid data or could not be accessed. #[staticmethod] fn read_only(path: &str, py: Python<'_>) -> PyResult { py.allow_threads(|| { @@ -92,7 +92,7 @@ impl PyStore { /// :type secondary_path: str or None, optional /// :return: the opened store. /// :rtype: Store - /// :raises IOError: if the target directories contain invalid data or could not be accessed. + /// :raises OSError: if the target directories contain invalid data or could not be accessed. #[staticmethod] #[pyo3(signature = (primary_path, secondary_path = None))] fn secondary( @@ -117,7 +117,7 @@ impl PyStore { /// :param quad: the quad to add. /// :type quad: Quad /// :rtype: None - /// :raises IOError: if an I/O error happens during the quad insertion. + /// :raises OSError: if an 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'))) @@ -138,7 +138,7 @@ impl PyStore { /// :param quads: the quads to add. /// :type quads: iterable(Quad) /// :rtype: None - /// :raises IOError: if an I/O error happens during the quad insertion. + /// :raises OSError: if an error happens during the quad insertion. /// /// >>> store = Store() /// >>> store.extend([Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))]) @@ -163,7 +163,7 @@ impl PyStore { /// :param quads: the quads to add. /// :type quads: iterable(Quad) /// :rtype: None - /// :raises IOError: if an I/O error happens during the quad insertion. + /// :raises OSError: if an error happens during the quad insertion. /// /// >>> store = Store() /// >>> store.bulk_extend([Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))]) @@ -183,7 +183,7 @@ impl PyStore { /// :param quad: the quad to remove. /// :type quad: Quad /// :rtype: None - /// :raises IOError: if an I/O error happens during the quad removal. + /// :raises OSError: if an 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')) @@ -210,7 +210,7 @@ impl PyStore { /// :type graph_name: NamedNode or BlankNode or DefaultGraph or None, optional /// :return: an iterator of the quads matching the pattern. /// :rtype: iterator(Quad) - /// :raises IOError: if an I/O error happens during the quads lookup. + /// :raises OSError: if an 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'))) @@ -251,7 +251,7 @@ impl PyStore { /// :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 OSError: if an error happens while reading the store. /// /// ``SELECT`` query: /// @@ -305,7 +305,7 @@ impl PyStore { /// :type base_iri: str or None, optional /// :rtype: None /// :raises SyntaxError: if the provided update is invalid. - /// :raises IOError: if an I/O error happens while reading the store. + /// :raises OSError: if an error happens while reading the store. /// /// ``INSERT DATA`` update: /// @@ -368,7 +368,7 @@ impl PyStore { /// :rtype: None /// :raises ValueError: if the MIME type is not supported. /// :raises SyntaxError: if the provided data is invalid. - /// :raises IOError: if an I/O error happens during a quad insertion. + /// :raises OSError: if an error happens during a quad insertion. /// /// >>> store = Store() /// >>> store.load(io.BytesIO(b'

"1" .'), "text/turtle", base_iri="http://example.com/", to_graph=NamedNode("http://example.com/g")) @@ -439,7 +439,7 @@ impl PyStore { /// :rtype: None /// :raises ValueError: if the MIME type is not supported. /// :raises SyntaxError: if the provided data is invalid. - /// :raises IOError: if an I/O error happens during a quad insertion. + /// :raises OSError: if an error happens during a quad insertion. /// /// >>> store = Store() /// >>> store.bulk_load(io.BytesIO(b'

"1" .'), "text/turtle", base_iri="http://example.com/", to_graph=NamedNode("http://example.com/g")) @@ -505,7 +505,7 @@ impl PyStore { /// :type from_graph: NamedNode or BlankNode or DefaultGraph or None, optional /// :rtype: None /// :raises ValueError: if the MIME type is not supported or the `from_graph` parameter is not given with a syntax not supporting named graphs. - /// :raises IOError: if an I/O error happens during a quad lookup + /// :raises OSError: if an error happens during a quad lookup /// /// >>> store = Store() /// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))) @@ -550,7 +550,7 @@ impl PyStore { /// /// :return: an iterator of the store graph names. /// :rtype: iterator(NamedNode or BlankNode) - /// :raises IOError: if an I/O error happens during the named graphs lookup. + /// :raises OSError: if an 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'))) @@ -567,7 +567,7 @@ impl PyStore { /// :param graph_name: the name of the named graph. /// :type graph_name: NamedNode or BlankNode or DefaultGraph /// :rtype: bool - /// :raises IOError: if an I/O error happens during the named graph lookup. + /// :raises OSError: if an error happens during the named graph lookup. /// /// >>> store = Store() /// >>> store.add_graph(NamedNode('http://example.com/g')) @@ -588,7 +588,7 @@ impl PyStore { /// :param graph_name: the name of the name graph to add. /// :type graph_name: NamedNode or BlankNode or DefaultGraph /// :rtype: None - /// :raises IOError: if an I/O error happens during the named graph insertion. + /// :raises OSError: if an error happens during the named graph insertion. /// /// >>> store = Store() /// >>> store.add_graph(NamedNode('http://example.com/g')) @@ -615,7 +615,7 @@ impl PyStore { /// :param graph_name: the name of the name graph to clear. /// :type graph_name: NamedNode or BlankNode or DefaultGraph /// :rtype: None - /// :raises IOError: if an I/O error happens during the operation. + /// :raises OSError: if an error happens during the operation. /// /// >>> store = Store() /// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))) @@ -640,7 +640,7 @@ impl PyStore { /// :param graph_name: the name of the name graph to remove. /// :type graph_name: NamedNode or BlankNode or DefaultGraph /// :rtype: None - /// :raises IOError: if an I/O error happens during the named graph removal. + /// :raises OSError: if an error happens during the named graph removal. /// /// >>> store = Store() /// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))) @@ -666,7 +666,7 @@ impl PyStore { /// Clears the store by removing all its contents. /// /// :rtype: None - /// :raises IOError: if an I/O error happens during the operation. + /// :raises OSError: if an error happens during the operation. /// /// >>> store = Store() /// >>> store.add(Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))) @@ -684,7 +684,7 @@ impl PyStore { /// Flushes are automatically done using background threads but might lag a little bit. /// /// :rtype: None - /// :raises IOError: if an I/O error happens during the flush. + /// :raises OSError: if an error happens during the flush. fn flush(&self, py: Python<'_>) -> PyResult<()> { py.allow_threads(|| self.inner.flush().map_err(map_storage_error)) } @@ -694,7 +694,7 @@ impl PyStore { /// Useful to call after a batch upload or another similar operation. /// /// :rtype: None - /// :raises IOError: if an I/O error happens during the optimization. + /// :raises OSError: if an error happens during the optimization. fn optimize(&self, py: Python<'_>) -> PyResult<()> { py.allow_threads(|| self.inner.optimize().map_err(map_storage_error)) } @@ -719,7 +719,7 @@ impl PyStore { /// :param target_directory: the directory name to save the database to. /// :type target_directory: str /// :rtype: None - /// :raises IOError: if an I/O error happens during the backup. + /// :raises OSError: if an error happens during the backup. fn backup(&self, target_directory: &str, py: Python<'_>) -> PyResult<()> { py.allow_threads(|| { self.inner @@ -830,7 +830,7 @@ pub fn extract_quads_pattern<'a>( pub fn map_storage_error(error: StorageError) -> PyErr { match error { - StorageError::Io(error) => PyIOError::new_err(error.to_string()), + StorageError::Io(error) => error.into(), _ => PyRuntimeError::new_err(error.to_string()), } } @@ -846,7 +846,7 @@ pub fn map_loader_error(error: LoaderError) -> PyErr { pub fn map_serializer_error(error: SerializerError) -> PyErr { match error { SerializerError::Storage(error) => map_storage_error(error), - SerializerError::Io(error) => PyIOError::new_err(error.to_string()), + SerializerError::Io(error) => error.into(), SerializerError::DatasetFormatExpected(_) => PyValueError::new_err(error.to_string()), } }