self.assertEqual(E().f(), 'AE')
+ @unittest.expectedFailure
def test___class___set(self):
# See issue #12370
class X(A):
self.assertEqual(x.f(), 'A')
self.assertEqual(x.__class__, 413)
+ def test___class___instancemethod(self):
+ # See issue #14857
+ class X:
+ def f(self):
+ return __class__
+ self.assertIs(X().f(), X)
+
+ def test___class___classmethod(self):
+ # See issue #14857
+ class X:
+ @classmethod
+ def f(cls):
+ return __class__
+ self.assertIs(X.f(), X)
+
+ def test___class___staticmethod(self):
+ # See issue #14857
+ class X:
+ @staticmethod
+ def f():
+ return __class__
+ self.assertIs(X.f(), X)
+
def test_main():
support.run_unittest(TestSuper)
FILTER_DIR = True
+# Workaround for issue #12370
+# Without this, the __class__ properties wouldn't be set correctly
+_safe_super = super
def _is_instance_mock(obj):
# can't use isinstance on Mock objects because they override __class__
if kwargs:
self.configure_mock(**kwargs)
- super(NonCallableMock, self).__init__(
+ _safe_super(NonCallableMock, self).__init__(
spec, wraps, name, spec_set, parent,
_spec_state
)
_spec_state=None, _new_name='', _new_parent=None, **kwargs):
self.__dict__['_mock_return_value'] = return_value
- super(CallableMixin, self).__init__(
+ _safe_super(CallableMixin, self).__init__(
spec, wraps, name, spec_set, parent,
_spec_state, _new_name, _new_parent, **kwargs
)
class MagicMixin(object):
def __init__(self, *args, **kw):
- super(MagicMixin, self).__init__(*args, **kw)
+ _safe_super(MagicMixin, self).__init__(*args, **kw)
self._mock_set_magics()
Core and Builtins
-----------------
+- Issue #14857: fix regression in references to PEP 3135 implicit __class__
+ closure variable (Reopens issue #12370)
+
- Issue #14712 (PEP 405): Virtual environments. Implemented by Vinay Sajip.
- Issue #14660 (PEP 420): Namespace packages. Implemented by Eric Smith.
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
assert(PyUnicode_Check(name));
if (!PyUnicode_CompareWithASCIIString(name,
- "@__class__")) {
+ "__class__")) {
Py_ssize_t index = co->co_nlocals +
PyTuple_GET_SIZE(co->co_cellvars) + i;
PyObject *cell = f->f_localsplus[index];
return 0;
}
/* return the (empty) __class__ cell */
- str = PyUnicode_InternFromString("@__class__");
+ str = PyUnicode_InternFromString("__class__");
if (str == NULL) {
compiler_exit_scope(c);
return 0;
Python 3.3a0 3200 (__qualname__ added)
3210 (added size modulo 2**32 to the pyc header)
Python 3.3a1 3220 (changed PEP 380 implementation)
+ Python 3.3a4 3230 (revert changes to implicit __class__ closure)
*/
/* MAGIC must change whenever the bytecode emitted by the compiler may no
#define STRIFY(name) QUOTE(name)
#define MAJOR STRIFY(PY_MAJOR_VERSION)
#define MINOR STRIFY(PY_MINOR_VERSION)
-#define MAGIC (3220 | ((long)'\r'<<16) | ((long)'\n'<<24))
+#define MAGIC (3230 | ((long)'\r'<<16) | ((long)'\n'<<24))
#define TAG "cpython-" MAJOR MINOR;
#define CACHEDIR "__pycache__"
/* Current magic word and string tag as globals. */
struct symtable *
PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
{
- struct symtable *st;
+ struct symtable *st = symtable_new();
asdl_seq *seq;
int i;
- if (__class__ == NULL) {
- __class__ = PyUnicode_InternFromString("@__class__");
- if (__class__ == NULL)
- return NULL;
- }
-
- st = symtable_new();
if (st == NULL)
return st;
st->st_filename = filename;
}
else {
/* Special-case __class__ */
+ if (!GET_IDENTIFIER(__class__))
+ goto error;
assert(PySet_Contains(local, __class__) == 1);
if (PySet_Add(newbound, __class__) < 0)
goto error;
NULL))
goto error;
else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
- "@__class__"))
+ "__class__"))
goto error;
/* Records the results of the analysis in the symbol table entry */
if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
(void *)s, s->lineno, s->col_offset))
return 0;
- if (!symtable_add_def(st, __class__, DEF_LOCAL) ||
+ if (!GET_IDENTIFIER(__class__) ||
+ !symtable_add_def(st, __class__, DEF_LOCAL) ||
!GET_IDENTIFIER(__locals__) ||
!symtable_add_def(st, __locals__, DEF_PARAM)) {
symtable_exit_block(st, s);
if (e->v.Name.ctx == Load &&
st->st_cur->ste_type == FunctionBlock &&
!PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) {
- if (!symtable_add_def(st, __class__, USE))
+ if (!GET_IDENTIFIER(__class__) ||
+ !symtable_add_def(st, __class__, USE))
return 0;
}
break;