Make #[pymethods] aware of #[cfg]

This commit is contained in:
David Hewitt 2020-02-15 14:05:12 +00:00
parent 0b5918e94d
commit d5509424b2
3 changed files with 65 additions and 2 deletions

View File

@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719) * Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719)
* Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745) * Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745)
* Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760) * Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760)
* `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769)
### Removed ### Removed

View File

@ -21,11 +21,12 @@ pub fn build_py_methods(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
} }
pub fn impl_methods(ty: &syn::Type, impls: &mut Vec<syn::ImplItem>) -> syn::Result<TokenStream> { pub fn impl_methods(ty: &syn::Type, impls: &mut Vec<syn::ImplItem>) -> syn::Result<TokenStream> {
// get method names in impl block
let mut methods = Vec::new(); let mut methods = Vec::new();
let mut cfg_attributes = Vec::new();
for iimpl in impls.iter_mut() { for iimpl in impls.iter_mut() {
if let syn::ImplItem::Method(ref mut meth) = iimpl { if let syn::ImplItem::Method(ref mut meth) = iimpl {
methods.push(pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs)?); methods.push(pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs)?);
cfg_attributes.push(get_cfg_attributes(&meth.attrs));
} }
} }
@ -33,8 +34,18 @@ pub fn impl_methods(ty: &syn::Type, impls: &mut Vec<syn::ImplItem>) -> syn::Resu
pyo3::inventory::submit! { pyo3::inventory::submit! {
#![crate = pyo3] { #![crate = pyo3] {
type TyInventory = <#ty as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType; type TyInventory = <#ty as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;
<TyInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(#methods),*]) <TyInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(
#(#cfg_attributes)*
#methods
),*])
} }
} }
}) })
} }
fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec<&syn::Attribute> {
attrs
.iter()
.filter(|attr| attr.path.is_ident("cfg"))
.collect()
}

View File

@ -402,3 +402,54 @@ fn method_with_lifetime() {
"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]" "assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]"
); );
} }
#[pyclass]
#[cfg(unix)]
struct CfgStruct {}
#[pyclass]
#[cfg(not(unix))]
struct CfgStruct {}
#[pymethods]
#[cfg(unix)]
impl CfgStruct {
fn unix_method(&self) -> &str {
"unix"
}
#[cfg(not(unix))]
fn never_compiled_method(&self) {}
}
#[pymethods]
#[cfg(not(unix))]
impl CfgStruct {
fn not_unix_method(&self) -> &str {
"not unix"
}
#[cfg(unix)]
fn never_compiled_method(&self) {}
}
#[test]
fn test_cfg_attrs() {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new(py, CfgStruct {}).unwrap();
#[cfg(unix)]
{
py_assert!(py, inst, "inst.unix_method() == 'unix'");
py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')");
}
#[cfg(not(unix))]
{
py_assert!(py, inst, "not hasattr(inst, 'unix_method')");
py_assert!(py, inst, "inst.not_unix_method() == 'not unix'");
}
py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')");
}