diff --git a/.travis.yml b/.travis.yml index a1bef474..08a8ed25 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,8 @@ -sudo: required -dist: trusty language: python cache: pip: true - directories: - - $HOME/.cargo - - $TRAVIS_BUILD_DIR/target + cargo: true matrix: include: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e30064b..178ee705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ 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 + +### Changed + + * PyTryFrom's error is always to `PyDowncastError` + +### Removed + + * The pyobject_downcast macro + ## [0.4.0] - 2018-07-30 ### Removed diff --git a/README.md b/README.md index e681913a..e874da2b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PyO3 [![Build Status](https://travis-ci.org/PyO3/pyo3.svg?branch=master)](https://travis-ci.org/PyO3/pyo3) -[![Build Status](https://ci.appveyor.com/api/projects/status/github/fafhrd91/pyo3?branch=master&svg=true)](https://ci.appveyor.com/project/fafhrd91/pyo3) +[![Build Status](https://ci.appveyor.com/api/projects/status/github/PyO3/pyo3?branch=master&svg=true)](https://ci.appveyor.com/project/fafhrd91/pyo3) [![codecov](https://codecov.io/gh/PyO3/pyo3/branch/master/graph/badge.svg)](https://codecov.io/gh/PyO3/pyo3) [![crates.io](http://meritbadge.herokuapp.com/pyo3)](https://crates.io/crates/pyo3) [![Join the dev chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/PyO3/Lobby) @@ -64,7 +64,7 @@ fn rust_py(py: Python, m: &PyModule) -> PyResult<()> { } ``` -On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content: +On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content: ```toml [target.x86_64-apple-darwin] @@ -117,6 +117,7 @@ fn main() -> PyResult<()> { * [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_ * [rust-numpy](https://github.com/rust-numpy/rust-numpy) _Rust binding of NumPy C-API_ * [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_ + * [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library_ ## License diff --git a/build.rs b/build.rs index d60417ab..add76a4f 100644 --- a/build.rs +++ b/build.rs @@ -200,8 +200,16 @@ fn get_rustc_link_lib( #[cfg(target_os = "macos")] fn get_macos_linkmodel() -> Result { - let script = "import sysconfig;\ - print('framework' if sysconfig.get_config_var('PYTHONFRAMEWORK') else ('shared' if sysconfig.get_config_var('Py_ENABLE_SHARED') else 'static'));"; + let script = r#" +import sysconfig + +if sysconfig.get_config_var("PYTHONFRAMEWORK"): + print("framework") +elif sysconfig.get_config_var("Py_ENABLE_SHARED"): + print("shared") +else: + print("static") +"#; let out = run_python_script("python", script).unwrap(); Ok(out.trim_right().to_owned()) } @@ -520,6 +528,10 @@ fn main() { } ); + if env::var_os("TARGET") == Some("x86_64-apple-darwin".into()) { + // TODO: Find out how we can set -undefined dynamic_lookup here (if this is possible) + } + let env_vars = ["LD_LIBRARY_PATH", "PATH", "PYTHON_SYS_EXECUTABLE"]; for var in env_vars.iter() { diff --git a/guide/src/overview.md b/guide/src/overview.md index 19aed6c7..95ae1e23 100644 --- a/guide/src/overview.md +++ b/guide/src/overview.md @@ -1,23 +1,86 @@ # PyO3 -[Rust](http://www.rust-lang.org/) bindings for the [Python](https://www.python.org/) interpreter. This includes running and interacting with python code from a rust binaries as well as writing native python modules. +[Rust](http://www.rust-lang.org/) bindings for [Python](https://www.python.org/). This includes running and interacting with python code from a rust binaries as well as writing native python modules. ## Usage -Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.27.0-nightly 2018-05-01. +Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.29.0-nightly 2018-07-16. -### From a rust binary +You can either write a native python module in rust or use python from a rust binary. -To use `pyo3`, add this to your `Cargo.toml`: +### Using rust from python + +Pyo3 can be used to generate a native python module. + +**`Cargo.toml`:** + +```toml +[package] +name = "rust-py" +version = "0.1.0" + +[lib] +name = "rust_py" +crate-type = ["cdylib"] + +[dependencies.pyo3] +version = "0.3" +features = ["extension-module"] +``` + +**`src/lib.rs`** + +```rust +#![feature(use_extern_macros, specialization)] + +#[macro_use] +extern crate pyo3; + +use pyo3::prelude::*; + +#[pyfunction] +/// Formats the sum of two numbers as string +fn sum_as_string(a: usize, b: usize) -> PyResult { + Ok((a + b).to_string()) +} + +/// This module is a python moudle implemented in Rust. +#[pymodinit] +fn rust_py(py: Python, m: &PyModule) -> PyResult<()> { + m.add_function(wrap_function!(sum_as_string))?; + + Ok(()) +} +``` + +On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content: + +```toml +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] +``` + +Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd. + +[`setuptools-rust`](https://github.com/PyO3/setuptools-rust) can be used to generate a python package and includes the commands above by default. See [examples/word-count](examples/https://github.com/PyO3/pyo3/tree/master/examples/word-count) and the associated setup.py. + +### Using python from rust + +Add `pyo3` this to your `Cargo.toml`: ```toml [dependencies] -pyo3 = "0.2" +pyo3 = "0.3" ``` Example program displaying the value of `sys.version`: ```rust +#![feature(use_extern_macros, specialization)] + extern crate pyo3; use pyo3::prelude::*; @@ -37,57 +100,10 @@ fn main() -> PyResult<()> { } ``` -### As native module +## Examples and tooling -Pyo3 can be used to write native python module. The example will generate a python-compatible library. - -For MacOS, "-C link-arg=-undefined -C link-arg=dynamic_lookup" is required to build the library. -`setuptools-rust` includes this by default. See [examples/word-count](examples/word-count) and the associated setup.py. Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd. - -**`Cargo.toml`:** - -```toml -[lib] -name = "rust2py" -crate-type = ["cdylib"] - -[dependencies.pyo3] -version = "0.2" -features = ["extension-module"] -``` - -**`src/lib.rs`** - -```rust -#![feature(use_extern_macros, specialization)] - -extern crate pyo3; -use pyo3::prelude::*; - - - -// Add bindings to the generated python module -// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file -/// This module is implemented in Rust. -#[pymodinit] -fn rust2py(py: Python, m: &PyModule) -> PyResult<()> { - - #[pyfn(m, "sum_as_string")] - // ``#[pyfn()]` converts the arguments from Python objects to Rust values - // and the Rust return value back into a Python object. - fn sum_as_string_py(a:i64, b:i64) -> PyResult { - let out = sum_as_string(a, b); - Ok(out) - } - - Ok(()) -} - -// The logic can be implemented as a normal rust function -fn sum_as_string(a:i64, b:i64) -> String { - format!("{}", a + b).to_string() -} - -``` - -For `setup.py` integration, see [setuptools-rust](https://github.com/PyO3/setuptools-rust) + * [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count) _Counting the occurences of a word in a text file_ + * [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_ + * [rust-numpy](https://github.com/rust-numpy/rust-numpy) _Rust binding of NumPy C-API_ + * [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_ + * [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library_ diff --git a/pyo3-derive-backend/src/py_class.rs b/pyo3-derive-backend/src/py_class.rs index 88c983d7..da09a509 100644 --- a/pyo3-derive-backend/src/py_class.rs +++ b/pyo3-derive-backend/src/py_class.rs @@ -136,14 +136,14 @@ fn impl_class( } impl std::fmt::Debug for #cls { fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - use pyo3::ObjectProtocol; + use ::pyo3::ObjectProtocol; let s = try!(self.repr().map_err(|_| std::fmt::Error)); f.write_str(&s.to_string_lossy()) } } impl std::fmt::Display for #cls { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - use pyo3::ObjectProtocol; + use ::pyo3::ObjectProtocol; let s = try!(self.str().map_err(|_| std::fmt::Error)); f.write_str(&s.to_string_lossy()) } diff --git a/src/class/macros.rs b/src/class/macros.rs index 3c6d86a2..6eddbddb 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -318,7 +318,7 @@ macro_rules! py_func_set { slf: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, - ) -> $crate::c_int + ) -> $crate::libc::c_int where T: for<'p> $trait<'p>, { @@ -368,7 +368,7 @@ macro_rules! py_func_del { slf: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, - ) -> $crate::c_int + ) -> $crate::libc::c_int where T: for<'p> $trait<'p>, { @@ -414,7 +414,7 @@ macro_rules! py_func_set_del { slf: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, - ) -> $crate::c_int + ) -> $crate::libc::c_int where T: for<'p> $trait<'p> + for<'p> $trait2<'p>, { diff --git a/src/class/methods.rs b/src/class/methods.rs index a2634320..dad3ba5a 100644 --- a/src/class/methods.rs +++ b/src/class/methods.rs @@ -4,6 +4,7 @@ use std; use std::ffi::CString; use ffi; +use libc::c_int; static NO_PY_METHODS: &'static [PyMethodDefType] = &[]; @@ -42,7 +43,7 @@ pub enum PyMethodType { pub struct PyMethodDef { pub ml_name: &'static str, pub ml_meth: PyMethodType, - pub ml_flags: ::c_int, + pub ml_flags: c_int, pub ml_doc: &'static str, } diff --git a/src/conversion.rs b/src/conversion.rs index 8c6c0c90..fa18142e 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -155,18 +155,18 @@ where /// Extract reference to instance from `PyObject` impl<'a, T> FromPyObject<'a> for &'a T where - T: PyTypeInfo, + T: PyTryFrom, { #[inline] default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a T> { - Ok(::try_from(ob)?) + Ok(T::try_from(ob)?) } } /// Extract mutable reference to instance from `PyObject` impl<'a, T> FromPyObject<'a> for &'a mut T where - T: PyTypeInfo, + T: PyTryFrom, { #[inline] default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a mut T> { @@ -212,20 +212,17 @@ pub trait PyTryInto: Sized { /// Trait implemented by Python object types that allow a checked downcast. /// This trait is similar to `std::convert::TryFrom` pub trait PyTryFrom: Sized { - /// The type returned in the event of a conversion error. - type Error; - /// Cast from a concrete Python object type to PyObject. - fn try_from(value: &PyObjectRef) -> Result<&Self, Self::Error>; + fn try_from(value: &PyObjectRef) -> Result<&Self, PyDowncastError>; /// Cast from a concrete Python object type to PyObject. With exact type check. - fn try_from_exact(value: &PyObjectRef) -> Result<&Self, Self::Error>; + fn try_from_exact(value: &PyObjectRef) -> Result<&Self, PyDowncastError>; /// Cast from a concrete Python object type to PyObject. - fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, Self::Error>; + fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>; /// Cast from a concrete Python object type to PyObject. With exact type check. - fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, Self::Error>; + fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>; } // TryFrom implies TryInto @@ -233,18 +230,18 @@ impl PyTryInto for PyObjectRef where U: PyTryFrom, { - type Error = U::Error; + type Error = PyDowncastError; - fn try_into(&self) -> Result<&U, U::Error> { + fn try_into(&self) -> Result<&U, PyDowncastError> { U::try_from(self) } - fn try_into_exact(&self) -> Result<&U, U::Error> { + fn try_into_exact(&self) -> Result<&U, PyDowncastError> { U::try_from_exact(self) } - fn try_into_mut(&self) -> Result<&mut U, U::Error> { + fn try_into_mut(&self) -> Result<&mut U, PyDowncastError> { U::try_from_mut(self) } - fn try_into_mut_exact(&self) -> Result<&mut U, U::Error> { + fn try_into_mut_exact(&self) -> Result<&mut U, PyDowncastError> { U::try_from_mut_exact(self) } } @@ -253,9 +250,7 @@ impl PyTryFrom for T where T: PyTypeInfo, { - type Error = PyDowncastError; - - fn try_from(value: &PyObjectRef) -> Result<&T, Self::Error> { + fn try_from(value: &PyObjectRef) -> Result<&T, PyDowncastError> { unsafe { if T::is_instance(value.as_ptr()) { let ptr = if T::OFFSET == 0 { @@ -270,7 +265,7 @@ where } } - fn try_from_exact(value: &PyObjectRef) -> Result<&T, Self::Error> { + fn try_from_exact(value: &PyObjectRef) -> Result<&T, PyDowncastError> { unsafe { if T::is_exact_instance(value.as_ptr()) { let ptr = if T::OFFSET == 0 { @@ -285,7 +280,7 @@ where } } - fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, Self::Error> { + fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> { unsafe { if T::is_instance(value.as_ptr()) { let ptr = if T::OFFSET == 0 { @@ -300,7 +295,7 @@ where } } - fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, Self::Error> { + fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> { unsafe { if T::is_exact_instance(value.as_ptr()) { let ptr = if T::OFFSET == 0 { diff --git a/src/freelist.rs b/src/freelist.rs index 734e10a5..15c98e2b 100644 --- a/src/freelist.rs +++ b/src/freelist.rs @@ -6,6 +6,7 @@ use std; use err::PyResult; use ffi; use python::Python; +use std::os::raw::c_void; use typeob::{PyObjectAlloc, PyTypeInfo}; /// Implementing this trait for custom class adds free allocation list to class. @@ -92,13 +93,13 @@ where if let Some(obj) = ::get_free_list().insert(obj) { match (*T::type_object()).tp_free { - Some(free) => free(obj as *mut ::c_void), + Some(free) => free(obj as *mut c_void), None => { let ty = ffi::Py_TYPE(obj); if ffi::PyType_IS_GC(ty) != 0 { - ffi::PyObject_GC_Del(obj as *mut ::c_void); + ffi::PyObject_GC_Del(obj as *mut c_void); } else { - ffi::PyObject_Free(obj as *mut ::c_void); + ffi::PyObject_Free(obj as *mut c_void); } // For heap types, PyType_GenericAlloc calls INCREF on the type objects, @@ -117,13 +118,13 @@ where if let Some(obj) = ::get_free_list().insert(obj) { match (*T::type_object()).tp_free { - Some(free) => free(obj as *mut ::c_void), + Some(free) => free(obj as *mut c_void), None => { let ty = ffi::Py_TYPE(obj); if ffi::PyType_IS_GC(ty) != 0 { - ffi::PyObject_GC_Del(obj as *mut ::c_void); + ffi::PyObject_GC_Del(obj as *mut c_void); } else { - ffi::PyObject_Free(obj as *mut ::c_void); + ffi::PyObject_Free(obj as *mut c_void); } // For heap types, PyType_GenericAlloc calls INCREF on the type objects, diff --git a/src/lib.rs b/src/lib.rs index b0734bc1..c1e1ac2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,7 +120,9 @@ //! //! [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) can be used to generate a python package and includes the commands above by default. See [examples/word-count](examples/word-count) and the associated setup.py. -extern crate libc; +// We need those types in the macro exports +#[doc(hidden)] +pub extern crate libc; extern crate pyo3cls; extern crate spin; // We need that reexport for wrap_function @@ -214,7 +216,3 @@ pub mod prelude; pub mod python; mod pythonrun; pub mod typeob; - -// re-export for simplicity -#[doc(hidden)] -pub use std::os::raw::*; diff --git a/src/object.rs b/src/object.rs index 6e0f5a05..6bd4708f 100644 --- a/src/object.rs +++ b/src/object.rs @@ -14,6 +14,7 @@ use pythonrun; /// Safe wrapper around unsafe `*mut ffi::PyObject` pointer. #[derive(Debug)] +#[repr(transparent)] pub struct PyObject(*mut ffi::PyObject); // `PyObject` is thread-safe, any python related operations require a Python<'p> token. @@ -136,9 +137,9 @@ impl PyObject { } /// Casts the PyObject to a concrete Python object type. - pub fn cast_as(&self, py: Python) -> Result<&D, ::Error> + pub fn cast_as(&self, py: Python) -> Result<&D, PyDowncastError> where - D: PyTryFrom, + D: PyTryFrom, { D::try_from(self.as_ref(py)) } diff --git a/src/objectprotocol.rs b/src/objectprotocol.rs index f951c060..482dc034 100644 --- a/src/objectprotocol.rs +++ b/src/objectprotocol.rs @@ -177,9 +177,9 @@ pub trait ObjectProtocol { Self: PyTypeInfo; /// Casts the PyObject to a concrete Python object type. - fn cast_as<'a, D>(&'a self) -> Result<&'a D, ::Error> + fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError> where - D: PyTryFrom, + D: PyTryFrom, &'a PyObjectRef: std::convert::From<&'a Self>; /// Extracts some type from the Python object. @@ -500,9 +500,9 @@ where unsafe { self.py().mut_from_borrowed_ptr(self.as_ptr()) } } - fn cast_as<'a, D>(&'a self) -> Result<&'a D, ::Error> + fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError> where - D: PyTryFrom, + D: PyTryFrom, &'a PyObjectRef: std::convert::From<&'a Self>, { D::try_from(self.into()) diff --git a/src/objects/mod.rs b/src/objects/mod.rs index ec9b0f10..79592552 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -93,7 +93,6 @@ macro_rules! pyobject_native_type( ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { pyobject_native_type_named!($name $(,$type_param)*); pyobject_native_type_convert!($name, $typeobject, $checkfunction $(,$type_param)*); - pyobject_downcast!($name, $checkfunction $(,$type_param)*); impl<'a, $($type_param,)*> ::std::convert::From<&'a $name> for &'a $crate::PyObjectRef { fn from(ob: &'a $name) -> Self { @@ -210,7 +209,6 @@ use python::ToPyPointer; pub struct PyObjectRef(::PyObject); pyobject_native_type_named!(PyObjectRef); pyobject_native_type_convert!(PyObjectRef, ffi::PyBaseObject_Type, ffi::PyObject_Check); -pyobject_downcast!(PyObjectRef, ffi::PyObject_Check); mod boolobject; mod bytearray; diff --git a/src/objects/sequence.rs b/src/objects/sequence.rs index 5fb908af..78388bc6 100644 --- a/src/objects/sequence.rs +++ b/src/objects/sequence.rs @@ -16,7 +16,6 @@ use python::ToPyPointer; #[repr(transparent)] pub struct PySequence(PyObject); pyobject_native_type_named!(PySequence); -pyobject_downcast!(PySequence, ffi::PySequence_Check); impl PySequence { /// Returns the number of objects in sequence. This is equivalent to Python `len()`. @@ -279,9 +278,7 @@ where } impl PyTryFrom for PySequence { - type Error = PyDowncastError; - - fn try_from(value: &PyObjectRef) -> Result<&PySequence, Self::Error> { + fn try_from(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> { unsafe { if ffi::PySequence_Check(value.as_ptr()) != 0 { let ptr = value as *const _ as *mut u8 as *mut PySequence; @@ -292,11 +289,11 @@ impl PyTryFrom for PySequence { } } - fn try_from_exact(value: &PyObjectRef) -> Result<&PySequence, Self::Error> { + fn try_from_exact(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> { ::try_from(value) } - fn try_from_mut(value: &PyObjectRef) -> Result<&mut PySequence, Self::Error> { + fn try_from_mut(value: &PyObjectRef) -> Result<&mut PySequence, PyDowncastError> { unsafe { if ffi::PySequence_Check(value.as_ptr()) != 0 { let ptr = value as *const _ as *mut u8 as *mut PySequence; @@ -307,7 +304,7 @@ impl PyTryFrom for PySequence { } } - fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut PySequence, Self::Error> { + fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut PySequence, PyDowncastError> { PySequence::try_from_mut(value) } } diff --git a/src/typeob.rs b/src/typeob.rs index 1aa3528c..88a1f1d4 100644 --- a/src/typeob.rs +++ b/src/typeob.rs @@ -12,6 +12,7 @@ use err::{PyErr, PyResult}; use instance::{Py, PyObjectWithToken, PyToken}; use objects::PyType; use python::{IntoPyPointer, Python}; +use std::os::raw::c_void; use {class, ffi, pythonrun}; /// Python type information. @@ -65,10 +66,7 @@ pub const PY_TYPE_FLAG_BASETYPE: usize = 1 << 2; /// The instances of this type have a dictionary containing instance variables pub const PY_TYPE_FLAG_DICT: usize = 1 << 3; -impl<'a, T: ?Sized> PyTypeInfo for &'a T -where - T: PyTypeInfo, -{ +impl<'a, T: PyTypeInfo + ?Sized> PyTypeInfo for &'a T { type Type = T::Type; type BaseType = T::BaseType; const NAME: &'static str = T::NAME; @@ -262,13 +260,13 @@ where } match (*T::type_object()).tp_free { - Some(free) => free(obj as *mut ::c_void), + Some(free) => free(obj as *mut c_void), None => { let ty = ffi::Py_TYPE(obj); if ffi::PyType_IS_GC(ty) != 0 { - ffi::PyObject_GC_Del(obj as *mut ::c_void); + ffi::PyObject_GC_Del(obj as *mut c_void); } else { - ffi::PyObject_Free(obj as *mut ::c_void); + ffi::PyObject_Free(obj as *mut c_void); } // For heap types, PyType_GenericAlloc calls INCREF on the type objects, @@ -285,13 +283,13 @@ where Self::drop(py, obj); match (*T::type_object()).tp_free { - Some(free) => free(obj as *mut ::c_void), + Some(free) => free(obj as *mut c_void), None => { let ty = ffi::Py_TYPE(obj); if ffi::PyType_IS_GC(ty) != 0 { - ffi::PyObject_GC_Del(obj as *mut ::c_void); + ffi::PyObject_GC_Del(obj as *mut c_void); } else { - ffi::PyObject_Free(obj as *mut ::c_void); + ffi::PyObject_Free(obj as *mut c_void); } // For heap types, PyType_GenericAlloc calls INCREF on the type objects, diff --git a/tests/test_dunder.rs b/tests/test_dunder.rs index 24388606..0aedb254 100644 --- a/tests/test_dunder.rs +++ b/tests/test_dunder.rs @@ -90,13 +90,13 @@ impl<'p> PyObjectProtocol<'p> for StringMethods { Ok(format!("format({})", format_spec)) } - fn __unicode__(&self) -> PyResult { - Ok(PyString::new(self.py(), "unicode").into()) - } - fn __bytes__(&self) -> PyResult { Ok(PyBytes::new(self.py(), b"bytes").into()) } + + fn __unicode__(&self) -> PyResult { + Ok(PyString::new(self.py(), "unicode").into()) + } } #[cfg(Py_3)]