as a ``__classcell__`` entry in the class namespace. If present, this must
be propagated up to the ``type.__new__`` call in order for the class to be
initialised correctly.
- Failing to do so will result in a :exc:`DeprecationWarning` in Python 3.6,
- and a :exc:`RuntimeError` in Python 3.8.
+ Failing to do so will result in a :exc:`RuntimeError` in Python 3.8.
When using the default metaclass :class:`type`, or any metaclass that ultimately
calls ``type.__new__``, the following additional customisation steps are
"""Unit tests for zero-argument super() & related machinery."""
import unittest
-import warnings
-from test.support import check_warnings
class A:
test_namespace = namespace
return None
- # This case shouldn't trigger the __classcell__ deprecation warning
- with check_warnings() as w:
- warnings.simplefilter("always", DeprecationWarning)
- class A(metaclass=Meta):
- @staticmethod
- def f():
- return __class__
- self.assertEqual(w.warnings, [])
+ class A(metaclass=Meta):
+ @staticmethod
+ def f():
+ return __class__
self.assertIs(A, None)
namespace.pop('__classcell__', None)
return super().__new__(cls, name, bases, namespace)
- # The default case should continue to work without any warnings
- with check_warnings() as w:
- warnings.simplefilter("always", DeprecationWarning)
- class WithoutClassRef(metaclass=Meta):
- pass
- self.assertEqual(w.warnings, [])
+ # The default case should continue to work without any errors
+ class WithoutClassRef(metaclass=Meta):
+ pass
# With zero-arg super() or an explicit __class__ reference, we expect
- # __build_class__ to emit a DeprecationWarning complaining that
+ # __build_class__ to raise a RuntimeError complaining that
# __class__ was not set, and asking if __classcell__ was propagated
# to type.__new__.
- # In Python 3.7, that warning will become a RuntimeError.
- expected_warning = (
- '__class__ not set.*__classcell__ propagated',
- DeprecationWarning
- )
- with check_warnings(expected_warning):
- warnings.simplefilter("always", DeprecationWarning)
+ expected_error = '__class__ not set.*__classcell__ propagated'
+ with self.assertRaisesRegex(RuntimeError, expected_error):
class WithClassRef(metaclass=Meta):
def f(self):
return __class__
- # Check __class__ still gets set despite the warning
- self.assertIs(WithClassRef().f(), WithClassRef)
-
- # Check the warning is turned into an error as expected
- with warnings.catch_warnings():
- warnings.simplefilter("error", DeprecationWarning)
- with self.assertRaises(DeprecationWarning):
- class WithClassRef(metaclass=Meta):
- def f(self):
- return __class__
def test___classcell___overwrite(self):
# See issue #23722
if (cls != NULL && PyType_Check(cls) && PyCell_Check(cell)) {
PyObject *cell_cls = PyCell_GET(cell);
if (cell_cls != cls) {
- /* TODO: In 3.7, DeprecationWarning will become RuntimeError.
- * At that point, cell_error won't be needed.
- */
- int cell_error;
if (cell_cls == NULL) {
const char *msg =
"__class__ not set defining %.200R as %.200R. "
"Was __classcell__ propagated to type.__new__?";
- cell_error = PyErr_WarnFormat(
- PyExc_DeprecationWarning, 1, msg, name, cls);
+ PyErr_Format(PyExc_RuntimeError, msg, name, cls);
} else {
const char *msg =
"__class__ set to %.200R defining %.200R as %.200R";
PyErr_Format(PyExc_TypeError, msg, cell_cls, name, cls);
- cell_error = 1;
- }
- if (cell_error) {
- Py_DECREF(cls);
- cls = NULL;
- goto error;
- } else {
- /* Fill in the cell, since type.__new__ didn't do it */
- PyCell_Set(cell, cls);
}
+ Py_DECREF(cls);
+ cls = NULL;
+ goto error;
}
}
}