Some api improvements

This commit is contained in:
konstin 2019-02-23 18:01:22 +01:00
parent 0cd72ac213
commit ad590bd158
65 changed files with 654 additions and 553 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ examples/*/py*
*.egg-info *.egg-info
extensions/stamps/ extensions/stamps/
pip-wheel-metadata pip-wheel-metadata
valgrind-python.supp

View File

@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3 * Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3
* Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details. * Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details.
* The `PyRef` and `PyRefMut` types, which allow to differentiate between an instance of a rust struct on the rust heap and an instance that is embedded inside a python object. By kngwyu in [#335](https://github.com/PyO3/pyo3/pull/335) * The `PyRef` and `PyRefMut` types, which allow to differentiate between an instance of a rust struct on the rust heap and an instance that is embedded inside a python object. By kngwyu in [#335](https://github.com/PyO3/pyo3/pull/335)
* Added `FromPy<T>` and `IntoPy<T>` which are equivalent to `From<T>` and `Into<T>` except that they require a gil token.
* Added `ManagedPyRef`, which should eventually replace `ToBorrowedObject`.
### Changed ### Changed
@ -27,14 +29,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* `#[pyfunction]` now supports the same arguments as `#[pyfn()]` * `#[pyfunction]` now supports the same arguments as `#[pyfn()]`
* Some macros now emit proper spanned errors instead of panics. * Some macros now emit proper spanned errors instead of panics.
* Migrated to the 2018 edition * Migrated to the 2018 edition
* Replace `IntoPyTuple` with `IntoPy<Py<PyTuple>>`. Eventually `IntoPy<T>` should replace `ToPyObject` and be itself implemented through `FromPy<T>` * `crate::types::exceptions` moved to `crate::exceptions`
* Replace `IntoPyTuple` with `IntoPy<Py<PyTuple>>`.
* `IntoPyPointer` and `ToPyPointer` moved into the crate root.
* `class::CompareOp` moved into `class::basic::CompareOp`
* PyTypeObject is now a direct subtrait PyTypeCreate, removing the old cyclical implementation in [#350](https://github.com/PyO3/pyo3/pull/350) * PyTypeObject is now a direct subtrait PyTypeCreate, removing the old cyclical implementation in [#350](https://github.com/PyO3/pyo3/pull/350)
* Add `PyList::{sort, reverse}` by chr1sj0nes in [#357](https://github.com/PyO3/pyo3/pull/357) and [#358](https://github.com/PyO3/pyo3/pull/358) * Add `PyList::{sort, reverse}` by chr1sj0nes in [#357](https://github.com/PyO3/pyo3/pull/357) and [#358](https://github.com/PyO3/pyo3/pull/358)
* Renamed the `typeob` module to `type_object`
### Removed ### Removed
* `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)). * `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)).
* Removed the unnecessary type parameter from `PyObjectAlloc` * Removed the unnecessary type parameter from `PyObjectAlloc`
* `NoArgs`. Just use an empty tuple
* `PyObjectWithGIL`. `PyNativeType` is sufficient now that PyToken is removed.
### Fixed ### Fixed

View File

@ -21,7 +21,7 @@ provides two methods:
* `call` - call callable python object. * `call` - call callable python object.
* `call_method` - call specific method on the object. * `call_method` - call specific method on the object.
Both methods accept `args` and `kwargs` arguments. The `NoArgs` object represents an empty tuple object. Both methods accept `args` and `kwargs` arguments.
```rust ```rust
use pyo3::prelude::*; use pyo3::prelude::*;
@ -87,16 +87,16 @@ fn main() {
// call object with PyDict // call object with PyDict
let kwargs = PyDict::new(py); let kwargs = PyDict::new(py);
kwargs.set_item(key1, val1); kwargs.set_item(key1, val1);
obj.call(py, NoArgs, Some(kwargs)); obj.call(py, (), Some(kwargs));
// pass arguments as Vec // pass arguments as Vec
let kwargs = vec![(key1, val1), (key2, val2)]; let kwargs = vec![(key1, val1), (key2, val2)];
obj.call(py, NoArgs, Some(kwargs.into_py_dict(py))); obj.call(py, (), Some(kwargs.into_py_dict(py)));
// pass arguments as HashMap // pass arguments as HashMap
let mut kwargs = HashMap::<&str, i32>::new(); let mut kwargs = HashMap::<&str, i32>::new();
kwargs.insert(key1, 1); kwargs.insert(key1, 1);
obj.call(py, NoArgs, Some(kwargs.into_py_dict(py))); obj.call(py, (), Some(kwargs.into_py_dict(py)));
} }
``` ```

View File

@ -18,3 +18,14 @@ cargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-ma
See [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate version of those commands. See [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate version of those commands.
## Running with Valgrind
Valgrind is a tool to detect memory managment bugs such as memory leaks.
You first need to installa debug build of python, otherwise valgrind won't produce usable results. In ubuntu there's e.g. a `python3-dbg` package.
Activate an environment with the debug interpreter and recompile. If you're on linux, use `ldd` with the name of you're binary and check that you're linking e.g. `libpython3.6dm.so.1.0` instead of `libpython3.6m.so.1.0`.
[Download the suppressions file for cpython](https://raw.githubusercontent.com/python/cpython/master/Misc/valgrind-python.supp).
Run valgrind with `valgrind --suppressions=valgrind-python.supp ./my-command --with-options`

View File

@ -101,7 +101,7 @@ To check the type of an exception, you can simply do:
# fn main() { # fn main() {
# let gil = Python::acquire_gil(); # let gil = Python::acquire_gil();
# let py = gil.python(); # let py = gil.python();
# let err = exceptions::TypeError::py_err(NoArgs); # let err = exceptions::TypeError::py_err(());
err.is_instance::<exceptions::TypeError>(py); err.is_instance::<exceptions::TypeError>(py);
# } # }
``` ```
@ -112,7 +112,7 @@ The vast majority of operations in this library will return [`PyResult<T>`](http
This is an alias for the type `Result<T, PyErr>`. This is an alias for the type `Result<T, PyErr>`.
A [`PyErr`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html) represents a Python exception. A [`PyErr`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html) represents a Python exception.
Errors within the `PyO3` library are also exposed as Python exceptions. Errors within the `Pyo3` library are also exposed as Python exceptions.
PyO3 library handles python exception in two stages. During first stage `PyErr` instance get PyO3 library handles python exception in two stages. During first stage `PyErr` instance get
created. At this stage python GIL is not required. During second stage, actual python created. At this stage python GIL is not required. During second stage, actual python

View File

@ -84,7 +84,7 @@ Currently, there are no conversions between `Fn`s in rust and callables in pytho
### Calling a python function in rust ### Calling a python function in rust
You can use `ObjectProtocol::is_callable` to check if you got a callable, which is true for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with `ObjectProtocol::call` with the args as first parameter and the kwargs (or `NoArgs`) as second parameter. There are also `ObjectProtocol::call0` with no args and `ObjectProtocol::call1` with only the args. You can use `ObjectProtocol::is_callable` to check if you got a callable, which is true for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with `ObjectProtocol::call` with the args as first parameter and the kwargs (or `None`) as second parameter. There are also `ObjectProtocol::call0` with no args and `ObjectProtocol::call1` with only the args.
### Calling rust `Fn`s in python ### Calling rust `Fn`s in python

View File

@ -110,16 +110,16 @@ impl PyClassArgs {
let flag = exp.path.segments.first().unwrap().value().ident.to_string(); let flag = exp.path.segments.first().unwrap().value().ident.to_string();
let path = match flag.as_str() { let path = match flag.as_str() {
"gc" => { "gc" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_GC} parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_GC}
} }
"weakref" => { "weakref" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_WEAKREF}
} }
"subclass" => { "subclass" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_BASETYPE} parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_BASETYPE}
} }
"dict" => { "dict" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_DICT}
} }
_ => { _ => {
return Err(syn::Error::new_spanned( return Err(syn::Error::new_spanned(
@ -250,7 +250,7 @@ fn impl_class(
FREELIST = Box::into_raw(Box::new( FREELIST = Box::into_raw(Box::new(
::pyo3::freelist::FreeList::with_capacity(#freelist))); ::pyo3::freelist::FreeList::with_capacity(#freelist)));
<#cls as ::pyo3::typeob::PyTypeObject>::init_type(); <#cls as ::pyo3::type_object::PyTypeObject>::init_type();
} }
&mut *FREELIST &mut *FREELIST
} }
@ -259,7 +259,7 @@ fn impl_class(
} }
} else { } else {
quote! { quote! {
impl ::pyo3::typeob::PyObjectAlloc for #cls {} impl ::pyo3::type_object::PyObjectAlloc for #cls {}
} }
} }
}; };
@ -280,9 +280,9 @@ fn impl_class(
let mut has_dict = false; let mut has_dict = false;
for f in attr.flags.iter() { for f in attr.flags.iter() {
if let syn::Expr::Path(ref epath) = f { if let syn::Expr::Path(ref epath) = f {
if epath.path == parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} { if epath.path == parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_WEAKREF} {
has_weakref = true; has_weakref = true;
} else if epath.path == parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} { } else if epath.path == parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_DICT} {
has_dict = true; has_dict = true;
} }
} }
@ -304,7 +304,7 @@ fn impl_class(
let flags = &attr.flags; let flags = &attr.flags;
quote! { quote! {
impl ::pyo3::typeob::PyTypeInfo for #cls { impl ::pyo3::type_object::PyTypeInfo for #cls {
type Type = #cls; type Type = #cls;
type BaseType = #base; type BaseType = #base;
@ -319,7 +319,7 @@ fn impl_class(
const OFFSET: isize = { const OFFSET: isize = {
// round base_size up to next multiple of align // round base_size up to next multiple of align
( (
(<#base as ::pyo3::typeob::PyTypeInfo>::SIZE + (<#base as ::pyo3::type_object::PyTypeInfo>::SIZE +
::std::mem::align_of::<#cls>() - 1) / ::std::mem::align_of::<#cls>() - 1) /
::std::mem::align_of::<#cls>() * ::std::mem::align_of::<#cls>() ::std::mem::align_of::<#cls>() * ::std::mem::align_of::<#cls>()
) as isize ) as isize

View File

@ -62,7 +62,7 @@ pub fn impl_wrap(
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf); let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _result = { let _result = {
::pyo3::IntoPyResult::into_py_result(#body) ::pyo3::derive_utils::IntoPyResult::into_py_result(#body)
}; };
::pyo3::callback::cb_convert( ::pyo3::callback::cb_convert(
@ -136,12 +136,12 @@ pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> T
_args: *mut ::pyo3::ffi::PyObject, _args: *mut ::pyo3::ffi::PyObject,
_kwargs: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject _kwargs: *mut ::pyo3::ffi::PyObject) -> *mut ::pyo3::ffi::PyObject
{ {
use ::pyo3::typeob::PyTypeInfo; use ::pyo3::type_object::PyTypeInfo;
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = ::pyo3::GILPool::new(); let _pool = ::pyo3::GILPool::new();
let _py = ::pyo3::Python::assume_gil_acquired(); let _py = ::pyo3::Python::assume_gil_acquired();
match ::pyo3::typeob::PyRawObject::new(_py, #cls::type_object(), _cls) { match ::pyo3::type_object::PyRawObject::new(_py, #cls::type_object(), _cls) {
Ok(_obj) => { Ok(_obj) => {
let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args); let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args);
let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); let _kwargs: Option<&::pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -355,7 +355,7 @@ pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream {
if spec.args.is_empty() { if spec.args.is_empty() {
return quote! { return quote! {
let _result = { let _result = {
::pyo3::IntoPyResult::into_py_result(#body) ::pyo3::derive_utils::IntoPyResult::into_py_result(#body)
}; };
}; };
} }
@ -415,7 +415,7 @@ pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream {
#(#param_conversion)* #(#param_conversion)*
::pyo3::IntoPyResult::into_py_result(#body) ::pyo3::derive_utils::IntoPyResult::into_py_result(#body)
})(); })();
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use syn;
pub fn print_err(msg: String, t: TokenStream) { pub fn print_err(msg: String, t: TokenStream) {
println!("Error: {} in '{}'", msg, t.to_string()); println!("Error: {} in '{}'", msg, t.to_string());

View File

@ -20,8 +20,9 @@
use crate::err::{self, PyResult}; use crate::err::{self, PyResult};
use crate::exceptions; use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::python::{Python, ToPyPointer};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::Python;
use crate::ToPyPointer;
use libc; use libc;
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw; use std::os::raw;
@ -661,7 +662,7 @@ impl_element!(f64, Float);
mod test { mod test {
use super::PyBuffer; use super::PyBuffer;
use crate::ffi; use crate::ffi;
use crate::python::Python; use crate::Python;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;

View File

@ -2,11 +2,11 @@
//! Utilities for a Python callable object that invokes a Rust function. //! Utilities for a Python callable object that invokes a Rust function.
use crate::conversion::IntoPyObject;
use crate::err::PyResult; use crate::err::PyResult;
use crate::exceptions::OverflowError;
use crate::ffi::{self, Py_hash_t}; use crate::ffi::{self, Py_hash_t};
use crate::python::{IntoPyPointer, Python}; use crate::Python;
use crate::types::exceptions::OverflowError; use crate::{IntoPyObject, IntoPyPointer};
use std::os::raw::c_int; use std::os::raw::c_int;
use std::{isize, ptr}; use std::{isize, ptr};

View File

@ -10,17 +10,29 @@
use crate::callback::{BoolCallbackConverter, HashConverter, PyObjectCallbackConverter}; use crate::callback::{BoolCallbackConverter, HashConverter, PyObjectCallbackConverter};
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::conversion::{FromPyObject, IntoPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::{IntoPyPointer, Python}; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo; use crate::types::PyObjectRef;
use crate::types::{exceptions, PyObjectRef}; use crate::IntoPyPointer;
use crate::CompareOp; use crate::Python;
use crate::{FromPyObject, IntoPyObject};
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr; use std::ptr;
/// Operators for the __richcmp__ method
#[derive(Debug)]
pub enum CompareOp {
Lt = ffi::Py_LT as isize,
Le = ffi::Py_LE as isize,
Eq = ffi::Py_EQ as isize,
Ne = ffi::Py_NE as isize,
Gt = ffi::Py_GT as isize,
Ge = ffi::Py_GE as isize,
}
/// Basic python class customization /// Basic python class customization
#[allow(unused_variables)] #[allow(unused_variables)]
pub trait PyObjectProtocol<'p>: PyTypeInfo { pub trait PyObjectProtocol<'p>: PyTypeInfo {

View File

@ -7,7 +7,7 @@
use crate::callback::UnitCallbackConverter; use crate::callback::UnitCallbackConverter;
use crate::err::PyResult; use crate::err::PyResult;
use crate::ffi; use crate::ffi;
use crate::typeob::PyTypeInfo; use crate::type_object::PyTypeInfo;
use std::os::raw::c_int; use std::os::raw::c_int;
/// Buffer protocol interface /// Buffer protocol interface

View File

@ -6,7 +6,7 @@
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::err::PyResult; use crate::err::PyResult;
use crate::typeob::PyTypeInfo; use crate::type_object::PyTypeInfo;
/// Context manager interface /// Context manager interface
#[allow(unused_variables)] #[allow(unused_variables)]

View File

@ -7,11 +7,11 @@
use crate::callback::{PyObjectCallbackConverter, UnitCallbackConverter}; use crate::callback::{PyObjectCallbackConverter, UnitCallbackConverter};
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::conversion::{FromPyObject, IntoPyObject};
use crate::err::PyResult; use crate::err::PyResult;
use crate::ffi; use crate::ffi;
use crate::typeob::PyTypeInfo; use crate::type_object::PyTypeInfo;
use crate::types::{PyObjectRef, PyType}; use crate::types::{PyObjectRef, PyType};
use crate::{FromPyObject, IntoPyObject};
use std::os::raw::c_int; use std::os::raw::c_int;
/// Descriptor interface /// Descriptor interface

View File

@ -4,8 +4,9 @@
//! //!
use crate::ffi; use crate::ffi;
use crate::python::{Python, ToPyPointer}; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo; use crate::Python;
use crate::ToPyPointer;
use std::os::raw::{c_int, c_void}; use std::os::raw::{c_int, c_void};
#[repr(transparent)] #[repr(transparent)]

View File

@ -3,12 +3,13 @@
//! Trait and support implementation for implementing iterators //! Trait and support implementation for implementing iterators
use crate::callback::{CallbackConverter, PyObjectCallbackConverter}; use crate::callback::{CallbackConverter, PyObjectCallbackConverter};
use crate::conversion::IntoPyObject;
use crate::err::PyResult; use crate::err::PyResult;
use crate::ffi; use crate::ffi;
use crate::instance::PyRefMut; use crate::instance::PyRefMut;
use crate::python::{IntoPyPointer, Python}; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo; use crate::IntoPyObject;
use crate::IntoPyPointer;
use crate::Python;
use std::ptr; use std::ptr;
/// Python Iterator Interface. /// Python Iterator Interface.

View File

@ -5,12 +5,12 @@
use crate::callback::{LenResultConverter, PyObjectCallbackConverter}; use crate::callback::{LenResultConverter, PyObjectCallbackConverter};
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::conversion::{FromPyObject, IntoPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::python::Python; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo; use crate::Python;
use crate::types::exceptions; use crate::{FromPyObject, IntoPyObject};
/// Mapping interface /// Mapping interface
#[allow(unused_variables)] #[allow(unused_variables)]

View File

@ -21,23 +21,10 @@ pub use self::basic::PyObjectProtocol;
pub use self::buffer::PyBufferProtocol; pub use self::buffer::PyBufferProtocol;
pub use self::context::PyContextProtocol; pub use self::context::PyContextProtocol;
pub use self::descr::PyDescrProtocol; pub use self::descr::PyDescrProtocol;
pub use self::gc::{PyGCProtocol, PyTraverseError, PyVisit};
pub use self::iter::PyIterProtocol; pub use self::iter::PyIterProtocol;
pub use self::mapping::PyMappingProtocol; pub use self::mapping::PyMappingProtocol;
pub use self::methods::{PyGetterDef, PyMethodDef, PyMethodDefType, PyMethodType, PySetterDef};
pub use self::number::PyNumberProtocol; pub use self::number::PyNumberProtocol;
pub use self::pyasync::PyAsyncProtocol; pub use self::pyasync::PyAsyncProtocol;
pub use self::sequence::PySequenceProtocol; pub use self::sequence::PySequenceProtocol;
pub use self::gc::{PyGCProtocol, PyTraverseError, PyVisit};
pub use self::methods::{PyGetterDef, PyMethodDef, PyMethodDefType, PyMethodType, PySetterDef};
use crate::ffi;
/// Operators for the __richcmp__ method
#[derive(Debug)]
pub enum CompareOp {
Lt = ffi::Py_LT as isize,
Le = ffi::Py_LE as isize,
Eq = ffi::Py_EQ as isize,
Ne = ffi::Py_NE as isize,
Gt = ffi::Py_GT as isize,
Ge = ffi::Py_GE as isize,
}

View File

@ -8,7 +8,7 @@ use crate::class::basic::PyObjectProtocolImpl;
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::err::PyResult; use crate::err::PyResult;
use crate::ffi; use crate::ffi;
use crate::typeob::PyTypeInfo; use crate::type_object::PyTypeInfo;
use crate::{FromPyObject, IntoPyObject}; use crate::{FromPyObject, IntoPyObject};
/// Number interface /// Number interface

View File

@ -12,7 +12,7 @@ use crate::callback::PyObjectCallbackConverter;
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::err::PyResult; use crate::err::PyResult;
use crate::ffi; use crate::ffi;
use crate::typeob::PyTypeInfo; use crate::type_object::PyTypeInfo;
/// Python Async/Await support interface. /// Python Async/Await support interface.
/// ///
@ -190,9 +190,10 @@ impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
mod anext { mod anext {
use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl}; use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
use crate::callback::CallbackConverter; use crate::callback::CallbackConverter;
use crate::conversion::IntoPyObject;
use crate::ffi; use crate::ffi;
use crate::python::{IntoPyPointer, Python}; use crate::IntoPyObject;
use crate::IntoPyPointer;
use crate::Python;
use std::ptr; use std::ptr;
pub struct IterANextResultConverter; pub struct IterANextResultConverter;

View File

@ -4,13 +4,14 @@
//! Trait and support implementation for implementing sequence //! Trait and support implementation for implementing sequence
use crate::callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter}; use crate::callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter};
use crate::conversion::{FromPyObject, IntoPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::Python; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo; use crate::types::PyObjectRef;
use crate::types::{exceptions, PyObjectRef}; use crate::Python;
use crate::{FromPyObject, IntoPyObject};
use std::os::raw::c_int; use std::os::raw::c_int;
/// Sequece interface /// Sequece interface

View File

@ -1,13 +1,73 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
//! This module contains some conversion traits //! Conversions between various states of rust and python types and their wrappers.
use crate::err::{PyDowncastError, PyResult}; use crate::err::{PyDowncastError, PyResult};
use crate::ffi; use crate::ffi;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo;
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::types::PyTuple;
use crate::Py;
use crate::Python;
/// This trait allows retrieving the underlying FFI pointer from Python objects.
///
/// This trait is implemented for types that internally wrap a pointer to a python object.
pub trait ToPyPointer {
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
fn as_ptr(&self) -> *mut ffi::PyObject;
}
/// This trait allows retrieving the underlying FFI pointer from Python objects.
pub trait IntoPyPointer {
/// Retrieves the underlying FFI pointer. Whether pointer owned or borrowed
/// depends on implementation.
fn into_ptr(self) -> *mut ffi::PyObject;
}
/// Convert `None` into a null pointer.
impl<T> ToPyPointer for Option<T>
where
T: ToPyPointer,
{
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
match *self {
Some(ref t) => t.as_ptr(),
None => std::ptr::null_mut(),
}
}
}
/// Convert `None` into a null pointer.
impl<T> IntoPyPointer for Option<T>
where
T: IntoPyPointer,
{
#[inline]
fn into_ptr(self) -> *mut ffi::PyObject {
match self {
Some(t) => t.into_ptr(),
None => std::ptr::null_mut(),
}
}
}
impl<'a, T> IntoPyPointer for &'a T
where
T: ToPyPointer,
{
fn into_ptr(self) -> *mut ffi::PyObject {
let ptr = self.as_ptr();
if !ptr.is_null() {
unsafe {
ffi::Py_INCREF(ptr);
}
}
ptr
}
}
/// Conversion trait that allows various objects to be converted into `PyObject` /// Conversion trait that allows various objects to be converted into `PyObject`
pub trait ToPyObject { pub trait ToPyObject {
@ -18,7 +78,9 @@ pub trait ToPyObject {
/// This trait has two implementations: The slow one is implemented for /// This trait has two implementations: The slow one is implemented for
/// all [ToPyObject] and creates a new object using [ToPyObject::to_object], /// all [ToPyObject] and creates a new object using [ToPyObject::to_object],
/// while the fast one is only implemented for ToPyPointer (we know /// while the fast one is only implemented for ToPyPointer (we know
/// that every ToPyObject is also ToPyObject) and uses [ToPyPointer::as_ptr()] /// that every ToPyPointer is also ToPyObject) and uses [ToPyPointer::as_ptr()]
///
/// This trait should eventually be replaced with [ManagedPyRef](crate::ManagedPyRef).
pub trait ToBorrowedObject: ToPyObject { pub trait ToBorrowedObject: ToPyObject {
/// Converts self into a Python object and calls the specified closure /// Converts self into a Python object and calls the specified closure
/// on the native FFI pointer underlying the Python object. /// on the native FFI pointer underlying the Python object.
@ -52,12 +114,35 @@ where
} }
} }
/// Similar to [std::convert::Into], just that it requires a gil token and there's /// Similar to [std::convert::From], just that it requires a gil token.
/// currently no corresponding [std::convert::From] part. pub trait FromPy<T>: Sized {
/// Performs the conversion.
fn from_py(_: T, py: Python) -> Self;
}
/// Similar to [std::convert::Into], just that it requires a gil token.
pub trait IntoPy<T>: Sized { pub trait IntoPy<T>: Sized {
/// Performs the conversion.
fn into_py(self, py: Python) -> T; fn into_py(self, py: Python) -> T;
} }
// From implies Into
impl<T, U> IntoPy<U> for T
where
U: FromPy<T>,
{
fn into_py(self, py: Python) -> U {
U::from_py(self, py)
}
}
// From (and thus Into) is reflexive
impl<T> FromPy<T> for T {
fn from_py(t: T, _: Python) -> T {
t
}
}
/// Conversion trait that allows various objects to be converted into `PyObject` /// Conversion trait that allows various objects to be converted into `PyObject`
/// by consuming original object. /// by consuming original object.
pub trait IntoPyObject { pub trait IntoPyObject {
@ -202,20 +287,17 @@ where
/// Trait implemented by Python object types that allow a checked downcast. /// Trait implemented by Python object types that allow a checked downcast.
/// This trait is similar to `std::convert::TryInto` /// This trait is similar to `std::convert::TryInto`
pub trait PyTryInto<T>: Sized { pub trait PyTryInto<T>: Sized {
/// The type returned in the event of a conversion error.
type Error;
/// Cast from PyObject to a concrete Python object type. /// Cast from PyObject to a concrete Python object type.
fn try_into(&self) -> Result<&T, Self::Error>; fn try_into(&self) -> Result<&T, PyDowncastError>;
/// Cast from PyObject to a concrete Python object type. With exact type check. /// Cast from PyObject to a concrete Python object type. With exact type check.
fn try_into_exact(&self) -> Result<&T, Self::Error>; fn try_into_exact(&self) -> Result<&T, PyDowncastError>;
/// Cast from PyObject to a concrete Python object type. /// Cast from PyObject to a concrete Python object type.
fn try_into_mut(&self) -> Result<&mut T, Self::Error>; fn try_into_mut(&self) -> Result<&mut T, PyDowncastError>;
/// Cast from PyObject to a concrete Python object type. With exact type check. /// Cast from PyObject to a concrete Python object type. With exact type check.
fn try_into_mut_exact(&self) -> Result<&mut T, Self::Error>; fn try_into_mut_exact(&self) -> Result<&mut T, PyDowncastError>;
} }
/// Trait implemented by Python object types that allow a checked downcast. /// Trait implemented by Python object types that allow a checked downcast.
@ -250,8 +332,6 @@ impl<U> PyTryInto<U> for PyObjectRef
where where
U: for<'v> PyTryFrom<'v>, U: for<'v> PyTryFrom<'v>,
{ {
type Error = PyDowncastError;
fn try_into(&self) -> Result<&U, PyDowncastError> { fn try_into(&self) -> Result<&U, PyDowncastError> {
U::try_from(self) U::try_from(self)
} }
@ -339,34 +419,20 @@ where
} }
} }
#[doc(hidden)] /// Converts `()` to an empty Python tuple.
/// This trait wraps a T: IntoPyObject into PyResult<T> while PyResult<T> remains PyResult<T>. impl FromPy<()> for Py<PyTuple> {
/// fn from_py(_: (), py: Python) -> Py<PyTuple> {
/// This is necessary because proc macros run before typechecking and can't decide PyTuple::empty(py)
/// whether a return type is a (possibly aliased) PyResult or not. It is also quite handy because
/// the codegen is currently built on the assumption that all functions return a PyResult.
pub trait IntoPyResult<T> {
fn into_py_result(self) -> PyResult<T>;
}
impl<T: IntoPyObject> IntoPyResult<T> for T {
fn into_py_result(self) -> PyResult<T> {
Ok(self)
}
}
impl<T: IntoPyObject> IntoPyResult<T> for PyResult<T> {
fn into_py_result(self) -> PyResult<T> {
self
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::PyTryFrom;
use crate::types::PyList; use crate::types::PyList;
use crate::Python; use crate::Python;
use super::PyTryFrom;
#[test] #[test]
fn test_try_from_unchecked() { fn test_try_from_unchecked() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();

View File

@ -4,15 +4,14 @@
//! Functionality for the code generated by the derive backend //! Functionality for the code generated by the derive backend
use crate::conversion::PyTryFrom;
use crate::err::PyResult; use crate::err::PyResult;
use crate::exceptions::TypeError; use crate::exceptions::TypeError;
use crate::ffi; use crate::ffi;
use crate::init_once; use crate::init_once;
use crate::types::PyModule; use crate::types::{PyDict, PyModule, PyObjectRef, PyString, PyTuple};
use crate::types::{PyDict, PyObjectRef, PyString, PyTuple};
use crate::GILPool; use crate::GILPool;
use crate::Python; use crate::Python;
use crate::{IntoPyObject, PyTryFrom};
use std::ptr; use std::ptr;
/// Description of a python parameter; used for `parse_args()`. /// Description of a python parameter; used for `parse_args()`.
@ -111,14 +110,13 @@ pub fn parse_fn_args<'p>(
} }
#[cfg(Py_3)] #[cfg(Py_3)]
#[doc(hidden)]
/// Builds a module (or null) from a user given initializer. Used for `#[pymodule]`. /// Builds a module (or null) from a user given initializer. Used for `#[pymodule]`.
pub unsafe fn make_module( pub unsafe fn make_module(
name: &str, name: &str,
doc: &str, doc: &str,
initializer: impl Fn(Python, &PyModule) -> PyResult<()>, initializer: impl Fn(Python, &PyModule) -> PyResult<()>,
) -> *mut ffi::PyObject { ) -> *mut ffi::PyObject {
use crate::python::IntoPyPointer; use crate::IntoPyPointer;
init_once(); init_once();
@ -196,3 +194,24 @@ pub unsafe fn make_module(
e.restore(py) e.restore(py)
} }
} }
/// This trait wraps a T: IntoPyObject into PyResult<T> while PyResult<T> remains PyResult<T>.
///
/// This is necessary because proc macros run before typechecking and can't decide
/// whether a return type is a (possibly aliased) PyResult or not. It is also quite handy because
/// the codegen is currently built on the assumption that all functions return a PyResult.
pub trait IntoPyResult<T> {
fn into_py_result(self) -> PyResult<T>;
}
impl<T: IntoPyObject> IntoPyResult<T> for T {
fn into_py_result(self) -> PyResult<T> {
Ok(self)
}
}
impl<T: IntoPyObject> IntoPyResult<T> for PyResult<T> {
fn into_py_result(self) -> PyResult<T> {
self
}
}

View File

@ -1,12 +1,15 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject}; use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::instance::Py; use crate::instance::Py;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::type_object::PyTypeObject;
use crate::typeob::PyTypeObject; use crate::types::{PyObjectRef, PyType};
use crate::types::{exceptions, PyObjectRef, PyType}; use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{IntoPyObject, ToBorrowedObject, ToPyObject};
use libc::c_int; use libc::c_int;
use std::error::Error; use std::error::Error;
use std::ffi::CString; use std::ffi::CString;
@ -54,7 +57,6 @@ impl PyErr {
/// Creates a new PyErr of type `T`. /// Creates a new PyErr of type `T`.
/// ///
/// `value` can be: /// `value` can be:
/// * `NoArgs`: the exception instance will be created using python `T()`
/// * a tuple: the exception instance will be created using python `T(*tuple)` /// * a tuple: the exception instance will be created using python `T(*tuple)`
/// * any other value: the exception instance will be created using python `T(value)` /// * any other value: the exception instance will be created using python `T(value)`
/// ///
@ -521,7 +523,7 @@ pub fn error_on_minusone(py: Python, result: c_int) -> PyResult<()> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::types::exceptions; use crate::exceptions;
use crate::{PyErr, Python}; use crate::{PyErr, Python};
#[test] #[test]

View File

@ -1,13 +1,13 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
//! This module contains the standard python exception types. //! Exception types defined by python.
use crate::conversion::ToPyObject;
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::python::{Python, ToPyPointer}; use crate::type_object::PyTypeObject;
use crate::typeob::PyTypeObject;
use crate::types::{PyObjectRef, PyTuple}; use crate::types::{PyObjectRef, PyTuple};
use crate::Python;
use crate::{ToPyObject, ToPyPointer};
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::{self, ops}; use std::{self, ops};
@ -84,12 +84,12 @@ macro_rules! import_exception {
}; };
} }
/// `impl $crate::typeob::PyTypeObject for $name` where `$name` is an exception defined in python /// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an exception defined in python
/// code. /// code.
#[macro_export] #[macro_export]
macro_rules! import_exception_type_object { macro_rules! import_exception_type_object {
($module: expr, $name: ident) => { ($module: expr, $name: ident) => {
impl $crate::typeob::PyTypeObject for $name { impl $crate::type_object::PyTypeObject for $name {
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
// We can't use lazy_static here because raw pointers aren't Send // We can't use lazy_static here because raw pointers aren't Send
static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new(); static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new();
@ -170,12 +170,12 @@ macro_rules! create_exception {
}; };
} }
/// `impl $crate::typeob::PyTypeObject for $name` where `$name` is an exception newly defined in /// `impl $crate::type_object::PyTypeObject for $name` where `$name` is an exception newly defined in
/// rust code. /// rust code.
#[macro_export] #[macro_export]
macro_rules! create_exception_type_object { macro_rules! create_exception_type_object {
($module: ident, $name: ident, $base: ty) => { ($module: ident, $name: ident, $base: ty) => {
impl $crate::typeob::PyTypeObject for $name { impl $crate::type_object::PyTypeObject for $name {
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
// We can't use lazy_static here because raw pointers aren't Send // We can't use lazy_static here because raw pointers aren't Send
static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new(); static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new();
@ -379,8 +379,8 @@ pub mod socket {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::exceptions::Exception;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::types::exceptions::Exception;
use crate::types::PyDict; use crate::types::PyDict;
use crate::{PyErr, Python}; use crate::{PyErr, Python};

View File

@ -3,68 +3,59 @@
#![cfg_attr(Py_LIMITED_API, allow(unused_imports))] #![cfg_attr(Py_LIMITED_API, allow(unused_imports))]
#![cfg_attr(feature="cargo-clippy", allow(clippy::inline_always))] #![cfg_attr(feature="cargo-clippy", allow(clippy::inline_always))]
pub use self::pymem::*; pub use self::bltinmodule::*;
pub use self::pyport::*;
pub use self::object::*;
pub use self::objimpl::*;
pub use self::pyhash::*;
pub use self::typeslots::*;
pub use self::pydebug::*;
pub use self::boolobject::*; pub use self::boolobject::*;
pub use self::bytearrayobject::*; pub use self::bytearrayobject::*;
pub use self::bytesobject::*; pub use self::bytesobject::*;
pub use self::ceval::*;
pub use self::code::*;
pub use self::codecs::*;
pub use self::compile::*;
pub use self::complexobject::*; pub use self::complexobject::*;
pub use self::descrobject::*; pub use self::descrobject::*;
pub use self::dictobject::*; pub use self::dictobject::*;
pub use self::enumobject::*; pub use self::enumobject::*;
pub use self::eval::*;
pub use self::fileobject::*; pub use self::fileobject::*;
pub use self::floatobject::*; pub use self::floatobject::*;
pub use self::frameobject::PyFrameObject;
pub use self::genobject::*; pub use self::genobject::*;
pub use self::import::*;
pub use self::intrcheck::*;
pub use self::iterobject::*; pub use self::iterobject::*;
pub use self::listobject::*; pub use self::listobject::*;
pub use self::longobject::*; pub use self::longobject::*;
pub use self::memoryobject::*; pub use self::memoryobject::*;
pub use self::methodobject::*; pub use self::methodobject::*;
pub use self::modsupport::*;
pub use self::moduleobject::*; pub use self::moduleobject::*;
pub use self::object::*;
pub use self::objectabstract::*;
pub use self::objimpl::*;
#[cfg(Py_3_6)]
pub use self::osmodule::*;
pub use self::pyarena::*;
pub use self::pycapsule::*; pub use self::pycapsule::*;
pub use self::pydebug::*;
pub use self::pyerrors::*;
pub use self::pyhash::*;
pub use self::pymem::*;
pub use self::pyport::*;
pub use self::pystate::*;
pub use self::pystrtod::*;
pub use self::pythonrun::*;
pub use self::rangeobject::*; pub use self::rangeobject::*;
pub use self::setobject::*; pub use self::setobject::*;
pub use self::sliceobject::*; pub use self::sliceobject::*;
pub use self::structseq::*; pub use self::structseq::*;
pub use self::sysmodule::*;
pub use self::traceback::*; pub use self::traceback::*;
pub use self::tupleobject::*; pub use self::tupleobject::*;
pub use self::typeslots::*;
pub use self::unicodeobject::*; pub use self::unicodeobject::*;
pub use self::warnings::*; pub use self::warnings::*;
pub use self::weakrefobject::*; pub use self::weakrefobject::*;
pub use self::codecs::*;
pub use self::pyerrors::*;
pub use self::pystate::*;
pub use self::ceval::*;
pub use self::import::*;
pub use self::intrcheck::*;
pub use self::modsupport::*;
#[cfg(Py_3_6)]
pub use self::osmodule::*;
pub use self::pyarena::*;
pub use self::pythonrun::*;
pub use self::sysmodule::*;
pub use self::bltinmodule::*;
pub use self::objectabstract::*;
pub use self::code::*;
pub use self::compile::*;
pub use self::eval::*;
pub use self::frameobject::PyFrameObject;
pub use self::pystrtod::*;
mod pyport; mod pyport;
// mod pymacro; contains nothing of interest for Rust // mod pymacro; contains nothing of interest for Rust
// mod pyatomic; contains nothing of interest for Rust // mod pyatomic; contains nothing of interest for Rust

View File

@ -3,8 +3,8 @@
//! Free allocation list //! Free allocation list
use crate::ffi; use crate::ffi;
use crate::python::Python; use crate::type_object::{pytype_drop, PyObjectAlloc, PyTypeInfo};
use crate::typeob::{pytype_drop, PyObjectAlloc, PyTypeInfo}; use crate::Python;
use std::mem; use std::mem;
use std::os::raw::c_void; use std::os::raw::c_void;

View File

@ -1,7 +1,10 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
//! Interaction with python's global interpreter lock
use crate::ffi; use crate::ffi;
use crate::python::Python;
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::Python;
use spin; use spin;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::{any, marker, rc, sync}; use std::{any, marker, rc, sync};
@ -325,10 +328,11 @@ mod array_list {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{GILPool, NonNull, ReleasePool, POOL}; use super::{GILPool, NonNull, ReleasePool, POOL};
use crate::conversion::ToPyObject;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::Python;
use crate::{ffi, pythonrun}; use crate::ToPyObject;
use crate::ToPyPointer;
use crate::{ffi, gil};
fn get_object() -> PyObject { fn get_object() -> PyObject {
// Convenience function for getting a single unique object // Convenience function for getting a single unique object
@ -342,7 +346,7 @@ mod test {
#[test] #[test]
fn test_owned() { fn test_owned() {
pythonrun::init_once(); gil::init_once();
unsafe { unsafe {
let p: &'static mut ReleasePool = &mut *POOL; let p: &'static mut ReleasePool = &mut *POOL;
@ -355,7 +359,7 @@ mod test {
empty = ffi::PyTuple_New(0); empty = ffi::PyTuple_New(0);
cnt = ffi::Py_REFCNT(empty) - 1; cnt = ffi::Py_REFCNT(empty) - 1;
let _ = pythonrun::register_owned(py, NonNull::new(empty).unwrap()); let _ = gil::register_owned(py, NonNull::new(empty).unwrap());
assert_eq!(p.owned.len(), 1); assert_eq!(p.owned.len(), 1);
} }
@ -369,7 +373,7 @@ mod test {
#[test] #[test]
fn test_owned_nested() { fn test_owned_nested() {
pythonrun::init_once(); gil::init_once();
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
@ -386,14 +390,14 @@ mod test {
empty = ffi::PyTuple_New(0); empty = ffi::PyTuple_New(0);
cnt = ffi::Py_REFCNT(empty) - 1; cnt = ffi::Py_REFCNT(empty) - 1;
let _ = pythonrun::register_owned(py, NonNull::new(empty).unwrap()); let _ = gil::register_owned(py, NonNull::new(empty).unwrap());
assert_eq!(p.owned.len(), 1); assert_eq!(p.owned.len(), 1);
{ {
let _pool = GILPool::new(); let _pool = GILPool::new();
let empty = ffi::PyTuple_New(0); let empty = ffi::PyTuple_New(0);
let _ = pythonrun::register_owned(py, NonNull::new(empty).unwrap()); let _ = gil::register_owned(py, NonNull::new(empty).unwrap());
assert_eq!(p.owned.len(), 2); assert_eq!(p.owned.len(), 2);
} }
assert_eq!(p.owned.len(), 1); assert_eq!(p.owned.len(), 1);
@ -407,7 +411,7 @@ mod test {
#[test] #[test]
fn test_borrowed() { fn test_borrowed() {
pythonrun::init_once(); gil::init_once();
unsafe { unsafe {
let p: &'static mut ReleasePool = &mut *POOL; let p: &'static mut ReleasePool = &mut *POOL;
@ -421,7 +425,7 @@ mod test {
assert_eq!(p.borrowed.len(), 0); assert_eq!(p.borrowed.len(), 0);
cnt = ffi::Py_REFCNT(obj_ptr); cnt = ffi::Py_REFCNT(obj_ptr);
pythonrun::register_borrowed(py, NonNull::new(obj_ptr).unwrap()); gil::register_borrowed(py, NonNull::new(obj_ptr).unwrap());
assert_eq!(p.borrowed.len(), 1); assert_eq!(p.borrowed.len(), 1);
assert_eq!(ffi::Py_REFCNT(obj_ptr), cnt); assert_eq!(ffi::Py_REFCNT(obj_ptr), cnt);
@ -436,7 +440,7 @@ mod test {
#[test] #[test]
fn test_borrowed_nested() { fn test_borrowed_nested() {
pythonrun::init_once(); gil::init_once();
unsafe { unsafe {
let p: &'static mut ReleasePool = &mut *POOL; let p: &'static mut ReleasePool = &mut *POOL;
@ -450,7 +454,7 @@ mod test {
assert_eq!(p.borrowed.len(), 0); assert_eq!(p.borrowed.len(), 0);
cnt = ffi::Py_REFCNT(obj_ptr); cnt = ffi::Py_REFCNT(obj_ptr);
pythonrun::register_borrowed(py, NonNull::new(obj_ptr).unwrap()); gil::register_borrowed(py, NonNull::new(obj_ptr).unwrap());
assert_eq!(p.borrowed.len(), 1); assert_eq!(p.borrowed.len(), 1);
assert_eq!(ffi::Py_REFCNT(obj_ptr), cnt); assert_eq!(ffi::Py_REFCNT(obj_ptr), cnt);
@ -458,7 +462,7 @@ mod test {
{ {
let _pool = GILPool::new(); let _pool = GILPool::new();
assert_eq!(p.borrowed.len(), 1); assert_eq!(p.borrowed.len(), 1);
pythonrun::register_borrowed(py, NonNull::new(obj_ptr).unwrap()); gil::register_borrowed(py, NonNull::new(obj_ptr).unwrap());
assert_eq!(p.borrowed.len(), 2); assert_eq!(p.borrowed.len(), 2);
} }
@ -475,7 +479,7 @@ mod test {
#[test] #[test]
fn test_pyobject_drop() { fn test_pyobject_drop() {
pythonrun::init_once(); gil::init_once();
unsafe { unsafe {
let p: &'static mut ReleasePool = &mut *POOL; let p: &'static mut ReleasePool = &mut *POOL;

View File

@ -1,32 +1,31 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::gil;
use crate::instance; use crate::instance;
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::type_object::PyTypeCreate;
use crate::pythonrun; use crate::type_object::{PyTypeInfo, PyTypeObject};
use crate::typeob::PyTypeCreate;
use crate::typeob::{PyTypeInfo, PyTypeObject};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPyObject, ToPyObject};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
/// Any instance that is managed Python can have access to `gil`. /// Types that are built into the python interpreter.
/// ///
/// Originally, this was given to all classes with a `PyToken` field, but since `PyToken` was /// pyo3 is designed in a way that that all references to those types are bound to the GIL,
/// removed this is only given to native types. /// which is why you can get a token from all references of those types.
pub trait PyObjectWithGIL: Sized { pub trait PyNativeType: Sized {
fn py(&self) -> Python; fn py(&self) -> Python;
} }
#[doc(hidden)]
pub trait PyNativeType: PyObjectWithGIL {}
/// A special reference of type `T`. `PyRef<T>` refers a instance of T, which exists in the Python /// A special reference of type `T`. `PyRef<T>` refers a instance of T, which exists in the Python
/// heap as a part of a Python object. /// heap as a part of a Python object.
/// ///
@ -267,21 +266,19 @@ unsafe impl<T> Send for Py<T> {}
unsafe impl<T> Sync for Py<T> {} unsafe impl<T> Sync for Py<T> {}
impl<T> Py<T> impl<T> Py<T> {
where
T: PyTypeCreate + PyTypeObject,
{
/// Create new instance of T and move it under python management /// Create new instance of T and move it under python management
pub fn new(py: Python, value: T) -> PyResult<Py<T>> { pub fn new(py: Python, value: T) -> PyResult<Py<T>>
where
T: PyTypeCreate,
{
let ob = T::create(py)?; let ob = T::create(py)?;
ob.init(value); ob.init(value);
let ob = unsafe { Py::from_owned_ptr(ob.into_ptr()) }; let ob = unsafe { Py::from_owned_ptr(ob.into_ptr()) };
Ok(ob) Ok(ob)
} }
}
impl<T> Py<T> {
/// Creates a `Py<T>` instance for the given FFI pointer. /// Creates a `Py<T>` instance for the given FFI pointer.
/// This moves ownership over the pointer into the `Py<T>`. /// This moves ownership over the pointer into the `Py<T>`.
/// Undefined behavior if the pointer is NULL or invalid. /// Undefined behavior if the pointer is NULL or invalid.
@ -440,7 +437,7 @@ impl<T> PartialEq for Py<T> {
impl<T> Drop for Py<T> { impl<T> Drop for Py<T> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
pythonrun::register_pointer(self.0); gil::register_pointer(self.0);
} }
} }
} }
@ -501,3 +498,140 @@ where
} }
} }
} }
/// Reference to a converted [ToPyObject].
///
/// Many methods want to take anything that can be converted into a python object. This type
/// takes care of both types types that are already python object (i.e. implement
/// [ToPyPointer]) and those that don't (i.e. [ToPyObject] types).
/// For the [ToPyPointer] types, we just use the borrowed pointer, which is a lot faster
/// and simpler than creating a new extra object. The remaning [ToPyObject] types are
/// converted to python objects, the owned pointer is stored and decref'd on drop.
///
/// # Example
///
/// ```
/// use pyo3::ffi;
/// use pyo3::{ToPyObject, ToPyPointer, PyNativeType, ManagedPyRef};
/// use pyo3::types::{PyDict, PyObjectRef};
///
/// pub fn get_dict_item<'p>(dict: &'p PyDict, key: &impl ToPyObject) -> Option<&'p PyObjectRef> {
/// let key = ManagedPyRef::from_to_pyobject(dict.py(), key);
/// unsafe {
/// dict.py().from_borrowed_ptr_or_opt(ffi::PyDict_GetItem(dict.as_ptr(), key.as_ptr()))
/// }
/// }
/// ```
#[repr(transparent)]
pub struct ManagedPyRef<'p, T: ToPyObject + ?Sized> {
data: *mut ffi::PyObject,
data_type: PhantomData<T>,
_py: Python<'p>,
}
/// This should eventually be replaced with a generic `IntoPy` trait impl by figuring
/// out the correct lifetime annotation to make the compiler happy
impl<'p, T: ToPyObject> ManagedPyRef<'p, T> {
pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self {
to_pyobject.to_managed_py_ref(py)
}
}
impl<'p, T: ToPyObject> ToPyPointer for ManagedPyRef<'p, T> {
fn as_ptr(&self) -> *mut ffi::PyObject {
self.data
}
}
/// Helper trait to choose the right implementation for [BorrowedPyRef]
pub trait ManagedPyRefDispatch: ToPyObject {
/// Optionally converts into a python object and stores the pointer to the python heap.
///
/// Contains the case 1 impl (with to_object) to avoid a specialization error
fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self> {
ManagedPyRef {
data: self.to_object(py).into_ptr(),
data_type: PhantomData,
_py: py,
}
}
/// Dispatch over a xdecref and a noop drop impl
///
/// Contains the case 1 impl (decref) to avoid a specialization error
fn drop_impl(borrowed: &mut ManagedPyRef<Self>) {
unsafe { ffi::Py_DECREF(borrowed.data) };
}
}
/// Case 1: It's a rust object which still needs to be converted to a python object.
/// This means we're storing the owned pointer that into_ptr() has given us
/// and therefore need to xdecref when we're done.
///
/// Note that the actual implementations are part of the trait declaration to avoid
/// a specialization error
impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {}
/// Case 2: It's an object on the python heap, we're just storing a borrowed pointer.
/// The object we're getting is an owned pointer, it might have it's own drop impl.
impl<T: ToPyObject + ToPyPointer + ?Sized> ManagedPyRefDispatch for T {
/// Use ToPyPointer to copy the pointer and store it as borrowed pointer
fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self> {
ManagedPyRef {
data: self.as_ptr(),
data_type: PhantomData,
_py: py,
}
}
/// We have a borrowed pointer, so nothing to do here
fn drop_impl(_: &mut ManagedPyRef<T>) {}
}
impl<'p, T: ToPyObject + ?Sized> Drop for ManagedPyRef<'p, T> {
/// Uses the internal [ManagedPyRefDispatch] trait to get the right drop impl without causing
/// a specialization error
fn drop(&mut self) {
ManagedPyRefDispatch::drop_impl(self);
}
}
#[cfg(test)]
mod test {
use crate::ffi;
use crate::types::PyDict;
use crate::{ManagedPyRef, Python, ToPyPointer};
#[test]
fn borrowed_py_ref_with_to_pointer() {
let gil = Python::acquire_gil();
let py = gil.python();
let native = PyDict::new(py);
let ref_count = unsafe { ffi::Py_REFCNT(native.as_ptr()) };
let borrowed = ManagedPyRef::from_to_pyobject(py, native);
assert_eq!(native.as_ptr(), borrowed.data);
assert_eq!(ref_count, unsafe { ffi::Py_REFCNT(borrowed.data) });
drop(borrowed);
assert_eq!(ref_count, unsafe { ffi::Py_REFCNT(native.as_ptr()) });
}
#[test]
fn borrowed_py_ref_with_to_object() {
let gil = Python::acquire_gil();
let py = gil.python();
let convertible = (1, 2, 3);
let borrowed = ManagedPyRef::from_to_pyobject(py, &convertible);
let ptr = borrowed.data;
// The refcountwould become 0 after dropping, which means the gc can free the pointer
// and getting the refcount would be UB. This incref ensures that it remains 1
unsafe {
ffi::Py_INCREF(ptr);
}
assert_eq!(2, unsafe { ffi::Py_REFCNT(ptr) });
drop(borrowed);
assert_eq!(1, unsafe { ffi::Py_REFCNT(ptr) });
unsafe {
ffi::Py_DECREF(ptr);
}
}
}

View File

@ -118,29 +118,18 @@
//! } //! }
//! ``` //! ```
//pub extern crate libc;
//pub extern crate mashup;
//extern crate pyo3cls;
//extern crate num_traits;
//extern crate spin;
//extern crate indoc;
//#[macro_use]
//extern crate assert_approx_eq;
pub use crate::class::*; pub use crate::class::*;
pub use crate::conversion::{ pub use crate::conversion::{
FromPyObject, IntoPy, IntoPyObject, IntoPyResult, PyTryFrom, PyTryInto, ToBorrowedObject, FromPy, FromPyObject, IntoPy, IntoPyObject, IntoPyPointer, PyTryFrom, PyTryInto,
ToPyObject, ToBorrowedObject, ToPyObject, ToPyPointer,
}; };
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult}; pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
pub use crate::instance::{AsPyRef, Py, PyNativeType, PyObjectWithGIL, PyRef, PyRefMut}; pub use crate::gil::{init_once, GILGuard, GILPool};
pub use crate::noargs::NoArgs; pub use crate::instance::{AsPyRef, ManagedPyRef, Py, PyNativeType, PyRef, PyRefMut};
pub use crate::object::PyObject; pub use crate::object::PyObject;
pub use crate::objectprotocol::ObjectProtocol; pub use crate::objectprotocol::ObjectProtocol;
pub use crate::python::{IntoPyPointer, Python, ToPyPointer}; pub use crate::python::{prepare_freethreaded_python, Python};
pub use crate::pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool}; pub use crate::type_object::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub use crate::typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub use crate::types::exceptions;
// We need that reexport for wrap_function // We need that reexport for wrap_function
#[doc(hidden)] #[doc(hidden)]
@ -149,7 +138,7 @@ pub use mashup;
#[doc(hidden)] #[doc(hidden)]
pub use inventory; pub use inventory;
/// Rust FFI declarations for Python /// Raw ffi declarations for the c interface of python
pub mod ffi; pub mod ffi;
#[cfg(not(Py_3))] #[cfg(not(Py_3))]
@ -175,15 +164,15 @@ mod conversion;
#[doc(hidden)] #[doc(hidden)]
pub mod derive_utils; pub mod derive_utils;
mod err; mod err;
pub mod exceptions;
pub mod freelist; pub mod freelist;
mod gil;
mod instance; mod instance;
mod noargs;
mod object; mod object;
mod objectprotocol; mod objectprotocol;
pub mod prelude; pub mod prelude;
pub mod python; mod python;
mod pythonrun; pub mod type_object;
pub mod typeob;
pub mod types; pub mod types;
/// The proc macros, which are also part of the prelude /// The proc macros, which are also part of the prelude

View File

@ -1,50 +0,0 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{IntoPy, IntoPyObject, ToPyObject};
use crate::instance::Py;
use crate::object::PyObject;
use crate::python::Python;
use crate::types::PyTuple;
/// An empty struct that represents the empty argument list.
/// Corresponds to the empty tuple `()` in Python.
///
/// # Example
/// ```
/// # use pyo3::prelude::*;
///
/// let gil = Python::acquire_gil();
/// let py = gil.python();
/// let os = py.import("os").unwrap();
/// let pid = os.call("get_pid", NoArgs, None);
/// ```
#[derive(Copy, Clone, Debug)]
pub struct NoArgs;
/// Converts `NoArgs` to an empty Python tuple.
impl IntoPy<Py<PyTuple>> for NoArgs {
fn into_py(self, py: Python) -> Py<PyTuple> {
PyTuple::empty(py)
}
}
/// Converts `()` to an empty Python tuple.
impl IntoPy<Py<PyTuple>> for () {
fn into_py(self, py: Python) -> Py<PyTuple> {
PyTuple::empty(py)
}
}
/// Converts `NoArgs` to an empty Python tuple.
impl ToPyObject for NoArgs {
fn to_object(&self, py: Python) -> PyObject {
PyTuple::empty(py).into()
}
}
/// Converts `NoArgs` to an empty Python tuple.
impl IntoPyObject for NoArgs {
fn into_object(self, py: Python) -> PyObject {
PyTuple::empty(py).into()
}
}

View File

@ -1,15 +1,16 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{
FromPyObject, IntoPy, IntoPyObject, PyTryFrom, ToBorrowedObject, ToPyObject,
};
use crate::err::{PyDowncastError, PyErr, PyResult}; use crate::err::{PyDowncastError, PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::{AsPyRef, PyObjectWithGIL, PyRef, PyRefMut}; use crate::gil;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::instance::{AsPyRef, PyNativeType, PyRef, PyRefMut};
use crate::pythonrun;
use crate::types::{PyDict, PyObjectRef, PyTuple}; use crate::types::{PyDict, PyObjectRef, PyTuple};
use crate::Py; use crate::Py;
use crate::Python;
use crate::ToPyPointer;
use crate::{
FromPyObject, IntoPy, IntoPyObject, IntoPyPointer, PyTryFrom, ToBorrowedObject, ToPyObject,
};
use std::ptr::NonNull; use std::ptr::NonNull;
/// A python object /// A python object
@ -202,7 +203,7 @@ impl PyObject {
/// Calls the object without arguments. /// Calls the object without arguments.
/// This is equivalent to the Python expression: 'self()' /// This is equivalent to the Python expression: 'self()'
pub fn call0(&self, py: Python) -> PyResult<PyObject> { pub fn call0(&self, py: Python) -> PyResult<PyObject> {
self.call(py, PyTuple::empty(py), None) self.call(py, (), None)
} }
/// Calls the object. /// Calls the object.
@ -238,7 +239,7 @@ impl PyObject {
/// Calls a method on the object. /// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name()' /// This is equivalent to the Python expression: 'self.name()'
pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> { pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> {
self.call_method(py, name, PyTuple::empty(py), None) self.call_method(py, name, (), None)
} }
/// Calls a method on the object. /// Calls a method on the object.
@ -279,14 +280,6 @@ impl ToPyPointer for PyObject {
} }
} }
impl<'a> ToPyPointer for &'a PyObject {
/// Gets the underlying FFI pointer, returns a borrowed pointer.
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
self.0.as_ptr()
}
}
impl IntoPyPointer for PyObject { impl IntoPyPointer for PyObject {
/// Gets the underlying FFI pointer, returns a owned pointer. /// Gets the underlying FFI pointer, returns a owned pointer.
#[inline] #[inline]
@ -325,16 +318,16 @@ impl<'a> FromPyObject<'a> for PyObject {
impl Drop for PyObject { impl Drop for PyObject {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
pythonrun::register_pointer(self.0); gil::register_pointer(self.0);
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::PyObject;
use crate::python::Python;
use crate::types::PyDict; use crate::types::PyDict;
use crate::PyObject;
use crate::Python;
#[test] #[test]
fn test_call_for_non_existing_method() { fn test_call_for_non_existing_method() {

View File

@ -1,15 +1,18 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{FromPyObject, IntoPy, PyTryFrom, ToBorrowedObject, ToPyObject}; use crate::class::basic::CompareOp;
use crate::err::{self, PyDowncastError, PyErr, PyResult}; use crate::err::{self, PyDowncastError, PyErr, PyResult};
use crate::exceptions::TypeError; use crate::exceptions::TypeError;
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::type_object::PyTypeInfo;
use crate::typeob::PyTypeInfo;
use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType}; use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType};
use crate::IntoPyPointer;
use crate::Py; use crate::Py;
use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPy, PyTryFrom, ToBorrowedObject, ToPyObject};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::os::raw::c_int; use std::os::raw::c_int;
@ -68,7 +71,7 @@ pub trait ObjectProtocol {
/// * CompareOp::Le: `self <= other` /// * CompareOp::Le: `self <= other`
/// * CompareOp::Gt: `self > other` /// * CompareOp::Gt: `self > other`
/// * CompareOp::Ge: `self >= other` /// * CompareOp::Ge: `self >= other`
fn rich_compare<O>(&self, other: O, compare_op: crate::CompareOp) -> PyResult<PyObject> fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<PyObject>
where where
O: ToPyObject; O: ToPyObject;
@ -208,7 +211,7 @@ pub trait ObjectProtocol {
impl<T> ObjectProtocol for T impl<T> ObjectProtocol for T
where where
T: PyObjectWithGIL + ToPyPointer, T: PyNativeType + ToPyPointer,
{ {
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>
where where
@ -290,7 +293,7 @@ where
}) })
} }
fn rich_compare<O>(&self, other: O, compare_op: crate::CompareOp) -> PyResult<PyObject> fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<PyObject>
where where
O: ToPyObject, O: ToPyObject,
{ {
@ -341,7 +344,7 @@ where
} }
fn call0(&self) -> PyResult<&PyObjectRef> { fn call0(&self) -> PyResult<&PyObjectRef> {
self.call(PyTuple::empty(self.py()), None) self.call((), None)
} }
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> { fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> {
@ -372,7 +375,7 @@ where
} }
fn call_method0(&self, name: &str) -> PyResult<&PyObjectRef> { fn call_method0(&self, name: &str) -> PyResult<&PyObjectRef> {
self.call_method(name, PyTuple::empty(self.py()), None) self.call_method(name, (), None)
} }
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> { fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> {
@ -497,10 +500,10 @@ where
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::python::Python;
use crate::types::{IntoPyDict, PyString}; use crate::types::{IntoPyDict, PyString};
use crate::Python;
use crate::{PyTryFrom, ToPyObject};
#[test] #[test]
fn test_debug_string() { fn test_debug_string() {

View File

@ -10,14 +10,15 @@
//! use pyo3::prelude::*; //! use pyo3::prelude::*;
//! ``` //! ```
pub use crate::conversion::{FromPyObject, IntoPyObject, PyTryFrom, PyTryInto, ToPyObject};
pub use crate::err::{PyErr, PyResult}; pub use crate::err::{PyErr, PyResult};
pub use crate::gil::GILGuard;
pub use crate::instance::{AsPyRef, Py, PyRef, PyRefMut}; pub use crate::instance::{AsPyRef, Py, PyRef, PyRefMut};
pub use crate::noargs::NoArgs;
pub use crate::object::PyObject; pub use crate::object::PyObject;
pub use crate::objectprotocol::ObjectProtocol; pub use crate::objectprotocol::ObjectProtocol;
pub use crate::python::Python; pub use crate::python::Python;
pub use crate::pythonrun::GILGuard; pub use crate::{
FromPy, FromPyObject, IntoPy, IntoPyObject, IntoPyPointer, PyTryFrom, PyTryInto, ToPyObject,
};
// This is only part of the prelude because we need it for the pymodule function // This is only part of the prelude because we need it for the pymodule function
pub use crate::types::PyModule; pub use crate::types::PyModule;
// This is required for the constructor // This is required for the constructor

View File

@ -2,20 +2,22 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use crate::conversion::PyTryFrom;
use crate::err::{PyDowncastError, PyErr, PyResult}; use crate::err::{PyDowncastError, PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::{AsPyRef, Py, PyRef, PyRefMut}; use crate::gil::{self, GILGuard};
use crate::instance::AsPyRef;
use crate::object::PyObject; use crate::object::PyObject;
use crate::pythonrun::{self, GILGuard}; use crate::type_object::{PyTypeInfo, PyTypeObject};
use crate::typeob::PyTypeCreate;
use crate::typeob::{PyTypeInfo, PyTypeObject};
use crate::types::{PyDict, PyModule, PyObjectRef, PyType}; use crate::types::{PyDict, PyModule, PyObjectRef, PyType};
use crate::ToPyPointer;
use crate::{IntoPyPointer, PyTryFrom};
use std::ffi::CString; use std::ffi::CString;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::NonNull; use std::ptr::NonNull;
pub use gil::prepare_freethreaded_python;
/// Marker type that indicates that the GIL is currently held. /// Marker type that indicates that the GIL is currently held.
/// ///
/// The 'Python' struct is a zero-size marker struct that is required for most Python operations. /// The 'Python' struct is a zero-size marker struct that is required for most Python operations.
@ -48,62 +50,6 @@ use std::ptr::NonNull;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Python<'p>(PhantomData<&'p GILGuard>); pub struct Python<'p>(PhantomData<&'p GILGuard>);
/// This trait allows retrieving the underlying FFI pointer from Python objects.
pub trait ToPyPointer {
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
fn as_ptr(&self) -> *mut ffi::PyObject;
}
/// This trait allows retrieving the underlying FFI pointer from Python objects.
pub trait IntoPyPointer {
/// Retrieves the underlying FFI pointer. Whether pointer owned or borrowed
/// depends on implementation.
fn into_ptr(self) -> *mut ffi::PyObject;
}
/// Convert `None` into a null pointer.
impl<T> ToPyPointer for Option<T>
where
T: ToPyPointer,
{
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
match *self {
Some(ref t) => t.as_ptr(),
None => std::ptr::null_mut(),
}
}
}
/// Convert `None` into a null pointer.
impl<T> IntoPyPointer for Option<T>
where
T: IntoPyPointer,
{
#[inline]
fn into_ptr(self) -> *mut ffi::PyObject {
match self {
Some(t) => t.into_ptr(),
None => std::ptr::null_mut(),
}
}
}
impl<'a, T> IntoPyPointer for &'a T
where
T: ToPyPointer,
{
fn into_ptr(self) -> *mut ffi::PyObject {
let ptr = self.as_ptr();
if !ptr.is_null() {
unsafe {
ffi::Py_INCREF(ptr);
}
}
ptr
}
}
impl<'p> Python<'p> { impl<'p> Python<'p> {
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point, /// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
/// and stays acquired for the lifetime `'p`. /// and stays acquired for the lifetime `'p`.
@ -246,38 +192,6 @@ impl<'p> Python<'p> {
} }
} }
impl<'p> Python<'p> {
/// Create new instance of `T` and move it under python management.
/// Returns `Py<T>`.
#[inline]
pub fn init<T>(self, value: T) -> PyResult<Py<T>>
where
T: PyTypeCreate,
{
Py::new(self, value)
}
/// Create new instance of `T` and move it under python management.
/// Created object get registered in release pool. Returns references to `T`
#[inline]
pub fn init_ref<T>(self, value: T) -> PyResult<PyRef<'p, T>>
where
T: PyTypeCreate,
{
PyRef::new(self, value)
}
/// Create new instance of `T` and move it under python management.
/// Created object get registered in release pool. Returns mutable references to `T`
#[inline]
pub fn init_mut<T>(self, value: T) -> PyResult<PyRefMut<'p, T>>
where
T: PyTypeCreate,
{
PyRefMut::new(self, value)
}
}
impl<'p> Python<'p> { impl<'p> Python<'p> {
unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p T { unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p T {
if T::OFFSET == 0 { if T::OFFSET == 0 {
@ -303,7 +217,7 @@ impl<'p> Python<'p> {
where where
T: PyTypeInfo, T: PyTypeInfo,
{ {
let p = unsafe { pythonrun::register_owned(self, obj.into_nonnull()) }; let p = unsafe { gil::register_owned(self, obj.into_nonnull()) };
<T as PyTryFrom>::try_from(p) <T as PyTryFrom>::try_from(p)
} }
@ -312,14 +226,14 @@ impl<'p> Python<'p> {
where where
T: PyTypeInfo, T: PyTypeInfo,
{ {
let p = pythonrun::register_owned(self, obj.into_nonnull()); let p = gil::register_owned(self, obj.into_nonnull());
self.unchecked_downcast(p) self.unchecked_downcast(p)
} }
/// Register `ffi::PyObject` pointer in release pool /// Register `ffi::PyObject` pointer in release pool
pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyObjectRef { pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyObjectRef {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => pythonrun::register_borrowed(self, p), Some(p) => gil::register_borrowed(self, p),
None => crate::err::panic_after_error(), None => crate::err::panic_after_error(),
} }
} }
@ -333,7 +247,7 @@ impl<'p> Python<'p> {
{ {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => { Some(p) => {
let p = pythonrun::register_owned(self, p); let p = gil::register_owned(self, p);
self.unchecked_downcast(p) self.unchecked_downcast(p)
} }
None => crate::err::panic_after_error(), None => crate::err::panic_after_error(),
@ -348,7 +262,7 @@ impl<'p> Python<'p> {
{ {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => { Some(p) => {
let p = pythonrun::register_owned(self, p); let p = gil::register_owned(self, p);
self.unchecked_mut_downcast(p) self.unchecked_mut_downcast(p)
} }
None => crate::err::panic_after_error(), None => crate::err::panic_after_error(),
@ -364,7 +278,7 @@ impl<'p> Python<'p> {
{ {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => { Some(p) => {
let p = pythonrun::register_owned(self, p); let p = gil::register_owned(self, p);
Ok(self.unchecked_downcast(p)) Ok(self.unchecked_downcast(p))
} }
None => Err(PyErr::fetch(self)), None => Err(PyErr::fetch(self)),
@ -379,7 +293,7 @@ impl<'p> Python<'p> {
T: PyTypeInfo, T: PyTypeInfo,
{ {
NonNull::new(ptr).map(|p| { NonNull::new(ptr).map(|p| {
let p = pythonrun::register_owned(self, p); let p = gil::register_owned(self, p);
self.unchecked_downcast(p) self.unchecked_downcast(p)
}) })
} }
@ -393,7 +307,7 @@ impl<'p> Python<'p> {
{ {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => { Some(p) => {
let p = pythonrun::register_borrowed(self, p); let p = gil::register_borrowed(self, p);
self.unchecked_downcast(p) self.unchecked_downcast(p)
} }
None => crate::err::panic_after_error(), None => crate::err::panic_after_error(),
@ -409,7 +323,7 @@ impl<'p> Python<'p> {
{ {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => { Some(p) => {
let p = pythonrun::register_borrowed(self, p); let p = gil::register_borrowed(self, p);
self.unchecked_mut_downcast(p) self.unchecked_mut_downcast(p)
} }
None => crate::err::panic_after_error(), None => crate::err::panic_after_error(),
@ -425,7 +339,7 @@ impl<'p> Python<'p> {
{ {
match NonNull::new(ptr) { match NonNull::new(ptr) {
Some(p) => { Some(p) => {
let p = pythonrun::register_borrowed(self, p); let p = gil::register_borrowed(self, p);
Ok(self.unchecked_downcast(p)) Ok(self.unchecked_downcast(p))
} }
None => Err(PyErr::fetch(self)), None => Err(PyErr::fetch(self)),
@ -440,7 +354,7 @@ impl<'p> Python<'p> {
T: PyTypeInfo, T: PyTypeInfo,
{ {
NonNull::new(ptr).map(|p| { NonNull::new(ptr).map(|p| {
let p = pythonrun::register_borrowed(self, p); let p = gil::register_borrowed(self, p);
self.unchecked_downcast(p) self.unchecked_downcast(p)
}) })
} }
@ -449,7 +363,7 @@ impl<'p> Python<'p> {
/// Pass value ownership to `Python` object and get reference back. /// Pass value ownership to `Python` object and get reference back.
/// Value get cleaned up on the GIL release. /// Value get cleaned up on the GIL release.
pub fn register_any<T: 'static>(self, ob: T) -> &'p T { pub fn register_any<T: 'static>(self, ob: T) -> &'p T {
unsafe { pythonrun::register_any(ob) } unsafe { gil::register_any(ob) }
} }
/// Release PyObject reference. /// Release PyObject reference.

View File

@ -4,12 +4,13 @@
use crate::class::methods::PyMethodDefType; use crate::class::methods::PyMethodDefType;
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyNativeType};
use crate::python::ToPyPointer;
use crate::python::{IntoPyPointer, Python};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::types::PyType; use crate::types::PyType;
use crate::{class, ffi, pythonrun}; use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{class, ffi, gil};
use class::methods::PyMethodsProtocol; use class::methods::PyMethodsProtocol;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CString; use std::ffi::CString;
@ -171,7 +172,7 @@ impl IntoPyPointer for PyRawObject {
} }
} }
impl PyObjectWithGIL for PyRawObject { impl PyNativeType for PyRawObject {
#[inline] #[inline]
fn py(&self) -> Python { fn py(&self) -> Python {
unsafe { Python::assume_gil_acquired() } unsafe { Python::assume_gil_acquired() }
@ -430,7 +431,7 @@ unsafe extern "C" fn tp_dealloc_callback<T>(obj: *mut ffi::PyObject)
where where
T: PyObjectAlloc, T: PyObjectAlloc,
{ {
let _pool = pythonrun::GILPool::new_no_pointers(); let _pool = gil::GILPool::new_no_pointers();
let py = Python::assume_gil_acquired(); let py = Python::assume_gil_acquired();
<T as PyObjectAlloc>::dealloc(py, obj) <T as PyObjectAlloc>::dealloc(py, obj)
} }

View File

@ -1,11 +1,12 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{IntoPyObject, PyTryFrom, ToPyObject};
use crate::ffi; use crate::ffi;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::FromPyObject; use crate::FromPyObject;
use crate::PyResult; use crate::PyResult;
use crate::Python;
use crate::ToPyPointer;
use crate::{IntoPyObject, PyTryFrom, ToPyObject};
/// Represents a Python `bool`. /// Represents a Python `bool`.
#[repr(transparent)] #[repr(transparent)]
@ -62,10 +63,10 @@ impl<'source> FromPyObject<'source> for bool {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::ToPyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::Python;
use crate::types::{PyBool, PyObjectRef}; use crate::types::{PyBool, PyObjectRef};
use crate::Python;
use crate::ToPyObject;
#[test] #[test]
fn test_true() { fn test_true() {

View File

@ -2,9 +2,10 @@
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::Python;
use crate::ToPyPointer;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::slice; use std::slice;
@ -72,8 +73,8 @@ impl PyByteArray {
mod test { mod test {
use crate::exceptions; use crate::exceptions;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::Python;
use crate::types::PyByteArray; use crate::types::PyByteArray;
use crate::Python;
#[test] #[test]
fn test_bytearray() { fn test_bytearray() {

View File

@ -1,7 +1,8 @@
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::Python;
use crate::ToPyPointer;
#[cfg(any(not(Py_LIMITED_API), not(Py_3)))] #[cfg(any(not(Py_LIMITED_API), not(Py_3)))]
use std::ops::*; use std::ops::*;
use std::os::raw::c_double; use std::os::raw::c_double;
@ -117,10 +118,10 @@ impl<'py> Neg for &'py PyComplex {
#[cfg(feature = "num-complex")] #[cfg(feature = "num-complex")]
mod complex_conversion { mod complex_conversion {
use super::*; use super::*;
use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::PyErr; use crate::err::PyErr;
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::PyResult; use crate::PyResult;
use crate::{FromPyObject, IntoPyObject, ToPyObject};
use num_complex::Complex; use num_complex::Complex;
impl PyComplex { impl PyComplex {
@ -215,7 +216,7 @@ mod complex_conversion {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::PyComplex; use super::PyComplex;
use crate::python::Python; use crate::Python;
use assert_approx_eq::assert_approx_eq; use assert_approx_eq::assert_approx_eq;
#[test] #[test]

View File

@ -5,7 +5,6 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use crate::conversion::ToPyObject;
use crate::err::PyResult; use crate::err::PyResult;
use crate::ffi; use crate::ffi;
use crate::ffi::PyDateTimeAPI; use crate::ffi::PyDateTimeAPI;
@ -26,8 +25,10 @@ use crate::ffi::{
}; };
use crate::instance::Py; use crate::instance::Py;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer};
use crate::types::PyTuple; use crate::types::PyTuple;
use crate::Python;
use crate::ToPyObject;
use crate::ToPyPointer;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr; use std::ptr;

View File

@ -1,12 +1,14 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use crate::err::{self, PyErr, PyResult}; use crate::err::{self, PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::types::{PyList, PyObjectRef}; use crate::types::{PyList, PyObjectRef};
use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{IntoPyObject, ToBorrowedObject, ToPyObject};
use std::{cmp, collections, hash, mem}; use std::{cmp, collections, hash, mem};
/// Represents a Python `dict`. /// Represents a Python `dict`.
@ -300,12 +302,12 @@ where
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::{IntoPyObject, PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::python::Python;
use crate::types::dict::IntoPyDict; use crate::types::dict::IntoPyDict;
use crate::types::{PyDict, PyList, PyTuple}; use crate::types::{PyDict, PyList, PyTuple};
use crate::ObjectProtocol; use crate::ObjectProtocol;
use crate::Python;
use crate::{IntoPyObject, PyTryFrom, ToPyObject};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
#[test] #[test]

View File

@ -2,16 +2,17 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use crate::conversion::{IntoPyObject, ToPyObject};
use crate::err::PyErr; use crate::err::PyErr;
use crate::ffi; use crate::ffi;
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::{Python, ToPyPointer};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::FromPyObject; use crate::FromPyObject;
use crate::PyResult; use crate::PyResult;
use crate::Python;
use crate::ToPyPointer;
use crate::{IntoPyObject, ToPyObject};
use std::os::raw::c_double; use std::os::raw::c_double;
/// Represents a Python `float` object. /// Represents a Python `float` object.
@ -83,8 +84,8 @@ impl<'source> FromPyObject<'source> for f32 {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::ToPyObject; use crate::Python;
use crate::python::Python; use crate::ToPyObject;
macro_rules! num_to_py_object_and_back ( macro_rules! num_to_py_object_and_back (
($func_name:ident, $t1:ty, $t2:ty) => ( ($func_name:ident, $t1:ty, $t2:ty) => (

View File

@ -4,9 +4,10 @@
use crate::err::{PyDowncastError, PyErr, PyResult}; use crate::err::{PyDowncastError, PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::python::{Python, ToPyPointer};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::Python;
use crate::ToPyPointer;
/// A python iterator object. /// A python iterator object.
/// ///
@ -83,13 +84,13 @@ impl<'p> Drop for PyIterator<'p> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::conversion::ToPyObject; use crate::gil::GILPool;
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::Python;
use crate::pythonrun::GILPool;
use crate::types::{PyDict, PyList}; use crate::types::{PyDict, PyList};
use crate::GILGuard; use crate::GILGuard;
use crate::Python;
use crate::ToPyObject;
use indoc::indoc; use indoc::indoc;
#[test] #[test]

View File

@ -2,13 +2,15 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use crate::err::{self, PyResult}; use crate::err::{self, PyResult};
use crate::ffi::{self, Py_ssize_t}; use crate::ffi::{self, Py_ssize_t};
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{IntoPyObject, ToBorrowedObject, ToPyObject};
/// Represents a Python `list`. /// Represents a Python `list`.
#[repr(transparent)] #[repr(transparent)]
@ -166,7 +168,7 @@ impl<T> ToPyObject for [T]
where where
T: ToPyObject, T: ToPyObject,
{ {
fn to_object<'p>(&self, py: Python<'p>) -> PyObject { fn to_object(&self, py: Python<'_>) -> PyObject {
unsafe { unsafe {
let ptr = ffi::PyList_New(self.len() as Py_ssize_t); let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
for (i, e) in self.iter().enumerate() { for (i, e) in self.iter().enumerate() {
@ -182,7 +184,7 @@ impl<T> ToPyObject for Vec<T>
where where
T: ToPyObject, T: ToPyObject,
{ {
fn to_object<'p>(&self, py: Python<'p>) -> PyObject { fn to_object(&self, py: Python<'_>) -> PyObject {
self.as_slice().to_object(py) self.as_slice().to_object(py)
} }
} }
@ -205,11 +207,11 @@ where
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::Python;
use crate::types::PyList; use crate::types::PyList;
use crate::Python;
use crate::{PyTryFrom, ToPyObject};
#[test] #[test]
fn test_new() { fn test_new() {

View File

@ -30,7 +30,6 @@ pub use self::string2::{PyBytes, PyString, PyUnicode};
pub use self::tuple::PyTuple; pub use self::tuple::PyTuple;
pub use self::typeobject::PyType; pub use self::typeobject::PyType;
use crate::ffi; use crate::ffi;
use crate::python::ToPyPointer;
use crate::PyObject; use crate::PyObject;
/// Implements a typesafe conversions throught [FromPyObject], given a typecheck function as second /// Implements a typesafe conversions throught [FromPyObject], given a typecheck function as second
@ -58,8 +57,6 @@ macro_rules! pyobject_downcast (
#[macro_export] #[macro_export]
macro_rules! pyobject_native_type_named ( macro_rules! pyobject_native_type_named (
($name: ty $(,$type_param: ident)*) => { ($name: ty $(,$type_param: ident)*) => {
impl<$($type_param,)*> $crate::PyNativeType for $name {}
impl<$($type_param,)*> ::std::convert::AsRef<$crate::types::PyObjectRef> for $name { impl<$($type_param,)*> ::std::convert::AsRef<$crate::types::PyObjectRef> for $name {
#[inline] #[inline]
fn as_ref(&self) -> &$crate::types::PyObjectRef { fn as_ref(&self) -> &$crate::types::PyObjectRef {
@ -67,14 +64,13 @@ macro_rules! pyobject_native_type_named (
} }
} }
impl<$($type_param,)*> $crate::PyObjectWithGIL for $name { impl<$($type_param,)*> $crate::PyNativeType for $name {
#[inline]
fn py(&self) -> $crate::Python { fn py(&self) -> $crate::Python {
unsafe { $crate::Python::assume_gil_acquired() } unsafe { $crate::Python::assume_gil_acquired() }
} }
} }
impl<$($type_param,)*> $crate::python::ToPyPointer for $name { impl<$($type_param,)*> $crate::ToPyPointer for $name {
/// Gets the underlying FFI pointer, returns a borrowed pointer. /// Gets the underlying FFI pointer, returns a borrowed pointer.
#[inline] #[inline]
fn as_ptr(&self) -> *mut $crate::ffi::PyObject { fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
@ -85,6 +81,8 @@ macro_rules! pyobject_native_type_named (
impl<$($type_param,)*> PartialEq for $name { impl<$($type_param,)*> PartialEq for $name {
#[inline] #[inline]
fn eq(&self, o: &$name) -> bool { fn eq(&self, o: &$name) -> bool {
use $crate::ToPyPointer;
self.as_ptr() == o.as_ptr() self.as_ptr() == o.as_ptr()
} }
} }
@ -108,7 +106,7 @@ macro_rules! pyobject_native_type (
#[macro_export] #[macro_export]
macro_rules! pyobject_native_type_convert( macro_rules! pyobject_native_type_convert(
($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => { ($name: ty, $typeobject: expr, $checkfunction: path $(,$type_param: ident)*) => {
impl<$($type_param,)*> $crate::typeob::PyTypeInfo for $name { impl<$($type_param,)*> $crate::type_object::PyTypeInfo for $name {
type Type = (); type Type = ();
type BaseType = $crate::types::PyObjectRef; type BaseType = $crate::types::PyObjectRef;
@ -121,18 +119,20 @@ macro_rules! pyobject_native_type_convert(
&mut $typeobject &mut $typeobject
} }
fn is_instance(ptr: &$crate::types::PyObjectRef) -> bool {
#[allow(unused_unsafe)] #[allow(unused_unsafe)]
fn is_instance(ptr: &$crate::types::PyObjectRef) -> bool {
use $crate::ToPyPointer;
unsafe { $checkfunction(ptr.as_ptr()) > 0 } unsafe { $checkfunction(ptr.as_ptr()) > 0 }
} }
} }
impl<$($type_param,)*> $crate::typeob::PyObjectAlloc for $name {} impl<$($type_param,)*> $crate::type_object::PyObjectAlloc for $name {}
impl<$($type_param,)*> $crate::typeob::PyTypeObject for $name { impl<$($type_param,)*> $crate::type_object::PyTypeObject for $name {
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
unsafe { unsafe {
std::ptr::NonNull::new_unchecked(<Self as $crate::typeob::PyTypeInfo>::type_object() as *mut _) std::ptr::NonNull::new_unchecked(<Self as $crate::type_object::PyTypeInfo>::type_object() as *mut _)
} }
} }
} }
@ -141,6 +141,8 @@ macro_rules! pyobject_native_type_convert(
{ {
#[inline] #[inline]
fn to_object(&self, py: $crate::Python) -> $crate::PyObject { fn to_object(&self, py: $crate::Python) -> $crate::PyObject {
use $crate::ToPyPointer;
unsafe {$crate::PyObject::from_borrowed_ptr(py, self.0.as_ptr())} unsafe {$crate::PyObject::from_borrowed_ptr(py, self.0.as_ptr())}
} }
} }
@ -178,7 +180,6 @@ mod bytearray;
mod complex; mod complex;
mod datetime; mod datetime;
mod dict; mod dict;
pub mod exceptions;
mod floatob; mod floatob;
mod iterator; mod iterator;
mod list; mod list;

View File

@ -2,18 +2,21 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use crate::conversion::{IntoPy, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::{Python, ToPyPointer}; use crate::type_object::PyTypeCreate;
use crate::typeob::PyTypeCreate; use crate::type_object::PyTypeObject;
use crate::typeob::PyTypeObject;
use crate::types::PyTuple; use crate::types::PyTuple;
use crate::types::{exceptions, PyDict, PyObjectRef}; use crate::types::{PyDict, PyObjectRef};
use crate::IntoPy;
use crate::Py; use crate::Py;
use crate::Python;
use crate::ToPyObject;
use crate::ToPyPointer;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::os::raw::c_char; use std::os::raw::c_char;
use std::str; use std::str;
@ -64,7 +67,7 @@ impl PyModule {
return Err(PyErr::fetch(py)); return Err(PyErr::fetch(py));
} }
<&PyModule as crate::conversion::FromPyObject>::extract(py.from_owned_ptr_or_err(mptr)?) <&PyModule as crate::FromPyObject>::extract(py.from_owned_ptr_or_err(mptr)?)
} }
} }
@ -124,10 +127,7 @@ impl PyModule {
/// Calls a function in the module. /// Calls a function in the module.
/// This is equivalent to the Python expression: `getattr(module, name)(*args)` /// This is equivalent to the Python expression: `getattr(module, name)(*args)`
pub fn call1<A>(&self, name: &str, args: A) -> PyResult<&PyObjectRef> pub fn call1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> {
where
A: IntoPy<Py<PyTuple>>,
{
self.getattr(name)?.call1(args) self.getattr(name)?.call1(args)
} }

View File

@ -3,13 +3,16 @@
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN}; use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN};
use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::types::PyObjectRef;
use crate::types::{exceptions, PyObjectRef}; use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPyObject, ToPyObject};
use num_traits::cast::cast; use num_traits::cast::cast;
use std::os::raw::{c_long, c_uchar}; use std::os::raw::{c_long, c_uchar};
@ -177,8 +180,8 @@ int_convert_bignum!(u128, 16, IS_LITTLE_ENDIAN, 0);
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::ToPyObject; use crate::Python;
use crate::python::Python; use crate::ToPyObject;
macro_rules! num_to_py_object_and_back ( macro_rules! num_to_py_object_and_back (
($func_name:ident, $t1:ty, $t2:ty) => ( ($func_name:ident, $t1:ty, $t2:ty) => (

View File

@ -3,13 +3,15 @@
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN}; use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN};
use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::types::PyObjectRef;
use crate::types::{exceptions, PyObjectRef}; use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPyObject, ToPyObject};
use num_traits::cast::cast; use num_traits::cast::cast;
use std::i64; use std::i64;
use std::os::raw::{c_long, c_uchar}; use std::os::raw::{c_long, c_uchar};
@ -146,9 +148,9 @@ mod test {
macro_rules! test_common ( macro_rules! test_common (
($test_mod_name:ident, $t:ty) => ( ($test_mod_name:ident, $t:ty) => (
mod $test_mod_name { mod $test_mod_name {
use crate::types::exceptions; use crate::exceptions;
use crate::conversion::ToPyObject; use crate::ToPyObject;
use crate::python::Python; use crate::Python;
#[test] #[test]
fn from_py_string_type_error() { fn from_py_string_type_error() {

View File

@ -1,7 +1,7 @@
//! common macros for num2.rs and num3.rs //! common macros for num2.rs and num3.rs
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::python::Python; use crate::Python;
use std::os::raw::c_int; use std::os::raw::c_int;
pub(super) fn err_if_invalid_value<T: PartialEq + Copy>( pub(super) fn err_if_invalid_value<T: PartialEq + Copy>(
@ -104,8 +104,8 @@ pub(super) const IS_LITTLE_ENDIAN: c_int = 0;
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::ToPyObject; use crate::Python;
use crate::python::Python; use crate::ToPyObject;
#[test] #[test]
fn test_u32_max() { fn test_u32_max() {
@ -188,9 +188,9 @@ mod test {
#[test] #[test]
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
fn test_u128_overflow() { fn test_u128_overflow() {
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::object::PyObject; use crate::object::PyObject;
use crate::types::exceptions;
use std::os::raw::c_uchar; use std::os::raw::c_uchar;
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();

View File

@ -1,14 +1,14 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::buffer; use crate::buffer;
use crate::conversion::{FromPyObject, PyTryFrom, ToBorrowedObject};
use crate::err::{self, PyDowncastError, PyErr, PyResult}; use crate::err::{self, PyDowncastError, PyErr, PyResult};
use crate::ffi::{self, Py_ssize_t}; use crate::ffi::{self, Py_ssize_t};
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::ToPyPointer;
use crate::types::{PyList, PyObjectRef, PyTuple}; use crate::types::{PyList, PyObjectRef, PyTuple};
use crate::ToPyPointer;
use crate::{FromPyObject, PyTryFrom, ToBorrowedObject};
/// Represents a reference to a python object supporting the sequence protocol. /// Represents a reference to a python object supporting the sequence protocol.
#[repr(transparent)] #[repr(transparent)]
@ -327,12 +327,13 @@ impl<'v> PyTryFrom<'v> for PySequence {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::{Python, ToPyPointer};
use crate::types::PySequence; use crate::types::PySequence;
use crate::Python;
use crate::ToPyPointer;
use crate::{PyTryFrom, ToPyObject};
fn get_object() -> PyObject { fn get_object() -> PyObject {
// Convenience function for getting a single unique object // Convenience function for getting a single unique object

View File

@ -1,12 +1,13 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
// //
use crate::conversion::{ToBorrowedObject, ToPyObject};
use crate::err::{self, PyErr, PyResult}; use crate::err::{self, PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::{AsPyRef, Py, PyObjectWithGIL}; use crate::instance::{AsPyRef, Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::Python;
use crate::ToPyPointer;
use crate::{ToBorrowedObject, ToPyObject};
use std::{collections, hash}; use std::{collections, hash};
/// Represents a Python `set` /// Represents a Python `set`
@ -160,10 +161,10 @@ impl PyFrozenSet {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{PyFrozenSet, PySet}; use super::{PyFrozenSet, PySet};
use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::Python; use crate::Python;
use crate::{PyTryFrom, ToPyObject};
use std::collections::HashSet; use std::collections::HashSet;
#[test] #[test]

View File

@ -1,11 +1,11 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::ToPyObject;
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::ffi::{self, Py_ssize_t}; use crate::ffi::{self, Py_ssize_t};
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::Python;
use crate::{ToPyObject, ToPyPointer};
use std::os::raw::c_long; use std::os::raw::c_long;
/// Represents a Python `slice`. /// Represents a Python `slice`.

View File

@ -1,12 +1,13 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer};
use crate::types::exceptions;
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::Python;
use crate::ToPyPointer;
use std::borrow::Cow; use std::borrow::Cow;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::{mem, str}; use std::{mem, str};
@ -119,10 +120,10 @@ impl PyBytes {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::PyString; use super::PyString;
use crate::conversion::{FromPyObject, PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::Python; use crate::Python;
use crate::{FromPyObject, PyTryFrom, ToPyObject};
use std::borrow::Cow; use std::borrow::Cow;
#[test] #[test]

View File

@ -4,13 +4,14 @@
use super::PyObjectRef; use super::PyObjectRef;
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi; use crate::ffi;
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::IntoPyPointer; use crate::python::IntoPyPointer;
use crate::python::{Python, ToPyPointer}; use crate::Python;
use crate::types::exceptions; use crate::ToPyPointer;
use std::borrow::Cow; use std::borrow::Cow;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::str; use std::str;
@ -204,10 +205,10 @@ impl std::convert::From<Py<PyUnicode>> for Py<PyString> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::PyString; use super::PyString;
use crate::conversion::{FromPyObject, PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::Python; use crate::Python;
use crate::{FromPyObject, PyTryFrom, ToPyObject};
use std::borrow::Cow; use std::borrow::Cow;
#[test] #[test]

View File

@ -1,10 +1,10 @@
use crate::conversion::{IntoPyObject, PyTryFrom, ToPyObject};
use crate::err::PyResult; use crate::err::PyResult;
use crate::instance::PyObjectWithGIL; use crate::instance::PyNativeType;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::Python;
use crate::types::{PyObjectRef, PyString}; use crate::types::{PyObjectRef, PyString};
use crate::FromPyObject; use crate::FromPyObject;
use crate::Python;
use crate::{IntoPyObject, PyTryFrom, ToPyObject};
use std::borrow::Cow; use std::borrow::Cow;
/// Converts Rust `str` to Python object. /// Converts Rust `str` to Python object.

View File

@ -1,13 +1,16 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use super::exceptions; use crate::conversion::FromPy;
use crate::conversion::{FromPyObject, IntoPy, IntoPyObject, PyTryFrom, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi::{self, Py_ssize_t}; use crate::ffi::{self, Py_ssize_t};
use crate::instance::{AsPyRef, Py, PyObjectWithGIL}; use crate::instance::{AsPyRef, Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPy, IntoPyObject, PyTryFrom, ToPyObject};
use std::slice; use std::slice;
/// Represents a Python `tuple` object. /// Represents a Python `tuple` object.
@ -131,25 +134,9 @@ impl<'a> IntoIterator for &'a PyTuple {
} }
} }
impl<'a> IntoPy<Py<PyTuple>> for &'a PyTuple { impl<'a> FromPy<&'a PyTuple> for Py<PyTuple> {
fn into_py(self, _py: Python) -> Py<PyTuple> { fn from_py(tuple: &'a PyTuple, _py: Python) -> Py<PyTuple> {
unsafe { Py::from_borrowed_ptr(self.as_ptr()) } unsafe { Py::from_borrowed_ptr(tuple.as_ptr()) }
}
}
impl IntoPy<Py<PyTuple>> for Py<PyTuple> {
fn into_py(self, _py: Python) -> Py<PyTuple> {
self
}
}
impl<'a> IntoPy<Py<PyTuple>> for &'a str {
fn into_py(self, py: Python) -> Py<PyTuple> {
unsafe {
let ptr = ffi::PyTuple_New(1);
ffi::PyTuple_SetItem(ptr, 0, self.into_object(py).into_ptr());
Py::from_owned_ptr_or_panic(ptr)
}
} }
} }
@ -265,12 +252,12 @@ tuple_conversion!(
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;
use crate::python::Python;
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::types::PyTuple; use crate::types::PyTuple;
use crate::Python;
use crate::{PyTryFrom, ToPyObject};
use std::collections::HashSet; use std::collections::HashSet;
#[test] #[test]

View File

@ -4,10 +4,11 @@
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyNativeType};
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::type_object::{PyTypeInfo, PyTypeObject};
use crate::typeob::{PyTypeInfo, PyTypeObject}; use crate::Python;
use crate::ToPyPointer;
use std::borrow::Cow; use std::borrow::Cow;
use std::ffi::CStr; use std::ffi::CStr;

View File

@ -1,3 +1,4 @@
use pyo3::class::basic::CompareOp;
use pyo3::class::*; use pyo3::class::*;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyObjectRef; use pyo3::types::PyObjectRef;

View File

@ -12,7 +12,7 @@ fn empty_class() {
let py = gil.python(); let py = gil.python();
let typeobj = py.get_type::<EmptyClass>(); let typeobj = py.get_type::<EmptyClass>();
// By default, don't allow creating instances from python. // By default, don't allow creating instances from python.
assert!(typeobj.call(NoArgs, None).is_err()); assert!(typeobj.call((), None).is_err());
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'"); py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
} }

View File

@ -18,7 +18,7 @@ fn empty_class_with_new() {
let py = gil.python(); let py = gil.python();
let typeobj = py.get_type::<EmptyClassWithNew>(); let typeobj = py.get_type::<EmptyClassWithNew>();
assert!(typeobj assert!(typeobj
.call(NoArgs, None) .call((), None)
.unwrap() .unwrap()
.cast_as::<EmptyClassWithNew>() .cast_as::<EmptyClassWithNew>()
.is_ok()); .is_ok());

View File

@ -6,8 +6,8 @@ use pyo3::class::{
use pyo3::exceptions::{IndexError, ValueError}; use pyo3::exceptions::{IndexError, ValueError};
use pyo3::ffi; use pyo3::ffi;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::python::ToPyPointer;
use pyo3::types::{PyBytes, PyDict, PyObjectRef, PySlice, PyString, PyType}; use pyo3::types::{PyBytes, PyDict, PyObjectRef, PySlice, PyString, PyType};
use pyo3::ToPyPointer;
use std::{isize, iter}; use std::{isize, iter};
#[macro_use] #[macro_use]
@ -176,7 +176,7 @@ impl PySequenceProtocol for Sequence {
fn __getitem__(&self, key: isize) -> PyResult<isize> { fn __getitem__(&self, key: isize) -> PyResult<isize> {
if key == 5 { if key == 5 {
return Err(PyErr::new::<IndexError, NoArgs>(NoArgs)); return Err(PyErr::new::<IndexError, _>(()));
} }
Ok(key) Ok(key)
} }

View File

@ -3,10 +3,10 @@ use pyo3::class::PyTraverseError;
use pyo3::class::PyVisit; use pyo3::class::PyVisit;
use pyo3::ffi; use pyo3::ffi;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::python::ToPyPointer;
use pyo3::types::PyObjectRef; use pyo3::types::PyObjectRef;
use pyo3::types::PyTuple; use pyo3::types::PyTuple;
use pyo3::PyRawObject; use pyo3::PyRawObject;
use pyo3::ToPyPointer;
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
@ -100,7 +100,7 @@ impl Drop for ClassWithDrop {
} }
} }
// Test behavior of pythonrun::register_pointers + typeob::dealloc // Test behavior of pythonrun::register_pointers + type_object::dealloc
#[test] #[test]
fn create_pointers_in_drop() { fn create_pointers_in_drop() {
let _gil = Python::acquire_gil(); let _gil = Python::acquire_gil();
@ -258,7 +258,7 @@ fn inheritance_with_new_methods_with_drop() {
let py = gil.python(); let py = gil.python();
let _typebase = py.get_type::<BaseClassWithDrop>(); let _typebase = py.get_type::<BaseClassWithDrop>();
let typeobj = py.get_type::<SubClassWithDrop>(); let typeobj = py.get_type::<SubClassWithDrop>();
let inst = typeobj.call(NoArgs, None).unwrap(); let inst = typeobj.call((), None).unwrap();
let obj = SubClassWithDrop::try_from_mut(inst).unwrap(); let obj = SubClassWithDrop::try_from_mut(inst).unwrap();
obj.data = Some(Arc::clone(&drop_called1)); obj.data = Some(Arc::clone(&drop_called1));

View File

@ -60,6 +60,6 @@ fn inheritance_with_new_methods() {
let py = gil.python(); let py = gil.python();
let _typebase = py.get_type::<BaseClass>(); let _typebase = py.get_type::<BaseClass>();
let typeobj = py.get_type::<SubClass>(); let typeobj = py.get_type::<SubClass>();
let inst = typeobj.call(NoArgs, None).unwrap(); let inst = typeobj.call((), None).unwrap();
py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5"); py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5");
} }

View File

@ -86,13 +86,13 @@ fn some_name(_: Python, _: &PyModule) -> PyResult<()> {
#[test] #[test]
#[cfg(Py_3)] #[cfg(Py_3)]
fn test_module_renaming() { fn test_module_renaming() {
use pyo3::wrap_pymodule;
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
let d = PyDict::new(py); let d = PyDict::new(py);
d.set_item("different_name", unsafe { d.set_item("different_name", wrap_pymodule!(other_name)(py))
PyObject::from_owned_ptr(py, PyInit_other_name())
})
.unwrap(); .unwrap();
py.run( py.run(