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
extensions/stamps/
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 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)
* 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
@ -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()]`
* Some macros now emit proper spanned errors instead of panics.
* 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)
* 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
* `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)).
* Removed the unnecessary type parameter from `PyObjectAlloc`
* `NoArgs`. Just use an empty tuple
* `PyObjectWithGIL`. `PyNativeType` is sufficient now that PyToken is removed.
### Fixed

View file

@ -21,7 +21,7 @@ provides two methods:
* `call` - call callable python 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
use pyo3::prelude::*;
@ -87,16 +87,16 @@ fn main() {
// call object with PyDict
let kwargs = PyDict::new(py);
kwargs.set_item(key1, val1);
obj.call(py, NoArgs, Some(kwargs));
obj.call(py, (), Some(kwargs));
// pass arguments as Vec
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
let mut kwargs = HashMap::<&str, i32>::new();
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.
## 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() {
# let gil = Python::acquire_gil();
# let py = gil.python();
# let err = exceptions::TypeError::py_err(NoArgs);
# let err = exceptions::TypeError::py_err(());
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>`.
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
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
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

View file

@ -110,16 +110,16 @@ impl PyClassArgs {
let flag = exp.path.segments.first().unwrap().value().ident.to_string();
let path = match flag.as_str() {
"gc" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_GC}
parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_GC}
}
"weakref" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF}
parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_WEAKREF}
}
"subclass" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_BASETYPE}
parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_BASETYPE}
}
"dict" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT}
parse_quote! {::pyo3::type_object::PY_TYPE_FLAG_DICT}
}
_ => {
return Err(syn::Error::new_spanned(
@ -250,7 +250,7 @@ fn impl_class(
FREELIST = Box::into_raw(Box::new(
::pyo3::freelist::FreeList::with_capacity(#freelist)));
<#cls as ::pyo3::typeob::PyTypeObject>::init_type();
<#cls as ::pyo3::type_object::PyTypeObject>::init_type();
}
&mut *FREELIST
}
@ -259,7 +259,7 @@ fn impl_class(
}
} else {
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;
for f in attr.flags.iter() {
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;
} 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;
}
}
@ -304,7 +304,7 @@ fn impl_class(
let flags = &attr.flags;
quote! {
impl ::pyo3::typeob::PyTypeInfo for #cls {
impl ::pyo3::type_object::PyTypeInfo for #cls {
type Type = #cls;
type BaseType = #base;
@ -319,7 +319,7 @@ fn impl_class(
const OFFSET: isize = {
// 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>() * ::std::mem::align_of::<#cls>()
) as isize

View file

@ -62,7 +62,7 @@ pub fn impl_wrap(
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _result = {
::pyo3::IntoPyResult::into_py_result(#body)
::pyo3::derive_utils::IntoPyResult::into_py_result(#body)
};
::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,
_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),"()");
let _pool = ::pyo3::GILPool::new();
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) => {
let _args = _py.from_borrowed_ptr::<::pyo3::types::PyTuple>(_args);
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() {
return quote! {
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)*
::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
use proc_macro2::TokenStream;
use syn;
pub fn print_err(msg: String, t: TokenStream) {
println!("Error: {} in '{}'", msg, t.to_string());

View file

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

View file

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

View file

@ -10,17 +10,29 @@
use crate::callback::{BoolCallbackConverter, HashConverter, PyObjectCallbackConverter};
use crate::class::methods::PyMethodDef;
use crate::conversion::{FromPyObject, IntoPyObject};
use crate::err::{PyErr, PyResult};
use crate::exceptions;
use crate::ffi;
use crate::objectprotocol::ObjectProtocol;
use crate::python::{IntoPyPointer, Python};
use crate::typeob::PyTypeInfo;
use crate::types::{exceptions, PyObjectRef};
use crate::CompareOp;
use crate::type_object::PyTypeInfo;
use crate::types::PyObjectRef;
use crate::IntoPyPointer;
use crate::Python;
use crate::{FromPyObject, IntoPyObject};
use std::os::raw::c_int;
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
#[allow(unused_variables)]
pub trait PyObjectProtocol<'p>: PyTypeInfo {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,23 +21,10 @@ pub use self::basic::PyObjectProtocol;
pub use self::buffer::PyBufferProtocol;
pub use self::context::PyContextProtocol;
pub use self::descr::PyDescrProtocol;
pub use self::gc::{PyGCProtocol, PyTraverseError, PyVisit};
pub use self::iter::PyIterProtocol;
pub use self::mapping::PyMappingProtocol;
pub use self::methods::{PyGetterDef, PyMethodDef, PyMethodDefType, PyMethodType, PySetterDef};
pub use self::number::PyNumberProtocol;
pub use self::pyasync::PyAsyncProtocol;
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::err::PyResult;
use crate::ffi;
use crate::typeob::PyTypeInfo;
use crate::type_object::PyTypeInfo;
use crate::{FromPyObject, IntoPyObject};
/// Number interface

View file

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

View file

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

View file

@ -1,13 +1,73 @@
// 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::ffi;
use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeInfo;
use crate::type_object::PyTypeInfo;
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`
pub trait ToPyObject {
@ -18,7 +78,9 @@ pub trait ToPyObject {
/// This trait has two implementations: The slow one is implemented for
/// all [ToPyObject] and creates a new object using [ToPyObject::to_object],
/// 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 {
/// Converts self into a Python object and calls the specified closure
/// 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
/// currently no corresponding [std::convert::From] part.
/// Similar to [std::convert::From], just that it requires a gil token.
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 {
/// Performs the conversion.
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`
/// by consuming original object.
pub trait IntoPyObject {
@ -202,20 +287,17 @@ where
/// Trait implemented by Python object types that allow a checked downcast.
/// This trait is similar to `std::convert::TryInto`
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.
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.
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.
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.
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.
@ -250,8 +332,6 @@ impl<U> PyTryInto<U> for PyObjectRef
where
U: for<'v> PyTryFrom<'v>,
{
type Error = PyDowncastError;
fn try_into(&self) -> Result<&U, PyDowncastError> {
U::try_from(self)
}
@ -339,34 +419,20 @@ where
}
}
#[doc(hidden)]
/// 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
/// Converts `()` to an empty Python tuple.
impl FromPy<()> for Py<PyTuple> {
fn from_py(_: (), py: Python) -> Py<PyTuple> {
PyTuple::empty(py)
}
}
#[cfg(test)]
mod test {
use super::PyTryFrom;
use crate::types::PyList;
use crate::Python;
use super::PyTryFrom;
#[test]
fn test_try_from_unchecked() {
let gil = Python::acquire_gil();

View file

@ -4,15 +4,14 @@
//! Functionality for the code generated by the derive backend
use crate::conversion::PyTryFrom;
use crate::err::PyResult;
use crate::exceptions::TypeError;
use crate::ffi;
use crate::init_once;
use crate::types::PyModule;
use crate::types::{PyDict, PyObjectRef, PyString, PyTuple};
use crate::types::{PyDict, PyModule, PyObjectRef, PyString, PyTuple};
use crate::GILPool;
use crate::Python;
use crate::{IntoPyObject, PyTryFrom};
use std::ptr;
/// Description of a python parameter; used for `parse_args()`.
@ -111,14 +110,13 @@ pub fn parse_fn_args<'p>(
}
#[cfg(Py_3)]
#[doc(hidden)]
/// Builds a module (or null) from a user given initializer. Used for `#[pymodule]`.
pub unsafe fn make_module(
name: &str,
doc: &str,
initializer: impl Fn(Python, &PyModule) -> PyResult<()>,
) -> *mut ffi::PyObject {
use crate::python::IntoPyPointer;
use crate::IntoPyPointer;
init_once();
@ -196,3 +194,24 @@ pub unsafe fn make_module(
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
use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use crate::exceptions;
use crate::ffi;
use crate::instance::Py;
use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeObject;
use crate::types::{exceptions, PyObjectRef, PyType};
use crate::type_object::PyTypeObject;
use crate::types::{PyObjectRef, PyType};
use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{IntoPyObject, ToBorrowedObject, ToPyObject};
use libc::c_int;
use std::error::Error;
use std::ffi::CString;
@ -54,7 +57,6 @@ impl PyErr {
/// Creates a new PyErr of type `T`.
///
/// `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)`
/// * 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)]
mod tests {
use crate::types::exceptions;
use crate::exceptions;
use crate::{PyErr, Python};
#[test]

View file

@ -1,13 +1,13 @@
// 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::ffi;
use crate::python::{Python, ToPyPointer};
use crate::typeob::PyTypeObject;
use crate::type_object::PyTypeObject;
use crate::types::{PyObjectRef, PyTuple};
use crate::Python;
use crate::{ToPyObject, ToPyPointer};
use std::ffi::CStr;
use std::os::raw::c_char;
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.
#[macro_export]
macro_rules! import_exception_type_object {
($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> {
// We can't use lazy_static here because raw pointers aren't Send
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.
#[macro_export]
macro_rules! create_exception_type_object {
($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> {
// We can't use lazy_static here because raw pointers aren't Send
static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new();
@ -379,8 +379,8 @@ pub mod socket {
#[cfg(test)]
mod test {
use crate::exceptions::Exception;
use crate::objectprotocol::ObjectProtocol;
use crate::types::exceptions::Exception;
use crate::types::PyDict;
use crate::{PyErr, Python};

View file

@ -3,68 +3,59 @@
#![cfg_attr(Py_LIMITED_API, allow(unused_imports))]
#![cfg_attr(feature="cargo-clippy", allow(clippy::inline_always))]
pub use self::pymem::*;
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::bltinmodule::*;
pub use self::boolobject::*;
pub use self::bytearrayobject::*;
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::descrobject::*;
pub use self::dictobject::*;
pub use self::enumobject::*;
pub use self::eval::*;
pub use self::fileobject::*;
pub use self::floatobject::*;
pub use self::frameobject::PyFrameObject;
pub use self::genobject::*;
pub use self::import::*;
pub use self::intrcheck::*;
pub use self::iterobject::*;
pub use self::listobject::*;
pub use self::longobject::*;
pub use self::memoryobject::*;
pub use self::methodobject::*;
pub use self::modsupport::*;
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::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::setobject::*;
pub use self::sliceobject::*;
pub use self::structseq::*;
pub use self::sysmodule::*;
pub use self::traceback::*;
pub use self::tupleobject::*;
pub use self::typeslots::*;
pub use self::unicodeobject::*;
pub use self::warnings::*;
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 pymacro; contains nothing of interest for Rust
// mod pyatomic; contains nothing of interest for Rust

View file

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

View file

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

View file

@ -1,32 +1,31 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::{PyErr, PyResult};
use crate::ffi;
use crate::gil;
use crate::instance;
use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::pythonrun;
use crate::typeob::PyTypeCreate;
use crate::typeob::{PyTypeInfo, PyTypeObject};
use crate::type_object::PyTypeCreate;
use crate::type_object::{PyTypeInfo, PyTypeObject};
use crate::types::PyObjectRef;
use crate::IntoPyPointer;
use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPyObject, ToPyObject};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
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
/// removed this is only given to native types.
pub trait PyObjectWithGIL: Sized {
/// pyo3 is designed in a way that that all references to those types are bound to the GIL,
/// which is why you can get a token from all references of those types.
pub trait PyNativeType: Sized {
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
/// 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> {}
impl<T> Py<T>
where
T: PyTypeCreate + PyTypeObject,
{
impl<T> Py<T> {
/// 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)?;
ob.init(value);
let ob = unsafe { Py::from_owned_ptr(ob.into_ptr()) };
Ok(ob)
}
}
impl<T> Py<T> {
/// Creates a `Py<T>` instance for the given FFI pointer.
/// This moves ownership over the pointer into the `Py<T>`.
/// 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> {
fn drop(&mut self) {
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::conversion::{
FromPyObject, IntoPy, IntoPyObject, IntoPyResult, PyTryFrom, PyTryInto, ToBorrowedObject,
ToPyObject,
FromPy, FromPyObject, IntoPy, IntoPyObject, IntoPyPointer, PyTryFrom, PyTryInto,
ToBorrowedObject, ToPyObject, ToPyPointer,
};
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
pub use crate::instance::{AsPyRef, Py, PyNativeType, PyObjectWithGIL, PyRef, PyRefMut};
pub use crate::noargs::NoArgs;
pub use crate::gil::{init_once, GILGuard, GILPool};
pub use crate::instance::{AsPyRef, ManagedPyRef, Py, PyNativeType, PyRef, PyRefMut};
pub use crate::object::PyObject;
pub use crate::objectprotocol::ObjectProtocol;
pub use crate::python::{IntoPyPointer, Python, ToPyPointer};
pub use crate::pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool};
pub use crate::typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub use crate::types::exceptions;
pub use crate::python::{prepare_freethreaded_python, Python};
pub use crate::type_object::{PyObjectAlloc, PyRawObject, PyTypeInfo};
// We need that reexport for wrap_function
#[doc(hidden)]
@ -149,7 +138,7 @@ pub use mashup;
#[doc(hidden)]
pub use inventory;
/// Rust FFI declarations for Python
/// Raw ffi declarations for the c interface of python
pub mod ffi;
#[cfg(not(Py_3))]
@ -175,15 +164,15 @@ mod conversion;
#[doc(hidden)]
pub mod derive_utils;
mod err;
pub mod exceptions;
pub mod freelist;
mod gil;
mod instance;
mod noargs;
mod object;
mod objectprotocol;
pub mod prelude;
pub mod python;
mod pythonrun;
pub mod typeob;
mod python;
pub mod type_object;
pub mod types;
/// 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
use crate::conversion::{
FromPyObject, IntoPy, IntoPyObject, PyTryFrom, ToBorrowedObject, ToPyObject,
};
use crate::err::{PyDowncastError, PyErr, PyResult};
use crate::ffi;
use crate::instance::{AsPyRef, PyObjectWithGIL, PyRef, PyRefMut};
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::pythonrun;
use crate::gil;
use crate::instance::{AsPyRef, PyNativeType, PyRef, PyRefMut};
use crate::types::{PyDict, PyObjectRef, PyTuple};
use crate::Py;
use crate::Python;
use crate::ToPyPointer;
use crate::{
FromPyObject, IntoPy, IntoPyObject, IntoPyPointer, PyTryFrom, ToBorrowedObject, ToPyObject,
};
use std::ptr::NonNull;
/// A python object
@ -202,7 +203,7 @@ impl PyObject {
/// Calls the object without arguments.
/// This is equivalent to the Python expression: 'self()'
pub fn call0(&self, py: Python) -> PyResult<PyObject> {
self.call(py, PyTuple::empty(py), None)
self.call(py, (), None)
}
/// Calls the object.
@ -238,7 +239,7 @@ impl PyObject {
/// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name()'
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.
@ -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 {
/// Gets the underlying FFI pointer, returns a owned pointer.
#[inline]
@ -325,16 +318,16 @@ impl<'a> FromPyObject<'a> for PyObject {
impl Drop for PyObject {
fn drop(&mut self) {
unsafe {
pythonrun::register_pointer(self.0);
gil::register_pointer(self.0);
}
}
}
#[cfg(test)]
mod test {
use super::PyObject;
use crate::python::Python;
use crate::types::PyDict;
use crate::PyObject;
use crate::Python;
#[test]
fn test_call_for_non_existing_method() {

View file

@ -1,15 +1,18 @@
// 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::exceptions::TypeError;
use crate::ffi;
use crate::instance::PyObjectWithGIL;
use crate::instance::PyNativeType;
use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeInfo;
use crate::type_object::PyTypeInfo;
use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType};
use crate::IntoPyPointer;
use crate::Py;
use crate::Python;
use crate::ToPyPointer;
use crate::{FromPyObject, IntoPy, PyTryFrom, ToBorrowedObject, ToPyObject};
use std::cmp::Ordering;
use std::os::raw::c_int;
@ -68,7 +71,7 @@ pub trait ObjectProtocol {
/// * CompareOp::Le: `self <= other`
/// * CompareOp::Gt: `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
O: ToPyObject;
@ -208,7 +211,7 @@ pub trait ObjectProtocol {
impl<T> ObjectProtocol for T
where
T: PyObjectWithGIL + ToPyPointer,
T: PyNativeType + ToPyPointer,
{
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>
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
O: ToPyObject,
{
@ -341,7 +344,7 @@ where
}
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> {
@ -372,7 +375,7 @@ where
}
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> {
@ -497,10 +500,10 @@ where
#[cfg(test)]
mod test {
use super::*;
use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef;
use crate::python::Python;
use crate::types::{IntoPyDict, PyString};
use crate::Python;
use crate::{PyTryFrom, ToPyObject};
#[test]
fn test_debug_string() {

View file

@ -10,14 +10,15 @@
//! use pyo3::prelude::*;
//! ```
pub use crate::conversion::{FromPyObject, IntoPyObject, PyTryFrom, PyTryInto, ToPyObject};
pub use crate::err::{PyErr, PyResult};
pub use crate::gil::GILGuard;
pub use crate::instance::{AsPyRef, Py, PyRef, PyRefMut};
pub use crate::noargs::NoArgs;
pub use crate::object::PyObject;
pub use crate::objectprotocol::ObjectProtocol;
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
pub use crate::types::PyModule;
// This is required for the constructor

View file

@ -2,20 +2,22 @@
//
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use crate::conversion::PyTryFrom;
use crate::err::{PyDowncastError, PyErr, PyResult};
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::pythonrun::{self, GILGuard};
use crate::typeob::PyTypeCreate;
use crate::typeob::{PyTypeInfo, PyTypeObject};
use crate::type_object::{PyTypeInfo, PyTypeObject};
use crate::types::{PyDict, PyModule, PyObjectRef, PyType};
use crate::ToPyPointer;
use crate::{IntoPyPointer, PyTryFrom};
use std::ffi::CString;
use std::marker::PhantomData;
use std::os::raw::c_int;
use std::ptr::NonNull;
pub use gil::prepare_freethreaded_python;
/// 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.
@ -48,62 +50,6 @@ use std::ptr::NonNull;
#[derive(Copy, Clone)]
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> {
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
/// 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> {
unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p T {
if T::OFFSET == 0 {
@ -303,7 +217,7 @@ impl<'p> Python<'p> {
where
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)
}
@ -312,14 +226,14 @@ impl<'p> Python<'p> {
where
T: PyTypeInfo,
{
let p = pythonrun::register_owned(self, obj.into_nonnull());
let p = gil::register_owned(self, obj.into_nonnull());
self.unchecked_downcast(p)
}
/// Register `ffi::PyObject` pointer in release pool
pub unsafe fn from_borrowed_ptr_to_obj(self, ptr: *mut ffi::PyObject) -> &'p PyObjectRef {
match NonNull::new(ptr) {
Some(p) => pythonrun::register_borrowed(self, p),
Some(p) => gil::register_borrowed(self, p),
None => crate::err::panic_after_error(),
}
}
@ -333,7 +247,7 @@ impl<'p> Python<'p> {
{
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_owned(self, p);
let p = gil::register_owned(self, p);
self.unchecked_downcast(p)
}
None => crate::err::panic_after_error(),
@ -348,7 +262,7 @@ impl<'p> Python<'p> {
{
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_owned(self, p);
let p = gil::register_owned(self, p);
self.unchecked_mut_downcast(p)
}
None => crate::err::panic_after_error(),
@ -364,7 +278,7 @@ impl<'p> Python<'p> {
{
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_owned(self, p);
let p = gil::register_owned(self, p);
Ok(self.unchecked_downcast(p))
}
None => Err(PyErr::fetch(self)),
@ -379,7 +293,7 @@ impl<'p> Python<'p> {
T: PyTypeInfo,
{
NonNull::new(ptr).map(|p| {
let p = pythonrun::register_owned(self, p);
let p = gil::register_owned(self, p);
self.unchecked_downcast(p)
})
}
@ -393,7 +307,7 @@ impl<'p> Python<'p> {
{
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_borrowed(self, p);
let p = gil::register_borrowed(self, p);
self.unchecked_downcast(p)
}
None => crate::err::panic_after_error(),
@ -409,7 +323,7 @@ impl<'p> Python<'p> {
{
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_borrowed(self, p);
let p = gil::register_borrowed(self, p);
self.unchecked_mut_downcast(p)
}
None => crate::err::panic_after_error(),
@ -425,7 +339,7 @@ impl<'p> Python<'p> {
{
match NonNull::new(ptr) {
Some(p) => {
let p = pythonrun::register_borrowed(self, p);
let p = gil::register_borrowed(self, p);
Ok(self.unchecked_downcast(p))
}
None => Err(PyErr::fetch(self)),
@ -440,7 +354,7 @@ impl<'p> Python<'p> {
T: PyTypeInfo,
{
NonNull::new(ptr).map(|p| {
let p = pythonrun::register_borrowed(self, p);
let p = gil::register_borrowed(self, p);
self.unchecked_downcast(p)
})
}
@ -449,7 +363,7 @@ impl<'p> Python<'p> {
/// Pass value ownership to `Python` object and get reference back.
/// Value get cleaned up on the GIL release.
pub fn register_any<T: 'static>(self, ob: T) -> &'p T {
unsafe { pythonrun::register_any(ob) }
unsafe { gil::register_any(ob) }
}
/// Release PyObject reference.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@ fn empty_class() {
let py = gil.python();
let typeobj = py.get_type::<EmptyClass>();
// 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'");
}

View file

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

View file

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

View file

@ -3,10 +3,10 @@ use pyo3::class::PyTraverseError;
use pyo3::class::PyVisit;
use pyo3::ffi;
use pyo3::prelude::*;
use pyo3::python::ToPyPointer;
use pyo3::types::PyObjectRef;
use pyo3::types::PyTuple;
use pyo3::PyRawObject;
use pyo3::ToPyPointer;
use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};
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]
fn create_pointers_in_drop() {
let _gil = Python::acquire_gil();
@ -258,7 +258,7 @@ fn inheritance_with_new_methods_with_drop() {
let py = gil.python();
let _typebase = py.get_type::<BaseClassWithDrop>();
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();
obj.data = Some(Arc::clone(&drop_called1));

View file

@ -60,6 +60,6 @@ fn inheritance_with_new_methods() {
let py = gil.python();
let _typebase = py.get_type::<BaseClass>();
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");
}

View file

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