-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Support for overloaded functions in stubgenc generated by pybind11 #5975
Support for overloaded functions in stubgenc generated by pybind11 #5975
Conversation
I presume you mean that stubgenc should produce such a stub, and this PR implements that behavior? (We prefer our commit messages to describe the change rather than the new state of affairs.) I will try to review soon, but I think this has missed the train for the upcoming 0.650 release (see #5960). |
Ok, updated description. |
Hm... Having looked at this a bit more, it really feels like string partitioning is a pretty poor way of parsing something of this complexity. I realize that all of stubgen looks like a hack, but since you are doing your best to make it better, perhaps you can improve the approach to parsing a bit more? Maybe write a tiny recursive-descent parser, using the |
Thank you for pointing me to I'll start with replacing parsing docstring function declarations. Though quick scan of the code suggests, that some regex usage will remain in the stubgenc/stubutil. |
Sounds like a plan!
|
Hey @wiktorn, just to let you know, we're planning fairly extensive refactorings of part of stubgen, however, we don't expect the docstring parsing to be affected, so don't worry! |
Thank you for the heads up @gvanrossum . I'll finally have more time next week to polish this PR. |
@gvanrossum Can you trigger another AppVeyor build? My guess that this failure was totally unrelated to my changes (some exceptions in IPC and ast3 module that are not mentioned in this changes) |
@wiktorn if you rebase on master those errors should go away. |
1530871
to
ae08bd3
Compare
Sorry I haven't got to review this yet! I missed that you had updated it because you used Note that when #6256 lands this will become one big merge conflict, but according to Ivan it's easy to resolve -- he just moved all the docstring parsing logic to a new file, stubdoc.c. |
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.
Here are a few review comments anyway. Sorry again!
I hope that's ok right now. Just let me know how you want to move forward. Shall I till #6256 lands in master and merge master back to this branch? Sorry for the force push, that's how I understood @ethanhs and since there was no comments on code yet, I've decided to rebase instead of merging master |
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.
LG! This looks ready to merge.
I'm leaving it up to @ilevkivskyi which one to merge first: this one (then he has to merge your code back into #6256) or the latter (leaving the merge up to you).
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.
I would be glad to merge this before my PR, but I have a bunch of additional comments.
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 looks like there are bunch of comments from my previous review that are not implemented. I tried to explain some of them more, in case you didn't understand what to do. Are you going to implement them?
If no, I would probably merge this anyway and fix them myself, but it would be better if you can do this.
mypy/stubgenc.py
Outdated
if name == 'getitem': | ||
return '(index)' | ||
return [TypedArgSig(name='index', type=None, default=False)] |
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.
If you would use normal classes instead of named tuples you could define __init__
as:
def __init__(self, name: str, type: Optional[str] = None, default: bool = False) -> None: ...
and then this an d a dozen others will be just TypedArgSig('index')
.
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.
Also with normal classes you can define __repr__()
, to simplify test cases significantly. You can just check that str(<generated signature>)
matches an expected string.
mypy/stubgenc.py
Outdated
return [ | ||
TypedArgSig(name='name', type=None, default=False), | ||
TypedArgSig(name='value', type=None, default=False) | ||
] |
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.
For multiline we use this style:
return [TypedArgSig(name='name', type=None, default=False),
TypedArgSig(name='value', type=None, default=False)]
(also many of these will not need to be multiline if you implement the suggestion above).
TypedArgSig -> ArgSig TypedFunctionSig -> FunctionSig
I've missed your comments on conversation tab on GitHub. As I reviewed changes I found your comments and started to address them. |
@wiktorn Currently there is one more big change that I proposed: switch from named tuples to normal classes, see #5975 (comment) and #5975 (comment) After that you could also remove redundant class ArgSig:
...
def __repr__(self) -> str:
r = self.name
if self.type:
r += ': ' + self.type
if self.default:
r += ' = ...' if self.type else '=...'
return r
class FunctionSig:
...
def __repr__(self) -> str:
args = ','.join([str(arg) for arg in self.args])
return '{}({}) -> {}: ...' Then many tests can be simplified to just check the string representation of the result. You can still define |
(also there is a lint failure now) |
And what do you think about this approach:
As far as I see, it works in Python3.4, and once oldest supported version will be 3.7, we can move this declaration to NamedTuple call itself. I'm reluctant to use |
With this call sites will not type-check by mypy.
Why? If you just want to be sure it is clear from the string form it is a custom class, use something like |
As I'm testing it right now, it rather doesn't pass self-check: Though it properly detects problems in call sites
So I'll convert them to normal classes.
We could actually have |
I meant that mypy will flag as errors the calls with less arguments like
OK
Yes, this could be useful only for testing. Anyway, I don't insist on this. You can just define |
Create ArgList class instead of NamedTuple and provide defaults for type and default
I did not add defaults to |
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.
OK, I am going to merge this now. There are some minor formatting changes, but I will take care of those.
@wiktorn Thanks for contributing! I have successfully merged my PR on top for yours. |
Thank you for your patience @ilevkivskyi and help with getting this merged. |
For overloaded methods pybind generates following docstring:
For such docstrings stubgenc currently produces following stub:
With this change stubgenc will generate following stub:
This pull request introduces:
infer_sig_from_docstring
now returns list ofFunctionSig
. List contains one object when function is not overloaded, more objects - when it's overloaded. Each object represents signature of function.infer_arg_sig_from_docstring
is a new function that parses argument list for function in docstring. As the type information may contain commas, the code checks, if the comma is outside brackets. I tried to approach that with regex and failed, also tried to useast
module, but its not straightforward to move from ast form back to source code form that's why I settled with naive approach, as this is not performance critical path. Tests for edge cases included intest_infer_sig_from_docstring