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 ### Fixed
* `__radd__` and other `__r*__` methods now correctly work with operators. [#839](https://github.com/PyO3/pyo3/pull/839) * `__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] ## [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) * `PyAny` is now on the top level module and prelude. [#816](https://github.com/PyO3/pyo3/pull/816)
### Added ### Added
* `PyCell`, which has RefCell-like features. [#770](https://github.com/PyO3/pyo3/pull/770) * `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) * `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) * 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) * 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) * Fix proc-macro definition of PySetAttrProtocol. [#645](https://github.com/PyO3/pyo3/pull/645)
## [0.8.1] ## [0.8.1]
### Added ### Added
* Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608) * Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608)
### Fixed ### Fixed
* Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604) * 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 * Remove use of now unneeded 'AsciiExt' trait
## [0.2.2] - 09-26-2017 ## [0.2.2] - 09-26-2017
### Changed ### 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 Our guide has [a section](https://pyo3.rs/master/python_from_rust.html) with lots of examples
about this topic. 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_ * [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_ * [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._ * [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_ * [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._ * [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) * 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 * Contains an example of building wheels on Azure Pipelines
* [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library_ * [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_ * [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_ * [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_ * [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 Our guide has [a section](https://pyo3.rs/master/python_from_rust.html) with lots of examples
about this topic. about this topic.
## Examples and tooling ## Tools and libraries
* [maturin](https://github.com/PyO3/maturin) _Zero configuration build tool for Rust-made Python extensions_.
* [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count) _Counting the occurrences of a word in a text file_ * [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_.
* [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)_ * [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_ * [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._ * [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) * 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 * Contains an example of building wheels on Azure Pipelines
* [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library_ * [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_ * [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], 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 struct PyMethod {
pub name: &'static str, pub name: &'static str,
pub proto: &'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 { pub const OBJECT: Proto = Proto {
@ -73,18 +108,9 @@ pub const OBJECT: Proto = Proto {
}, },
], ],
py_methods: &[ py_methods: &[
PyMethod { PyMethod::new("__format__", "pyo3::class::basic::FormatProtocolImpl"),
name: "__format__", PyMethod::new("__bytes__", "pyo3::class::basic::BytesProtocolImpl"),
proto: "pyo3::class::basic::FormatProtocolImpl", PyMethod::new("__unicode__", "pyo3::class::basic::UnicodeProtocolImpl"),
},
PyMethod {
name: "__bytes__",
proto: "pyo3::class::basic::BytesProtocolImpl",
},
PyMethod {
name: "__unicode__",
proto: "pyo3::class::basic::UnicodeProtocolImpl",
},
], ],
}; };
@ -120,14 +146,14 @@ pub const ASYNC: Proto = Proto {
}, },
], ],
py_methods: &[ py_methods: &[
PyMethod { PyMethod::new(
name: "__aenter__", "__aenter__",
proto: "pyo3::class::pyasync::PyAsyncAenterProtocolImpl", "pyo3::class::pyasync::PyAsyncAenterProtocolImpl",
}, ),
PyMethod { PyMethod::new(
name: "__aexit__", "__aexit__",
proto: "pyo3::class::pyasync::PyAsyncAexitProtocolImpl", "pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
}, ),
], ],
}; };
@ -165,14 +191,14 @@ pub const CONTEXT: Proto = Proto {
}, },
], ],
py_methods: &[ py_methods: &[
PyMethod { PyMethod::new(
name: "__enter__", "__enter__",
proto: "pyo3::class::context::PyContextEnterProtocolImpl", "pyo3::class::context::PyContextEnterProtocolImpl",
}, ),
PyMethod { PyMethod::new(
name: "__exit__", "__exit__",
proto: "pyo3::class::context::PyContextExitProtocolImpl", "pyo3::class::context::PyContextExitProtocolImpl",
}, ),
], ],
}; };
@ -222,14 +248,11 @@ pub const DESCR: Proto = Proto {
}, },
], ],
py_methods: &[ py_methods: &[
PyMethod { PyMethod::new("__del__", "pyo3::class::context::PyDescrDelProtocolImpl"),
name: "__del__", PyMethod::new(
proto: "pyo3::class::context::PyDescrDelProtocolImpl", "__set_name__",
}, "pyo3::class::context::PyDescrNameProtocolImpl",
PyMethod { ),
name: "__set_name__",
proto: "pyo3::class::context::PyDescrNameProtocolImpl",
},
], ],
}; };
@ -283,10 +306,10 @@ pub const MAPPING: Proto = Proto {
proto: "pyo3::class::mapping::PyMappingReversedProtocol", proto: "pyo3::class::mapping::PyMappingReversedProtocol",
}, },
], ],
py_methods: &[PyMethod { py_methods: &[PyMethod::new(
name: "__reversed__", "__reversed__",
proto: "pyo3::class::mapping::PyMappingReversedProtocolImpl", "pyo3::class::mapping::PyMappingReversedProtocolImpl",
}], )],
}; };
pub const SEQ: Proto = Proto { pub const SEQ: Proto = Proto {
@ -579,10 +602,9 @@ pub const NUM: Proto = Proto {
pyres: false, pyres: false,
proto: "pyo3::class::number::PyNumberIModProtocol", proto: "pyo3::class::number::PyNumberIModProtocol",
}, },
MethodProto::Ternary { MethodProto::Binary {
name: "__ipow__", name: "__ipow__",
arg1: "Other", arg: "Other",
arg2: "Modulo",
pyres: false, pyres: false,
proto: "pyo3::class::number::PyNumberIPowProtocol", proto: "pyo3::class::number::PyNumberIPowProtocol",
}, },
@ -651,81 +673,58 @@ pub const NUM: Proto = Proto {
pyres: true, pyres: true,
proto: "pyo3::class::number::PyNumberFloatProtocol", proto: "pyo3::class::number::PyNumberFloatProtocol",
}, },
MethodProto::Unary {
name: "__round__",
pyres: true,
proto: "pyo3::class::number::PyNumberRoundProtocol",
},
MethodProto::Unary { MethodProto::Unary {
name: "__index__", name: "__index__",
pyres: true, pyres: true,
proto: "pyo3::class::number::PyNumberIndexProtocol", proto: "pyo3::class::number::PyNumberIndexProtocol",
}, },
MethodProto::Binary {
name: "__round__",
arg: "NDigits",
pyres: true,
proto: "pyo3::class::number::PyNumberRoundProtocol",
},
], ],
py_methods: &[ py_methods: &[
PyMethod { PyMethod::coexist("__radd__", "pyo3::class::number::PyNumberRAddProtocolImpl"),
name: "__radd__", PyMethod::coexist("__rsub__", "pyo3::class::number::PyNumberRSubProtocolImpl"),
proto: "pyo3::class::number::PyNumberRAddProtocolImpl", PyMethod::coexist("__rmul__", "pyo3::class::number::PyNumberRMulProtocolImpl"),
}, PyMethod::coexist(
PyMethod { "__rmatmul__",
name: "__rsub__", "pyo3::class::number::PyNumberRMatmulProtocolImpl",
proto: "pyo3::class::number::PyNumberRSubProtocolImpl", ),
}, PyMethod::coexist(
PyMethod { "__rtruediv__",
name: "__rmul__", "pyo3::class::number::PyNumberRTruedivProtocolImpl",
proto: "pyo3::class::number::PyNumberRMulProtocolImpl", ),
}, PyMethod::coexist(
PyMethod { "__rfloordiv__",
name: "__rmatmul__", "pyo3::class::number::PyNumberRFloordivProtocolImpl",
proto: "pyo3::class::number::PyNumberRMatmulProtocolImpl", ),
}, PyMethod::coexist("__rmod__", "pyo3::class::number::PyNumberRModProtocolImpl"),
PyMethod { PyMethod::coexist(
name: "__rtruediv__", "__rdivmod__",
proto: "pyo3::class::number::PyNumberRTruedivProtocolImpl", "pyo3::class::number::PyNumberRDivmodProtocolImpl",
}, ),
PyMethod { PyMethod::coexist("__rpow__", "pyo3::class::number::PyNumberRPowProtocolImpl"),
name: "__rfloordiv__", PyMethod::coexist(
proto: "pyo3::class::number::PyNumberRFloordivProtocolImpl", "__rlshift__",
}, "pyo3::class::number::PyNumberRLShiftProtocolImpl",
PyMethod { ),
name: "__rmod__", PyMethod::coexist(
proto: "pyo3::class::number::PyNumberRModProtocolImpl", "__rrshift__",
}, "pyo3::class::number::PyNumberRRShiftProtocolImpl",
PyMethod { ),
name: "__rdivmod__", PyMethod::coexist("__rand__", "pyo3::class::number::PyNumberRAndProtocolImpl"),
proto: "pyo3::class::number::PyNumberRDivmodProtocolImpl", PyMethod::coexist("__rxor__", "pyo3::class::number::PyNumberRXorProtocolImpl"),
}, PyMethod::coexist("__ror__", "pyo3::class::number::PyNumberROrProtocolImpl"),
PyMethod { PyMethod::new(
name: "__rpow__", "__complex__",
proto: "pyo3::class::number::PyNumberRPowProtocolImpl", "pyo3::class::number::PyNumberComplexProtocolImpl",
}, ),
PyMethod { PyMethod::new(
name: "__rlshift__", "__round__",
proto: "pyo3::class::number::PyNumberRLShiftProtocolImpl", "pyo3::class::number::PyNumberRoundProtocolImpl",
}, ),
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",
},
], ],
}; };

View File

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

View File

@ -63,7 +63,7 @@ impl<'a> FnSpec<'a> {
let is_mut = self let is_mut = self
.self_ .self_
.expect("impl_borrow_self is called for non-self fn"); .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 /// 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), "()"); const _LOCATION: &'static str = concat!(stringify!(#name), "()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args); let _pool = pyo3::GILPool::new(_py);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); 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<_>>()?; .collect::<syn::Result<_>>()?;
Ok(quote! { Ok(quote! {
pyo3::inventory::submit! { pyo3::inventory::submit! {
#![crate = pyo3] { #![crate = pyo3] {
type ClsInventory = <#cls as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType; type ClsInventory = <#cls as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;

View File

@ -83,10 +83,7 @@ pub fn impl_wrap_pyslf(
}; };
let slf = quote! { let slf = quote! {
let _cell = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf); let _cell = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _slf: #self_ty = match std::convert::TryFrom::try_from(_cell) { let _slf: #self_ty = std::convert::TryFrom::try_from(_cell)?;
Ok(_slf) => _slf,
Err(e) => return pyo3::PyErr::from(e).restore_and_null(_py),
};
}; };
impl_wrap_common(cls, spec, noargs, slf, body) impl_wrap_common(cls, spec, noargs, slf, body)
} }
@ -109,13 +106,11 @@ fn impl_wrap_common(
const _LOCATION: &'static str = concat!( const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#python_name), "()"); stringify!(#cls), ".", stringify!(#python_name), "()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
#slf let _pool = pyo3::GILPool::new(_py);
let _result = { #slf
pyo3::derive_utils::IntoPyResult::into_py_result(#body) pyo3::callback::convert(_py, #body)
}; })
pyo3::callback::cb_obj_convert(_py, _result)
} }
} }
} else { } else {
@ -130,14 +125,16 @@ fn impl_wrap_common(
const _LOCATION: &'static str = concat!( const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#python_name), "()"); stringify!(#cls), ".", stringify!(#python_name), "()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
#slf let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args); #slf
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); 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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf); let _pool = pyo3::GILPool::new(_py);
#borrow_self let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args); #borrow_self
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); 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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args); let _pool = pyo3::GILPool::new(_py);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); 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)) { let cell = pyo3::PyClassInitializer::from(_result?).create_cell(_py)?;
Ok(slf) => slf as _, Ok(cell as *mut pyo3::ffi::PyObject)
Err(e) => e.restore_and_null(_py), })
}
} }
} }
} }
@ -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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject); let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args); let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); 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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args); let _pool = pyo3::GILPool::new(_py);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs); 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)?), 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! { Ok(quote! {
unsafe extern "C" fn __wrap( unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> *mut pyo3::ffi::PyObject _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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf); let _pool = pyo3::GILPool::new(_py);
#borrow_self let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
#borrow_self
let result = pyo3::derive_utils::IntoPyResult::into_py_result(#getter_impl); pyo3::callback::convert(_py, #getter_impl)
})
match result {
Ok(val) => pyo3::IntoPyPointer::into_ptr(pyo3::IntoPy::<PyObject>::into_py(val, _py)),
Err(e) => e.restore_and_null(_py),
}
} }
}) })
} }
@ -344,9 +343,9 @@ fn impl_call_setter(spec: &FnSpec) -> syn::Result<TokenStream> {
let name = &spec.name; let name = &spec.name;
let fncall = if py_arg.is_some() { 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 { } 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) Ok(fncall)
@ -360,12 +359,12 @@ pub(crate) fn impl_wrap_setter(
let (python_name, setter_impl) = match property_type { let (python_name, setter_impl) = match property_type {
PropertyType::Descriptor(field) => { PropertyType::Descriptor(field) => {
let name = field.ident.as_ref().unwrap(); 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)?), 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! { Ok(quote! {
#[allow(unused_mut)] #[allow(unused_mut)]
unsafe extern "C" fn __wrap( 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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#python_name),"()");
let _py = pyo3::Python::assume_gil_acquired(); let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py); pyo3::run_callback(_py, || {
let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf); let _pool = pyo3::GILPool::new(_py);
#borrow_self let _slf = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _value = _py.from_borrowed_ptr(_value); #borrow_self
let _value = _py.from_borrowed_ptr::<pyo3::types::PyAny>(_value);
let _result = match pyo3::FromPyObject::extract(_value) { let _val = pyo3::FromPyObject::extract(_value)?;
Ok(_val) => { pyo3::callback::convert(_py, {#setter_impl})
#setter_impl })
}
Err(e) => Err(e)
};
match _result {
Ok(_) => 0,
Err(e) => e.restore_and_minus1(_py),
}
} }
}) })
} }
@ -462,22 +454,19 @@ fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStre
let mut _args = _args; let mut _args = _args;
let mut _kwargs = _kwargs; let mut _kwargs = _kwargs;
// Workaround to use the question mark operator without rewriting everything let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args(
let _result = (|| { Some(_LOCATION),
let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args( PARAMS,
Some(_LOCATION), _args,
PARAMS, _kwargs,
_args, #accept_args,
_kwargs, #accept_kwargs,
#accept_args, &mut output
#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() { for iimpl in impls.iter_mut() {
if let syn::ImplItem::Method(ref mut met) = iimpl { if let syn::ImplItem::Method(ref mut met) = iimpl {
for m in proto.methods { if let Some(m) = proto.get_proto(&met.sig.ident) {
if met.sig.ident == m.name() { impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
}
} }
for m in proto.py_methods { if let Some(m) = proto.get_method(&met.sig.ident) {
if met.sig.ident == m.name { let name = &met.sig.ident;
let name = &met.sig.ident; let proto: syn::Path = syn::parse_str(m.proto).unwrap();
let proto: syn::Path = syn::parse_str(m.proto).unwrap();
let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) { let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) {
Ok(fn_spec) => fn_spec, Ok(fn_spec) => fn_spec,
Err(err) => return err.to_compile_error(), Err(err) => return err.to_compile_error(),
}; };
let meth = pymethod::impl_proto_wrap(ty, &fn_spec); 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! { Some(pyo3::class::PyMethodDef {
impl #proto for #ty ml_name: stringify!(#name),
{ ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
#[inline] // We need METH_COEXIST here to prevent __add__ from overriding __radd__
fn #name() -> Option<pyo3::class::methods::PyMethodDef> { ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist,
#meth ml_doc: ""
})
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: ""
})
}
} }
}); }
} });
} }
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@
//! [Python information]( //! [Python information](
//! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors) //! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors)
use crate::callback::{PyObjectCallbackConverter, UnitCallbackConverter};
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::err::PyResult; use crate::err::PyResult;
use crate::types::{PyAny, PyType}; use crate::types::{PyAny, PyType};
@ -84,11 +83,7 @@ where
T: for<'p> PyDescrGetProtocol<'p>, T: for<'p> PyDescrGetProtocol<'p>,
{ {
fn tp_descr_get() -> Option<ffi::descrgetfunc> { fn tp_descr_get() -> Option<ffi::descrgetfunc> {
py_ternary_func!( py_ternary_func!(PyDescrGetProtocol, T::__get__)
PyDescrGetProtocol,
T::__get__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -108,7 +103,7 @@ where
T: for<'p> PyDescrSetProtocol<'p>, T: for<'p> PyDescrSetProtocol<'p>,
{ {
fn tp_descr_set() -> Option<ffi::descrsetfunc> { 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, arg,
_py: py, _py: py,
}; };
match slf.borrow().__traverse__(visit) {
Ok(()) => 0, if let Ok(borrow) = slf.try_borrow() {
Err(PyTraverseError(code)) => code, match borrow.__traverse__(visit) {
Ok(()) => 0,
Err(PyTraverseError(code)) => code,
}
} else {
0
} }
} }

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@
//! Python Number Interface //! Python Number Interface
//! Trait and support implementation for implementing number protocol //! Trait and support implementation for implementing number protocol
use crate::callback::PyObjectCallbackConverter;
use crate::class::basic::PyObjectProtocolImpl; use crate::class::basic::PyObjectProtocolImpl;
use crate::class::methods::PyMethodDef; use crate::class::methods::PyMethodDef;
use crate::err::PyResult; use crate::err::PyResult;
@ -60,7 +59,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{ {
unimplemented!() 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 where
Self: PyNumberPowProtocol<'p>, Self: PyNumberPowProtocol<'p>,
{ {
@ -145,7 +144,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{ {
unimplemented!() unimplemented!()
} }
fn __rpow__(&'p self, other: Self::Other) -> Self::Result fn __rpow__(&'p self, other: Self::Other, modulo: Option<Self::Modulo>) -> Self::Result
where where
Self: PyNumberRPowProtocol<'p>, Self: PyNumberRPowProtocol<'p>,
{ {
@ -224,7 +223,7 @@ pub trait PyNumberProtocol<'p>: PyClass {
{ {
unimplemented!() 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 where
Self: PyNumberIPowProtocol<'p>, Self: PyNumberIPowProtocol<'p>,
{ {
@ -304,18 +303,18 @@ pub trait PyNumberProtocol<'p>: PyClass {
{ {
unimplemented!() unimplemented!()
} }
fn __round__(&'p self) -> Self::Result
where
Self: PyNumberRoundProtocol<'p>,
{
unimplemented!()
}
fn __index__(&'p self) -> Self::Result fn __index__(&'p self) -> Self::Result
where where
Self: PyNumberIndexProtocol<'p>, Self: PyNumberIndexProtocol<'p>,
{ {
unimplemented!() unimplemented!()
} }
fn __round__(&'p self, ndigits: Option<Self::NDigits>) -> Self::Result
where
Self: PyNumberRoundProtocol<'p>,
{
unimplemented!()
}
} }
pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> {
@ -544,7 +543,6 @@ pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Modulo: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: Into<PyResult<()>>;
} }
@ -610,6 +608,7 @@ pub trait PyNumberFloatProtocol<'p>: PyNumberProtocol<'p> {
pub trait PyNumberRoundProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRoundProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Success: IntoPy<PyObject>;
type NDigits: FromPyObject<'p>;
type Result: Into<PyResult<Self::Success>>; type Result: Into<PyResult<Self::Success>>;
} }
@ -647,22 +646,22 @@ where
{ {
fn tp_as_number() -> Option<ffi::PyNumberMethods> { fn tp_as_number() -> Option<ffi::PyNumberMethods> {
Some(ffi::PyNumberMethods { Some(ffi::PyNumberMethods {
nb_add: Self::nb_add(), nb_add: Self::nb_add().or_else(Self::nb_add_fallback),
nb_subtract: Self::nb_subtract(), nb_subtract: Self::nb_subtract().or_else(Self::nb_sub_fallback),
nb_multiply: Self::nb_multiply(), nb_multiply: Self::nb_multiply().or_else(Self::nb_mul_fallback),
nb_remainder: Self::nb_remainder(), nb_remainder: Self::nb_remainder(),
nb_divmod: Self::nb_divmod(), nb_divmod: Self::nb_divmod().or_else(Self::nb_divmod_fallback),
nb_power: Self::nb_power(), nb_power: Self::nb_power().or_else(Self::nb_pow_fallback),
nb_negative: Self::nb_negative(), nb_negative: Self::nb_negative(),
nb_positive: Self::nb_positive(), nb_positive: Self::nb_positive(),
nb_absolute: Self::nb_absolute(), nb_absolute: Self::nb_absolute(),
nb_bool: <Self as PyObjectProtocolImpl>::nb_bool_fn(), nb_bool: <Self as PyObjectProtocolImpl>::nb_bool_fn(),
nb_invert: Self::nb_invert(), nb_invert: Self::nb_invert(),
nb_lshift: Self::nb_lshift(), nb_lshift: Self::nb_lshift().or_else(Self::nb_lshift_fallback),
nb_rshift: Self::nb_rshift(), nb_rshift: Self::nb_rshift().or_else(Self::nb_rshift_fallback),
nb_and: Self::nb_and(), nb_and: Self::nb_and().or_else(Self::nb_and_fallback),
nb_xor: Self::nb_xor(), nb_xor: Self::nb_xor().or_else(Self::nb_xor_fallback),
nb_or: Self::nb_or(), nb_or: Self::nb_or().or_else(Self::nb_or_fallback),
nb_int: Self::nb_int(), nb_int: Self::nb_int(),
nb_reserved: ::std::ptr::null_mut(), nb_reserved: ::std::ptr::null_mut(),
nb_float: Self::nb_float(), nb_float: Self::nb_float(),
@ -676,12 +675,12 @@ where
nb_inplace_and: Self::nb_inplace_and(), nb_inplace_and: Self::nb_inplace_and(),
nb_inplace_xor: Self::nb_inplace_xor(), nb_inplace_xor: Self::nb_inplace_xor(),
nb_inplace_or: Self::nb_inplace_or(), nb_inplace_or: Self::nb_inplace_or(),
nb_floor_divide: Self::nb_floor_divide(), nb_floor_divide: Self::nb_floor_divide().or_else(Self::nb_floordiv_fallback),
nb_true_divide: Self::nb_true_divide(), nb_true_divide: Self::nb_true_divide().or_else(Self::nb_truediv_fallback),
nb_inplace_floor_divide: Self::nb_inplace_floor_divide(), nb_inplace_floor_divide: Self::nb_inplace_floor_divide(),
nb_inplace_true_divide: Self::nb_inplace_true_divide(), nb_inplace_true_divide: Self::nb_inplace_true_divide(),
nb_index: Self::nb_index(), 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(), nb_inplace_matrix_multiply: Self::nb_inplace_matrix_multiply(),
}) })
} }
@ -761,11 +760,7 @@ where
T: for<'p> PyNumberAddProtocol<'p>, T: for<'p> PyNumberAddProtocol<'p>,
{ {
fn nb_add() -> Option<ffi::binaryfunc> { fn nb_add() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberAddProtocol, T::__add__)
PyNumberAddProtocol,
T::__add__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -787,11 +782,7 @@ where
T: for<'p> PyNumberSubProtocol<'p>, T: for<'p> PyNumberSubProtocol<'p>,
{ {
fn nb_subtract() -> Option<ffi::binaryfunc> { fn nb_subtract() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberSubProtocol, T::__sub__)
PyNumberSubProtocol,
T::__sub__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -813,11 +804,7 @@ where
T: for<'p> PyNumberMulProtocol<'p>, T: for<'p> PyNumberMulProtocol<'p>,
{ {
fn nb_multiply() -> Option<ffi::binaryfunc> { fn nb_multiply() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberMulProtocol, T::__mul__)
PyNumberMulProtocol,
T::__mul__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -839,11 +826,7 @@ where
T: for<'p> PyNumberMatmulProtocol<'p>, T: for<'p> PyNumberMatmulProtocol<'p>,
{ {
fn nb_matrix_multiply() -> Option<ffi::binaryfunc> { fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberMatmulProtocol, T::__matmul__)
PyNumberMatmulProtocol,
T::__matmul__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -865,11 +848,7 @@ where
T: for<'p> PyNumberTruedivProtocol<'p>, T: for<'p> PyNumberTruedivProtocol<'p>,
{ {
fn nb_true_divide() -> Option<ffi::binaryfunc> { fn nb_true_divide() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberTruedivProtocol, T::__truediv__)
PyNumberTruedivProtocol,
T::__truediv__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -891,11 +870,7 @@ where
T: for<'p> PyNumberFloordivProtocol<'p>, T: for<'p> PyNumberFloordivProtocol<'p>,
{ {
fn nb_floor_divide() -> Option<ffi::binaryfunc> { fn nb_floor_divide() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberFloordivProtocol, T::__floordiv__)
PyNumberFloordivProtocol,
T::__floordiv__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -917,11 +892,7 @@ where
T: for<'p> PyNumberModProtocol<'p>, T: for<'p> PyNumberModProtocol<'p>,
{ {
fn nb_remainder() -> Option<ffi::binaryfunc> { fn nb_remainder() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberModProtocol, T::__mod__)
PyNumberModProtocol,
T::__mod__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -943,11 +914,7 @@ where
T: for<'p> PyNumberDivmodProtocol<'p>, T: for<'p> PyNumberDivmodProtocol<'p>,
{ {
fn nb_divmod() -> Option<ffi::binaryfunc> { fn nb_divmod() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberDivmodProtocol, T::__divmod__)
PyNumberDivmodProtocol,
T::__divmod__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -969,11 +936,7 @@ where
T: for<'p> PyNumberPowProtocol<'p>, T: for<'p> PyNumberPowProtocol<'p>,
{ {
fn nb_power() -> Option<ffi::ternaryfunc> { fn nb_power() -> Option<ffi::ternaryfunc> {
py_ternary_num_func!( py_ternary_num_func!(PyNumberPowProtocol, T::__pow__)
PyNumberPowProtocol,
T::__pow__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -995,11 +958,7 @@ where
T: for<'p> PyNumberLShiftProtocol<'p>, T: for<'p> PyNumberLShiftProtocol<'p>,
{ {
fn nb_lshift() -> Option<ffi::binaryfunc> { fn nb_lshift() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberLShiftProtocol, T::__lshift__)
PyNumberLShiftProtocol,
T::__lshift__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1021,11 +980,7 @@ where
T: for<'p> PyNumberRShiftProtocol<'p>, T: for<'p> PyNumberRShiftProtocol<'p>,
{ {
fn nb_rshift() -> Option<ffi::binaryfunc> { fn nb_rshift() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberRShiftProtocol, T::__rshift__)
PyNumberRShiftProtocol,
T::__rshift__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1047,11 +1002,7 @@ where
T: for<'p> PyNumberAndProtocol<'p>, T: for<'p> PyNumberAndProtocol<'p>,
{ {
fn nb_and() -> Option<ffi::binaryfunc> { fn nb_and() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberAndProtocol, T::__and__)
PyNumberAndProtocol,
T::__and__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1073,11 +1024,7 @@ where
T: for<'p> PyNumberXorProtocol<'p>, T: for<'p> PyNumberXorProtocol<'p>,
{ {
fn nb_xor() -> Option<ffi::binaryfunc> { fn nb_xor() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberXorProtocol, T::__xor__)
PyNumberXorProtocol,
T::__xor__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1099,11 +1046,7 @@ where
T: for<'p> PyNumberOrProtocol<'p>, T: for<'p> PyNumberOrProtocol<'p>,
{ {
fn nb_or() -> Option<ffi::binaryfunc> { fn nb_or() -> Option<ffi::binaryfunc> {
py_binary_num_func!( py_binary_num_func!(PyNumberOrProtocol, T::__or__)
PyNumberOrProtocol,
T::__or__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1279,7 +1222,7 @@ where
T: for<'p> PyNumberIPowProtocol<'p>, T: for<'p> PyNumberIPowProtocol<'p>,
{ {
fn nb_inplace_power() -> Option<ffi::ternaryfunc> { 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)] // Fallback trait for nb_add
pub trait PyNumberRSubProtocolImpl { trait PyNumberAddFallback {
fn __rsub__() -> Option<PyMethodDef> { 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 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)] #[doc(hidden)]
pub trait PyNumberRMulProtocolImpl { 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)] #[doc(hidden)]
pub trait PyNumberRMatmulProtocolImpl { pub trait PyNumberRMatmulProtocolImpl {
fn __rmatmul__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRTruedivProtocolImpl { pub trait PyNumberRTruedivProtocolImpl {
fn __rtruediv__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRFloordivProtocolImpl { pub trait PyNumberRFloordivProtocolImpl {
fn __rfloordiv__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRModProtocolImpl { pub trait PyNumberRModProtocolImpl {
fn __rmod__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRDivmodProtocolImpl { pub trait PyNumberRDivmodProtocolImpl {
fn __rdivmod__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRPowProtocolImpl { pub trait PyNumberRPowProtocolImpl {
fn __rpow__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRLShiftProtocolImpl { pub trait PyNumberRLShiftProtocolImpl {
fn __rlshift__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRRShiftProtocolImpl { pub trait PyNumberRRShiftProtocolImpl {
fn __rrshift__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRAndProtocolImpl { pub trait PyNumberRAndProtocolImpl {
fn __rand__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberRXorProtocolImpl { pub trait PyNumberRXorProtocolImpl {
fn __rxor__() -> Option<PyMethodDef>; 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)] #[doc(hidden)]
pub trait PyNumberROrProtocolImpl { pub trait PyNumberROrProtocolImpl {
fn __ror__() -> Option<PyMethodDef>; 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 { trait PyNumberNegProtocolImpl {
fn nb_negative() -> Option<ffi::unaryfunc>; fn nb_negative() -> Option<ffi::unaryfunc>;
} }
@ -1603,11 +1860,7 @@ where
{ {
#[inline] #[inline]
fn nb_negative() -> Option<ffi::unaryfunc> { fn nb_negative() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberNegProtocol, T::__neg__)
PyNumberNegProtocol,
T::__neg__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1629,11 +1882,7 @@ where
T: for<'p> PyNumberPosProtocol<'p>, T: for<'p> PyNumberPosProtocol<'p>,
{ {
fn nb_positive() -> Option<ffi::unaryfunc> { fn nb_positive() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberPosProtocol, T::__pos__)
PyNumberPosProtocol,
T::__pos__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1655,11 +1904,7 @@ where
T: for<'p> PyNumberAbsProtocol<'p>, T: for<'p> PyNumberAbsProtocol<'p>,
{ {
fn nb_absolute() -> Option<ffi::unaryfunc> { fn nb_absolute() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberAbsProtocol, T::__abs__)
PyNumberAbsProtocol,
T::__abs__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1681,11 +1926,7 @@ where
T: for<'p> PyNumberInvertProtocol<'p>, T: for<'p> PyNumberInvertProtocol<'p>,
{ {
fn nb_invert() -> Option<ffi::unaryfunc> { fn nb_invert() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberInvertProtocol, T::__invert__)
PyNumberInvertProtocol,
T::__invert__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1707,11 +1948,7 @@ where
T: for<'p> PyNumberIntProtocol<'p>, T: for<'p> PyNumberIntProtocol<'p>,
{ {
fn nb_int() -> Option<ffi::unaryfunc> { fn nb_int() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberIntProtocol, T::__int__)
PyNumberIntProtocol,
T::__int__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1733,11 +1970,7 @@ where
T: for<'p> PyNumberFloatProtocol<'p>, T: for<'p> PyNumberFloatProtocol<'p>,
{ {
fn nb_float() -> Option<ffi::unaryfunc> { fn nb_float() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberFloatProtocol, T::__float__)
PyNumberFloatProtocol,
T::__float__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
@ -1759,15 +1992,11 @@ where
T: for<'p> PyNumberIndexProtocol<'p>, T: for<'p> PyNumberIndexProtocol<'p>,
{ {
fn nb_index() -> Option<ffi::unaryfunc> { fn nb_index() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(PyNumberIndexProtocol, T::__index__)
PyNumberIndexProtocol,
T::__index__,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
} }
} }
trait PyNumberComplexProtocolImpl { pub trait PyNumberComplexProtocolImpl {
fn __complex__() -> Option<PyMethodDef>; fn __complex__() -> Option<PyMethodDef>;
} }
@ -1780,7 +2009,7 @@ where
} }
} }
trait PyNumberRoundProtocolImpl { pub trait PyNumberRoundProtocolImpl {
fn __round__() -> Option<PyMethodDef>; fn __round__() -> Option<PyMethodDef>;
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -45,7 +45,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPy_MakePendingCalls")] #[cfg_attr(PyPy, link_name = "PyPy_MakePendingCalls")]
pub fn Py_MakePendingCalls() -> c_int; pub fn Py_MakePendingCalls() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPy_SetRecursionLimit")] #[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")] #[cfg_attr(PyPy, link_name = "PyPy_GetRecursionLimit")]
pub fn Py_GetRecursionLimit() -> c_int; pub fn Py_GetRecursionLimit() -> c_int;
fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int; fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int;
@ -74,7 +74,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")] #[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")]
pub fn PyEval_SaveThread() -> *mut PyThreadState; pub fn PyEval_SaveThread() -> *mut PyThreadState;
#[cfg_attr(PyPy, link_name = "PyPyEval_RestoreThread")] #[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")] #[cfg(py_sys_config = "WITH_THREAD")]
@ -83,13 +83,13 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyEval_ThreadsInitialized")] #[cfg_attr(PyPy, link_name = "PyPyEval_ThreadsInitialized")]
pub fn PyEval_ThreadsInitialized() -> c_int; pub fn PyEval_ThreadsInitialized() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyEval_InitThreads")] #[cfg_attr(PyPy, link_name = "PyPyEval_InitThreads")]
pub fn PyEval_InitThreads() -> (); pub fn PyEval_InitThreads();
pub fn PyEval_AcquireLock() -> (); pub fn PyEval_AcquireLock();
pub fn PyEval_ReleaseLock() -> (); pub fn PyEval_ReleaseLock();
#[cfg_attr(PyPy, link_name = "PyPyEval_AcquireThread")] #[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")] #[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))] #[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" { extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyDict_New")] #[cfg_attr(PyPy, link_name = "PyPyDict_New")]
pub fn PyDict_New() -> *mut PyObject; 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")] #[cfg_attr(PyPy, link_name = "PyPyDict_GetItem")]
pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject; pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;
pub fn PyDict_GetItemWithError(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")] #[cfg_attr(PyPy, link_name = "PyPyDict_DelItem")]
pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int; pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyDict_Clear")] #[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")] #[cfg_attr(PyPy, link_name = "PyPyDict_Next")]
pub fn PyDict_Next( pub fn PyDict_Next(
mp: *mut PyObject, mp: *mut PyObject,

View File

@ -65,17 +65,12 @@ extern "C" {
locals: *mut PyObject, locals: *mut PyObject,
) -> *mut PyFrameObject; ) -> *mut PyFrameObject;
pub fn PyFrame_BlockSetup( pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int);
f: *mut PyFrameObject,
_type: c_int,
handler: c_int,
level: c_int,
) -> ();
pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock; 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_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_ClearFreeList() -> c_int;
pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> 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; pub fn PyImport_Import(name: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyImport_ReloadModule")] #[cfg_attr(PyPy, link_name = "PyPyImport_ReloadModule")]
pub fn PyImport_ReloadModule(m: *mut PyObject) -> *mut PyObject; 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_ImportFrozenModuleObject(name: *mut PyObject) -> c_int;
pub fn PyImport_ImportFrozenModule(name: *const c_char) -> 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" { extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyOS_InterruptOccurred")] #[cfg_attr(PyPy, link_name = "PyPyOS_InterruptOccurred")]
pub fn PyOS_InterruptOccurred() -> c_int; pub fn PyOS_InterruptOccurred() -> c_int;
pub fn PyOS_InitInterrupts() -> (); pub fn PyOS_InitInterrupts();
#[cfg_attr(PyPy, link_name = "PyPyOS_AfterFork")] #[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, arg3: c_int,
) -> c_int; ) -> c_int;
pub type releasebufferproc = 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 /// Maximum number of dimensions
pub const PyBUF_MAX_NDIM: c_int = 64; pub const PyBUF_MAX_NDIM: c_int = 64;
@ -829,9 +829,9 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCallable_Check")] #[cfg_attr(PyPy, link_name = "PyPyCallable_Check")]
pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int; pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyObject_ClearWeakRefs")] #[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))] #[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(not(Py_LIMITED_API))]
#[cfg_attr(PyPy, link_name = "PyPyObject_CallFinalizerFromDealloc")] #[cfg_attr(PyPy, link_name = "PyPyObject_CallFinalizerFromDealloc")]
pub fn PyObject_CallFinalizerFromDealloc(arg1: *mut PyObject) -> c_int; pub fn PyObject_CallFinalizerFromDealloc(arg1: *mut PyObject) -> c_int;
@ -839,7 +839,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyObject_Dir")] #[cfg_attr(PyPy, link_name = "PyPyObject_Dir")]
pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject; pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject;
pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int; 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: // 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"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
#[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")] #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
pub fn _Py_Dealloc(arg1: *mut PyObject) -> (); pub fn _Py_Dealloc(arg1: *mut PyObject);
} }
// Reference counting macros. // Reference counting macros.

View File

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

View File

@ -11,7 +11,7 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyObject_Realloc")] #[cfg_attr(PyPy, link_name = "PyPyObject_Realloc")]
pub fn PyObject_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void; pub fn PyObject_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;
#[cfg_attr(PyPy, link_name = "PyPyObject_Free")] #[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))] #[cfg(not(Py_LIMITED_API))]
pub fn _Py_GetAllocatedBlocks() -> Py_ssize_t; pub fn _Py_GetAllocatedBlocks() -> Py_ssize_t;
@ -37,7 +37,7 @@ extern "C" {
pub struct PyObjectArenaAllocator { pub struct PyObjectArenaAllocator {
pub ctx: *mut c_void, pub ctx: *mut c_void,
pub alloc: Option<extern "C" fn(ctx: *mut c_void, size: size_t) -> *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))] #[cfg(not(Py_LIMITED_API))]
@ -50,8 +50,8 @@ impl Default for PyObjectArenaAllocator {
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator) -> (); pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator) -> (); pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
} }
/// Test if a type has a GC head /// Test if a type has a GC head
@ -84,10 +84,10 @@ extern "C" {
pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject; pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "_PyPyObject_GC_NewVar")] #[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_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject;
pub fn PyObject_GC_Track(arg1: *mut c_void) -> (); pub fn PyObject_GC_Track(arg1: *mut c_void);
pub fn PyObject_GC_UnTrack(arg1: *mut c_void) -> (); pub fn PyObject_GC_UnTrack(arg1: *mut c_void);
#[cfg_attr(PyPy, link_name = "PyPyObject_GC_Del")] #[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 /// 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"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyErr_SetNone")] #[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")] #[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")] #[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")] #[cfg_attr(PyPy, link_name = "PyPyErr_Occurred")]
pub fn PyErr_Occurred() -> *mut PyObject; pub fn PyErr_Occurred() -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyErr_Clear")] #[cfg_attr(PyPy, link_name = "PyPyErr_Clear")]
pub fn PyErr_Clear() -> (); pub fn PyErr_Clear();
#[cfg_attr(PyPy, link_name = "PyPyErr_Fetch")] #[cfg_attr(PyPy, link_name = "PyPyErr_Fetch")]
pub fn PyErr_Fetch( pub fn PyErr_Fetch(
arg1: *mut *mut PyObject, arg1: *mut *mut PyObject,
arg2: *mut *mut PyObject, arg2: *mut *mut PyObject,
arg3: *mut *mut PyObject, arg3: *mut *mut PyObject,
) -> (); );
#[cfg_attr(PyPy, link_name = "PyPyErr_Restore")] #[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")] #[cfg_attr(PyPy, link_name = "PyPyErr_GetExcInfo")]
pub fn PyErr_GetExcInfo( pub fn PyErr_GetExcInfo(
arg1: *mut *mut PyObject, arg1: *mut *mut PyObject,
arg2: *mut *mut PyObject, arg2: *mut *mut PyObject,
arg3: *mut *mut PyObject, arg3: *mut *mut PyObject,
) -> (); );
#[cfg_attr(PyPy, link_name = "PyPyErr_SetExcInfo")] #[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")] #[cfg_attr(PyPy, link_name = "PyPy_FatalError")]
pub fn Py_FatalError(message: *const c_char) -> !; pub fn Py_FatalError(message: *const c_char) -> !;
#[cfg_attr(PyPy, link_name = "PyPyErr_GivenExceptionMatches")] #[cfg_attr(PyPy, link_name = "PyPyErr_GivenExceptionMatches")]
@ -45,7 +45,7 @@ extern "C" {
arg1: *mut *mut PyObject, arg1: *mut *mut PyObject,
arg2: *mut *mut PyObject, arg2: *mut *mut PyObject,
arg3: *mut *mut PyObject, arg3: *mut *mut PyObject,
) -> (); );
#[cfg_attr(PyPy, link_name = "PyPyException_SetTraceback")] #[cfg_attr(PyPy, link_name = "PyPyException_SetTraceback")]
pub fn PyException_SetTraceback(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; pub fn PyException_SetTraceback(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyException_GetTraceback")] #[cfg_attr(PyPy, link_name = "PyPyException_GetTraceback")]
@ -53,11 +53,11 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyException_GetCause")] #[cfg_attr(PyPy, link_name = "PyPyException_GetCause")]
pub fn PyException_GetCause(arg1: *mut PyObject) -> *mut PyObject; pub fn PyException_GetCause(arg1: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyException_SetCause")] #[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")] #[cfg_attr(PyPy, link_name = "PyPyException_GetContext")]
pub fn PyException_GetContext(arg1: *mut PyObject) -> *mut PyObject; pub fn PyException_GetContext(arg1: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyException_SetContext")] #[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] #[inline]
@ -277,8 +277,8 @@ extern "C" {
arg3: *mut PyObject, arg3: *mut PyObject,
) -> *mut PyObject; ) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyErr_BadInternalCall")] #[cfg_attr(PyPy, link_name = "PyPyErr_BadInternalCall")]
pub fn PyErr_BadInternalCall() -> (); pub fn PyErr_BadInternalCall();
pub fn _PyErr_BadInternalCall(filename: *const c_char, lineno: c_int) -> (); pub fn _PyErr_BadInternalCall(filename: *const c_char, lineno: c_int);
#[cfg_attr(PyPy, link_name = "PyPyErr_NewException")] #[cfg_attr(PyPy, link_name = "PyPyErr_NewException")]
pub fn PyErr_NewException( pub fn PyErr_NewException(
name: *const c_char, name: *const c_char,
@ -293,13 +293,13 @@ extern "C" {
dict: *mut PyObject, dict: *mut PyObject,
) -> *mut PyObject; ) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyErr_WriteUnraisable")] #[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")] #[cfg_attr(PyPy, link_name = "PyPyErr_CheckSignals")]
pub fn PyErr_CheckSignals() -> c_int; pub fn PyErr_CheckSignals() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyErr_SetInterrupt")] #[cfg_attr(PyPy, link_name = "PyPyErr_SetInterrupt")]
pub fn PyErr_SetInterrupt() -> (); pub fn PyErr_SetInterrupt();
pub fn PyErr_SyntaxLocation(filename: *const c_char, lineno: c_int) -> (); 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_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; pub fn PyErr_ProgramText(filename: *const c_char, lineno: c_int) -> *mut PyObject;
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub fn PyUnicodeDecodeError_Create( pub fn PyUnicodeDecodeError_Create(

View File

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

View File

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

View File

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

View File

@ -22,10 +22,6 @@ pub struct PyStructSequence_Desc {
extern "C" { extern "C" {
pub fn PyStructSequence_NewType(desc: *mut PyStructSequence_Desc) -> *mut PyTypeObject; pub fn PyStructSequence_NewType(desc: *mut PyStructSequence_Desc) -> *mut PyTypeObject;
pub fn PyStructSequence_New(_type: *mut PyTypeObject) -> *mut PyObject; pub fn PyStructSequence_New(_type: *mut PyTypeObject) -> *mut PyObject;
pub fn PyStructSequence_SetItem( pub fn PyStructSequence_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject);
arg1: *mut PyObject,
arg2: Py_ssize_t,
arg3: *mut PyObject,
) -> ();
pub fn PyStructSequence_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *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; pub fn PySys_GetObject(arg1: *const c_char) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPySys_SetObject")] #[cfg_attr(PyPy, link_name = "PyPySys_SetObject")]
pub fn PySys_SetObject(arg1: *const c_char, arg2: *mut PyObject) -> c_int; 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_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_SetArgvEx(arg1: c_int, arg2: *mut *mut wchar_t, arg3: c_int);
pub fn PySys_SetPath(arg1: *const wchar_t) -> (); pub fn PySys_SetPath(arg1: *const wchar_t);
#[cfg_attr(PyPy, link_name = "PyPySys_WriteStdout")] #[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")] #[cfg_attr(PyPy, link_name = "PyPySys_WriteStderr")]
pub fn PySys_WriteStderr(format: *const c_char, ...) -> (); pub fn PySys_WriteStderr(format: *const c_char, ...);
pub fn PySys_FormatStdout(format: *const c_char, ...) -> (); pub fn PySys_FormatStdout(format: *const c_char, ...);
pub fn PySys_FormatStderr(format: *const c_char, ...) -> (); pub fn PySys_FormatStderr(format: *const c_char, ...);
pub fn PySys_ResetWarnOptions() -> (); pub fn PySys_ResetWarnOptions();
pub fn PySys_AddWarnOption(arg1: *const wchar_t) -> (); pub fn PySys_AddWarnOption(arg1: *const wchar_t);
pub fn PySys_AddWarnOptionUnicode(arg1: *mut PyObject) -> (); pub fn PySys_AddWarnOptionUnicode(arg1: *mut PyObject);
pub fn PySys_HasWarnOptions() -> c_int; 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; pub fn PySys_GetXOptions() -> *mut PyObject;
} }

View File

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

View File

@ -108,7 +108,6 @@ impl Drop for GILGuard {
unsafe { unsafe {
let pool: &'static mut ReleasePool = &mut *POOL; let pool: &'static mut ReleasePool = &mut *POOL;
pool.drain(self.python(), self.owned, self.borrowed); pool.drain(self.python(), self.owned, self.borrowed);
ffi::PyGILState_Release(self.gstate); 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 /// This trait is private to implement; this method exists to make it
/// impossible to implement outside the crate. /// impossible to implement outside the crate.
fn __private__(&self) -> crate::internal_tricks::PrivateMarker; fn __private__(&self) -> crate::internal_tricks::PrivateMarker;
} };
} }
macro_rules! private_impl { macro_rules! private_impl {
@ -21,7 +21,7 @@ macro_rules! private_impl {
fn __private__(&self) -> crate::internal_tricks::PrivateMarker { fn __private__(&self) -> crate::internal_tricks::PrivateMarker {
crate::internal_tricks::PrivateMarker crate::internal_tricks::PrivateMarker
} }
} };
} }
macro_rules! pyo3_exception { macro_rules! pyo3_exception {

View File

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

View File

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

View File

@ -4,8 +4,8 @@
use crate::err::{self, PyErr, PyResult}; use crate::err::{self, PyErr, PyResult};
use crate::internal_tricks::Unsendable; use crate::internal_tricks::Unsendable;
use crate::{ use crate::{
ffi, AsPyPointer, FromPyObject, PyAny, PyNativeType, PyObject, PyTryFrom, Python, ffi, AsPyPointer, FromPyObject, PyAny, PyNativeType, PyObject, Python, ToBorrowedObject,
ToBorrowedObject, ToPyObject, ToPyObject,
}; };
use std::cmp; use std::cmp;
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};
@ -189,13 +189,9 @@ where
K: FromPyObject<'source> + cmp::Eq + hash::Hash, K: FromPyObject<'source> + cmp::Eq + hash::Hash,
S: hash::BuildHasher + Default, S: hash::BuildHasher + Default,
{ {
fn extract(ob: &'source PyAny) -> Result<Self, PyErr> { fn extract(ob: &'source PyAny) -> PyResult<Self> {
let set = <PySet as PyTryFrom>::try_from(ob)?; let set: &PySet = ob.downcast()?;
let mut ret = HashSet::default(); set.iter().map(K::extract).collect()
for k in set.iter() {
ret.insert(K::extract(k)?);
}
Ok(ret)
} }
} }
@ -203,13 +199,9 @@ impl<'source, K> FromPyObject<'source> for BTreeSet<K>
where where
K: FromPyObject<'source> + cmp::Ord, K: FromPyObject<'source> + cmp::Ord,
{ {
fn extract(ob: &'source PyAny) -> Result<Self, PyErr> { fn extract(ob: &'source PyAny) -> PyResult<Self> {
let set = <PySet as PyTryFrom>::try_from(ob)?; let set: &PySet = ob.downcast()?;
let mut ret = BTreeSet::default(); set.iter().map(K::extract).collect()
for k in set.iter() {
ret.insert(K::extract(k)?);
}
Ok(ret)
} }
} }
@ -279,9 +271,9 @@ impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{PyFrozenSet, PySet}; use super::{PyFrozenSet, PySet};
use crate::instance::AsPyRef; use crate::{AsPyRef, ObjectProtocol, PyTryFrom, Python, ToPyObject};
use crate::{ObjectProtocol, PyTryFrom, Python, ToPyObject}; use std::collections::{BTreeSet, HashSet};
use std::collections::HashSet; use std::iter::FromIterator;
#[test] #[test]
fn test_set_new() { fn test_set_new() {
@ -433,4 +425,30 @@ mod test {
assert_eq!(1i32, el.extract::<i32>().unwrap()); 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; mod common;
#[pyclass] #[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] #[pyproto]
impl PyNumberProtocol for UnaryArithmetic { impl PyNumberProtocol for UnaryArithmetic {
fn __neg__(&self) -> PyResult<&'static str> { fn __neg__(&self) -> PyResult<Self> {
Ok("neg") Ok(Self::new(-self.inner))
} }
fn __pos__(&self) -> PyResult<&'static str> { fn __pos__(&self) -> PyResult<Self> {
Ok("pos") Ok(Self::new(self.inner))
} }
fn __abs__(&self) -> PyResult<&'static str> { fn __abs__(&self) -> PyResult<Self> {
Ok("abs") Ok(Self::new(self.inner.abs()))
} }
fn __invert__(&self) -> PyResult<&'static str> { fn __round__(&self, _ndigits: Option<u32>) -> PyResult<Self> {
Ok("invert") Ok(Self::new(self.inner.round()))
} }
} }
@ -34,11 +49,12 @@ fn unary_arithmetic() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
let c = Py::new(py, UnaryArithmetic {}).unwrap(); let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
py_run!(py, c, "assert -c == 'neg'"); py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
py_run!(py, c, "assert +c == 'pos'"); py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
py_run!(py, c, "assert abs(c) == 'abs'"); py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
py_run!(py, c, "assert ~c == 'invert'"); py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
} }
#[pyclass] #[pyclass]
@ -104,15 +120,19 @@ impl PyNumberProtocol for InPlaceOperations {
self.value |= other; self.value |= other;
Ok(()) Ok(())
} }
fn __ipow__(&mut self, other: u32) -> PyResult<()> {
self.value = self.value.pow(other);
Ok(())
}
} }
#[test] #[test]
fn inplace_operations() { fn inplace_operations() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
let init = |value, code| { 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); 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 &= 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 |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'"); 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] #[pyproto]
@ -159,6 +184,10 @@ impl PyNumberProtocol for BinaryArithmetic {
fn __or__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> { fn __or__(lhs: &PyAny, rhs: &PyAny) -> PyResult<String> {
Ok(format!("{:?} | {:?}", lhs, rhs)) Ok(format!("{:?} | {:?}", lhs, rhs))
} }
fn __pow__(lhs: &PyAny, rhs: &PyAny, mod_: Option<u32>) -> PyResult<String> {
Ok(format!("{:?} ** {:?} (mod: {:?})", lhs, rhs, mod_))
}
} }
#[test] #[test]
@ -166,8 +195,9 @@ fn binary_arithmetic() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); 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 + 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 c + 1 == 'BA + 1'");
py_run!(py, c, "assert 1 + c == '1 + BA'"); py_run!(py, c, "assert 1 + c == '1 + BA'");
py_run!(py, c, "assert c - 1 == 'BA - 1'"); 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 1 ^ c == '1 ^ BA'");
py_run!(py, c, "assert c | 1 == 'BA | 1'"); py_run!(py, c, "assert c | 1 == 'BA | 1'");
py_run!(py, c, "assert 1 | c == '1 | BA'"); 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] #[pyclass]
@ -195,6 +229,38 @@ impl PyNumberProtocol for RhsArithmetic {
fn __radd__(&self, other: &PyAny) -> PyResult<String> { fn __radd__(&self, other: &PyAny) -> PyResult<String> {
Ok(format!("{:?} + RA", other)) 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] #[test]
@ -202,11 +268,78 @@ fn rhs_arithmetic() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); 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'"); py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
// TODO: commented out for now until reflected arithemtics gets fixed. py_run!(py, c, "assert 1 + c == '1 + RA'");
// see discussion here: https://github.com/PyO3/pyo3/pull/550 py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
// py_run!(py, c, "assert 1 + c == '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] #[pyclass]
@ -254,7 +387,7 @@ fn rich_comparisons() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); 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 < c) == 'RC < RC'");
py_run!(py, c, "assert (c < 1) == 'RC < 1'"); py_run!(py, c, "assert (c < 1) == 'RC < 1'");
py_run!(py, c, "assert (1 < c) == '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 gil = Python::acquire_gil();
let py = gil.python(); 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 < c2", TypeError);
py_expect_exception!(py, c2, "c2 < 1", TypeError); py_expect_exception!(py, c2, "c2 < 1", TypeError);
py_expect_exception!(py, c2, "1 < c2", 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::PyTraverseError;
use pyo3::class::PyVisit; use pyo3::class::PyVisit;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::type_object::PyTypeObject;
use pyo3::{py_run, AsPyPointer, PyCell, PyTryInto}; use pyo3::{py_run, AsPyPointer, PyCell, PyTryInto};
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering}; 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_called1.load(Ordering::Relaxed));
assert!(drop_called2.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);
}
}