-
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
bugfix: KeysView/ValuesView/ItemsView using Python types. Fix #4529 #4983
Conversation
Wow, thanks! It's very late in my current timezone, I can only look later. I tried to start global testing for this PR as well, hoping for overnight results, but I didn't get very far, initial testing fails with this error (one of many):
NOTE: The line numbers are off, compared to pybind11 master. This error is generated by the feature merged with smart_holder PR #4022. (Google production uses a branch of pybind11 that includes that feature.) It's saying that there is one (or more) translation unit(s) in which That's all I know at the moment. I/we need to find out how this PR is leading to that situation. |
@rwgk Thanks for the testing and the quick feedback.
So this seems to be a case when it is a mix use of "stl.h" and "stl_bind.h"?
I tried merging this PR with the Considering the error message you provided only has something to do with If possible, please also let me know whether PR #4972 can pass your tests. |
The feature may not be ON by default, it depends on how exactly you run the tests. — But it might be best not to spend time reproducing my observations; better to stay focused on pybind11 master. The problem is probably (I didn't verify yet) because of the rather unusual way the pybind11 unit tests are organized. Most tests are implemented as submodules and statically linked together into
I'm thinking the ODR guard errors will disappear if we change test_stl_binders.cpp to be in an isolated module, so that the linker visibility protections apply (optional: look for "visibility" under https://pybind11.readthedocs.io/en/stable/faq.html). We're just lucky that the existing tests are such that the ODR guard doesn't trigger. We have 4 tests already that are in isolated modules (cross_module_gil_utils, cross_module_interleaved_error_already_set, eigen_tensor_avoid_stl_array, pybind11_cross_module_tests), so it's probably pretty easy to change the stl_binders test to be in an isolated module, too. ... I'll give that a try. |
Oh, wait, I overlooked that before. |
I tried, it doesn't help. Let me try moving the stl_binders test to an isolated module. |
Previously I wrote:
Confirmed, by applying #4984 locally. (The GitHub Actions failures under #4984 are yet another known problem; see PR description there.) I'm now in a position to run Google global testing with this PR. That will probably take about half a day at least. |
The reduced diff for the case identified previously is below. Looks like we need special handling for -class ItemsView[int, object]:
+class ItemsView[int, %]:
-class ItemsView[str, object]:
+class ItemsView[str, %]:
class KeysView[int]:
- @overload
- def __contains__(self, arg0: int) -> bool: ...
- @overload
def __contains__(self, arg0: object) -> bool: ...
class KeysView[str]:
- @overload
- def __contains__(self, arg0: str) -> bool: ...
- @overload
def __contains__(self, arg0: object) -> bool: ...
- def items(self) -> ItemsView[int,object]: ...
+ def items(self, *args, **kwargs) -> Any: ...
- def values(self) -> ValuesView[object]: ...
+ def values(self, *args, **kwargs) -> Any: ...
- def items(self) -> ItemsView[str,object]: ...
+ def items(self, *args, **kwargs) -> Any: ...
- def values(self) -> ValuesView[object]: ...
+ def values(self, *args, **kwargs) -> Any: ...
-class ValuesView[object]:
+class ValuesView[%]: |
I'm still waiting for the global testing results for this PR, but maybe it's good to share what's going through my mind (inconclusive): The An already existing cost: What's the benefit? Really, all we're getting is Is that worth it? Assume we decide the cost / benefit is too high by some measure. We could just Then something like
to override the member functions, and then return a base-class pointer here:
In terms of code complexity this would be much cheaper. Would it be a big loss to not have the |
@rwgk Thanks for these tests and comments. They are very helpful.
This is related to the missing I added these 4 lines which should fix the test cases you mentioned. |
I agree that this PR is probably too complicated for the purpose. Especially when compared with: #2244 (comment)
I think this is a good idea. It can solve #4529 with the smallest cost. See #4985 |
For completeness:
After applying commit c43713f, the only diff is this: class KeysView[int]:
- @overload
- def __contains__(self, arg0: int) -> bool: ...
- @overload
def __contains__(self, arg0: object) -> bool: ...
class KeysView[str]:
- @overload
- def __contains__(self, arg0: str) -> bool: ...
- @overload
def __contains__(self, arg0: object) -> bool: ... |
The overloading of |
Closing this after #4985 was merged. |
Description
This PR is an alternative to PR #4972. Fixes issue #4529 and #3986. Compatible to #4888.
Here,
KeysView/ValuesView/ItemsView
will have python style typing strings, likeKeysView[int]
(see #3986).KeysView[int]
will only be registered once for all relevantKeyType = int16_t, int32_t, int64_t, ...
which solves #4529. A mix of C++ and Python types can also be supported.Note: To achieve the goal of this PR I cannot directly use
detail::make_caster<KeyType>::name
for the Python type name. Consider the case whenKeyType = std::pair<int, std::vector<int>>
which is a mix of Python and C++ types.detail::make_caster<KeyType>::name
for this case will betuple[int, %]
. The%
appears, sincedetail::make_caster<KeyType>::name
is aconstexpr
, which cannot recognize the binding name forstd::vector<int>
. PR #4353 usesif (key_type_name == "%")
to get rid of "%" and fall back to the C++ type name, but unfortunately this does not work for the nested casetuple[int, %]
. With this PR, I introduceddetail::type_mapper<KeyType>::py_name()
to construct the correct type name.Suggested changelog entry: