mirror of
https://github.com/python/cpython.git
synced 2025-11-13 15:40:05 +00:00
Close off the "Verre Carlo hack" as discussed on python-dev.
This commit is contained in:
parent
2fd02eb80f
commit
4dcdb78c6f
2 changed files with 39 additions and 0 deletions
|
|
@ -3840,6 +3840,22 @@ def proxysuper():
|
||||||
p = Proxy(obj)
|
p = Proxy(obj)
|
||||||
vereq(C.__dict__["f"](p), "B.f->C.f")
|
vereq(C.__dict__["f"](p), "B.f->C.f")
|
||||||
|
|
||||||
|
def verrecarlo():
|
||||||
|
if verbose:
|
||||||
|
print "Testing prohibition of Verre Carlo's hack..."
|
||||||
|
try:
|
||||||
|
object.__setattr__(str, "foo", 42)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed, "Verre Carlo __setattr__ suceeded!"
|
||||||
|
try:
|
||||||
|
object.__delattr__(str, "lower")
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed, "Verre Carlo __delattr__ succeeded!"
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
do_this_first()
|
do_this_first()
|
||||||
|
|
@ -3929,6 +3945,7 @@ def test_main():
|
||||||
meth_class_get()
|
meth_class_get()
|
||||||
isinst_isclass()
|
isinst_isclass()
|
||||||
proxysuper()
|
proxysuper()
|
||||||
|
verrecarlo()
|
||||||
|
|
||||||
if verbose: print "All OK"
|
if verbose: print "All OK"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3574,6 +3574,24 @@ wrap_cmpfunc(PyObject *self, PyObject *args, void *wrapped)
|
||||||
return PyInt_FromLong((long)res);
|
return PyInt_FromLong((long)res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper to check for object.__setattr__ or __delattr__ applied to a type.
|
||||||
|
This is called the Verre Carlo hack after its discoverer. */
|
||||||
|
static int
|
||||||
|
hackcheck(PyObject *self, setattrofunc func, char *what)
|
||||||
|
{
|
||||||
|
PyTypeObject *type = self->ob_type;
|
||||||
|
while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE)
|
||||||
|
type = type->tp_base;
|
||||||
|
if (type->tp_setattro != func) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"can't apply this %s to %s object",
|
||||||
|
what,
|
||||||
|
type->tp_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrap_setattr(PyObject *self, PyObject *args, void *wrapped)
|
wrap_setattr(PyObject *self, PyObject *args, void *wrapped)
|
||||||
{
|
{
|
||||||
|
|
@ -3583,6 +3601,8 @@ wrap_setattr(PyObject *self, PyObject *args, void *wrapped)
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OO", &name, &value))
|
if (!PyArg_ParseTuple(args, "OO", &name, &value))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (!hackcheck(self, func, "__setattr__"))
|
||||||
|
return NULL;
|
||||||
res = (*func)(self, name, value);
|
res = (*func)(self, name, value);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -3599,6 +3619,8 @@ wrap_delattr(PyObject *self, PyObject *args, void *wrapped)
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &name))
|
if (!PyArg_ParseTuple(args, "O", &name))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (!hackcheck(self, func, "__delattr__"))
|
||||||
|
return NULL;
|
||||||
res = (*func)(self, name, NULL);
|
res = (*func)(self, name, NULL);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue