-
Notifications
You must be signed in to change notification settings - Fork 769
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
add #[text_signature = "..."] attribute #675
Conversation
Thank you.
>>> from rustapi_module.buf_and_str import BytesExtractor
>>> b = BytesExtractor()
>>> b.__doc__
'This is for confirming that PyBuffer does not cause memory leak' So I think what this PR should do is just filling out
|
Yes, I am building this pull request on top of the existing doc comment machinery (and improving error handling too by using
Being able to set
This feature is useful when you don't want the special
This also does some checks to make sure the provided signature is valid enough to actually be put in This is also useful because the /// my really long docs for `my_fn`
/// that cover many
/// many lines
#[pyfunction(b = 2, "*", c = "None")]
#[text_signature = "my_fn(a, b=2, *, c=None)"]
/// more docs here
fn my_fn(a: &str, b: i32, c: Option<u32>) -> i16 {
unimplemented!()
} This also is much nicer when you want to have #[pyfunction]
#[text_signature = "no_docs()"] // simple
fn no_docs() {} vs. // hope this is right -- easy to mess up:
// must have exactly 2 trailing "\n"
/// no_docs()
/// --
///
///
#[pyfunction]
fn no_docs() {} Additional useful property: should CPython (or any other supported Python interpreter) switch to getting When the code to implement automatically generating |
I think this makes a lot of sense since it gives a clear way to provide |
That's part of why I ended up picking |
@programmerjake
These are all good.
Is it a proper/efficient way to provide In [15]: object.__signature__
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-e544111936b4> in <module>
----> 1 object.__signature__
AttributeError: type object 'object' has no attribute '__signature__'
In [16]: list.__signature__
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-27c4b7eaead5> in <module>
----> 1 list.__signature__
AttributeError: type object 'list' has no attribute '__signature__' I think what we need for type-annotation is just fill out the And... |
Yeah, but that's probably quite a bit harder to implement, so
I don't think so, it didn't work with argument annotations when I tried; a return type annotation causes CPython to not detect the signature ( In the latest CPython git,
Yes,
yes, but it's probably also much harder to implement, hence why |
Unfortunately not, see #305, python#3208 amd #510 (comment).
Imo we should eventually autogenerate the text signature, even though this is pratically useful intermediate step. How does this currently interact with rustdoc, i.e. does the signature show up when running |
Agreed, though I don't think we should remove
I haven't tested it yet, but the signature shouldn't show up in the Rust doc-string. It will show up as a |
I finished adding tests and documentation. I switched the syntax for #[pyfunction(a, b, c=3, "*", d=4, e=5]
// doesn't have function name in text_signature
#[text_signature = "(a, b, c=3, *, d=4, e=5)"]
fn my_function(a: i32, b: i32, c: i32, d: i32, e: i32) -> i32 {
a + b + c + d + e
} rather than #[pyfunction(a, b, c=3, "*", d=4, e=5]
#[text_signature = "my_function(a, b, c=3, *, d=4, e=5)"]
fn my_function(a: i32, b: i32, c: i32, d: i32, e: i32) -> i32 {
a + b + c + d + e
} |
This comment has been minimized.
This comment has been minimized.
pyo3-derive-backend/src/pymethod.rs
Outdated
FnType::Fn | FnType::PySelf(_) | FnType::FnClass | FnType::FnStatic => { | ||
utils::parse_text_signature_attrs(&mut *meth_attrs, name)? | ||
} | ||
FnType::FnNew => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These three patterns do almost the same thing and thus we should shorten the code.
E.g.,
FnType::FnNew | FnType::FnCall |.. => {
if let Some(type_signature) = utils::parse_text_signature_attrs(
&mut *meth_attrs,
name
)? {
return Err(syn::Error::new_spanned(
type_signature,
"type_signature not allowed to use here",
));
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the name does need some translation for __new__
and __call__
, so it would probably be just as many lines and be more complex to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then you can use macro or closure to construct an error.
I didn't want to say 'you should treat all errors as the same', but this kind of common error throwing code should be packed compactly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
pyo3-derive-backend/src/pymethod.rs
Outdated
)? { | ||
return Err(syn::Error::new_spanned( | ||
type_signature, | ||
"type_signature not allowed on __new__, put it on the struct definition instead", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put it on the struct definition instead
What does this mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it means that instead of writing:
#[pyclass]
struct MyClass {
}
#[pymethods]
impl MyClass {
#[new]
#[text_signature = "(a, b, c)"]
fn new(...) {...}
}
This should be written instead:
#[pyclass]
#[text_signature = "(a, b, c)"]
struct MyClass {
}
#[pymethods]
impl MyClass {
#[new]
fn new(...) {...}
}
Do you have any suggestions for how to rephrase the error message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[pyclass]
#[text_signature = "(a, b, c)"]
struct MyClass {
}
So this (a, b, c)
is a signature of __init__
?
Then I suggest adding 'If you want to add a signature to __init__
, '
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, though I used __new__
instead of __init__
since PyO3 doesn't support __init__
Thank you. |
Thank you, it's a pretty good feature! |
Is the notation with the default values in the signature actually supported or was it dropped? |
There is a test for that still present here: pyo3/tests/test_text_signature.rs Line 104 in 9ea4733
|
Based on design at #310 (comment)
Just implemented parsing
#[text_signature = "..."]
and adding to generated doc strings.Still need to add docs, tests, changelog entries, etc.
Demo code: