Merge of descr-branch back into trunk.

This commit is contained in:
Tim Peters 2001-08-02 04:15:00 +00:00
parent 52d55a3926
commit 6d6c1a35e0
57 changed files with 6923 additions and 1309 deletions

View file

@ -1588,6 +1588,24 @@ PyObject_CallObject(PyObject *o, PyObject *a)
return r;
}
PyObject *
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
ternaryfunc call;
if ((call = func->ob_type->tp_call) != NULL) {
PyObject *result = (*call)(func, arg, kw);
if (result == NULL && !PyErr_Occurred())
PyErr_SetString(
PyExc_SystemError,
"NULL result without error in PyObject_Call");
return result;
}
PyErr_Format(PyExc_TypeError, "object is not callable: %s",
PyString_AS_STRING(PyObject_Repr(func)));
return NULL;
}
PyObject *
PyObject_CallFunction(PyObject *callable, char *format, ...)
{
@ -1746,7 +1764,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
}
}
else if (PyType_Check(cls)) {
retval = ((PyObject *)(inst->ob_type) == cls);
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
}
else if (!PyInstance_Check(inst)) {
if (__class__ == NULL) {

View file

@ -537,21 +537,21 @@ PyTypeObject PyBuffer_Type = {
"buffer",
sizeof(PyBufferObject),
0,
(destructor)buffer_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)buffer_compare, /*tp_compare*/
(reprfunc)buffer_repr, /*tp_repr*/
0, /*tp_as_number*/
&buffer_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)buffer_hash, /*tp_hash*/
0, /*tp_call*/
(reprfunc)buffer_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
&buffer_as_buffer, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
(destructor)buffer_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)buffer_compare, /* tp_compare */
(reprfunc)buffer_repr, /* tp_repr */
0, /* tp_as_number */
&buffer_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)buffer_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)buffer_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
&buffer_as_buffer, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
};

View file

@ -106,7 +106,7 @@ PyTypeObject PyCell_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */

View file

@ -36,12 +36,12 @@ PyClass_New(PyObject *bases, PyObject *dict, PyObject *name)
return NULL;
}
if (name == NULL || !PyString_Check(name)) {
PyErr_SetString(PyExc_SystemError,
PyErr_SetString(PyExc_TypeError,
"PyClass_New: name must be a string");
return NULL;
}
if (dict == NULL || !PyDict_Check(dict)) {
PyErr_SetString(PyExc_SystemError,
PyErr_SetString(PyExc_TypeError,
"PyClass_New: dict must be a dictionary");
return NULL;
}
@ -67,14 +67,14 @@ PyClass_New(PyObject *bases, PyObject *dict, PyObject *name)
else {
int i;
if (!PyTuple_Check(bases)) {
PyErr_SetString(PyExc_SystemError,
PyErr_SetString(PyExc_TypeError,
"PyClass_New: bases must be a tuple");
return NULL;
}
i = PyTuple_Size(bases);
while (--i >= 0) {
if (!PyClass_Check(PyTuple_GetItem(bases, i))) {
PyErr_SetString(PyExc_SystemError,
PyErr_SetString(PyExc_TypeError,
"PyClass_New: base must be a class");
return NULL;
}
@ -106,6 +106,18 @@ PyClass_New(PyObject *bases, PyObject *dict, PyObject *name)
return (PyObject *) op;
}
static PyObject *
class_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *name, *bases, *dict;
static char *kwlist[] = {"name", "bases", "dict", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist,
&name, &bases, &dict))
return NULL;
return PyClass_New(bases, dict, name);
}
/* Class methods */
static void
@ -149,6 +161,8 @@ class_getattr(register PyClassObject *op, PyObject *name)
register PyObject *v;
register char *sname = PyString_AsString(name);
PyClassObject *class;
descrgetfunc f;
if (sname[0] == '_' && sname[1] == '_') {
if (strcmp(sname, "__dict__") == 0) {
if (PyEval_GetRestricted()) {
@ -186,6 +200,11 @@ class_getattr(register PyClassObject *op, PyObject *name)
Py_DECREF(v);
v = w;
}
f = v->ob_type->tp_descr_get;
if (f == NULL)
Py_INCREF(v);
else
v = f(v, (PyObject *)NULL, (PyObject *)op);
return v;
}
@ -396,7 +415,7 @@ PyTypeObject PyClass_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
PyInstance_New, /* tp_call */
(reprfunc)class_str, /* tp_str */
(getattrofunc)class_getattr, /* tp_getattro */
(setattrofunc)class_setattr, /* tp_setattro */
@ -404,6 +423,22 @@ PyTypeObject PyClass_Type = {
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)class_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
class_new, /* tp_new */
};
int
@ -531,7 +566,7 @@ instance_dealloc(register PyInstanceObject *inst)
/* compensate for boost in _Py_NewReference; note that
* _Py_RefTotal was also boosted; we'll knock that down later.
*/
inst->ob_type->tp_alloc--;
inst->ob_type->tp_allocs--;
#endif
#else /* !Py_TRACE_REFS */
/* Py_INCREF boosts _Py_RefTotal if Py_REF_DEBUG is defined */
@ -564,7 +599,7 @@ instance_dealloc(register PyInstanceObject *inst)
#endif
if (--inst->ob_refcnt > 0) {
#ifdef COUNT_ALLOCS
inst->ob_type->tp_free--;
inst->ob_type->tp_frees--;
#endif
return; /* __del__ added a reference; don't delete now */
}
@ -572,7 +607,7 @@ instance_dealloc(register PyInstanceObject *inst)
_Py_ForgetReference((PyObject *)inst);
#ifdef COUNT_ALLOCS
/* compensate for increment in _Py_ForgetReference */
inst->ob_type->tp_free--;
inst->ob_type->tp_frees--;
#endif
#ifndef WITH_CYCLE_GC
inst->ob_type = NULL;
@ -619,6 +654,8 @@ instance_getattr2(register PyInstanceObject *inst, PyObject *name)
{
register PyObject *v;
PyClassObject *class;
descrgetfunc f;
class = NULL;
v = PyDict_GetItem(inst->in_dict, name);
if (v == NULL) {
@ -628,17 +665,20 @@ instance_getattr2(register PyInstanceObject *inst, PyObject *name)
}
Py_INCREF(v);
if (class != NULL) {
if (PyFunction_Check(v)) {
PyObject *w = PyMethod_New(v, (PyObject *)inst,
(PyObject *)class);
f = v->ob_type->tp_descr_get;
if (f != NULL) {
PyObject *w = f(v, (PyObject *)inst,
(PyObject *)(inst->in_class));
Py_DECREF(v);
v = w;
}
else if (PyMethod_Check(v)) {
PyObject *im_class = PyMethod_Class(v);
/* XXX This should be a tp_descr_get slot of
PyMethodObjects */
PyObject *im_class = PyMethod_GET_CLASS(v);
/* Only if classes are compatible */
if (PyClass_IsSubclass((PyObject *)class, im_class)) {
PyObject *im_func = PyMethod_Function(v);
PyObject *im_func = PyMethod_GET_FUNCTION(v);
PyObject *w = PyMethod_New(im_func,
(PyObject *)inst, im_class);
Py_DECREF(v);
@ -1814,6 +1854,23 @@ instance_iternext(PyInstanceObject *self)
return NULL;
}
static PyObject *
instance_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
if (call == NULL) {
PyInstanceObject *inst = (PyInstanceObject*) func;
PyErr_Clear();
PyErr_Format(PyExc_AttributeError,
"%.200s instance has no __call__ method",
PyString_AsString(inst->in_class->cl_name));
return NULL;
}
res = PyObject_Call(call, arg, kw);
Py_DECREF(call);
return res;
}
static PyNumberMethods instance_as_number = {
(binaryfunc)instance_add, /* nb_add */
@ -1868,7 +1925,7 @@ PyTypeObject PyInstance_Type = {
&instance_as_sequence, /* tp_as_sequence */
&instance_as_mapping, /* tp_as_mapping */
(hashfunc)instance_hash, /* tp_hash */
0, /* tp_call */
instance_call, /* tp_call */
(reprfunc)instance_str, /* tp_str */
(getattrofunc)instance_getattr, /* tp_getattro */
(setattrofunc)instance_setattr, /* tp_setattro */
@ -1921,36 +1978,6 @@ PyMethod_New(PyObject *func, PyObject *self, PyObject *class)
return (PyObject *)im;
}
PyObject *
PyMethod_Function(register PyObject *im)
{
if (!PyMethod_Check(im)) {
PyErr_BadInternalCall();
return NULL;
}
return ((PyMethodObject *)im)->im_func;
}
PyObject *
PyMethod_Self(register PyObject *im)
{
if (!PyMethod_Check(im)) {
PyErr_BadInternalCall();
return NULL;
}
return ((PyMethodObject *)im)->im_self;
}
PyObject *
PyMethod_Class(register PyObject *im)
{
if (!PyMethod_Check(im)) {
PyErr_BadInternalCall();
return NULL;
}
return ((PyMethodObject *)im)->im_class;
}
/* Class method methods */
#define OFF(x) offsetof(PyMethodObject, x)
@ -2028,43 +2055,52 @@ instancemethod_compare(PyMethodObject *a, PyMethodObject *b)
static PyObject *
instancemethod_repr(PyMethodObject *a)
{
char buf[240];
PyInstanceObject *self = (PyInstanceObject *)(a->im_self);
char buffer[240];
PyObject *self = a->im_self;
PyObject *func = a->im_func;
PyClassObject *class = (PyClassObject *)(a->im_class);
PyObject *fclassname, *iclassname, *funcname;
char *fcname, *icname, *fname;
fclassname = class->cl_name;
if (PyFunction_Check(func)) {
funcname = ((PyFunctionObject *)func)->func_name;
Py_INCREF(funcname);
PyObject *klass = a->im_class;
PyObject *funcname = NULL, *klassname = NULL, *result = NULL;
char *sfuncname = "?", *sklassname = "?";
funcname = PyObject_GetAttrString(func, "__name__");
if (funcname == NULL)
PyErr_Clear();
else if (!PyString_Check(funcname)) {
Py_DECREF(funcname);
funcname = NULL;
}
else {
funcname = PyObject_GetAttrString(func,"__name__");
if (funcname == NULL)
PyErr_Clear();
else
sfuncname = PyString_AS_STRING(funcname);
klassname = PyObject_GetAttrString(klass, "__name__");
if (klassname == NULL)
PyErr_Clear();
else if (!PyString_Check(klassname)) {
Py_DECREF(klassname);
klassname = NULL;
}
if (funcname != NULL && PyString_Check(funcname))
fname = PyString_AS_STRING(funcname);
else
fname = "?";
if (fclassname != NULL && PyString_Check(fclassname))
fcname = PyString_AsString(fclassname);
else
fcname = "?";
sklassname = PyString_AS_STRING(klassname);
if (self == NULL)
sprintf(buf, "<unbound method %.100s.%.100s>", fcname, fname);
sprintf(buffer, "<unbound method %.100s.%.100s>",
sklassname, sfuncname);
else {
iclassname = self->in_class->cl_name;
if (iclassname != NULL && PyString_Check(iclassname))
icname = PyString_AsString(iclassname);
else
icname = "?";
sprintf(buf, "<method %.60s.%.60s of %.60s instance at %p>",
fcname, fname, icname, self);
/* XXX Shouldn't use repr() here! */
PyObject *selfrepr = PyObject_Repr(self);
if (selfrepr == NULL)
goto fail;
if (!PyString_Check(selfrepr)) {
Py_DECREF(selfrepr);
goto fail;
}
sprintf(buffer, "<bound method %.60s.%.60s of %.60s>",
sklassname, sfuncname, PyString_AS_STRING(selfrepr));
Py_DECREF(selfrepr);
}
result = PyString_FromString(buffer);
fail:
Py_XDECREF(funcname);
return PyString_FromString(buf);
Py_XDECREF(klassname);
return result;
}
static long
@ -2105,6 +2141,57 @@ instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg)
return 0;
}
static PyObject *
instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyObject *self = PyMethod_GET_SELF(func);
PyObject *class = PyMethod_GET_CLASS(func);
PyObject *result;
func = PyMethod_GET_FUNCTION(func);
if (self == NULL) {
/* Unbound methods must be called with an instance of
the class (or a derived class) as first argument */
int ok;
if (PyTuple_Size(arg) >= 1)
self = PyTuple_GET_ITEM(arg, 0);
if (self == NULL)
ok = 0;
else {
ok = PyObject_IsInstance(self, class);
if (ok < 0)
return NULL;
}
if (!ok) {
PyErr_Format(PyExc_TypeError,
"unbound method %s%s must be "
"called with instance as first argument",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func));
return NULL;
}
Py_INCREF(arg);
}
else {
int argcount = PyTuple_Size(arg);
PyObject *newarg = PyTuple_New(argcount + 1);
int i;
if (newarg == NULL)
return NULL;
Py_INCREF(self);
PyTuple_SET_ITEM(newarg, 0, self);
for (i = 0; i < argcount; i++) {
PyObject *v = PyTuple_GET_ITEM(arg, i);
Py_XINCREF(v);
PyTuple_SET_ITEM(newarg, i+1, v);
}
arg = newarg;
}
result = PyObject_Call((PyObject *)func, arg, kw);
Py_DECREF(arg);
return result;
}
PyTypeObject PyMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
@ -2121,7 +2208,7 @@ PyTypeObject PyMethod_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)instancemethod_hash, /* tp_hash */
0, /* tp_call */
instancemethod_call, /* tp_call */
0, /* tp_str */
(getattrofunc)instancemethod_getattro, /* tp_getattro */
(setattrofunc)instancemethod_setattro, /* tp_setattro */

View file

@ -8,6 +8,7 @@
#ifndef WITHOUT_COMPLEX
#include "Python.h"
#include "structmember.h"
/* Precisions used by repr() and str(), respectively.
@ -182,6 +183,17 @@ c_powi(Py_complex x, long n)
}
static PyObject *
complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval)
{
PyObject *op;
op = PyType_GenericAlloc(type, 0);
if (op != NULL)
((PyComplexObject *)op)->cval = cval;
return op;
}
PyObject *
PyComplex_FromCComplex(Py_complex cval)
{
@ -196,6 +208,15 @@ PyComplex_FromCComplex(Py_complex cval)
return (PyObject *) op;
}
static PyObject *
complex_subtype_from_doubles(PyTypeObject *type, double real, double imag)
{
Py_complex c;
c.real = real;
c.imag = imag;
return complex_subtype_from_c_complex(type, c);
}
PyObject *
PyComplex_FromDoubles(double real, double imag)
{
@ -559,19 +580,261 @@ static PyMethodDef complex_methods[] = {
{NULL, NULL} /* sentinel */
};
static struct memberlist complex_members[] = {
{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0},
{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0},
{0},
};
static PyObject *
complex_getattr(PyComplexObject *self, char *name)
complex_subtype_from_string(PyTypeObject *type, PyObject *v)
{
if (strcmp(name, "real") == 0)
return (PyObject *)PyFloat_FromDouble(self->cval.real);
else if (strcmp(name, "imag") == 0)
return (PyObject *)PyFloat_FromDouble(self->cval.imag);
else if (strcmp(name, "__members__") == 0)
return Py_BuildValue("[ss]", "imag", "real");
return Py_FindMethod(complex_methods, (PyObject *)self, name);
extern double strtod(const char *, char **);
const char *s, *start;
char *end;
double x=0.0, y=0.0, z;
int got_re=0, got_im=0, done=0;
int digit_or_dot;
int sw_error=0;
int sign;
char buffer[256]; /* For errors */
char s_buffer[256];
int len;
if (PyString_Check(v)) {
s = PyString_AS_STRING(v);
len = PyString_GET_SIZE(v);
}
else if (PyUnicode_Check(v)) {
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
PyErr_SetString(PyExc_ValueError,
"complex() literal too large to convert");
return NULL;
}
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
PyUnicode_GET_SIZE(v),
s_buffer,
NULL))
return NULL;
s = s_buffer;
len = (int)strlen(s);
}
else if (PyObject_AsCharBuffer(v, &s, &len)) {
PyErr_SetString(PyExc_TypeError,
"complex() arg is not a string");
return NULL;
}
/* position on first nonblank */
start = s;
while (*s && isspace(Py_CHARMASK(*s)))
s++;
if (s[0] == '\0') {
PyErr_SetString(PyExc_ValueError,
"complex() arg is an empty string");
return NULL;
}
z = -1.0;
sign = 1;
do {
switch (*s) {
case '\0':
if (s-start != len) {
PyErr_SetString(
PyExc_ValueError,
"complex() arg contains a null byte");
return NULL;
}
if(!done) sw_error=1;
break;
case '-':
sign = -1;
/* Fallthrough */
case '+':
if (done) sw_error=1;
s++;
if ( *s=='\0'||*s=='+'||*s=='-' ||
isspace(Py_CHARMASK(*s)) ) sw_error=1;
break;
case 'J':
case 'j':
if (got_im || done) {
sw_error = 1;
break;
}
if (z<0.0) {
y=sign;
}
else{
y=sign*z;
}
got_im=1;
s++;
if (*s!='+' && *s!='-' )
done=1;
break;
default:
if (isspace(Py_CHARMASK(*s))) {
while (*s && isspace(Py_CHARMASK(*s)))
s++;
if (s[0] != '\0')
sw_error=1;
else
done = 1;
break;
}
digit_or_dot =
(*s=='.' || isdigit(Py_CHARMASK(*s)));
if (done||!digit_or_dot) {
sw_error=1;
break;
}
errno = 0;
PyFPE_START_PROTECT("strtod", return 0)
z = strtod(s, &end) ;
PyFPE_END_PROTECT(z)
if (errno != 0) {
sprintf(buffer,
"float() out of range: %.150s", s);
PyErr_SetString(
PyExc_ValueError,
buffer);
return NULL;
}
s=end;
if (*s=='J' || *s=='j') {
break;
}
if (got_re) {
sw_error=1;
break;
}
/* accept a real part */
x=sign*z;
got_re=1;
if (got_im) done=1;
z = -1.0;
sign = 1;
break;
} /* end of switch */
} while (*s!='\0' && !sw_error);
if (sw_error) {
PyErr_SetString(PyExc_ValueError,
"complex() arg is a malformed string");
return NULL;
}
return complex_subtype_from_doubles(type, x, y);
}
static PyObject *
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *r, *i, *tmp;
PyNumberMethods *nbr, *nbi = NULL;
Py_complex cr, ci;
int own_r = 0;
static char *kwlist[] = {"real", "imag", 0};
r = Py_False;
i = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,
&r, &i))
return NULL;
if (PyString_Check(r) || PyUnicode_Check(r))
return complex_subtype_from_string(type, r);
if ((nbr = r->ob_type->tp_as_number) == NULL ||
nbr->nb_float == NULL ||
(i != NULL &&
((nbi = i->ob_type->tp_as_number) == NULL ||
nbi->nb_float == NULL))) {
PyErr_SetString(PyExc_TypeError,
"complex() arg can't be converted to complex");
return NULL;
}
/* XXX Hack to support classes with __complex__ method */
if (PyInstance_Check(r)) {
static PyObject *complexstr;
PyObject *f;
if (complexstr == NULL) {
complexstr = PyString_InternFromString("__complex__");
if (complexstr == NULL)
return NULL;
}
f = PyObject_GetAttr(r, complexstr);
if (f == NULL)
PyErr_Clear();
else {
PyObject *args = Py_BuildValue("()");
if (args == NULL)
return NULL;
r = PyEval_CallObject(f, args);
Py_DECREF(args);
Py_DECREF(f);
if (r == NULL)
return NULL;
own_r = 1;
}
}
if (PyComplex_Check(r)) {
cr = ((PyComplexObject*)r)->cval;
if (own_r) {
Py_DECREF(r);
}
}
else {
tmp = PyNumber_Float(r);
if (own_r) {
Py_DECREF(r);
}
if (tmp == NULL)
return NULL;
if (!PyFloat_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"float(r) didn't return a float");
Py_DECREF(tmp);
return NULL;
}
cr.real = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
cr.imag = 0.0;
}
if (i == NULL) {
ci.real = 0.0;
ci.imag = 0.0;
}
else if (PyComplex_Check(i))
ci = ((PyComplexObject*)i)->cval;
else {
tmp = (*nbi->nb_float)(i);
if (tmp == NULL)
return NULL;
ci.real = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
ci.imag = 0.;
}
cr.real -= ci.imag;
cr.imag += ci.real;
return complex_subtype_from_c_complex(type, cr);
}
static char complex_doc[] =
"complex(real[, imag]) -> complex number\n\
\n\
Create a complex number from a real part and an optional imaginary part.\n\
This is equivalent to (real + imag*1j) where imag defaults to 0.";
static PyNumberMethods complex_as_number = {
(binaryfunc)complex_add, /* nb_add */
(binaryfunc)complex_sub, /* nb_subtract */
@ -606,7 +869,7 @@ PyTypeObject PyComplex_Type = {
0,
(destructor)complex_dealloc, /* tp_dealloc */
(printfunc)complex_print, /* tp_print */
(getattrfunc)complex_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)complex_repr, /* tp_repr */
@ -616,14 +879,28 @@ PyTypeObject PyComplex_Type = {
(hashfunc)complex_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)complex_str, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
complex_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
complex_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
complex_methods, /* tp_methods */
complex_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
complex_new, /* tp_new */
};
#endif

854
Objects/descrobject.c Normal file
View file

@ -0,0 +1,854 @@
/* Descriptors -- a new, flexible way to describe attributes */
#include "Python.h"
#include "structmember.h" /* Why is this not included in Python.h? */
/* Various kinds of descriptor objects */
#define COMMON \
PyObject_HEAD \
PyTypeObject *d_type; \
PyObject *d_name
typedef struct {
COMMON;
} PyDescrObject;
typedef struct {
COMMON;
PyMethodDef *d_method;
} PyMethodDescrObject;
typedef struct {
COMMON;
struct memberlist *d_member;
} PyMemberDescrObject;
typedef struct {
COMMON;
struct getsetlist *d_getset;
} PyGetSetDescrObject;
typedef struct {
COMMON;
struct wrapperbase *d_base;
void *d_wrapped; /* This can be any function pointer */
} PyWrapperDescrObject;
static void
descr_dealloc(PyDescrObject *descr)
{
Py_XDECREF(descr->d_type);
Py_XDECREF(descr->d_name);
PyObject_DEL(descr);
}
static char *
descr_name(PyDescrObject *descr)
{
if (descr->d_name != NULL && PyString_Check(descr->d_name))
return PyString_AS_STRING(descr->d_name);
else
return "?";
}
static PyObject *
descr_repr(PyDescrObject *descr, char *format)
{
char buffer[500];
sprintf(buffer, format, descr_name(descr), descr->d_type->tp_name);
return PyString_FromString(buffer);
}
static PyObject *
method_repr(PyMethodDescrObject *descr)
{
return descr_repr((PyDescrObject *)descr,
"<method '%.300s' of '%.100s' objects>");
}
static PyObject *
member_repr(PyMemberDescrObject *descr)
{
return descr_repr((PyDescrObject *)descr,
"<member '%.300s' of '%.100s' objects>");
}
static PyObject *
getset_repr(PyGetSetDescrObject *descr)
{
return descr_repr((PyDescrObject *)descr,
"<attribute '%.300s' of '%.100s' objects>");
}
static PyObject *
wrapper_repr(PyWrapperDescrObject *descr)
{
return descr_repr((PyDescrObject *)descr,
"<slot wrapper '%.300s' of '%.100s' objects>");
}
static int
descr_check(PyDescrObject *descr, PyObject *obj, PyTypeObject *type,
PyObject **pres)
{
if (obj == NULL || obj == Py_None) {
Py_INCREF(descr);
*pres = (PyObject *)descr;
return 1;
}
if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.200s' for '%.100s' objects "
"doesn't apply to '%.100s' object",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name,
obj->ob_type->tp_name);
*pres = NULL;
return 1;
}
return 0;
}
static PyObject *
method_get(PyMethodDescrObject *descr, PyObject *obj, PyTypeObject *type)
{
PyObject *res;
if (descr_check((PyDescrObject *)descr, obj, type, &res))
return res;
return PyCFunction_New(descr->d_method, obj);
}
static PyObject *
member_get(PyMemberDescrObject *descr, PyObject *obj, PyTypeObject *type)
{
PyObject *res;
if (descr_check((PyDescrObject *)descr, obj, type, &res))
return res;
return PyMember_Get((char *)obj, descr->d_member,
descr->d_member->name);
}
static PyObject *
getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyTypeObject *type)
{
PyObject *res;
if (descr_check((PyDescrObject *)descr, obj, type, &res))
return res;
if (descr->d_getset->get != NULL)
return descr->d_getset->get(obj, descr->d_getset->closure);
PyErr_Format(PyExc_TypeError,
"attribute '%300s' of '%.100s' objects is not readable",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name);
return NULL;
}
static PyObject *
wrapper_get(PyWrapperDescrObject *descr, PyObject *obj, PyTypeObject *type)
{
PyObject *res;
if (descr_check((PyDescrObject *)descr, obj, type, &res))
return res;
return PyWrapper_New((PyObject *)descr, obj);
}
static int
descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
int *pres)
{
assert(obj != NULL);
if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.200s' for '%.100s' objects "
"doesn't apply to '%.100s' object",
descr_name(descr),
descr->d_type->tp_name,
obj->ob_type->tp_name);
*pres = -1;
return 1;
}
return 0;
}
static int
member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
{
int res;
if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
return res;
return PyMember_Set((char *)obj, descr->d_member,
descr->d_member->name, value);
}
static int
getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
{
int res;
if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
return res;
if (descr->d_getset->set != NULL)
return descr->d_getset->set(obj, value,
descr->d_getset->closure);
PyErr_Format(PyExc_TypeError,
"attribute '%300s' of '%.100s' objects is not writable",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name);
return -1;
}
static PyObject *
methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
{
int argc;
PyObject *self, *func, *result;
/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
argc = PyTuple_GET_SIZE(args);
if (argc < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.300s' of '%.100s' "
"object needs an argument",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name);
return NULL;
}
self = PyTuple_GET_ITEM(args, 0);
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.200s' "
"requires a '%.100s' object "
"but received a '%.100s'",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name,
self->ob_type->tp_name);
return NULL;
}
func = PyCFunction_New(descr->d_method, self);
if (func == NULL)
return NULL;
args = PyTuple_GetSlice(args, 1, argc);
if (args == NULL) {
Py_DECREF(func);
return NULL;
}
result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(args);
Py_DECREF(func);
return result;
}
static PyObject *
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
{
int argc;
PyObject *self, *func, *result;
/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
argc = PyTuple_GET_SIZE(args);
if (argc < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.300s' of '%.100s' "
"object needs an argument",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name);
return NULL;
}
self = PyTuple_GET_ITEM(args, 0);
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%.200s' "
"requires a '%.100s' object "
"but received a '%.100s'",
descr_name((PyDescrObject *)descr),
descr->d_type->tp_name,
self->ob_type->tp_name);
return NULL;
}
func = PyWrapper_New((PyObject *)descr, self);
if (func == NULL)
return NULL;
args = PyTuple_GetSlice(args, 1, argc);
if (args == NULL) {
Py_DECREF(func);
return NULL;
}
result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(args);
Py_DECREF(func);
return result;
}
static PyObject *
member_get_doc(PyMethodDescrObject *descr, void *closure)
{
if (descr->d_method->ml_doc == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromString(descr->d_method->ml_doc);
}
static struct memberlist descr_members[] = {
{"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
{"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
{0}
};
static struct getsetlist member_getset[] = {
{"__doc__", (getter)member_get_doc},
{0}
};
static PyObject *
wrapper_get_doc(PyWrapperDescrObject *descr, void *closure)
{
if (descr->d_base->doc == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromString(descr->d_base->doc);
}
static struct getsetlist wrapper_getset[] = {
{"__doc__", (getter)wrapper_get_doc},
{0}
};
static PyTypeObject PyMethodDescr_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"method_descriptor",
sizeof(PyMethodDescrObject),
0,
(destructor)descr_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)method_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)methoddescr_call, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
descr_members, /* tp_members */
member_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)method_get, /* tp_descr_get */
0, /* tp_descr_set */
};
static PyTypeObject PyMemberDescr_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"member_descriptor",
sizeof(PyMemberDescrObject),
0,
(destructor)descr_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)member_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
descr_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)member_get, /* tp_descr_get */
(descrsetfunc)member_set, /* tp_descr_set */
};
static PyTypeObject PyGetSetDescr_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"getset_descriptor",
sizeof(PyGetSetDescrObject),
0,
(destructor)descr_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)getset_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
descr_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)getset_get, /* tp_descr_get */
(descrsetfunc)getset_set, /* tp_descr_set */
};
static PyTypeObject PyWrapperDescr_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"wrapper_descriptor",
sizeof(PyWrapperDescrObject),
0,
(destructor)descr_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)wrapper_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)wrapperdescr_call, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
descr_members, /* tp_members */
wrapper_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)wrapper_get, /* tp_descr_get */
0, /* tp_descr_set */
};
static PyDescrObject *
descr_new(PyTypeObject *descrtype, PyTypeObject *type, char *name)
{
PyDescrObject *descr;
descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
if (descr != NULL) {
Py_XINCREF(type);
descr->d_type = type;
descr->d_name = PyString_InternFromString(name);
if (descr->d_name == NULL) {
Py_DECREF(descr);
descr = NULL;
}
}
return descr;
}
PyObject *
PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
{
PyMethodDescrObject *descr;
descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
type, method->ml_name);
if (descr != NULL)
descr->d_method = method;
return (PyObject *)descr;
}
PyObject *
PyDescr_NewMember(PyTypeObject *type, struct memberlist *member)
{
PyMemberDescrObject *descr;
descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
type, member->name);
if (descr != NULL)
descr->d_member = member;
return (PyObject *)descr;
}
PyObject *
PyDescr_NewGetSet(PyTypeObject *type, struct getsetlist *getset)
{
PyGetSetDescrObject *descr;
descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
type, getset->name);
if (descr != NULL)
descr->d_getset = getset;
return (PyObject *)descr;
}
PyObject *
PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
{
PyWrapperDescrObject *descr;
descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
type, base->name);
if (descr != NULL) {
descr->d_base = base;
descr->d_wrapped = wrapped;
}
return (PyObject *)descr;
}
int
PyDescr_IsData(PyObject *d)
{
return d->ob_type->tp_descr_set != NULL;
}
/* --- Readonly proxy for dictionaries (actually any mapping) --- */
/* This has no reason to be in this file except that adding new files is a
bit of a pain */
typedef struct {
PyObject_HEAD
PyObject *dict;
} proxyobject;
static int
proxy_len(proxyobject *pp)
{
return PyObject_Size(pp->dict);
}
static PyObject *
proxy_getitem(proxyobject *pp, PyObject *key)
{
return PyObject_GetItem(pp->dict, key);
}
static PyMappingMethods proxy_as_mapping = {
(inquiry)proxy_len, /* mp_length */
(binaryfunc)proxy_getitem, /* mp_subscript */
0, /* mp_ass_subscript */
};
static int
proxy_contains(proxyobject *pp, PyObject *key)
{
return PySequence_Contains(pp->dict, key);
}
static PySequenceMethods proxy_as_sequence = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)proxy_contains, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
static PyObject *
proxy_has_key(proxyobject *pp, PyObject *args)
{
PyObject *key;
if (!PyArg_ParseTuple(args, "O:has_key", &key))
return NULL;
return PyInt_FromLong(PySequence_Contains(pp->dict, key));
}
static PyObject *
proxy_get(proxyobject *pp, PyObject *args)
{
PyObject *key, *def = Py_None;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
return NULL;
return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def);
}
static PyObject *
proxy_keys(proxyobject *pp, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":keys"))
return NULL;
return PyMapping_Keys(pp->dict);
}
static PyObject *
proxy_values(proxyobject *pp, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":values"))
return NULL;
return PyMapping_Values(pp->dict);
}
static PyObject *
proxy_items(proxyobject *pp, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":items"))
return NULL;
return PyMapping_Items(pp->dict);
}
static PyObject *
proxy_copy(proxyobject *pp, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":copy"))
return NULL;
return PyObject_CallMethod(pp->dict, "copy", NULL);
}
static PyMethodDef proxy_methods[] = {
{"has_key", (PyCFunction)proxy_has_key, METH_VARARGS, "XXX"},
{"get", (PyCFunction)proxy_get, METH_VARARGS, "XXX"},
{"keys", (PyCFunction)proxy_keys, METH_VARARGS, "XXX"},
{"values", (PyCFunction)proxy_values, METH_VARARGS, "XXX"},
{"items", (PyCFunction)proxy_items, METH_VARARGS, "XXX"},
{"copy", (PyCFunction)proxy_copy, METH_VARARGS, "XXX"},
{0}
};
static void
proxy_dealloc(proxyobject *pp)
{
Py_DECREF(pp->dict);
PyObject_DEL(pp);
}
static PyObject *
proxy_getiter(proxyobject *pp)
{
return PyObject_GetIter(pp->dict);
}
PyObject *
proxy_str(proxyobject *pp)
{
return PyObject_Str(pp->dict);
}
PyTypeObject proxytype = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
"dict-proxy", /* tp_name */
sizeof(proxyobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)proxy_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
&proxy_as_sequence, /* tp_as_sequence */
&proxy_as_mapping, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
(reprfunc)proxy_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)proxy_getiter, /* tp_iter */
0, /* tp_iternext */
proxy_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
};
PyObject *
PyDictProxy_New(PyObject *dict)
{
proxyobject *pp;
pp = PyObject_NEW(proxyobject, &proxytype);
if (pp != NULL) {
Py_INCREF(dict);
pp->dict = dict;
}
return (PyObject *)pp;
}
/* --- Wrapper object for "slot" methods --- */
/* This has no reason to be in this file except that adding new files is a
bit of a pain */
typedef struct {
PyObject_HEAD
PyWrapperDescrObject *descr;
PyObject *self;
} wrapperobject;
static void
wrapper_dealloc(wrapperobject *wp)
{
Py_XDECREF(wp->descr);
Py_XDECREF(wp->self);
PyObject_DEL(wp);
}
static PyMethodDef wrapper_methods[] = {
{0}
};
static PyObject *
wrapper_name(wrapperobject *wp)
{
char *s = wp->descr->d_base->name;
return PyString_FromString(s);
}
static PyObject *
wrapper_doc(wrapperobject *wp)
{
char *s = wp->descr->d_base->doc;
if (s == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
else {
return PyString_FromString(s);
}
}
static struct getsetlist wrapper_getsets[] = {
{"__name__", (getter)wrapper_name},
{"__doc__", (getter)wrapper_doc},
{0}
};
static PyObject *
wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
{
wrapperfunc wrapper = wp->descr->d_base->wrapper;
PyObject *self = wp->self;
return (*wrapper)(self, args, wp->descr->d_wrapped);
}
PyTypeObject wrappertype = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
"method-wrapper", /* tp_name */
sizeof(wrapperobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)wrapper_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)wrapper_call, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
wrapper_methods, /* tp_methods */
0, /* tp_members */
wrapper_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
};
PyObject *
PyWrapper_New(PyObject *d, PyObject *self)
{
wrapperobject *wp;
PyWrapperDescrObject *descr;
assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
descr = (PyWrapperDescrObject *)d;
assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
wp = PyObject_NEW(wrapperobject, &wrappertype);
if (wp != NULL) {
Py_INCREF(descr);
wp->descr = descr;
Py_INCREF(self);
wp->self = self;
}
return (PyObject *)wp;
}

View file

@ -3,15 +3,8 @@
#include "Python.h"
/* MINSIZE is the minimum size of a dictionary. This many slots are
* allocated directly in the dict object (in the ma_smalltable member).
* It must be a power of 2, and at least 4. 8 allows dicts with no more than
* 5 active entries to live in ma_smalltable (and so avoid an additional
* malloc); instrumentation suggested this suffices for the majority of
* dicts (consisting mostly of usually-small instance dicts and usually-small
* dicts created to pass keyword arguments).
*/
#define MINSIZE 8
typedef PyDictEntry dictentry;
typedef PyDictObject dictobject;
/* Define this out if you don't want conversion statistics on exit. */
#undef SHOW_CONVERSION_COUNTS
@ -116,69 +109,6 @@ equally good collision statistics, needed less code & used less memory.
/* Object used as dummy key to fill deleted entries */
static PyObject *dummy; /* Initialized by first call to newdictobject() */
/*
There are three kinds of slots in the table:
1. Unused. me_key == me_value == NULL
Does not hold an active (key, value) pair now and never did. Unused can
transition to Active upon key insertion. This is the only case in which
me_key is NULL, and is each slot's initial state.
2. Active. me_key != NULL and me_key != dummy and me_value != NULL
Holds an active (key, value) pair. Active can transition to Dummy upon
key deletion. This is the only case in which me_value != NULL.
3. Dummy. me_key == dummy and me_value == NULL
Previously held an active (key, value) pair, but that was deleted and an
active pair has not yet overwritten the slot. Dummy can transition to
Active upon key insertion. Dummy slots cannot be made Unused again
(cannot have me_key set to NULL), else the probe sequence in case of
collision would have no way to know they were once active.
Note: .popitem() abuses the me_hash field of an Unused or Dummy slot to
hold a search finger. The me_hash field of Unused or Dummy slots has no
meaning otherwise.
*/
typedef struct {
long me_hash; /* cached hash code of me_key */
PyObject *me_key;
PyObject *me_value;
#ifdef USE_CACHE_ALIGNED
long aligner;
#endif
} dictentry;
/*
To ensure the lookup algorithm terminates, there must be at least one Unused
slot (NULL key) in the table.
The value ma_fill is the number of non-NULL keys (sum of Active and Dummy);
ma_used is the number of non-NULL, non-dummy keys (== the number of non-NULL
values == the number of Active items).
To avoid slowing down lookups on a near-full table, we resize the table when
it's two-thirds full.
*/
typedef struct dictobject dictobject;
struct dictobject {
PyObject_HEAD
int ma_fill; /* # Active + # Dummy */
int ma_used; /* # Active */
/* The table contains ma_mask + 1 slots, and that's a power of 2.
* We store the mask instead of the size because the mask is more
* frequently needed.
*/
int ma_mask;
/* ma_table points to ma_smalltable for small tables, else to
* additional malloc'ed memory. ma_table is never NULL! This rule
* saves repeated runtime null-tests in the workhorse getitem and
* setitem calls.
*/
dictentry *ma_table;
dictentry *(*ma_lookup)(dictobject *mp, PyObject *key, long hash);
dictentry ma_smalltable[MINSIZE];
};
/* forward declarations */
static dictentry *
lookdict_string(dictobject *mp, PyObject *key, long hash);
@ -196,12 +126,24 @@ show_counts(void)
}
#endif
/* Set dictobject* mp to empty but w/ MINSIZE slots, using ma_smalltable. */
#define empty_to_minsize(mp) do { \
memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \
/* Initialization macros.
There are two ways to create a dict: PyDict_New() is the main C API
function, and the tp_new slot maps to dict_new(). In the latter case we
can save a little time over what PyDict_New does because it's guaranteed
that the PyDictObject struct is already zeroed out.
Everyone except dict_new() should use EMPTY_TO_MINSIZE (unless they have
an excellent reason not to).
*/
#define INIT_NONZERO_DICT_SLOTS(mp) do { \
(mp)->ma_table = (mp)->ma_smalltable; \
(mp)->ma_mask = MINSIZE - 1; \
(mp)->ma_mask = PyDict_MINSIZE - 1; \
} while(0)
#define EMPTY_TO_MINSIZE(mp) do { \
memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \
(mp)->ma_used = (mp)->ma_fill = 0; \
INIT_NONZERO_DICT_SLOTS(mp); \
} while(0)
PyObject *
@ -219,7 +161,7 @@ PyDict_New(void)
mp = PyObject_NEW(dictobject, &PyDict_Type);
if (mp == NULL)
return NULL;
empty_to_minsize(mp);
EMPTY_TO_MINSIZE(mp);
mp->ma_lookup = lookdict_string;
#ifdef SHOW_CONVERSION_COUNTS
++created;
@ -418,7 +360,10 @@ insertdict(register dictobject *mp, PyObject *key, long hash, PyObject *value)
{
PyObject *old_value;
register dictentry *ep;
ep = (mp->ma_lookup)(mp, key, hash);
typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, long);
assert(mp->ma_lookup != NULL);
ep = mp->ma_lookup(mp, key, hash);
if (ep->me_value != NULL) {
old_value = ep->me_value;
ep->me_value = value;
@ -449,12 +394,12 @@ dictresize(dictobject *mp, int minused)
dictentry *oldtable, *newtable, *ep;
int i;
int is_oldtable_malloced;
dictentry small_copy[MINSIZE];
dictentry small_copy[PyDict_MINSIZE];
assert(minused >= 0);
/* Find the smallest table size > minused. */
for (newsize = MINSIZE;
for (newsize = PyDict_MINSIZE;
newsize <= minused && newsize > 0;
newsize <<= 1)
;
@ -468,7 +413,7 @@ dictresize(dictobject *mp, int minused)
assert(oldtable != NULL);
is_oldtable_malloced = oldtable != mp->ma_smalltable;
if (newsize == MINSIZE) {
if (newsize == PyDict_MINSIZE) {
/* A large table is shrinking, or we can't get any smaller. */
newtable = mp->ma_smalltable;
if (newtable == oldtable) {
@ -649,7 +594,7 @@ PyDict_Clear(PyObject *op)
dictentry *ep, *table;
int table_is_malloced;
int fill;
dictentry small_copy[MINSIZE];
dictentry small_copy[PyDict_MINSIZE];
#ifdef Py_DEBUG
int i, n;
#endif
@ -674,7 +619,7 @@ PyDict_Clear(PyObject *op)
*/
fill = mp->ma_fill;
if (table_is_malloced)
empty_to_minsize(mp);
EMPTY_TO_MINSIZE(mp);
else if (fill > 0) {
/* It's a small table with something that needs to be cleared.
@ -683,7 +628,7 @@ PyDict_Clear(PyObject *op)
*/
memcpy(small_copy, table, sizeof(small_copy));
table = small_copy;
empty_to_minsize(mp);
EMPTY_TO_MINSIZE(mp);
}
/* else it's a small table that's already empty */
@ -1042,32 +987,47 @@ dict_items(register dictobject *mp, PyObject *args)
}
static PyObject *
dict_update(register dictobject *mp, PyObject *args)
dict_update(PyObject *mp, PyObject *args)
{
PyObject *other;
if (!PyArg_ParseTuple(args, "O:update", &other))
return NULL;
if (PyDict_Update(mp, other) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
int
PyDict_Update(PyObject *a, PyObject *b)
{
register PyDictObject *mp, *other;
register int i;
dictobject *other;
dictentry *entry;
PyObject *param;
/* We accept for the argument either a concrete dictionary object,
* or an abstract "mapping" object. For the former, we can do
* things quite efficiently. For the latter, we only require that
* PyMapping_Keys() and PyObject_GetItem() be supported.
*/
if (!PyArg_ParseTuple(args, "O:update", &param))
return NULL;
if (PyDict_Check(param)) {
other = (dictobject*)param;
if (a == NULL || !PyDict_Check(a) || b == NULL) {
PyErr_BadInternalCall();
return -1;
}
mp = (dictobject*)a;
if (PyDict_Check(b)) {
other = (dictobject*)b;
if (other == mp || other->ma_used == 0)
/* a.update(a) or a.update({}); nothing to do */
goto done;
return 0;
/* Do one big resize at the start, rather than
* incrementally resizing as we insert new items. Expect
* that there will be no (or few) overlapping keys.
*/
if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) {
if (dictresize(mp, (mp->ma_used + other->ma_used)*3/2) != 0)
return NULL;
return -1;
}
for (i = 0; i <= other->ma_mask; i++) {
entry = &other->ma_table[i];
@ -1081,7 +1041,7 @@ dict_update(register dictobject *mp, PyObject *args)
}
else {
/* Do it the generic, slower way */
PyObject *keys = PyMapping_Keys(param);
PyObject *keys = PyMapping_Keys(b);
PyObject *iter;
PyObject *key, *value;
int status;
@ -1092,37 +1052,34 @@ dict_update(register dictobject *mp, PyObject *args)
* AttributeError to percolate up. Might as well
* do the same for any other error.
*/
return NULL;
return -1;
iter = PyObject_GetIter(keys);
Py_DECREF(keys);
if (iter == NULL)
return NULL;
return -1;
for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
value = PyObject_GetItem(param, key);
value = PyObject_GetItem(b, key);
if (value == NULL) {
Py_DECREF(iter);
Py_DECREF(key);
return NULL;
return -1;
}
status = PyDict_SetItem((PyObject*)mp, key, value);
Py_DECREF(key);
Py_DECREF(value);
if (status < 0) {
Py_DECREF(iter);
return NULL;
return -1;
}
}
Py_DECREF(iter);
if (PyErr_Occurred())
/* Iterator completed, via error */
return NULL;
return -1;
}
done:
Py_INCREF(Py_None);
return Py_None;
return 0;
}
static PyObject *
@ -1694,12 +1651,6 @@ static PyMethodDef mapp_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *
dict_getattr(dictobject *mp, char *name)
{
return Py_FindMethod(mapp_methods, (PyObject *)mp, name);
}
static int
dict_contains(dictobject *mp, PyObject *key)
{
@ -1731,6 +1682,26 @@ static PySequenceMethods dict_as_sequence = {
0, /* sq_inplace_repeat */
};
static PyObject *
dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *self;
assert(type != NULL && type->tp_alloc != NULL);
self = type->tp_alloc(type, 0);
if (self != NULL) {
PyDictObject *d = (PyDictObject *)self;
/* It's guaranteed that tp->alloc zeroed out the struct. */
assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0);
INIT_NONZERO_DICT_SLOTS(d);
d->ma_lookup = lookdict_string;
#ifdef SHOW_CONVERSION_COUNTS
++created;
#endif
}
return self;
}
static PyObject *
dict_iter(dictobject *dict)
{
@ -1745,7 +1716,7 @@ PyTypeObject PyDict_Type = {
0,
(destructor)dict_dealloc, /* tp_dealloc */
(printfunc)dict_print, /* tp_print */
(getattrfunc)dict_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)dict_compare, /* tp_compare */
(reprfunc)dict_repr, /* tp_repr */
@ -1755,17 +1726,29 @@ PyTypeObject PyDict_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
"dictionary type", /* tp_doc */
(traverseproc)dict_traverse, /* tp_traverse */
(inquiry)dict_tp_clear, /* tp_clear */
dict_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dict_iter, /* tp_iter */
0, /* tp_iternext */
mapp_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
dict_new, /* tp_new */
};
/* For backward compatibility with old dictionary interface */
@ -1873,12 +1856,6 @@ static PyMethodDef dictiter_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *
dictiter_getattr(dictiterobject *di, char *name)
{
return Py_FindMethod(dictiter_methods, (PyObject *)di, name);
}
static PyObject *dictiter_iternext(dictiterobject *di)
{
PyObject *key, *value;
@ -1903,7 +1880,7 @@ PyTypeObject PyDictIter_Type = {
/* methods */
(destructor)dictiter_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)dictiter_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
@ -1913,7 +1890,7 @@ PyTypeObject PyDictIter_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
@ -1924,4 +1901,11 @@ PyTypeObject PyDictIter_Type = {
0, /* tp_weaklistoffset */
(getiterfunc)dictiter_getiter, /* tp_iter */
(iternextfunc)dictiter_iternext, /* tp_iternext */
dictiter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
};

View file

@ -1273,29 +1273,15 @@ static struct memberlist file_memberlist[] = {
};
static PyObject *
file_getattr(PyFileObject *f, char *name)
get_closed(PyFileObject *f, void *closure)
{
PyObject *res;
res = Py_FindMethod(file_methods, (PyObject *)f, name);
if (res != NULL)
return res;
PyErr_Clear();
if (strcmp(name, "closed") == 0)
return PyInt_FromLong((long)(f->f_fp == 0));
return PyMember_Get((char *)f, file_memberlist, name);
return PyInt_FromLong((long)(f->f_fp == 0));
}
static int
file_setattr(PyFileObject *f, char *name, PyObject *v)
{
if (v == NULL) {
PyErr_SetString(PyExc_AttributeError,
"can't delete file attributes");
return -1;
}
return PyMember_Set((char *)f, file_memberlist, name, v);
}
static struct getsetlist file_getsetlist[] = {
{"closed", (getter)get_closed, NULL, NULL},
{0},
};
static PyObject *
file_getiter(PyObject *f)
@ -1311,27 +1297,32 @@ PyTypeObject PyFile_Type = {
0,
(destructor)file_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)file_getattr, /* tp_getattr */
(setattrfunc)file_setattr, /* tp_setattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)file_repr, /* tp_repr */
(reprfunc)file_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
file_getiter, /* tp_iter */
0, /* tp_iternext */
file_methods, /* tp_methods */
file_memberlist, /* tp_members */
file_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};
/* Interface for the 'soft space' between print items. */

View file

@ -636,6 +636,26 @@ float_float(PyObject *v)
}
static PyObject *
float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = Py_False; /* Integer zero */
static char *kwlist[] = {"x", 0};
assert(type == &PyFloat_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
return NULL;
if (PyString_Check(x))
return PyFloat_FromString(x, NULL);
return PyNumber_Float(x);
}
static char float_doc[] =
"float(x) -> floating point number\n\
\n\
Convert a string or number to a floating point number, if possible.";
static PyNumberMethods float_as_number = {
(binaryfunc)float_add, /*nb_add*/
(binaryfunc)float_sub, /*nb_subtract*/
@ -679,22 +699,40 @@ PyTypeObject PyFloat_Type = {
"float",
sizeof(PyFloatObject),
0,
(destructor)float_dealloc, /*tp_dealloc*/
(printfunc)float_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)float_compare, /*tp_compare*/
(reprfunc)float_repr, /*tp_repr*/
&float_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)float_hash, /*tp_hash*/
0, /*tp_call*/
(reprfunc)float_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_CHECKTYPES /*tp_flags*/
(destructor)float_dealloc, /* tp_dealloc */
(printfunc)float_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)float_compare, /* tp_compare */
(reprfunc)float_repr, /* tp_repr */
&float_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)float_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)float_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
float_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
float_new, /* tp_new */
};
void

View file

@ -15,7 +15,6 @@ static struct memberlist frame_memberlist[] = {
{"f_code", T_OBJECT, OFF(f_code), RO},
{"f_builtins", T_OBJECT, OFF(f_builtins),RO},
{"f_globals", T_OBJECT, OFF(f_globals), RO},
{"f_locals", T_OBJECT, OFF(f_locals), RO},
{"f_lasti", T_INT, OFF(f_lasti), RO},
{"f_lineno", T_INT, OFF(f_lineno), RO},
{"f_restricted",T_INT, OFF(f_restricted),RO},
@ -27,18 +26,17 @@ static struct memberlist frame_memberlist[] = {
};
static PyObject *
frame_getattr(PyFrameObject *f, char *name)
frame_getlocals(PyFrameObject *f, void *closure)
{
if (strcmp(name, "f_locals") == 0)
PyFrame_FastToLocals(f);
return PyMember_Get((char *)f, frame_memberlist, name);
PyFrame_FastToLocals(f);
Py_INCREF(f->f_locals);
return f->f_locals;
}
static int
frame_setattr(PyFrameObject *f, char *name, PyObject *value)
{
return PyMember_Set((char *)f, frame_memberlist, name, value);
}
static struct getsetlist frame_getsetlist[] = {
{"f_locals", (getter)frame_getlocals, NULL, NULL},
{0}
};
/* Stack frames are allocated and deallocated at a considerable rate.
In an attempt to improve the speed of function calls, we maintain a
@ -177,8 +175,8 @@ PyTypeObject PyFrame_Type = {
0,
(destructor)frame_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)frame_getattr, /* tp_getattr */
(setattrfunc)frame_setattr, /* tp_setattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
@ -187,13 +185,22 @@ PyTypeObject PyFrame_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
PyObject_GenericGetAttr, /* tp_getattro */
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)frame_traverse, /* tp_traverse */
(inquiry)frame_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
frame_memberlist, /* tp_members */
frame_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};
PyFrameObject *

