Merge branch 'python-eval' of https://github.com/murarth/rust-cpython
This commit is contained in:
commit
65395a11b1
|
@ -17,10 +17,12 @@
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
use std::ffi::CString;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use libc::c_int;
|
||||||
use ffi;
|
use ffi;
|
||||||
use objects::{PyObject, PyType, PyBool, PyModule};
|
use objects::{PyObject, PyType, PyBool, PyDict, PyModule};
|
||||||
use err::PyResult;
|
use err::{self, PyErr, PyResult};
|
||||||
use pythonrun::GILGuard;
|
use pythonrun::GILGuard;
|
||||||
|
|
||||||
/// Marker type that indicates that the GIL is currently held.
|
/// Marker type that indicates that the GIL is currently held.
|
||||||
|
@ -150,6 +152,62 @@ impl<'p> Python<'p> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluates a Python expression in the given context and returns the result.
|
||||||
|
///
|
||||||
|
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||||
|
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||||
|
pub fn eval(self, code: &str, globals: Option<&PyDict<'p>>,
|
||||||
|
locals: Option<&PyDict<'p>>) -> PyResult<'p, PyObject<'p>> {
|
||||||
|
self.run_code(code, ffi::Py_eval_input, globals, locals)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes one or more Python statements in the given context.
|
||||||
|
///
|
||||||
|
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||||
|
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||||
|
pub fn run(self, code: &str, globals: Option<&PyDict<'p>>,
|
||||||
|
locals: Option<&PyDict<'p>>) -> PyResult<'p, ()> {
|
||||||
|
try!(self.run_code(code, ffi::Py_file_input, globals, locals));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs code in the given context.
|
||||||
|
/// `start` indicates the type of input expected:
|
||||||
|
/// one of `Py_single_input`, `Py_file_input`, or `Py_eval_input`.
|
||||||
|
///
|
||||||
|
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||||
|
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||||
|
fn run_code(self, code: &str, start: c_int,
|
||||||
|
globals: Option<&PyDict<'p>>, locals: Option<&PyDict<'p>>)
|
||||||
|
-> PyResult<'p, PyObject<'p>> {
|
||||||
|
let code = CString::new(code).unwrap();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mptr = ffi::PyImport_AddModule("__main__\0".as_ptr() as *const _);
|
||||||
|
|
||||||
|
if mptr.is_null() {
|
||||||
|
return Err(PyErr::fetch(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mdict = ffi::PyModule_GetDict(mptr);
|
||||||
|
|
||||||
|
let globals = match globals {
|
||||||
|
Some(g) => g.as_ptr(),
|
||||||
|
None => mdict,
|
||||||
|
};
|
||||||
|
|
||||||
|
let locals = match locals {
|
||||||
|
Some(l) => l.as_ptr(),
|
||||||
|
None => globals
|
||||||
|
};
|
||||||
|
|
||||||
|
let res_ptr = ffi::PyRun_StringFlags(code.as_ptr(),
|
||||||
|
start, globals, locals, 0 as *mut _);
|
||||||
|
|
||||||
|
err::result_from_owned_ptr(self, res_ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the Python builtin value `None`.
|
/// Gets the Python builtin value `None`.
|
||||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -188,3 +246,27 @@ impl <'p> std::fmt::Debug for PythonObjectDowncastError<'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use {Python, PyDict};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eval() {
|
||||||
|
let gil = Python::acquire_gil();
|
||||||
|
let py = gil.python();
|
||||||
|
|
||||||
|
// Make sure builtin names are accessible
|
||||||
|
let v: i32 = py.eval("min(1, 2)", None, None).unwrap().extract().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(v, 1);
|
||||||
|
|
||||||
|
let d = PyDict::new(py);
|
||||||
|
|
||||||
|
d.set_item("foo", 13).unwrap();
|
||||||
|
|
||||||
|
// Inject our own local namespace
|
||||||
|
let v: i32 = py.eval("foo + 29", None, Some(&d)).unwrap().extract().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(v, 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue