From c4357f8111379bc79a616b9e5c301830d0d8f53c Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Thu, 21 Jul 2016 16:15:19 +0200 Subject: [PATCH 1/7] py_class_impl: make generated struct public Signed-off-by: Tibor Benke --- src/py_class/py_class_impl.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/py_class/py_class_impl.py b/src/py_class/py_class_impl.py index 0f577fa4..7ad02790 100644 --- a/src/py_class/py_class_impl.py +++ b/src/py_class/py_class_impl.py @@ -48,7 +48,7 @@ } $slots:tt { $( $imp:item )* } $members:tt } => { - struct $class { _unsafe_inner: $crate::PyObject } + pub struct $class { _unsafe_inner: $crate::PyObject } py_impl_to_py_object_for_python_object!($class); py_impl_from_py_object_for_python_object!($class); @@ -771,4 +771,3 @@ def main(): if __name__ == '__main__': main() - From b572bf811090ae385274ce6b98e789ada4cb7f87 Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Fri, 22 Jul 2016 09:57:27 +0200 Subject: [PATCH 2/7] Regenerate py_class_impl{2,3}.rs files Signed-off-by: Tibor Benke --- src/py_class/py_class_impl2.rs | 2 +- src/py_class/py_class_impl3.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/py_class/py_class_impl2.rs b/src/py_class/py_class_impl2.rs index b15d5411..1aa8506b 100644 --- a/src/py_class/py_class_impl2.rs +++ b/src/py_class/py_class_impl2.rs @@ -40,7 +40,7 @@ macro_rules! py_class_impl { } $slots:tt { $( $imp:item )* } $members:tt } => { - struct $class { _unsafe_inner: $crate::PyObject } + pub struct $class { _unsafe_inner: $crate::PyObject } py_impl_to_py_object_for_python_object!($class); py_impl_from_py_object_for_python_object!($class); diff --git a/src/py_class/py_class_impl3.rs b/src/py_class/py_class_impl3.rs index 3f6eed27..0771202f 100644 --- a/src/py_class/py_class_impl3.rs +++ b/src/py_class/py_class_impl3.rs @@ -40,7 +40,7 @@ macro_rules! py_class_impl { } $slots:tt { $( $imp:item )* } $members:tt } => { - struct $class { _unsafe_inner: $crate::PyObject } + pub struct $class { _unsafe_inner: $crate::PyObject } py_impl_to_py_object_for_python_object!($class); py_impl_from_py_object_for_python_object!($class); From a84cf44b53aa7f0aaa6b243ebc6f9fc21ab78b9d Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Fri, 22 Jul 2016 10:04:25 +0200 Subject: [PATCH 3/7] Correct documentation by replacing ExtractPyObject with FromPyObject Signed-off-by: Tibor Benke --- src/argparse.rs | 2 +- src/py_class/py_class.rs | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/argparse.rs b/src/argparse.rs index 40032512..08734d45 100644 --- a/src/argparse.rs +++ b/src/argparse.rs @@ -120,7 +120,7 @@ pub fn parse_args( /// 5. `*name : ty` /// 6. `**name` /// 7. `**name : ty` -/// The types used must implement the `ExtractPyObject` trait. +/// The types used must implement the `FromPyObject` trait. /// If no type is specified, the parameter implicitly uses /// `&PyObject` (format 1), `&PyTuple` (format 4) or `&PyDict` (format 6). /// If a default value is specified, it must be a compile-time constant diff --git a/src/py_class/py_class.rs b/src/py_class/py_class.rs index 0e9dab99..841e854d 100644 --- a/src/py_class/py_class.rs +++ b/src/py_class/py_class.rs @@ -302,15 +302,15 @@ py_class!(class MyIterator |py| { `__length_hint__` is new in Python 3.4; older versions will ignore the method. - * `def __getitem__(&self, key: impl ExtractPyObject) -> PyResult` + * `def __getitem__(&self, key: impl FromPyObject) -> PyResult` Called by the Python subscript operator `self[key]`. - * `def __setitem__(&self, key: impl ExtractPyObject, value: impl ExtractPyObject) -> PyResult<()>` + * `def __setitem__(&self, key: impl FromPyObject, value: impl FromPyObject) -> PyResult<()>` Called by Python `self[key] = value`. - * `def __delitem__(&self, key: impl ExtractPyObject) -> PyResult<()>` + * `def __delitem__(&self, key: impl FromPyObject) -> PyResult<()>` Called by Python `del self[key]`. @@ -319,7 +319,7 @@ py_class!(class MyIterator |py| { Called by the `reversed()` built-in. It should return a new iterator object that iterates over all the objects in the container in reverse order. - * `def __contains__(&self, item: impl ExtractPyObject) -> PyResult` + * `def __contains__(&self, item: impl FromPyObject) -> PyResult` Called by Python `item in self`. For mapping types, this should consider the keys of the mapping rather than the values @@ -351,18 +351,18 @@ py_class!(class MyIterator |py| { If you can't handle the combination of types you've been given, you should return `Ok(py.NotImplemented())`. - * `def __iadd__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __isub__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __imul__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __imatmul__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __itruediv__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __ifloordiv__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __imod__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __ilshift__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __irshift__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __iand__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __ixor__(&self, other: impl ExtractPyObject) -> PyResult` - * `def __ior__(&self, other: impl ExtractPyObject) -> PyResult` + * `def __iadd__(&self, other: impl FromPyObject) -> PyResult` + * `def __isub__(&self, other: impl FromPyObject) -> PyResult` + * `def __imul__(&self, other: impl FromPyObject) -> PyResult` + * `def __imatmul__(&self, other: impl FromPyObject) -> PyResult` + * `def __itruediv__(&self, other: impl FromPyObject) -> PyResult` + * `def __ifloordiv__(&self, other: impl FromPyObject) -> PyResult` + * `def __imod__(&self, other: impl FromPyObject) -> PyResult` + * `def __ilshift__(&self, other: impl FromPyObject) -> PyResult` + * `def __irshift__(&self, other: impl FromPyObject) -> PyResult` + * `def __iand__(&self, other: impl FromPyObject) -> PyResult` + * `def __ixor__(&self, other: impl FromPyObject) -> PyResult` + * `def __ior__(&self, other: impl FromPyObject) -> PyResult` Handles inplace operations if possible, falling back to the non-inplace versions. These methods must return a new reference! In the common case of returning the From d3ec635fb3ff01b1c2adf7750ffb8ec1490598d3 Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Fri, 22 Jul 2016 10:09:06 +0200 Subject: [PATCH 4/7] Make struct TestDropCall public struct DataIsDropped is public, so all of its fields needs to be public as well. Signed-off-by: Tibor Benke --- tests/test_class.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_class.rs b/tests/test_class.rs index 257fdd4b..c2eb92eb 100644 --- a/tests/test_class.rs +++ b/tests/test_class.rs @@ -93,7 +93,7 @@ fn new_with_two_args() { assert_eq!(*obj._data2(py), 20); } -struct TestDropCall { +pub struct TestDropCall { drop_called: Arc } impl Drop for TestDropCall { From a33583b65372111c8818ded376537830eb80bb3c Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Fri, 22 Jul 2016 10:18:48 +0200 Subject: [PATCH 5/7] Fix Markdown formatting in py_fn!'s documentation Signed-off-by: Tibor Benke --- src/function.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/function.rs b/src/function.rs index 98a7dd5d..352f067f 100644 --- a/src/function.rs +++ b/src/function.rs @@ -49,8 +49,9 @@ macro_rules! py_method_def { /// Creates a Python callable object that invokes a Rust function. /// /// There are two forms of this macro: -/// 1) `py_fn!(py, f(parameter_list))` -/// 2) `py_fn!(py, f(parameter_list) -> PyResult { body })` +/// +/// 1. `py_fn!(py, f(parameter_list))` +/// 1. `py_fn!(py, f(parameter_list) -> PyResult { body })` /// /// All three forms return a value of type `PyObject`. /// This python object is a callable object that invokes @@ -60,13 +61,15 @@ macro_rules! py_method_def { /// the Rust types specified in the parameter list. /// See `py_argparse!()` for details on argument parsing. /// -/// Form 1: +/// Form 1: +/// /// * `py` must be an expression of type `Python` /// * `f` must be the name of a function that is compatible with the specified /// parameter list, except that a single parameter of type `Python` is prepended. /// The function must return `PyResult` for some `T` that implements `ToPyObject`. /// /// Form 2: +/// /// * `py` must be an identifier refers to a `Python` value. /// The function body will also have access to a `Python` variable of this name. /// * `f` must be an identifier. From d9a4874d5ff00a035d9b9d7c9668697d1da54b75 Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Fri, 22 Jul 2016 10:35:44 +0200 Subject: [PATCH 6/7] Make OrdPyObject public Signed-off-by: Tibor Benke --- extensions/btree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/btree.rs b/extensions/btree.rs index 2c11e10a..86366be2 100644 --- a/extensions/btree.rs +++ b/extensions/btree.rs @@ -14,7 +14,7 @@ py_module_initializer!(btree, initbtree, PyInit_btree, |py, m| { /// Newtype around PyObject that implements Ord using python value comparisons. /// Python exceptions are converted into Rust panics. -struct OrdPyObject(PyObject); +pub struct OrdPyObject(PyObject); impl PartialEq for OrdPyObject { fn eq(&self, _other: &Self) -> bool { From 11c99fc0cae4a4d599f48714f73e5fdebd8481c8 Mon Sep 17 00:00:00 2001 From: Tibor Benke Date: Fri, 22 Jul 2016 21:22:17 +0200 Subject: [PATCH 7/7] Fix C FFI bug in PyErr Use null-terminated strings to call PyErr_NewException() Signed-off-by: Tibor Benke --- src/err.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/err.rs b/src/err.rs index fd55ae3b..f46e748d 100644 --- a/src/err.rs +++ b/src/err.rs @@ -164,7 +164,10 @@ impl PyErr { }; unsafe { - let ptr: *mut ffi::PyObject = ffi::PyErr_NewException(name.as_ptr() as *mut c_char, base, dict); + let null_terminated_name = CString::new(name).unwrap(); + let ptr: *mut ffi::PyObject = ffi::PyErr_NewException(null_terminated_name.as_ptr() as *mut c_char, + base, + dict); PyObject::from_borrowed_ptr(py, ptr).unchecked_cast_into::() } }