-
-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
Weird int.__str__
behaviour inside sub-interpreters
#117482
Comments
Bisected to de64e75 |
I think i've got a shorter MRE, i believe this issue is not related to enums. import _xxsubinterpreters as interpreters
script = """print(int.__str__)"""
exec(script)
# Output: <slot wrapper '__str__' of 'object' objects>
interp_id = interpreters.create()
interpreters.run_string(interp_id, script)
# Output: <slot wrapper '__str__' of 'int' objects> |
This sheds light on what is going on. Thanks, @Elchinchel! |
int.__str__
behaviour inside sub-interpreters
Awesome! Thanks for looking into this @Eclips4 and @Elchinchel. By running the simplified script, I noticed that other base types have the same issue: The commit de64e75 you mentioned seems to change how the MRO works for base-types. I think that's probably related to the problem. |
FTR, #117660 (comment) provides further analysis. |
When builtin static types are initialized for a subinterpreter, various "tp" slots have already been inherited (for the main interpreter). This was interfering with the logic in add_operators() (in Objects/typeobject.c), causing a wrapper to get created when it shouldn't. This change fixes that by preserving the original data from the static type struct and checking that.
When builtin static types are initialized for a subinterpreter, various "tp" slots have already been inherited (for the main interpreter). This was interfering with the logic in add_operators() (in Objects/typeobject.c), causing a wrapper to get created when it shouldn't. This change fixes that by preserving the original data from the static type struct and checking that. (cherry picked from commit 5250a03) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
When builtin static types are initialized for a subinterpreter, various "tp" slots have already been inherited (for the main interpreter). This was interfering with the logic in add_operators() (in Objects/typeobject.c), causing a wrapper to get created when it shouldn't. This change fixes that by preserving the original data from the static type struct and checking that. (cherry picked from commit 5250a03, AKA gh-121602) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
When builtin static types are initialized for a subinterpreter, various "tp" slots have already been inherited (for the main interpreter). This was interfering with the logic in add_operators() (in Objects/typeobject.c), causing a wrapper to get created when it shouldn't. This change fixes that by preserving the original data from the static type struct and checking that.
When builtin static types are initialized for a subinterpreter, various "tp" slots have already been inherited (for the main interpreter). This was interfering with the logic in add_operators() (in Objects/typeobject.c), causing a wrapper to get created when it shouldn't. This change fixes that by preserving the original data from the static type struct and checking that. (cherry picked from commit 5250a03, AKA gh-121602) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
I think an alternative option is for |
@markshannon pointed out an alternate solution to the one I merged: in There are good reasons to keep (and build on) the changes we've made already, for 3.13+. That isn't so much the case for 3.12 though. Thus, I'll probably update 3.12 to take the simpler approach. |
When builtin static types are initialized for a subinterpreter, various "tp" slots have already been inherited (for the main interpreter). This was interfering with the logic in add_operators() (in Objects/typeobject.c), causing a wrapper to get created when it shouldn't. This change fixes that by preserving the original data from the static type struct and checking that.
… Static Builtin Types (pythongh-122192) (cherry picked from commit 33d32fa) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
… Static Builtin Types (pythongh-122192)
…h-121932) In gh-121602, I applied a fix to a builtin types initialization bug. That fix made sense in the context of some broader future changes, but introduced a little bit of extra complexity. For earlier versions those future changes are not relevant; we can avoid the extra complexity. Thus we can revert that earlier change and replace it with this one, which is more focused and conceptually simpler. This is essentially the implementation of an idea that @markshannon pointed out to me. Note that this change would be much smaller if we didn't have to deal with repr compatibility for builtin types that explicitly inherit tp slots (see expect_manually_inherited()). The alternative is to stop *explicitly* inheriting tp slots in static PyTypeObject values, which is churn that we can do separately.
…ers (pythongh-121932) In pythongh-121602, I applied a fix to a builtin types initialization bug. That fix made sense in the context of some broader future changes, but introduced a little bit of extra complexity. For earlier versions those future changes are not relevant; we can avoid the extra complexity. Thus we can revert that earlier change and replace it with this one, which is more focused and conceptually simpler. This is essentially the implementation of an idea that @markshannon pointed out to me. Note that this change would be much smaller if we didn't have to deal with repr compatibility for builtin types that explicitly inherit tp slots (see expect_manually_inherited()). The alternative is to stop *explicitly* inheriting tp slots in static PyTypeObject values, which is churn that we can do separately. (cherry picked from commit 716c677, AKA pythongh-121932)
…h-122241) In gh-121602, I applied a fix to a builtin types initialization bug. That fix made sense in the context of some broader future changes, but introduced a little bit of extra complexity. For earlier versions those future changes are not relevant; we can avoid the extra complexity. Thus we can revert that earlier change and replace it with this one, which is more focused and conceptually simpler. This is essentially the implementation of an idea that @markshannon pointed out to me. Note that this change would be much smaller if we didn't have to deal with repr compatibility for builtin types that explicitly inherit tp slots (see expect_manually_inherited()). The alternative is to stop *explicitly* inheriting tp slots in static PyTypeObject values, which is churn that we can do separately. (cherry picked from commit 716c677, AKA gh-121932)
… Static Builtin Types (pythongh-122192)
… Static Builtin Types (pythongh-122192)
The tests were only checking cases where the slot wrapper was present in the initial case. They were missing when the slot wrapper was added in the additional initializations. This fixes that.
…gh-122867) There were a still a number of gaps in the tests, including not looking at all the builtin types and not checking wrappers in subinterpreters that weren't in the main interpreter. This fixes all that. I considered incorporating the names of the PyTypeObject fields (a la gh-122866), but figured doing so doesn't add much value.
…orough (pythongh-122867) There were a still a number of gaps in the tests, including not looking at all the builtin types and not checking wrappers in subinterpreters that weren't in the main interpreter. This fixes all that. I considered incorporating the names of the PyTypeObject fields (a la pythongh-122866), but figured doing so doesn't add much value.
In gh-121602, I applied a fix to a builtin types initialization bug. That fix made sense in the context of some broader future changes, but introduced a little bit of extra complexity. That fix has turned out to be incomplete for some of the builtin types we haven't been testing. I found that out while improving the tests. A while back, @markshannon suggested a simpler fix that doesn't have that problem, which I've already applied to 3.12 and 3.13. I'm switching to that here. Given the potential long-term benefits of the more complex (but still incomplete) approach, I'll circle back to it in the future, particularly after I've improved the tests so no corner cases slip through the cracks. (This is effectively a "forward-port" of 716c677 from 3.13.)
Note that current PRs are closed, the issue should stay open. @ericsnowcurrently said in #122865:
|
Bug report
Bug description:
Hi Python maintainers!
I noticed something weird when using subinterpreters, while converting an Enum to string I get an unexpected result. This occurs in Python 3.12 and 3.13.
Here's an script to reproduce it:
In all python versions previous to 3.12 this prints "1" two times, on newer versions I get
<MyEnum.DATA: 1>
when running inside a subinterpreter. For some reason, the__str__
function being used is different on new Python versions.I also noticed that the function pointed by
__str__
is different inside and outside the subinterpreter.Outside:
Inside:
I hope this is enough to get to the source of the issue.
Appreciate all your work and effort on building Python, thank you!
CPython versions tested on:
3.8, 3.9, 3.10, 3.11, 3.12, 3.13
Operating systems tested on:
Linux, macOS
Linked PRs
The text was updated successfully, but these errors were encountered: