Merge branch 'master' into merge-0.9.2

This commit is contained in:
Yuji Kanagawa 2020-04-09 17:17:52 +09:00 committed by GitHub
commit 5add8d1dee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1409 additions and 1078 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed
* `__radd__` and other `__r*__` methods now correctly work with operators. [#839](https://github.com/PyO3/pyo3/pull/839)
* Garbage Collector causing random panics when traversing objects that were mutably borrowed. [#855](https://github.com/PyO3/pyo3/pull/855)
## [0.9.2]
@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* `PyAny` is now on the top level module and prelude. [#816](https://github.com/PyO3/pyo3/pull/816)
### Added
* `PyCell`, which has RefCell-like features. [#770](https://github.com/PyO3/pyo3/pull/770)
* `PyClass`, `PyLayout`, `PyClassInitializer`. [#683](https://github.com/PyO3/pyo3/pull/683)
* Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716)
@ -113,14 +115,12 @@ and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642).
* Remove `__contains__` and `__iter__` from PyMappingProtocol. [#644](https://github.com/PyO3/pyo3/pull/644)
* Fix proc-macro definition of PySetAttrProtocol. [#645](https://github.com/PyO3/pyo3/pull/645)
## [0.8.1]
### Added
* Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608)
### Fixed
* Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604)
@ -403,7 +403,6 @@ Yanked
* Remove use of now unneeded 'AsciiExt' trait
## [0.2.2] - 09-26-2017
### Changed

View File

@ -128,13 +128,18 @@ fn main_(py: Python) -> PyResult<()> {
Our guide has [a section](https://pyo3.rs/master/python_from_rust.html) with lots of examples
about this topic.
## Examples and tooling
## Tools and libraries
* [maturin](https://github.com/PyO3/maturin) _Zero configuration build tool for Rust-made Python extensions_.
* [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_.
* [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_
* [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_
* [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_
## Examples
* [examples/word-count](examples/word-count) _Counting the occurrences of a word in a text file_
* [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_
* [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_
* [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/master/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._
* [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_
* [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library_
* [autopy](https://github.com/autopilot-rs/autopy) _A simple, cross-platform GUI automation library for Python and Rust._
* Contains an example of building wheels on TravisCI and appveyor using [cibuildwheel](https://github.com/joerick/cibuildwheel)
@ -144,7 +149,6 @@ about this topic.
* Contains an example of building wheels on Azure Pipelines
* [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library_
* [python-ext-wasm](https://github.com/wasmerio/python-ext-wasm) _Python library to run WebAssembly binaries_
* [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_
* [mocpy](https://github.com/cds-astro/mocpy) _Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere_
* [tokenizers](https://github.com/huggingface/tokenizers/tree/master/bindings/python) _Python bindings to the Hugging Face tokenizers (NLP) written in Rust_

View File

@ -123,13 +123,18 @@ fn main_(py: Python) -> PyResult<()> {
Our guide has [a section](https://pyo3.rs/master/python_from_rust.html) with lots of examples
about this topic.
## Examples and tooling
* [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count) _Counting the occurrences of a word in a text file_
* [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_
* [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_
* [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/master/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._
## Tools and libraries
* [maturin](https://github.com/PyO3/maturin) _Zero configuration build tool for Rust-made Python extensions_.
* [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_.
* [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_
* [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_
* [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_
## Examples
* [examples/word-count](examples/word-count) _Counting the occurrences of a word in a text file_
* [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json_
* [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/master/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._
* [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library_
* [autopy](https://github.com/autopilot-rs/autopy) _A simple, cross-platform GUI automation library for Python and Rust._
* Contains an example of building wheels on TravisCI and appveyor using [cibuildwheel](https://github.com/joerick/cibuildwheel)
@ -139,4 +144,5 @@ about this topic.
* Contains an example of building wheels on Azure Pipelines
* [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library_
* [python-ext-wasm](https://github.com/wasmerio/python-ext-wasm) _Python library to run WebAssembly binaries_
* [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_
* [mocpy](https://github.com/cds-astro/mocpy) _Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere_
* [tokenizers](https://github.com/huggingface/tokenizers/tree/master/bindings/python) _Python bindings to the Hugging Face tokenizers (NLP) written in Rust_

View File

@ -7,9 +7,44 @@ pub struct Proto {
pub py_methods: &'static [PyMethod],
}
impl Proto {
pub(crate) fn get_proto<Q>(&self, query: Q) -> Option<&'static MethodProto>
where
Q: PartialEq<&'static str>,
{
self.methods.iter().find(|m| query == m.name())
}
pub(crate) fn get_method<Q>(&self, query: Q) -> Option<&'static PyMethod>
where
Q: PartialEq<&'static str>,
{
self.py_methods.iter().find(|m| query == m.name)
}
}
// TODO(kngwyu): Currently only __radd__-like methods use METH_COEXIST to prevent
// __add__-like methods from overriding them.
pub struct PyMethod {
pub name: &'static str,
pub proto: &'static str,
pub can_coexist: bool,
}
impl PyMethod {
const fn coexist(name: &'static str, proto: &'static str) -> Self {
PyMethod {
name,
proto,
can_coexist: true,
}
}
const fn new(name: &'static str, proto: &'static str) -> Self {
PyMethod {
name,
proto,
can_coexist: false,
}
}
}
pub const OBJECT: Proto = Proto {
@ -73,18 +108,9 @@ pub const OBJECT: Proto = Proto {
},
],
py_methods: &[
PyMethod {
name: "__format__",
proto: "pyo3::class::basic::FormatProtocolImpl",
},
PyMethod {
name: "__bytes__",
proto: "pyo3::class::basic::BytesProtocolImpl",
},
PyMethod {
name: "__unicode__",
proto: "pyo3::class::basic::UnicodeProtocolImpl",
},
PyMethod::new("__format__", "pyo3::class::basic::FormatProtocolImpl"),
PyMethod::new("__bytes__", "pyo3::class::basic::BytesProtocolImpl"),
PyMethod::new("__unicode__", "pyo3::class::basic::UnicodeProtocolImpl"),
],
};
@ -120,14 +146,14 @@ pub const ASYNC: Proto = Proto {
},
],
py_methods: &[
PyMethod {
name: "__aenter__",
proto: "pyo3::class::pyasync::PyAsyncAenterProtocolImpl",
},
PyMethod {
name: "__aexit__",
proto: "pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
},
PyMethod::new(
"__aenter__",
"pyo3::class::pyasync::PyAsyncAenterProtocolImpl",
),
PyMethod::new(
"__aexit__",
"pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
),
],
};
@ -165,14 +191,14 @@ pub const CONTEXT: Proto = Proto {
},
],
py_methods: &[
PyMethod {
name: "__enter__",
proto: "pyo3::class::context::PyContextEnterProtocolImpl",
},
PyMethod {
name: "__exit__",
proto: "pyo3::class::context::PyContextExitProtocolImpl",
},
PyMethod::new(
"__enter__",
"pyo3::class::context::PyContextEnterProtocolImpl",
),
PyMethod::new(
"__exit__",
"pyo3::class::context::PyContextExitProtocolImpl",
),
],
};
@ -222,14 +248,11 @@ pub const DESCR: Proto = Proto {
},
],
py_methods: &[
PyMethod {
name: "__del__",
proto: "pyo3::class::context::PyDescrDelProtocolImpl",
},
PyMethod {
name: "__set_name__",
proto: "pyo3::class::context::PyDescrNameProtocolImpl",
},
PyMethod::new("__del__", "pyo3::class::context::PyDescrDelProtocolImpl"),
PyMethod::new(
"__set_name__",
"pyo3::class::context::PyDescrNameProtocolImpl",
),
],
};
@ -283,10 +306,10 @@ pub const MAPPING: Proto = Proto {
proto: "pyo3::class::mapping::PyMappingReversedProtocol",
},
],
py_methods: &[PyMethod {
name: "__reversed__",
proto: "pyo3::class::mapping::PyMappingReversedProtocolImpl",
}],
py_methods: &[PyMethod::new(
"__reversed__",
"pyo3::class::mapping::PyMappingReversedProtocolImpl",
)],
};
pub const SEQ: Proto = Proto {
@ -579,10 +602,9 @@ pub const NUM: Proto = Proto {
pyres: false,
proto: "pyo3::class::number::PyNumberIModProtocol",
},
MethodProto::Ternary {
MethodProto::Binary {
name: "__ipow__",
arg1: "Other",
arg2: "Modulo",
arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIPowProtocol",
},
@ -651,81 +673,58 @@ pub const NUM: Proto = Proto {
pyres: true,
proto: "pyo3::class::number::PyNumberFloatProtocol",
},
MethodProto::Unary {
name: "__round__",
pyres: true,
proto: "pyo3::class::number::PyNumberRoundProtocol",
},
MethodProto::Unary {
name: "__index__",
pyres: true,
proto: "pyo3::class::number::PyNumberIndexProtocol",
},
MethodProto::Binary {
name: "__round__",
arg: "NDigits",
pyres: true,
proto: "pyo3::class::number::PyNumberRoundProtocol",
},
],
py_methods: &[
PyMethod {
name: "__radd__",
proto: "pyo3::class::number::PyNumberRAddProtocolImpl",
},
PyMethod {
name: "__rsub__",
proto: "pyo3::class::number::PyNumberRSubProtocolImpl",
},
PyMethod {
name: "__rmul__",
proto: "pyo3::class::number::PyNumberRMulProtocolImpl",
},
PyMethod {
name: "__rmatmul__",
proto: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
},
PyMethod {
name: "__rtruediv__",
proto: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
},
PyMethod {
name: "__rfloordiv__",
proto: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
},
PyMethod {
name: "__rmod__",
proto: "pyo3::class::number::PyNumberRModProtocolImpl",
},
PyMethod {
name: "__rdivmod__",
proto: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
},
PyMethod {
name: "__rpow__",
proto: "pyo3::class::number::PyNumberRPowProtocolImpl",
},
PyMethod {
name: "__rlshift__",
proto: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
},
PyMethod {
name: "__rrshift__",
proto: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
},
PyMethod {
name: "__rand__",
proto: "pyo3::class::number::PyNumberRAndProtocolImpl",
},
PyMethod {
name: "__rxor__",
proto: "pyo3::class::number::PyNumberRXorProtocolImpl",
},
PyMethod {
name: "__ror__",
proto: "pyo3::class::number::PyNumberROrProtocolImpl",
},
PyMethod {
name: "__complex__",
proto: "pyo3::class::number::PyNumberComplexProtocolImpl",
},
PyMethod {
name: "__round__",
proto: "pyo3::class::number::PyNumberRoundProtocolImpl",
},
PyMethod::coexist("__radd__", "pyo3::class::number::PyNumberRAddProtocolImpl"),
PyMethod::coexist("__rsub__", "pyo3::class::number::PyNumberRSubProtocolImpl"),
PyMethod::coexist("__rmul__", "pyo3::class::number::PyNumberRMulProtocolImpl"),
PyMethod::coexist(
"__rmatmul__",
"pyo3::class::number::PyNumberRMatmulProtocolImpl",
),
PyMethod::coexist(
"__rtruediv__",
"pyo3::class::number::PyNumberRTruedivProtocolImpl",
),
PyMethod::coexist(
"__rfloordiv__",
"pyo3::class::number::PyNumberRFloordivProtocolImpl",
),
PyMethod::coexist("__rmod__", "pyo3::class::number::PyNumberRModProtocolImpl"),
PyMethod::coexist(
"__rdivmod__",
"pyo3::class::number::PyNumberRDivmodProtocolImpl",
),
PyMethod::coexist("__rpow__", "pyo3::class::number::PyNumberRPowProtocolImpl"),
PyMethod::coexist(
"__rlshift__",
"pyo3::class::number::PyNumberRLShiftProtocolImpl",
),
PyMethod::coexist(
"__rrshift__",
"pyo3::class::number::PyNumberRRShiftProtocolImpl",
),
PyMethod::coexist("__rand__", "pyo3::class::number::PyNumberRAndProtocolImpl"),
PyMethod::coexist("__rxor__", "pyo3::class::number::PyNumberRXorProtocolImpl"),
PyMethod::coexist("__ror__", "pyo3::class::number::PyNumberROrProtocolImpl"),
PyMethod::new(
"__complex__",
"pyo3::class::number::PyNumberComplexProtocolImpl",
),
PyMethod::new(
"__round__",
"pyo3::class::number::PyNumberRoundProtocolImpl",
),
],
};

View File

@ -69,7 +69,7 @@ impl MethodProto {
}
}
pub fn impl_method_proto(
pub(crate) fn impl_method_proto(
cls: &syn::Type,
sig: &mut syn::Signature,
meth: &MethodProto,

View File

@ -63,7 +63,7 @@ impl<'a> FnSpec<'a> {
let is_mut = self
.self_
.expect("impl_borrow_self is called for non-self fn");
crate::utils::borrow_self(is_mut, true)
crate::utils::borrow_self(is_mut)
}
/// Parser function signature and function attributes

View File

@ -221,13 +221,15 @@ fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>) -> TokenStream {
const _LOCATION: &'static str = concat!(stringify!(#name), "()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
#body
#body
pyo3::callback::cb_obj_convert(_py, _result)
pyo3::callback::convert(_py, _result)
})
}
}
}

View File

@ -459,7 +459,6 @@ fn impl_descriptors(
.collect::<syn::Result<_>>()?;
Ok(quote! {
pyo3::inventory::submit! {
#![crate = pyo3] {
type ClsInventory = <#cls as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;

View File

@ -83,10 +83,7 @@ pub fn impl_wrap_pyslf(
};
let slf = quote! {
let _cell = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _slf: #self_ty = match std::convert::TryFrom::try_from(_cell) {
Ok(_slf) => _slf,
Err(e) => return pyo3::PyErr::from(e).restore_and_null(_py),
};
let _slf: #self_ty = std::convert::TryFrom::try_from(_cell)?;
};
impl_wrap_common(cls, spec, noargs, slf, body)
}
@ -109,13 +106,11 @@ fn impl_wrap_common(
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#python_name), "()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
#slf
let _result = {
pyo3::derive_utils::IntoPyResult::into_py_result(#body)
};
pyo3::callback::cb_obj_convert(_py, _result)
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
#slf
pyo3::callback::convert(_py, #body)
})
}
}
} else {
@ -130,14 +125,16 @@ fn impl_wrap_common(
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#python_name), "()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
#body
#body
pyo3::callback::cb_obj_convert(_py, _result)
pyo3::callback::convert(_py, _result)
})
}
}
}
@ -159,15 +156,17 @@ pub fn impl_proto_wrap(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
#body
#body
pyo3::callback::cb_obj_convert(_py, _result)
pyo3::callback::convert(_py, _result)
})
}
}
}
@ -195,16 +194,16 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
#body
#body
match _result.and_then(|init| pyo3::PyClassInitializer::from(init).create_cell(_py)) {
Ok(slf) => slf as _,
Err(e) => e.restore_and_null(_py),
}
let cell = pyo3::PyClassInitializer::from(_result?).create_cell(_py)?;
Ok(cell as *mut pyo3::ffi::PyObject)
})
}
}
}
@ -227,14 +226,16 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
#body
#body
pyo3::callback::cb_obj_convert(_py, _result)
pyo3::callback::convert(_py, _result)
})
}
}
}
@ -257,13 +258,15 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
#body
#body
pyo3::callback::cb_obj_convert(_py, _result)
pyo3::callback::convert(_py, _result)
})
}
}
}
@ -305,7 +308,7 @@ pub(crate) fn impl_wrap_getter(
PropertyType::Function(spec) => (spec.python_name.clone(), impl_call_getter(&spec)?),
};
let borrow_self = crate::utils::borrow_self(false, true);
let borrow_self = crate::utils::borrow_self(false);
Ok(quote! {
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> *mut pyo3::ffi::PyObject
@ -313,16 +316,12 @@ pub(crate) fn impl_wrap_getter(
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
let result = pyo3::derive_utils::IntoPyResult::into_py_result(#getter_impl);
match result {
Ok(val) => pyo3::IntoPyPointer::into_ptr(pyo3::IntoPy::<PyObject>::into_py(val, _py)),
Err(e) => e.restore_and_null(_py),
}
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
pyo3::callback::convert(_py, #getter_impl)
})
}
})
}
@ -344,9 +343,9 @@ fn impl_call_setter(spec: &FnSpec) -> syn::Result<TokenStream> {
let name = &spec.name;
let fncall = if py_arg.is_some() {
quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_py, _val)))
quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_py, _val))?;)
} else {
quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_val)))
quote!(pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_val))?;)
};
Ok(fncall)
@ -360,12 +359,12 @@ pub(crate) fn impl_wrap_setter(
let (python_name, setter_impl) = match property_type {
PropertyType::Descriptor(field) => {
let name = field.ident.as_ref().unwrap();
(name.unraw(), quote!({ _slf.#name = _val; Ok(()) }))
(name.unraw(), quote!(_slf.#name = _val;))
}
PropertyType::Function(spec) => (spec.python_name.clone(), impl_call_setter(&spec)?),
};
let borrow_self = crate::utils::borrow_self(true, false);
let borrow_self = crate::utils::borrow_self(true);
Ok(quote! {
#[allow(unused_mut)]
unsafe extern "C" fn __wrap(
@ -374,21 +373,14 @@ pub(crate) fn impl_wrap_setter(
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
let _value = _py.from_borrowed_ptr(_value);
let _result = match pyo3::FromPyObject::extract(_value) {
Ok(_val) => {
#setter_impl
}
Err(e) => Err(e)
};
match _result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(_py),
}
pyo3::run_callback(_py, || {
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
let _value = _py.from_borrowed_ptr::<pyo3::types::PyAny>(_value);
let _val = pyo3::FromPyObject::extract(_value)?;
pyo3::callback::convert(_py, {#setter_impl})
})
}
})
}
@ -462,22 +454,19 @@ fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStre
let mut _args = _args;
let mut _kwargs = _kwargs;
// Workaround to use the question mark operator without rewriting everything
let _result = (|| {
let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args(
Some(_LOCATION),
PARAMS,
_args,
_kwargs,
#accept_args,
#accept_kwargs,
&mut output
)?;
let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args(
Some(_LOCATION),
PARAMS,
_args,
_kwargs,
#accept_args,
#accept_kwargs,
&mut output
)?;
#(#param_conversion)*
#(#param_conversion)*
#into_result(#body)
})();
let _result = #into_result(#body);
}
}

View File

@ -63,39 +63,40 @@ fn impl_proto_impl(
for iimpl in impls.iter_mut() {
if let syn::ImplItem::Method(ref mut met) = iimpl {
for m in proto.methods {
if met.sig.ident == m.name() {
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
}
if let Some(m) = proto.get_proto(&met.sig.ident) {
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
}
for m in proto.py_methods {
if met.sig.ident == m.name {
let name = &met.sig.ident;
let proto: syn::Path = syn::parse_str(m.proto).unwrap();
if let Some(m) = proto.get_method(&met.sig.ident) {
let name = &met.sig.ident;
let proto: syn::Path = syn::parse_str(m.proto).unwrap();
let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) {
Ok(fn_spec) => fn_spec,
Err(err) => return err.to_compile_error(),
};
let meth = pymethod::impl_proto_wrap(ty, &fn_spec);
let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) {
Ok(fn_spec) => fn_spec,
Err(err) => return err.to_compile_error(),
};
let meth = pymethod::impl_proto_wrap(ty, &fn_spec);
let coexist = if m.can_coexist {
quote!(pyo3::ffi::METH_COEXIST)
} else {
quote!(0)
};
py_methods.push(quote! {
impl #proto for #ty
{
#[inline]
fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
#meth
py_methods.push(quote! {
impl #proto for #ty
{
#[inline]
fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
#meth
Some(pyo3::class::PyMethodDef {
ml_name: stringify!(#name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
ml_doc: ""
})
}
Some(pyo3::class::PyMethodDef {
ml_name: stringify!(#name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
// We need METH_COEXIST here to prevent __add__ from overriding __radd__
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist,
ml_doc: ""
})
}
});
}
}
});
}
}
}

View File

@ -4,25 +4,14 @@ use proc_macro2::TokenStream;
use quote::quote;
use std::fmt::Display;
pub(crate) fn borrow_self(is_mut: bool, return_null: bool) -> TokenStream {
let ret = if return_null {
quote! { restore_and_null }
} else {
quote! { restore_and_minus1 }
};
pub(crate) fn borrow_self(is_mut: bool) -> TokenStream {
if is_mut {
quote! {
let mut _slf = match _slf.try_borrow_mut() {
Ok(ref_) => ref_,
Err(e) => return pyo3::PyErr::from(e).#ret(_py),
};
let mut _slf = _slf.try_borrow_mut()?;
}
} else {
quote! {
let _slf = match _slf.try_borrow() {
Ok(ref_) => ref_,
Err(e) => return pyo3::PyErr::from(e).#ret(_py),
};
let _slf = _slf.try_borrow()?;
}
}
}

View File

@ -7,89 +7,91 @@ use crate::exceptions::OverflowError;
use crate::ffi::{self, Py_hash_t};
use crate::IntoPyPointer;
use crate::{IntoPy, PyObject, Python};
use std::isize;
use std::os::raw::c_int;
use std::{isize, ptr};
/// A type which can be the return type of a python C-API callback
pub trait PyCallbackOutput: Copy {
/// The error value to return to python if the callback raised an exception
const ERR_VALUE: Self;
}
impl PyCallbackOutput for *mut ffi::PyObject {
const ERR_VALUE: Self = std::ptr::null_mut();
}
impl PyCallbackOutput for libc::c_int {
const ERR_VALUE: Self = -1;
}
impl PyCallbackOutput for ffi::Py_ssize_t {
const ERR_VALUE: Self = -1;
}
impl PyCallbackOutput for () {
const ERR_VALUE: Self = ();
}
/// Convert the result of callback function into the appropriate return value.
///
/// Used by PyO3 macros.
pub trait CallbackConverter {
type Source;
type Result: Copy;
const ERR_VALUE: Self::Result;
pub trait IntoPyCallbackOutput<Target> {
fn convert(self, py: Python) -> PyResult<Target>;
}
fn convert(s: Self::Source, py: Python) -> Self::Result;
#[inline]
fn convert_result(py: Python, value: PyResult<Self::Source>) -> Self::Result {
match value {
Ok(val) => Self::convert(val, py),
Err(e) => {
e.restore(py);
Self::ERR_VALUE
}
}
impl<T, U> IntoPyCallbackOutput<U> for PyResult<T>
where
T: IntoPyCallbackOutput<U>,
{
fn convert(self, py: Python) -> PyResult<U> {
self.and_then(|t| t.convert(py))
}
}
pub struct PyObjectCallbackConverter<T>(pub std::marker::PhantomData<T>);
impl<T> CallbackConverter for PyObjectCallbackConverter<T>
impl<T> IntoPyCallbackOutput<*mut ffi::PyObject> for T
where
T: IntoPy<PyObject>,
{
type Source = T;
type Result = *mut ffi::PyObject;
const ERR_VALUE: Self::Result = ptr::null_mut();
fn convert(s: Self::Source, py: Python) -> Self::Result {
s.into_py(py).into_ptr()
fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> {
Ok(self.into_py(py).into_ptr())
}
}
pub struct BoolCallbackConverter;
impl IntoPyCallbackOutput<Self> for *mut ffi::PyObject {
fn convert(self, _: Python) -> PyResult<Self> {
Ok(self)
}
}
impl CallbackConverter for BoolCallbackConverter {
type Source = bool;
type Result = c_int;
const ERR_VALUE: Self::Result = -1;
impl IntoPyCallbackOutput<libc::c_int> for () {
fn convert(self, _: Python) -> PyResult<libc::c_int> {
Ok(0)
}
}
impl IntoPyCallbackOutput<libc::c_int> for bool {
fn convert(self, _: Python) -> PyResult<libc::c_int> {
Ok(self as c_int)
}
}
impl IntoPyCallbackOutput<()> for () {
fn convert(self, _: Python) -> PyResult<()> {
Ok(())
}
}
pub struct LenCallbackOutput(pub usize);
impl IntoPyCallbackOutput<ffi::Py_ssize_t> for LenCallbackOutput {
#[inline]
fn convert(s: Self::Source, _py: Python) -> Self::Result {
s as c_int
}
}
pub struct LenResultConverter;
impl CallbackConverter for LenResultConverter {
type Source = usize;
type Result = isize;
const ERR_VALUE: Self::Result = -1;
fn convert(val: Self::Source, py: Python) -> Self::Result {
if val <= (isize::MAX as usize) {
val as isize
fn convert(self, _py: Python) -> PyResult<ffi::Py_ssize_t> {
if self.0 <= (isize::MAX as usize) {
Ok(self.0 as isize)
} else {
OverflowError::py_err(()).restore(py);
-1
Err(OverflowError::py_err(()))
}
}
}
pub struct UnitCallbackConverter;
impl CallbackConverter for UnitCallbackConverter {
type Source = ();
type Result = c_int;
const ERR_VALUE: Self::Result = -1;
#[inline]
fn convert(_s: Self::Source, _py: Python) -> Self::Result {
0
}
}
pub trait WrappingCastTo<T> {
fn wrapping_cast(self) -> T;
}
@ -115,50 +117,49 @@ wrapping_cast!(i32, Py_hash_t);
wrapping_cast!(isize, Py_hash_t);
wrapping_cast!(i64, Py_hash_t);
pub struct HashConverter<T>(pub std::marker::PhantomData<T>);
pub struct HashCallbackOutput<T>(pub T);
impl<T> CallbackConverter for HashConverter<T>
impl<T> IntoPyCallbackOutput<Py_hash_t> for HashCallbackOutput<T>
where
T: WrappingCastTo<Py_hash_t>,
{
type Source = T;
type Result = Py_hash_t;
const ERR_VALUE: Self::Result = -1;
#[inline]
fn convert(val: T, _py: Python) -> Py_hash_t {
let hash = val.wrapping_cast();
fn convert(self, _py: Python) -> PyResult<Py_hash_t> {
let hash = self.0.wrapping_cast();
if hash == -1 {
-2
Ok(-2)
} else {
hash
Ok(hash)
}
}
}
// Short hands methods for macros
#[doc(hidden)]
#[inline]
pub fn cb_convert<C, T>(_c: C, py: Python, value: PyResult<T>) -> C::Result
pub fn convert<T, U>(py: Python, value: T) -> PyResult<U>
where
C: CallbackConverter<Source = T>,
T: IntoPyCallbackOutput<U>,
{
C::convert_result(py, value)
value.convert(py)
}
// Same as cb_convert(PyObjectCallbackConverter<T>, py, value)
#[doc(hidden)]
#[inline]
pub fn cb_obj_convert<T: IntoPy<PyObject>>(
py: Python,
value: PyResult<T>,
) -> <PyObjectCallbackConverter<T> as CallbackConverter>::Result {
PyObjectCallbackConverter::<T>::convert_result(py, value)
pub fn callback_error<T>() -> T
where
T: PyCallbackOutput,
{
T::ERR_VALUE
}
#[inline]
pub unsafe fn cb_err<C>(_c: C, py: Python, err: impl Into<crate::PyErr>) -> C::Result
#[doc(hidden)]
pub fn run_callback<T, F>(py: Python, callback: F) -> T
where
C: CallbackConverter,
F: FnOnce() -> PyResult<T>,
T: PyCallbackOutput,
{
err.into().restore(py);
C::ERR_VALUE
callback().unwrap_or_else(|e| {
e.restore(py);
T::ERR_VALUE
})
}

View File

@ -8,11 +8,11 @@
//! Parts of the documentation are copied from the respective methods from the
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)
use crate::callback::{BoolCallbackConverter, HashConverter, PyObjectCallbackConverter};
use crate::callback::HashCallbackOutput;
use crate::class::methods::PyMethodDef;
use crate::{
exceptions, ffi, FromPyObject, IntoPy, IntoPyPointer, ObjectProtocol, PyAny, PyClass, PyErr,
PyObject, PyResult, Python,
callback, exceptions, ffi, run_callback, FromPyObject, GILPool, IntoPy, ObjectProtocol, PyAny,
PyCell, PyClass, PyErr, PyObject, PyResult, Python,
};
use std::os::raw::c_int;
@ -219,27 +219,23 @@ where
T: for<'p> PyObjectGetAttrProtocol<'p>,
{
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
run_callback(py, || {
let _pool = GILPool::new(py);
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
// for existing fields and methods first
let existing = ffi::PyObject_GenericGetAttr(slf, arg);
if existing.is_null() {
// PyObject_HasAttr also tries to get an object and clears the error if it fails
ffi::PyErr_Clear();
} else {
return existing;
}
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
// for existing fields and methods first
let existing = ffi::PyObject_GenericGetAttr(slf, arg);
if existing.is_null() {
// PyObject_HasAttr also tries to get an object and clears the error if it fails
ffi::PyErr_Clear();
} else {
return Ok(existing);
}
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<crate::PyAny>(arg);
call_ref_with_converter!(
slf,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData),
py,
__getattr__,
arg
)
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<PyAny>(arg);
callback::convert(py, call_ref!(slf, __getattr__, arg))
})
}
Some(wrap::<T>)
}
@ -357,11 +353,7 @@ where
T: for<'p> PyObjectStrProtocol<'p>,
{
fn tp_str() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyObjectStrProtocol,
T::__str__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyObjectStrProtocol, T::__str__)
}
}
@ -381,11 +373,7 @@ where
T: for<'p> PyObjectReprProtocol<'p>,
{
fn tp_repr() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyObjectReprProtocol,
T::__repr__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyObjectReprProtocol, T::__repr__)
}
}
@ -447,8 +435,8 @@ where
py_unary_func!(
PyObjectHashProtocol,
T::__hash__,
HashConverter::<isize>(std::marker::PhantomData),
ffi::Py_hash_t
ffi::Py_hash_t,
HashCallbackOutput
)
}
}
@ -469,12 +457,7 @@ where
T: for<'p> PyObjectBoolProtocol<'p>,
{
fn nb_bool() -> Option<ffi::inquiry> {
py_unary_func!(
PyObjectBoolProtocol,
T::__bool__,
BoolCallbackConverter,
c_int
)
py_unary_func!(PyObjectBoolProtocol, T::__bool__, c_int)
}
}
@ -503,26 +486,17 @@ where
T: for<'p> PyObjectRichcmpProtocol<'p>,
{
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<PyAny>(arg);
run_callback(py, || {
let _pool = GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<PyAny>(arg);
match slf.try_borrow() {
Ok(borrowed_slf) => {
let res = match extract_op(op) {
Ok(op) => match arg.extract() {
Ok(arg) => borrowed_slf.__richcmp__(arg, op).into(),
Err(e) => Err(e),
},
Err(e) => Err(e),
};
match res {
Ok(val) => val.into_py(py).into_ptr(),
Err(e) => e.restore_and_null(py),
}
}
Err(e) => PyErr::from(e).restore_and_null(py),
}
let borrowed_slf = slf.try_borrow()?;
let op = extract_op(op)?;
let arg = arg.extract()?;
let result = borrowed_slf.__richcmp__(arg, op).into();
callback::convert(py, result)
})
}
Some(wrap::<T>)
}

View File

@ -4,9 +4,9 @@
//!
//! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
//! c-api
use crate::callback::UnitCallbackConverter;
use crate::err::PyResult;
use crate::{ffi, PyClass, PyRefMut};
use crate::gil::GILPool;
use crate::{callback, ffi, run_callback, PyCell, PyClass, PyRefMut, Python};
use std::os::raw::c_int;
/// Buffer protocol interface
@ -91,14 +91,13 @@ where
where
T: for<'p> PyBufferGetBufferProtocol<'p>,
{
let py = crate::Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let result = slf
.try_borrow_mut()
.map_err(crate::PyErr::from)
.and_then(|slf_mut| T::bf_getbuffer(slf_mut, arg1, arg2).into());
crate::callback::cb_convert(UnitCallbackConverter, py, result)
let py = Python::assume_gil_acquired();
run_callback(py, || {
let _pool = GILPool::new(py);
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
let result = T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).into();
callback::convert(py, result)
})
}
Some(wrap::<T>)
}
@ -127,14 +126,13 @@ where
where
T: for<'p> PyBufferReleaseBufferProtocol<'p>,
{
let py = crate::Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let result = slf
.try_borrow_mut()
.map_err(crate::PyErr::from)
.and_then(|slf_mut| T::bf_releasebuffer(slf_mut, arg1).into());
crate::callback::cb_convert(UnitCallbackConverter, py, result);
let py = Python::assume_gil_acquired();
run_callback(py, || {
let _pool = GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let result = T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).into();
crate::callback::convert(py, result)
})
}
Some(wrap::<T>)
}

View File

@ -5,7 +5,6 @@
//! [Python information](
//! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors)
use crate::callback::{PyObjectCallbackConverter, UnitCallbackConverter};
use crate::class::methods::PyMethodDef;
use crate::err::PyResult;
use crate::types::{PyAny, PyType};
@ -84,11 +83,7 @@ where
T: for<'p> PyDescrGetProtocol<'p>,
{
fn tp_descr_get() -> Option<ffi::descrgetfunc> {
py_ternary_func!(
PyDescrGetProtocol,
T::__get__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_ternary_func!(PyDescrGetProtocol, T::__get__)
}
}
@ -108,7 +103,7 @@ where
T: for<'p> PyDescrSetProtocol<'p>,
{
fn tp_descr_set() -> Option<ffi::descrsetfunc> {
py_ternary_func!(PyDescrSetProtocol, T::__set__, UnitCallbackConverter, c_int)
py_ternary_func!(PyDescrSetProtocol, T::__set__, c_int)
}
}

View File

@ -98,9 +98,14 @@ where
arg,
_py: py,
};
match slf.borrow().__traverse__(visit) {
Ok(()) => 0,
Err(PyTraverseError(code)) => code,
if let Ok(borrow) = slf.try_borrow() {
match borrow.__traverse__(visit) {
Ok(()) => 0,
Err(PyTraverseError(code)) => code,
}
} else {
0
}
}

View File

@ -2,10 +2,9 @@
//! Python Iterator Interface.
//! Trait and support implementation for implementing iterators
use crate::callback::{CallbackConverter, PyObjectCallbackConverter};
use crate::callback::IntoPyCallbackOutput;
use crate::err::PyResult;
use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, PyRefMut, Python};
use std::ptr;
/// Python Iterator Interface.
///
@ -77,11 +76,7 @@ where
{
#[inline]
fn tp_iter() -> Option<ffi::getiterfunc> {
py_unary_refmut_func!(
PyIterIterProtocol,
T::__iter__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_refmut_func!(PyIterIterProtocol, T::__iter__)
}
}
@ -104,31 +99,20 @@ where
{
#[inline]
fn tp_iternext() -> Option<ffi::iternextfunc> {
py_unary_refmut_func!(
PyIterNextProtocol,
T::__next__,
IterNextConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_refmut_func!(PyIterNextProtocol, T::__next__, IterNextConverter)
}
}
struct IterNextConverter<T>(std::marker::PhantomData<T>);
struct IterNextConverter<T>(Option<T>);
impl<T> CallbackConverter for IterNextConverter<T>
impl<T> IntoPyCallbackOutput<*mut ffi::PyObject> for IterNextConverter<T>
where
T: IntoPy<PyObject>,
{
type Source = Option<T>;
type Result = *mut ffi::PyObject;
const ERR_VALUE: Self::Result = ptr::null_mut();
fn convert(val: Self::Source, py: Python) -> Self::Result {
match val {
Some(val) => val.into_py(py).into_ptr(),
None => unsafe {
ffi::PyErr_SetNone(ffi::PyExc_StopIteration);
ptr::null_mut()
},
fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> {
match self.0 {
Some(val) => Ok(val.into_py(py).into_ptr()),
None => Err(crate::exceptions::StopIteration::py_err(())),
}
}
}

View File

@ -3,51 +3,44 @@
#[macro_export]
#[doc(hidden)]
macro_rules! py_unary_func {
($trait:ident, $class:ident :: $f:ident, $conv: expr) => {
py_unary_func!($trait, $class::$f, $conv, *mut $crate::ffi::PyObject);
};
// Use call_ref! by default
($trait:ident, $class:ident :: $f:ident, $conv: expr, $ret_type:ty) => {
py_unary_func!(
$trait,
$class::$f,
$conv,
$ret_type,
call_ref_with_converter
);
};
($trait: ident,
$class:ident :: $f:ident,
$conv: expr,
$ret_type: ty,
$call: ident
) => {{
($trait: ident, $class:ident :: $f:ident, $call:ident, $ret_type: ty $(, $conv:expr)?) => {{
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
where
T: for<'p> $trait<'p>,
{
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
$call!(slf, $conv, py, $f)
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
$crate::callback::convert(py, $call!(slf, $f)$(.map($conv))?)
})
}
Some(wrap::<$class>)
}};
// Use call_ref! by default
($trait:ident, $class:ident :: $f:ident, $ret_type:ty $(, $conv:expr)?) => {
py_unary_func!($trait, $class::$f, call_ref, $ret_type $(, $conv)?);
};
($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => {
py_unary_func!($trait, $class::$f, call_ref, *mut $crate::ffi::PyObject $(, $conv)?);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_unary_refmut_func {
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => {{
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> *mut $crate::ffi::PyObject
where
T: for<'p> $trait<'p>,
{
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let res = $class::$f(slf.borrow_mut()).into();
$crate::callback::cb_convert($conv, py, res)
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let res = $class::$f(slf.borrow_mut()).into();
$crate::callback::convert(py, res $(.map($conv))?)
})
}
Some(wrap::<$class>)
}};
@ -56,51 +49,48 @@ macro_rules! py_unary_refmut_func {
#[macro_export]
#[doc(hidden)]
macro_rules! py_len_func {
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $crate::ffi::Py_ssize_t
where
T: for<'p> $trait<'p>,
{
let py = Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let result = call_ref!(slf, $f);
$crate::callback::cb_convert($conv, py, result)
}
Some(wrap::<$class>)
}};
($trait:ident, $class:ident :: $f:ident) => {
py_unary_func!(
$trait,
$class::$f,
$crate::ffi::Py_ssize_t,
$crate::callback::LenCallbackOutput
)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_binary_func {
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {
py_binary_func!($trait, $class::$f, $conv, *mut $crate::ffi::PyObject)
};
// Use call_ref! by default
($trait:ident, $class:ident :: $f:ident, $conv:expr, $return:ty) => {{
py_binary_func!($trait, $class::$f, $conv, $return, call_ref_with_converter)
}};
($trait:ident, $class:ident :: $f:ident, $conv:expr, $return:ty, $call:ident) => {{
($trait:ident, $class:ident :: $f:ident, $return:ty, $call:ident $(, $conv:expr)?) => {{
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject, arg: *mut ffi::PyObject) -> $return
where
T: for<'p> $trait<'p>,
{
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg);
$call!(slf, $conv, py, $f, arg)
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg);
$crate::callback::convert(py, $call!(slf, $f, arg)$(.map($conv))?)
})
}
Some(wrap::<$class>)
}};
($trait:ident, $class:ident :: $f:ident, $return:ty $(, $conv:expr)?) => {
py_binary_func!($trait, $class::$f, $return, call_ref $(, $conv)?)
};
($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => {
py_binary_func!($trait, $class::$f, *mut $crate::ffi::PyObject $(, $conv)?)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_binary_num_func {
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>(
lhs: *mut ffi::PyObject,
rhs: *mut ffi::PyObject,
@ -110,18 +100,42 @@ macro_rules! py_binary_num_func {
{
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let lhs = py.from_borrowed_ptr::<$crate::PyAny>(lhs);
let rhs = py.from_borrowed_ptr::<$crate::PyAny>(rhs);
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let lhs = py.from_borrowed_ptr::<$crate::PyAny>(lhs);
let rhs = py.from_borrowed_ptr::<$crate::PyAny>(rhs);
let result = match lhs.extract() {
Ok(lhs) => match rhs.extract() {
Ok(rhs) => $class::$f(lhs, rhs).into(),
Err(e) => Err(e.into()),
},
Err(e) => Err(e.into()),
};
$crate::callback::cb_convert($conv, py, result)
let result = $class::$f(lhs.extract()?, rhs.extract()?).into();
$crate::callback::convert(py, result)
})
}
Some(wrap::<$class>)
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_binary_reverse_num_func {
($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>(
lhs: *mut ffi::PyObject,
rhs: *mut ffi::PyObject,
) -> *mut $crate::ffi::PyObject
where
T: for<'p> $trait<'p>,
{
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
// Swap lhs <-> rhs
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(rhs);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(lhs);
$crate::callback::convert(
py,
$class::$f(&*slf.try_borrow()?, arg.extract()?).into(),
)
})
}
Some(wrap::<$class>)
}};
@ -142,17 +156,14 @@ macro_rules! py_binary_self_func {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg);
let result = call_mut!(slf_, $f, arg);
match result {
Ok(_) => {
ffi::Py_INCREF(slf);
slf
}
Err(e) => e.restore_and_null(py),
}
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg);
call_mut!(slf_, $f, arg)?;
ffi::Py_INCREF(slf);
Ok(slf)
})
}
Some(wrap::<$class>)
}};
@ -162,15 +173,10 @@ macro_rules! py_binary_self_func {
#[doc(hidden)]
macro_rules! py_ssizearg_func {
// Use call_ref! by default
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {
py_ssizearg_func!(
$trait,
$class::$f,
$conv,
call_ref_with_converter
)
($trait:ident, $class:ident :: $f:ident) => {
py_ssizearg_func!($trait, $class::$f, call_ref)
};
($trait:ident, $class:ident :: $f:ident, $conv:expr, $call:ident) => {{
($trait:ident, $class:ident :: $f:ident, $call:ident) => {{
unsafe extern "C" fn wrap<T>(
slf: *mut ffi::PyObject,
arg: $crate::ffi::Py_ssize_t,
@ -179,9 +185,11 @@ macro_rules! py_ssizearg_func {
T: for<'p> $trait<'p>,
{
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
$call!(slf, $conv, py, $f ;arg.into())
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
$crate::callback::convert(py, $call!(slf, $f; arg.into()))
})
}
Some(wrap::<$class>)
}};
@ -190,10 +198,7 @@ macro_rules! py_ssizearg_func {
#[macro_export]
#[doc(hidden)]
macro_rules! py_ternary_func {
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {
py_ternary_func!($trait, $class::$f, $conv, *mut $crate::ffi::PyObject);
};
($trait:ident, $class:ident :: $f:ident, $conv:expr, $return_type:ty) => {{
($trait:ident, $class:ident :: $f:ident, $return_type:ty) => {{
unsafe extern "C" fn wrap<T>(
slf: *mut $crate::ffi::PyObject,
arg1: *mut $crate::ffi::PyObject,
@ -205,22 +210,31 @@ macro_rules! py_ternary_func {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2);
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg1 = py
.from_borrowed_ptr::<$crate::types::PyAny>(arg1)
.extract()?;
let arg2 = py
.from_borrowed_ptr::<$crate::types::PyAny>(arg2)
.extract()?;
call_ref_with_converter!(slf, $conv, py, $f, arg1, arg2)
$crate::callback::convert(py, slf.try_borrow()?.$f(arg1, arg2).into())
})
}
Some(wrap::<T>)
}};
($trait:ident, $class:ident :: $f:ident) => {
py_ternary_func!($trait, $class::$f, *mut $crate::ffi::PyObject);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_ternary_num_func {
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>(
arg1: *mut $crate::ffi::PyObject,
arg2: *mut $crate::ffi::PyObject,
@ -232,22 +246,21 @@ macro_rules! py_ternary_num_func {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2);
let arg3 = py.from_borrowed_ptr::<$crate::PyAny>(arg3);
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let arg1 = py
.from_borrowed_ptr::<$crate::types::PyAny>(arg1)
.extract()?;
let arg2 = py
.from_borrowed_ptr::<$crate::types::PyAny>(arg2)
.extract()?;
let arg3 = py
.from_borrowed_ptr::<$crate::types::PyAny>(arg3)
.extract()?;
let result = match arg1.extract() {
Ok(arg1) => match arg2.extract() {
Ok(arg2) => match arg3.extract() {
Ok(arg3) => $class::$f(arg1, arg2, arg3).into(),
Err(e) => Err(e.into()),
},
Err(e) => Err(e.into()),
},
Err(e) => Err(e.into()),
};
$crate::callback::cb_convert($conv, py, result)
let result = $class::$f(arg1, arg2, arg3).into();
$crate::callback::convert(py, result)
})
}
Some(wrap::<T>)
@ -256,12 +269,43 @@ macro_rules! py_ternary_num_func {
#[macro_export]
#[doc(hidden)]
macro_rules! py_ternary_self_func {
macro_rules! py_ternary_reverse_num_func {
($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>(
arg1: *mut $crate::ffi::PyObject,
arg2: *mut $crate::ffi::PyObject,
arg3: *mut $crate::ffi::PyObject,
) -> *mut $crate::ffi::PyObject
where
T: for<'p> $trait<'p>,
{
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
// Swap lhs <-> rhs
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(arg2);
let slf = slf.try_borrow()?;
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg3);
let result = $class::$f(&*slf, arg1.extract()?, arg2.extract()?).into();
$crate::callback::convert(py, result)
})
}
Some(wrap::<$class>)
}};
}
// NOTE(kngwyu): Somehow __ipow__ causes SIGSEGV in Python < 3.8 when we extract arg2,
// so we ignore it. It's the same as what CPython does.
#[macro_export]
#[doc(hidden)]
macro_rules! py_dummy_ternary_self_func {
($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>(
slf: *mut $crate::ffi::PyObject,
arg1: *mut $crate::ffi::PyObject,
arg2: *mut $crate::ffi::PyObject,
_arg2: *mut $crate::ffi::PyObject,
) -> *mut $crate::ffi::PyObject
where
T: for<'p> $trait<'p>,
@ -269,17 +313,16 @@ macro_rules! py_ternary_self_func {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg2);
let result = call_mut!(slf_cell, $f, arg1, arg2);
match result {
Ok(_) => slf,
Err(e) => e.restore_and_null(py),
}
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
call_mut!(slf_cell, $f, arg1)?;
ffi::Py_INCREF(slf);
Ok(slf)
})
}
Some(wrap::<T>)
Some(wrap::<$class>)
}};
}
@ -296,25 +339,23 @@ macro_rules! py_func_set {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf);
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf);
let result = if value.is_null() {
Err($crate::PyErr::new::<exceptions::NotImplementedError, _>(
format!(
"Subscript deletion not supported by {:?}",
stringify!($generic)
),
))
} else {
let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
let value = py.from_borrowed_ptr::<$crate::PyAny>(value);
call_mut!(slf, $fn_set, name, value)
};
match result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(py),
}
if value.is_null() {
Err($crate::PyErr::new::<exceptions::NotImplementedError, _>(
format!(
"Subscript deletion not supported by {:?}",
stringify!($generic)
),
))
} else {
let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
let value = py.from_borrowed_ptr::<$crate::PyAny>(value);
crate::callback::convert(py, call_mut!(slf, $fn_set, name, value))
}
})
}
Some(wrap::<$generic>)
@ -334,22 +375,21 @@ macro_rules! py_func_del {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let result = if value.is_null() {
let slf = py.from_borrowed_ptr::<$crate::PyCell<U>>(slf);
let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
call_mut!(slf, $fn_del, name)
} else {
Err(PyErr::new::<exceptions::NotImplementedError, _>(
"Subscript assignment not supported",
))
};
match result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(py),
}
if value.is_null() {
let slf = py.from_borrowed_ptr::<$crate::PyCell<U>>(slf);
let name = py
.from_borrowed_ptr::<$crate::types::PyAny>(name)
.extract()?;
$crate::callback::convert(py, slf.try_borrow_mut()?.$fn_del(name).into())
} else {
Err(PyErr::new::<exceptions::NotImplementedError, _>(
"Subscript assignment not supported",
))
}
})
}
Some(wrap::<$generic>)
@ -369,71 +409,43 @@ macro_rules! py_func_set_del {
use $crate::ObjectProtocol;
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf);
let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
$crate::run_callback(py, || {
let _pool = $crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf);
let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
let result = if value.is_null() {
call_mut!(slf, $fn_del, name)
} else {
let value = py.from_borrowed_ptr::<$crate::PyAny>(value);
call_mut!(slf, $fn_set, name, value)
};
match result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(py),
}
let result = if value.is_null() {
call_mut!(slf, $fn_del, name)
} else {
let value = py.from_borrowed_ptr::<$crate::PyAny>(value);
call_mut!(slf, $fn_set, name, value)
};
$crate::callback::convert(py, result)
})
}
Some(wrap::<$generic>)
}};
}
macro_rules! _call_impl {
($slf: ident, $fn: ident $(; $args: expr)*) => { $slf.$fn($($args,)*).into() };
($slf: ident, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => {
match $raw_arg.extract() {
Ok(arg) => _call_impl!($slf, $fn $(,$raw_args)* $(;$args)* ;arg),
Err(e) => Err(e.into()),
}
($slf: expr, $fn: ident $(; $args: expr)*) => {
$slf.$fn($($args,)*).into()
};
($slf: expr, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => {
_call_impl!($slf, $fn $(,$raw_args)* $(;$args)* ;$raw_arg.extract()?)
};
}
/// Call `slf.try_borrow()?.$fn(...)`
macro_rules! call_ref {
($slf: expr, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => {
match $slf.try_borrow() {
Ok(slf) => _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*),
Err(e) => Err(e.into()),
}
};
}
/// Call `slf.try_borrow()?.$fn(...)` and returns the result using the given CallbackConverter
macro_rules! call_ref_with_converter {
($slf: expr, $conv: expr, $py: ident, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => {
match $slf.try_borrow() {
Ok(slf) => $crate::callback::cb_convert($conv, $py, _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*)),
Err(e) => $crate::callback::cb_err($conv, $py, e)
}
_call_impl!($slf.try_borrow()?, $fn $(,$raw_args)* $(;$args)*)
};
}
/// Call `slf.try_borrow_mut()?.$fn(...)`
macro_rules! call_mut {
($slf: expr, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => {
match $slf.try_borrow_mut() {
Ok(mut slf) => _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*),
Err(e) => Err(e.into()),
}
};
}
/// Call `slf.try_borrow_mut()?.$fn(...)` and returns the result using the given CallbackConverter
macro_rules! call_mut_with_converter {
($slf: expr, $conv: expr, $py: ident, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => {
match $slf.try_borrow_mut() {
Ok(mut slf) => $crate::callback::cb_convert($conv, $py, _call_impl!(slf, $fn $(,$raw_args)* $(;$args)*)),
Err(e) => $crate::callback::cb_err($conv, $py, e)
}
_call_impl!($slf.try_borrow_mut()?, $fn $(,$raw_args)* $(;$args)*)
};
}

View File

@ -3,10 +3,9 @@
//! Python Mapping Interface
//! Trait and support implementation for implementing mapping support
use crate::callback::{LenResultConverter, PyObjectCallbackConverter};
use crate::class::methods::PyMethodDef;
use crate::err::{PyErr, PyResult};
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject, Python};
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject};
/// Mapping interface
#[allow(unused_variables)]
@ -141,7 +140,7 @@ where
{
#[inline]
fn mp_length() -> Option<ffi::lenfunc> {
py_len_func!(PyMappingLenProtocol, T::__len__, LenResultConverter)
py_len_func!(PyMappingLenProtocol, T::__len__)
}
}
@ -164,11 +163,7 @@ where
{
#[inline]
fn mp_subscript() -> Option<ffi::binaryfunc> {
py_binary_func!(
PyMappingGetItemProtocol,
T::__getitem__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_func!(PyMappingGetItemProtocol, T::__getitem__)
}
}

View File

@ -3,7 +3,6 @@
//! Python Number Interface
//! Trait and support implementation for implementing number protocol
use crate::callback::PyObjectCallbackConverter;
use crate::class::basic::PyObjectProtocolImpl;
use crate::class::methods::PyMethodDef;
use crate::err::PyResult;
@ -60,7 +59,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{
unimplemented!()
}
fn __pow__(lhs: Self::Left, rhs: Self::Right, modulo: Self::Modulo) -> Self::Result
fn __pow__(lhs: Self::Left, rhs: Self::Right, modulo: Option<Self::Modulo>) -> Self::Result
where
Self: PyNumberPowProtocol<'p>,
{
@ -145,7 +144,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{
unimplemented!()
}
fn __rpow__(&'p self, other: Self::Other) -> Self::Result
fn __rpow__(&'p self, other: Self::Other, modulo: Option<Self::Modulo>) -> Self::Result
where
Self: PyNumberRPowProtocol<'p>,
{
@ -224,7 +223,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{
unimplemented!()
}
fn __ipow__(&'p mut self, other: Self::Other, modulo: Self::Modulo) -> Self::Result
fn __ipow__(&'p mut self, other: Self::Other) -> Self::Result
where
Self: PyNumberIPowProtocol<'p>,
{
@ -304,18 +303,18 @@ pub trait PyNumberProtocol<'p>: PyClass {
{
unimplemented!()
}
fn __round__(&'p self) -> Self::Result
where
Self: PyNumberRoundProtocol<'p>,
{
unimplemented!()
}
fn __index__(&'p self) -> Self::Result
where
Self: PyNumberIndexProtocol<'p>,
{
unimplemented!()
}
fn __round__(&'p self, ndigits: Option<Self::NDigits>) -> Self::Result
where
Self: PyNumberRoundProtocol<'p>,
{
unimplemented!()
}
}
pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> {
@ -544,7 +543,6 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>;
type Modulo: FromPyObject<'p>;
type Result: Into<PyResult<()>>;
}
@ -610,6 +608,7 @@ pub trait PyNumberFloatProtocol<'p>: PyNumberProtocol<'p> {
pub trait PyNumberRoundProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>;
type NDigits: FromPyObject<'p>;
type Result: Into<PyResult<Self::Success>>;
}
@ -647,22 +646,22 @@ where
{
fn tp_as_number() -> Option<ffi::PyNumberMethods> {
Some(ffi::PyNumberMethods {
nb_add: Self::nb_add(),
nb_subtract: Self::nb_subtract(),
nb_multiply: Self::nb_multiply(),
nb_add: Self::nb_add().or_else(Self::nb_add_fallback),
nb_subtract: Self::nb_subtract().or_else(Self::nb_sub_fallback),
nb_multiply: Self::nb_multiply().or_else(Self::nb_mul_fallback),
nb_remainder: Self::nb_remainder(),
nb_divmod: Self::nb_divmod(),
nb_power: Self::nb_power(),
nb_divmod: Self::nb_divmod().or_else(Self::nb_divmod_fallback),
nb_power: Self::nb_power().or_else(Self::nb_pow_fallback),
nb_negative: Self::nb_negative(),
nb_positive: Self::nb_positive(),
nb_absolute: Self::nb_absolute(),
nb_bool: <Self as PyObjectProtocolImpl>::nb_bool_fn(),
nb_invert: Self::nb_invert(),
nb_lshift: Self::nb_lshift(),
nb_rshift: Self::nb_rshift(),
nb_and: Self::nb_and(),
nb_xor: Self::nb_xor(),
nb_or: Self::nb_or(),
nb_lshift: Self::nb_lshift().or_else(Self::nb_lshift_fallback),
nb_rshift: Self::nb_rshift().or_else(Self::nb_rshift_fallback),
nb_and: Self::nb_and().or_else(Self::nb_and_fallback),
nb_xor: Self::nb_xor().or_else(Self::nb_xor_fallback),
nb_or: Self::nb_or().or_else(Self::nb_or_fallback),
nb_int: Self::nb_int(),
nb_reserved: ::std::ptr::null_mut(),
nb_float: Self::nb_float(),
@ -676,12 +675,12 @@ where
nb_inplace_and: Self::nb_inplace_and(),
nb_inplace_xor: Self::nb_inplace_xor(),
nb_inplace_or: Self::nb_inplace_or(),
nb_floor_divide: Self::nb_floor_divide(),
nb_true_divide: Self::nb_true_divide(),
nb_floor_divide: Self::nb_floor_divide().or_else(Self::nb_floordiv_fallback),
nb_true_divide: Self::nb_true_divide().or_else(Self::nb_truediv_fallback),
nb_inplace_floor_divide: Self::nb_inplace_floor_divide(),
nb_inplace_true_divide: Self::nb_inplace_true_divide(),
nb_index: Self::nb_index(),
nb_matrix_multiply: Self::nb_matrix_multiply(),
nb_matrix_multiply: Self::nb_matrix_multiply().or_else(Self::nb_matmul_fallback),
nb_inplace_matrix_multiply: Self::nb_inplace_matrix_multiply(),
})
}
@ -761,11 +760,7 @@ where
T: for<'p> PyNumberAddProtocol<'p>,
{
fn nb_add() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberAddProtocol,
T::__add__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberAddProtocol, T::__add__)
}
}
@ -787,11 +782,7 @@ where
T: for<'p> PyNumberSubProtocol<'p>,
{
fn nb_subtract() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberSubProtocol,
T::__sub__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberSubProtocol, T::__sub__)
}
}
@ -813,11 +804,7 @@ where
T: for<'p> PyNumberMulProtocol<'p>,
{
fn nb_multiply() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberMulProtocol,
T::__mul__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberMulProtocol, T::__mul__)
}
}
@ -839,11 +826,7 @@ where
T: for<'p> PyNumberMatmulProtocol<'p>,
{
fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberMatmulProtocol,
T::__matmul__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberMatmulProtocol, T::__matmul__)
}
}
@ -865,11 +848,7 @@ where
T: for<'p> PyNumberTruedivProtocol<'p>,
{
fn nb_true_divide() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberTruedivProtocol,
T::__truediv__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberTruedivProtocol, T::__truediv__)
}
}
@ -891,11 +870,7 @@ where
T: for<'p> PyNumberFloordivProtocol<'p>,
{
fn nb_floor_divide() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberFloordivProtocol,
T::__floordiv__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberFloordivProtocol, T::__floordiv__)
}
}
@ -917,11 +892,7 @@ where
T: for<'p> PyNumberModProtocol<'p>,
{
fn nb_remainder() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberModProtocol,
T::__mod__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberModProtocol, T::__mod__)
}
}
@ -943,11 +914,7 @@ where
T: for<'p> PyNumberDivmodProtocol<'p>,
{
fn nb_divmod() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberDivmodProtocol,
T::__divmod__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberDivmodProtocol, T::__divmod__)
}
}
@ -969,11 +936,7 @@ where
T: for<'p> PyNumberPowProtocol<'p>,
{
fn nb_power() -> Option<ffi::ternaryfunc> {
py_ternary_num_func!(
PyNumberPowProtocol,
T::__pow__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_ternary_num_func!(PyNumberPowProtocol, T::__pow__)
}
}
@ -995,11 +958,7 @@ where
T: for<'p> PyNumberLShiftProtocol<'p>,
{
fn nb_lshift() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberLShiftProtocol,
T::__lshift__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberLShiftProtocol, T::__lshift__)
}
}
@ -1021,11 +980,7 @@ where
T: for<'p> PyNumberRShiftProtocol<'p>,
{
fn nb_rshift() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberRShiftProtocol,
T::__rshift__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberRShiftProtocol, T::__rshift__)
}
}
@ -1047,11 +1002,7 @@ where
T: for<'p> PyNumberAndProtocol<'p>,
{
fn nb_and() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberAndProtocol,
T::__and__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberAndProtocol, T::__and__)
}
}
@ -1073,11 +1024,7 @@ where
T: for<'p> PyNumberXorProtocol<'p>,
{
fn nb_xor() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberXorProtocol,
T::__xor__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberXorProtocol, T::__xor__)
}
}
@ -1099,11 +1046,7 @@ where
T: for<'p> PyNumberOrProtocol<'p>,
{
fn nb_or() -> Option<ffi::binaryfunc> {
py_binary_num_func!(
PyNumberOrProtocol,
T::__or__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_num_func!(PyNumberOrProtocol, T::__or__)
}
}
@ -1279,7 +1222,7 @@ where
T: for<'p> PyNumberIPowProtocol<'p>,
{
fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
py_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__)
py_dummy_ternary_self_func!(PyNumberIPowProtocol, T::__ipow__)
}
}
@ -1407,14 +1350,64 @@ where
}
}
#[doc(hidden)]
pub trait PyNumberRSubProtocolImpl {
fn __rsub__() -> Option<PyMethodDef> {
// Fallback trait for nb_add
trait PyNumberAddFallback {
fn nb_add_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberAddFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_add_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<'p, T> PyNumberRSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
impl<T> PyNumberAddFallback for T
where
T: for<'p> PyNumberRAddProtocol<'p>,
{
fn nb_add_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRAddProtocol, T::__radd__)
}
}
#[doc(hidden)]
pub trait PyNumberRSubProtocolImpl {
fn __rsub__() -> Option<PyMethodDef>;
}
impl<'p, T> PyNumberRSubProtocolImpl for T
where
T: PyNumberProtocol<'p>,
{
default fn __rsub__() -> Option<PyMethodDef> {
None
}
}
trait PyNumberSubFallback {
fn nb_sub_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberSubFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_sub_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberSubFallback for T
where
T: for<'p> PyNumberRSubProtocol<'p>,
{
fn nb_sub_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRSubProtocol, T::__rsub__)
}
}
#[doc(hidden)]
pub trait PyNumberRMulProtocolImpl {
@ -1430,6 +1423,28 @@ where
}
}
trait PyNumberMulFallback {
fn nb_mul_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberMulFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_mul_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberMulFallback for T
where
T: for<'p> PyNumberRMulProtocol<'p>,
{
fn nb_mul_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRMulProtocol, T::__rmul__)
}
}
#[doc(hidden)]
pub trait PyNumberRMatmulProtocolImpl {
fn __rmatmul__() -> Option<PyMethodDef>;
@ -1444,6 +1459,28 @@ where
}
}
trait PyNumberMatmulFallback {
fn nb_matmul_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberMatmulFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_matmul_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberMatmulFallback for T
where
T: for<'p> PyNumberRMatmulProtocol<'p>,
{
fn nb_matmul_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRMatmulProtocol, T::__rmatmul__)
}
}
#[doc(hidden)]
pub trait PyNumberRTruedivProtocolImpl {
fn __rtruediv__() -> Option<PyMethodDef>;
@ -1458,6 +1495,28 @@ where
}
}
trait PyNumberTruedivFallback {
fn nb_truediv_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberTruedivFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_truediv_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberTruedivFallback for T
where
T: for<'p> PyNumberRTruedivProtocol<'p>,
{
fn nb_truediv_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRTruedivProtocol, T::__rtruediv__)
}
}
#[doc(hidden)]
pub trait PyNumberRFloordivProtocolImpl {
fn __rfloordiv__() -> Option<PyMethodDef>;
@ -1472,6 +1531,28 @@ where
}
}
trait PyNumberFloordivFallback {
fn nb_floordiv_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberFloordivFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_floordiv_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberFloordivFallback for T
where
T: for<'p> PyNumberRFloordivProtocol<'p>,
{
fn nb_floordiv_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRFloordivProtocol, T::__rfloordiv__)
}
}
#[doc(hidden)]
pub trait PyNumberRModProtocolImpl {
fn __rmod__() -> Option<PyMethodDef>;
@ -1486,6 +1567,28 @@ where
}
}
trait PyNumberModFallback {
fn nb_mod_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberModFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_mod_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberModFallback for T
where
T: for<'p> PyNumberRModProtocol<'p>,
{
fn nb_mod_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRModProtocol, T::__rmod__)
}
}
#[doc(hidden)]
pub trait PyNumberRDivmodProtocolImpl {
fn __rdivmod__() -> Option<PyMethodDef>;
@ -1500,6 +1603,28 @@ where
}
}
trait PyNumberDivmodFallback {
fn nb_divmod_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberDivmodFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_divmod_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberDivmodFallback for T
where
T: for<'p> PyNumberRDivmodProtocol<'p>,
{
fn nb_divmod_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRDivmodProtocol, T::__rdivmod__)
}
}
#[doc(hidden)]
pub trait PyNumberRPowProtocolImpl {
fn __rpow__() -> Option<PyMethodDef>;
@ -1514,6 +1639,28 @@ where
}
}
trait PyNumberPowFallback {
fn nb_pow_fallback() -> Option<ffi::ternaryfunc>;
}
impl<'p, T> PyNumberPowFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_pow_fallback() -> Option<ffi::ternaryfunc> {
None
}
}
impl<T> PyNumberPowFallback for T
where
T: for<'p> PyNumberRPowProtocol<'p>,
{
fn nb_pow_fallback() -> Option<ffi::ternaryfunc> {
py_ternary_reverse_num_func!(PyNumberRPowProtocol, T::__rpow__)
}
}
#[doc(hidden)]
pub trait PyNumberRLShiftProtocolImpl {
fn __rlshift__() -> Option<PyMethodDef>;
@ -1528,6 +1675,28 @@ where
}
}
trait PyNumberLShiftFallback {
fn nb_lshift_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberLShiftFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_lshift_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberLShiftFallback for T
where
T: for<'p> PyNumberRLShiftProtocol<'p>,
{
fn nb_lshift_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRLShiftProtocol, T::__rlshift__)
}
}
#[doc(hidden)]
pub trait PyNumberRRShiftProtocolImpl {
fn __rrshift__() -> Option<PyMethodDef>;
@ -1542,6 +1711,28 @@ where
}
}
trait PyNumberRRshiftFallback {
fn nb_rshift_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberRRshiftFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_rshift_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberRRshiftFallback for T
where
T: for<'p> PyNumberRRShiftProtocol<'p>,
{
fn nb_rshift_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRRShiftProtocol, T::__rrshift__)
}
}
#[doc(hidden)]
pub trait PyNumberRAndProtocolImpl {
fn __rand__() -> Option<PyMethodDef>;
@ -1556,6 +1747,28 @@ where
}
}
trait PyNumberAndFallback {
fn nb_and_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberAndFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_and_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberAndFallback for T
where
T: for<'p> PyNumberRAndProtocol<'p>,
{
fn nb_and_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRAndProtocol, T::__rand__)
}
}
#[doc(hidden)]
pub trait PyNumberRXorProtocolImpl {
fn __rxor__() -> Option<PyMethodDef>;
@ -1570,6 +1783,28 @@ where
}
}
trait PyNumberXorFallback {
fn nb_xor_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberXorFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_xor_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberXorFallback for T
where
T: for<'p> PyNumberRXorProtocol<'p>,
{
fn nb_xor_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberRXorProtocol, T::__rxor__)
}
}
#[doc(hidden)]
pub trait PyNumberROrProtocolImpl {
fn __ror__() -> Option<PyMethodDef>;
@ -1584,6 +1819,28 @@ where
}
}
trait PyNumberOrFallback {
fn nb_or_fallback() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyNumberOrFallback for T
where
T: PyNumberProtocol<'p>,
{
default fn nb_or_fallback() -> Option<ffi::binaryfunc> {
None
}
}
impl<T> PyNumberOrFallback for T
where
T: for<'p> PyNumberROrProtocol<'p>,
{
fn nb_or_fallback() -> Option<ffi::binaryfunc> {
py_binary_reverse_num_func!(PyNumberROrProtocol, T::__ror__)
}
}
trait PyNumberNegProtocolImpl {
fn nb_negative() -> Option<ffi::unaryfunc>;
}
@ -1603,11 +1860,7 @@ where
{
#[inline]
fn nb_negative() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberNegProtocol,
T::__neg__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberNegProtocol, T::__neg__)
}
}
@ -1629,11 +1882,7 @@ where
T: for<'p> PyNumberPosProtocol<'p>,
{
fn nb_positive() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberPosProtocol,
T::__pos__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberPosProtocol, T::__pos__)
}
}
@ -1655,11 +1904,7 @@ where
T: for<'p> PyNumberAbsProtocol<'p>,
{
fn nb_absolute() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberAbsProtocol,
T::__abs__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberAbsProtocol, T::__abs__)
}
}
@ -1681,11 +1926,7 @@ where
T: for<'p> PyNumberInvertProtocol<'p>,
{
fn nb_invert() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberInvertProtocol,
T::__invert__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberInvertProtocol, T::__invert__)
}
}
@ -1707,11 +1948,7 @@ where
T: for<'p> PyNumberIntProtocol<'p>,
{
fn nb_int() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberIntProtocol,
T::__int__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberIntProtocol, T::__int__)
}
}
@ -1733,11 +1970,7 @@ where
T: for<'p> PyNumberFloatProtocol<'p>,
{
fn nb_float() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberFloatProtocol,
T::__float__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberFloatProtocol, T::__float__)
}
}
@ -1759,15 +1992,11 @@ where
T: for<'p> PyNumberIndexProtocol<'p>,
{
fn nb_index() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyNumberIndexProtocol,
T::__index__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyNumberIndexProtocol, T::__index__)
}
}
trait PyNumberComplexProtocolImpl {
pub trait PyNumberComplexProtocolImpl {
fn __complex__() -> Option<PyMethodDef>;
}
@ -1780,7 +2009,7 @@ where
}
}
trait PyNumberRoundProtocolImpl {
pub trait PyNumberRoundProtocolImpl {
fn __round__() -> Option<PyMethodDef>;
}

View File

@ -8,7 +8,6 @@
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)
//!
use crate::callback::PyObjectCallbackConverter;
use crate::class::methods::PyMethodDef;
use crate::err::PyResult;
use crate::{ffi, PyClass, PyObject};
@ -150,11 +149,7 @@ where
{
#[inline]
fn am_await() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyAsyncAwaitProtocol,
T::__await__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyAsyncAwaitProtocol, T::__await__)
}
}
@ -177,11 +172,7 @@ where
{
#[inline]
fn am_aiter() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyAsyncAiterProtocol,
T::__aiter__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_unary_func!(PyAsyncAiterProtocol, T::__aiter__)
}
}
@ -200,30 +191,22 @@ where
mod anext {
use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
use crate::callback::CallbackConverter;
use crate::callback::IntoPyCallbackOutput;
use crate::err::PyResult;
use crate::IntoPyPointer;
use crate::Python;
use crate::{ffi, IntoPy, PyObject};
use std::marker::PhantomData;
use std::ptr;
struct IterANextResultConverter<T>(PhantomData<T>);
struct IterANextOutput<T>(Option<T>);
impl<T> CallbackConverter for IterANextResultConverter<T>
impl<T> IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput<T>
where
T: IntoPy<PyObject>,
{
type Source = Option<T>;
type Result = *mut ffi::PyObject;
const ERR_VALUE: Self::Result = ptr::null_mut();
fn convert(val: Self::Source, py: Python) -> Self::Result {
match val {
Some(val) => val.into_py(py).into_ptr(),
None => unsafe {
ffi::PyErr_SetNone(ffi::PyExc_StopAsyncIteration);
ptr::null_mut()
},
fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> {
match self.0 {
Some(val) => Ok(val.into_py(py).into_ptr()),
None => Err(crate::exceptions::StopAsyncIteration::py_err(())),
}
}
}
@ -237,9 +220,9 @@ mod anext {
py_unary_func!(
PyAsyncAnextProtocol,
T::__anext__,
IterANextResultConverter::<T::Success>(std::marker::PhantomData),
call_mut,
*mut crate::ffi::PyObject,
call_mut_with_converter
IterANextOutput
)
}
}

View File

@ -3,10 +3,11 @@
//! Python Sequence Interface
//! Trait and support implementation for implementing sequence
use crate::callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter};
use crate::conversion::{FromPyObject, IntoPy};
use crate::err::{PyErr, PyResult};
use crate::gil::GILPool;
use crate::objectprotocol::ObjectProtocol;
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyAny, PyClass, PyObject, Python};
use crate::{callback, exceptions, ffi, run_callback, PyAny, PyCell, PyClass, PyObject, Python};
use std::os::raw::c_int;
/// Sequence interface
@ -176,7 +177,7 @@ where
T: for<'p> PySequenceLenProtocol<'p>,
{
fn sq_length() -> Option<ffi::lenfunc> {
py_len_func!(PySequenceLenProtocol, T::__len__, LenResultConverter)
py_len_func!(PySequenceLenProtocol, T::__len__)
}
}
@ -198,11 +199,7 @@ where
T: for<'p> PySequenceGetItemProtocol<'p>,
{
fn sq_item() -> Option<ffi::ssizeargfunc> {
py_ssizearg_func!(
PySequenceGetItemProtocol,
T::__getitem__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_ssizearg_func!(PySequenceGetItemProtocol, T::__getitem__)
}
}
@ -260,31 +257,23 @@ mod sq_ass_item_impl {
T: for<'p> PySequenceSetItemProtocol<'p>,
{
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
run_callback(py, || {
let _pool = GILPool::new(py);
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
if value.is_null() {
return PyErr::new::<exceptions::NotImplementedError, _>(format!(
"Item deletion is not supported by {:?}",
stringify!(T)
))
.restore_and_minus1(py);
}
let result = match slf.try_borrow_mut() {
Ok(mut slf) => {
let value = py.from_borrowed_ptr::<PyAny>(value);
match value.extract() {
Ok(value) => slf.__setitem__(key.into(), value).into(),
Err(e) => e.into(),
}
if value.is_null() {
return Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
"Item deletion is not supported by {:?}",
stringify!(T)
)));
}
Err(e) => Err(PyErr::from(e)),
};
match result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(py),
}
let mut slf = slf.try_borrow_mut()?;
let value = py.from_borrowed_ptr::<PyAny>(value);
let value = value.extract()?;
let result = slf.__setitem__(key.into(), value).into();
callback::convert(py, result)
})
}
Some(wrap::<T>)
}
@ -317,22 +306,21 @@ mod sq_ass_item_impl {
T: for<'p> PySequenceDelItemProtocol<'p>,
{
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
run_callback(py, || {
let _pool = GILPool::new(py);
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
let result = if value.is_null() {
slf.borrow_mut().__delitem__(key.into()).into()
} else {
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
"Item assignment not supported by {:?}",
stringify!(T)
)))
};
let result = if value.is_null() {
slf.borrow_mut().__delitem__(key.into()).into()
} else {
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
"Item assignment not supported by {:?}",
stringify!(T)
)))
};
match result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(py),
}
callback::convert(py, result)
})
}
Some(wrap::<T>)
}
@ -365,25 +353,20 @@ mod sq_ass_item_impl {
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
{
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
run_callback(py, || {
let _pool = GILPool::new(py);
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
let result = if value.is_null() {
call_mut!(slf, __delitem__; key.into())
} else {
let value = py.from_borrowed_ptr::<PyAny>(value);
match slf.try_borrow_mut() {
Ok(mut slf_) => match value.extract() {
Ok(value) => slf_.__setitem__(key.into(), value).into(),
Err(e) => Err(e),
},
Err(e) => Err(e.into()),
}
};
match result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(py),
}
let result = if value.is_null() {
call_mut!(slf, __delitem__; key.into())
} else {
let value = py.from_borrowed_ptr::<PyAny>(value);
let mut slf_ = slf.try_borrow_mut()?;
let value = value.extract()?;
slf_.__setitem__(key.into(), value).into()
};
callback::convert(py, result)
})
}
Some(wrap::<T>)
}
@ -408,12 +391,7 @@ where
T: for<'p> PySequenceContainsProtocol<'p>,
{
fn sq_contains() -> Option<ffi::objobjproc> {
py_binary_func!(
PySequenceContainsProtocol,
T::__contains__,
BoolCallbackConverter,
c_int
)
py_binary_func!(PySequenceContainsProtocol, T::__contains__, c_int)
}
}
@ -435,11 +413,7 @@ where
T: for<'p> PySequenceConcatProtocol<'p>,
{
fn sq_concat() -> Option<ffi::binaryfunc> {
py_binary_func!(
PySequenceConcatProtocol,
T::__concat__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_binary_func!(PySequenceConcatProtocol, T::__concat__)
}
}
@ -461,11 +435,7 @@ where
T: for<'p> PySequenceRepeatProtocol<'p>,
{
fn sq_repeat() -> Option<ffi::ssizeargfunc> {
py_ssizearg_func!(
PySequenceRepeatProtocol,
T::__repeat__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
py_ssizearg_func!(PySequenceRepeatProtocol, T::__repeat__)
}
}
@ -490,9 +460,8 @@ where
py_binary_func!(
PySequenceInplaceConcatProtocol,
T::__inplace_concat__,
PyObjectCallbackConverter::<T>(std::marker::PhantomData),
*mut crate::ffi::PyObject,
call_mut_with_converter
*mut ffi::PyObject,
call_mut
)
}
}
@ -518,8 +487,7 @@ where
py_ssizearg_func!(
PySequenceInplaceRepeatProtocol,
T::__inplace_repeat__,
PyObjectCallbackConverter::<T>(std::marker::PhantomData),
call_mut_with_converter
call_mut
)
}
}

View File

@ -1,15 +1,12 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use crate::instance::Py;
use crate::object::PyObject;
use crate::type_object::PyTypeObject;
use crate::types::{PyAny, PyType};
use crate::AsPyPointer;
use crate::IntoPyPointer;
use crate::Python;
use crate::{exceptions, IntoPy};
use crate::{ffi, FromPy};
use crate::{ToBorrowedObject, ToPyObject};
use crate::types::PyType;
use crate::{exceptions, ffi};
use crate::{
AsPyPointer, FromPy, IntoPy, IntoPyPointer, Py, PyAny, PyObject, Python, ToBorrowedObject,
ToPyObject,
};
use libc::c_int;
use std::ffi::CString;
use std::io;

View File

@ -37,9 +37,9 @@ extern "C" {
pub fn PyBytes_AsString(arg1: *mut PyObject) -> *mut c_char;
pub fn PyBytes_Repr(arg1: *mut PyObject, arg2: c_int) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyBytes_Concat")]
pub fn PyBytes_Concat(arg1: *mut *mut PyObject, arg2: *mut PyObject) -> ();
pub fn PyBytes_Concat(arg1: *mut *mut PyObject, arg2: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyBytes_ConcatAndDel")]
pub fn PyBytes_ConcatAndDel(arg1: *mut *mut PyObject, arg2: *mut PyObject) -> ();
pub fn PyBytes_ConcatAndDel(arg1: *mut *mut PyObject, arg2: *mut PyObject);
pub fn PyBytes_DecodeEscape(
arg1: *const c_char,
arg2: Py_ssize_t,

View File

@ -45,7 +45,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPy_MakePendingCalls")]
pub fn Py_MakePendingCalls() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPy_SetRecursionLimit")]
pub fn Py_SetRecursionLimit(arg1: c_int) -> ();
pub fn Py_SetRecursionLimit(arg1: c_int);
#[cfg_attr(PyPy, link_name = "PyPy_GetRecursionLimit")]
pub fn Py_GetRecursionLimit() -> c_int;
fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int;
@ -74,7 +74,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")]
pub fn PyEval_SaveThread() -> *mut PyThreadState;
#[cfg_attr(PyPy, link_name = "PyPyEval_RestoreThread")]
pub fn PyEval_RestoreThread(arg1: *mut PyThreadState) -> ();
pub fn PyEval_RestoreThread(arg1: *mut PyThreadState);
}
#[cfg(py_sys_config = "WITH_THREAD")]
@ -83,13 +83,13 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyEval_ThreadsInitialized")]
pub fn PyEval_ThreadsInitialized() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyEval_InitThreads")]
pub fn PyEval_InitThreads() -> ();
pub fn PyEval_AcquireLock() -> ();
pub fn PyEval_ReleaseLock() -> ();
pub fn PyEval_InitThreads();
pub fn PyEval_AcquireLock();
pub fn PyEval_ReleaseLock();
#[cfg_attr(PyPy, link_name = "PyPyEval_AcquireThread")]
pub fn PyEval_AcquireThread(tstate: *mut PyThreadState) -> ();
pub fn PyEval_AcquireThread(tstate: *mut PyThreadState);
#[cfg_attr(PyPy, link_name = "PyPyEval_ReleaseThread")]
pub fn PyEval_ReleaseThread(tstate: *mut PyThreadState) -> ();
pub fn PyEval_ReleaseThread(tstate: *mut PyThreadState);
#[cfg(not(Py_3_8))]
pub fn PyEval_ReInitThreads() -> ();
pub fn PyEval_ReInitThreads();
}

View File

@ -69,6 +69,8 @@ pub unsafe fn PyDictViewSet_Check(op: *mut PyObject) -> c_int {
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyDict_New")]
pub fn PyDict_New() -> *mut PyObject;
#[cfg(not(PyPy))]
pub fn _PyDict_NewPresized(minused: Py_ssize_t) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyDict_GetItem")]
pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;
pub fn PyDict_GetItemWithError(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;
@ -84,7 +86,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyDict_DelItem")]
pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyDict_Clear")]
pub fn PyDict_Clear(mp: *mut PyObject) -> ();
pub fn PyDict_Clear(mp: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyDict_Next")]
pub fn PyDict_Next(
mp: *mut PyObject,

View File

@ -65,17 +65,12 @@ extern "C" {
locals: *mut PyObject,
) -> *mut PyFrameObject;
pub fn PyFrame_BlockSetup(
f: *mut PyFrameObject,
_type: c_int,
handler: c_int,
level: c_int,
) -> ();
pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int);
pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock;
pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int) -> ();
pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int);
pub fn PyFrame_FastToLocalsWithError(f: *mut PyFrameObject) -> c_int;
pub fn PyFrame_FastToLocals(f: *mut PyFrameObject) -> ();
pub fn PyFrame_FastToLocals(f: *mut PyFrameObject);
pub fn PyFrame_ClearFreeList() -> c_int;
pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int;

View File

@ -68,7 +68,7 @@ extern "C" {
pub fn PyImport_Import(name: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyImport_ReloadModule")]
pub fn PyImport_ReloadModule(m: *mut PyObject) -> *mut PyObject;
pub fn PyImport_Cleanup() -> ();
pub fn PyImport_Cleanup();
pub fn PyImport_ImportFrozenModuleObject(name: *mut PyObject) -> c_int;
pub fn PyImport_ImportFrozenModule(name: *const c_char) -> c_int;

View File

@ -4,7 +4,7 @@ use std::os::raw::c_int;
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyOS_InterruptOccurred")]
pub fn PyOS_InterruptOccurred() -> c_int;
pub fn PyOS_InitInterrupts() -> ();
pub fn PyOS_InitInterrupts();
#[cfg_attr(PyPy, link_name = "PyPyOS_AfterFork")]
pub fn PyOS_AfterFork() -> ();
pub fn PyOS_AfterFork();
}

View File

@ -165,7 +165,7 @@ mod bufferinfo {
arg3: c_int,
) -> c_int;
pub type releasebufferproc =
unsafe extern "C" fn(arg1: *mut crate::ffi::PyObject, arg2: *mut Py_buffer) -> ();
unsafe extern "C" fn(arg1: *mut crate::ffi::PyObject, arg2: *mut Py_buffer);
/// Maximum number of dimensions
pub const PyBUF_MAX_NDIM: c_int = 64;
@ -829,9 +829,9 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCallable_Check")]
pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyObject_ClearWeakRefs")]
pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject) -> ();
pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject);
#[cfg(not(Py_LIMITED_API))]
pub fn PyObject_CallFinalizer(arg1: *mut PyObject) -> ();
pub fn PyObject_CallFinalizer(arg1: *mut PyObject);
#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(PyPy, link_name = "PyPyObject_CallFinalizerFromDealloc")]
pub fn PyObject_CallFinalizerFromDealloc(arg1: *mut PyObject) -> c_int;
@ -839,7 +839,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyObject_Dir")]
pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject;
pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int;
pub fn Py_ReprLeave(arg1: *mut PyObject) -> ();
pub fn Py_ReprLeave(arg1: *mut PyObject);
}
// Flag bits for printing:
@ -908,7 +908,7 @@ pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int {
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
#[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
pub fn _Py_Dealloc(arg1: *mut PyObject) -> ();
pub fn _Py_Dealloc(arg1: *mut PyObject);
}
// Reference counting macros.

View File

@ -132,7 +132,7 @@ extern "C" {
strides: *mut Py_ssize_t,
itemsize: c_int,
fort: c_char,
) -> ();
);
#[cfg_attr(PyPy, link_name = "PyPyBuffer_FillInfo")]
pub fn PyBuffer_FillInfo(
view: *mut Py_buffer,
@ -143,7 +143,7 @@ extern "C" {
flags: c_int,
) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyBuffer_Release")]
pub fn PyBuffer_Release(view: *mut Py_buffer) -> ();
pub fn PyBuffer_Release(view: *mut Py_buffer);
}
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -11,7 +11,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyObject_Realloc")]
pub fn PyObject_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;
#[cfg_attr(PyPy, link_name = "PyPyObject_Free")]
pub fn PyObject_Free(ptr: *mut c_void) -> ();
pub fn PyObject_Free(ptr: *mut c_void);
#[cfg(not(Py_LIMITED_API))]
pub fn _Py_GetAllocatedBlocks() -> Py_ssize_t;
@ -37,7 +37,7 @@ extern "C" {
pub struct PyObjectArenaAllocator {
pub ctx: *mut c_void,
pub alloc: Option<extern "C" fn(ctx: *mut c_void, size: size_t) -> *mut c_void>,
pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void, size: size_t) -> ()>,
pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void, size: size_t)>,
}
#[cfg(not(Py_LIMITED_API))]
@ -50,8 +50,8 @@ impl Default for PyObjectArenaAllocator {
#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator) -> ();
pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator) -> ();
pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
}
/// Test if a type has a GC head
@ -84,10 +84,10 @@ extern "C" {
pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "_PyPyObject_GC_NewVar")]
pub fn _PyObject_GC_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject;
pub fn PyObject_GC_Track(arg1: *mut c_void) -> ();
pub fn PyObject_GC_UnTrack(arg1: *mut c_void) -> ();
pub fn PyObject_GC_Track(arg1: *mut c_void);
pub fn PyObject_GC_UnTrack(arg1: *mut c_void);
#[cfg_attr(PyPy, link_name = "PyPyObject_GC_Del")]
pub fn PyObject_GC_Del(arg1: *mut c_void) -> ();
pub fn PyObject_GC_Del(arg1: *mut c_void);
}
/// Test if a type supports weak references

View File

@ -9,31 +9,31 @@ use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyErr_SetNone")]
pub fn PyErr_SetNone(arg1: *mut PyObject) -> ();
pub fn PyErr_SetNone(arg1: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyErr_SetObject")]
pub fn PyErr_SetObject(arg1: *mut PyObject, arg2: *mut PyObject) -> ();
pub fn PyErr_SetObject(arg1: *mut PyObject, arg2: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyErr_SetString")]
pub fn PyErr_SetString(exception: *mut PyObject, string: *const c_char) -> ();
pub fn PyErr_SetString(exception: *mut PyObject, string: *const c_char);
#[cfg_attr(PyPy, link_name = "PyPyErr_Occurred")]
pub fn PyErr_Occurred() -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyErr_Clear")]
pub fn PyErr_Clear() -> ();
pub fn PyErr_Clear();
#[cfg_attr(PyPy, link_name = "PyPyErr_Fetch")]
pub fn PyErr_Fetch(
arg1: *mut *mut PyObject,
arg2: *mut *mut PyObject,
arg3: *mut *mut PyObject,
) -> ();
);
#[cfg_attr(PyPy, link_name = "PyPyErr_Restore")]
pub fn PyErr_Restore(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> ();
pub fn PyErr_Restore(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyErr_GetExcInfo")]
pub fn PyErr_GetExcInfo(
arg1: *mut *mut PyObject,
arg2: *mut *mut PyObject,
arg3: *mut *mut PyObject,
) -> ();
);
#[cfg_attr(PyPy, link_name = "PyPyErr_SetExcInfo")]
pub fn PyErr_SetExcInfo(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> ();
pub fn PyErr_SetExcInfo(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPy_FatalError")]
pub fn Py_FatalError(message: *const c_char) -> !;
#[cfg_attr(PyPy, link_name = "PyPyErr_GivenExceptionMatches")]
@ -45,7 +45,7 @@ extern "C" {
arg1: *mut *mut PyObject,
arg2: *mut *mut PyObject,
arg3: *mut *mut PyObject,
) -> ();
);
#[cfg_attr(PyPy, link_name = "PyPyException_SetTraceback")]
pub fn PyException_SetTraceback(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyException_GetTraceback")]
@ -53,11 +53,11 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyException_GetCause")]
pub fn PyException_GetCause(arg1: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyException_SetCause")]
pub fn PyException_SetCause(arg1: *mut PyObject, arg2: *mut PyObject) -> ();
pub fn PyException_SetCause(arg1: *mut PyObject, arg2: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyException_GetContext")]
pub fn PyException_GetContext(arg1: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyException_SetContext")]
pub fn PyException_SetContext(arg1: *mut PyObject, arg2: *mut PyObject) -> ();
pub fn PyException_SetContext(arg1: *mut PyObject, arg2: *mut PyObject);
}
#[inline]
@ -277,8 +277,8 @@ extern "C" {
arg3: *mut PyObject,
) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyErr_BadInternalCall")]
pub fn PyErr_BadInternalCall() -> ();
pub fn _PyErr_BadInternalCall(filename: *const c_char, lineno: c_int) -> ();
pub fn PyErr_BadInternalCall();
pub fn _PyErr_BadInternalCall(filename: *const c_char, lineno: c_int);
#[cfg_attr(PyPy, link_name = "PyPyErr_NewException")]
pub fn PyErr_NewException(
name: *const c_char,
@ -293,13 +293,13 @@ extern "C" {
dict: *mut PyObject,
) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyErr_WriteUnraisable")]
pub fn PyErr_WriteUnraisable(arg1: *mut PyObject) -> ();
pub fn PyErr_WriteUnraisable(arg1: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyErr_CheckSignals")]
pub fn PyErr_CheckSignals() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyErr_SetInterrupt")]
pub fn PyErr_SetInterrupt() -> ();
pub fn PyErr_SyntaxLocation(filename: *const c_char, lineno: c_int) -> ();
pub fn PyErr_SyntaxLocationEx(filename: *const c_char, lineno: c_int, col_offset: c_int) -> ();
pub fn PyErr_SetInterrupt();
pub fn PyErr_SyntaxLocation(filename: *const c_char, lineno: c_int);
pub fn PyErr_SyntaxLocationEx(filename: *const c_char, lineno: c_int, col_offset: c_int);
pub fn PyErr_ProgramText(filename: *const c_char, lineno: c_int) -> *mut PyObject;
#[cfg(not(PyPy))]
pub fn PyUnicodeDecodeError_Create(

View File

@ -11,7 +11,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyMem_RawRealloc")]
pub fn PyMem_RawRealloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;
#[cfg_attr(PyPy, link_name = "PyPyMem_RawFree")]
pub fn PyMem_RawFree(ptr: *mut c_void) -> ();
pub fn PyMem_RawFree(ptr: *mut c_void);
}
#[cfg_attr(windows, link(name = "pythonXY"))]
@ -23,7 +23,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyMem_Realloc")]
pub fn PyMem_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;
#[cfg_attr(PyPy, link_name = "PyPyMem_Free")]
pub fn PyMem_Free(ptr: *mut c_void) -> ();
pub fn PyMem_Free(ptr: *mut c_void);
}
#[cfg(not(Py_LIMITED_API))]
@ -45,15 +45,13 @@ pub struct PyMemAllocatorEx {
Option<extern "C" fn(ctx: *mut c_void, nelem: size_t, elsize: size_t) -> *mut c_void>,
pub realloc:
Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void, new_size: size_t) -> *mut c_void>,
pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void) -> ()>,
pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void)>,
}
#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
pub fn PyMem_GetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx)
-> ();
pub fn PyMem_SetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx)
-> ();
pub fn PyMem_SetupDebugHooks() -> ();
pub fn PyMem_GetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx);
pub fn PyMem_SetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx);
pub fn PyMem_SetupDebugHooks();
}

View File

@ -25,8 +25,8 @@ pub struct PyThreadState {
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
pub fn PyInterpreterState_New() -> *mut PyInterpreterState;
pub fn PyInterpreterState_Clear(arg1: *mut PyInterpreterState) -> ();
pub fn PyInterpreterState_Delete(arg1: *mut PyInterpreterState) -> ();
pub fn PyInterpreterState_Clear(arg1: *mut PyInterpreterState);
pub fn PyInterpreterState_Delete(arg1: *mut PyInterpreterState);
//fn _PyState_AddModule(arg1: *mut PyObject,
// arg2: *mut PyModuleDef) -> c_int;
pub fn PyState_FindModule(arg1: *mut PyModuleDef) -> *mut PyObject;
@ -34,14 +34,14 @@ extern "C" {
pub fn PyThreadState_New(arg1: *mut PyInterpreterState) -> *mut PyThreadState;
//fn _PyThreadState_Prealloc(arg1: *mut PyInterpreterState)
// -> *mut PyThreadState;
//fn _PyThreadState_Init(arg1: *mut PyThreadState) -> ();
//fn _PyThreadState_Init(arg1: *mut PyThreadState);
#[cfg_attr(PyPy, link_name = "PyPyThreadState_Clear")]
pub fn PyThreadState_Clear(arg1: *mut PyThreadState) -> ();
pub fn PyThreadState_Clear(arg1: *mut PyThreadState);
#[cfg_attr(PyPy, link_name = "PyPyThreadState_Delete")]
pub fn PyThreadState_Delete(arg1: *mut PyThreadState) -> ();
pub fn PyThreadState_Delete(arg1: *mut PyThreadState);
#[cfg(py_sys_config = "WITH_THREAD")]
#[cfg_attr(PyPy, link_name = "PyPyThreadState_DeleteCurrent")]
pub fn PyThreadState_DeleteCurrent() -> ();
pub fn PyThreadState_DeleteCurrent();
#[cfg_attr(PyPy, link_name = "PyPyThreadState_Get")]
pub fn PyThreadState_Get() -> *mut PyThreadState;
#[cfg_attr(PyPy, link_name = "PyPyThreadState_Swap")]
@ -63,7 +63,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")]
pub fn PyGILState_Ensure() -> PyGILState_STATE;
#[cfg_attr(PyPy, link_name = "PyPyGILState_Release")]
pub fn PyGILState_Release(arg1: PyGILState_STATE) -> ();
pub fn PyGILState_Release(arg1: PyGILState_STATE);
pub fn PyGILState_GetThisThreadState() -> *mut PyThreadState;
}

View File

@ -11,18 +11,18 @@ use std::ptr;
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
// TODO: these moved to pylifecycle.h
pub fn Py_SetProgramName(arg1: *mut wchar_t) -> ();
pub fn Py_SetProgramName(arg1: *mut wchar_t);
#[cfg_attr(PyPy, link_name = "PyPy_GetProgramName")]
pub fn Py_GetProgramName() -> *mut wchar_t;
pub fn Py_SetPythonHome(arg1: *mut wchar_t) -> ();
pub fn Py_SetPythonHome(arg1: *mut wchar_t);
pub fn Py_GetPythonHome() -> *mut wchar_t;
pub fn Py_Initialize() -> ();
pub fn Py_InitializeEx(arg1: c_int) -> ();
pub fn Py_Finalize() -> ();
pub fn Py_Initialize();
pub fn Py_InitializeEx(arg1: c_int);
pub fn Py_Finalize();
#[cfg_attr(PyPy, link_name = "PyPy_IsInitialized")]
pub fn Py_IsInitialized() -> c_int;
pub fn Py_NewInterpreter() -> *mut PyThreadState;
pub fn Py_EndInterpreter(arg1: *mut PyThreadState) -> ();
pub fn Py_EndInterpreter(arg1: *mut PyThreadState);
}
#[repr(C)]
@ -220,22 +220,22 @@ extern "C" {
) -> *mut symtable;
#[cfg_attr(PyPy, link_name = "PyPyErr_Print")]
pub fn PyErr_Print() -> ();
pub fn PyErr_Print();
#[cfg_attr(PyPy, link_name = "PyPyErr_PrintEx")]
pub fn PyErr_PrintEx(arg1: c_int) -> ();
pub fn PyErr_PrintEx(arg1: c_int);
#[cfg_attr(PyPy, link_name = "PyPyErr_Display")]
pub fn PyErr_Display(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> ();
pub fn PyErr_Display(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject);
// TODO: these moved to pylifecycle.h
#[cfg_attr(PyPy, link_name = "PyPy_AtExit")]
pub fn Py_AtExit(func: Option<extern "C" fn() -> ()>) -> c_int;
pub fn Py_Exit(arg1: c_int) -> ();
pub fn Py_AtExit(func: Option<extern "C" fn()>) -> c_int;
pub fn Py_Exit(arg1: c_int);
pub fn Py_Main(argc: c_int, argv: *mut *mut wchar_t) -> c_int;
pub fn Py_GetProgramFullPath() -> *mut wchar_t;
pub fn Py_GetPrefix() -> *mut wchar_t;
pub fn Py_GetExecPrefix() -> *mut wchar_t;
pub fn Py_GetPath() -> *mut wchar_t;
pub fn Py_SetPath(arg1: *const wchar_t) -> ();
pub fn Py_SetPath(arg1: *const wchar_t);
#[cfg_attr(PyPy, link_name = "PyPy_GetVersion")]
pub fn Py_GetVersion() -> *const c_char;
pub fn Py_GetPlatform() -> *const c_char;

View File

@ -22,10 +22,6 @@ pub struct PyStructSequence_Desc {
extern "C" {
pub fn PyStructSequence_NewType(desc: *mut PyStructSequence_Desc) -> *mut PyTypeObject;
pub fn PyStructSequence_New(_type: *mut PyTypeObject) -> *mut PyObject;
pub fn PyStructSequence_SetItem(
arg1: *mut PyObject,
arg2: Py_ssize_t,
arg3: *mut PyObject,
) -> ();
pub fn PyStructSequence_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject);
pub fn PyStructSequence_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;
}

View File

@ -10,19 +10,19 @@ extern "C" {
pub fn PySys_GetObject(arg1: *const c_char) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPySys_SetObject")]
pub fn PySys_SetObject(arg1: *const c_char, arg2: *mut PyObject) -> c_int;
pub fn PySys_SetArgv(arg1: c_int, arg2: *mut *mut wchar_t) -> ();
pub fn PySys_SetArgvEx(arg1: c_int, arg2: *mut *mut wchar_t, arg3: c_int) -> ();
pub fn PySys_SetPath(arg1: *const wchar_t) -> ();
pub fn PySys_SetArgv(arg1: c_int, arg2: *mut *mut wchar_t);
pub fn PySys_SetArgvEx(arg1: c_int, arg2: *mut *mut wchar_t, arg3: c_int);
pub fn PySys_SetPath(arg1: *const wchar_t);
#[cfg_attr(PyPy, link_name = "PyPySys_WriteStdout")]
pub fn PySys_WriteStdout(format: *const c_char, ...) -> ();
pub fn PySys_WriteStdout(format: *const c_char, ...);
#[cfg_attr(PyPy, link_name = "PyPySys_WriteStderr")]
pub fn PySys_WriteStderr(format: *const c_char, ...) -> ();
pub fn PySys_FormatStdout(format: *const c_char, ...) -> ();
pub fn PySys_FormatStderr(format: *const c_char, ...) -> ();
pub fn PySys_ResetWarnOptions() -> ();
pub fn PySys_AddWarnOption(arg1: *const wchar_t) -> ();
pub fn PySys_AddWarnOptionUnicode(arg1: *mut PyObject) -> ();
pub fn PySys_WriteStderr(format: *const c_char, ...);
pub fn PySys_FormatStdout(format: *const c_char, ...);
pub fn PySys_FormatStderr(format: *const c_char, ...);
pub fn PySys_ResetWarnOptions();
pub fn PySys_AddWarnOption(arg1: *const wchar_t);
pub fn PySys_AddWarnOptionUnicode(arg1: *mut PyObject);
pub fn PySys_HasWarnOptions() -> c_int;
pub fn PySys_AddXOption(arg1: *const wchar_t) -> ();
pub fn PySys_AddXOption(arg1: *const wchar_t);
pub fn PySys_GetXOptions() -> *mut PyObject;
}

View File

@ -116,8 +116,8 @@ extern "C" {
// vargs: va_list) -> *mut PyObject;
pub fn PyUnicode_FromFormat(format: *const c_char, ...) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyUnicode_InternInPlace")]
pub fn PyUnicode_InternInPlace(arg1: *mut *mut PyObject) -> ();
pub fn PyUnicode_InternImmortal(arg1: *mut *mut PyObject) -> ();
pub fn PyUnicode_InternInPlace(arg1: *mut *mut PyObject);
pub fn PyUnicode_InternImmortal(arg1: *mut *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyUnicode_InternFromString")]
pub fn PyUnicode_InternFromString(u: *const c_char) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyUnicode_FromWideChar")]
@ -389,8 +389,8 @@ extern "C" {
pub fn PyUnicode_EncodeFSDefault(unicode: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyUnicode_Concat")]
pub fn PyUnicode_Concat(left: *mut PyObject, right: *mut PyObject) -> *mut PyObject;
pub fn PyUnicode_Append(pleft: *mut *mut PyObject, right: *mut PyObject) -> ();
pub fn PyUnicode_AppendAndDel(pleft: *mut *mut PyObject, right: *mut PyObject) -> ();
pub fn PyUnicode_Append(pleft: *mut *mut PyObject, right: *mut PyObject);
pub fn PyUnicode_AppendAndDel(pleft: *mut *mut PyObject, right: *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyUnicode_Split")]
pub fn PyUnicode_Split(
s: *mut PyObject,

View File

@ -108,7 +108,6 @@ impl Drop for GILGuard {
unsafe {
let pool: &'static mut ReleasePool = &mut *POOL;
pool.drain(self.python(), self.owned, self.borrowed);
ffi::PyGILState_Release(self.gstate);
}
}

View File

@ -12,7 +12,7 @@ macro_rules! private_decl {
/// This trait is private to implement; this method exists to make it
/// impossible to implement outside the crate.
fn __private__(&self) -> crate::internal_tricks::PrivateMarker;
}
};
}
macro_rules! private_impl {
@ -21,7 +21,7 @@ macro_rules! private_impl {
fn __private__(&self) -> crate::internal_tricks::PrivateMarker {
crate::internal_tricks::PrivateMarker
}
}
};
}
macro_rules! pyo3_exception {

View File

@ -133,6 +133,7 @@
//! }
//! ```
pub use crate::callback::run_callback;
pub use crate::class::*;
pub use crate::conversion::{
AsPyPointer, FromPy, FromPyObject, FromPyPointer, IntoPy, IntoPyPointer, PyTryFrom, PyTryInto,

View File

@ -9,8 +9,7 @@ use crate::instance::AsPyRef;
use crate::object::PyObject;
use crate::type_object::{PyDowncastImpl, PyTypeInfo, PyTypeObject};
use crate::types::{PyAny, PyDict, PyModule, PyType};
use crate::AsPyPointer;
use crate::{FromPyPointer, IntoPyPointer, PyTryFrom};
use crate::{AsPyPointer, FromPyPointer, IntoPyPointer, PyTryFrom};
use std::ffi::CString;
use std::marker::PhantomData;
use std::os::raw::c_int;

View File

@ -4,8 +4,8 @@
use crate::err::{self, PyErr, PyResult};
use crate::internal_tricks::Unsendable;
use crate::{
ffi, AsPyPointer, FromPyObject, PyAny, PyNativeType, PyObject, PyTryFrom, Python,
ToBorrowedObject, ToPyObject,
ffi, AsPyPointer, FromPyObject, PyAny, PyNativeType, PyObject, Python, ToBorrowedObject,
ToPyObject,
};
use std::cmp;
use std::collections::{BTreeSet, HashSet};
@ -189,13 +189,9 @@ where
K: FromPyObject<'source> + cmp::Eq + hash::Hash,
S: hash::BuildHasher + Default,
{
fn extract(ob: &'source PyAny) -> Result<Self, PyErr> {
let set = <PySet as PyTryFrom>::try_from(ob)?;
let mut ret = HashSet::default();
for k in set.iter() {
ret.insert(K::extract(k)?);
}
Ok(ret)
fn extract(ob: &'source PyAny) -> PyResult<Self> {
let set: &PySet = ob.downcast()?;
set.iter().map(K::extract).collect()
}
}
@ -203,13 +199,9 @@ impl<'source, K> FromPyObject<'source> for BTreeSet<K>
where
K: FromPyObject<'source> + cmp::Ord,
{
fn extract(ob: &'source PyAny) -> Result<Self, PyErr> {
let set = <PySet as PyTryFrom>::try_from(ob)?;
let mut ret = BTreeSet::default();
for k in set.iter() {
ret.insert(K::extract(k)?);
}
Ok(ret)
fn extract(ob: &'source PyAny) -> PyResult<Self> {
let set: &PySet = ob.downcast()?;
set.iter().map(K::extract).collect()
}
}
@ -279,9 +271,9 @@ impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
#[cfg(test)]
mod test {
use super::{PyFrozenSet, PySet};
use crate::instance::AsPyRef;
use crate::{ObjectProtocol, PyTryFrom, Python, ToPyObject};
use std::collections::HashSet;
use crate::{AsPyRef, ObjectProtocol, PyTryFrom, Python, ToPyObject};
use std::collections::{BTreeSet, HashSet};
use std::iter::FromIterator;
#[test]
fn test_set_new() {
@ -433,4 +425,30 @@ mod test {
assert_eq!(1i32, el.extract::<i32>().unwrap());
}
}
#[test]
fn test_extract_hashset() {
let gil = Python::acquire_gil();
let py = gil.python();
let set = PySet::new(py, &[1, 2, 3, 4, 5]).unwrap();
let hash_set: HashSet<usize> = set.extract().unwrap();
assert_eq!(
hash_set,
HashSet::from_iter([1, 2, 3, 4, 5].iter().copied())
);
}
#[test]
fn test_extract_btreeset() {
let gil = Python::acquire_gil();
let py = gil.python();
let set = PySet::new(py, &[1, 2, 3, 4, 5]).unwrap();
let hash_set: BTreeSet<usize> = set.extract().unwrap();
assert_eq!(
hash_set,
BTreeSet::from_iter([1, 2, 3, 4, 5].iter().copied())
);
}
}

View File

@ -8,24 +8,39 @@ use pyo3::py_run;
mod common;
#[pyclass]
struct UnaryArithmetic {}
struct UnaryArithmetic {
inner: f64,
}
impl UnaryArithmetic {
fn new(value: f64) -> Self {
UnaryArithmetic { inner: value }
}
}
#[pyproto]
impl PyObjectProtocol for UnaryArithmetic {
fn __repr__(&self) -> PyResult<String> {
Ok(format!("UA({})", self.inner))
}
}
#[pyproto]
impl PyNumberProtocol for UnaryArithmetic {
fn __neg__(&self) -> PyResult<&'static str> {
Ok("neg")
fn __neg__(&self) -> PyResult<Self> {
Ok(Self::new(-self.inner))
}
fn __pos__(&self) -> PyResult<&'static str> {
Ok("pos")
fn __pos__(&self) -> PyResult<Self> {
Ok(Self::new(self.inner))
}
fn __abs__(&self) -> PyResult<&'static str> {
Ok("abs")
fn __abs__(&self) -> PyResult<Self> {
Ok(Self::new(self.inner.abs()))
}
fn __invert__(&self) -> PyResult<&'static str> {
Ok("invert")
fn __round__(&self, _ndigits: Option<u32>) -> PyResult<Self> {
Ok(Self::new(self.inner.round()))
}
}
@ -34,11 +49,12 @@ fn unary_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
let c = Py::new(py, UnaryArithmetic {}).unwrap();
py_run!(py, c, "assert -c == 'neg'");
py_run!(py, c, "assert +c == 'pos'");
py_run!(py, c, "assert abs(c) == 'abs'");
py_run!(py, c, "assert ~c == 'invert'");
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
}
#[pyclass]
@ -104,15 +120,19 @@ impl PyNumberProtocol for InPlaceOperations {
self.value |= other;
Ok(())
}
fn __ipow__(&mut self, other: u32) -> PyResult<()> {
self.value = self.value.pow(other);
Ok(())
}
}
#[test]
fn inplace_operations() {
let gil = Python::acquire_gil();
let py = gil.python();
let init = |value, code| {
let c = Py::new(py, InPlaceOperations { value }).unwrap();
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
py_run!(py, c, code);
};
@ -124,6 +144,11 @@ fn inplace_operations() {
init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'");
init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'");
init(
3,
"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
);
}
#[pyproto]
@ -159,6 +184,10 @@ impl PyNumberProtocol for BinaryArithmetic {
fn __or__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
Ok(format!("{:?} | {:?}", lhs, rhs))
}
fn __pow__(lhs: &PyAny, rhs: &PyAny, mod_: Option<u32>) -> PyResult<String> {
Ok(format!("{:?} ** {:?} (mod: {:?})", lhs, rhs, mod_))
}
}
#[test]
@ -166,8 +195,9 @@ fn binary_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
let c = Py::new(py, BinaryArithmetic {}).unwrap();
let c = PyCell::new(py, BinaryArithmetic {}).unwrap();
py_run!(py, c, "assert c + c == 'BA + BA'");
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
py_run!(py, c, "assert c + 1 == 'BA + 1'");
py_run!(py, c, "assert 1 + c == '1 + BA'");
py_run!(py, c, "assert c - 1 == 'BA - 1'");
@ -185,6 +215,10 @@ fn binary_arithmetic() {
py_run!(py, c, "assert 1 ^ c == '1 ^ BA'");
py_run!(py, c, "assert c | 1 == 'BA | 1'");
py_run!(py, c, "assert 1 | c == '1 | BA'");
py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'");
py_run!(py, c, "assert 1 ** c == '1 ** BA (mod: None)'");
py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
}
#[pyclass]
@ -195,6 +229,38 @@ impl PyNumberProtocol for RhsArithmetic {
fn __radd__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} + RA", other))
}
fn __rsub__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} - RA", other))
}
fn __rmul__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} * RA", other))
}
fn __rlshift__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} << RA", other))
}
fn __rrshift__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} >> RA", other))
}
fn __rand__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} & RA", other))
}
fn __rxor__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} ^ RA", other))
}
fn __ror__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} | RA", other))
}
fn __rpow__(&self, other: &PyAny, _mod: Option<&'p PyAny>) -> PyResult<String> {
Ok(format!("{:?} ** RA", other))
}
}
#[test]
@ -202,11 +268,78 @@ fn rhs_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
let c = Py::new(py, RhsArithmetic {}).unwrap();
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
// TODO: commented out for now until reflected arithemtics gets fixed.
// see discussion here: https://github.com/PyO3/pyo3/pull/550
// py_run!(py, c, "assert 1 + c == '1 + RA'");
py_run!(py, c, "assert 1 + c == '1 + RA'");
py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
py_run!(py, c, "assert 1 - c == '1 - RA'");
py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'");
py_run!(py, c, "assert 1 * c == '1 * RA'");
py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'");
py_run!(py, c, "assert 1 << c == '1 << RA'");
py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'");
py_run!(py, c, "assert 1 >> c == '1 >> RA'");
py_run!(py, c, "assert c.__rand__(1) == '1 & RA'");
py_run!(py, c, "assert 1 & c == '1 & RA'");
py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'");
py_run!(py, c, "assert 1 ^ c == '1 ^ RA'");
py_run!(py, c, "assert c.__ror__(1) == '1 | RA'");
py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
}
#[pyclass]
struct LhsAndRhsArithmetic {}
#[pyproto]
impl PyNumberProtocol for LhsAndRhsArithmetic {
fn __radd__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} + RA", other))
}
fn __rsub__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} - RA", other))
}
fn __rpow__(&self, other: &PyAny, _mod: Option<&'p PyAny>) -> PyResult<String> {
Ok(format!("{:?} ** RA", other))
}
fn __add__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
Ok(format!("{:?} + {:?}", lhs, rhs))
}
fn __sub__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
Ok(format!("{:?} - {:?}", lhs, rhs))
}
fn __pow__(lhs: &PyAny, rhs: &PyAny, _mod: Option<u32>) -> PyResult<String> {
Ok(format!("{:?} ** {:?}", lhs, rhs))
}
}
#[pyproto]
impl PyObjectProtocol for LhsAndRhsArithmetic {
fn __repr__(&self) -> PyResult<&'static str> {
Ok("BA")
}
}
#[test]
fn lhs_override_rhs() {
let gil = Python::acquire_gil();
let py = gil.python();
let c = PyCell::new(py, LhsAndRhsArithmetic {}).unwrap();
// Not overrided
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
// Overrided
py_run!(py, c, "assert 1 + c == '1 + BA'");
py_run!(py, c, "assert 1 - c == '1 - BA'");
py_run!(py, c, "assert 1 ** c == '1 ** BA'");
}
#[pyclass]
@ -254,7 +387,7 @@ fn rich_comparisons() {
let gil = Python::acquire_gil();
let py = gil.python();
let c = Py::new(py, RichComparisons {}).unwrap();
let c = PyCell::new(py, RichComparisons {}).unwrap();
py_run!(py, c, "assert (c < c) == 'RC < RC'");
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
@ -280,7 +413,7 @@ fn rich_comparisons_python_3_type_error() {
let gil = Python::acquire_gil();
let py = gil.python();
let c2 = Py::new(py, RichComparisons2 {}).unwrap();
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
py_expect_exception!(py, c2, "c2 < c2", TypeError);
py_expect_exception!(py, c2, "c2 < 1", TypeError);
py_expect_exception!(py, c2, "1 < c2", TypeError);

View File

@ -2,6 +2,7 @@ use pyo3::class::PyGCProtocol;
use pyo3::class::PyTraverseError;
use pyo3::class::PyVisit;
use pyo3::prelude::*;
use pyo3::type_object::PyTypeObject;
use pyo3::{py_run, AsPyPointer, PyCell, PyTryInto};
use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};
@ -245,3 +246,63 @@ fn inheritance_with_new_methods_with_drop() {
assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed));
}
#[pyclass(gc)]
struct TraversableClass {
traversed: AtomicBool,
}
impl TraversableClass {
fn new() -> Self {
Self {
traversed: AtomicBool::new(false),
}
}
}
#[pyproto]
impl PyGCProtocol for TraversableClass {
fn __clear__(&mut self) {}
fn __traverse__(&self, _visit: PyVisit) -> Result<(), PyTraverseError> {
self.traversed.store(true, Ordering::Relaxed);
Ok(())
}
}
#[test]
fn gc_during_borrow() {
let gil = Python::acquire_gil();
let py = gil.python();
unsafe {
// declare a dummy visitor function
extern "C" fn novisit(
_object: *mut pyo3::ffi::PyObject,
_arg: *mut core::ffi::c_void,
) -> std::os::raw::c_int {
0
}
// get the traverse function
let ty = TraversableClass::type_object().as_ref(py).as_type_ptr();
let traverse = (*ty).tp_traverse.unwrap();
// create an object and check that traversing it works normally
// when it's not borrowed
let cell = PyCell::new(py, TraversableClass::new()).unwrap();
let obj = cell.to_object(py);
assert!(!cell.borrow().traversed.load(Ordering::Relaxed));
traverse(obj.as_ptr(), novisit, std::ptr::null_mut());
assert!(cell.borrow().traversed.load(Ordering::Relaxed));
// create an object and check that it is not traversed if the GC
// is invoked while it is already borrowed mutably
let cell2 = PyCell::new(py, TraversableClass::new()).unwrap();
let obj2 = cell2.to_object(py);
let guard = cell2.borrow_mut();
assert!(!guard.traversed.load(Ordering::Relaxed));
traverse(obj2.as_ptr(), novisit, std::ptr::null_mut());
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
}
}