Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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!"
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion pyiks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from _pyiks import (
from ._iks import (
BadJidError,
BadXmlError,
Document,
Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ homepage = "https://github.com/meduketto/iksemel-python"

[tool.maturin]
features = ["pyo3/extension-module"]
exclude = [
".github/**/*",
".gitignore",
]
module-name = "pyiks._iks"
37 changes: 29 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use std::sync::Arc;
use std::sync::Mutex;
use std::sync::PoisonError;
use std::time::Duration;

use iks::BadJid;
Expand All @@ -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);
Expand All @@ -31,6 +33,7 @@ create_exception!(pyiks, XmppError, PyException);

enum PyIksError {
NoMemory,
PoisonedMutex,
BadXml(&'static str),
BadJid(&'static str),
StreamError(&'static str),
Expand Down Expand Up @@ -67,10 +70,17 @@ impl From<XmppClientError> for PyIksError {
}
}

impl<T> From<PoisonError<T>> for PyIksError {
fn from(_: PoisonError<T>) -> Self {
PyIksError::PoisonedMutex
}
}

impl From<PyIksError> 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),
Expand Down Expand Up @@ -294,6 +304,17 @@ pub enum XmlText {
Bytes(Vec<u8>),
}

/// 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<PyDocument, PyIksError> {
let bytes = match xml_text {
Expand Down Expand Up @@ -341,12 +362,12 @@ impl PyXmppClient {

fn wait_for_stanza(&self, py: Python<'_>) -> PyResult<PyDocument> {
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<Option<Document>, 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),
Expand All @@ -360,27 +381,27 @@ 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(())
}
}

#[pymodule]
fn _pyiks(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
fn _iks(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyDocument>()?;
m.add_class::<DocumentChildrenIterator>()?;
m.add_class::<PyXmppClient>()?;
Expand Down
Loading