Skip to content

Commit 45d892a

Browse files
authored
Merge pull request #769 from davidhewitt/cfg-attrs
Make #[pymethods] aware of #[cfg]
2 parents 0b5918e + d550942 commit 45d892a

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

CHANGELOG.md

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

3536
### Removed
3637

pyo3-derive-backend/src/pyimpl.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,31 @@ pub fn build_py_methods(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
2121
}
2222

2323
pub fn impl_methods(ty: &syn::Type, impls: &mut Vec<syn::ImplItem>) -> syn::Result<TokenStream> {
24-
// get method names in impl block
2524
let mut methods = Vec::new();
25+
let mut cfg_attributes = Vec::new();
2626
for iimpl in impls.iter_mut() {
2727
if let syn::ImplItem::Method(ref mut meth) = iimpl {
2828
methods.push(pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs)?);
29+
cfg_attributes.push(get_cfg_attributes(&meth.attrs));
2930
}
3031
}
3132

3233
Ok(quote! {
3334
pyo3::inventory::submit! {
3435
#![crate = pyo3] {
3536
type TyInventory = <#ty as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;
36-
<TyInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(#methods),*])
37+
<TyInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(
38+
#(#cfg_attributes)*
39+
#methods
40+
),*])
3741
}
3842
}
3943
})
4044
}
45+
46+
fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec<&syn::Attribute> {
47+
attrs
48+
.iter()
49+
.filter(|attr| attr.path.is_ident("cfg"))
50+
.collect()
51+
}

tests/test_methods.rs

+51
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,54 @@ fn method_with_lifetime() {
402402
"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]"
403403
);
404404
}
405+
406+
#[pyclass]
407+
#[cfg(unix)]
408+
struct CfgStruct {}
409+
410+
#[pyclass]
411+
#[cfg(not(unix))]
412+
struct CfgStruct {}
413+
414+
#[pymethods]
415+
#[cfg(unix)]
416+
impl CfgStruct {
417+
fn unix_method(&self) -> &str {
418+
"unix"
419+
}
420+
421+
#[cfg(not(unix))]
422+
fn never_compiled_method(&self) {}
423+
}
424+
425+
#[pymethods]
426+
#[cfg(not(unix))]
427+
impl CfgStruct {
428+
fn not_unix_method(&self) -> &str {
429+
"not unix"
430+
}
431+
432+
#[cfg(unix)]
433+
fn never_compiled_method(&self) {}
434+
}
435+
436+
#[test]
437+
fn test_cfg_attrs() {
438+
let gil = Python::acquire_gil();
439+
let py = gil.python();
440+
let inst = Py::new(py, CfgStruct {}).unwrap();
441+
442+
#[cfg(unix)]
443+
{
444+
py_assert!(py, inst, "inst.unix_method() == 'unix'");
445+
py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')");
446+
}
447+
448+
#[cfg(not(unix))]
449+
{
450+
py_assert!(py, inst, "not hasattr(inst, 'unix_method')");
451+
py_assert!(py, inst, "inst.not_unix_method() == 'not unix'");
452+
}
453+
454+
py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')");
455+
}

0 commit comments

Comments
 (0)