Uh oh!
There was an error while loading. Please reload this page.
Force the builtin module key to be the correct type. - #2814
Conversation
Previously it was always going to be a std::string which converted into unicode. Python 2 appears to want module keys to be normal str types, so this was breaking code that expected plain string types in the builtins.keys() data structure
YannickJadoul
commented
Jan 22, 2021
We discussed this on Gitter. I agree that it makes sense that a module's Fun thing, this is actually not breaking the ABI, and (probably) not even stopping different pybind11 libraries from interacting, since: Python 2.7.17 (default, Sep 30 2020, 13:38:04) [GCC 7.5.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {}
>>> d[u'answer'] =42
>>> d[u'answer']
42
>>> d['answer']
42
>>> type(u'answer')
<type 'unicode'>
>>> type('answer')
<type 'str'>
>>> Do you mind checking this, @crimsoncor, whether a pybind11 library from our current |
crimsoncor
commented
Jan 22, 2021
Did some very basic testing of this (source code in the attached zip). I built one module with a pre-patch pybind11 and the other with post-patch (and then also flipped the order). In all cases, both modules were able to access the same internals block. What I did notice was that which one was loaded first determined the type of the argument in the builtin dict: But even with that said, regardless of the type of the key, it still worked for both modules. Also double checked to make sure there was ever only a single entry in the map (despite it being str vs unicode) And that looks like it also was correct |
YannickJadoul
commented
Jan 22, 2021
@henryiii, I'm going to say it's your call on whether we've already stopped accepting PRs for 2.6.2 :-P |
henryiii
commented
Jan 22, 2021
If we can get another global testing run (which I think we will, @rwgk ?), maybe over the weekend, and release Monday, perhaps? |
rwgk
commented
Jan 22, 2021
OK, np, I'll include this PR in the next run. |
rwgk
commented
Jan 22, 2021
@crimsoncor if you could add a minimal test that would be great. |
crimsoncor
commented
Jan 22, 2021
What sort of test do you think would be applicable? The existing tests that exercise internals being shared across multiple modules continue to function fine, which shows that changing the type of the key in python 2.7 has not caused any regression. The only other test that seems like it might be applicable would be testing a module built with an older version and a module built with the new code (like I did manually) and I'm not sure how to add that in any sane fashion in the pybind11 test suite. |
YannickJadoul
commented
Jan 22, 2021
@crimsoncor, what about just adding a single test that checks |
crimsoncor
commented
Jan 22, 2021
done |
rwgk
commented
Jan 22, 2021
Awesome, thanks! |
| if hasattr(__builtins__, "keys"): | ||
| keys = __builtins__.keys() | ||
| else: # this is to make pypy happy since builtins is different there. | ||
| keys = __builtins__.__dict__.keys() |
There was a problem hiding this comment.
Why not simply always go through __builtins__.__dict__.keys()? It works in CPython and PyPy.
There was a problem hiding this comment.
answered in gitter, but I'll add here as well. Python 2 has the following amazing feature
In module __main__:
__builtins__ is a reference to module __builtin__.
__builtin__ only exists if you import it.
In any other module:
__builtins__ is a reference to module __builtin__'s __dict__.
__builtin__ only exists if you import it.
so we need to handle both cases.
rwgk
left a comment
There was a problem hiding this comment.
I ran this through our global testing and found no issues.
Thanks for creating this PR, @crimsoncor / @jesse-sony! |
Previously it was always going to be a std::string which converted into
unicode. Python 2 appears to want module keys to be normal str types, so
this was breaking code that expected plain string types in the
builtins.keys() data structure
Description
Suggested changelog entry: