Python: test Pyodide wheel

pull/760/head
Tpt 10 months ago committed by Thomas Tanon
parent 2a81106c34
commit ec030fb652
  1. 48
      .github/workflows/tests.yml
  2. 5
      python/Cargo.toml
  3. 17
      python/src/store.rs
  4. 6
      python/tests/test_store.py

@ -88,6 +88,24 @@ jobs:
component: clippy
- run: cargo clippy --lib --tests --target wasm32-wasi -- -D warnings -D clippy::all
working-directory: ./lib
- run: cargo clippy --target wasm32-wasi --features abi3 --no-default-features -- -D warnings -D clippy::all
working-directory: ./python
clippy_wasm_emscripten:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- uses: ./.github/actions/setup-rust
with:
version: 1.74.1
target: wasm32-unknown-emscripten
component: clippy
- run: cargo clippy --lib --tests --target wasm32-unknown-emscripten -- -D warnings -D clippy::all
working-directory: ./lib
- run: cargo clippy --target wasm32-unknown-emscripten --features abi3 -- -D warnings -D clippy::all
working-directory: ./python
clippy_wasm_unknown:
runs-on: ubuntu-latest
@ -346,6 +364,36 @@ jobs:
- run: python -m unittest
working-directory: ./python/tests
python_pyodide:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v4
with:
python-version: "3.11"
cache: pip
cache-dependency-path: '**/requirements.dev.txt'
- uses: ./.github/actions/setup-rust
with:
version: nightly
target: wasm32-unknown-emscripten
- run: |
pip install pyodide-build
echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV
- uses: mymindstorm/setup-emsdk@v13
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
- run: pyodide build
working-directory: ./python
- run: |
pyodide venv venv
source venv/bin/activate
pip install --no-index --find-links=../dist/ pyoxigraph
python -m unittest
working-directory: ./python/tests
typos:
runs-on: ubuntu-latest
steps:

@ -27,7 +27,10 @@ pyo3 = { version = "0.20.1", features = ["extension-module"] }
[target.'cfg(any(target_family = "windows", target_os = "macos", target_os = "ios"))'.dependencies]
oxigraph = { path = "../lib", features = ["http-client-native-tls"] }
[target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios")))'.dependencies]
[target.'cfg(target_family = "wasm")'.dependencies]
oxigraph.path = "../lib"
[target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios", target_family = "wasm")))'.dependencies]
oxigraph = { path = "../lib", features = ["http-client-rustls-native"] }
[lints]

@ -48,6 +48,7 @@ pub struct PyStore {
#[pymethods]
impl PyStore {
#[cfg(not(target_family = "wasm"))]
#[new]
#[pyo3(signature = (path = None))]
fn new(path: Option<PathBuf>, py: Python<'_>) -> PyResult<Self> {
@ -63,6 +64,16 @@ impl PyStore {
})
}
#[cfg(target_family = "wasm")]
#[new]
fn new(py: Python<'_>) -> PyResult<Self> {
py.allow_threads(|| {
Ok(Self {
inner: Store::new().map_err(map_storage_error)?,
})
})
}
/// Opens a read-only store from disk.
///
/// Opening as read-only while having an other process writing the database is undefined behavior.
@ -73,6 +84,7 @@ impl PyStore {
/// :return: the opened store.
/// :rtype: Store
/// :raises OSError: if the target directory contains invalid data or could not be accessed.
#[cfg(not(target_family = "wasm"))]
#[staticmethod]
fn read_only(path: &str, py: Python<'_>) -> PyResult<Self> {
py.allow_threads(|| {
@ -97,6 +109,7 @@ impl PyStore {
/// :return: the opened store.
/// :rtype: Store
/// :raises OSError: if the target directories contain invalid data or could not be accessed.
#[cfg(not(target_family = "wasm"))]
#[staticmethod]
#[pyo3(signature = (primary_path, secondary_path = None))]
fn secondary(
@ -173,6 +186,7 @@ impl PyStore {
/// >>> store.bulk_extend([Quad(NamedNode('http://example.com'), NamedNode('http://example.com/p'), Literal('1'), NamedNode('http://example.com/g'))])
/// >>> list(store)
/// [<Quad subject=<NamedNode value=http://example.com> predicate=<NamedNode value=http://example.com/p> object=<Literal value=1 datatype=<NamedNode value=http://www.w3.org/2001/XMLSchema#string>> graph_name=<NamedNode value=http://example.com/g>>]
#[cfg(not(target_family = "wasm"))]
fn bulk_extend(&self, quads: &PyAny) -> PyResult<()> {
self.inner
.bulk_loader()
@ -695,6 +709,7 @@ impl PyStore {
///
/// :rtype: None
/// :raises OSError: if an error happens during the flush.
#[cfg(not(target_family = "wasm"))]
fn flush(&self, py: Python<'_>) -> PyResult<()> {
py.allow_threads(|| self.inner.flush().map_err(map_storage_error))
}
@ -705,6 +720,7 @@ impl PyStore {
///
/// :rtype: None
/// :raises OSError: if an error happens during the optimization.
#[cfg(not(target_family = "wasm"))]
fn optimize(&self, py: Python<'_>) -> PyResult<()> {
py.allow_threads(|| self.inner.optimize().map_err(map_storage_error))
}
@ -730,6 +746,7 @@ impl PyStore {
/// :type target_directory: str or os.PathLike[str]
/// :rtype: None
/// :raises OSError: if an error happens during the backup.
#[cfg(not(target_family = "wasm"))]
fn backup(&self, target_directory: PathBuf, py: Python<'_>) -> PyResult<()> {
py.allow_threads(|| {
self.inner

@ -1,4 +1,5 @@
import gc
import sys
import unittest
from io import BytesIO, StringIO, UnsupportedOperation
from pathlib import Path
@ -26,6 +27,7 @@ bar = NamedNode("http://bar")
baz = NamedNode("http://baz")
triple = Triple(foo, foo, foo)
graph = NamedNode("http://graph")
is_wasm = sys.platform == "emscripten"
class TestStore(unittest.TestCase):
@ -49,6 +51,7 @@ class TestStore(unittest.TestCase):
)
self.assertEqual(len(store), 2)
@unittest.skipIf(is_wasm, "Not supported with WASM")
def test_bulk_extend(self) -> None:
store = Store()
store.bulk_extend(
@ -244,6 +247,7 @@ class TestStore(unittest.TestCase):
store.update("DELETE WHERE { ?v ?v ?v }")
self.assertEqual(len(store), 0)
@unittest.skipIf(is_wasm, "Not supported with WASM")
def test_update_load(self) -> None:
store = Store()
store.update("LOAD <https://www.w3.org/1999/02/22-rdf-syntax-ns>")
@ -381,6 +385,7 @@ class TestStore(unittest.TestCase):
self.assertEqual(list(store.named_graphs()), [])
self.assertEqual(list(store), [])
@unittest.skipIf(is_wasm, "Not supported with WASM")
def test_read_only(self) -> None:
quad = Quad(foo, bar, baz, graph)
with TemporaryDirectory() as dir:
@ -391,6 +396,7 @@ class TestStore(unittest.TestCase):
store = Store.read_only(dir)
self.assertEqual(list(store), [quad])
@unittest.skipIf(is_wasm, "Not supported with WASM")
def test_secondary(self) -> None:
quad = Quad(foo, bar, baz, graph)
with TemporaryDirectory() as dir:

Loading…
Cancel
Save