View file

@ -3,6 +3,7 @@
#include "Python.h"
#include "compile.h"
#include "eval.h"
#include "structmember.h"
PyObject *
@ -141,9 +142,8 @@ static struct memberlist func_memberlist[] = {
};
static PyObject *
func_getattro(PyFunctionObject *op, PyObject *name)
func_getattro(PyObject *op, PyObject *name)
{
PyObject *rtn;
char *sname = PyString_AsString(name);
if (sname[0] != '_' && PyEval_GetRestricted()) {
@ -152,25 +152,12 @@ func_getattro(PyFunctionObject *op, PyObject *name)
return NULL;
}
/* no API for PyMember_HasAttr() */
rtn = PyMember_Get((char *)op, func_memberlist, sname);
if (rtn == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
if (op->func_dict != NULL) {
rtn = PyDict_GetItem(op->func_dict, name);
Py_XINCREF(rtn);
}
if (rtn == NULL)
PyErr_SetObject(PyExc_AttributeError, name);
}
return rtn;
return PyObject_GenericGetAttr(op, name);
}
static int
func_setattro(PyFunctionObject *op, PyObject *name, PyObject *value)
func_setattro(PyObject *op, PyObject *name, PyObject *value)
{
int rtn;
char *sname = PyString_AsString(name);
if (PyEval_GetRestricted()) {
@ -216,31 +203,7 @@ func_setattro(PyFunctionObject *op, PyObject *name, PyObject *value)
}
}
rtn = PyMember_Set((char *)op, func_memberlist, sname, value);
if (rtn < 0 && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
if (op->func_dict == NULL) {
/* don't create the dict if we're deleting an
* attribute. In that case, we know we'll get an
* AttributeError.
*/
if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, sname);
return -1;
}
op->func_dict = PyDict_New();
if (op->func_dict == NULL)
return -1;
}
if (value == NULL)
rtn = PyDict_DelItem(op->func_dict, name);
else
rtn = PyDict_SetItem(op->func_dict, name, value);
/* transform KeyError into AttributeError */
if (rtn < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_SetString(PyExc_AttributeError, sname);
}
return rtn;
return PyObject_GenericSetAttr(op, name, value);
}
static void
@ -314,31 +277,324 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
return 0;
}
static PyObject *
function_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyObject *result;
PyObject *argdefs;
PyObject **d, **k;
int nk, nd;
argdefs = PyFunction_GET_DEFAULTS(func);
if (argdefs != NULL && PyTuple_Check(argdefs)) {
d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0);
nd = PyTuple_Size(argdefs);
}
else {
d = NULL;
nd = 0;
}
if (kw != NULL && PyDict_Check(kw)) {
int pos, i;
nk = PyDict_Size(kw);
k = PyMem_NEW(PyObject *, 2*nk);
if (k == NULL) {
PyErr_NoMemory();
Py_DECREF(arg);
return NULL;
}
pos = i = 0;
while (PyDict_Next(kw, &pos, &k[i], &k[i+1]))
i += 2;
nk = i/2;
/* XXX This is broken if the caller deletes dict items! */
}
else {
k = NULL;
nk = 0;
}
result = PyEval_EvalCodeEx(
(PyCodeObject *)PyFunction_GET_CODE(func),
PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
&PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg),
k, nk, d, nd,
PyFunction_GET_CLOSURE(func));
if (k != NULL)
PyMem_DEL(k);
return result;
}
/* Bind a function to an object */
static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
if (obj == Py_None)
obj = NULL;
return PyMethod_New(func, obj, type);
}
PyTypeObject PyFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"function",
sizeof(PyFunctionObject) + PyGC_HEAD_SIZE,
0,
(destructor)func_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
(getattrofunc)func_getattro, /* tp_getattro */
(setattrofunc)func_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
(destructor)func_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
function_call, /* tp_call */
0, /* tp_str */
func_getattro, /* tp_getattro */
func_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
func_memberlist, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
func_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
};
/* Class method object */
/* A class method receives the class as implicit first argument,
just like an instance method receives the instance.
To declare a class method, use this idiom:
class C:
def f(cls, arg1, arg2, ...): ...
f = classmethod(f)
It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()); the instance is ignored except for its class.
If a class method is called for a derived class, the derived class
object is passed as the implied first argument.
Class methods are different than C++ or Java static methods.
If you want those, see static methods below.
*/
typedef struct {
PyObject_HEAD
PyObject *cm_callable;
} classmethod;
static void
cm_dealloc(classmethod *cm)
{
Py_XDECREF(cm->cm_callable);
PyObject_DEL(cm);
}
static PyObject *
cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
classmethod *cm = (classmethod *)self;
if (cm->cm_callable == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"uninitialized classmethod object");
return NULL;
}
return PyMethod_New(cm->cm_callable,
type, (PyObject *)(type->ob_type));
}
static int
cm_init(PyObject *self, PyObject *args, PyObject *kwds)
{
classmethod *cm = (classmethod *)self;
PyObject *callable;
if (!PyArg_ParseTuple(args, "O:callable", &callable))
return -1;
Py_INCREF(callable);
cm->cm_callable = callable;
return 0;
}
PyTypeObject PyClassMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"classmethod",
sizeof(classmethod),
0,
(destructor)cm_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
cm_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
cm_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};
PyObject *
PyClassMethod_New(PyObject *callable)
{
classmethod *cm = (classmethod *)
PyType_GenericAlloc(&PyClassMethod_Type, 0);
if (cm != NULL) {
Py_INCREF(callable);
cm->cm_callable = callable;
}
return (PyObject *)cm;
}
/* Static method object */
/* A static method does not receive an implicit first argument.
To declare a static method, use this idiom:
class C:
def f(arg1, arg2, ...): ...
f = staticmethod(f)
It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()); the instance is ignored except for its class.
Static methods in Python are similar to those found in Java or C++.
For a more advanced concept, see class methods above.
*/
typedef struct {
PyObject_HEAD
PyObject *sm_callable;
} staticmethod;
static void
sm_dealloc(staticmethod *sm)
{
Py_XDECREF(sm->sm_callable);
PyObject_DEL(sm);
}
static PyObject *
sm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
staticmethod *sm = (staticmethod *)self;
if (sm->sm_callable == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"uninitialized staticmethod object");
return NULL;
}
Py_INCREF(sm->sm_callable);
return sm->sm_callable;
}
static int
sm_init(PyObject *self, PyObject *args, PyObject *kwds)
{
staticmethod *sm = (staticmethod *)self;
PyObject *callable;
if (!PyArg_ParseTuple(args, "O:callable", &callable))
return -1;
Py_INCREF(callable);
sm->sm_callable = callable;
return 0;
}
PyTypeObject PyStaticMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"staticmethod",
sizeof(staticmethod),
0,
(destructor)sm_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
sm_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
sm_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};
PyObject *
PyStaticMethod_New(PyObject *callable)
{
staticmethod *sm = (staticmethod *)
PyType_GenericAlloc(&PyStaticMethod_Type, 0);
if (sm != NULL) {
Py_INCREF(callable);
sm->sm_callable = callable;
}
return (PyObject *)sm;
}

View file

@ -742,6 +742,41 @@ int_hex(PyIntObject *v)
return PyString_FromString(buf);
}
static PyObject *
int_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = NULL;
int base = -909;
static char *kwlist[] = {"x", "base", 0};
assert(type == &PyInt_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,
&x, &base))
return NULL;
if (x == NULL)
return PyInt_FromLong(0L);
if (base == -909)
return PyNumber_Int(x);
if (PyString_Check(x))
return PyInt_FromString(PyString_AS_STRING(x), NULL, base);
if (PyUnicode_Check(x))
return PyInt_FromUnicode(PyUnicode_AS_UNICODE(x),
PyUnicode_GET_SIZE(x),
base);
PyErr_SetString(PyExc_TypeError,
"int() can't convert non-string with explicit base");
return NULL;
}
static char int_doc[] =
"int(x[, base]) -> integer\n\
\n\
Convert a string or number to an integer, if possible. A floating point\n\
argument will be truncated towards zero (this does not include a string\n\
representation of a floating point number!) When converting a string, use\n\
the optional base. It is an error to supply a base when converting a\n\
non-string.";
static PyNumberMethods int_as_number = {
(binaryfunc)int_add, /*nb_add*/
(binaryfunc)int_sub, /*nb_subtract*/
@ -785,22 +820,40 @@ PyTypeObject PyInt_Type = {
"int",
sizeof(PyIntObject),
0,
(destructor)int_dealloc, /*tp_dealloc*/
(printfunc)int_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)int_compare, /*tp_compare*/
(reprfunc)int_repr, /*tp_repr*/
&int_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)int_hash, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_CHECKTYPES /*tp_flags*/
(destructor)int_dealloc, /* tp_dealloc */
(printfunc)int_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)int_compare, /* tp_compare */
(reprfunc)int_repr, /* tp_repr */
&int_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)int_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
int_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
int_new, /* tp_new */
};
void

View file

@ -96,12 +96,6 @@ static PyMethodDef iter_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *
iter_getattr(seqiterobject *it, char *name)
{
return Py_FindMethod(iter_methods, (PyObject *)it, name);
}
PyTypeObject PySeqIter_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
@ -111,7 +105,7 @@ PyTypeObject PySeqIter_Type = {
/* methods */
(destructor)iter_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)iter_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
@ -121,7 +115,7 @@ PyTypeObject PySeqIter_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
@ -132,6 +126,13 @@ PyTypeObject PySeqIter_Type = {
0, /* tp_weaklistoffset */
(getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)iter_iternext, /* tp_iternext */
iter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
};
/* -------------------------------------- */
@ -197,12 +198,6 @@ static PyMethodDef calliter_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *
calliter_getattr(calliterobject *it, char *name)
{
return Py_FindMethod(calliter_methods, (PyObject *)it, name);
}
static PyObject *
calliter_iternext(calliterobject *it)
{
@ -228,7 +223,7 @@ PyTypeObject PyCallIter_Type = {
/* methods */
(destructor)calliter_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)calliter_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
@ -238,7 +233,7 @@ PyTypeObject PyCallIter_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
@ -249,4 +244,11 @@ PyTypeObject PyCallIter_Type = {
0, /* tp_weaklistoffset */
(getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)calliter_iternext, /* tp_iternext */
calliter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
};

View file

@ -523,6 +523,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
Py_XDECREF(*p);
PyMem_DEL(recycle);
}
if (a->ob_size == 0 && a->ob_item != NULL) {
PyMem_FREE(a->ob_item);
a->ob_item = NULL;
}
return 0;
#undef b
}
@ -1289,16 +1293,18 @@ listsort(PyListObject *self, PyObject *args)
{
int err;
PyObject *compare = NULL;
PyTypeObject *savetype;
if (args != NULL) {
if (!PyArg_ParseTuple(args, "|O:sort", &compare))
return NULL;
}
savetype = self->ob_type;
self->ob_type = &immutable_list_type;
err = samplesortslice(self->ob_item,
self->ob_item + self->ob_size,
compare);
self->ob_type = &PyList_Type;
self->ob_type = savetype;
if (err < 0)
return NULL;
Py_INCREF(Py_None);
@ -1541,6 +1547,100 @@ list_richcompare(PyObject *v, PyObject *w, int op)
return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
}
/* Adapted from newer code by Tim */
static int
list_fill(PyListObject *result, PyObject *v)
{
PyObject *it; /* iter(v) */
int n; /* guess for result list size */
int i;
n = result->ob_size;
/* Special-case list(a_list), for speed. */
if (PyList_Check(v)) {
if (v == (PyObject *)result)
return 0; /* source is destination, we're done */
return list_ass_slice(result, 0, n, v);
}
/* Empty previous contents */
if (n != 0) {
if (list_ass_slice(result, 0, n, (PyObject *)NULL) != 0)
return -1;
}
/* Get iterator. There may be some low-level efficiency to be gained
* by caching the tp_iternext slot instead of using PyIter_Next()
* later, but premature optimization is the root etc.
*/
it = PyObject_GetIter(v);
if (it == NULL)
return -1;
/* Guess a result list size. */
n = -1; /* unknown */
if (PySequence_Check(v) &&
v->ob_type->tp_as_sequence->sq_length) {
n = PySequence_Size(v);
if (n < 0)
PyErr_Clear();
}
if (n < 0)
n = 8; /* arbitrary */
NRESIZE(result->ob_item, PyObject*, n);
if (result->ob_item == NULL)
goto error;
for (i = 0; i < n; i++)
result->ob_item[i] = NULL;
result->ob_size = n;
/* Run iterator to exhaustion. */
for (i = 0; ; i++) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred())
goto error;
break;
}
if (i < n)
PyList_SET_ITEM(result, i, item); /* steals ref */
else {
int status = ins1(result, result->ob_size, item);
Py_DECREF(item); /* append creates a new ref */
if (status < 0)
goto error;
}
}
/* Cut back result list if initial guess was too large. */
if (i < n && result != NULL) {
if (list_ass_slice(result, i, n, (PyObject *)NULL) != 0)
goto error;
}
Py_DECREF(it);
return 0;
error:
Py_DECREF(it);
return -1;
}
static int
list_init(PyListObject *self, PyObject *args, PyObject *kw)
{
PyObject *arg = NULL;
static char *kwlist[] = {"sequence", 0};
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
return -1;
if (arg != NULL)
return list_fill(self, arg);
if (self->ob_size > 0)
return list_ass_slice(self, 0, self->ob_size, (PyObject*)NULL);
return 0;
}
static char append_doc[] =
"L.append(object) -- append object to end";
static char extend_doc[] =
@ -1573,12 +1673,6 @@ static PyMethodDef list_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *
list_getattr(PyListObject *f, char *name)
{
return Py_FindMethod(list_methods, (PyObject *)f, name);
}
static PySequenceMethods list_as_sequence = {
(inquiry)list_length, /* sq_length */
(binaryfunc)list_concat, /* sq_concat */
@ -1592,6 +1686,10 @@ static PySequenceMethods list_as_sequence = {
(intargfunc)list_inplace_repeat, /* sq_inplace_repeat */
};
static char list_doc[] =
"list() -> new list\n"
"list(sequence) -> new list initialized from sequence's items";
PyTypeObject PyList_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
@ -1600,7 +1698,7 @@ PyTypeObject PyList_Type = {
0,
(destructor)list_dealloc, /* tp_dealloc */
(printfunc)list_print, /* tp_print */
(getattrfunc)list_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)list_repr, /* tp_repr */
@ -1610,14 +1708,29 @@ PyTypeObject PyList_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
(inquiry)list_clear, /* tp_clear */
list_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
list_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)list_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};
@ -1646,12 +1759,6 @@ static PyMethodDef immutable_list_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *
immutable_list_getattr(PyListObject *f, char *name)
{
return Py_FindMethod(immutable_list_methods, (PyObject *)f, name);
}
static int
immutable_list_ass(void)
{
@ -1678,7 +1785,7 @@ static PyTypeObject immutable_list_type = {
0,
0, /* Cannot happen */ /* tp_dealloc */
(printfunc)list_print, /* tp_print */
(getattrfunc)immutable_list_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* Won't be called */ /* tp_compare */
(reprfunc)list_repr, /* tp_repr */
@ -1688,13 +1795,24 @@ static PyTypeObject immutable_list_type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
0, /* tp_clear */
list_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
immutable_list_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_init */
/* NOTE: This is *not* the standard list_type struct! */
};

View file

@ -2031,6 +2031,43 @@ long_hex(PyObject *v)
return long_format(v, 16, 1);
}
static PyObject *
long_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = NULL;
int base = -909; /* unlikely! */
static char *kwlist[] = {"x", "base", 0};
assert(type == &PyLong_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist,
&x, &base))
return NULL;
if (x == NULL)
return PyLong_FromLong(0L);
if (base == -909)
return PyNumber_Long(x);
else if (PyString_Check(x))
return PyLong_FromString(PyString_AS_STRING(x), NULL, base);
else if (PyUnicode_Check(x))
return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x),
PyUnicode_GET_SIZE(x),
base);
else {
PyErr_SetString(PyExc_TypeError,
"long() can't convert non-string with explicit base");
return NULL;
}
}
static char long_doc[] =
"long(x[, base]) -> integer\n\
\n\
Convert a string or number to a long integer, if possible. A floating\n\
point argument will be truncated towards zero (this does not include a\n\
string representation of a floating point number!) When converting a\n\
string, use the optional base. It is an error to supply a base when\n\
converting a non-string.";
static PyNumberMethods long_as_number = {
(binaryfunc) long_add, /*nb_add*/
(binaryfunc) long_sub, /*nb_subtract*/
@ -2070,24 +2107,42 @@ static PyNumberMethods long_as_number = {
PyTypeObject PyLong_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"long int",
sizeof(PyLongObject) - sizeof(digit),
sizeof(digit),
(destructor)long_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)long_compare, /*tp_compare*/
(reprfunc)long_repr, /*tp_repr*/
&long_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)long_hash, /*tp_hash*/
0, /*tp_call*/
(reprfunc)long_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_CHECKTYPES /*tp_flags*/
0, /* ob_size */
"long", /* tp_name */
sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */
sizeof(digit), /* tp_itemsize */
(destructor)long_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)long_compare, /* tp_compare */
(reprfunc)long_repr, /* tp_repr */
&long_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)long_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)long_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
long_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
long_new, /* tp_new */
};

View file

@ -3,8 +3,6 @@
#include "Python.h"
#include "token.h"
static PyCFunctionObject *free_list = NULL;
PyObject *
@ -69,6 +67,23 @@ meth_dealloc(PyCFunctionObject *m)
free_list = m;
}
static PyObject *
meth_get__doc__(PyCFunctionObject *m, void *closure)
{
char *doc = m->m_ml->ml_doc;
if (doc != NULL)
return PyString_FromString(doc);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
meth_get__name__(PyCFunctionObject *m, void *closure)
{
return PyString_FromString(m->m_ml->ml_name);
}
static int
meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
{
@ -79,39 +94,28 @@ meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
}
static PyObject *
meth_getattr(PyCFunctionObject *m, char *name)
meth_get__self__(PyCFunctionObject *m, void *closure)
{
if (strcmp(name, "__name__") == 0) {
return PyString_FromString(m->m_ml->ml_name);
PyObject *self;
if (PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError,
"method.__self__ not accessible in restricted mode");
return NULL;
}
if (strcmp(name, "__doc__") == 0) {
char *doc = m->m_ml->ml_doc;
if (doc != NULL)
return PyString_FromString(doc);
Py_INCREF(Py_None);
return Py_None;
}
if (strcmp(name, "__self__") == 0) {
PyObject *self;
if (PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError,
"method.__self__ not accessible in restricted mode");
return NULL;
}
self = m->m_self;
if (self == NULL)
self = Py_None;
Py_INCREF(self);
return self;
}
if (strcmp(name, "__members__") == 0) {
return Py_BuildValue("[sss]",
"__doc__", "__name__", "__self__");
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
self = m->m_self;
if (self == NULL)
self = Py_None;
Py_INCREF(self);
return self;
}
static struct getsetlist meth_getsets [] = {
{"__doc__", (getter)meth_get__doc__, NULL, NULL},
{"__name__", (getter)meth_get__name__, NULL, NULL},
{"__self__", (getter)meth_get__self__, NULL, NULL},
{0}
};
static PyObject *
meth_repr(PyCFunctionObject *m)
{
@ -159,6 +163,41 @@ meth_hash(PyCFunctionObject *a)
return x;
}
static PyObject *
meth_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyCFunctionObject* f = (PyCFunctionObject*)func;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
int flags = PyCFunction_GET_FLAGS(func);
if (flags & METH_KEYWORDS) {
return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
}
if (kw != NULL && PyDict_Size(kw) != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
f->m_ml->ml_name);
return NULL;
}
if (flags & METH_VARARGS) {
return (*meth)(self, arg);
}
if (!(flags & METH_VARARGS)) {
/* the really old style */
int size = PyTuple_GET_SIZE(arg);
if (size == 1)
arg = PyTuple_GET_ITEM(arg, 0);
else if (size == 0)
arg = NULL;
return (*meth)(self, arg);
}
/* should never get here ??? */
PyErr_BadInternalCall();
return NULL;
}
PyTypeObject PyCFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
@ -167,7 +206,7 @@ PyTypeObject PyCFunction_Type = {
0,
(destructor)meth_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)meth_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)meth_compare, /* tp_compare */
(reprfunc)meth_repr, /* tp_repr */
@ -175,14 +214,24 @@ PyTypeObject PyCFunction_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)meth_hash, /* tp_hash */
0, /* tp_call */
meth_call, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)meth_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
meth_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};
/* List all methods in a chain -- helper for findmethodinchain */

View file

@ -2,12 +2,18 @@
/* Module object implementation */
#include "Python.h"
#include "structmember.h"
typedef struct {
PyObject_HEAD
PyObject *md_dict;
} PyModuleObject;
struct memberlist module_members[] = {
{"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
{0}
};
PyObject *
PyModule_New(char *name)
{
@ -128,6 +134,15 @@ _PyModule_Clear(PyObject *m)
/* Methods */
static int
module_init(PyModuleObject *m, PyObject *args, PyObject *kw)
{
m->md_dict = PyDict_New();
if (m->md_dict == NULL)
return -1;
return 0;
}
static void
module_dealloc(PyModuleObject *m)
{
@ -161,59 +176,6 @@ module_repr(PyModuleObject *m)
return PyString_FromString(buf);
}
static PyObject *
module_getattro(PyModuleObject *m, PyObject *name)
{
PyObject *res;
char *sname = PyString_AsString(name);
if (sname[0] == '_' && strcmp(sname, "__dict__") == 0) {
Py_INCREF(m->md_dict);
return m->md_dict;
}
res = PyDict_GetItem(m->md_dict, name);
if (res == NULL) {
char *modname = PyModule_GetName((PyObject *)m);
if (modname == NULL) {
PyErr_Clear();
modname = "?";
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' module has no attribute '%.400s'",
modname, sname);
}
else
Py_INCREF(res);
return res;
}
static int
module_setattro(PyModuleObject *m, PyObject *name, PyObject *v)
{
char *sname = PyString_AsString(name);
if (sname[0] == '_' && strcmp(sname, "__dict__") == 0) {
PyErr_SetString(PyExc_TypeError,
"read-only special attribute");
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItem(m->md_dict, name);
if (rv < 0) {
char *modname = PyModule_GetName((PyObject *)m);
if (modname == NULL) {
PyErr_Clear();
modname = "?";
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' module has no attribute '%.400s'",
modname, sname);
}
return rv;
}
else
return PyDict_SetItem(m->md_dict, name, v);
}
/* We only need a traverse function, no clear function: If the module
is in a cycle, md_dict will be cleared as well, which will break
the cycle. */
@ -229,24 +191,41 @@ PyTypeObject PyModule_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
"module", /* tp_name */
sizeof(PyModuleObject) + PyGC_HEAD_SIZE,/* tp_size */
sizeof(PyModuleObject) + PyGC_HEAD_SIZE, /* tp_size */
0, /* tp_itemsize */
(destructor)module_dealloc, /* tp_dealloc */
(destructor)module_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)module_repr, /* tp_repr */
(reprfunc)module_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
(getattrofunc)module_getattro, /* tp_getattro */
(setattrofunc)module_setattro, /* tp_setattro */
PyObject_GenericGetAttr, /* tp_getattro */
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
(traverseproc)module_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
module_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(PyModuleObject, md_dict), /* tp_dictoffset */
(initproc)module_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};

View file

@ -32,7 +32,7 @@ dump_counts(void)
for (tp = type_list; tp; tp = tp->tp_next)
fprintf(stderr, "%s alloc'd: %d, freed: %d, max in use: %d\n",
tp->tp_name, tp->tp_alloc, tp->tp_free,
tp->tp_name, tp->tp_allocs, tp->tp_frees,
tp->tp_maxalloc);
fprintf(stderr, "fast tuple allocs: %d, empty: %d\n",
fast_tuple_allocs, tuple_zero_allocs);
@ -53,8 +53,8 @@ get_counts(void)
if (result == NULL)
return NULL;
for (tp = type_list; tp; tp = tp->tp_next) {
v = Py_BuildValue("(siii)", tp->tp_name, tp->tp_alloc,
tp->tp_free, tp->tp_maxalloc);
v = Py_BuildValue("(siii)", tp->tp_name, tp->tp_allocs,
tp->tp_frees, tp->tp_maxalloc);
if (v == NULL) {
Py_DECREF(result);
return NULL;
@ -72,16 +72,16 @@ get_counts(void)
void
inc_count(PyTypeObject *tp)
{
if (tp->tp_alloc == 0) {
if (tp->tp_allocs == 0) {
/* first time; insert in linked list */
if (tp->tp_next != NULL) /* sanity check */
Py_FatalError("XXX inc_count sanity check");
tp->tp_next = type_list;
type_list = tp;
}
tp->tp_alloc++;
if (tp->tp_alloc - tp->tp_free > tp->tp_maxalloc)
tp->tp_maxalloc = tp->tp_alloc - tp->tp_free;
tp->tp_allocs++;
if (tp->tp_allocs - tp->tp_frees > tp->tp_maxalloc)
tp->tp_maxalloc = tp->tp_allocs - tp->tp_frees;
}
#endif
@ -93,10 +93,8 @@ PyObject_Init(PyObject *op, PyTypeObject *tp)
"NULL object passed to PyObject_Init");
return op;
}
#ifdef WITH_CYCLE_GC
if (PyType_IS_GC(tp))
op = (PyObject *) PyObject_FROM_GC(op);
#endif
/* Any changes should be reflected in PyObject_INIT (objimpl.h) */
op->ob_type = tp;
_Py_NewReference(op);
@ -111,10 +109,8 @@ PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, int size)
"NULL object passed to PyObject_InitVar");
return op;
}
#ifdef WITH_CYCLE_GC
if (PyType_IS_GC(tp))
op = (PyVarObject *) PyObject_FROM_GC(op);
#endif
/* Any changes should be reflected in PyObject_INIT_VAR */
op->ob_size = size;
op->ob_type = tp;
@ -129,10 +125,8 @@ _PyObject_New(PyTypeObject *tp)
op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
if (op == NULL)
return PyErr_NoMemory();
#ifdef WITH_CYCLE_GC
if (PyType_IS_GC(tp))
op = (PyObject *) PyObject_FROM_GC(op);
#endif
return PyObject_INIT(op, tp);
}
@ -143,21 +137,17 @@ _PyObject_NewVar(PyTypeObject *tp, int size)
op = (PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE(tp, size));
if (op == NULL)
return (PyVarObject *)PyErr_NoMemory();
#ifdef WITH_CYCLE_GC
if (PyType_IS_GC(tp))
op = (PyVarObject *) PyObject_FROM_GC(op);
#endif
return PyObject_INIT_VAR(op, tp, size);
}
void
_PyObject_Del(PyObject *op)
{
#ifdef WITH_CYCLE_GC
if (op && PyType_IS_GC(op->ob_type)) {
op = (PyObject *) PyObject_AS_GC(op);
}
#endif
PyObject_FREE(op);
}
@ -994,26 +984,16 @@ PyObject_Hash(PyObject *v)
PyObject *
PyObject_GetAttrString(PyObject *v, char *name)
{
if (v->ob_type->tp_getattro != NULL) {
PyObject *w, *res;
w = PyString_InternFromString(name);
if (w == NULL)
return NULL;
res = (*v->ob_type->tp_getattro)(v, w);
Py_XDECREF(w);
return res;
}
PyObject *w, *res;
if (v->ob_type->tp_getattr == NULL) {
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
v->ob_type->tp_name,
name);
return NULL;
}
else {
if (v->ob_type->tp_getattr != NULL)
return (*v->ob_type->tp_getattr)(v, name);
}
w = PyString_InternFromString(name);
if (w == NULL)
return NULL;
res = PyObject_GetAttr(v, w);
Py_XDECREF(w);
return res;
}
int
@ -1031,34 +1011,24 @@ PyObject_HasAttrString(PyObject *v, char *name)
int
PyObject_SetAttrString(PyObject *v, char *name, PyObject *w)
{
if (v->ob_type->tp_setattro != NULL) {
PyObject *s;
int res;
s = PyString_InternFromString(name);
if (s == NULL)
return -1;
res = (*v->ob_type->tp_setattro)(v, s, w);
Py_XDECREF(s);
return res;
}
PyObject *s;
int res;
if (v->ob_type->tp_setattr == NULL) {
if (v->ob_type->tp_getattr == NULL)
PyErr_SetString(PyExc_TypeError,
"attribute-less object (assign or del)");
else
PyErr_SetString(PyExc_TypeError,
"object has read-only attributes");
return -1;
}
else {
if (v->ob_type->tp_setattr != NULL)
return (*v->ob_type->tp_setattr)(v, name, w);
}
s = PyString_InternFromString(name);
if (s == NULL)
return -1;
res = PyObject_SetAttr(v, s, w);
Py_XDECREF(s);
return res;
}
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
PyTypeObject *tp = v->ob_type;
/* The Unicode to string conversion is done here because the
existing tp_getattro slots expect a string object as name
and we wouldn't want to break those. */
@ -1067,16 +1037,19 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
if (name == NULL)
return NULL;
}
if (!PyString_Check(name)) {
PyErr_SetString(PyExc_TypeError,
"attribute name must be string");
return NULL;
}
if (v->ob_type->tp_getattro != NULL)
return (*v->ob_type->tp_getattro)(v, name);
else
return PyObject_GetAttrString(v, PyString_AS_STRING(name));
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
if (tp->tp_getattr != NULL)
return (*tp->tp_getattr)(v, PyString_AS_STRING(name));
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
tp->tp_name, PyString_AS_STRING(name));
return NULL;
}
int
@ -1094,6 +1067,7 @@ PyObject_HasAttr(PyObject *v, PyObject *name)
int
PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
{
PyTypeObject *tp = v->ob_type;
int err;
/* The Unicode to string conversion is done here because the
@ -1104,25 +1078,182 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
if (name == NULL)
return -1;
}
else
Py_INCREF(name);
if (!PyString_Check(name)){
else if (!PyString_Check(name)){
PyErr_SetString(PyExc_TypeError,
"attribute name must be string");
err = -1;
return -1;
}
else {
PyString_InternInPlace(&name);
if (v->ob_type->tp_setattro != NULL)
err = (*v->ob_type->tp_setattro)(v, name, value);
else
err = PyObject_SetAttrString(v,
PyString_AS_STRING(name), value);
else
Py_INCREF(name);
PyString_InternInPlace(&name);
if (tp->tp_setattro != NULL) {
err = (*tp->tp_setattro)(v, name, value);
Py_DECREF(name);
return err;
}
if (tp->tp_setattr != NULL) {
err = (*tp->tp_setattr)(v, PyString_AS_STRING(name), value);
Py_DECREF(name);
return err;
}
Py_DECREF(name);
return err;
if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
PyErr_Format(PyExc_TypeError,
"'%.100s' object has no attributes "
"(%s .%.100s)",
tp->tp_name,
value==NULL ? "del" : "assign to",
PyString_AS_STRING(name));
else
PyErr_Format(PyExc_TypeError,
"'%.100s' object has only read-only attributes "
"(%s .%.100s)",
tp->tp_name,
value==NULL ? "del" : "assign to",
PyString_AS_STRING(name));
return -1;
}
/* Helper to get a pointer to an object's __dict__ slot, if any */
PyObject **
_PyObject_GetDictPtr(PyObject *obj)
{
#define PTRSIZE (sizeof(PyObject *))
long dictoffset;
PyTypeObject *tp = obj->ob_type;
if (!(tp->tp_flags & Py_TPFLAGS_HAVE_CLASS))
return NULL;
dictoffset = tp->tp_dictoffset;
if (dictoffset == 0)
return NULL;
if (dictoffset < 0) {
dictoffset += PyType_BASICSIZE(tp);
assert(dictoffset > 0); /* Sanity check */
if (tp->tp_itemsize > 0) {
int n = ((PyVarObject *)obj)->ob_size;
if (n > 0) {
dictoffset += tp->tp_itemsize * n;
/* Round up, if necessary */
if (tp->tp_itemsize % PTRSIZE != 0) {
dictoffset += PTRSIZE - 1;
dictoffset /= PTRSIZE;
dictoffset *= PTRSIZE;
}
}
}
}
return (PyObject **) ((char *)obj + dictoffset);
}
/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
PyObject *
PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
{
PyTypeObject *tp = obj->ob_type;
PyObject *descr;
descrgetfunc f;
PyObject **dictptr;
if (tp->tp_dict == NULL) {
if (PyType_InitDict(tp) < 0)
return NULL;
}
descr = _PyType_Lookup(tp, name);
f = NULL;
if (descr != NULL) {
f = descr->ob_type->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr))
return f(descr, obj, (PyObject *)obj->ob_type);
}
dictptr = _PyObject_GetDictPtr(obj);
if (dictptr != NULL) {
PyObject *dict = *dictptr;
if (dict != NULL) {
PyObject *res = PyDict_GetItem(dict, name);
if (res != NULL) {
Py_INCREF(res);
return res;
}
}
}
if (f != NULL)
return f(descr, obj, (PyObject *)obj->ob_type);
if (descr != NULL) {
Py_INCREF(descr);
return descr;
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
tp->tp_name, PyString_AS_STRING(name));
return NULL;
}
int
PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
{
PyTypeObject *tp = obj->ob_type;
PyObject *descr;
descrsetfunc f;
PyObject **dictptr;
if (tp->tp_dict == NULL) {
if (PyType_InitDict(tp) < 0)
return -1;
}
descr = _PyType_Lookup(tp, name);
f = NULL;
if (descr != NULL) {
f = descr->ob_type->tp_descr_set;
if (f != NULL && PyDescr_IsData(descr))
return f(descr, obj, value);
}
dictptr = _PyObject_GetDictPtr(obj);
if (dictptr != NULL) {
PyObject *dict = *dictptr;
if (dict == NULL && value != NULL) {
dict = PyDict_New();
if (dict == NULL)
return -1;
*dictptr = dict;
}
if (dict != NULL) {
int res;
if (value == NULL)
res = PyDict_DelItem(dict, name);
else
res = PyDict_SetItem(dict, name, value);
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_SetObject(PyExc_AttributeError, name);
return res;
}
}
if (f != NULL)
return f(descr, obj, value);
if (descr == NULL) {
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
tp->tp_name, PyString_AS_STRING(name));
return -1;
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object attribute '%.400s' is read-only",
tp->tp_name, PyString_AS_STRING(name));
return -1;
}
/* Test a value used as condition, e.g., in a for or if statement.
@ -1218,12 +1349,6 @@ PyCallable_Check(PyObject *x)
{
if (x == NULL)
return 0;
if (x->ob_type->tp_call != NULL ||
PyFunction_Check(x) ||
PyMethod_Check(x) ||
PyCFunction_Check(x) ||
PyClass_Check(x))
return 1;
if (PyInstance_Check(x)) {
PyObject *call = PyObject_GetAttrString(x, "__call__");
if (call == NULL) {
@ -1235,7 +1360,9 @@ PyCallable_Check(PyObject *x)
Py_DECREF(call);
return 1;
}
return 0;
else {
return x->ob_type->tp_call != NULL;
}
}
@ -1365,7 +1492,7 @@ _Py_ForgetReference(register PyObject *op)
op->_ob_prev->_ob_next = op->_ob_next;
op->_ob_next = op->_ob_prev = NULL;
#ifdef COUNT_ALLOCS
op->ob_type->tp_free++;
op->ob_type->tp_frees++;
#endif
}

View file

@ -310,22 +310,34 @@ PyTypeObject PyRange_Type = {
"xrange", /* Name of this type */
sizeof(rangeobject), /* Basic object size */
0, /* Item size for varobject */
(destructor)range_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)range_getattr, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)range_compare, /*tp_compare*/
(reprfunc)range_repr, /*tp_repr*/
0, /*tp_as_number*/
&range_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
(destructor)range_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)range_getattr, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)range_compare, /*tp_compare*/
(reprfunc)range_repr, /*tp_repr*/
0, /*tp_as_number*/
&range_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
PyObject_GenericGetAttr, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};
#undef WARN

