#6201: Fix test_winreg on Windows:
since the introduction of the SETUP_WITH opcode, __enter__ and __exit__ methods must belong to the type, and are not retrieved at the instance level (__dict__ or __getattr__). Add a note in whatsnew about this incompatibility; old style classes are not affected.
This commit is contained in:
parent
03dcc73c11
commit
901f200c81
|
@ -669,7 +669,11 @@ Porting to Python 2.7
|
|||
This section lists previously described changes and other bugfixes
|
||||
that may require changes to your code:
|
||||
|
||||
To be written.
|
||||
* Because of an optimization for the :keyword:`with` statement, the special
|
||||
methods :meth:`__enter__` and :meth:`__exit__` must belong to the object's
|
||||
type, and cannot be directly attached to the object's instance. This
|
||||
affects new-styles classes (derived from :class:`object`) or C extension
|
||||
types. (:issue:`6101`.)
|
||||
|
||||
.. ======================================================================
|
||||
|
||||
|
|
62
PC/_winreg.c
62
PC/_winreg.c
|
@ -469,9 +469,23 @@ static PyNumberMethods PyHKEY_NumberMethods =
|
|||
PyHKEY_unaryFailureFunc, /* nb_hex */
|
||||
};
|
||||
|
||||
static PyObject *PyHKEY_CloseMethod(PyObject *self, PyObject *args);
|
||||
static PyObject *PyHKEY_DetachMethod(PyObject *self, PyObject *args);
|
||||
static PyObject *PyHKEY_Enter(PyObject *self);
|
||||
static PyObject *PyHKEY_Exit(PyObject *self, PyObject *args);
|
||||
|
||||
/* fwd declare __getattr__ */
|
||||
static PyObject *PyHKEY_getattr(PyObject *self, const char *name);
|
||||
static struct PyMethodDef PyHKEY_methods[] = {
|
||||
{"Close", PyHKEY_CloseMethod, METH_VARARGS, PyHKEY_Close_doc},
|
||||
{"Detach", PyHKEY_DetachMethod, METH_VARARGS, PyHKEY_Detach_doc},
|
||||
{"__enter__", (PyCFunction)PyHKEY_Enter, METH_NOARGS, NULL},
|
||||
{"__exit__", PyHKEY_Exit, METH_VARARGS, NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static PyMemberDef PyHKEY_memberlist[] = {
|
||||
{"handle", T_PYSSIZET, offsetof(PyHKEYObject, hkey), READONLY},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
/* The type itself */
|
||||
PyTypeObject PyHKEY_Type =
|
||||
|
@ -482,7 +496,7 @@ PyTypeObject PyHKEY_Type =
|
|||
0,
|
||||
PyHKEY_deallocFunc, /* tp_dealloc */
|
||||
PyHKEY_printFunc, /* tp_print */
|
||||
PyHKEY_getattr, /* tp_getattr */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
PyHKEY_compareFunc, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
|
@ -495,15 +509,16 @@ PyTypeObject PyHKEY_Type =
|
|||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
0, /* tp_flags */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
PyHKEY_doc, /* tp_doc */
|
||||
};
|
||||
|
||||
#define OFF(e) offsetof(PyHKEYObject, e)
|
||||
|
||||
static struct memberlist PyHKEY_memberlist[] = {
|
||||
{"handle", T_INT, OFF(hkey)},
|
||||
{NULL} /* Sentinel */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
PyHKEY_methods, /* tp_methods */
|
||||
PyHKEY_memberlist, /* tp_members */
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
@ -550,28 +565,6 @@ PyHKEY_Exit(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
|
||||
static struct PyMethodDef PyHKEY_methods[] = {
|
||||
{"Close", PyHKEY_CloseMethod, METH_VARARGS, PyHKEY_Close_doc},
|
||||
{"Detach", PyHKEY_DetachMethod, METH_VARARGS, PyHKEY_Detach_doc},
|
||||
{"__enter__", (PyCFunction)PyHKEY_Enter, METH_NOARGS, NULL},
|
||||
{"__exit__", PyHKEY_Exit, METH_VARARGS, NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/*static*/ PyObject *
|
||||
PyHKEY_getattr(PyObject *self, const char *name)
|
||||
{
|
||||
PyObject *res;
|
||||
|
||||
res = Py_FindMethod(PyHKEY_methods, self, name);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
PyErr_Clear();
|
||||
if (strcmp(name, "handle") == 0)
|
||||
return PyLong_FromVoidPtr(((PyHKEYObject *)self)->hkey);
|
||||
return PyMember_Get((char *)self, PyHKEY_memberlist, name);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
The public PyHKEY API (well, not public yet :-)
|
||||
************************************************************************/
|
||||
|
@ -1634,7 +1627,8 @@ PyMODINIT_FUNC init_winreg(void)
|
|||
if (m == NULL)
|
||||
return;
|
||||
d = PyModule_GetDict(m);
|
||||
PyHKEY_Type.ob_type = &PyType_Type;
|
||||
if (PyType_Ready(&PyHKEY_Type) < 0)
|
||||
return;
|
||||
PyHKEY_Type.tp_doc = PyHKEY_doc;
|
||||
Py_INCREF(&PyHKEY_Type);
|
||||
if (PyDict_SetItemString(d, "HKEYType",
|
||||
|
|
Loading…
Reference in New Issue