diff --git a/python/src/io.rs b/python/src/io.rs index a87b7982..86896853 100644 --- a/python/src/io.rs +++ b/python/src/io.rs @@ -3,7 +3,7 @@ use crate::model::{hash, PyQuad, PyTriple}; use oxigraph::io::{FromReadQuadReader, ParseError, RdfFormat, RdfParser, RdfSerializer}; use oxigraph::model::QuadRef; -use pyo3::exceptions::{PySyntaxError, PyValueError}; +use pyo3::exceptions::{PyDeprecationWarning, PySyntaxError, PyValueError}; use pyo3::intern; use pyo3::prelude::*; use pyo3::types::PyBytes; @@ -53,7 +53,7 @@ use std::sync::OnceLock; #[pyo3(signature = (input = None, format = None, *, path = None, base_iri = None, without_named_graphs = false, rename_blank_nodes = false))] pub fn parse( input: Option, - format: Option, + format: Option, path: Option, base_iri: Option<&str>, without_named_graphs: bool, @@ -120,7 +120,7 @@ pub fn parse( pub fn serialize<'a>( input: &PyAny, output: Option, - format: Option, + format: Option, py: Python<'a>, ) -> PyResult> { PyWritable::do_write( @@ -519,9 +519,22 @@ impl Write for PyIo { } } -pub fn lookup_rdf_format(format: Option, path: Option<&Path>) -> PyResult { +pub fn lookup_rdf_format( + format: Option, + path: Option<&Path>, +) -> PyResult { if let Some(format) = format { - return Ok(format.inner); + return match format { + PyRdfFormatInput::Object(format) => Ok(format.inner), + PyRdfFormatInput::MediaType(media_type) => { + deprecation_warning("Using string to specify a RDF format is deprecated, please use a RdfFormat object instead.")?; + RdfFormat::from_media_type(&media_type).ok_or_else(|| { + PyValueError::new_err(format!( + "The media type {media_type} is not supported by pyoxigraph" + )) + }) + } + }; } let Some(path) = path else { return Err(PyValueError::new_err( @@ -538,6 +551,12 @@ pub fn lookup_rdf_format(format: Option, path: Option<&Path>) -> Py .ok_or_else(|| PyValueError::new_err(format!("Not supported RDF format extension: {ext}"))) } +#[derive(FromPyObject)] +pub enum PyRdfFormatInput { + Object(PyRdfFormat), + MediaType(String), +} + pub fn map_parse_error(error: ParseError, file_path: Option) -> PyErr { match error { ParseError::Syntax(error) => { @@ -608,3 +627,7 @@ pub fn python_version() -> (u8, u8) { }) }) } + +pub fn deprecation_warning(message: &str) -> PyResult<()> { + Python::with_gil(|py| PyErr::warn(py, py.get_type::(), message, 0)) +} diff --git a/python/src/sparql.rs b/python/src/sparql.rs index 36506e02..8f6c7498 100644 --- a/python/src/sparql.rs +++ b/python/src/sparql.rs @@ -240,7 +240,7 @@ impl PyQuerySolutions { fn serialize<'a>( &mut self, output: Option, - format: Option, + format: Option, py: Python<'a>, ) -> PyResult> { PyWritable::do_write( @@ -340,7 +340,7 @@ impl PyQueryBoolean { fn serialize<'a>( &mut self, output: Option, - format: Option, + format: Option, py: Python<'a>, ) -> PyResult> { PyWritable::do_write( @@ -418,7 +418,7 @@ impl PyQueryTriples { fn serialize<'a>( &mut self, output: Option, - format: Option, + format: Option, py: Python<'a>, ) -> PyResult> { PyWritable::do_write( @@ -479,7 +479,7 @@ impl PyQueryTriples { #[pyo3(signature = (input = None, format = None, *, path = None))] pub fn parse_query_results( input: Option, - format: Option, + format: Option, path: Option, py: Python<'_>, ) -> PyResult { @@ -650,11 +650,21 @@ impl PyQueryResultsFormat { } pub fn lookup_query_results_format( - format: Option, + format: Option, path: Option<&Path>, ) -> PyResult { if let Some(format) = format { - return Ok(format.inner); + return match format { + PyQueryResultsFormatInput::Object(format) => Ok(format.inner), + PyQueryResultsFormatInput::MediaType(media_type) => { + deprecation_warning("Using a string to specify a query results format is deprecated, please use a QueryResultsFormat object instead.")?; + QueryResultsFormat::from_media_type(&media_type).ok_or_else(|| { + PyValueError::new_err(format!( + "The media type {media_type} is not supported by pyoxigraph" + )) + }) + } + }; } let Some(path) = path else { return Err(PyValueError::new_err( @@ -671,6 +681,12 @@ pub fn lookup_query_results_format( .ok_or_else(|| PyValueError::new_err(format!("Not supported RDF format extension: {ext}"))) } +#[derive(FromPyObject)] +pub enum PyQueryResultsFormatInput { + Object(PyQueryResultsFormat), + MediaType(String), +} + pub fn map_evaluation_error(error: EvaluationError) -> PyErr { match error { EvaluationError::Parsing(error) => PySyntaxError::new_err(error.to_string()), diff --git a/python/src/store.rs b/python/src/store.rs index f9e0b800..910247df 100644 --- a/python/src/store.rs +++ b/python/src/store.rs @@ -1,7 +1,7 @@ #![allow(clippy::needless_option_as_deref)] use crate::io::{ - allow_threads_unsafe, lookup_rdf_format, map_parse_error, PyRdfFormat, PyReadable, + allow_threads_unsafe, lookup_rdf_format, map_parse_error, PyRdfFormatInput, PyReadable, PyReadableInput, PyWritable, PyWritableOutput, }; use crate::model::*; @@ -385,7 +385,7 @@ impl PyStore { fn load( &self, input: Option, - format: Option, + format: Option, path: Option, base_iri: Option<&str>, to_graph: Option<&PyAny>, @@ -452,7 +452,7 @@ impl PyStore { fn bulk_load( &self, input: Option, - format: Option, + format: Option, path: Option, base_iri: Option<&str>, to_graph: Option<&PyAny>, @@ -520,7 +520,7 @@ impl PyStore { fn dump<'a>( &self, output: Option, - format: Option, + format: Option, from_graph: Option<&PyAny>, py: Python<'a>, ) -> PyResult> {