From d11943ab6dadf7f157510428add58d96c1cf45e1 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Thu, 8 Jul 2021 23:41:24 +0100 Subject: [PATCH] macros-backend: don't error on #[doc(hidden)] --- CHANGELOG.md | 8 +++++- pyo3-macros-backend/src/utils.rs | 46 +++++++++++++++++++------------- tests/test_module.rs | 14 ++++++++++ 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07632a0c9c5..f0c0abbcbbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,17 @@ PyO3 versions, please see the [migration guide](https://pyo3.rs/main/migration.h The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +- Fix regression in 0.14.0 rejecting usage of `#[doc(hidden)]` on structs and functions annotated with PyO3 macros. [#1722](https://github.com/PyO3/pyo3/pull/1722) + ## [0.14.1] - 2021-07-04 ### Added -- Implement `IntoPy` for `&PathBuf` and `&OsString`. [#1721](https://github.com/PyO3/pyo3/pull/1712) +- Implement `IntoPy` for `&PathBuf` and `&OsString`. [#1712](https://github.com/PyO3/pyo3/pull/1712) ### Fixed diff --git a/pyo3-macros-backend/src/utils.rs b/pyo3-macros-backend/src/utils.rs index 101a9b05a00..9ff259d961e 100644 --- a/pyo3-macros-backend/src/utils.rs +++ b/pyo3-macros-backend/src/utils.rs @@ -75,25 +75,19 @@ pub fn get_doc( for attr in attrs.iter() { if attr.path.is_ident("doc") { - match attr.parse_meta()? { - syn::Meta::NameValue(syn::MetaNameValue { - lit: syn::Lit::Str(litstr), - .. - }) => { - if first { - first = false; - span = litstr.span(); - } - let d = litstr.value(); - doc.push_str(separator); - if d.starts_with(' ') { - doc.push_str(&d[1..d.len()]); - } else { - doc.push_str(&d); - }; - separator = "\n"; + if let Ok(DocArgs { _eq_token, lit_str }) = syn::parse2(attr.tokens.clone()) { + if first { + first = false; + span = lit_str.span(); } - _ => bail_spanned!(attr.span() => "invalid doc comment"), + let d = lit_str.value(); + doc.push_str(separator); + if d.starts_with(' ') { + doc.push_str(&d[1..d.len()]); + } else { + doc.push_str(&d); + }; + separator = "\n"; } } } @@ -103,6 +97,22 @@ pub fn get_doc( Ok(syn::LitStr::new(&doc, span)) } +struct DocArgs { + _eq_token: syn::Token![=], + lit_str: syn::LitStr, +} + +impl syn::parse::Parse for DocArgs { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let this = Self { + _eq_token: input.parse()?, + lit_str: input.parse()?, + }; + ensure_spanned!(input.is_empty(), input.span() => "expected end of doc attribute"); + Ok(this) + } +} + pub fn ensure_not_async_fn(sig: &syn::Signature) -> syn::Result<()> { if let Some(asyncness) = &sig.asyncness { bail_spanned!( diff --git a/tests/test_module.rs b/tests/test_module.rs index bd6a5528aea..18efb5bf017 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -451,3 +451,17 @@ fn test_module_with_deprecated_name() { py_assert!(py, m, "m.__name__ == 'custom_name'"); }) } + +#[test] +fn test_module_doc_hidden() { + #[doc(hidden)] + #[pymodule] + fn my_module(_py: Python, _m: &PyModule) -> PyResult<()> { + Ok(()) + } + + Python::with_gil(|py| { + let m = pyo3::wrap_pymodule!(my_module)(py); + py_assert!(py, m, "m.__doc__ == ''"); + }) +}