Skip to content

Commit

Permalink
Added query solution methods to rudof
Browse files Browse the repository at this point in the history
  • Loading branch information
labra committed Nov 13, 2024
1 parent 78ee659 commit e9e0be4
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 9 deletions.
21 changes: 21 additions & 0 deletions python/examples/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pyrudof import Rudof, RudofConfig, QuerySolutions

rudof = Rudof(RudofConfig())
rdf = """prefix : <http://example.org/>
:alice a :Person ;
:name "Alice" ;
:knows :bob .
:bob a :Person ;
:name "Robert" .
"""
rudof.read_data_str(rdf)

query = """prefix : <http://example.org/>
select * where {
?x a :Person
}
"""

results = rudof.run_query_str(query)
for result in iter(results):
print(result.show())
8 changes: 4 additions & 4 deletions python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ pub mod pyrudof {

#[pymodule_export]
use super::{
PyDCTAP, PyDCTapFormat, PyRDFFormat, PyReaderMode, PyRudof, PyRudofConfig, PyRudofError,
PyShExFormat, PyShExFormatter, PyShaclFormat, PyShaclValidationMode, PyShapeMapFormat,
PyShapeMapFormatter, PyShapesGraphSource, PyUmlGenerationMode, PyValidationReport,
PyValidationStatus,
PyDCTAP, PyDCTapFormat, PyQuerySolution, PyQuerySolutions, PyRDFFormat, PyReaderMode,
PyRudof, PyRudofConfig, PyRudofError, PyShExFormat, PyShExFormatter, PyShaclFormat,
PyShaclValidationMode, PyShapeMapFormat, PyShapeMapFormatter, PyShapesGraphSource,
PyUmlGenerationMode, PyValidationReport, PyValidationStatus,
};

#[pymodule_init]
Expand Down
79 changes: 74 additions & 5 deletions python/src/pyrudof_lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//! This is a wrapper of the methods provided by `rudof_lib`
//!
use pyo3::{exceptions::PyValueError, pyclass, pymethods, PyErr, PyResult, Python};
use pyo3::{
exceptions::PyValueError, pyclass, pymethods, Py, PyErr, PyRef, PyRefMut, PyResult, Python,
};
use rudof_lib::{
iri, DCTAPFormat, PrefixMap, QueryShapeMap, QuerySolutions, RDFFormat, RdfData, ReaderMode,
ResultShapeMap, Rudof, RudofConfig, RudofError, ShExFormat, ShExFormatter, ShExSchema,
ShaclFormat, ShaclSchema, ShaclValidationMode, ShapeMapFormat, ShapeMapFormatter,
iri, DCTAPFormat, PrefixMap, QueryShapeMap, QuerySolution, QuerySolutions, RDFFormat, RdfData,

Check failure on line 7 in python/src/pyrudof_lib.rs

View workflow job for this annotation

GitHub Actions / Clippy

unresolved import `rudof_lib::QuerySolution`
ReaderMode, ResultShapeMap, Rudof, RudofConfig, RudofError, ShExFormat, ShExFormatter,
ShExSchema, ShaclFormat, ShaclSchema, ShaclValidationMode, ShapeMapFormat, ShapeMapFormatter,
ShapesGraphSource, UmlGenerationMode, ValidationReport, ValidationStatus, DCTAP,
};
use std::{ffi::OsStr, fs::File, io::BufReader, path::Path};
Expand Down Expand Up @@ -123,6 +125,28 @@ impl PyRudof {
shacl_schema.map(|s| PyShaclSchema { inner: s.clone() })
}

/// Run a SPARQL query obtained from a string on the RDF data
#[pyo3(signature = (input))]
pub fn run_query_str(&mut self, input: &str) -> PyResult<PyQuerySolutions> {
let results = self.inner.run_query_str(input).map_err(cnv_err)?;

Check failure on line 131 in python/src/pyrudof_lib.rs

View workflow job for this annotation

GitHub Actions / Clippy

no method named `run_query_str` found for struct `rudof_lib::Rudof` in the current scope
Ok(PyQuerySolutions { inner: results })
}

/// Run a SPARQL query obtained from a file path on the RDF data
#[pyo3(signature = (path_name))]
pub fn run_query_path(&mut self, path_name: &str) -> PyResult<PyQuerySolutions> {
let path = Path::new(path_name);
let file = File::open::<&OsStr>(path.as_ref())
.map_err(|e| RudofError::ReadingDCTAPPath {
path: path_name.to_string(),
error: format!("{e}"),
})
.map_err(cnv_err)?;
let mut reader = BufReader::new(file);
let results = self.inner.run_query(&mut reader).map_err(cnv_err)?;
Ok(PyQuerySolutions { inner: results })
}

/// Reads DCTAP from a String
#[pyo3(signature = (input, format = &PyDCTapFormat::CSV))]
pub fn read_dctap_str(&mut self, input: &str, format: &PyDCTapFormat) -> PyResult<()> {
Expand Down Expand Up @@ -683,15 +707,60 @@ pub enum PyShapesGraphSource {
CurrentSchema,
}

#[pyclass(name = "QuerySulutions")]
#[pyclass(name = "QuerySolution")]
pub struct PyQuerySolution {
inner: QuerySolution<RdfData>,
}

#[pymethods]
impl PyQuerySolution {
pub fn show(&self) -> String {
self.inner.show().to_string()
}
}

#[pyclass(name = "QuerySolutions")]
pub struct PyQuerySolutions {
inner: QuerySolutions<RdfData>,
}

#[pymethods]
impl PyQuerySolutions {
pub fn show(&self) -> String {
format!("Solutions: {:?}", self.inner)
}

pub fn count(&self) -> usize {
self.inner.count()
}

fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<QuerySolutionIter>> {
let rs: Vec<PyQuerySolution> = slf
.inner
.iter()
.map(|qs| PyQuerySolution { inner: qs.clone() })
.collect();
let iter = QuerySolutionIter {
inner: rs.into_iter(),
};
Py::new(slf.py(), iter)
}
}

#[pyclass]
struct QuerySolutionIter {
inner: std::vec::IntoIter<PyQuerySolution>,
}

#[pymethods]
impl QuerySolutionIter {
fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
slf
}

fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<PyQuerySolution> {
slf.inner.next()
}
}

#[pyclass(frozen, name = "ResultShapeMap")]
Expand Down

0 comments on commit e9e0be4

Please sign in to comment.