diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb655b7..906c7ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,10 +42,17 @@ jobs: uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 with: command: build - args: --release --out dist + args: --verbose --release --out dist - name: Run tests run: | - pip install pytest + python -m pip install pytest python -m pip install --find-links=dist/ pyiks - python -m pytest tests/ -v + cd tests + python -m pytest -v + + all-tests-passed: + needs: test + runs-on: ubuntu-latest + steps: + - run: echo "All matrix jobs completed!" diff --git a/Cargo.toml b/Cargo.toml index 902d8ae..a1d9307 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ license = "LGPL-3.0-or-later" repository = "https://github.com/meduketto/iksemel-python" [lib] -name = "_pyiks" +name = "_iks" crate-type = ["cdylib"] [dependencies] diff --git a/pyiks/__init__.py b/pyiks/__init__.py index eab985f..1a1b512 100644 --- a/pyiks/__init__.py +++ b/pyiks/__init__.py @@ -1,4 +1,4 @@ -from _pyiks import ( +from ._iks import ( BadJidError, BadXmlError, Document, diff --git a/pyiks/pyiks.pyi b/pyiks/_iks.pyi similarity index 100% rename from pyiks/pyiks.pyi rename to pyiks/_iks.pyi diff --git a/pyproject.toml b/pyproject.toml index a8747e0..8fdc2af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,3 +27,8 @@ homepage = "https://github.com/meduketto/iksemel-python" [tool.maturin] features = ["pyo3/extension-module"] +exclude = [ + ".github/**/*", + ".gitignore", +] +module-name = "pyiks._iks" diff --git a/src/lib.rs b/src/lib.rs index 2e1af73..d577f89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use std::sync::Mutex; +use std::sync::PoisonError; use std::time::Duration; use iks::BadJid; @@ -23,6 +24,7 @@ use iks::XmppClientError; use pyo3::create_exception; use pyo3::exceptions::PyException; use pyo3::exceptions::PyMemoryError; +use pyo3::exceptions::PyRuntimeError; use pyo3::prelude::*; create_exception!(pyiks, BadXmlError, PyException); @@ -31,6 +33,7 @@ create_exception!(pyiks, XmppError, PyException); enum PyIksError { NoMemory, + PoisonedMutex, BadXml(&'static str), BadJid(&'static str), StreamError(&'static str), @@ -67,10 +70,17 @@ impl From for PyIksError { } } +impl From> for PyIksError { + fn from(_: PoisonError) -> Self { + PyIksError::PoisonedMutex + } +} + impl From for PyErr { fn from(err: PyIksError) -> Self { match err { PyIksError::NoMemory => PyMemoryError::new_err("pyiks alloc failed"), + PyIksError::PoisonedMutex => PyRuntimeError::new_err("poisoned mutex"), PyIksError::BadXml(msg) => BadXmlError::new_err(msg), PyIksError::BadJid(msg) => BadJidError::new_err(msg), PyIksError::StreamError(msg) => XmppError::new_err(msg), @@ -294,6 +304,17 @@ pub enum XmlText { Bytes(Vec), } +/// Parse given text and return a 'Document' if successful. +/// +/// Args: +/// xml_text: The XML text to parse. +/// +/// Returns: +/// Parsed XML tree. +/// +/// Raises: +/// BadXmlError: If the XML text is not well-formed. +/// MemoryError: Not enough memory for the document tree. #[pyfunction] fn parse(xml_text: XmlText) -> Result { let bytes = match xml_text { @@ -341,12 +362,12 @@ impl PyXmppClient { fn wait_for_stanza(&self, py: Python<'_>) -> PyResult { loop { - let result = py.detach(|| { - let mut client = self.client.lock().unwrap(); - client.wait_for_stanza_timeout(Some(Duration::from_millis(250))) + let result: Result, PyIksError> = py.detach(|| { + let mut client = self.client.lock()?; + Ok(client.wait_for_stanza_timeout(Some(Duration::from_millis(250)))?) }); match result { - Err(e) => return Err(PyIksError::from(e).into()), + Err(e) => return Err(e.into()), Ok(Some(document)) => { return Ok(PyDocument { inner: SyncCursor::new(document), @@ -360,19 +381,19 @@ impl PyXmppClient { } fn send_stanza(&self, stanza: &PyDocument) -> Result<(), PyIksError> { - let mut client = self.client.lock().unwrap(); + let mut client = self.client.lock()?; client.send_bytes(stanza.inner.to_string().into_bytes())?; Ok(()) } fn request_roster(&self) -> Result<(), PyIksError> { - let mut client = self.client.lock().unwrap(); + let mut client = self.client.lock()?; client.request_roster()?; Ok(()) } fn send_message(&self, to: String, body: String) -> Result<(), PyIksError> { - let mut client = self.client.lock().unwrap(); + let mut client = self.client.lock()?; let to_jid = Jid::new(&to)?; client.send_message(to_jid, &body)?; Ok(()) @@ -380,7 +401,7 @@ impl PyXmppClient { } #[pymodule] -fn _pyiks(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { +fn _iks(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?;