Use PyMethodsImpl instead of *ProtocolImpl::methods
This commit is contained in:
parent
da22eecb5f
commit
69dba08b01
|
@ -24,11 +24,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- The `GILGuard` returned from `Python::acquire_gil` will now only assume responsiblity for freeing owned references on drop if no other `GILPool` or `GILGuard` exists. This ensures that multiple calls to the safe api `Python::acquire_gil` cannot lead to dangling references. [#893](https://github.com/PyO3/pyo3/pull/893)
|
||||
- The trait `ObjectProtocol` has been removed, and all the methods from the trait have been moved to `PyAny`. [#911](https://github.com/PyO3/pyo3/pull/911)
|
||||
- The exception to this is `ObjectProtocol::None`, which has simply been removed. Use `Python::None` instead.
|
||||
- No `#![feature(specialization)]` in user code. [#917](https://github.com/PyO3/pyo3/pull/917)
|
||||
|
||||
### Removed
|
||||
- `PyMethodsProtocol` is now renamed to `PyMethodsImpl` and hidden. [#889](https://github.com/PyO3/pyo3/pull/889)
|
||||
- `num-traits` is no longer a dependency. [#895](https://github.com/PyO3/pyo3/pull/895)
|
||||
- `ObjectProtocol`. [#911](https://github.com/PyO3/pyo3/pull/911)
|
||||
- All `*ProtocolImpl` traits. [#917](https://github.com/PyO3/pyo3/pull/917)
|
||||
|
||||
### Fixed
|
||||
- `__radd__` and other `__r*__` methods now correctly work with operators. [#839](https://github.com/PyO3/pyo3/pull/839)
|
||||
|
|
|
@ -17,76 +17,7 @@ struct MyClass {
|
|||
The above example generates implementations for [`PyTypeInfo`], [`PyTypeObject`],
|
||||
and [`PyClass`] for `MyClass`.
|
||||
|
||||
Specifically, the following implementation is generated:
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
||||
/// Class for demonstration
|
||||
struct MyClass {
|
||||
num: i32,
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
impl pyo3::pyclass::PyClassAlloc for MyClass {}
|
||||
|
||||
unsafe impl pyo3::PyTypeInfo for MyClass {
|
||||
type Type = MyClass;
|
||||
type BaseType = PyAny;
|
||||
type BaseLayout = pyo3::pycell::PyCellBase<PyAny>;
|
||||
type Layout = PyCell<Self>;
|
||||
type Initializer = PyClassInitializer<Self>;
|
||||
type AsRefTarget = PyCell<Self>;
|
||||
|
||||
const NAME: &'static str = "MyClass";
|
||||
const MODULE: Option<&'static str> = None;
|
||||
const DESCRIPTION: &'static str = "Class for demonstration";
|
||||
const FLAGS: usize = 0;
|
||||
|
||||
#[inline]
|
||||
fn type_object() -> &'static pyo3::ffi::PyTypeObject {
|
||||
use pyo3::type_object::LazyStaticType;
|
||||
static TYPE_OBJECT: LazyStaticType = LazyStaticType::new();
|
||||
TYPE_OBJECT.get_or_init::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
impl pyo3::pyclass::PyClass for MyClass {
|
||||
type Dict = pyo3::pyclass_slots::PyClassDummySlot;
|
||||
type WeakRef = pyo3::pyclass_slots::PyClassDummySlot;
|
||||
type BaseNativeType = PyAny;
|
||||
}
|
||||
|
||||
impl pyo3::IntoPy<PyObject> for MyClass {
|
||||
fn into_py(self, py: pyo3::Python) -> pyo3::PyObject {
|
||||
pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pyo3MethodsInventoryForMyClass {
|
||||
methods: &'static [pyo3::class::PyMethodDefType],
|
||||
}
|
||||
|
||||
impl pyo3::class::methods::PyMethodsInventory for Pyo3MethodsInventoryForMyClass {
|
||||
fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self {
|
||||
Self { methods }
|
||||
}
|
||||
|
||||
fn get_methods(&self) -> &'static [pyo3::class::PyMethodDefType] {
|
||||
self.methods
|
||||
}
|
||||
}
|
||||
|
||||
impl pyo3::class::methods::PyMethodsImpl for MyClass {
|
||||
type Methods = Pyo3MethodsInventoryForMyClass;
|
||||
}
|
||||
|
||||
pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass);
|
||||
# let gil = Python::acquire_gil();
|
||||
# let py = gil.python();
|
||||
# let cls = py.get_type::<MyClass>();
|
||||
# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'")
|
||||
```
|
||||
If you curious what `#[pyclass]` generates, see [How methods are implemented](#how-methods-are-implemented) section.
|
||||
|
||||
## Adding the class to a module
|
||||
|
||||
|
@ -944,7 +875,77 @@ pyclass dependent on whether there is an impl block, we'd need to implement the
|
|||
`#[pyclass]` and override the implementation in `#[pymethods]`, which is to the best of my knowledge
|
||||
only possible with the specialization feature, which can't be used on stable.
|
||||
|
||||
To escape this we use [inventory](https://github.com/dtolnay/inventory), which allows us to collect `impl`s from arbitrary source code by exploiting some binary trick. See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) and `pyo3_derive_backend::py_class::impl_inventory` for more details.
|
||||
To escape this we use [inventory](https://github.com/dtolnay/inventory),
|
||||
which allows us to collect `impl`s from arbitrary source code by exploiting some binary trick.
|
||||
See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) and `pyo3_derive_backend::py_class` for more details.
|
||||
|
||||
Specifically, the following implementation is generated:
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
||||
/// Class for demonstration
|
||||
struct MyClass {
|
||||
num: i32,
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
impl pyo3::pyclass::PyClassAlloc for MyClass {}
|
||||
|
||||
unsafe impl pyo3::PyTypeInfo for MyClass {
|
||||
type Type = MyClass;
|
||||
type BaseType = PyAny;
|
||||
type BaseLayout = pyo3::pycell::PyCellBase<PyAny>;
|
||||
type Layout = PyCell<Self>;
|
||||
type Initializer = PyClassInitializer<Self>;
|
||||
type AsRefTarget = PyCell<Self>;
|
||||
|
||||
const NAME: &'static str = "MyClass";
|
||||
const MODULE: Option<&'static str> = None;
|
||||
const DESCRIPTION: &'static str = "Class for demonstration";
|
||||
const FLAGS: usize = 0;
|
||||
|
||||
#[inline]
|
||||
fn type_object() -> &'static pyo3::ffi::PyTypeObject {
|
||||
use pyo3::type_object::LazyStaticType;
|
||||
static TYPE_OBJECT: LazyStaticType = LazyStaticType::new();
|
||||
TYPE_OBJECT.get_or_init::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
impl pyo3::pyclass::PyClass for MyClass {
|
||||
type Dict = pyo3::pyclass_slots::PyClassDummySlot;
|
||||
type WeakRef = pyo3::pyclass_slots::PyClassDummySlot;
|
||||
type BaseNativeType = PyAny;
|
||||
}
|
||||
|
||||
impl pyo3::IntoPy<PyObject> for MyClass {
|
||||
fn into_py(self, py: pyo3::Python) -> pyo3::PyObject {
|
||||
pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pyo3MethodsInventoryForMyClass {
|
||||
methods: &'static [pyo3::class::PyMethodDefType],
|
||||
}
|
||||
impl pyo3::class::methods::PyMethodsInventory for Pyo3MethodsInventoryForMyClass {
|
||||
fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self {
|
||||
Self { methods }
|
||||
}
|
||||
fn get(&self) -> &'static [pyo3::class::PyMethodDefType] {
|
||||
self.methods
|
||||
}
|
||||
}
|
||||
impl pyo3::class::methods::PyMethodsImpl for MyClass {
|
||||
type Methods = Pyo3MethodsInventoryForMyClass;
|
||||
}
|
||||
pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass);
|
||||
# let gil = Python::acquire_gil();
|
||||
# let py = gil.python();
|
||||
# let cls = py.get_type::<MyClass>();
|
||||
# pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'")
|
||||
```
|
||||
|
||||
|
||||
[`GILGuard`]: https://docs.rs/pyo3/latest/pyo3/struct.GILGuard.html
|
||||
[`PyGCProtocol`]: https://docs.rs/pyo3/latest/pyo3/class/gc/trait.PyGCProtocol.html
|
||||
|
|
|
@ -208,11 +208,9 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result<Vec<FnType>> {
|
|||
Ok(descs)
|
||||
}
|
||||
|
||||
/// The orphan rule disallows using a generic inventory struct, so we create the whole boilerplate
|
||||
/// once per class
|
||||
fn impl_inventory(cls: &syn::Ident) -> TokenStream {
|
||||
// Try to build a unique type that gives a hint about it's function when
|
||||
// it comes up in error messages
|
||||
/// To allow multiple #[pymethods]/#[pyproto] block, we define inventory types.
|
||||
fn impl_methods_inventory(cls: &syn::Ident) -> TokenStream {
|
||||
// Try to build a unique type for better error messages
|
||||
let name = format!("Pyo3MethodsInventoryFor{}", cls);
|
||||
let inventory_cls = syn::Ident::new(&name, Span::call_site());
|
||||
|
||||
|
@ -221,15 +219,11 @@ fn impl_inventory(cls: &syn::Ident) -> TokenStream {
|
|||
pub struct #inventory_cls {
|
||||
methods: &'static [pyo3::class::PyMethodDefType],
|
||||
}
|
||||
|
||||
impl pyo3::class::methods::PyMethodsInventory for #inventory_cls {
|
||||
fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self {
|
||||
Self {
|
||||
methods
|
||||
}
|
||||
Self { methods }
|
||||
}
|
||||
|
||||
fn get_methods(&self) -> &'static [pyo3::class::PyMethodDefType] {
|
||||
fn get(&self) -> &'static [pyo3::class::PyMethodDefType] {
|
||||
self.methods
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +339,7 @@ fn impl_class(
|
|||
quote! {}
|
||||
};
|
||||
|
||||
let inventory_impl = impl_inventory(&cls);
|
||||
let impl_inventory = impl_methods_inventory(&cls);
|
||||
|
||||
let base = &attr.base;
|
||||
let flags = &attr.flags;
|
||||
|
@ -418,7 +412,7 @@ fn impl_class(
|
|||
|
||||
#into_pyobject
|
||||
|
||||
#inventory_impl
|
||||
#impl_inventory
|
||||
|
||||
#extra
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
|
|||
));
|
||||
};
|
||||
|
||||
let tokens = impl_proto_impl(&ast.self_ty, &mut ast.items, proto);
|
||||
let tokens = impl_proto_impl(&ast.self_ty, &mut ast.items, proto)?;
|
||||
|
||||
// attach lifetime
|
||||
let mut seg = path.segments.pop().unwrap().into_value();
|
||||
|
@ -57,53 +57,54 @@ fn impl_proto_impl(
|
|||
ty: &syn::Type,
|
||||
impls: &mut Vec<syn::ImplItem>,
|
||||
proto: &defs::Proto,
|
||||
) -> TokenStream {
|
||||
let mut tokens = TokenStream::new();
|
||||
) -> syn::Result<TokenStream> {
|
||||
let mut trait_impls = TokenStream::new();
|
||||
let mut py_methods = Vec::new();
|
||||
|
||||
for iimpl in impls.iter_mut() {
|
||||
if let syn::ImplItem::Method(ref mut met) = iimpl {
|
||||
if let Some(m) = proto.get_proto(&met.sig.ident) {
|
||||
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
|
||||
impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut trait_impls);
|
||||
}
|
||||
if let Some(m) = proto.get_method(&met.sig.ident) {
|
||||
let name = &met.sig.ident;
|
||||
let proto: syn::Path = syn::parse_str(m.proto).unwrap();
|
||||
|
||||
let fn_spec = match FnSpec::parse(&met.sig, &mut met.attrs, false) {
|
||||
Ok(fn_spec) => fn_spec,
|
||||
Err(err) => return err.to_compile_error(),
|
||||
};
|
||||
let meth = pymethod::impl_proto_wrap(ty, &fn_spec);
|
||||
let fn_spec = FnSpec::parse(&met.sig, &mut met.attrs, false)?;
|
||||
let method = pymethod::impl_proto_wrap(ty, &fn_spec);
|
||||
let coexist = if m.can_coexist {
|
||||
// We need METH_COEXIST here to prevent __add__ from overriding __radd__
|
||||
quote!(pyo3::ffi::METH_COEXIST)
|
||||
} else {
|
||||
quote!(0)
|
||||
};
|
||||
// TODO(kngwyu): doc
|
||||
py_methods.push(quote! {
|
||||
impl #proto for #ty
|
||||
{
|
||||
#[inline]
|
||||
fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
|
||||
#meth
|
||||
|
||||
Some(pyo3::class::PyMethodDef {
|
||||
ml_name: stringify!(#name),
|
||||
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
|
||||
// We need METH_COEXIST here to prevent __add__ from overriding __radd__
|
||||
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist,
|
||||
ml_doc: ""
|
||||
})
|
||||
pyo3::class::PyMethodDefType::Method({
|
||||
#method
|
||||
pyo3::class::PyMethodDef {
|
||||
ml_name: stringify!(#name),
|
||||
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
|
||||
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist,
|
||||
ml_doc: ""
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
#tokens
|
||||
|
||||
#(#py_methods)*
|
||||
if py_methods.is_empty() {
|
||||
return Ok(quote! { #trait_impls });
|
||||
}
|
||||
let inventory_submission = quote! {
|
||||
pyo3::inventory::submit! {
|
||||
#![crate = pyo3] {
|
||||
type ProtoInventory = <#ty as pyo3::class::methods::PyMethodsImpl>::Methods;
|
||||
<ProtoInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(#py_methods),*])
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(quote! {
|
||||
#trait_impls
|
||||
#inventory_submission
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)
|
||||
|
||||
use crate::callback::HashCallbackOutput;
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::{
|
||||
exceptions, ffi, FromPyObject, IntoPy, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult,
|
||||
};
|
||||
|
@ -145,15 +144,11 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub trait PyObjectProtocolImpl {
|
||||
fn methods() -> Vec<PyMethodDef>;
|
||||
fn tp_as_object(_type_object: &mut ffi::PyTypeObject);
|
||||
fn nb_bool_fn() -> Option<ffi::inquiry>;
|
||||
}
|
||||
|
||||
impl<T> PyObjectProtocolImpl for T {
|
||||
default fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
default fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
|
||||
default fn nb_bool_fn() -> Option<ffi::inquiry> {
|
||||
None
|
||||
|
@ -164,20 +159,6 @@ impl<'p, T> PyObjectProtocolImpl for T
|
|||
where
|
||||
T: PyObjectProtocol<'p>,
|
||||
{
|
||||
fn methods() -> Vec<PyMethodDef> {
|
||||
let mut methods = Vec::new();
|
||||
|
||||
if let Some(def) = <Self as FormatProtocolImpl>::__format__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as BytesProtocolImpl>::__bytes__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as UnicodeProtocolImpl>::__unicode__() {
|
||||
methods.push(def)
|
||||
}
|
||||
methods
|
||||
}
|
||||
fn tp_as_object(type_object: &mut ffi::PyTypeObject) {
|
||||
type_object.tp_str = Self::tp_str();
|
||||
type_object.tp_repr = Self::tp_repr();
|
||||
|
@ -373,45 +354,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait FormatProtocolImpl {
|
||||
fn __format__() -> Option<PyMethodDef>;
|
||||
}
|
||||
impl<'p, T> FormatProtocolImpl for T
|
||||
where
|
||||
T: PyObjectProtocol<'p>,
|
||||
{
|
||||
default fn __format__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait BytesProtocolImpl {
|
||||
fn __bytes__() -> Option<PyMethodDef>;
|
||||
}
|
||||
impl<'p, T> BytesProtocolImpl for T
|
||||
where
|
||||
T: PyObjectProtocol<'p>,
|
||||
{
|
||||
default fn __bytes__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait UnicodeProtocolImpl {
|
||||
fn __unicode__() -> Option<PyMethodDef>;
|
||||
}
|
||||
impl<'p, T> UnicodeProtocolImpl for T
|
||||
where
|
||||
T: PyObjectProtocol<'p>,
|
||||
{
|
||||
default fn __unicode__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait HashProtocolImpl {
|
||||
fn tp_hash() -> Option<ffi::hashfunc>;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
//! Trait and support implementation for context manager api
|
||||
//!
|
||||
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::{PyClass, PyObject};
|
||||
|
||||
|
@ -43,61 +42,3 @@ pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> {
|
|||
type Success: crate::IntoPy<PyObject>;
|
||||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyContextProtocolImpl {
|
||||
fn methods() -> Vec<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<T> PyContextProtocolImpl for T {
|
||||
default fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyContextProtocolImpl for T
|
||||
where
|
||||
T: PyContextProtocol<'p>,
|
||||
{
|
||||
#[inline]
|
||||
fn methods() -> Vec<PyMethodDef> {
|
||||
let mut methods = Vec::new();
|
||||
|
||||
if let Some(def) = <Self as PyContextEnterProtocolImpl>::__enter__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyContextExitProtocolImpl>::__exit__() {
|
||||
methods.push(def)
|
||||
}
|
||||
|
||||
methods
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyContextEnterProtocolImpl {
|
||||
fn __enter__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyContextEnterProtocolImpl for T
|
||||
where
|
||||
T: PyContextProtocol<'p>,
|
||||
{
|
||||
default fn __enter__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyContextExitProtocolImpl {
|
||||
fn __exit__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyContextExitProtocolImpl for T
|
||||
where
|
||||
T: PyContextProtocol<'p>,
|
||||
{
|
||||
default fn __exit__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,14 +123,10 @@ impl<'p, T> PyDescrSetNameProtocolImpl for T where T: PyDescrProtocol<'p> {}
|
|||
|
||||
#[doc(hidden)]
|
||||
pub trait PyDescrProtocolImpl {
|
||||
fn methods() -> Vec<PyMethodDef>;
|
||||
fn tp_as_descr(_type_object: &mut ffi::PyTypeObject);
|
||||
}
|
||||
|
||||
impl<T> PyDescrProtocolImpl for T {
|
||||
default fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
default fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
|
||||
}
|
||||
|
||||
|
@ -138,9 +134,6 @@ impl<'p, T> PyDescrProtocolImpl for T
|
|||
where
|
||||
T: PyDescrProtocol<'p>,
|
||||
{
|
||||
fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
fn tp_as_descr(type_object: &mut ffi::PyTypeObject) {
|
||||
type_object.tp_descr_get = Self::tp_descr_get();
|
||||
type_object.tp_descr_set = Self::tp_descr_set();
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//! Python Mapping Interface
|
||||
//! Trait and support implementation for implementing mapping support
|
||||
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject};
|
||||
|
||||
|
@ -78,16 +77,12 @@ pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> {
|
|||
#[doc(hidden)]
|
||||
pub trait PyMappingProtocolImpl {
|
||||
fn tp_as_mapping() -> Option<ffi::PyMappingMethods>;
|
||||
fn methods() -> Vec<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<T> PyMappingProtocolImpl for T {
|
||||
default fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
|
||||
None
|
||||
}
|
||||
default fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyMappingProtocolImpl for T
|
||||
|
@ -108,17 +103,6 @@ where
|
|||
mp_ass_subscript: f,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn methods() -> Vec<PyMethodDef> {
|
||||
let mut methods = Vec::new();
|
||||
|
||||
if let Some(def) = <Self as PyMappingReversedProtocolImpl>::__reversed__() {
|
||||
methods.push(def)
|
||||
}
|
||||
|
||||
methods
|
||||
}
|
||||
}
|
||||
|
||||
trait PyMappingLenProtocolImpl {
|
||||
|
@ -242,17 +226,3 @@ where
|
|||
<T as DelSetItemDispatch>::det_set_dispatch()
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyMappingReversedProtocolImpl {
|
||||
fn __reversed__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyMappingReversedProtocolImpl for T
|
||||
where
|
||||
T: PyMappingProtocol<'p>,
|
||||
{
|
||||
default fn __reversed__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,16 +135,16 @@ impl PySetterDef {
|
|||
}
|
||||
|
||||
/// Implementation detail. Only to be used through the proc macros.
|
||||
/// Allows arbitrary pymethod blocks to submit their methods, which are eventually
|
||||
/// collected by pyclass.
|
||||
/// Allows arbitrary `#[pymethod]/#[pyproto]` blocks to submit their methods,
|
||||
/// which are eventually collected by `#[pyclass]`.
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "macros")]
|
||||
pub trait PyMethodsInventory: inventory::Collect {
|
||||
/// Create a new instance
|
||||
fn new(methods: &'static [PyMethodDefType]) -> Self;
|
||||
|
||||
/// Returns the methods for a single impl block
|
||||
fn get_methods(&self) -> &'static [PyMethodDefType];
|
||||
/// Returns the methods for a single `#[pymethods] impl` block
|
||||
fn get(&self) -> &'static [PyMethodDefType];
|
||||
}
|
||||
|
||||
/// Implementation detail. Only to be used through the proc macros.
|
||||
|
@ -159,7 +159,7 @@ pub trait PyMethodsImpl {
|
|||
fn py_methods() -> Vec<&'static PyMethodDefType> {
|
||||
inventory::iter::<Self::Methods>
|
||||
.into_iter()
|
||||
.flat_map(PyMethodsInventory::get_methods)
|
||||
.flat_map(PyMethodsInventory::get)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
//! Trait and support implementation for implementing number protocol
|
||||
|
||||
use crate::class::basic::PyObjectProtocolImpl;
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::{ffi, FromPyObject, IntoPy, PyClass, PyObject};
|
||||
|
||||
|
@ -619,14 +618,10 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberProtocolImpl: PyObjectProtocolImpl {
|
||||
fn methods() -> Vec<PyMethodDef>;
|
||||
fn tp_as_number() -> Option<ffi::PyNumberMethods>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberProtocolImpl for T {
|
||||
default fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
default fn tp_as_number() -> Option<ffi::PyNumberMethods> {
|
||||
if let Some(nb_bool) = <Self as PyObjectProtocolImpl>::nb_bool_fn() {
|
||||
let meth = ffi::PyNumberMethods {
|
||||
|
@ -684,62 +679,6 @@ where
|
|||
nb_inplace_matrix_multiply: Self::nb_inplace_matrix_multiply(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn methods() -> Vec<PyMethodDef> {
|
||||
let mut methods = Vec::new();
|
||||
|
||||
if let Some(def) = <Self as PyNumberRAddProtocolImpl>::__radd__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRSubProtocolImpl>::__rsub__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRMulProtocolImpl>::__rmul__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRMatmulProtocolImpl>::__rmatmul__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRTruedivProtocolImpl>::__rtruediv__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRFloordivProtocolImpl>::__rfloordiv__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRModProtocolImpl>::__rmod__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRDivmodProtocolImpl>::__rdivmod__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRPowProtocolImpl>::__rpow__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRLShiftProtocolImpl>::__rlshift__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRRShiftProtocolImpl>::__rrshift__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRAndProtocolImpl>::__rand__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRXorProtocolImpl>::__rxor__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberROrProtocolImpl>::__ror__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberComplexProtocolImpl>::__complex__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyNumberRoundProtocolImpl>::__round__() {
|
||||
methods.push(def)
|
||||
}
|
||||
|
||||
methods
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberAddProtocolImpl {
|
||||
|
@ -1336,20 +1275,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRAddProtocolImpl {
|
||||
fn __radd__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRAddProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __radd__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback trait for nb_add
|
||||
trait PyNumberAddFallback {
|
||||
fn nb_add_fallback() -> Option<ffi::binaryfunc>;
|
||||
|
@ -1373,20 +1298,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[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>;
|
||||
}
|
||||
|
@ -1409,20 +1320,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRMulProtocolImpl {
|
||||
fn __rmul__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRMulProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rmul__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberMulFallback {
|
||||
fn nb_mul_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1445,20 +1342,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRMatmulProtocolImpl {
|
||||
fn __rmatmul__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRMatmulProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rmatmul__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberMatmulFallback {
|
||||
fn nb_matmul_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1481,20 +1364,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRTruedivProtocolImpl {
|
||||
fn __rtruediv__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRTruedivProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rtruediv__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberTruedivFallback {
|
||||
fn nb_truediv_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1517,20 +1386,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRFloordivProtocolImpl {
|
||||
fn __rfloordiv__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRFloordivProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rfloordiv__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberFloordivFallback {
|
||||
fn nb_floordiv_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1553,20 +1408,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRModProtocolImpl {
|
||||
fn __rmod__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRModProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rmod__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberModFallback {
|
||||
fn nb_mod_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1589,20 +1430,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRDivmodProtocolImpl {
|
||||
fn __rdivmod__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRDivmodProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rdivmod__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberDivmodFallback {
|
||||
fn nb_divmod_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1625,20 +1452,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRPowProtocolImpl {
|
||||
fn __rpow__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRPowProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rpow__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberPowFallback {
|
||||
fn nb_pow_fallback() -> Option<ffi::ternaryfunc>;
|
||||
}
|
||||
|
@ -1661,20 +1474,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRLShiftProtocolImpl {
|
||||
fn __rlshift__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRLShiftProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rlshift__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberLShiftFallback {
|
||||
fn nb_lshift_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1697,20 +1496,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRRShiftProtocolImpl {
|
||||
fn __rrshift__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRRShiftProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rrshift__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberRRshiftFallback {
|
||||
fn nb_rshift_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1733,20 +1518,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRAndProtocolImpl {
|
||||
fn __rand__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRAndProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rand__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberAndFallback {
|
||||
fn nb_and_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1769,20 +1540,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberRXorProtocolImpl {
|
||||
fn __rxor__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRXorProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __rxor__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberXorFallback {
|
||||
fn nb_xor_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1805,20 +1562,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyNumberROrProtocolImpl {
|
||||
fn __ror__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberROrProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __ror__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyNumberOrFallback {
|
||||
fn nb_or_fallback() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
@ -1995,29 +1738,3 @@ where
|
|||
py_unary_func!(PyNumberIndexProtocol, T::__index__)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyNumberComplexProtocolImpl {
|
||||
fn __complex__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberComplexProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __complex__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PyNumberRoundProtocolImpl {
|
||||
fn __round__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyNumberRoundProtocolImpl for T
|
||||
where
|
||||
T: PyNumberProtocol<'p>,
|
||||
{
|
||||
default fn __round__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)
|
||||
//!
|
||||
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::{ffi, PyClass, PyObject};
|
||||
|
||||
|
@ -89,17 +88,12 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
|
|||
#[doc(hidden)]
|
||||
pub trait PyAsyncProtocolImpl {
|
||||
fn tp_as_async() -> Option<ffi::PyAsyncMethods>;
|
||||
fn methods() -> Vec<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<T> PyAsyncProtocolImpl for T {
|
||||
default fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
|
||||
None
|
||||
}
|
||||
|
||||
default fn methods() -> Vec<PyMethodDef> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncProtocolImpl for T
|
||||
|
@ -114,20 +108,6 @@ where
|
|||
am_anext: Self::am_anext(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn methods() -> Vec<PyMethodDef> {
|
||||
let mut methods = Vec::new();
|
||||
|
||||
if let Some(def) = <Self as PyAsyncAenterProtocolImpl>::__aenter__() {
|
||||
methods.push(def)
|
||||
}
|
||||
if let Some(def) = <Self as PyAsyncAexitProtocolImpl>::__aexit__() {
|
||||
methods.push(def)
|
||||
}
|
||||
|
||||
methods
|
||||
}
|
||||
}
|
||||
|
||||
trait PyAsyncAwaitProtocolImpl {
|
||||
|
@ -227,29 +207,3 @@ mod anext {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait PyAsyncAenterProtocolImpl {
|
||||
fn __aenter__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncAenterProtocolImpl for T
|
||||
where
|
||||
T: PyAsyncProtocol<'p>,
|
||||
{
|
||||
default fn __aenter__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait PyAsyncAexitProtocolImpl {
|
||||
fn __aexit__() -> Option<PyMethodDef>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncAexitProtocolImpl for T
|
||||
where
|
||||
T: PyAsyncProtocol<'p>,
|
||||
{
|
||||
default fn __aexit__() -> Option<PyMethodDef> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ where
|
|||
// normal methods
|
||||
if !methods.is_empty() {
|
||||
methods.push(ffi::PyMethodDef_INIT);
|
||||
type_object.tp_methods = Box::into_raw(methods.into_boxed_slice()) as *mut _;
|
||||
type_object.tp_methods = Box::into_raw(methods.into_boxed_slice()) as _;
|
||||
}
|
||||
|
||||
// class attributes
|
||||
|
@ -197,7 +197,7 @@ where
|
|||
}
|
||||
if !props.is_empty() {
|
||||
props.push(ffi::PyGetSetDef_INIT);
|
||||
type_object.tp_getset = Box::into_raw(props.into_boxed_slice()) as *mut _;
|
||||
type_object.tp_getset = Box::into_raw(props.into_boxed_slice()) as _;
|
||||
}
|
||||
|
||||
// set type flags
|
||||
|
@ -264,33 +264,9 @@ fn py_class_method_defs<T: PyMethodsImpl>() -> (
|
|||
}
|
||||
}
|
||||
|
||||
for def in <T as class::basic::PyObjectProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def());
|
||||
}
|
||||
for def in <T as class::context::PyContextProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def());
|
||||
}
|
||||
for def in <T as class::mapping::PyMappingProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def());
|
||||
}
|
||||
for def in <T as class::number::PyNumberProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def());
|
||||
}
|
||||
for def in <T as class::descr::PyDescrProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def());
|
||||
}
|
||||
|
||||
py_class_async_methods::<T>(&mut defs);
|
||||
|
||||
(new, call, defs, attrs)
|
||||
}
|
||||
|
||||
fn py_class_async_methods<T>(defs: &mut Vec<ffi::PyMethodDef>) {
|
||||
for def in <T as class::pyasync::PyAsyncProtocolImpl>::methods() {
|
||||
defs.push(def.as_method_def());
|
||||
}
|
||||
}
|
||||
|
||||
fn py_class_properties<T: PyMethodsImpl>() -> Vec<ffi::PyGetSetDef> {
|
||||
let mut defs = std::collections::HashMap::new();
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
use pyo3::class::basic::CompareOp;
|
||||
use pyo3::class::*;
|
||||
use pyo3::prelude::*;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
use pyo3::class::{
|
||||
PyContextProtocol, PyIterProtocol, PyMappingProtocol, PyObjectProtocol, PySequenceProtocol,
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(specialization)]
|
||||
use std::collections::HashMap;
|
||||
|
||||
use pyo3::exceptions::KeyError;
|
||||
|
|
Loading…
Reference in a new issue