-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
feat: make stl.h list|set|map_caster
more user friendly.
#4686
Merged
Merged
Changes from 49 commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
d2a36d9
Add `test_pass_std_vector_int()`, `test_pass_std_set_int()` in test_stl
7d30378
Change `list_caster` to also accept generator objects (`PyGen_Check(s…
039d1b7
Drop in (currently unpublished) PyCLIF code, use in `list_caster`, ad…
bdba857
Use `PyObjectTypeIsConvertibleToStdSet()` in `set_caster`, adjust tests.
ec50ca0
Use `PyObjectTypeIsConvertibleToStdMap()` in `map_caster`, add tests.
eeb59af
Simplify `list_caster` `load()` implementation, push str/bytes check …
3631886
clang-tidy cleanup with a few extra `(... != 0)` to be more consistent.
b4f767b
Also use `PyObjectTypeIsConvertibleToStdVector()` in `array_caster`.
42e22d7
Merge branch 'master' into list_caster_pass_generator
9647a92
Merge branch 'master' into list_caster_pass_generator
1ed90cf
Merge branch 'master' into list_caster_pass_generator
3cc034b
Update comment pointing to clif/python/runtime.cc (code is unchanged).
18c4153
Merge branch 'master' into list_caster_pass_generator
e7330f2
Comprehensive test coverage, enhanced set_caster load implementation.
da29bf5
Resolve clang-tidy eror.
1fa338e
Add a long C++ comment explaining what led to the `PyObjectTypeIsConv…
6b5c780
Minor function name change in test.
9150a88
Merge branch 'master' into list_caster_pass_generator
62fda81
Merge branch 'master' into list_caster_pass_generator
4b25f74
strcmp -> std::strcmp (thanks @Skylion007 for catching this)
3cfc95b
Add `PyCallable_Check(items)` in `PyObjectTypeIsConvertibleToStdMap()`
59509f2
Resolve clang-tidy error
903faac
Merge branch 'master' into list_caster_pass_generator
4ab40d7
Use `PyMapping_Items()` instead of `src.attr("items")()`, to be inter…
5f7c9d4
Update link to PyCLIF sources.
ccfeb02
Fix typo (thanks @wangxf123456 for catching this)
6c1ec6a
Merge branch 'master' into list_caster_pass_generator
cc4d69c
Merge branch 'master' into list_caster_pass_generator
dacb827
Add `test_pass_std_vector_int()`, `test_pass_std_set_int()` in test_stl
3fc2d2a
Change `list_caster` to also accept generator objects (`PyGen_Check(s…
ff0724f
Drop in (currently unpublished) PyCLIF code, use in `list_caster`, ad…
be02291
Use `PyObjectTypeIsConvertibleToStdSet()` in `set_caster`, adjust tests.
0a79f55
Use `PyObjectTypeIsConvertibleToStdMap()` in `map_caster`, add tests.
ae95424
Simplify `list_caster` `load()` implementation, push str/bytes check …
8aa81d7
clang-tidy cleanup with a few extra `(... != 0)` to be more consistent.
4435ed0
Also use `PyObjectTypeIsConvertibleToStdVector()` in `array_caster`.
9aca5e8
Update comment pointing to clif/python/runtime.cc (code is unchanged).
9dc7d7c
Comprehensive test coverage, enhanced set_caster load implementation.
d9eeea8
Resolve clang-tidy eror.
9ac319b
Add a long C++ comment explaining what led to the `PyObjectTypeIsConv…
b834767
Minor function name change in test.
d19a0ff
strcmp -> std::strcmp (thanks @Skylion007 for catching this)
69a0da8
Add `PyCallable_Check(items)` in `PyObjectTypeIsConvertibleToStdMap()`
c86fa97
Resolve clang-tidy error
940e190
Use `PyMapping_Items()` instead of `src.attr("items")()`, to be inter…
f7725e4
Update link to PyCLIF sources.
fa72918
Fix typo (thanks @wangxf123456 for catching this)
a6b9a00
Merge branch 'list_caster_pass_generator' of https://github.com/rwgk/…
ac3ac4d
Merge branch 'master' into list_caster_pass_generator
87ff92a
Merge branch 'master' into list_caster_pass_generator
3ae34f3
Fix typo discovered by new version of codespell.
d1ffe4f
Merge branch 'master' into list_caster_pass_generator
2267e5c
Merge branch 'master' into list_caster_pass_generator
a38d0bd
Merge branch 'master' into list_caster_pass_generator
fbf41fd
Merge branch 'master' into list_caster_pass_generator
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This requires explicit subclasses, rather than any object that conforms to
collections.abc.Sequence
? (Likewise forcollections.abc.Mapping
andcollections.abc.Set
below) The Pythonic way to do this would be to ask if the object has the methods required by these protocols, rather than checking explicit inheritance.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.
Specifically, from https://docs.python.org/3/library/collections.abc.html:
Sequence
:__getitem__
,__len__
,__contains__
,__iter__
,__reversed__
,index
, andcount
.Set
:__contains__
,__iter__
,__len__
,__le__
,__lt__
,__eq__
,__ne__
,__gt__
,__ge__
,__and__
,__or__
,__sub__
,__xor__
, andisdisjoint
.Mapping
:__getitem__
,__iter__
,__len__
,__contains__
,keys
,items
,values
,get
,__eq__
, and__ne__
.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.
In addition to what I wrote yesterday, there was actually another concern in the back of my mind: the current implementation is super fast, direct
strcmp
calls for 5 (vector
) of 1 (set
) very short string(s).In contrast,
hasattr
is far more complex and probably orders of magnitude slower, although I wouldn't really worry about it in the usual bigger context (it'll not even be a blip on the radar in most cases). The code extra code complexity is the bigger worry.So there is a code complexity and runtime overhead cost.
What is the benefit?
That brings me back to my "large-scale field experiment" experience hinted in the PR description. In a nutshell:
Current pybind11 is super restrictive.
Original PyCLIF was super permissive.
I had this huge pile of data from the wild contrasting the two. Based on that I could see very clearly that there is very little to gain from being more permissive than what this PR implements. IOW I don't think paying the code complexity and runtime overhead cost will help in any significant way.
Could you please let me know if you have a different opinion? — It will probably cost me a whole day worth of effort to implement and fully test (global testing) attribute inspection. We will also have to agree on what subsets of the attributes we actually want to test against. I expect that there will be some devils in the details.
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 think having a short path (check inheritance first) could alleviate much of the speed problem - the slower "correct" check could be done if this is not a subclass of X for common X. Also, this list is somewhat arbitrary - you probably included things (like
dict_keys
?dict_items
?) based on usage (in PyCLIF), rather than making a comprehensive list of everything iterable in Python? Also, I believe checking the attributes on a class (you don't need to check them on the instance) is pretty fast if you avoid the descriptor protocol (typing.runtime_checkable
switched to this in 3.12 (since 3.2) which made it much faster).From a usage standpoint, implementing the Protocol specified by these ABC's is supposed to make your class work wherever the standard library classes work, so it seems ideal if this could follow that. Not required (and we could start with this if you really want to), but it seems like the correct thing to do.
This is concretely specified in
collections.abc
. No arguments needed.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 agree. Which basically means: this PR plus follow-on work to make the check more permissive.
Do you think it's reasonable then to merge this PR, and do the fallback attribute inspection in a separate PR? — To be completely honest, I wouldn't want to prioritize this, for the reasons explained before. It a significant amount of work, extra code complexity, and I don't think very many people will ever notice the difference in practice. But if someone else wants to invest the effort, I'd be on board.
I see, sounds good to me, but from a purely practical viewpoint, assuming that most duck-typing only implements a subset of the attributes, insisting on the full set of attributes here probably means nobody will ever see a difference in practice, unless they are specifically looking to pass the checks here.