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

Skip to content

Commit e773754

Browse files
committed
Mods (really diffs to 2.29) by Michael Scharf for alternative __getattr__ etc.
1 parent 56bf235 commit e773754

1 file changed

Lines changed: 204 additions & 105 deletions

File tree

Objects/classobject.c

Lines changed: 204 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -104,23 +104,21 @@ class_getattr(op, name)
104104
{
105105
register object *v;
106106
classobject *class;
107-
if (name[0] == '_' && name[1] == '_') {
108-
if (strcmp(name, "__dict__") == 0) {
109-
INCREF(op->cl_dict);
110-
return op->cl_dict;
111-
}
112-
if (strcmp(name, "__bases__") == 0) {
113-
INCREF(op->cl_bases);
114-
return op->cl_bases;
115-
}
116-
if (strcmp(name, "__name__") == 0) {
117-
if (op->cl_name == NULL)
118-
v = None;
119-
else
120-
v = op->cl_name;
121-
INCREF(v);
122-
return v;
123-
}
107+
if (strcmp(name, "__dict__") == 0) {
108+
INCREF(op->cl_dict);
109+
return op->cl_dict;
110+
}
111+
if (strcmp(name, "__bases__") == 0) {
112+
INCREF(op->cl_bases);
113+
return op->cl_bases;
114+
}
115+
if (strcmp(name, "__name__") == 0) {
116+
if (op->cl_name == NULL)
117+
v = None;
118+
else
119+
v = op->cl_name;
120+
INCREF(v);
121+
return v;
124122
}
125123
v = class_lookup(op, name, &class);
126124
if (v == NULL) {
@@ -282,25 +280,11 @@ newinstanceobject(class, arg)
282280
INCREF(class);
283281
inst->in_class = (classobject *)class;
284282
inst->in_dict = newdictobject();
285-
inst->in_getattr = NULL;
286-
inst->in_setattr = NULL;
287-
#ifdef WITH_THREAD
288-
inst->in_lock = NULL;
289-
inst->in_ident = 0;
290-
#endif
291283
if (inst->in_dict == NULL ||
292284
addaccess((classobject *)class, inst) != 0) {
293285
DECREF(inst);
294286
return NULL;
295287
}
296-
inst->in_setattr = instance_getattr(inst, "__setattr__");
297-
err_clear();
298-
inst->in_getattr = instance_getattr(inst, "__getattr__");
299-
err_clear();
300-
#ifdef WITH_THREAD
301-
if (inst->in_getattr != NULL)
302-
inst->in_lock = allocate_lock();
303-
#endif
304288
init = instance_getattr(inst, "__init__");
305289
if (init == NULL) {
306290
err_clear();
@@ -361,17 +345,81 @@ instance_dealloc(inst)
361345
return; /* __del__ added a reference; don't delete now */
362346
DECREF(inst->in_class);
363347
XDECREF(inst->in_dict);
364-
XDECREF(inst->in_getattr);
365-
XDECREF(inst->in_setattr);
366-
#ifdef WITH_THREAD
367-
if (inst->in_lock != NULL)
368-
free_lock(inst->in_lock);
369-
#endif
370348
free((ANY *)inst);
371349
}
372350

351+
static object *instance_getattr1();
352+
static int instance_setattr1();
353+
373354
static object *
374-
instance_getattr(inst, name)
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+
421+
static object *
422+
instance_getattr1(inst, name)
375423
register instanceobject *inst;
376424
register char *name;
377425
{
@@ -392,32 +440,6 @@ instance_getattr(inst, name)
392440
if (v == NULL) {
393441
v = class_lookup(inst->in_class, name, &class);
394442
if (v == NULL) {
395-
object *func;
396-
long ident;
397-
if ((func = inst->in_getattr) != NULL &&
398-
inst->in_ident != (ident = get_thread_ident())) {
399-
object *args;
400-
#ifdef WITH_THREAD
401-
type_lock lock = inst->in_lock;
402-
if (lock != NULL) {
403-
BGN_SAVE
404-
acquire_lock(lock, 0);
405-
END_SAVE
406-
}
407-
#endif
408-
inst->in_ident = ident;
409-
args = mkvalue("(s)", name);
410-
if (args != NULL) {
411-
v = call_object(func, args);
412-
DECREF(args);
413-
}
414-
inst->in_ident = 0;
415-
#ifdef WITH_THREAD
416-
if (lock != NULL)
417-
release_lock(lock);
418-
#endif
419-
return v;
420-
}
421443
err_setstr(AttributeError, name);
422444
return NULL;
423445
}
@@ -451,29 +473,76 @@ instance_getattr(inst, name)
451473
return v;
452474
}
453475

476+
static object *
477+
instance_getattr(inst, name)
478+
register instanceobject *inst;
479+
register char *name;
480+
{
481+
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);
513+
}
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);
528+
return NULL;
529+
}
530+
arg = newstringobject(name);
531+
/*... and call it */
532+
res = call_object(func,arg);
533+
DECREF(arg);
534+
DECREF(func);
535+
}
536+
return res;
537+
}
538+
454539
static int
455-
instance_setattr(inst, name, v)
540+
instance_setattr1(inst, name, v)
456541
instanceobject *inst;
457542
char *name;
458543
object *v;
459544
{
460545
object *ac;
461-
if (inst->in_setattr != NULL) {
462-
object *args;
463-
if (v == NULL)
464-
args = mkvalue("(s)", name);
465-
else
466-
args = mkvalue("(sO)", name, v);
467-
if (args != NULL) {
468-
object *res = call_object(inst->in_setattr, args);
469-
DECREF(args);
470-
if (res != NULL) {
471-
DECREF(res);
472-
return 0;
473-
}
474-
}
475-
return -1;
476-
}
477546
if (name[0] == '_' && name[1] == '_') {
478547
int n = strlen(name);
479548
if (name[n-1] == '_' && name[n-2] == '_') {
@@ -495,6 +564,58 @@ instance_setattr(inst, name, v)
495564
return dictinsert(inst->in_dict, name, v);
496565
}
497566

567+
static int
568+
instance_setattr(inst, name, v)
569+
instanceobject *inst;
570+
char *name;
571+
object *v;
572+
{
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 :-( */
612+
return -1;
613+
}
614+
DECREF(res);
615+
}
616+
return 0;
617+
}
618+
498619
static object *
499620
instance_repr(inst)
500621
instanceobject *inst;
@@ -888,33 +1009,11 @@ BINARY(instance_mul, "__mul__")
8881009
BINARY(instance_div, "__div__")
8891010
BINARY(instance_mod, "__mod__")
8901011
BINARY(instance_divmod, "__divmod__")
1012+
BINARY(instance_pow, "__pow__")
8911013
UNARY(instance_neg, "__neg__")
8921014
UNARY(instance_pos, "__pos__")
8931015
UNARY(instance_abs, "__abs__")
8941016

895-
static object *
896-
instance_pow(self, other, modulus)
897-
instanceobject *self;
898-
object *other, *modulus;
899-
{
900-
object *func, *arg, *res;
901-
902-
if ((func = instance_getattr(self, "__pow__")) == NULL)
903-
return NULL;
904-
if (modulus == None)
905-
arg = mkvalue("O", other);
906-
else
907-
arg = mkvalue("(OO)", other, modulus);
908-
if (arg == NULL) {
909-
DECREF(func);
910-
return NULL;
911-
}
912-
res = call_object(func, arg);
913-
DECREF(func);
914-
DECREF(arg);
915-
return res;
916-
}
917-
9181017
static int
9191018
instance_nonzero(self)
9201019
instanceobject *self;
@@ -1008,7 +1107,7 @@ static number_methods instance_as_number = {
10081107
(binaryfunc)instance_div, /*nb_divide*/
10091108
(binaryfunc)instance_mod, /*nb_remainder*/
10101109
(binaryfunc)instance_divmod, /*nb_divmod*/
1011-
(ternaryfunc)instance_pow, /*nb_power*/
1110+
(binaryfunc)instance_pow, /*nb_power*/
10121111
(unaryfunc)instance_neg, /*nb_negative*/
10131112
(unaryfunc)instance_pos, /*nb_positive*/
10141113
(unaryfunc)instance_abs, /*nb_absolute*/

0 commit comments

Comments
 (0)