hide the __class__ closure from the class body (#12370) · pythoncapi/cpython@312595c · GitHub
Skip to content

Commit 312595c

Browse files
committed
hide the __class__ closure from the class body (python#12370)
1 parent fe361df commit 312595c

7 files changed

Lines changed: 221 additions & 152 deletions

File tree

Include/symtable.h

Lines changed: 3 additions & 0 deletions

Lib/importlib/_bootstrap.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,13 @@ def _call_with_frames_removed(f, *args, **kwds):
390390
# keyword-only defaults)
391391
# Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override
392392
# free vars)
393+
# Python 3.4a1 3270 (various tweaks to the __class_ closure)
393394
#
394395
# MAGIC must change whenever the bytecode emitted by the compiler may no
395396
# longer be understood by older implementations of the eval loop (usually
396397
# due to the addition of new opcodes).
397398

398-
_MAGIC_BYTES = (3260).to_bytes(2, 'little') + b'\r\n'
399+
_MAGIC_BYTES = (3270).to_bytes(2, 'little') + b'\r\n'
399400
_RAW_MAGIC_NUMBER = int.from_bytes(_MAGIC_BYTES, 'little')
400401

401402
_PYCACHE = '__pycache__'

Lib/test/test_super.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ def nested():
8181

8282
self.assertEqual(E().f(), 'AE')
8383

84-
@unittest.expectedFailure
85-
def test___class___set(self):
84+
def test_various___class___pathologies(self):
8685
# See issue #12370
8786
class X(A):
8887
def f(self):
@@ -91,6 +90,31 @@ def f(self):
9190
x = X()
9291
self.assertEqual(x.f(), 'A')
9392
self.assertEqual(x.__class__, 413)
93+
class X:
94+
x = __class__
95+
def f():
96+
__class__
97+
self.assertIs(X.x, type(self))
98+
with self.assertRaises(NameError) as e:
99+
exec("""class X:
100+
__class__
101+
def f():
102+
__class__""", globals(), {})
103+
self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
104+
class X:
105+
global __class__
106+
__class__ = 42
107+
def f():
108+
__class__
109+
self.assertEqual(globals()["__class__"], 42)
110+
del globals()["__class__"]
111+
self.assertNotIn("__class__", X.__dict__)
112+
class X:
113+
nonlocal __class__
114+
__class__ = 42
115+
def f():
116+
__class__
117+
self.assertEqual(__class__, 42)
94118

95119
def test___class___instancemethod(self):
96120
# See issue #14857

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #12370: Prevent class bodies from interfering with the __class__
14+
closure.
15+
1316
- Issue #17237: Fix crash in the ASCII decoder on m68k.
1417

1518
- Issue #17927: Frame objects kept arguments alive if they had been

Python/compile.c

Lines changed: 49 additions & 15 deletions

0 commit comments

Comments
 (0)