Skip to content

Commit

Permalink
Merge pull request #769 from davidhewitt/cfg-attrs
Browse files Browse the repository at this point in the history
Make #[pymethods] aware of #[cfg]
  • Loading branch information
kngwyu authored Feb 15, 2020
2 parents 0b5918e + d550942 commit 45d892a
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
* 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)
* `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769)

### Removed

Expand Down
15 changes: 13 additions & 2 deletions pyo3-derive-backend/src/pyimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,31 @@ 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> {
// get method names in impl block
let mut methods = Vec::new();
let mut cfg_attributes = Vec::new();
for iimpl in impls.iter_mut() {
if let syn::ImplItem::Method(ref mut meth) = iimpl {
methods.push(pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs)?);
cfg_attributes.push(get_cfg_attributes(&meth.attrs));
}
}

Ok(quote! {
pyo3::inventory::submit! {
#![crate = pyo3] {
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()
}
51 changes: 51 additions & 0 deletions tests/test_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,54 @@ fn method_with_lifetime() {
"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')");
}

0 comments on commit 45d892a

Please sign in to comment.