Get rid of the pyobject_extract macro
This commit is contained in:
parent
9cadbd11de
commit
db4a2d9017
|
@ -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
|
||||
|
|
|
@ -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(<PyBool as PyTryFrom>::try_from(obj)?.is_true())
|
||||
});
|
||||
impl<'source> FromPyObject<'source> for bool {
|
||||
fn extract(obj: &'source PyObjectRef) -> PyResult<Self> {
|
||||
Ok(<PyBool as PyTryFrom>::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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Self> {
|
||||
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::<f64>()? as f32)
|
||||
});
|
||||
impl<'source> FromPyObject<'source> for f32 {
|
||||
fn extract(obj: &'source PyObjectRef) -> PyResult<Self> {
|
||||
Ok(obj.extract::<f64>()? as f32)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
|
|
@ -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<Self>
|
||||
{
|
||||
$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<Self, $crate::PyErr>
|
||||
{
|
||||
$body
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
use ffi;
|
||||
use python::ToPyPointer;
|
||||
/// Represents general python instance.
|
||||
|
|
|
@ -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<Self> {
|
||||
let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) };
|
||||
if val == -1 && PyErr::occurred(obj.py()) {
|
||||
return Err(PyErr::fetch(obj.py()));
|
||||
}
|
||||
match cast::<c_long, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(exc::OverflowError.into())
|
||||
}
|
||||
}
|
||||
match cast::<c_long, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(exc::OverflowError.into())
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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<Self> {
|
||||
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::<c_long, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(exc::OverflowError.into())
|
||||
}
|
||||
}?;
|
||||
match cast::<c_long, $rust_type>(val) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(exc::OverflowError.into())
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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<Self> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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 => {
|
||||
<PyString as PyTryFrom>::try_from(obj)?.to_string().map(Cow::into_owned)
|
||||
});
|
||||
impl<'source> FromPyObject<'source> for String {
|
||||
fn extract(obj: &'source PyObjectRef) -> PyResult<Self> {
|
||||
<PyString as PyTryFrom>::try_from(obj)?
|
||||
.to_string()
|
||||
.map(Cow::into_owned)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue