From 71abeeff8b13da998736bdbb77f78bb22456a517 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 24 May 2022 07:38:41 +0100 Subject: [PATCH] macros: fix raw-ident pyclasses having r# at the start of the Python name --- CHANGELOG.md | 1 + pyo3-macros-backend/src/method.rs | 6 +++++- pyo3-macros-backend/src/pyclass.rs | 8 +++++--- pyo3-macros-backend/src/pyfunction.rs | 4 +++- pyo3-macros-backend/src/utils.rs | 6 ++++-- tests/test_methods.rs | 1 + 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a184d25..ccc72da7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed incorrectly disabled FFI definition `PyThreadState_DeleteCurrent`. [#2357](https://github.com/PyO3/pyo3/pull/2357) - Correct FFI definition `PyEval_EvalCodeEx` to take `*const *mut PyObject` array arguments instead of `*mut *mut PyObject` (this was changed in CPython 3.6). [#2368](https://github.com/PyO3/pyo3/pull/2368) +- Fix "raw-ident" structs (e.g. `#[pyclass] struct r#RawName`) incorrectly having `r#` at the start of the class name created in Python. [#2395](https://github.com/PyO3/pyo3/pull/2395) ## [0.16.5] - 2022-05-15 diff --git a/pyo3-macros-backend/src/method.rs b/pyo3-macros-backend/src/method.rs index e25575c1..c095c23c 100644 --- a/pyo3-macros-backend/src/method.rs +++ b/pyo3-macros-backend/src/method.rs @@ -1,5 +1,7 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +use std::borrow::Cow; + use crate::attributes::TextSignatureAttribute; use crate::deprecations::Deprecation; use crate::params::{accept_args_kwargs, impl_arg_params}; @@ -287,7 +289,9 @@ impl<'a> FnSpec<'a> { let doc = utils::get_doc( meth_attrs, - text_signature.as_ref().map(|attr| (&python_name, attr)), + text_signature + .as_ref() + .map(|attr| (Cow::Borrowed(&python_name), attr)), ); let arguments: Vec<_> = if skip_first_arg { diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs index d421acf5..a47004bc 100644 --- a/pyo3-macros-backend/src/pyclass.rs +++ b/pyo3-macros-backend/src/pyclass.rs @@ -1,5 +1,7 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +use std::borrow::Cow; + use crate::attributes::{ self, kw, take_pyo3_options, CrateAttribute, ExtendsAttribute, FreelistAttribute, ModuleAttribute, NameAttribute, NameLitStr, TextSignatureAttribute, @@ -282,12 +284,12 @@ impl FieldPyO3Options { } } -fn get_class_python_name<'a>(cls: &'a syn::Ident, args: &'a PyClassArgs) -> &'a syn::Ident { +fn get_class_python_name<'a>(cls: &'a syn::Ident, args: &'a PyClassArgs) -> Cow<'a, syn::Ident> { args.options .name .as_ref() - .map(|name_attr| &name_attr.value.0) - .unwrap_or(cls) + .map(|name_attr| Cow::Borrowed(&name_attr.value.0)) + .unwrap_or_else(|| Cow::Owned(cls.unraw())) } fn impl_class( diff --git a/pyo3-macros-backend/src/pyfunction.rs b/pyo3-macros-backend/src/pyfunction.rs index f8c53b5c..c4403a40 100644 --- a/pyo3-macros-backend/src/pyfunction.rs +++ b/pyo3-macros-backend/src/pyfunction.rs @@ -1,5 +1,7 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +use std::borrow::Cow; + use crate::{ attributes::{ self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute, @@ -408,7 +410,7 @@ pub fn impl_wrap_pyfunction( options .text_signature .as_ref() - .map(|attr| (&python_name, attr)), + .map(|attr| (Cow::Borrowed(&python_name), attr)), ); let krate = get_pyo3_crate(&options.krate); diff --git a/pyo3-macros-backend/src/utils.rs b/pyo3-macros-backend/src/utils.rs index 471c40d2..25743562 100644 --- a/pyo3-macros-backend/src/utils.rs +++ b/pyo3-macros-backend/src/utils.rs @@ -1,7 +1,9 @@ +use std::borrow::Cow; + // Copyright (c) 2017-present PyO3 Project and Contributors use proc_macro2::{Span, TokenStream}; use quote::ToTokens; -use syn::spanned::Spanned; +use syn::{spanned::Spanned, Ident}; use crate::attributes::{CrateAttribute, TextSignatureAttribute}; @@ -66,7 +68,7 @@ pub struct PythonDoc(TokenStream); /// e.g. concat!("...", "\n", "\0") pub fn get_doc( attrs: &[syn::Attribute], - text_signature: Option<(&syn::Ident, &TextSignatureAttribute)>, + text_signature: Option<(Cow<'_, Ident>, &TextSignatureAttribute)>, ) -> PythonDoc { let mut tokens = TokenStream::new(); let comma = syn::token::Comma(Span::call_site()); diff --git a/tests/test_methods.rs b/tests/test_methods.rs index 75b960cd..81e09fca 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -902,6 +902,7 @@ impl r#RawIdents { fn test_raw_idents() { Python::with_gil(|py| { let raw_idents_type = py.get_type::(); + assert_eq!(raw_idents_type.name().unwrap(), "RawIdents"); py_run!( py, raw_idents_type,