Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52ca98a

Browse files
committed
Yet another version (by me) of __getattr__ etc.
1 parent e773754 commit 52ca98a

1 file changed

Lines changed: 51 additions & 174 deletions

File tree

Objects/classobject.c

Lines changed: 51 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2929
#include "structmember.h"
3030
#include "ceval.h"
3131

32+
/* Forward */
33+
static object *class_lookup PROTO((classobject *, char *, classobject **));
34+
static object *instance_getattr1 PROTO((instanceobject *, char *));
35+
3236
object *
3337
newclassobject(bases, dict, name)
3438
object *bases; /* NULL or tuple of classobjects! */
@@ -37,7 +41,7 @@ newclassobject(bases, dict, name)
3741
{
3842
int pos;
3943
object *key, *value;
40-
classobject *op;
44+
classobject *op, *dummy;
4145
if (bases == NULL) {
4246
bases = newtupleobject(0);
4347
if (bases == NULL)
@@ -55,6 +59,12 @@ newclassobject(bases, dict, name)
5559
op->cl_dict = dict;
5660
XINCREF(name);
5761
op->cl_name = name;
62+
op->cl_getattr = class_lookup(op, "__getattr__", &dummy);
63+
op->cl_setattr = class_lookup(op, "__setattr__", &dummy);
64+
op->cl_delattr = class_lookup(op, "__delattr__", &dummy);
65+
XINCREF(op->cl_getattr);
66+
XINCREF(op->cl_setattr);
67+
XINCREF(op->cl_delattr);
5868
pos = 0;
5969
while (mappinggetnext(dict, &pos, &key, &value)) {
6070
if (is_accessobject(value))
@@ -223,8 +233,6 @@ issubclass(class, base)
223233

224234
/* Instance objects */
225235

226-
static object *instance_getattr PROTO((instanceobject *, char *));
227-
228236
static int
229237
addaccess(class, inst)
230238
classobject *class;
@@ -285,7 +293,7 @@ newinstanceobject(class, arg)
285293
DECREF(inst);
286294
return NULL;
287295
}
288-
init = instance_getattr(inst, "__init__");
296+
init = instance_getattr1(inst, "__init__");
289297
if (init == NULL) {
290298
err_clear();
291299
if (arg != NULL && !(is_tupleobject(arg) &&
@@ -328,7 +336,7 @@ instance_dealloc(inst)
328336
revive the object and save the current exception, if any. */
329337
INCREF(inst);
330338
err_get(&error_type, &error_value);
331-
if ((del = instance_getattr(inst, "__del__")) != NULL) {
339+
if ((del = instance_getattr1(inst, "__del__")) != NULL) {
332340
object *args = newtupleobject(0);
333341
object *res = args;
334342
if (res != NULL)
@@ -348,76 +356,6 @@ instance_dealloc(inst)
348356
free((ANY *)inst);
349357
}
350358

351-
static object *instance_getattr1();
352-
static int instance_setattr1();
353-
354-
static object *
355-
instance_getslot_meth(self, args)
356-
instanceobject *self;
357-
object *args;
358-
{
359-
object *v;
360-
char *name;
361-
if (!getargs(args, "s", &name))
362-
return NULL;
363-
return instance_getattr1(self, name);
364-
}
365-
366-
static object *
367-
instance_hasslot_meth(self, args)
368-
instanceobject *self;
369-
object *args;
370-
{
371-
object *v;
372-
char *name;
373-
if (!getargs(args, "s", &name))
374-
return NULL;
375-
v = instance_getattr1(self, name);
376-
if (v == NULL) {
377-
err_clear();
378-
return newintobject(0L);
379-
}
380-
DECREF(v);
381-
return newintobject(1L);
382-
}
383-
384-
static object *
385-
instance_setslot_meth(self, args)
386-
instanceobject *self;
387-
object *args;
388-
{
389-
char*name;
390-
object*value;
391-
value = NULL;
392-
if (!getargs(args, "s", &name)) {
393-
err_clear();
394-
if (!getargs(args, "(sO)", &name, &value))
395-
return NULL;
396-
}
397-
if(instance_setattr1(self, name, value)<0) {
398-
return NULL;
399-
}
400-
INCREF(None);
401-
return None;
402-
}
403-
404-
static object *
405-
instance_delslot_meth(self, args)
406-
instanceobject *self;
407-
object *args;
408-
{
409-
char*name;
410-
if (!getargs(args, "s", &name)) {
411-
return NULL;
412-
}
413-
if(instance_setattr1(self, name, 0)<0) {
414-
return NULL;
415-
}
416-
INCREF(None);
417-
return None;
418-
}
419-
420-
421359
static object *
422360
instance_getattr1(inst, name)
423361
register instanceobject *inst;
@@ -479,59 +417,23 @@ instance_getattr(inst, name)
479417
register char *name;
480418
{
481419
register object *func, *res;
482-
if (name[0] == '_' && name[1] == '_') {
483-
/* Let's not compare the first "__": */
484-
/* use &name[2] :-) */
485-
if (strcmp(&name[2], "setslot__") == 0) {
486-
return newmethodobject(name,
487-
(method)instance_setslot_meth,
488-
(object*)inst,
489-
0);
490-
}
491-
if (strcmp(&name[2], "getslot__") == 0) {
492-
return newmethodobject(name,
493-
(method)instance_getslot_meth,
494-
(object*)inst,
495-
0);
496-
}
497-
if (strcmp(&name[2], "hasslot__") == 0) {
498-
return newmethodobject(name,
499-
(method)instance_hasslot_meth,
500-
(object*)inst,
501-
0);
502-
}
503-
if (strcmp(&name[2], "delslot__") == 0) {
504-
return newmethodobject(name,
505-
(method)instance_delslot_meth,
506-
(object*)inst,
507-
0);
508-
}
509-
/* The following methods should not be forwarded! */
510-
if ( strcmp(&name[2], "init__") == 0
511-
|| strcmp(&name[2], "del__") == 0) {
512-
return instance_getattr1(inst,name);
420+
res = instance_getattr1(inst, name);
421+
if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {
422+
object *args;
423+
#if 0
424+
if (name[0] == '_' && name[1] == '_') {
425+
int n = strlen(name);
426+
if (name[n-1] == '_' && name[n-2] == '_') {
427+
/* Don't mess with system attributes */
428+
return NULL;
429+
}
513430
}
514-
}
515-
res=instance_getattr1(inst,name);
516-
if (res == NULL) {
517-
/* Self doesn't have this attribute, */
518-
/* so let's try to call self.__getattr__(name) */
519-
object* func;
520-
object *arg;
521-
/* Well, lets get a funcobject for __getattr__ ...*/
522-
func = instance_getattr1(inst,"__getattr__");
523-
if (func == NULL) {
524-
/* OOPS, we don't have a __getattr__. */
525-
/* Set the error ... */
526-
err_clear();
527-
err_setstr(AttributeError, name);
431+
#endif
432+
args = mkvalue("(Os)", inst, name);
433+
if (args == NULL)
528434
return NULL;
529-
}
530-
arg = newstringobject(name);
531-
/*... and call it */
532-
res = call_object(func,arg);
533-
DECREF(arg);
534-
DECREF(func);
435+
res = call_object(func, args);
436+
DECREF(args);
535437
}
536438
return res;
537439
}
@@ -543,13 +445,6 @@ instance_setattr1(inst, name, v)
543445
object *v;
544446
{
545447
object *ac;
546-
if (name[0] == '_' && name[1] == '_') {
547-
int n = strlen(name);
548-
if (name[n-1] == '_' && name[n-2] == '_') {
549-
err_setstr(TypeError, "read-only special attribute");
550-
return -1;
551-
}
552-
}
553448
ac = dictlookup(inst->in_dict, name);
554449
if (ac != NULL && is_accessobject(ac))
555450
return setaccessvalue(ac, getowner(), v);
@@ -570,49 +465,31 @@ instance_setattr(inst, name, v)
570465
char *name;
571466
object *v;
572467
{
573-
object *ac, *func;
574-
classobject *class;
575-
char* setattrname;
576-
/* I think I saw something in the news, that deletion of an attribute */
577-
/* is done by setattr with the value being NULL. */
578-
/* Let's be prepared for this case :-)*/
579-
if (v != NULL)
580-
setattrname = "__setattr__";
581-
else
582-
setattrname = "__delattr__";
583-
584-
/* Here is the only performance loss: */
585-
/* We have to check if there is a method __setattr__.*/
586-
/* Only class can have a __setattr__ because it's forbidden to */
587-
/* assign to self.__setattr__.*/
588-
/* So, lets do a class_lookup which is (hopefully) cheap */
589-
class = NULL;
590-
func = class_lookup(inst->in_class, setattrname, &class);
591-
if (func == NULL) {
592-
/* Call the original instance_setattr */
593-
return instance_setattr1(inst,name,v);
594-
} else {
595-
object *arg, *res;
596-
/* class_lookup did'nt REF(func) - so we won't UNREF(func). */
597-
/* Let's get the function (could be optimized....) */
598-
func = instance_getattr(inst,setattrname);
599-
if (func == 0)
600-
return -1;
601-
/* Deleting an attribute is done by v==NULL */
602-
if (v == NULL)
603-
/* __delattr__ has only one argument: the name */
604-
arg = mkvalue("s",name);
605-
else
606-
arg = mkvalue("(sO)",name,v);
607-
res = call_object(func,arg);
608-
DECREF(func);
609-
DECREF(arg);
610-
if (res == NULL) {
611-
/* Oops, something went wrong :-( */
468+
object *func, *args, *res;
469+
if (name[0] == '_' && name[1] == '_') {
470+
int n = strlen(name);
471+
if (name[n-1] == '_' && name[n-2] == '_') {
472+
err_setstr(TypeError, "read-only special attribute");
612473
return -1;
613474
}
614-
DECREF(res);
615475
}
476+
if (v == NULL)
477+
func = inst->in_class->cl_delattr;
478+
else
479+
func = inst->in_class->cl_setattr;
480+
if (func == NULL)
481+
return instance_setattr1(inst, name, v);
482+
if (v == NULL)
483+
args = mkvalue("(Os)", inst, name);
484+
else
485+
args = mkvalue("(OsO)", inst, name, v);
486+
if (args == NULL)
487+
return -1;
488+
res = call_object(func, args);
489+
DECREF(args);
490+
if (res == NULL)
491+
return -1;
492+
DECREF(res);
616493
return 0;
617494
}
618495

@@ -1107,7 +984,7 @@ static number_methods instance_as_number = {
1107984
(binaryfunc)instance_div, /*nb_divide*/
1108985
(binaryfunc)instance_mod, /*nb_remainder*/
1109986
(binaryfunc)instance_divmod, /*nb_divmod*/
1110-
(binaryfunc)instance_pow, /*nb_power*/
987+
(ternaryfunc)instance_pow, /*nb_power*/
1111988
(unaryfunc)instance_neg, /*nb_negative*/
1112989
(unaryfunc)instance_pos, /*nb_positive*/
1113990
(unaryfunc)instance_abs, /*nb_absolute*/

0 commit comments

Comments
 (0)