Skip to content

Commit

Permalink
Adds basic Python bindings to Oxigraph
Browse files Browse the repository at this point in the history
  • Loading branch information
Tpt committed Jul 18, 2020
1 parent fe92703 commit f74bc12
Show file tree
Hide file tree
Showing 18 changed files with 1,504 additions and 19 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/build.yml
Expand Up @@ -41,3 +41,17 @@ jobs:
working-directory: ./js
- run: npm test
working-directory: ./js

python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: rustup update
- uses: actions/setup-python@v2
with:
python-version: 3.5
- run: python -m pip install --upgrade pip maturin
- run: maturin develop
working-directory: ./python
- run: python -m unittest
working-directory: ./python/tests
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -2,6 +2,7 @@
members = [
"js",
"lib",
"python",
"server",
"testsuite",
"wikibase"
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -13,6 +13,7 @@ It is written in Rust.

It is split into multiple parts:
* The `lib` directory contains the database written as a Rust library.
* The `python` directory contains bindings to use Oxigraph in Python. See [its README](https://github.com/oxigraph/oxigraph/blob/master/python/README.md) for the Python bindings documentation.
* The `js` directory contains bindings to use Oxigraph in JavaScript with the help of WebAssembly. See [its README](https://github.com/oxigraph/oxigraph/blob/master/js/README.md) for the JS bindings documentation.
* The `server` directory contains a stand-alone binary of a web server implementing the [SPARQL 1.1 Protocol](https://www.w3.org/TR/sparql11-protocol/).
* The `wikibase` directory contains a stand-alone binary of a web server able to synchronize with a [Wikibase instance](https://wikiba.se/).
Expand Down
2 changes: 1 addition & 1 deletion js/Cargo.toml
Expand Up @@ -3,7 +3,7 @@ name = "oxigraph_js"
version = "0.0.2"
authors = ["Tpt <thomas@pellissier-tanon.fr>"]
license = "MIT/Apache-2.0"
readme = "../README.md"
readme = "README.md"
keywords = ["RDF", "N-Triples", "Turtle", "RDF/XML", "SPARQL"]
repository = "https://github.com/oxigraph/oxigraph/tree/master/js"
description = "JavaScript bindings of Oxigraph"
Expand Down
30 changes: 15 additions & 15 deletions js/README.md
Expand Up @@ -23,6 +23,21 @@ npm install oxigraph
const oxigraph = require('oxigraph');
```

## Example

Insert the triple `<http://example/> <http://schema.org/name> "example"` and log the name of `<http://example/>` in SPARQL:
```js
const { MemoryStore } = require('oxigraph');
const store = new MemoryStore();
const dataFactory = store.dataFactory;
const ex = dataFactory.namedNode("http://example/");
const schemaName = dataFactory.namedNode("http://schema.org/name");
store.add(dataFactory.triple(ex, schemaName, dataFactory.literal("example")));
for (binding of store.query("SELECT ?name WHERE { <http://example/> <http://schema.org/name> ?name }")) {
console.log(binding.get("name").value);
}
```

## API

Oxigraph currently provides a simple JS API.
Expand Down Expand Up @@ -140,21 +155,6 @@ Example of loading a Turtle file into the named graph `<http://example.com/graph
store.load("<http://example.com> <http://example.com> <> .", "text/turtle", "http://example.com", store.dataFactory.namedNode("http://example.com/graph"));
```

## Example

Insert the triple `<http://example/> <http://schema.org/name> "example"` and log the name of `<http://example/>` in SPARQL:
```js
const { MemoryStore } = require('oxigraph');
const store = new MemoryStore();
const dataFactory = store.dataFactory;
const ex = dataFactory.namedNode("http://example/");
const schemaName = dataFactory.namedNode("http://schema.org/name");
store.add(dataFactory.triple(ex, schemaName, dataFactory.literal("example")));
for (binding of store.query("SELECT ?name WHERE { <http://example/> <http://schema.org/name> ?name }")) {
console.log(binding.get("name").value);
}
```


## How to contribute

Expand Down
2 changes: 1 addition & 1 deletion lib/src/sparql/json_results.rs
@@ -1,4 +1,4 @@
//! Implementation of [SPARQL Query Results XML Format](https://www.w3.org/TR/sparql11-results-json/)
//! Implementation of [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/)

use crate::model::*;
use crate::sparql::model::*;
Expand Down
26 changes: 25 additions & 1 deletion lib/src/store/rocksdb.rs
Expand Up @@ -9,8 +9,8 @@ use rocksdb::*;
use std::io::BufRead;
use std::mem::take;
use std::path::Path;
use std::str;
use std::sync::Arc;
use std::{fmt, str};

/// Store based on the [RocksDB](https://rocksdb.org/) key-value database.
/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL.
Expand Down Expand Up @@ -155,6 +155,21 @@ impl RocksDbStore {
self.handle().contains(&quad)
}

/// Returns the number of quads in the store
pub fn len(&self) -> usize {
self.db
.full_iterator_cf(self.handle().spog_cf, IteratorMode::Start)
.count()
}

/// Returns if the store is empty
pub fn is_empty(&self) -> bool {
self.db
.full_iterator_cf(self.handle().spog_cf, IteratorMode::Start)
.next()
.is_none()
}

/// Executes a transaction.
///
/// The transaction is executed if the given closure returns `Ok`.
Expand Down Expand Up @@ -235,6 +250,15 @@ impl RocksDbStore {
}
}

impl fmt::Display for RocksDbStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.quads_for_pattern(None, None, None, None) {
writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?;
}
Ok(())
}
}

impl StrLookup for RocksDbStore {
fn get_str(&self, id: StrHash) -> Result<Option<String>> {
Ok(self
Expand Down
21 changes: 20 additions & 1 deletion lib/src/store/sled.rs
Expand Up @@ -8,7 +8,7 @@ use crate::{DatasetSyntax, GraphSyntax, Result};
use sled::{Config, Iter, Tree};
use std::io::BufRead;
use std::path::Path;
use std::str;
use std::{fmt, str};

/// Store based on the [Sled](https://sled.rs/) key-value database.
/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL.
Expand Down Expand Up @@ -138,6 +138,16 @@ impl SledStore {
self.contains_encoded(&quad)
}

/// Returns the number of quads in the store
pub fn len(&self) -> usize {
self.spog.len()
}

/// Returns if the store is empty
pub fn is_empty(&self) -> bool {
self.spog.is_empty()
}

/// Loads a graph file (i.e. triples) into the store
///
/// Warning: This functions saves the triples in batch. If the parsing fails in the middle of the file,
Expand Down Expand Up @@ -394,6 +404,15 @@ impl SledStore {
}
}

impl fmt::Display for SledStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in self.quads_for_pattern(None, None, None, None) {
writeln!(f, "{}", t.map_err(|_| fmt::Error)?)?;
}
Ok(())
}
}

impl StrLookup for SledStore {
fn get_str(&self, id: StrHash) -> Result<Option<String>> {
Ok(self
Expand Down
31 changes: 31 additions & 0 deletions python/Cargo.toml
@@ -0,0 +1,31 @@
[package]
name = "oxigraph_python"
version = "0.1.0"
authors = ["Tpt <thomas@pellissier-tanon.fr>"]
license = "MIT/Apache-2.0"
readme = "README.md"
keywords = ["RDF", "N-Triples", "Turtle", "RDF/XML", "SPARQL"]
repository = "https://github.com/oxigraph/oxigraph/tree/master/python"
description = """
Python bindings of Oxigraph
"""
edition = "2018"

[lib]
crate-type = ["cdylib"]
name = "oxigraph"

[dependencies]
oxigraph = {path = "../lib", features=["sled"]}
pyo3 = {version="0.11", features = ["extension-module"]}

[package.metadata.maturin]
classifier = [
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Rust",
"Topic :: Database :: Database Engines/Servers"
]

0 comments on commit f74bc12

Please sign in to comment.