Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error on passing arguments to #[new] and similar attributes #3484

Merged
merged 2 commits into from
Oct 8, 2023

Conversation

davidhewitt
Copy link
Member

This PR reworks #[new] to reject additional arguments rather than ignore them, as noted in #3475 (comment)

We could change in the future to allow #[new(signature = ())] to be equivalent to #[new] #[pyo3(signature = ())] if desired, as a backwards-compatible change.

The bulk of the diff is because I threw out the old implementation of parse_method_attributes to make it compose better for the error messages I wanted to emit.

Comment on lines +678 to +716
let meta = &attr.meta;
let path = meta.path();

if path.is_ident("new") {
ensure_no_arguments(meta, "new")?;
Ok(Some(MethodTypeAttribute::New(path.span())))
} else if path.is_ident("__new__") {
// TODO deprecate this form?
ensure_no_arguments(meta, "__new__")?;
Ok(Some(MethodTypeAttribute::New(path.span())))
} else if path.is_ident("classmethod") {
ensure_no_arguments(meta, "classmethod")?;
Ok(Some(MethodTypeAttribute::ClassMethod(path.span())))
} else if path.is_ident("staticmethod") {
ensure_no_arguments(meta, "staticmethod")?;
Ok(Some(MethodTypeAttribute::StaticMethod(path.span())))
} else if path.is_ident("classattr") {
ensure_no_arguments(meta, "classattr")?;
Ok(Some(MethodTypeAttribute::ClassAttribute(path.span())))
} else if path.is_ident("getter") {
let name = extract_name(meta, "getter")?;
Ok(Some(MethodTypeAttribute::Getter(path.span(), name)))
} else if path.is_ident("setter") {
let name = extract_name(meta, "setter")?;
Ok(Some(MethodTypeAttribute::Setter(path.span(), name)))
} else {
Ok(None)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is essentially the new logic for these #[pymethods] attributes.

Comment on lines +684 to +698
} else if path.is_ident("__new__") {
// TODO deprecate this form?
ensure_no_arguments(meta, "__new__")?;
Ok(Some(MethodTypeAttribute::New(path.span())))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered #[__new__] is a valid attribute in our code, I think as this is undocumented and redundant with #[new] we should deprecate it.

Comment on lines +4 to +5
11 | #[getter(number)]
| ^^^^^^
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test changed from erroring on the first of two attributes which specify name (#[pyo3(name = "num")] to erroring on the second site (#[getter(number)]`). Functionally no different as the code is rejected either way.

Copy link
Member

@mejrs mejrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!. I also like this implementation better.

pyo3-macros-backend/src/method.rs Outdated Show resolved Hide resolved
pyo3-macros-backend/src/method.rs Show resolved Hide resolved
pyo3-macros-backend/src/method.rs Outdated Show resolved Hide resolved
/// `#[new]`
New,
/// `#[new]` && `#[classmethod]`
NewClassMethod,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the thought behind yeeting the NewClassMethod variant? I have no particular opinion - just curious.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of the complexity from the old implementation came from the need to work out when this variant was being built out of the two attributes. By removing it and instead pattern matching this combination I think the code reads better.

Some(MethodTypeAttribute::StaticMethod) => (FnType::FnStatic, false, None),
Some(MethodTypeAttribute::ClassAttribute) => (FnType::ClassAttribute, false, None),
Some(MethodTypeAttribute::New) | Some(MethodTypeAttribute::NewClassMethod) => {
let (fn_type, skip_first_arg, fixed_convention) = match method_attributes.as_mut_slice() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO skip_first_arg should really be a boolean-like enum, there are too many trues and falses in here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree but I'll deal with that in a follow-up PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I pushed a second commit to address this, which moves this to be a method on the FnType enum.

tests/ui/invalid_pymethods.stderr Show resolved Hide resolved
@davidhewitt
Copy link
Member Author

Thanks for the review, force-pushed to apply all suggestions.

@davidhewitt
Copy link
Member Author

@mejrs anything further you would like to see in this PR?

@davidhewitt
Copy link
Member Author

I'm going to assume this is now ok to merge; if there is more you wanted please forgive me and I'll happily follow up 🙏

@davidhewitt davidhewitt added this pull request to the merge queue Oct 5, 2023
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Oct 5, 2023
@davidhewitt davidhewitt added this pull request to the merge queue Oct 8, 2023
Merged via the queue into PyO3:main with commit 234c7b3 Oct 8, 2023
32 checks passed
@davidhewitt davidhewitt deleted the new-no-arguments branch October 8, 2023 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants