diff options
author | Guido van Rossum <guido@python.org> | 1994-09-05 07:31:41 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1994-09-05 07:31:41 (GMT) |
commit | e773754ae54fc22510ace44a96252d3cae8f2f04 (patch) | |
tree | 0489216f97991c2997729ba82dc265320ccd3ea5 /Objects/classobject.c | |
parent | 56bf235d4c648174c71b38a20e1c2f40e1b515d0 (diff) | |
download | cpython-e773754ae54fc22510ace44a96252d3cae8f2f04.zip cpython-e773754ae54fc22510ace44a96252d3cae8f2f04.tar.gz cpython-e773754ae54fc22510ace44a96252d3cae8f2f04.tar.bz2 |
Mods (really diffs to 2.29) by Michael Scharf for alternative __getattr__ etc.
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r-- | Objects/classobject.c | 309 |
1 files changed, 204 insertions, 105 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c index a05c0bf..9601181 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -104,23 +104,21 @@ class_getattr(op, name) { register object *v; classobject *class; - if (name[0] == '_' && name[1] == '_') { - if (strcmp(name, "__dict__") == 0) { - INCREF(op->cl_dict); - return op->cl_dict; - } - if (strcmp(name, "__bases__") == 0) { - INCREF(op->cl_bases); - return op->cl_bases; - } - if (strcmp(name, "__name__") == 0) { - if (op->cl_name == NULL) - v = None; - else - v = op->cl_name; - INCREF(v); - return v; - } + if (strcmp(name, "__dict__") == 0) { + INCREF(op->cl_dict); + return op->cl_dict; + } + if (strcmp(name, "__bases__") == 0) { + INCREF(op->cl_bases); + return op->cl_bases; + } + if (strcmp(name, "__name__") == 0) { + if (op->cl_name == NULL) + v = None; + else + v = op->cl_name; + INCREF(v); + return v; } v = class_lookup(op, name, &class); if (v == NULL) { @@ -282,25 +280,11 @@ newinstanceobject(class, arg) INCREF(class); inst->in_class = (classobject *)class; inst->in_dict = newdictobject(); - inst->in_getattr = NULL; - inst->in_setattr = NULL; -#ifdef WITH_THREAD - inst->in_lock = NULL; - inst->in_ident = 0; -#endif if (inst->in_dict == NULL || addaccess((classobject *)class, inst) != 0) { DECREF(inst); return NULL; } - inst->in_setattr = instance_getattr(inst, "__setattr__"); - err_clear(); - inst->in_getattr = instance_getattr(inst, "__getattr__"); - err_clear(); -#ifdef WITH_THREAD - if (inst->in_getattr != NULL) - inst->in_lock = allocate_lock(); -#endif init = instance_getattr(inst, "__init__"); if (init == NULL) { err_clear(); @@ -361,17 +345,81 @@ instance_dealloc(inst) return; /* __del__ added a reference; don't delete now */ DECREF(inst->in_class); XDECREF(inst->in_dict); - XDECREF(inst->in_getattr); - XDECREF(inst->in_setattr); -#ifdef WITH_THREAD - if (inst->in_lock != NULL) - free_lock(inst->in_lock); -#endif free((ANY *)inst); } +static object *instance_getattr1(); +static int instance_setattr1(); + static object * -instance_getattr(inst, name) +instance_getslot_meth(self, args) + instanceobject *self; + object *args; +{ + object *v; + char *name; + if (!getargs(args, "s", &name)) + return NULL; + return instance_getattr1(self, name); +} + +static object * +instance_hasslot_meth(self, args) + instanceobject *self; + object *args; +{ + object *v; + char *name; + if (!getargs(args, "s", &name)) + return NULL; + v = instance_getattr1(self, name); + if (v == NULL) { + err_clear(); + return newintobject(0L); + } + DECREF(v); + return newintobject(1L); +} + +static object * +instance_setslot_meth(self, args) + instanceobject *self; + object *args; +{ + char*name; + object*value; + value = NULL; + if (!getargs(args, "s", &name)) { + err_clear(); + if (!getargs(args, "(sO)", &name, &value)) + return NULL; + } + if(instance_setattr1(self, name, value)<0) { + return NULL; + } + INCREF(None); + return None; +} + +static object * +instance_delslot_meth(self, args) + instanceobject *self; + object *args; +{ + char*name; + if (!getargs(args, "s", &name)) { + return NULL; + } + if(instance_setattr1(self, name, 0)<0) { + return NULL; + } + INCREF(None); + return None; +} + + +static object * +instance_getattr1(inst, name) register instanceobject *inst; register char *name; { @@ -392,32 +440,6 @@ instance_getattr(inst, name) if (v == NULL) { v = class_lookup(inst->in_class, name, &class); if (v == NULL) { - object *func; - long ident; - if ((func = inst->in_getattr) != NULL && - inst->in_ident != (ident = get_thread_ident())) { - object *args; -#ifdef WITH_THREAD - type_lock lock = inst->in_lock; - if (lock != NULL) { - BGN_SAVE - acquire_lock(lock, 0); - END_SAVE - } -#endif - inst->in_ident = ident; - args = mkvalue("(s)", name); - if (args != NULL) { - v = call_object(func, args); - DECREF(args); - } - inst->in_ident = 0; -#ifdef WITH_THREAD - if (lock != NULL) - release_lock(lock); -#endif - return v; - } err_setstr(AttributeError, name); return NULL; } @@ -451,29 +473,76 @@ instance_getattr(inst, name) return v; } +static object * +instance_getattr(inst, name) + register instanceobject *inst; + register char *name; +{ + register object *func, *res; + if (name[0] == '_' && name[1] == '_') { + /* Let's not compare the first "__": */ + /* use &name[2] :-) */ + if (strcmp(&name[2], "setslot__") == 0) { + return newmethodobject(name, + (method)instance_setslot_meth, + (object*)inst, + 0); + } + if (strcmp(&name[2], "getslot__") == 0) { + return newmethodobject(name, + (method)instance_getslot_meth, + (object*)inst, + 0); + } + if (strcmp(&name[2], "hasslot__") == 0) { + return newmethodobject(name, + (method)instance_hasslot_meth, + (object*)inst, + 0); + } + if (strcmp(&name[2], "delslot__") == 0) { + return newmethodobject(name, + (method)instance_delslot_meth, + (object*)inst, + 0); + } + /* The following methods should not be forwarded! */ + if ( strcmp(&name[2], "init__") == 0 + || strcmp(&name[2], "del__") == 0) { + return instance_getattr1(inst,name); + } + } + res=instance_getattr1(inst,name); + if (res == NULL) { + /* Self doesn't have this attribute, */ + /* so let's try to call self.__getattr__(name) */ + object* func; + object *arg; + /* Well, lets get a funcobject for __getattr__ ...*/ + func = instance_getattr1(inst,"__getattr__"); + if (func == NULL) { + /* OOPS, we don't have a __getattr__. */ + /* Set the error ... */ + err_clear(); + err_setstr(AttributeError, name); + return NULL; + } + arg = newstringobject(name); + /*... and call it */ + res = call_object(func,arg); + DECREF(arg); + DECREF(func); + } + return res; +} + static int -instance_setattr(inst, name, v) +instance_setattr1(inst, name, v) instanceobject *inst; char *name; object *v; { object *ac; - if (inst->in_setattr != NULL) { - object *args; - if (v == NULL) - args = mkvalue("(s)", name); - else - args = mkvalue("(sO)", name, v); - if (args != NULL) { - object *res = call_object(inst->in_setattr, args); - DECREF(args); - if (res != NULL) { - DECREF(res); - return 0; - } - } - return -1; - } if (name[0] == '_' && name[1] == '_') { int n = strlen(name); if (name[n-1] == '_' && name[n-2] == '_') { @@ -495,6 +564,58 @@ instance_setattr(inst, name, v) return dictinsert(inst->in_dict, name, v); } +static int +instance_setattr(inst, name, v) + instanceobject *inst; + char *name; + object *v; +{ + object *ac, *func; + classobject *class; + char* setattrname; + /* I think I saw something in the news, that deletion of an attribute */ + /* is done by setattr with the value being NULL. */ + /* Let's be prepared for this case :-)*/ + if (v != NULL) + setattrname = "__setattr__"; + else + setattrname = "__delattr__"; + + /* Here is the only performance loss: */ + /* We have to check if there is a method __setattr__.*/ + /* Only class can have a __setattr__ because it's forbidden to */ + /* assign to self.__setattr__.*/ + /* So, lets do a class_lookup which is (hopefully) cheap */ + class = NULL; + func = class_lookup(inst->in_class, setattrname, &class); + if (func == NULL) { + /* Call the original instance_setattr */ + return instance_setattr1(inst,name,v); + } else { + object *arg, *res; + /* class_lookup did'nt REF(func) - so we won't UNREF(func). */ + /* Let's get the function (could be optimized....) */ + func = instance_getattr(inst,setattrname); + if (func == 0) + return -1; + /* Deleting an attribute is done by v==NULL */ + if (v == NULL) + /* __delattr__ has only one argument: the name */ + arg = mkvalue("s",name); + else + arg = mkvalue("(sO)",name,v); + res = call_object(func,arg); + DECREF(func); + DECREF(arg); + if (res == NULL) { + /* Oops, something went wrong :-( */ + return -1; + } + DECREF(res); + } + return 0; +} + static object * instance_repr(inst) instanceobject *inst; @@ -888,33 +1009,11 @@ BINARY(instance_mul, "__mul__") BINARY(instance_div, "__div__") BINARY(instance_mod, "__mod__") BINARY(instance_divmod, "__divmod__") +BINARY(instance_pow, "__pow__") UNARY(instance_neg, "__neg__") UNARY(instance_pos, "__pos__") UNARY(instance_abs, "__abs__") -static object * -instance_pow(self, other, modulus) - instanceobject *self; - object *other, *modulus; -{ - object *func, *arg, *res; - - if ((func = instance_getattr(self, "__pow__")) == NULL) - return NULL; - if (modulus == None) - arg = mkvalue("O", other); - else - arg = mkvalue("(OO)", other, modulus); - if (arg == NULL) { - DECREF(func); - return NULL; - } - res = call_object(func, arg); - DECREF(func); - DECREF(arg); - return res; -} - static int instance_nonzero(self) instanceobject *self; @@ -1008,7 +1107,7 @@ static number_methods instance_as_number = { (binaryfunc)instance_div, /*nb_divide*/ (binaryfunc)instance_mod, /*nb_remainder*/ (binaryfunc)instance_divmod, /*nb_divmod*/ - (ternaryfunc)instance_pow, /*nb_power*/ + (binaryfunc)instance_pow, /*nb_power*/ (unaryfunc)instance_neg, /*nb_negative*/ (unaryfunc)instance_pos, /*nb_positive*/ (unaryfunc)instance_abs, /*nb_absolute*/ |