Skip to content

Operator methods include a type signature of the additional overload #2277

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

AWhetter
Copy link
Contributor

@AWhetter AWhetter commented Jul 3, 2020

Closes #2269

@@ -250,6 +250,7 @@ class cpp_function : public function {
/* Generate a proper function signature */
std::string signature;
size_t type_index = 0, arg_index = 0;
std::string self_type("object");

This comment was marked as outdated.

signatures += "\n";
signatures += std::to_string(++index) + ". ";
signatures += rec->name;
signatures += "(self: " + self_type + ", other: object) -> NotImplemented\n";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although the type signature of an operator method is actually (*args: Any, **kwargs: Any) -> NotImplemented because pybind falls back to returning NotImplemented when all other type signatures fail, mypy is specifically looking for the signature implemented here. We could add an additional type signature (*args: Any, **kwargs: Any) -> NotImplemented for correctness as well but that feels like overkill to me?

@AWhetter
Copy link
Contributor Author

Is there anything that I can do to help progress this pull request?

Copy link
Collaborator

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

Thanks for the ping. There's just a ton of issues and pull requests open and stuff slips through sometimes.

This PR looks good to me.

@YannickJadoul
Copy link
Collaborator

Let's run such a thing past @wjakob, though.

@wjakob
Copy link
Member

wjakob commented Nov 5, 2020

(More of a general rant, not specifically about this commit -- apologies @AWhetter)
Not a big fan of this change -- it adds code to every pybind11 project that few users will ever care about (I e.g. don't want to pay for it in my own projects). IMO pybind11 docstrings are pretty good. Getting them to "flawless quality" is a dangerous project -- an an almost bottomless rabbithole: each patch just adds a little bit of bloat, there are many further such improvements that folks will submit in the future. I'd rather stop this here. For those who want flawless docstrings, my recommendation would be to fork the library and go the whole way there.

if (rec->is_method) {
signatures += "self: " + self_type + ", ";
}
signatures += "*args, **kwargs) -> NotImplemented\n";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Scrutinizing this again: NotImplemented is the value, and not the type, right. type(NotImplemented) prints <class 'NotImplementedType'> for me.

Also, is this the way it's done? Can you give me a reference of type annotations in pure Python code, perhaps?

Copy link
Contributor Author

@AWhetter AWhetter Nov 7, 2020

Choose a reason for hiding this comment

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

I think I had incorrectly assumed that being a singleton, that NotImplemented was treated like None and that you're allowed to supply it. In fact, mypy doesn't use or need it at all (python/mypy#6710 (comment)) and so it isn't often used. Given that comment, Any seems like the correct type to return?
Alternatively, we could combine the two signatures into one and simply say that the type of the second argument is always object, because it will always be accepted and mypy will assume that NotImplemented will be returned regardless. It's less useful for a user that way, but it resolves the original issue without much extra complexity in the implementation?

@YannickJadoul YannickJadoul modified the milestones: v2.6.1, v2.7 Nov 5, 2020
@AWhetter
Copy link
Contributor Author

AWhetter commented Nov 7, 2020

I will say that I'm not hugely invested in this change. While I made this for completeness and correctness, for the use case described in the original issue I don't think it's unreasonable to expect someone to have to go through the type stubs generated by stubgen after running it on a pybind module and having to manually curate the output. It does mean that the process goes from being automated to being more manual, but I think it's an acceptable workflow nonetheless.

Overall I still think I would prefer the original issue to be addressed. I think it's worthwhile documenting that you can supply anything to operator methods for users' sake. But it's not the end of the world if we decide not to address it.

@wjakob On the topic of bloat, do you mean bloat in terms of extra run time code, in code complexity, or in terms of final binary size?
I can reduce the size of the code change by half if I don't establish a type for self, which the type checking doesn't care about anyway (I had considered making a separate issue about this because it would reduce the size of docstrings slightly). I was aiming for consistency with the existing docstring output. But maybe that's a worthwhile tradeoff if we're looking to simplify this change?

@YannickJadoul
Copy link
Collaborator

@AWhetter, as far as I understood the main concern is a steady increase of the binary size, by a series of small, insignificant increases such as this one.

@AWhetter
Copy link
Contributor Author

AWhetter commented Nov 9, 2020

That makes sense. As mentioned in my previous comment, I can make this change smaller, but I get the impression that even that is too high a cost. I'm happy to close this and close the issue as wontfix if we think that's best?

@YannickJadoul
Copy link
Collaborator

I wouldn't mind keeping this open for now, and collect it somewhere, in case we would later find a way to opt-in to this.

@EricCousineau-TRI
Copy link
Collaborator

EricCousineau-TRI commented Apr 18, 2021

For objective measurement, c.f. see #2760

@henryiii henryiii modified the milestones: v2.7, v2.8 Jul 16, 2021
@henryiii henryiii modified the milestones: v2.8, v2.9 Oct 4, 2021
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.

Include "object" as an argument type in the type signature of operator methods
6 participants