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

fix(types): render typed iterators in make_*iterator doc #4876

Merged
merged 1 commit into from
Oct 17, 2023

Conversation

sizmailov
Copy link
Contributor

@sizmailov sizmailov commented Oct 8, 2023

Description

Render typed iterators for make_iterator, make_key_iterator, make_value_iterator.

Example:

from pybind11_tests import sequences_and_iterators as m
print(m.IntPairs.nonref.__doc__.strip())

### Output ###

# current master:
nonref(self: pybind11_tests.sequences_and_iterators.IntPairs) -> Iterator
# this PR:
nonref(self: pybind11_tests.sequences_and_iterators.IntPairs) -> Iterator[tuple[int, int]]

The benchmark shows no measurable differences in runtime performance.

bench.py

import timeit
from pybind11_tests import sequences_and_iterators as m

pairs = m.IntPairs([])
repeat = 1000000
print(timeit.timeit(lambda: pairs.nonref(), number=repeat))
print(timeit.timeit(lambda: pairs.nonref_keys(), number=repeat))
print(timeit.timeit(lambda: pairs.nonref_values(), number=repeat))
print(timeit.timeit(lambda: pairs.simple_iterator(), number=repeat))
print(timeit.timeit(lambda: pairs.simple_keys(), number=repeat))
print(timeit.timeit(lambda: pairs.simple_values(), number=repeat))

The module size is increased by 8192 bytes (~0.2%):

du -b pybind11_tests.cpython-310-x86_64-linux-gnu.so
# current master:
3605824 ./pybind11_tests.cpython-310-x86_64-linux-gnu.so
# this PR
3614016 ./pybind11_tests.cpython-310-x86_64-linux-gnu.so

Previous attempts to address the same issue:

#2244
#2371

Suggested changelog entry:

Render typed iterators for ``make_iterator``, ``make_key_iterator``, ``make_value_iterator``

Copy link
Collaborator

@rwgk rwgk left a comment

Choose a reason for hiding this comment

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

Looks good to me. It's a very small change, based on what we have now.

@rwgk
Copy link
Collaborator

rwgk commented Oct 16, 2023

FYI: I just initiated Google-global testing for this PR.

Mainly to see how many stubgen-generated .pyi files need to be updated.

BTW: When I deployed PRs #4831 & #4833 (in one combined update) I had to update 50 .pyi around the codebase, which was very unusual, but also not surprising (because #4833 changed List to list etc.).

@rwgk
Copy link
Collaborator

rwgk commented Oct 17, 2023

FYI: I just initiated Google-global testing for this PR.

I will have to update 2 .pyi files. I inspected the auto-generated changes and they look like a nice cleanup, e.g.

-    def keys(self) -> Iterator: ...
-    def values(self) -> Iterator: ...
+    def keys(self) -> Iterator[str]: ...
+    def values(self, *args, **kwargs) -> Any: ...
-    def __iter__(self) -> Iterator: ...
+    def __iter__(self) -> Any: ...

I'll go ahead with merging this PR.

@rwgk rwgk merged commit 74439a6 into pybind:master Oct 17, 2023
85 checks passed
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Oct 17, 2023
@rwgk
Copy link
Collaborator

rwgk commented Oct 17, 2023

Note for completeness:

The

🐍 3.9-dbg (deadsnakes) • Valgrind • x64

CI failure is unrelated. First observed 2023-10-16 (yesterday).

@sizmailov
Copy link
Contributor Author

@rwgk Thank you!

TBH I expected more files to be affected. Probably Google's code base does not expose many iterators.

The diff doesn't look like a 100% improvement to me.

The following stub got worse, but it's an issue of binding code, not pybind11.

-    def values(self) -> Iterator: ...
+    def values(self, *args, **kwargs) -> Any: ...

I would speculate that the snippet was generated by an older version of pybind11-stubgen and actual docstring contains raw C++ type, e.g.

def values(self) -> Iterator[std::complex<double>]

I have no good guess what happened to __iter__.

@rwgk
Copy link
Collaborator

rwgk commented Oct 18, 2023

they look like a nice cleanup, e.g.

Oof ... I was looking at it wrong, thanks for pointing out that this went the wrong way.

According to metadata that are usually very reliable we're using mypy at this commit:

python/mypy@de4f2ad

That's from Aug 11, 2023, just 2 months ago.

This is what the __doc__ looks like (manually simplified):

__iter__(self: x.y.z.UserTypeA) -> Iterator[tuple[str, cpp_namespace::UserTypeB]]

Could it be that :: in the name confuse stubgen?

@sizmailov
Copy link
Contributor Author

The C++ signatures in docstrings should be fixed on the binding code side:
https://pybind11.readthedocs.io/en/latest/advanced/misc.html#avoiding-c-types-in-docstrings

I don't how mypy.stubgen handles C++ signatures, probably the same way as pybind11-stubgen.

Yes, :: and angle brackets should make any stubgen unhappy.

@sizmailov sizmailov deleted the typed-make-iterator branch October 18, 2023 05:53
@rwgk
Copy link
Collaborator

rwgk commented Oct 18, 2023

The C++ signatures in docstrings should be fixed on the binding code side:

Thanks for the pointer. I'll relay that to the owners of the code.

@rwgk
Copy link
Collaborator

rwgk commented Oct 18, 2023

Thanks for the pointer. I'll relay that to the owners of the code.

It's coming straight back at me like a boomerang:

  1. https://github.com/pybind/pybind11_protobuf/blob/6c081a7581e34d2f46cb9a6484eb88b5ba62f03f/pybind11_protobuf/proto_caster_impl.h#L193

  2. std::string tname(t->name());
    detail::clean_type_id(tname);
    signature += tname;

What could we do there (in pybind11/pybind11.h)?

@sizmailov
Copy link
Contributor Author

What pybind11 does in the cited snippet above makes perfect sense. I don't think we should change that.

I believe it should be fixed on the pybind11_protobuf side.

If we are talking about fixing .pyi stubs files only and keeping C++ in docstrings, replacing C++ types can be done at the stubs parsing/post-processing stage.

@rwgk
Copy link
Collaborator

rwgk commented Oct 19, 2023

@sizmailov wrote:

I believe it should be fixed on the pybind11_protobuf side.

That's not possible: the Python name is not known at compile time (type_caster name is a constexpr).

After turning this over in my mind, discarding several ideas, and asking my team mates for advice, I landed on this:

#4888

It's probably best to continue the discussion there.

@henryiii henryiii changed the title Render typed iterators in make_*iterator doc fix(types): render typed iterators in make_*iterator doc Nov 15, 2023
@Skylion007
Copy link
Collaborator

We should have added the test from this issue: #4100 Can we verify we did not accidentally reintroduce this problem?

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.

4 participants