Issue 46034: Patch-adding __init__ in a class takes no effect when called from a subinterpreter - Python tracker

This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
process
Status: closed Resolution: duplicate
Dependencies: Superseder:
Assigned To: Nosy List: eric.snow, hroncok, vstinner
Priority: normal Keywords:

Created on 2021-12-10 12:01 by hroncok, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (3)
msg408196 - (view) Author: Miro Hrončok (hroncok) * Date: 2021-12-10 12:01
Hello,

based on some bug reports reported in:

- https://github.com/GrahamDumpleton/mod_wsgi/issues/729
- https://github.com/poljar/weechat-matrix/issues/293
- https://bugzilla.redhat.com/show_bug.cgi?id=2030621

I have isolated the following reproducer that shows a regression in Python 3.10+. It happens at least with 3.10.0, 3.10.1 and 3.11.0a2. It works as expected in Python 3.9.

The following code is valid and works on 3.9, 3.10, 3.11:

=========================================
class Greeting():
    pass

def new_init(inst, name):
    inst.text = f"Hello, {name}\n"

Greeting.__init__ = new_init

Greeting("Miro")
=========================================


But if we run it via a subinterpreter, it breaks on 3.10+:

=========================================
import _testcapi

code = r"""class Greeting():
    pass

def new_init(inst, name):
    inst.text = f"Hello, {name}\n"

Greeting.__init__ = new_init

Greeting("Miro")"""

_testcapi.run_in_subinterp(code)
=========================================


$ python3.9 reproducer.py
(exits cleanly)

$ python3.10 reproducer.py 
Traceback (most recent call last):
  File "<string>", line 9, in <module>
TypeError: Greeting() takes no arguments

$ python3.11 reproducer.py 
Traceback (most recent call last):
  File "<string>", line 9, in <module>
TypeError: Greeting() takes no arguments


My observation also shows that if the Greeting class already had (any) __init__:

=========================================
class Greeting():
    __init__ = ...
=========================================

It works as expected on 3.9, 3.10, 3.11.



In reality, this is most likely to affect classes with decorators, like:

=========================================
import attr

@attr.s
class TestClass:
    foo = attr.ib()

TestClass("Miro")
=========================================

This works standalone, but fails in a subinterpreter:

$ python3.10 reproducer.py 
Traceback (most recent call last):
  File "<string>", line 7, in <module>
TypeError: TestClass() takes no arguments
msg408199 - (view) Author: Miro Hrončok (hroncok) * Date: 2021-12-10 12:22
git bisect gives:

https://github.com/python/cpython/commit/ea251806b8dffff11b30d2182af1e589caf88acf
msg408200 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-12-10 12:29
I mark this issue as a duplicate of bpo-46006. It's not exactly the same issue, but the root cause is the same: in some functions, Python use fast pointer comparisons when two strings are interned, but this now fails if two interned strings belong to two different interpreters.