Put Python argument at beginning of argument list.

Closes #33.
This commit is contained in:
Daniel Grunwald 2015-10-26 23:52:18 +01:00
parent 44611991c3
commit 0a270a0583
29 changed files with 292 additions and 288 deletions

View File

@ -8,11 +8,11 @@ fn main() {
let py = gil.python();
let sys = py.import("sys").unwrap();
let version: String = sys.get("version", py).unwrap().extract(py).unwrap();
let version: String = sys.get(py, "version").unwrap().extract(py).unwrap();
let os = py.import("os").unwrap();
let getenv = os.get("getenv", py).unwrap();
let user: String = getenv.call(("USER",), None, py).unwrap().extract(py).unwrap();
let getenv = os.get(py, "getenv").unwrap();
let user: String = getenv.call(py, ("USER",), None).unwrap().extract(py).unwrap();
println!("Hello {}, I'm Python {}", user, version);
}

View File

@ -7,8 +7,8 @@
use cpython::{Python, PyObject, PyRustObject, PyResult};
py_module_initializer!(custom_type, |py, m| {
try!(m.add("__doc__", "Module documentation string", py));
try!(m.add_type::<i32>("MyType", py)
try!(m.add(py, "__doc__", "Module documentation string"));
try!(m.add_type::<i32>(py, "MyType")
.add("a", py_method!(a()))
.finish());
Ok(())

View File

@ -7,9 +7,9 @@
use cpython::{PyObject, PyResult, Python, PyTuple, PyDict};
py_module_initializer!(hello, |py, m| {
try!(m.add("__doc__", "Module documentation string", py));
try!(m.add("run", py_fn!(run), py));
try!(m.add("val", py_fn!(val()), py));
try!(m.add(py, "__doc__", "Module documentation string"));
try!(m.add(py, "run", py_fn!(run)));
try!(m.add(py, "val", py_fn!(val())));
Ok(())
});

View File

@ -5,14 +5,14 @@
#[macro_use] extern crate cpython;
py_module_initializer!(inheritance, |py, m| {
try!(m.add("__doc__", "Module documentation string", py));
try!(m.add(py, "__doc__", "Module documentation string"));
let base_class = try!(
m.add_type::<()>("BaseClass", py)
m.add_type::<()>(py, "BaseClass")
.doc("Type doc string")
.finish());
for i in 1..10 {
try!(
m.add_type::<()>(&format!("C{}", i), py)
m.add_type::<()>(py, &format!("C{}", i))
.base(&base_class)
.doc(&format!("Derived class #{}", i))
.finish());

View File

@ -43,10 +43,10 @@ pub struct ParamDescription<'a> {
/// * output: Output array that receives the arguments.
/// Must have same length as `params` and must be initialized to `None`.
pub fn parse_args(
py: Python,
fname: Option<&str>, params: &[ParamDescription],
args: &PyTuple, kwargs: Option<&PyDict>,
output: &mut[Option<PyObject>],
py: Python
output: &mut[Option<PyObject>]
) -> PyResult<()>
{
assert!(params.len() == output.len());
@ -65,7 +65,7 @@ pub fn parse_args(
let mut used_keywords = 0;
// Iterate through the parameters and assign values to output:
for (i, (p, out)) in params.iter().zip(output).enumerate() {
match kwargs.and_then(|d| d.get_item(p.name, py)) {
match kwargs.and_then(|d| d.get_item(py, p.name)) {
Some(kwarg) => {
*out = Some(kwarg);
used_keywords += 1;
@ -77,7 +77,7 @@ pub fn parse_args(
},
None => {
if i < nargs {
*out = Some(args.get_item(i, py));
*out = Some(args.get_item(py, i));
} else {
*out = None;
if !p.is_optional {
@ -92,7 +92,7 @@ pub fn parse_args(
if used_keywords != nkeywords {
// check for extraneous keyword arguments
for (key, _value) in kwargs.unwrap().items(py) {
let key = try!(PyString::extract(&key, py));
let key = try!(PyString::extract(py, &key));
if !params.iter().any(|p| p.name == key) {
return Err(err::PyErr::new::<exc::TypeError, _>(py,
format!("'{}' is an invalid keyword argument for this function",
@ -106,11 +106,11 @@ pub fn parse_args(
#[doc(hidden)]
#[macro_export]
macro_rules! py_argparse_extract {
( $iter:expr, $py:ident, ( ) $body:block ) => { $body };
( $iter:expr, $py:ident, ( $pname:ident : $ptype:ty ) $body:block) => {
match <$ptype as $crate::ExtractPyObject>::prepare_extract($iter.next().unwrap().as_ref().unwrap(), $py) {
( $py:ident, $iter:expr, ( ) $body:block ) => { $body };
( $py:ident, $iter:expr, ( $pname:ident : $ptype:ty ) $body:block) => {
match <$ptype as $crate::ExtractPyObject>::prepare_extract($py, $iter.next().unwrap().as_ref().unwrap()) {
Ok(prepared) => {
match <$ptype as $crate::ExtractPyObject>::extract(&prepared, $py) {
match <$ptype as $crate::ExtractPyObject>::extract($py, &prepared) {
Ok($pname) => $body,
Err(e) => Err(e)
}
@ -118,9 +118,9 @@ macro_rules! py_argparse_extract {
Err(e) => Err(e)
}
};
( $iter:expr, $py: ident, ( $pname:ident : $ptype:ty , $($r:tt)+ ) $body:block) => {
py_argparse_extract!($iter, $py, ($pname: $ptype) {
py_argparse_extract!( $iter, $py, ( $($r)* ) $body)
( $py: ident, $iter:expr, ( $pname:ident : $ptype:ty , $($r:tt)+ ) $body:block) => {
py_argparse_extract!($py, $iter, ($pname: $ptype) {
py_argparse_extract!( $py, $iter, ( $($r)* ) $body)
})
}
}
@ -133,8 +133,9 @@ macro_rules! py_argparse_snd {
/// This macro is used to parse a parameter list into a set of variables.
///
/// Syntax: `py_argparse!(fname, args, kwargs, (parameter-list) { body })`
/// Syntax: `py_argparse!(py, fname, args, kwargs, (parameter-list) { body })`
///
/// * `py`: the `Python` token
/// * `fname`: expression of type `Option<&str>`: Name of the function used in error messages.
/// * `args`: expression of type `&PyTuple`: The position arguments
/// * `kwargs`: expression of type `Option<&PyDict>`: The named arguments
@ -149,7 +150,7 @@ macro_rules! py_argparse_snd {
/// If extraction fails, `py_argparse!()` returns a failed `PyResult` without evaluating `body`.
#[macro_export]
macro_rules! py_argparse {
($fname:expr, $args:expr, $kwargs:expr, $py:expr, ($( $pname:ident : $ptype:ty ),*) $body:block) => {{
($py:expr, $fname:expr, $args:expr, $kwargs:expr, ($( $pname:ident : $ptype:ty ),*) $body:block) => {{
const PARAMS: &'static [$crate::argparse::ParamDescription<'static>] = &[
$(
$crate::argparse::ParamDescription {
@ -160,12 +161,12 @@ macro_rules! py_argparse {
];
let py: $crate::Python = $py;
let mut output = [$( py_argparse_snd!($pname, None) ),*];
match $crate::argparse::parse_args($fname, PARAMS, $args, $kwargs, &mut output, py) {
match $crate::argparse::parse_args(py, $fname, PARAMS, $args, $kwargs, &mut output) {
Ok(()) => {
// We can't use experimental slice pattern syntax in macros
//let &[$(ref $pname),*] = &output;
let mut iter = output.iter();
let ret = py_argparse_extract!( iter, py, ( $( $pname : $ptype ),* ) $body );
let ret = py_argparse_extract!( py, iter, ( $( $pname : $ptype ),* ) $body );
assert!(iter.next() == None);
ret
},
@ -185,7 +186,7 @@ mod test {
let py = gil_guard.python();
let mut called = false;
let tuple = ("abc", 42).to_py_object(py);
py_argparse!(None, &tuple, None, py, (x: &str, y: i32) {
py_argparse!(py, None, &tuple, None, (x: &str, y: i32) {
assert_eq!(x, "abc");
assert_eq!(y, 42);
called = true;

View File

@ -94,9 +94,9 @@ pub trait ToPyObject {
pub trait ExtractPyObject<'prepared> : Sized {
type Prepared : 'static;
fn prepare_extract<'a, 'p>(obj: &'a PyObject, py: Python<'p>) -> PyResult<Self::Prepared>;
fn prepare_extract<'a, 'p>(py: Python<'p>, obj: &'a PyObject) -> PyResult<Self::Prepared>;
fn extract<'p>(prepared: &'prepared Self::Prepared, py: Python<'p>) -> PyResult<Self>;
fn extract<'p>(py: Python<'p>, prepared: &'prepared Self::Prepared) -> PyResult<Self>;
}
impl <'prepared, T> ExtractPyObject<'prepared> for T
@ -105,12 +105,12 @@ where T: PythonObjectWithCheckedDowncast
type Prepared = PyObject;
#[inline]
fn prepare_extract(obj: &PyObject, py: Python) -> PyResult<Self::Prepared> {
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
Ok(obj.clone_ref(py))
}
#[inline]
fn extract(obj: &'prepared Self::Prepared, py: Python) -> PyResult<T> {
fn extract(py: Python, obj: &'prepared Self::Prepared) -> PyResult<T> {
Ok(try!(obj.clone_ref(py).cast_into(py)))
}
}

View File

@ -91,10 +91,10 @@ impl PyErr {
pub fn new<T, V>(py: Python, value: V) -> PyErr
where T: PythonObjectWithTypeObject, V: ToPyObject
{
PyErr::new_helper(py.get_type::<T>(), value.to_py_object(py).into_object())
PyErr::new_helper(py, py.get_type::<T>(), value.to_py_object(py).into_object())
}
fn new_helper(ty: PyType, value: PyObject) -> PyErr {
fn new_helper(_py: Python, ty: PyType, value: PyObject) -> PyErr {
assert!(unsafe { ffi::PyExceptionClass_Check(ty.as_object().as_ptr()) } != 0);
PyErr {
ptype: ty.into_object(),
@ -108,11 +108,11 @@ impl PyErr {
/// `obj` must be an Python exception instance, the PyErr will use that instance.
/// If `obj` is a Python exception type object, the PyErr will (lazily) create a new instance of that type.
/// Otherwise, a `TypeError` is created instead.
pub fn from_instance<O>(obj: O, py: Python) -> PyErr where O: PythonObject {
PyErr::from_instance_helper(obj.into_object(), py)
pub fn from_instance<O>(py: Python, obj: O) -> PyErr where O: PythonObject {
PyErr::from_instance_helper(py, obj.into_object())
}
fn from_instance_helper(obj: PyObject, py: Python) -> PyErr {
fn from_instance_helper(py: Python, obj: PyObject) -> PyErr {
if unsafe { ffi::PyExceptionInstance_Check(obj.as_ptr()) } != 0 {
PyErr {
ptype: unsafe { PyObject::from_borrowed_ptr(py, ffi::PyExceptionInstance_Class(obj.as_ptr())) },
@ -162,7 +162,7 @@ impl PyErr {
/// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass.
/// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.
#[inline]
pub fn matches(&self, exc: &PyObject, _py: Python) -> bool {
pub fn matches(&self, _py: Python, exc: &PyObject) -> bool {
unsafe { ffi::PyErr_GivenExceptionMatches(self.ptype.as_ptr(), exc.as_ptr()) != 0 }
}
@ -175,7 +175,7 @@ impl PyErr {
}
// This is safe as long as normalized() doesn't unwind due to a panic.
}
/// Helper function for normalizing the error by deconstructing and reconstructing the PyErr.
/// Must not panic for safety in normalize()
fn into_normalized(self, py: Python) -> PyErr {

View File

@ -91,7 +91,7 @@ macro_rules! py_fn {
Some(kwargs) => Some(<$crate::PyDict as $crate::PythonObject>::unchecked_downcast_from(kwargs)),
None => None
};
match py_argparse!(Some(stringify!($f)), &args, kwargs.as_ref(), py,
match py_argparse!(py, Some(stringify!($f)), &args, kwargs.as_ref(),
( $($pname : $ptype),* ) { $f( py, $($pname),* ) })
{
Ok(val) => {

View File

@ -20,7 +20,6 @@
#![feature(filling_drop)] // necessary to avoid segfault with unsafe_no_drop_flag
#![feature(optin_builtin_traits)] // for opting out of Sync/Send
#![feature(slice_patterns)] // for tuple_conversion macros
#![feature(utf8_error)] // for translating Utf8Error to Python exception
#![feature(plugin)]
#![plugin(interpolate_idents)]
#![allow(unused_imports)] // because some imports are only necessary with python 2.x or 3.x
@ -31,28 +30,25 @@
//! In Python, all objects are implicitly reference counted.
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
//!
//! The method `clone_ref()` (from trait `PyClone`) can be used to create additional
//! references to the same Python object.
//!
//! Because all Python objects potentially have multiple owners, the concept
//! concept of rust mutability does not apply to Python objects.
//! concept of Rust mutability does not apply to Python objects.
//! As a result, this API will allow mutating Python objects even if they are not stored
//! in a mutable rust variable.
//! in a mutable Rust variable.
//!
//! The Python interpreter uses a global interpreter lock (GIL)
//! to ensure thread-safety.
//! This API uses the lifetime parameter `PyObject<'p>` to ensure that Python objects cannot
//! be accessed without holding the GIL.
//! Throughout this library, the lifetime `'p` always refers to the lifetime of the Python interpreter.
//! This API uses a zero-sized `struct Python<'p>` as a token to indicate
//! that a function can assume that the GIL is held.
//!
//! When accessing existing objects, the lifetime on `PyObject<'p>` is sufficient to ensure that the GIL
//! is held by the current code. But we also need to ensure that the GIL is held when creating new objects.
//! For this purpose, this library uses the marker type `Python<'p>`,
//! which acts like a reference to the whole Python interpreter.
//!
//! You can obtain a `Python<'p>` instance by acquiring the GIL, or by calling `Python()`
//! on any existing Python object.
//! You obtain a `Python` instance by acquiring the GIL,
//! and have to pass it into all operations that call into the Python runtime.
//!
//! # Error Handling
//! The vast majority of operations in this library will return `PyResult<'p, ...>`.
//! This is an alias for the type `Result<..., PyErr<'p>>`.
//! The vast majority of operations in this library will return `PyResult<...>`.
//! This is an alias for the type `Result<..., PyErr>`.
//!
//! A `PyErr` represents a Python exception. Errors within the rust-cpython library are
//! also exposed as Python exceptions.
@ -66,14 +62,14 @@
//!
//! fn main() {
//! let gil = Python::acquire_gil();
//! let py = gil.python();
//! let py = gil.python(); // obtain `Python` token
//!
//! let sys = py.import("sys").unwrap();
//! let version: String = sys.get("version", py).unwrap().extract(py).unwrap();
//! let version: String = sys.get(py, "version").unwrap().extract(py).unwrap();
//!
//! let os = py.import("os").unwrap();
//! let getenv = os.get("getenv", py).unwrap();
//! let user: String = getenv.call(("USER",), None, py).unwrap().extract(py).unwrap();
//! let getenv = os.get(py, "getenv").unwrap();
//! let user: String = getenv.call(py, ("USER",), None).unwrap().extract(py).unwrap();
//!
//! println!("Hello {}, I'm Python {}", user, version);
//! }
@ -142,7 +138,7 @@ pub mod _detail {
/// assume_gil_acquired(), but the returned Python<'p> is bounded by the scope
/// of the referenced variable.
/// This is useful in macros to ensure that type inference doesn't set 'p == 'static.
/// This is useful in macros to ensure that type inference doesn't set `'p` == `'static`.
#[inline]
pub unsafe fn bounded_assume_gil_acquired<'p, T>(_bound: &'p T) -> super::Python<'p> {
super::Python::assume_gil_acquired()
@ -154,12 +150,8 @@ pub mod _detail {
///
/// Macro syntax: `py_module_initializer!($name, |$py, $m| $body)`
///
/// 1. The module name as a string literal.
/// 2. The name of the init function as an identifier.
/// The function must be named `init$module_name` so that Python 2.7 can load the module.
/// Note: this parameter will be removed in a future version
/// (once Rust supports `concat_ident!` as function name).
/// 3. A function or lambda of type `Fn(Python<'p>, &PyModule<'p>) -> PyResult<'p, ()>`.
/// 1. `name`: The module name as a Rust identifier.
/// 2. A lambda of type `Fn(Python, &PyModule) -> PyResult<()>`.
/// This function will be called when the module is imported, and is responsible
/// for adding the module's members.
///
@ -172,8 +164,8 @@ pub mod _detail {
/// use cpython::{Python, PyResult, PyObject};
///
/// py_module_initializer!(example, |py, m| {
/// try!(m.add("__doc__", "Module documentation string", py));
/// try!(m.add("run", py_fn!(run()), py));
/// try!(m.add(py, "__doc__", "Module documentation string"));
/// try!(m.add(py, "run", py_fn!(run())));
/// Ok(())
/// });
///

View File

@ -30,7 +30,7 @@ pub trait ObjectProtocol : PythonObject {
/// Determines whether this object has the given attribute.
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
#[inline]
fn hasattr<N>(&self, attr_name: N, py: Python) -> PyResult<bool> where N: ToPyObject {
fn hasattr<N>(&self, py: Python, attr_name: N) -> PyResult<bool> where N: ToPyObject {
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
Ok(ffi::PyObject_HasAttr(self.as_ptr(), attr_name) != 0)
})
@ -39,7 +39,7 @@ pub trait ObjectProtocol : PythonObject {
/// Retrieves an attribute value.
/// This is equivalent to the Python expression 'self.attr_name'.
#[inline]
fn getattr<N>(&self, attr_name: N, py: Python) -> PyResult<PyObject> where N: ToPyObject {
fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject> where N: ToPyObject {
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
err::result_from_owned_ptr(py,
ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
@ -49,7 +49,7 @@ pub trait ObjectProtocol : PythonObject {
/// Sets an attribute value.
/// This is equivalent to the Python expression 'self.attr_name = value'.
#[inline]
fn setattr<N, V>(&self, attr_name: N, value: V, py: Python) -> PyResult<()>
fn setattr<N, V>(&self, py: Python, attr_name: N, value: V) -> PyResult<()>
where N: ToPyObject, V: ToPyObject
{
attr_name.with_borrowed_ptr(py, move |attr_name|
@ -62,7 +62,7 @@ pub trait ObjectProtocol : PythonObject {
/// Deletes an attribute.
/// This is equivalent to the Python expression 'del self.attr_name'.
#[inline]
fn delattr<N>(&self, attr_name: N, py: Python) -> PyResult<()> where N: ToPyObject {
fn delattr<N>(&self, py: Python, attr_name: N) -> PyResult<()> where N: ToPyObject {
attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
err::error_on_minusone(py,
ffi::PyObject_DelAttr(self.as_ptr(), attr_name))
@ -72,7 +72,7 @@ pub trait ObjectProtocol : PythonObject {
/// Compares two Python objects.
/// This is equivalent to the Python expression 'cmp(self, other)'.
#[cfg(feature="python27-sys")]
fn compare<O>(&self, other: O, py: Python) -> PyResult<Ordering> where O: ToPyObject {
fn compare<O>(&self, py: Python, other: O) -> PyResult<Ordering> where O: ToPyObject {
other.with_borrowed_ptr(py, |other| unsafe {
let mut result : libc::c_int = -1;
try!(err::error_on_minusone(py,
@ -126,7 +126,7 @@ pub trait ObjectProtocol : PythonObject {
/// Calls the object.
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
#[inline]
fn call<A>(&self, args: A, kwargs: Option<&PyDict>, py: Python) -> PyResult<PyObject>
fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
where A: ToPyObject<ObjectType=PyTuple>
{
args.with_borrowed_ptr(py, |args| unsafe {
@ -137,10 +137,10 @@ pub trait ObjectProtocol : PythonObject {
/// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
#[inline]
fn call_method<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>, py: Python) -> PyResult<PyObject>
fn call_method<A>(&self, py: Python, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
where A: ToPyObject<ObjectType=PyTuple>
{
try!(self.getattr(name, py)).call(args, kwargs, py)
try!(self.getattr(py, name)).call(py, args, kwargs)
}
/// Retrieves the hash code of the object.
@ -181,7 +181,7 @@ pub trait ObjectProtocol : PythonObject {
/// This is equivalent to the Python expression: 'self[key]'
#[inline]
fn get_item<K>(&self, key: K, py: Python) -> PyResult<PyObject> where K: ToPyObject {
fn get_item<K>(&self, py: Python, key: K) -> PyResult<PyObject> where K: ToPyObject {
key.with_borrowed_ptr(py, |key| unsafe {
err::result_from_owned_ptr(py,
ffi::PyObject_GetItem(self.as_ptr(), key))
@ -191,7 +191,7 @@ pub trait ObjectProtocol : PythonObject {
/// Sets an item value.
/// This is equivalent to the Python expression 'self[key] = value'.
#[inline]
fn set_item<K, V>(&self, key: K, value: V, py: Python) -> PyResult<()> where K: ToPyObject, V: ToPyObject {
fn set_item<K, V>(&self, py: Python, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject {
key.with_borrowed_ptr(py, move |key|
value.with_borrowed_ptr(py, |value| unsafe {
err::error_on_minusone(py,
@ -202,14 +202,14 @@ pub trait ObjectProtocol : PythonObject {
/// Deletes an item.
/// This is equivalent to the Python expression 'del self[key]'.
#[inline]
fn del_item<K>(&self, key: K, py: Python) -> PyResult<()> where K: ToPyObject {
fn del_item<K>(&self, py: Python, key: K) -> PyResult<()> where K: ToPyObject {
key.with_borrowed_ptr(py, |key| unsafe {
err::error_on_minusone(py,
ffi::PyObject_DelItem(self.as_ptr(), key))
})
}
/* /// Takes an object and returns an iterator for it.
/* TODO /// Takes an object and returns an iterator for it.
/// This is typically a new iterator but if the argument
/// is an iterator, this returns itself.
#[cfg(feature="python27-sys")]
@ -248,7 +248,7 @@ mod test {
use std;
use python::{Python, PythonObject};
use conversion::ToPyObject;
use objects::{/*PySequence, */PyList, PyTuple};
use objects::{PyList, PyTuple};
#[test]
fn test_debug_string() {

View File

@ -48,3 +48,5 @@ extract!(obj to bool; py => {
Ok(try!(obj.cast_as::<PyBool>(py)).is_true())
});
// TODO: mod tests

View File

@ -61,7 +61,7 @@ impl PyDict {
/// Determine if the dictionary contains the specified key.
/// This is equivalent to the Python expression `key in self`.
pub fn contains<K>(&self, key: K, py: Python) -> PyResult<bool> where K: ToPyObject {
pub fn contains<K>(&self, py: Python, key: K) -> PyResult<bool> where K: ToPyObject {
key.with_borrowed_ptr(py, |key| unsafe {
match ffi::PyDict_Contains(self.0.as_ptr(), key) {
1 => Ok(true),
@ -73,7 +73,7 @@ impl PyDict {
/// Gets an item from the dictionary.
/// Returns None if the item is not present, or if an error occurs.
pub fn get_item<K>(&self, key: K, py: Python) -> Option<PyObject> where K: ToPyObject {
pub fn get_item<K>(&self, py: Python, key: K) -> Option<PyObject> where K: ToPyObject {
key.with_borrowed_ptr(py, |key| unsafe {
PyObject::from_borrowed_ptr_opt(py,
ffi::PyDict_GetItem(self.0.as_ptr(), key))
@ -82,7 +82,7 @@ impl PyDict {
/// Sets an item value.
/// This is equivalent to the Python expression `self[key] = value`.
pub fn set_item<K, V>(&self, key: K, value: V, py: Python) -> PyResult<()> where K: ToPyObject, V: ToPyObject {
pub fn set_item<K, V>(&self, py: Python, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject {
key.with_borrowed_ptr(py, move |key|
value.with_borrowed_ptr(py, |value| unsafe {
err::error_on_minusone(py,
@ -92,7 +92,7 @@ impl PyDict {
/// Deletes an item.
/// This is equivalent to the Python expression `del self[key]`.
pub fn del_item<K>(&self, key: K, py: Python) -> PyResult<()> where K: ToPyObject {
pub fn del_item<K>(&self, py: Python, key: K) -> PyResult<()> where K: ToPyObject {
key.with_borrowed_ptr(py, |key| unsafe {
err::error_on_minusone(py,
ffi::PyDict_DelItem(self.0.as_ptr(), key))
@ -135,7 +135,7 @@ impl <K, V> ToPyObject for collections::HashMap<K, V>
fn to_py_object(&self, py: Python) -> PyDict {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key, value, py).unwrap();
dict.set_item(py, key, value).unwrap();
};
dict
}
@ -150,7 +150,7 @@ impl <K, V> ToPyObject for collections::BTreeMap<K, V>
fn to_py_object(&self, py: Python) -> PyDict {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key, value, py).unwrap();
dict.set_item(py, key, value).unwrap();
};
dict
}
@ -183,8 +183,8 @@ mod test {
let mut v = HashMap::new();
v.insert(7, 32);
let dict = v.to_py_object(py);
assert_eq!(true, dict.contains(7i32, py).unwrap());
assert_eq!(false, dict.contains(8i32, py).unwrap());
assert_eq!(true, dict.contains(py, 7i32).unwrap());
assert_eq!(false, dict.contains(py, 8i32).unwrap());
}
#[test]
@ -194,8 +194,8 @@ mod test {
let mut v = HashMap::new();
v.insert(7, 32);
let dict = v.to_py_object(py);
assert_eq!(32, dict.get_item(7i32, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(None, dict.get_item(8i32, py));
assert_eq!(32, dict.get_item(py, 7i32).unwrap().extract::<i32>(py).unwrap());
assert_eq!(None, dict.get_item(py, 8i32));
}
#[test]
@ -205,10 +205,10 @@ mod test {
let mut v = HashMap::new();
v.insert(7, 32);
let dict = v.to_py_object(py);
assert!(dict.set_item(7i32, 42i32, py).is_ok()); // change
assert!(dict.set_item(8i32, 123i32, py).is_ok()); // insert
assert_eq!(42i32, dict.get_item(7i32, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(123i32, dict.get_item(8i32, py).unwrap().extract::<i32>(py).unwrap());
assert!(dict.set_item(py, 7i32, 42i32).is_ok()); // change
assert!(dict.set_item(py, 8i32, 123i32).is_ok()); // insert
assert_eq!(42i32, dict.get_item(py, 7i32).unwrap().extract::<i32>(py).unwrap());
assert_eq!(123i32, dict.get_item(py, 8i32).unwrap().extract::<i32>(py).unwrap());
}
#[test]
@ -218,8 +218,8 @@ mod test {
let mut v = HashMap::new();
v.insert(7, 32);
let dict = v.to_py_object(py);
assert!(dict.set_item(7i32, 42i32, py).is_ok()); // change
assert!(dict.set_item(8i32, 123i32, py).is_ok()); // insert
assert!(dict.set_item(py, 7i32, 42i32).is_ok()); // change
assert!(dict.set_item(py, 8i32, 123i32).is_ok()); // insert
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
assert_eq!(None, v.get(&8i32));
}
@ -232,9 +232,9 @@ mod test {
let mut v = HashMap::new();
v.insert(7, 32);
let dict = v.to_py_object(py);
assert!(dict.del_item(7i32, py).is_ok());
assert!(dict.del_item(py, 7i32).is_ok());
assert_eq!(0, dict.len(py));
assert_eq!(None, dict.get_item(7i32, py));
assert_eq!(None, dict.get_item(py, 7i32));
}
#[test]
@ -244,13 +244,13 @@ mod test {
let mut v = HashMap::new();
v.insert(7, 32);
let dict = v.to_py_object(py);
assert!(dict.del_item(7i32, py).is_ok()); // change
assert!(dict.del_item(py, 7i32).is_ok()); // change
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
}
/*
#[test]
fn test_items_list() {
TODO fn test_items_list() {
let gil = Python::acquire_gil();
let py = gil.python();
let mut v = HashMap::new();

View File

@ -37,7 +37,7 @@ macro_rules! exc_type(
impl PythonObjectWithCheckedDowncast for $name {
#[inline]
fn downcast_from<'p>(obj : PyObject, py: Python<'p>)
fn downcast_from<'p>(py: Python<'p>, obj : PyObject)
-> Result<$name, PythonObjectDowncastError<'p>>
{
unsafe {
@ -50,7 +50,7 @@ macro_rules! exc_type(
}
#[inline]
fn downcast_borrow_from<'a, 'p>(obj: &'a PyObject, py: Python<'p>)
fn downcast_borrow_from<'a, 'p>(py: Python<'p>, obj: &'a PyObject)
-> Result<&'a $name, PythonObjectDowncastError<'p>>
{
unsafe {

View File

@ -52,7 +52,8 @@ impl PyList {
/// Gets the item at the specified index.
///
/// Panics if the index is out of range.
pub fn get_item(&self, index: usize, py: Python) -> PyObject {
pub fn get_item(&self, py: Python, index: usize) -> PyObject {
// TODO: do we really want to panic here?
assert!(index < self.len(py));
unsafe {
PyObject::from_borrowed_ptr(py, ffi::PyList_GetItem(self.0.as_ptr(), index as Py_ssize_t))
@ -62,7 +63,7 @@ impl PyList {
/// Sets the item at the specified index.
///
/// Panics if the index is out of range.
pub fn set_item(&self, index: usize, item: PyObject, _py: Python) {
pub fn set_item(&self, _py: Python, index: usize, item: PyObject) {
let r = unsafe { ffi::PyList_SetItem(self.0.as_ptr(), index as Py_ssize_t, item.steal_ptr()) };
assert!(r == 0);
}
@ -70,7 +71,7 @@ impl PyList {
/// Inserts an item at the specified index.
///
/// Panics if the index is out of range.
pub fn insert_item(&self, index: usize, item: PyObject, _py: Python) {
pub fn insert_item(&self, _py: Python, index: usize, item: PyObject) {
let r = unsafe { ffi::PyList_Insert(self.0.as_ptr(), index as Py_ssize_t, item.as_ptr()) };
assert!(r == 0);
}
@ -98,7 +99,7 @@ impl <'a, 'p> IntoIterator for &'a PyList {
}
/// Used by `impl IntoIterator for &PyList`.
pub struct PyListIterator<'p> {
TODO pub struct PyListIterator<'p> {
list: PyList,
index: usize
}
@ -143,20 +144,20 @@ impl <'prepared, T> ExtractPyObject<'prepared> for Vec<T>
{
type Prepared = Vec<T::Prepared>;
fn prepare_extract(obj: &PyObject, py: Python) -> PyResult<Self::Prepared> {
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
let list = try!(obj.cast_as::<PyList>(py));
let len = list.len(py);
let mut v = Vec::with_capacity(len);
for i in 0 .. len {
v.push(try!(T::prepare_extract(&list.get_item(i, py), py)));
v.push(try!(T::prepare_extract(py, &list.get_item(py, i))));
}
Ok(v)
}
fn extract(prepared: &'prepared Self::Prepared, py: Python) -> PyResult<Vec<T>> {
fn extract(py: Python, prepared: &'prepared Self::Prepared) -> PyResult<Vec<T>> {
let mut v = Vec::with_capacity(prepared.len());
for prepared_elem in prepared {
v.push(try!(T::extract(prepared_elem, py)));
v.push(try!(T::extract(py, prepared_elem)));
}
Ok(v)
}
@ -184,10 +185,10 @@ mod test {
let py = gil.python();
let v = vec![2, 3, 5, 7];
let list = v.to_py_object(py);
assert_eq!(2, list.get_item(0, py).extract::<i32>(py).unwrap());
assert_eq!(3, list.get_item(1, py).extract::<i32>(py).unwrap());
assert_eq!(5, list.get_item(2, py).extract::<i32>(py).unwrap());
assert_eq!(7, list.get_item(3, py).extract::<i32>(py).unwrap());
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
assert_eq!(3, list.get_item(py, 1).extract::<i32>(py).unwrap());
assert_eq!(5, list.get_item(py, 2).extract::<i32>(py).unwrap());
assert_eq!(7, list.get_item(py, 3).extract::<i32>(py).unwrap());
}
#[test]
@ -197,9 +198,9 @@ mod test {
let v = vec![2, 3, 5, 7];
let list = v.to_py_object(py);
let val = 42i32.to_py_object(py).into_object();
assert_eq!(2, list.get_item(0, py).extract::<i32>(py).unwrap());
list.set_item(0, val, py);
assert_eq!(42, list.get_item(0, py).extract::<i32>(py).unwrap());
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
list.set_item(py, 0, val);
assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
}
#[test]
@ -210,16 +211,16 @@ mod test {
let list = v.to_py_object(py);
let val = 42i32.to_py_object(py).into_object();
assert_eq!(4, list.len(py));
assert_eq!(2, list.get_item(0, py).extract::<i32>(py).unwrap());
list.insert_item(0, val, py);
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
list.insert_item(py, 0, val);
assert_eq!(5, list.len(py));
assert_eq!(42, list.get_item(0, py).extract::<i32>(py).unwrap());
assert_eq!(2, list.get_item(1, py).extract::<i32>(py).unwrap());
assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
assert_eq!(2, list.get_item(py, 1).extract::<i32>(py).unwrap());
}
/*
#[test]
fn test_iter() {
fn test_iter() { TODO
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
@ -246,14 +247,14 @@ mod test {
assert_eq!(idx, v.len());
}
*/
/*#[test]
#[test]
fn test_extract() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let list = v.to_py_object(py);
let v2 = list.into_object().extract::<Vec<i32>>().unwrap();
let v2 = list.into_object().extract::<Vec<i32>>(py).unwrap();
assert_eq!(v, v2);
}*/
}
}

View File

@ -102,7 +102,7 @@ macro_rules! pyobject_newtype(
impl ::python::PythonObjectWithCheckedDowncast for $name {
#[inline]
fn downcast_from<'p>(obj: ::objects::object::PyObject, py: ::python::Python<'p>) -> Result<$name, ::python::PythonObjectDowncastError<'p>> {
fn downcast_from<'p>(py: ::python::Python<'p>, obj: ::objects::object::PyObject) -> Result<$name, ::python::PythonObjectDowncastError<'p>> {
unsafe {
if ::ffi::$checkfunction(obj.as_ptr()) != 0 {
Ok($name(obj))
@ -113,7 +113,7 @@ macro_rules! pyobject_newtype(
}
#[inline]
fn downcast_borrow_from<'a, 'p>(obj: &'a ::objects::object::PyObject, py: ::python::Python<'p>) -> Result<&'a $name, ::python::PythonObjectDowncastError<'p>> {
fn downcast_borrow_from<'a, 'p>(py: ::python::Python<'p>, obj: &'a ::objects::object::PyObject) -> Result<&'a $name, ::python::PythonObjectDowncastError<'p>> {
unsafe {
if ::ffi::$checkfunction(obj.as_ptr()) != 0 {
Ok(::std::mem::transmute(obj))
@ -144,11 +144,11 @@ macro_rules! extract(
type Prepared = PyObject;
#[inline]
fn prepare_extract(obj: &PyObject, py: Python) -> PyResult<Self::Prepared> {
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
Ok(::python::PyClone::clone_ref(obj, py))
}
fn extract($obj: &'prepared PyObject, $py: Python) -> PyResult<Self> {
fn extract($py: Python, $obj: &'prepared PyObject) -> PyResult<Self> {
$body
}
}

View File

@ -57,14 +57,14 @@ impl PyModule {
}
}
unsafe fn str_from_ptr<'a>(&'a self, ptr: *const c_char, py: Python) -> PyResult<&'a str> {
if ptr == std::ptr::null() {
unsafe fn str_from_ptr<'a>(&'a self, py: Python, ptr: *const c_char) -> PyResult<&'a str> {
if ptr.is_null() {
Err(PyErr::fetch(py))
} else {
let slice = CStr::from_ptr(ptr).to_bytes();
match std::str::from_utf8(slice) {
Ok(s) => Ok(s),
Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, slice, e)), py))
Err(e) => Err(PyErr::from_instance(py, try!(exc::UnicodeDecodeError::new_utf8(py, slice, e))))
}
}
}
@ -73,35 +73,35 @@ impl PyModule {
///
/// May fail if the module does not have a `__name__` attribute.
pub fn name<'a>(&'a self, py: Python) -> PyResult<&'a str> {
unsafe { self.str_from_ptr(ffi::PyModule_GetName(self.0.as_ptr()), py) }
unsafe { self.str_from_ptr(py, ffi::PyModule_GetName(self.0.as_ptr())) }
}
/// Gets the module filename.
///
/// May fail if the module does not have a `__file__` attribute.
pub fn filename<'a>(&'a self, py: Python) -> PyResult<&'a str> {
unsafe { self.str_from_ptr(ffi::PyModule_GetFilename(self.0.as_ptr()), py) }
unsafe { self.str_from_ptr(py, ffi::PyModule_GetFilename(self.0.as_ptr())) }
}
/// Gets a member from the module.
/// This is equivalent to the Python expression: `getattr(module, name)`
pub fn get(&self, name: &str, py: Python) -> PyResult<PyObject> {
self.as_object().getattr(name, py)
pub fn get(&self, py: Python, name: &str) -> PyResult<PyObject> {
self.as_object().getattr(py, name)
}
/// Calls a function in the module.
/// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
pub fn call<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>, py: Python) -> PyResult<PyObject>
pub fn call<A>(&self, py: Python, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
where A: ToPyObject<ObjectType=PyTuple>
{
try!(self.as_object().getattr(name, py)).call(args, kwargs, py)
try!(self.as_object().getattr(py, name)).call(py, args, kwargs)
}
/// Adds a member to the module.
///
/// This is a convenience function which can be used from the module's initialization function.
pub fn add<V>(&self, name: &str, value: V, py: Python) -> PyResult<()> where V: ToPyObject {
self.as_object().setattr(name, value, py)
pub fn add<V>(&self, py: Python, name: &str, value: V) -> PyResult<()> where V: ToPyObject {
self.as_object().setattr(py, name, value)
}
/// Adds a new extension type to the module.
@ -109,9 +109,9 @@ impl PyModule {
/// This is a convenience function that creates a new `PyRustTypeBuilder` and
/// sets `new_type.__module__` to this module's name.
/// The new type will be added to this module when `finish()` is called on the builder.
pub fn add_type<'p, T>(&self, name: &str, py: Python<'p>) -> ::rustobject::typebuilder::PyRustTypeBuilder<'p, T>
pub fn add_type<'p, T>(&self, py: Python<'p>, name: &str) -> ::rustobject::typebuilder::PyRustTypeBuilder<'p, T>
where T: 'static + Send {
::rustobject::typebuilder::new_typebuilder_for_module(self, name, py)
::rustobject::typebuilder::new_typebuilder_for_module(py, self, name)
}
}

View File

@ -196,12 +196,12 @@ macro_rules! int_convert_u64_or_i64 (
type Prepared = PyObject;
#[inline]
fn prepare_extract(obj: &PyObject, py: Python) -> PyResult<Self::Prepared> {
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
Ok(obj.clone_ref(py))
}
#[cfg(feature="python27-sys")]
fn extract(obj: &'prepared PyObject, py: Python) -> PyResult<$rust_type> {
fn extract(py: Python, obj: &'prepared PyObject) -> PyResult<$rust_type> {
let ptr = obj.as_ptr();
unsafe {
@ -220,7 +220,7 @@ macro_rules! int_convert_u64_or_i64 (
}
#[cfg(feature="python3-sys")]
fn extract(obj: &'prepared PyObject, py: Python) -> PyResult<$rust_type> {
fn extract(py: Python, obj: &'prepared PyObject) -> PyResult<$rust_type> {
let ptr = obj.as_ptr();
unsafe {
if ffi::PyLong_Check(ptr) != 0 {

View File

@ -25,17 +25,20 @@ use err::PyResult;
/// Represents a reference to a Python object.
///
/// Python objects are reference counted.
/// Calling `clone()` on a `PyObject` will return a new reference to the same object
/// Calling `clone_ref()` on a `PyObject` will return a new reference to the same object
/// (thus incrementing the reference count).
/// The `Drop` implementation will decrement the reference count.
/// The `Drop` implementation will automatically decrement the reference count.
/// You can also call `release_ref()` to explicitly decrement the reference count.
/// This is slightly faster than relying on automatic drop, because `release_ref`
/// does not need to check whether the GIL needs to be acquired.
///
/// `PyObject` can be used with all Python objects, since all python types
/// derive from `object`. This crate also contains other, more specific types
/// that serve as references to Python objects (e.g. `PyTuple` for Python tuples, etc.).
///
/// You can convert from any Python object to `PyObject` by calling `as_object()` or `into_object`
/// You can convert from any Python object to `PyObject` by calling `as_object()` or `into_object()`
/// from the [PythonObject trait](trait.PythonObject.html).
/// In the other direction, you can call `cast_as` or `cast_into`
/// In the other direction, you can call `cast_as()` or `cast_into()`
/// on `PyObject` to convert to more specific object types.
///
/// Most of the interesting methods are provided by the [ObjectProtocol trait](trait.ObjectProtocol.html).
@ -85,12 +88,12 @@ impl PythonObject for PyObject {
impl PythonObjectWithCheckedDowncast for PyObject {
#[inline]
fn downcast_from<'p>(obj: PyObject, _py: Python<'p>) -> Result<PyObject, PythonObjectDowncastError<'p>> {
fn downcast_from<'p>(_py: Python<'p>, obj: PyObject) -> Result<PyObject, PythonObjectDowncastError<'p>> {
Ok(obj)
}
#[inline]
fn downcast_borrow_from<'a, 'p>(obj: &'a PyObject, _py: Python<'p>) -> Result<&'a PyObject, PythonObjectDowncastError<'p>> {
fn downcast_borrow_from<'a, 'p>(_py: Python<'p>, obj: &'a PyObject) -> Result<&'a PyObject, PythonObjectDowncastError<'p>> {
Ok(obj)
}
}
@ -209,7 +212,7 @@ impl PyObject {
pub fn cast_into<'p, T>(self, py: Python<'p>) -> Result<T, PythonObjectDowncastError<'p>>
where T: PythonObjectWithCheckedDowncast
{
PythonObjectWithCheckedDowncast::downcast_from(self, py)
PythonObjectWithCheckedDowncast::downcast_from(py, self)
}
/// Casts the PyObject to a concrete Python object type.
@ -229,7 +232,7 @@ impl PyObject {
pub fn cast_as<'s, 'p, T>(&'s self, py: Python<'p>) -> Result<&'s T, PythonObjectDowncastError<'p>>
where T: PythonObjectWithCheckedDowncast
{
PythonObjectWithCheckedDowncast::downcast_borrow_from(self, py)
PythonObjectWithCheckedDowncast::downcast_borrow_from(py, self)
}
/// Extracts some type from the Python object.
@ -238,8 +241,8 @@ impl PyObject {
pub fn extract<T>(&self, py: Python) -> PyResult<T>
where T: for<'prep> ::conversion::ExtractPyObject<'prep>
{
let prepared = try!(<T as ::conversion::ExtractPyObject>::prepare_extract(self, py));
<T as ::conversion::ExtractPyObject>::extract(&prepared, py)
let prepared = try!(<T as ::conversion::ExtractPyObject>::prepare_extract(py, self));
<T as ::conversion::ExtractPyObject>::extract(py, &prepared)
}
}

View File

@ -40,13 +40,13 @@ pyobject_newtype!(PyInstance, PyInstance_Check, PyInstance_Type);
impl PyClass {
/// Return true if self is a subclass of base.
pub fn is_subclass_of(&self, base: &PyClass, _py: Python) -> bool {
pub fn is_subclass_of(&self, _py: Python, base: &PyClass) -> bool {
unsafe { ffi::PyClass_IsSubclass(self.as_ptr(), base.as_ptr()) != 0 }
}
/// Create a new instance of the class.
/// The parameters args and kw are used as the positional and keyword parameters to the objects constructor.
pub fn create_instance<T>(&self, args: T, kw: Option<&PyDict>, py: Python) -> PyResult<PyInstance>
pub fn create_instance<T>(&self, py: Python, args: T, kw: Option<&PyDict>) -> PyResult<PyInstance>
where T: ToPyObject<ObjectType=PyTuple>
{
args.with_borrowed_ptr(py, |args| unsafe {
@ -57,7 +57,7 @@ impl PyClass {
/// Create a new instance of a specific class without calling its constructor.
/// The dict parameter will be used as the objects __dict__.
pub fn create_instance_raw(&self, dict: &PyDict, py: Python) -> PyResult<PyInstance> {
pub fn create_instance_raw(&self, py: Python, dict: &PyDict) -> PyResult<PyInstance> {
unsafe {
err::result_cast_from_owned_ptr(py,
ffi::PyInstance_NewRaw(self.as_ptr(), dict.as_object().as_ptr()))

View File

@ -43,7 +43,7 @@ impl PySequence {
/// Return the concatenation of o1 and o2. Equivalent to python `o1 + o2`
#[inline]
pub fn concat(&self, other: &PySequence, py: Python) -> PyResult<PyObject> {
pub fn concat(&self, py: Python, other: &PySequence) -> PyResult<PyObject> {
unsafe {
err::result_from_owned_ptr(py, ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))
}
@ -53,7 +53,7 @@ impl PySequence {
/// Equivalent to python `o * count`
/// NB: Python accepts negative counts; it returns an empty Sequence.
#[inline]
pub fn repeat(&self, count: isize, py: Python) -> PyResult<PyObject> {
pub fn repeat(&self, py: Python, count: isize) -> PyResult<PyObject> {
unsafe {
err::result_from_owned_ptr(py, ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))
}
@ -61,7 +61,7 @@ impl PySequence {
/// Return the concatenation of o1 and o2 on success. Equivalent to python `o1 += o2`
#[inline]
pub fn in_place_concat(&self, other: &PySequence, py: Python) -> PyResult<PyObject> {
pub fn in_place_concat(&self, py: Python, other: &PySequence) -> PyResult<PyObject> {
unsafe {
result_from_owned_ptr(py, ffi::PySequence_InPlaceConcat(self.as_ptr(), other.as_ptr()))
}
@ -71,7 +71,7 @@ impl PySequence {
/// Equivalent to python `o *= count`
/// NB: Python accepts negative counts; it empties the Sequence.
#[inline]
pub fn in_place_repeat(&self, count: isize, py: Python) -> PyResult<PyObject> {
pub fn in_place_repeat(&self, py: Python, count: isize) -> PyResult<PyObject> {
unsafe {
result_from_owned_ptr(py,
ffi::PySequence_InPlaceRepeat(self.as_ptr(), count as Py_ssize_t))
@ -80,7 +80,7 @@ impl PySequence {
/// Return the ith element of the Sequence. Equivalent to python `o[index]`
#[inline]
pub fn get_item(&self, index: isize, py: Python) -> PyResult<PyObject> {
pub fn get_item(&self, py: Python, index: isize) -> PyResult<PyObject> {
unsafe {
result_from_owned_ptr(py,
ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t))
@ -90,7 +90,7 @@ impl PySequence {
/// Return the slice of sequence object o between begin and end.
/// This is the equivalent of the Python expression `o[begin:end]`
#[inline]
pub fn get_slice(&self, begin : isize, end : isize, py: Python) -> PyResult<PyObject> {
pub fn get_slice(&self, py: Python, begin : isize, end : isize) -> PyResult<PyObject> {
unsafe {
result_from_owned_ptr(py,
ffi::PySequence_GetSlice(self.as_ptr(), begin as Py_ssize_t, end as Py_ssize_t))
@ -100,7 +100,7 @@ impl PySequence {
/// Assign object v to the ith element of o.
/// Equivalent to Python statement `o[i] = v`
#[inline]
pub fn set_item(&self, i: isize, v: &PyObject, py: Python) -> PyResult<()> {
pub fn set_item(&self, py: Python, i: isize, v: &PyObject) -> PyResult<()> {
unsafe {
err::error_on_minusone(py,
ffi::PySequence_SetItem(self.as_ptr(), i as Py_ssize_t, v.as_ptr()))
@ -110,7 +110,7 @@ impl PySequence {
/// Delete the ith element of object o.
/// Python statement `del o[i]`
#[inline]
pub fn del_item(&self, i: isize, py: Python) -> PyResult<()> {
pub fn del_item(&self, py: Python, i: isize) -> PyResult<()> {
unsafe {
err::error_on_minusone(py,
ffi::PySequence_DelItem(self.as_ptr(), i as Py_ssize_t))
@ -120,7 +120,7 @@ impl PySequence {
/// Assign the sequence object v to the slice in sequence object o from i1 to i2.
/// This is the equivalent of the Python statement `o[i1:i2] = v`
#[inline]
pub fn set_slice(&self, i1: isize, i2: isize, v: &PyObject, py: Python) -> PyResult<()> {
pub fn set_slice(&self, py: Python, i1: isize, i2: isize, v: &PyObject) -> PyResult<()> {
unsafe {
err::error_on_minusone(py,
ffi::PySequence_SetSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t, v.as_ptr()))
@ -130,7 +130,7 @@ impl PySequence {
/// Delete the slice in sequence object o from i1 to i2.
/// equivalent of the Python statement `del o[i1:i2]`
#[inline]
pub fn del_slice(&self, i1: isize, i2: isize, py: Python) -> PyResult<()> {
pub fn del_slice(&self, py: Python, i1: isize, i2: isize) -> PyResult<()> {
unsafe {
err::error_on_minusone(py,
ffi::PySequence_DelSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t))
@ -140,7 +140,7 @@ impl PySequence {
/// Return the number of occurrences of value in o, that is, return the number of keys for
/// which `o[key] == value`
#[inline]
pub fn count<V>(&self, value: V, py: Python) -> PyResult<usize>
pub fn count<V>(&self, py: Python, value: V) -> PyResult<usize>
where V: ToPyObject
{
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
@ -155,7 +155,7 @@ impl PySequence {
/// Determine if o contains value. this is equivalent to the Python expression `value in o`
#[inline]
pub fn contains<V>(&self, value: V, py: Python) -> PyResult<bool>
pub fn contains<V>(&self, py: Python, value: V) -> PyResult<bool>
where V: ToPyObject
{
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
@ -171,7 +171,7 @@ impl PySequence {
/// Return the first index i for which o[i] == value.
/// This is equivalent to the Python expression `o.index(value)`
#[inline]
pub fn index<V>(&self, value: V, py: Python) -> PyResult<usize>
pub fn index<V>(&self, py: Python, value: V) -> PyResult<usize>
where V: ToPyObject
{
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
@ -233,7 +233,7 @@ impl <'p> Iterator for PySequenceIterator<'p> {
// can't report any errors in underlying size check so we panic.
let len = self.sequence.len(self.py).unwrap();
if self.index < len {
match self.sequence.get_item(self.index, self.py) {
match self.sequence.get_item(self.py, self.index) {
Ok(item) => {
self.index += 1;
Some(item)
@ -277,7 +277,7 @@ mod test {
assert_eq!(0, seq.len(py).unwrap());
let needle = 7i32.to_py_object(py).into_object();
assert_eq!(false, seq.contains(&needle, py).unwrap());
assert_eq!(false, seq.contains(py, &needle).unwrap());
}
#[test]
@ -289,13 +289,13 @@ mod test {
assert_eq!(6, seq.len(py).unwrap());
let bad_needle = 7i32.to_py_object(py).into_object();
assert_eq!(false, seq.contains(&bad_needle, py).unwrap());
assert_eq!(false, seq.contains(py, &bad_needle).unwrap());
let good_needle = 8i32.to_py_object(py).into_object();
assert_eq!(true, seq.contains(&good_needle, py).unwrap());
assert_eq!(true, seq.contains(py, &good_needle).unwrap());
let type_coerced_needle = 8f32.to_py_object(py).into_object();
assert_eq!(true, seq.contains(&type_coerced_needle, py).unwrap());
assert_eq!(true, seq.contains(py, &type_coerced_needle).unwrap());
}
#[test]
@ -304,18 +304,18 @@ mod test {
let py = gil.python();
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
assert_eq!(1, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(1, seq.get_item(1, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(2, seq.get_item(2, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(3, seq.get_item(3, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(5, seq.get_item(4, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(8, seq.get_item(5, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(8, seq.get_item(-1, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(5, seq.get_item(-2, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(3, seq.get_item(-3, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(2, seq.get_item(-4, py).unwrap().extract::<i32>(py).unwrap());
assert_eq!(1, seq.get_item(-5, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.get_item(10, py).is_err());
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert_eq!(1, seq.get_item(py, 1).unwrap().extract::<i32>(py).unwrap());
assert_eq!(2, seq.get_item(py, 2).unwrap().extract::<i32>(py).unwrap());
assert_eq!(3, seq.get_item(py, 3).unwrap().extract::<i32>(py).unwrap());
assert_eq!(5, seq.get_item(py, 4).unwrap().extract::<i32>(py).unwrap());
assert_eq!(8, seq.get_item(py, 5).unwrap().extract::<i32>(py).unwrap());
assert_eq!(8, seq.get_item(py, -1).unwrap().extract::<i32>(py).unwrap());
assert_eq!(5, seq.get_item(py, -2).unwrap().extract::<i32>(py).unwrap());
assert_eq!(3, seq.get_item(py, -3).unwrap().extract::<i32>(py).unwrap());
assert_eq!(2, seq.get_item(py, -4).unwrap().extract::<i32>(py).unwrap());
assert_eq!(1, seq.get_item(py, -5).unwrap().extract::<i32>(py).unwrap());
assert!(seq.get_item(py, 10).is_err());
}
// fn test_get_slice() {}
@ -328,21 +328,21 @@ mod test {
let py = gil.python();
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
assert!(seq.del_item(10, py).is_err());
assert_eq!(1, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(0, py).is_ok());
assert_eq!(1, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(0, py).is_ok());
assert_eq!(2, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(0, py).is_ok());
assert_eq!(3, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(0, py).is_ok());
assert_eq!(5, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(0, py).is_ok());
assert_eq!(8, seq.get_item(0, py).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(0, py).is_ok());
assert!(seq.del_item(py, 10).is_err());
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(py, 0).is_ok());
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(py, 0).is_ok());
assert_eq!(2, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(py, 0).is_ok());
assert_eq!(3, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(py, 0).is_ok());
assert_eq!(5, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(py, 0).is_ok());
assert_eq!(8, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
assert!(seq.del_item(py, 0).is_ok());
assert_eq!(0, seq.len(py).unwrap());
assert!(seq.del_item(0, py).is_err());
assert!(seq.del_item(py, 0).is_err());
}
#[test]
@ -351,12 +351,12 @@ mod test {
let py = gil.python();
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
assert_eq!(0, seq.index(1i32, py).unwrap());
assert_eq!(2, seq.index(2i32, py).unwrap());
assert_eq!(3, seq.index(3i32, py).unwrap());
assert_eq!(4, seq.index(5i32, py).unwrap());
assert_eq!(5, seq.index(8i32, py).unwrap());
assert!(seq.index(42i32, py).is_err());
assert_eq!(0, seq.index(py, 1i32).unwrap());
assert_eq!(2, seq.index(py, 2i32).unwrap());
assert_eq!(3, seq.index(py, 3i32).unwrap());
assert_eq!(4, seq.index(py, 5i32).unwrap());
assert_eq!(5, seq.index(py, 8i32).unwrap());
assert!(seq.index(py, 42i32).is_err());
}
#[test]
@ -365,17 +365,17 @@ mod test {
let py = gil.python();
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
assert_eq!(2, seq.count(1i32, py).unwrap());
assert_eq!(1, seq.count(2i32, py).unwrap());
assert_eq!(1, seq.count(3i32, py).unwrap());
assert_eq!(1, seq.count(5i32, py).unwrap());
assert_eq!(1, seq.count(8i32, py).unwrap());
assert_eq!(0, seq.count(42i32, py).unwrap());
assert_eq!(2, seq.count(py, 1i32).unwrap());
assert_eq!(1, seq.count(py, 2i32).unwrap());
assert_eq!(1, seq.count(py, 3i32).unwrap());
assert_eq!(1, seq.count(py, 5i32).unwrap());
assert_eq!(1, seq.count(py, 8i32).unwrap());
assert_eq!(0, seq.count(py, 42i32).unwrap());
}
/*
#[test]
fn test_seq_iter() {
fn test_seq_iter() { TODO
let gil = Python::acquire_gil();
let py = gil.python();
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
@ -411,10 +411,10 @@ mod test {
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
let bad_needle = "blurst".to_py_object(py);
assert_eq!(false, seq.contains(bad_needle, py).unwrap());
assert_eq!(false, seq.contains(py, bad_needle).unwrap());
let good_needle = "worst".to_py_object(py);
assert_eq!(true, seq.contains(good_needle, py).unwrap());
assert_eq!(true, seq.contains(py, good_needle).unwrap());
}
#[test]
@ -423,7 +423,7 @@ mod test {
let py = gil.python();
let v : Vec<i32> = vec![1, 2, 3];
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
let concat_seq = seq.concat(&seq, py).unwrap().cast_into::<PySequence>(py).unwrap();
let concat_seq = seq.concat(py, &seq).unwrap().cast_into::<PySequence>(py).unwrap();
assert_eq!(6, concat_seq.len(py).unwrap());
let concat_v : Vec<i32> = vec![1, 2, 3, 1, 2, 3];
for (el, cc) in seq.into_iter(py).zip(concat_v) {
@ -437,7 +437,7 @@ mod test {
let py = gil.python();
let v = "string";
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
let concat_seq = seq.concat(&seq, py).unwrap().cast_into::<PySequence>(py).unwrap();
let concat_seq = seq.concat(py, &seq).unwrap().cast_into::<PySequence>(py).unwrap();
assert_eq!(12, concat_seq.len(py).unwrap());
/*let concat_v = "stringstring".to_owned();
for (el, cc) in seq.into_iter(py).zip(concat_v.chars()) {
@ -451,7 +451,7 @@ mod test {
let py = gil.python();
let v = vec!["foo", "bar"];
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
let repeat_seq = seq.repeat(3, py).unwrap().cast_into::<PySequence>(py).unwrap();
let repeat_seq = seq.repeat(py, 3).unwrap().cast_into::<PySequence>(py).unwrap();
assert_eq!(6, repeat_seq.len(py).unwrap());
let repeated = vec!["foo", "bar", "foo", "bar", "foo", "bar"];
for (el, rpt) in seq.into_iter(py).zip(repeated.iter()) {

View File

@ -99,7 +99,7 @@ impl PyUnicode {
};
match str::from_utf8(bytes.as_slice(py)) {
Ok(s) => Ok(Cow::Owned(s.to_owned())),
Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, bytes.as_slice(py), e)), py))
Err(e) => Err(PyErr::from_instance(py, try!(exc::UnicodeDecodeError::new_utf8(py, bytes.as_slice(py), e))))
}
}
@ -137,7 +137,7 @@ impl PyUnicode {
let bytes = try!(self.to_utf8_bytes(py));
match str::from_utf8(bytes) {
Ok(s) => Ok(Cow::Borrowed(s)),
Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, bytes, e)), py))
Err(e) => Err(PyErr::from_instance(py, try!(exc::UnicodeDecodeError::new_utf8(py, bytes, e))))
}
}
@ -164,7 +164,7 @@ impl PyString {
/// Returns `TypeError` if the input is not one of the accepted types.
/// Returns `UnicodeDecodeError` if the input is not valid unicode.
#[cfg(feature="python27-sys")]
pub fn extract<'a>(o: &'a PyObject, py: Python) -> PyResult<Cow<'a, str>> {
pub fn extract<'a>(py: Python, o: &'a PyObject) -> PyResult<Cow<'a, str>> {
if let Ok(s) = o.cast_as::<PyBytes>(py) {
s.to_string(py)
} else if let Ok(u) = o.cast_as::<PyUnicode>(py) {
@ -184,7 +184,7 @@ impl PyString {
/// Returns `TypeError` if the input is not one of the accepted types.
/// Any invalid code points are replaced with U+FFFD REPLACEMENT CHARACTER.
#[cfg(feature="python27-sys")]
pub fn extract_lossy<'a>(o: &'a PyObject, py: Python) -> PyResult<Cow<'a, str>> {
pub fn extract_lossy<'a>(py: Python, o: &'a PyObject) -> PyResult<Cow<'a, str>> {
if let Ok(s) = o.cast_as::<PyBytes>(py) {
Ok(s.to_string_lossy(py))
} else if let Ok(u) = o.cast_as::<PyUnicode>(py) {
@ -204,7 +204,7 @@ impl PyString {
/// Returns `TypeError` if the input is not one of the accepted types.
/// Returns `UnicodeDecodeError` if the input is not valid unicode.
#[cfg(feature="python3-sys")]
pub fn extract<'a>(o: &'a PyObject, py: Python) -> PyResult<Cow<'a, str>> {
pub fn extract<'a>(py: Python, o: &'a PyObject) -> PyResult<Cow<'a, str>> {
if let Ok(u) = o.cast_as::<PyUnicode>(py) {
u.to_string(py)
} else {
@ -222,7 +222,7 @@ impl PyString {
/// Returns `TypeError` if the input is not one of the accepted types.
/// Any invalid code points are replaced with U+FFFD REPLACEMENT CHARACTER.
#[cfg(feature="python3-sys")]
pub fn extract_lossy<'a>(o: &'a PyObject, py: Python) -> PyResult<Cow<'a, str>> {
pub fn extract_lossy<'a>(py: Python, o: &'a PyObject) -> PyResult<Cow<'a, str>> {
if let Ok(u) = o.cast_as::<PyUnicode>(py) {
Ok(u.to_string_lossy(py))
} else {
@ -243,7 +243,7 @@ impl PyString {
pub fn to_string(&self, py: Python) -> PyResult<Cow<str>> {
match str::from_utf8(self.as_slice(py)) {
Ok(s) => Ok(Cow::Borrowed(s)),
Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, self.as_slice(py), e)), py))
Err(e) => Err(PyErr::from_instance(py, try!(exc::UnicodeDecodeError::new_utf8(py, self.as_slice(py), e))))
}
}
@ -312,14 +312,14 @@ impl ToPyObject for String {
/// Accepts Python `str` and `unicode` objects.
/// In Python 2.7, `str` is expected to be UTF-8 encoded.
extract!(obj to String; py => {
PyString::extract(obj, py).map(|s| s.into_owned())
PyString::extract(py, obj).map(|s| s.into_owned())
});
/// Allows extracting strings from Python objects.
/// Accepts Python `str` and `unicode` objects.
/// In Python 2.7, `str` is expected to be UTF-8 encoded.
extract!(obj to Cow<'prepared, str>; py => {
PyString::extract(obj, py)
PyString::extract(py, obj)
});
enum PreparedString {
@ -330,18 +330,18 @@ enum PreparedString {
impl <'prepared> ExtractPyObject<'prepared> for &'prepared str {
type Prepared = PreparedString;
fn prepare_extract(obj: &PyObject, py: Python) -> PyResult<Self::Prepared> {
match try!(PyString::extract(obj, py)) {
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
match try!(PyString::extract(py, obj)) {
Cow::Owned(s) => Ok(PreparedString::Extracted(s)),
Cow::Borrowed(_) => Ok(PreparedString::BorrowFrom(obj.clone_ref(py)))
}
}
fn extract(prepared: &'prepared PreparedString, py: Python) -> PyResult<Self> {
fn extract(py: Python, prepared: &'prepared PreparedString) -> PyResult<Self> {
match *prepared {
PreparedString::Extracted(ref s) => Ok(s),
PreparedString::BorrowFrom(ref obj) => {
match try!(PyString::extract(obj, py)) {
match try!(PyString::extract(py, obj)) {
Cow::Owned(_) => panic!("Failed to borrow from python object"),
Cow::Borrowed(s) => Ok(s)
}
@ -370,8 +370,8 @@ mod test {
let py = gil.python();
let s = "Hello Python";
let py_string = s.to_py_object(py).into_object();
let prepared = <&str>::prepare_extract(&py_string, py).unwrap();
assert_eq!(s, <&str>::extract(&prepared, py).unwrap());
let prepared = <&str>::prepare_extract(py, &py_string).unwrap();
assert_eq!(s, <&str>::extract(py, &prepared).unwrap());
}
}

View File

@ -19,6 +19,7 @@
use {Python, PyDict, ToPyObject, PyInt};
use std::collections::{BTreeMap, HashMap};
// TODO: move these tests into the dict module
#[test]
fn test_hashmap_to_python() {
let gil = Python::acquire_gil();
@ -30,7 +31,7 @@ fn test_hashmap_to_python() {
let py_map = map.to_py_object(py);
assert!(py_map.len(py) == 1);
assert!( py_map.get_item(1, py).unwrap().extract::<i32>(py).unwrap() == 1);
assert!( py_map.get_item(py, 1).unwrap().extract::<i32>(py).unwrap() == 1);
}
#[test]
@ -44,6 +45,6 @@ fn test_btreemap_to_python() {
let py_map = map.to_py_object(py);
assert!(py_map.len(py) == 1);
assert!( py_map.get_item(1, py).unwrap().extract::<i32>(py).unwrap() == 1);
assert!( py_map.get_item(py, 1).unwrap().extract::<i32>(py).unwrap() == 1);
}

View File

@ -53,7 +53,7 @@ impl PyTuple {
/// Gets the length of the tuple.
#[inline]
pub fn len(&self) -> usize {
// Safe despite not taking a `Python`, because tuples are immutable.
// Safe despite not taking a `Python` token, because tuples are immutable.
unsafe {
// non-negative Py_ssize_t should always fit into Rust uint
ffi::PyTuple_GET_SIZE(self.0.as_ptr()) as usize
@ -63,7 +63,9 @@ impl PyTuple {
/// Gets the item at the specified index.
///
/// Panics if the index is out of range.
pub fn get_item(&self, index: usize, py: Python) -> PyObject {
pub fn get_item(&self, py: Python, index: usize) -> PyObject {
// TODO: reconsider whether we should panic
// It's quite inconsistent that this method takes `Python` when `len()` does not.
assert!(index < self.len());
unsafe {
PyObject::from_borrowed_ptr(py, ffi::PyTuple_GET_ITEM(self.0.as_ptr(), index as Py_ssize_t))
@ -84,8 +86,10 @@ impl PyTuple {
}
}
// TODO impl Index for PyTuple
/*
impl IntoIterator for PyTuple {
impl IntoIterator for PyTuple { TODO
type Item = PyObject;
type IntoIter = PyTupleIterator;
@ -140,7 +144,7 @@ impl <'p> ExactSizeIterator for PyTupleIterator<'p> {
}
*/
fn wrong_tuple_length(t: &PyTuple, expected_length: usize, py: Python) -> PyErr {
fn wrong_tuple_length(py: Python, t: &PyTuple, expected_length: usize) -> PyErr {
let msg = format!("Expected tuple of length {}, but got tuple of length {}.", expected_length, t.len());
PyErr::new_lazy_init(py.get_type::<exc::ValueError>(), Some(msg.to_py_object(py).into_object()))
}
@ -203,7 +207,7 @@ tuple_conversion!(9, (ref0, 0, A), (ref1, 1, B), (ref2, 2, C), (ref3, 3, D),
/// let gil_guard = cpython::Python::acquire_gil();
/// let py = gil_guard.python();
/// let os = py.import("os").unwrap();
/// let pid = os.call("get_pid", cpython::NoArgs, None, py);
/// let pid = os.call(py, "get_pid", cpython::NoArgs, None);
/// ```
#[derive(Copy, Clone, Debug)]
pub struct NoArgs;
@ -224,7 +228,7 @@ extract!(obj to NoArgs; py => {
if t.len() == 0 {
Ok(NoArgs)
} else {
Err(wrong_tuple_length(t, 0, py))
Err(wrong_tuple_length(py, t, 0))
}
});

View File

@ -35,28 +35,29 @@ impl PyType {
}
/// Retrieves the PyType instance for the given FFI pointer.
/// This increments the reference count on the type object.
/// Undefined behavior if the pointer is NULL or invalid.
#[inline]
pub unsafe fn from_type_ptr(py: Python, p: *mut ffi::PyTypeObject) -> PyType {
PyObject::from_borrowed_ptr(py, p as *mut ffi::PyObject).unchecked_cast_into::<PyType>()
}
/// Return true if self is a subtype of b.
/// Return true if `self` is a subtype of `b`.
#[inline]
pub fn is_subtype_of(&self, b : &PyType, _: Python) -> bool {
pub fn is_subtype_of(&self, _: Python, b : &PyType) -> bool {
unsafe { ffi::PyType_IsSubtype(self.as_type_ptr(), b.as_type_ptr()) != 0 }
}
/// Return true if obj is an instance of self.
/// Return true if `obj` is an instance of `self`.
#[inline]
pub fn is_instance(&self, obj : &PyObject, _: Python) -> bool {
pub fn is_instance(&self, _: Python, obj : &PyObject) -> bool {
unsafe { ffi::PyObject_TypeCheck(obj.as_ptr(), self.as_type_ptr()) != 0 }
}
/// Calls the type object, thus creating a new instance.
/// This is equivalent to the Python expression: `self(*args, **kwargs)`
#[inline]
pub fn call<A>(&self, args: A, kwargs: Option<&PyDict>, py: Python) -> PyResult<PyObject>
pub fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
where A: ToPyObject<ObjectType=PyTuple>
{
args.with_borrowed_ptr(py, |args| unsafe {

View File

@ -61,10 +61,10 @@ pub struct PythonObjectDowncastError<'p>(pub Python<'p>);
/// Trait implemented by Python object types that allow a checked downcast.
pub trait PythonObjectWithCheckedDowncast : PythonObject {
/// Cast from PyObject to a concrete Python object type.
fn downcast_from<'p>(PyObject, Python<'p>) -> Result<Self, PythonObjectDowncastError<'p>>;
fn downcast_from<'p>(Python<'p>, PyObject) -> Result<Self, PythonObjectDowncastError<'p>>;
/// Cast from PyObject to a concrete Python object type.
fn downcast_borrow_from<'a, 'p>(&'a PyObject, Python<'p>) -> Result<&'a Self, PythonObjectDowncastError<'p>>;
fn downcast_borrow_from<'a, 'p>(Python<'p>, &'a PyObject) -> Result<&'a Self, PythonObjectDowncastError<'p>>;
}
/// Trait implemented by Python object types that have a corresponding type object.
@ -318,7 +318,7 @@ mod test {
let d = PyDict::new(py);
d.set_item("foo", 13, py).unwrap();
d.set_item(py, "foo", 13).unwrap();
// Inject our own local namespace
let v: i32 = py.eval("foo + 29", None, Some(&d)).unwrap().extract(py).unwrap();

View File

@ -54,8 +54,8 @@ use err;
/// let multiplier_type = PyRustTypeBuilder::<i32>::new(py, "Multiplier")
/// .add("mul", py_method!(mul(arg: i32)))
/// .finish().unwrap();
/// let obj = multiplier_type.create_instance(3, (), py).into_object();
/// let result = obj.call_method("mul", &(4,), None, py).unwrap().extract::<i32>(py).unwrap();
/// let obj = multiplier_type.create_instance(py, 3, ()).into_object();
/// let result = obj.call_method(py, "mul", &(4,), None).unwrap().extract::<i32>(py).unwrap();
/// assert_eq!(result, 12);
/// }
/// ```
@ -127,7 +127,7 @@ macro_rules! py_method {
None => None
};
let ret: $crate::PyResult<_> =
py_argparse!(Some(stringify!($f)), &args, kwargs.as_ref(), py,
py_argparse!(py, Some(stringify!($f)), &args, kwargs.as_ref(),
( $($pname : $ptype),* ) { $f( py, &slf, $($pname),* ) });
$crate::PyDrop::release_ref(kwargs, py);
$crate::PyDrop::release_ref(args, py);
@ -233,7 +233,7 @@ pub mod py_method_impl {
impl <T> TypeMember<T> for MethodDescriptor<T> where T: PythonObject {
#[inline]
fn to_descriptor(&self, ty: &PyType, _name: &str, py: Python) -> PyObject {
fn to_descriptor(&self, py: Python, ty: &PyType, _name: &str) -> PyObject {
unsafe {
err::from_owned_ptr_or_panic(py,
ffi::PyDescr_NewMethod(ty.as_type_ptr(), self.0))
@ -250,7 +250,7 @@ impl <T> TypeMember<T> for MethodDescriptor<T> where T: PythonObject {
/// Creates a Python class method descriptor that invokes a Rust function.
///
/// As arguments, takes the name of a rust function with the signature
/// `fn(&PyType, &PyTuple, Python) -> PyResult<T>`
/// `fn(Python, &PyType, &PyTuple, Option<&PyDict>) -> PyResult<T>`
/// for some `T` that implements `ToPyObject`.
///
/// Returns a type that implements `typebuilder::TypeMember<PyRustObject<_>>`
@ -261,9 +261,8 @@ impl <T> TypeMember<T> for MethodDescriptor<T> where T: PythonObject {
/// #![feature(plugin)]
/// #![plugin(interpolate_idents)]
/// #[macro_use] extern crate cpython;
/// use cpython::{Python, PythonObject, PyResult, PyErr, ObjectProtocol,
/// PyTuple, PyType, PyRustTypeBuilder, NoArgs};
/// use cpython::{exc};
/// use cpython::{Python, PythonObject, PyResult, ObjectProtocol,
/// PyRustTypeBuilder, NoArgs};
///
/// fn method(py: Python) -> PyResult<i32> {
/// Ok(42)
@ -275,7 +274,7 @@ impl <T> TypeMember<T> for MethodDescriptor<T> where T: PythonObject {
/// let my_type = PyRustTypeBuilder::<i32>::new(py, "MyType")
/// .add("method", py_class_method!(method()))
/// .finish().unwrap();
/// let result = my_type.as_object().call_method("method", NoArgs, None, py).unwrap();
/// let result = my_type.as_object().call_method(py, "method", NoArgs, None).unwrap();
/// assert_eq!(42, result.extract::<i32>(py).unwrap());
/// }
/// ```
@ -298,7 +297,7 @@ macro_rules! py_class_method {
Some(kwargs) => Some(<$crate::PyDict as $crate::PythonObject>::unchecked_downcast_from(kwargs)),
None => None
};
let ret: $crate::PyResult<_> = $f(&slf, &args, kwargs.as_ref(), py);
let ret: $crate::PyResult<_> = $f(py, &slf, &args, kwargs.as_ref());
$crate::PyDrop::release_ref(kwargs, py);
$crate::PyDrop::release_ref(args, py);
$crate::PyDrop::release_ref(slf, py);
@ -349,7 +348,7 @@ macro_rules! py_class_method {
None => None
};
let ret: $crate::PyResult<_> =
py_argparse!(Some(stringify!($f)), &args, kwargs.as_ref(), py,
py_argparse!(py, Some(stringify!($f)), &args, kwargs.as_ref(),
( $($pname : $ptype),* ) { $f( py, $($pname),* ) });
$crate::PyDrop::release_ref(kwargs, py);
$crate::PyDrop::release_ref(args, py);
@ -394,7 +393,7 @@ pub unsafe fn py_class_method_impl(def: *mut ffi::PyMethodDef) -> ClassMethodDes
impl <T> TypeMember<T> for ClassMethodDescriptor where T: PythonObject {
#[inline]
fn to_descriptor(&self, ty: &PyType, _name: &str, py: Python) -> PyObject {
fn to_descriptor(&self, py: Python, ty: &PyType, _name: &str) -> PyObject {
unsafe {
err::from_owned_ptr_or_panic(py,
ffi::PyDescr_NewClassMethod(ty.as_type_ptr(), self.0))

View File

@ -40,12 +40,12 @@ pub trait PythonBaseObject : PythonObject {
/// and initializes it using init_val.
/// `ty` must be derived from the Self type, and the resulting object
/// must be of type `ty`.
unsafe fn alloc(ty: &PyType, init_val: Self::InitType, py: Python) -> PyResult<Self>;
unsafe fn alloc(py: Python, ty: &PyType, init_val: Self::InitType) -> PyResult<Self>;
/// Calls the rust destructor for the object and frees the memory
/// (usually by calling ptr->ob_type->tp_free).
/// This function is used as tp_dealloc implementation.
unsafe fn dealloc(ptr: *mut ffi::PyObject, py: Python);
unsafe fn dealloc(py: Python, ptr: *mut ffi::PyObject);
}
impl PythonBaseObject for PyObject {
@ -56,12 +56,12 @@ impl PythonBaseObject for PyObject {
type InitType = ();
unsafe fn alloc(ty: &PyType, _init_val: (), py: Python) -> PyResult<PyObject> {
unsafe fn alloc(py: Python, ty: &PyType, _init_val: ()) -> PyResult<PyObject> {
let ptr = ffi::PyType_GenericAlloc(ty.as_type_ptr(), 0);
err::result_from_owned_ptr(py, ptr)
}
unsafe fn dealloc(ptr: *mut ffi::PyObject, _py: Python) {
unsafe fn dealloc(_py: Python, ptr: *mut ffi::PyObject) {
// Unfortunately, there is no PyType_GenericFree, so
// we have to manually un-do the work of PyType_GenericAlloc:
let ty = ffi::Py_TYPE(ptr);
@ -130,17 +130,17 @@ impl <T, B> PythonBaseObject for PyRustObject<T, B> where T: 'static + Send, B:
type InitType = (T, B::InitType);
unsafe fn alloc(ty: &PyType, (val, base_val): Self::InitType, py: Python) -> PyResult<Self> {
let obj = try!(B::alloc(ty, base_val, py));
unsafe fn alloc(py: Python, ty: &PyType, (val, base_val): Self::InitType) -> PyResult<Self> {
let obj = try!(B::alloc(py, ty, base_val));
let offset = PyRustObject::<T, B>::offset() as isize;
ptr::write((obj.as_object().as_ptr() as *mut u8).offset(offset) as *mut T, val);
Ok(Self::unchecked_downcast_from(obj.into_object()))
}
unsafe fn dealloc(obj: *mut ffi::PyObject, py: Python) {
unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
let offset = PyRustObject::<T, B>::offset() as isize;
ptr::read_and_drop((obj as *mut u8).offset(offset) as *mut T);
B::dealloc(obj, py)
B::dealloc(py, obj)
}
}
@ -204,9 +204,9 @@ pub struct PyRustType<T, B = PyObject> where T: 'static + Send, B: PythonBaseObj
impl <T, B> PyRustType<T, B> where T: 'static + Send, B: PythonBaseObject {
/// Creates a PyRustObject instance from a value.
pub fn create_instance(&self, val: T, base_val: B::InitType, py: Python) -> PyRustObject<T, B> {
pub fn create_instance(&self, py: Python, val: T, base_val: B::InitType) -> PyRustObject<T, B> {
unsafe {
PythonBaseObject::alloc(&self.type_obj, (val, base_val), py).unwrap()
PythonBaseObject::alloc(py, &self.type_obj, (val, base_val)).unwrap()
}
}
}

View File

@ -37,7 +37,7 @@ fn rustobject_calls_drop() {
let t = PyRustTypeBuilder::<MyObj>::new(py, "TypeWithDrop").finish().unwrap();
let drop_called = Arc::new(AtomicBool::new(false));
let inst = t.create_instance(MyObj { drop_called: drop_called.clone() }, (), py);
let inst = t.create_instance(py, MyObj { drop_called: drop_called.clone() }, ());
assert!(drop_called.load(Ordering::Relaxed) == false);
drop(inst);
assert!(drop_called.load(Ordering::Relaxed) == true);
@ -49,7 +49,7 @@ fn no_init_from_python() {
let gil = Python::acquire_gil();
let py = gil.python();
let t = PyRustTypeBuilder::<i32>::new(py, "MyType").finish().unwrap();
assert!(t.call(&NoArgs, None, py).is_err());
assert!(t.call(py, &NoArgs, None).is_err());
}
@ -61,7 +61,7 @@ fn heaptype_refcount() {
// TODO: investigate why the refcnt isn't 1.
//assert_eq!(1, t.as_object().get_refcnt());
let old_refcnt = t.as_object().get_refcnt(py);
let inst = t.create_instance(1, (), py);
let inst = t.create_instance(py, 1, ());
assert_eq!(old_refcnt + 1, t.as_object().get_refcnt(py));
drop(inst);
assert_eq!(old_refcnt, t.as_object().get_refcnt(py));

View File

@ -68,7 +68,7 @@ pub struct PyRustTypeBuilder<'p, T, B = PyObject> where T: 'static + Send, B: Py
phantom: marker::PhantomData<&'p (B, T)>
}
pub fn new_typebuilder_for_module<'p, T>(m: &PyModule, name: &str, py: Python<'p>) -> PyRustTypeBuilder<'p, T>
pub fn new_typebuilder_for_module<'p, T>(py: Python<'p>, m: &PyModule, name: &str) -> PyRustTypeBuilder<'p, T>
where T: 'static + Send {
let b = PyRustTypeBuilder::new(py, name);
PyRustTypeBuilder { target_module: Some(m.clone_ref(py)), .. b }
@ -86,7 +86,7 @@ unsafe extern "C" fn tp_dealloc_callback<T, B>(obj: *mut ffi::PyObject)
where T: 'static + Send, B: PythonBaseObject {
abort_on_panic!({
let py = Python::assume_gil_acquired();
PyRustObject::<T, B>::dealloc(obj, py)
PyRustObject::<T, B>::dealloc(py, obj)
});
}
@ -213,7 +213,7 @@ impl <'p, T, B> PyRustTypeBuilder<'p, T, B> where T: 'static + Send, B: PythonBa
pub fn add<M>(mut self, name: &str, val: M) -> Self
where M: TypeMember<PyRustObject<T, B>> {
self.can_change_base = false;
self.dict().set_item(name, val.to_descriptor(&self.type_obj, name, self.py), self.py).unwrap();
self.dict().set_item(self.py, name, val.to_descriptor(self.py, &self.type_obj, name)).unwrap();
self
}
@ -241,11 +241,11 @@ impl <'p, T, B> PyRustTypeBuilder<'p, T, B> where T: 'static + Send, B: PythonBa
if let Some(m) = self.target_module {
// Set module name for new type
if let Ok(mod_name) = m.name(py) {
try!(self.type_obj.as_object().setattr("__module__", mod_name, py));
try!(self.type_obj.as_object().setattr(py, "__module__", mod_name));
}
// Register the new type in the target module
let name = unsafe { PyObject::from_borrowed_ptr(py, (*self.ht).ht_name) };
try!(m.dict(py).set_item(name, self.type_obj.as_object(), py));
try!(m.dict(py).set_item(py, name, self.type_obj.as_object()));
}
Ok(PyRustType {
type_obj: self.type_obj,
@ -278,13 +278,13 @@ impl <'p, T, B> PyRustTypeBuilder<'p, T, B> where T: 'static + Send, B: PythonBa
self.py, &self.name, PyRustObject::<T, B>::size(),
self.flags, &mut self.slots) });
for (name, member) in self.members {
let descr = member.to_descriptor(&type_obj, &name, self.py);
try!(type_obj.as_object().setattr(name, descr, self.py));
let descr = member.to_descriptor(self.py, &type_obj, &name);
try!(type_obj.as_object().setattr(self.py, name, descr));
}
if let Some(m) = self.target_module {
// Set module name for new type
if let Ok(mod_name) = m.name(self.py) {
try!(type_obj.as_object().setattr("__module__", mod_name, self.py));
try!(type_obj.as_object().setattr(self.py, "__module__", mod_name));
}
// Register the new type in the target module
unsafe {
@ -353,7 +353,7 @@ unsafe fn create_type_from_slots<'p>(
pub trait TypeMember<T> where T: PythonObject {
/// Convert the type member into a python object
/// that can be stored in the type dict.
fn to_descriptor(&self, ty: &PyType, name: &str, py: Python) -> PyObject;
fn to_descriptor(&self, py: Python, ty: &PyType, name: &str) -> PyObject;
/// Put the type member into a box with lifetime `'p` so that
/// it can be used at a later point in time.
@ -367,7 +367,7 @@ pub trait TypeMember<T> where T: PythonObject {
impl <T, S> TypeMember<T> for S where T: PythonObject, S: ToPyObject {
#[inline]
fn to_descriptor(&self, _ty: &PyType, _name: &str, py: Python) -> PyObject {
fn to_descriptor(&self, py: Python, _ty: &PyType, _name: &str) -> PyObject {
self.to_py_object(py).into_object()
}