pyqie 0.0.4

Python extension module for Pyqie, a retro game engine for Python
Documentation
use std::process::exit;

use pyo3::exceptions::PyKeyboardInterrupt;
use pyo3::prelude::*;
use pyo3::types::{PyAny, PyDict};
use pyqie::{Pyqie, PyqieCallback};
use sysinfo::{Pid, System};

use crate::pyqie_singleton::{pyqie, set_pyqie_instance};

#[pyfunction]
#[pyo3(
    text_signature = "(fps)"
)]
fn init(
    py: Python,
    fps: Option<u32>
) -> PyResult<()> {
    let locals = PyDict::new(py);
    locals.set_item("os", py.import("os")?)?;
    locals.set_item("inspect", py.import("inspect")?)?;
    py.run(
        "os.chdir(os.path.dirname(inspect.stack()[1].filename) or '.')",
        None,
        Some(locals),
    )?;
    set_pyqie_instance(pyqie::init(
        fps
    ));
    Ok(())
}

#[pyfunction]
fn run(py: Python, update: &PyAny, draw: &PyAny, close: &PyAny) {
    struct PythonCallback<'a> {
        py: Python<'a>,
        update: &'a PyAny,
        draw: &'a PyAny,
        close: &'a PyAny,
    }

    impl<'a> PythonCallback<'a> {
        fn close(&mut self, _pyqie: &mut Pyqie) {
            if let Err(err) = self.close.call0() {
                err.print(self.py);
            }
        }

        fn print_err(&mut self,err:& PyErr){
            if !err.is_instance_of::<PyKeyboardInterrupt>(self.py){
                err.print(self.py);
            };
        }
    }

    impl<'a> PyqieCallback for PythonCallback<'a> {
        fn update(&mut self, _pyqie: &mut Pyqie) {
            if let Err(err) = self.update.call0() {
                self.close(_pyqie);
                self.print_err(&err);
                exit(1);
            }
        }

        fn draw(&mut self, _pyqie: &mut Pyqie) {
            if let Err(err) = self.draw.call0() {
                self.close(_pyqie);
                self.print_err(&err);
                exit(1);
            }
        }
    }

    pyqie().run(PythonCallback { py, update, draw, close });
}

#[pyfunction]
fn show() {
    pyqie().show();
}

#[pyfunction]
fn quit() {
    pyqie().quit();
}

#[pyfunction]
fn title(title: &str) {
    pyqie().title(title);
}

#[pyfunction]
fn process_exists(pid: u32) -> bool {
    let system = System::new_all();
    system.process(Pid::from_u32(pid)).is_some()
}

pub fn add_system_functions(m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(init, m)?)?;
    m.add_function(wrap_pyfunction!(run, m)?)?;
    m.add_function(wrap_pyfunction!(show, m)?)?;
    m.add_function(wrap_pyfunction!(quit, m)?)?;
    m.add_function(wrap_pyfunction!(title, m)?)?;
    m.add_function(wrap_pyfunction!(process_exists, m)?)?;
    Ok(())
}