pymodule: misc cleanups

This commit is contained in:
David Hewitt 2021-03-13 17:51:38 +00:00
parent d3dc031b22
commit bff39d8871
3 changed files with 27 additions and 41 deletions

View File

@ -22,7 +22,6 @@ pub use self::num::PyLong as PyInt;
pub use self::sequence::PySequence; pub use self::sequence::PySequence;
pub use self::set::{PyFrozenSet, PySet}; pub use self::set::{PyFrozenSet, PySet};
pub use self::slice::{PySlice, PySliceIndices}; pub use self::slice::{PySlice, PySliceIndices};
pub(crate) use self::string::with_tmp_string;
pub use self::string::{PyString, PyString as PyUnicode}; pub use self::string::{PyString, PyString as PyUnicode};
pub use self::tuple::PyTuple; pub use self::tuple::PyTuple;
pub use self::typeobject::PyType; pub use self::typeobject::PyType;

View File

@ -13,7 +13,6 @@ use crate::types::{PyAny, PyDict, PyList};
use crate::types::{PyCFunction, PyTuple}; use crate::types::{PyCFunction, PyTuple};
use crate::{AsPyPointer, IntoPy, Py, PyObject, Python}; use crate::{AsPyPointer, IntoPy, Py, PyObject, Python};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::str; use std::str;
/// Represents a Python `module` object. /// Represents a Python `module` object.
@ -32,9 +31,8 @@ impl PyModule {
/// Imports the Python module with the specified name. /// Imports the Python module with the specified name.
pub fn import<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> { pub fn import<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> {
crate::types::with_tmp_string(py, name, |name| unsafe { let name: PyObject = name.into_py(py);
py.from_owned_ptr_or_err(ffi::PyImport_Import(name)) unsafe { py.from_owned_ptr_or_err(ffi::PyImport_Import(name.as_ptr())) }
})
} }
/// Loads the Python code specified into a new module. /// Loads the Python code specified into a new module.
@ -95,25 +93,19 @@ impl PyModule {
} }
} }
unsafe fn str_from_ptr(&self, ptr: *const c_char) -> PyResult<&str> {
if ptr.is_null() {
Err(PyErr::fetch(self.py()))
} else {
let slice = CStr::from_ptr(ptr).to_bytes();
match str::from_utf8(slice) {
Ok(s) => Ok(s),
Err(e) => Err(PyErr::from_instance(
exceptions::PyUnicodeDecodeError::new_utf8(self.py(), slice, e)?,
)),
}
}
}
/// Returns the module's name. /// Returns the module's name.
/// ///
/// May fail if the module does not have a `__name__` attribute. /// May fail if the module does not have a `__name__` attribute.
pub fn name(&self) -> PyResult<&str> { pub fn name(&self) -> PyResult<&str> {
unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.as_ptr())) } let ptr = unsafe { ffi::PyModule_GetName(self.as_ptr()) };
if ptr.is_null() {
Err(PyErr::fetch(self.py()))
} else {
let name = unsafe { CStr::from_ptr(ptr) }
.to_str()
.expect("PyModule_GetName expected to return utf8");
Ok(name)
}
} }
/// Returns the module's filename. /// Returns the module's filename.
@ -311,3 +303,16 @@ impl PyModule {
self.add(name, fun) self.add(name, fun)
} }
} }
#[cfg(test)]
mod test {
use crate::{types::PyModule, Python};
#[test]
fn module_import_and_name() {
Python::with_gil(|py| {
let builtins = PyModule::import(py, "builtins").unwrap();
assert_eq!(builtins.name().unwrap(), "builtins");
})
}
}

View File

@ -2,8 +2,8 @@
use crate::types::PyBytes; use crate::types::PyBytes;
use crate::{ use crate::{
ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyErr, PyNativeType, PyObject, PyResult, ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyNativeType, PyObject, PyResult, PyTryFrom,
PyTryFrom, Python, ToPyObject, Python, ToPyObject,
}; };
use std::borrow::Cow; use std::borrow::Cow;
use std::os::raw::c_char; use std::os::raw::c_char;
@ -51,7 +51,7 @@ impl PyString {
let mut size: ffi::Py_ssize_t = 0; let mut size: ffi::Py_ssize_t = 0;
let data = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size) }; let data = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size) };
if data.is_null() { if data.is_null() {
return Err(PyErr::fetch(self.py())); return Err(crate::PyErr::fetch(self.py()));
} else { } else {
unsafe { std::slice::from_raw_parts(data as *const u8, size as usize) } unsafe { std::slice::from_raw_parts(data as *const u8, size as usize) }
} }
@ -88,24 +88,6 @@ impl PyString {
} }
} }
/// Convenience for calling Python APIs with a temporary string
/// object created from a given Rust string.
pub(crate) fn with_tmp_string<F, R>(py: Python, s: &str, f: F) -> PyResult<R>
where
F: FnOnce(*mut ffi::PyObject) -> PyResult<R>,
{
unsafe {
let s_obj =
ffi::PyUnicode_FromStringAndSize(s.as_ptr() as *const _, s.len() as ffi::Py_ssize_t);
if s_obj.is_null() {
return Err(PyErr::fetch(py));
}
let ret = f(s_obj);
ffi::Py_DECREF(s_obj);
ret
}
}
/// Converts a Rust `str` to a Python object. /// Converts a Rust `str` to a Python object.
/// See `PyString::new` for details on the conversion. /// See `PyString::new` for details on the conversion.
impl ToPyObject for str { impl ToPyObject for str {