From db4a2d9017e6e4c1bd3fd616fc0fff12cf81848f Mon Sep 17 00:00:00 2001 From: konstin Date: Mon, 20 Aug 2018 22:53:43 +0200 Subject: [PATCH] Get rid of the pyobject_extract macro --- CHANGELOG.md | 6 ++++++ src/objects/boolobject.rs | 15 +++++++++----- src/objects/floatob.rs | 34 +++++++++++++++++++------------ src/objects/mod.rs | 27 ------------------------- src/objects/num2.rs | 21 ++++++++++--------- src/objects/num3.rs | 41 ++++++++++++++++++++------------------ src/objects/num_common.rs | 15 ++++++++------ src/objects/stringutils.rs | 18 +++++++++++------ tests/test_methods.rs | 2 +- 9 files changed, 93 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aca1e294..1c61f1f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## Unreleased + +### Removed + + * The pyobject_extract macro + ## [0.4.1] - 2018-08-20 ### Fixed diff --git a/src/objects/boolobject.rs b/src/objects/boolobject.rs index 0ed168a3..8cab7c2c 100644 --- a/src/objects/boolobject.rs +++ b/src/objects/boolobject.rs @@ -2,7 +2,10 @@ use conversion::{IntoPyObject, PyTryFrom, ToBorrowedObject, ToPyObject}; use ffi; use object::PyObject; +use objects::PyObjectRef; use python::{Python, ToPyPointer}; +use FromPyObject; +use PyResult; /// Represents a Python `bool`. #[repr(transparent)] @@ -68,9 +71,11 @@ impl IntoPyObject for bool { /// Converts a Python `bool` to a rust `bool`. /// /// Fails with `TypeError` if the input is not a Python `bool`. -pyobject_extract!(obj to bool => { - Ok(::try_from(obj)?.is_true()) -}); +impl<'source> FromPyObject<'source> for bool { + fn extract(obj: &'source PyObjectRef) -> PyResult { + Ok(::try_from(obj)?.is_true()) + } +} #[cfg(test)] mod test { @@ -86,7 +91,7 @@ mod test { assert!(PyBool::new(py, true).is_true()); let t: &PyObjectRef = PyBool::new(py, true).into(); assert_eq!(true, t.extract().unwrap()); - assert!(true.to_object(py) == PyBool::new(py, true).into()); + assert_eq!(true.to_object(py), PyBool::new(py, true).into()); } #[test] @@ -96,6 +101,6 @@ mod test { assert!(!PyBool::new(py, false).is_true()); let t: &PyObjectRef = PyBool::new(py, false).into(); assert_eq!(false, t.extract().unwrap()); - assert!(false.to_object(py) == PyBool::new(py, false).into()); + assert_eq!(false.to_object(py), PyBool::new(py, false).into()); } } diff --git a/src/objects/floatob.rs b/src/objects/floatob.rs index 36c26d8e..fdde083b 100644 --- a/src/objects/floatob.rs +++ b/src/objects/floatob.rs @@ -2,15 +2,17 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -use std::os::raw::c_double; - use conversion::{IntoPyObject, ToPyObject}; use err::PyErr; use ffi; use instance::{Py, PyObjectWithToken}; use object::PyObject; use objectprotocol::ObjectProtocol; +use objects::PyObjectRef; use python::{Python, ToPyPointer}; +use std::os::raw::c_double; +use FromPyObject; +use PyResult; /// Represents a Python `float` object. /// @@ -40,38 +42,44 @@ impl ToPyObject for f64 { PyFloat::new(py, *self).into() } } + impl IntoPyObject for f64 { fn into_object(self, py: Python) -> PyObject { PyFloat::new(py, self).into() } } -pyobject_extract!(obj to f64 => { - let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) }; +impl<'source> FromPyObject<'source> for f64 { + fn extract(obj: &'source PyObjectRef) -> PyResult { + let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) }; - { - if v == -1.0 && PyErr::occurred(obj.py()) { - Err(PyErr::fetch(obj.py())) - } else { - Ok(v) + { + if v == -1.0 && PyErr::occurred(obj.py()) { + Err(PyErr::fetch(obj.py())) + } else { + Ok(v) + } } } -}); +} impl ToPyObject for f32 { fn to_object(&self, py: Python) -> PyObject { PyFloat::new(py, *self as f64).into() } } + impl IntoPyObject for f32 { fn into_object(self, py: Python) -> PyObject { PyFloat::new(py, self as f64).into() } } -pyobject_extract!(obj to f32 => { - Ok(obj.extract::()? as f32) -}); +impl<'source> FromPyObject<'source> for f32 { + fn extract(obj: &'source PyObjectRef) -> PyResult { + Ok(obj.extract::()? as f32) + } +} #[cfg(test)] mod test { diff --git a/src/objects/mod.rs b/src/objects/mod.rs index 79592552..2a4a1a13 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -175,33 +175,6 @@ macro_rules! pyobject_native_type_convert( }; ); -/// Implements [FromPyObject] and (currently deactivated until it's stabillized) a -/// [TryFrom](std::convert::TryFrom) implementation, given a function body that performs the actual -/// conversion -#[macro_export] -macro_rules! pyobject_extract( - ($obj:ident to $t:ty => $body: block) => { - impl<'source> $crate::FromPyObject<'source> for $t - { - fn extract($obj: &'source $crate::PyObjectRef) -> $crate::PyResult - { - $body - } - } - - #[cfg(feature = "try_from")] - impl<'source> ::std::convert::TryFrom<&'source $crate::PyObjectRef> for $t - { - type Error = $crate::PyErr; - - fn try_from($obj: &$crate::PyObjectRef) -> Result - { - $body - } - } - } -); - use ffi; use python::ToPyPointer; /// Represents general python instance. diff --git a/src/objects/num2.rs b/src/objects/num2.rs index 9caa6f3c..ddb9c2c1 100644 --- a/src/objects/num2.rs +++ b/src/objects/num2.rs @@ -77,16 +77,19 @@ macro_rules! int_fits_c_long( } } } - pyobject_extract!(obj to $rust_type => { - let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) }; - if val == -1 && PyErr::occurred(obj.py()) { - return Err(PyErr::fetch(obj.py())); + + impl<'source> FromPyObject<'source> for $rust_type { + fn extract(obj: &'source PyObjectRef) -> PyResult { + let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) }; + if val == -1 && PyErr::occurred(obj.py()) { + return Err(PyErr::fetch(obj.py())); + } + match cast::(val) { + Some(v) => Ok(v), + None => Err(exc::OverflowError.into()) + } } - match cast::(val) { - Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) - } - }); + } ) ); diff --git a/src/objects/num3.rs b/src/objects/num3.rs index 4547abdc..e97ced92 100644 --- a/src/objects/num3.rs +++ b/src/objects/num3.rs @@ -2,11 +2,9 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -use std::os::raw::{c_long, c_uchar}; - extern crate num_traits; -use self::num_traits::cast::cast; +use self::num_traits::cast::cast; use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN}; use conversion::{FromPyObject, IntoPyObject, ToPyObject}; use err::{PyErr, PyResult}; @@ -15,6 +13,8 @@ use instance::PyObjectWithToken; use object::PyObject; use objects::{exc, PyObjectRef}; use python::{Python, ToPyPointer}; +use std::os::raw::{c_long, c_uchar}; + /// Represents a Python `int` object. /// /// You can usually avoid directly working with this type @@ -26,7 +26,7 @@ pub struct PyLong(PyObject); pyobject_native_type!(PyLong, ffi::PyLong_Type, ffi::PyLong_Check); -macro_rules! int_fits_c_long( +macro_rules! int_fits_c_long ( ($rust_type:ty) => ( impl ToPyObject for $rust_type { @@ -44,23 +44,26 @@ macro_rules! int_fits_c_long( } } } - pyobject_extract!(obj to $rust_type => { - let ptr = obj.as_ptr(); - let val = unsafe { - let num = ffi::PyNumber_Index(ptr); - if num.is_null() { - Err(PyErr::fetch(obj.py())) - } else { - let val = err_if_invalid_value(obj.py(), -1, ffi::PyLong_AsLong(num)); - ffi::Py_DECREF(num); - val + + impl<'source> FromPyObject<'source> for $rust_type { + fn extract(obj: &'source PyObjectRef) -> PyResult { + let ptr = obj.as_ptr(); + let val = unsafe { + let num = ffi::PyNumber_Index(ptr); + if num.is_null() { + Err(PyErr::fetch(obj.py())) + } else { + let val = err_if_invalid_value(obj.py(), -1, ffi::PyLong_AsLong(num)); + ffi::Py_DECREF(num); + val + } + }?; + match cast::(val) { + Some(v) => Ok(v), + None => Err(exc::OverflowError.into()) } - }?; - match cast::(val) { - Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) } - }); + } ) ); diff --git a/src/objects/num_common.rs b/src/objects/num_common.rs index a71bf987..7f8baf5d 100644 --- a/src/objects/num_common.rs +++ b/src/objects/num_common.rs @@ -30,13 +30,16 @@ macro_rules! int_fits_larger_int( (self as $larger_type).into_object(py) } } - pyobject_extract!(obj to $rust_type => { - let val = try!($crate::objectprotocol::ObjectProtocol::extract::<$larger_type>(obj)); - match cast::<$larger_type, $rust_type>(val) { - Some(v) => Ok(v), - None => Err(exc::OverflowError.into()) + + impl<'source> FromPyObject<'source> for $rust_type { + fn extract(obj: &'source PyObjectRef) -> PyResult { + let val = try!($crate::objectprotocol::ObjectProtocol::extract::<$larger_type>(obj)); + match cast::<$larger_type, $rust_type>(val) { + Some(v) => Ok(v), + None => Err(exc::OverflowError.into()) + } } - }); + } ) ); diff --git a/src/objects/stringutils.rs b/src/objects/stringutils.rs index def967b6..e248ecad 100644 --- a/src/objects/stringutils.rs +++ b/src/objects/stringutils.rs @@ -1,12 +1,11 @@ -// Copyright (c) 2017-present PyO3 Project and Contributors -use std::borrow::Cow; - use conversion::{IntoPyObject, PyTryFrom, ToPyObject}; use err::PyResult; use instance::PyObjectWithToken; use object::PyObject; use objects::{PyObjectRef, PyString}; use python::Python; +use std::borrow::Cow; +use FromPyObject; /// Converts Rust `str` to Python object. /// See `PyString::new` for details on the conversion. @@ -16,6 +15,7 @@ impl ToPyObject for str { PyString::new(py, self).into() } } + impl<'a> IntoPyObject for &'a str { #[inline] fn into_object(self, py: Python) -> PyObject { @@ -40,12 +40,14 @@ impl ToPyObject for String { PyString::new(py, self).into() } } + impl IntoPyObject for String { #[inline] fn into_object(self, py: Python) -> PyObject { PyString::new(py, &self).into() } } + impl<'a> IntoPyObject for &'a String { #[inline] fn into_object(self, py: Python) -> PyObject { @@ -78,6 +80,10 @@ impl<'a> ::FromPyObject<'a> for &'a str { /// Allows extracting strings from Python objects. /// Accepts Python `str` and `unicode` objects. -pyobject_extract!(obj to String => { - ::try_from(obj)?.to_string().map(Cow::into_owned) -}); +impl<'source> FromPyObject<'source> for String { + fn extract(obj: &'source PyObjectRef) -> PyResult { + ::try_from(obj)? + .to_string() + .map(Cow::into_owned) + } +} diff --git a/tests/test_methods.rs b/tests/test_methods.rs index 62bb029d..760fb475 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -31,7 +31,7 @@ fn instance_method() { member: 42, token: t, }).unwrap(); - assert!(obj.method().unwrap() == 42); + assert_eq!(obj.method().unwrap(), 42); let d = PyDict::new(py); d.set_item("obj", obj).unwrap(); py.run("assert obj.method() == 42", None, Some(d)).unwrap();