View file

@ -14,6 +14,7 @@ this type and there is exactly one in existence.
*/
#include "Python.h"
#include "structmember.h"
static PyObject *
ellipsis_repr(PyObject *op)
@ -128,32 +129,12 @@ slice_repr(PySliceObject *r)
return s;
}
static PyObject *slice_getattr(PySliceObject *self, char *name)
{
PyObject *ret;
ret = NULL;
if (strcmp(name, "start") == 0) {
ret = self->start;
}
else if (strcmp(name, "stop") == 0) {
ret = self->stop;
}
else if (strcmp(name, "step") == 0) {
ret = self->step;
}
else if (strcmp(name, "__members__") == 0) {
return Py_BuildValue("[sss]",
"start", "stop", "step");
}
else {
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}
Py_INCREF(ret);
return ret;
}
static struct memberlist slice_members[] = {
{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
{0}
};
static int
slice_compare(PySliceObject *v, PySliceObject *w)
@ -182,13 +163,32 @@ PyTypeObject PySlice_Type = {
"slice", /* Name of this type */
sizeof(PySliceObject), /* Basic object size */
0, /* Item size for varobject */
(destructor)slice_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)slice_getattr, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)slice_compare, /*tp_compare*/
(reprfunc)slice_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(destructor)slice_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)slice_compare, /* tp_compare */
(reprfunc)slice_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
slice_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};

View file

@ -2522,41 +2522,65 @@ string_methods[] = {
};
static PyObject *
string_getattr(PyStringObject *s, char *name)
string_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
return Py_FindMethod(string_methods, (PyObject*)s, name);
PyObject *x = NULL;
static char *kwlist[] = {"object", 0};
assert(type == &PyString_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:str", kwlist, &x))
return NULL;
if (x == NULL)
return PyString_FromString("");
return PyObject_Str(x);
}
static char string_doc[] =
"str(object) -> string\n\
\n\
Return a nice string representation of the object.\n\
If the argument is a string, the return value is the same object.";
PyTypeObject PyString_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"string",
"str",
sizeof(PyStringObject),
sizeof(char),
(destructor)string_dealloc, /*tp_dealloc*/
(printfunc)string_print, /*tp_print*/
(getattrfunc)string_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)string_repr, /*tp_repr*/
0, /*tp_as_number*/
&string_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)string_hash, /*tp_hash*/
0, /*tp_call*/
(reprfunc)string_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
&string_as_buffer, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
(richcmpfunc)string_richcompare, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
(destructor)string_dealloc, /* tp_dealloc */
(printfunc)string_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)string_repr, /* tp_repr */
0, /* tp_as_number */
&string_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)string_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)string_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
&string_as_buffer, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
string_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)string_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
string_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
string_new, /* tp_new */
};
void

View file

@ -480,6 +480,28 @@ tuplerichcompare(PyObject *v, PyObject *w, int op)
return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
}
static PyObject *
tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *arg = NULL;
static char *kwlist[] = {"sequence", 0};
assert(type == &PyTuple_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
return NULL;
if (arg == NULL)
return PyTuple_New(0);
else
return PySequence_Tuple(arg);
}
static char tuple_doc[] =
"tuple(sequence) -> list\n\
\n\
Return a tuple whose items are the same as those of the argument sequence.\n\
If the argument is a tuple, the return value is the same object.";
static PySequenceMethods tuple_as_sequence = {
(inquiry)tuplelength, /* sq_length */
(binaryfunc)tupleconcat, /* sq_concat */
@ -509,14 +531,28 @@ PyTypeObject PyTuple_Type = {
(hashfunc)tuplehash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */
tuple_doc, /* tp_doc */
(traverseproc)tupletraverse, /* tp_traverse */
0, /* tp_clear */
tuplerichcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
tuple_new, /* tp_new */
};
/* The following function breaks the notion that tuples are immutable:

File diff suppressed because it is too large Load diff

View file

@ -4667,12 +4667,6 @@ static PyMethodDef unicode_methods[] = {
{NULL, NULL}
};
static PyObject *
unicode_getattr(PyUnicodeObject *self, char *name)
{
return Py_FindMethod(unicode_methods, (PyObject*) self, name);
}
static PySequenceMethods unicode_as_sequence = {
(inquiry) unicode_length, /* sq_length */
(binaryfunc) PyUnicode_Concat, /* sq_concat */
@ -5346,6 +5340,30 @@ static PyBufferProcs unicode_as_buffer = {
(getcharbufferproc) unicode_buffer_getcharbuf,
};
static PyObject *
unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = NULL;
static char *kwlist[] = {"string", "encoding", "errors", 0};
char *encoding = NULL;
char *errors = NULL;
assert(type == &PyUnicode_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:unicode",
kwlist, &x, &encoding, &errors))
return NULL;
if (x == NULL)
return (PyObject *)_PyUnicode_New(0);
return PyUnicode_FromEncodedObject(x, encoding, errors);
}
static char unicode_doc[] =
"unicode(string [, encoding[, errors]]) -> object\n\
\n\
Create a new Unicode object from the given encoded string.\n\
encoding defaults to the current default string encoding and \n\
errors, defining the error handling, to 'strict'.";
PyTypeObject PyUnicode_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
@ -5355,7 +5373,7 @@ PyTypeObject PyUnicode_Type = {
/* Slots */
(destructor)_PyUnicode_Free, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)unicode_getattr, /* tp_getattr */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc) unicode_compare, /* tp_compare */
(reprfunc) unicode_repr, /* tp_repr */
@ -5365,10 +5383,28 @@ PyTypeObject PyUnicode_Type = {
(hashfunc) unicode_hash, /* tp_hash*/
0, /* tp_call*/
(reprfunc) unicode_str, /* tp_str */
(getattrofunc) NULL, /* tp_getattro */
(setattrofunc) NULL, /* tp_setattro */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
&unicode_as_buffer, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
unicode_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
unicode_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
unicode_new, /* tp_new */
};
/* Initialize the Unicode implementation */