summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1994-09-05 07:32:29 (GMT)
committerGuido van Rossum <guido@python.org>1994-09-05 07:32:29 (GMT)
commit52ca98a39003cf977200cb5011bbde5271b1b1c0 (patch)
tree398a27ad0b21fb69696d6466233014cede5b376f
parente773754ae54fc22510ace44a96252d3cae8f2f04 (diff)
downloadcpython-52ca98a39003cf977200cb5011bbde5271b1b1c0.zip
cpython-52ca98a39003cf977200cb5011bbde5271b1b1c0.tar.gz
cpython-52ca98a39003cf977200cb5011bbde5271b1b1c0.tar.bz2
Yet another version (by me) of __getattr__ etc.
-rw-r--r--Objects/classobject.c225
1 files changed, 51 insertions, 174 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 9601181..8b7e4da 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -29,6 +29,10 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "structmember.h"
#include "ceval.h"
+/* Forward */
+static object *class_lookup PROTO((classobject *, char *, classobject **));
+static object *instance_getattr1 PROTO((instanceobject *, char *));
+
object *
newclassobject(bases, dict, name)
object *bases; /* NULL or tuple of classobjects! */
@@ -37,7 +41,7 @@ newclassobject(bases, dict, name)
{
int pos;
object *key, *value;
- classobject *op;
+ classobject *op, *dummy;
if (bases == NULL) {
bases = newtupleobject(0);
if (bases == NULL)
@@ -55,6 +59,12 @@ newclassobject(bases, dict, name)
op->cl_dict = dict;
XINCREF(name);
op->cl_name = name;
+ op->cl_getattr = class_lookup(op, "__getattr__", &dummy);
+ op->cl_setattr = class_lookup(op, "__setattr__", &dummy);
+ op->cl_delattr = class_lookup(op, "__delattr__", &dummy);
+ XINCREF(op->cl_getattr);
+ XINCREF(op->cl_setattr);
+ XINCREF(op->cl_delattr);
pos = 0;
while (mappinggetnext(dict, &pos, &key, &value)) {
if (is_accessobject(value))
@@ -223,8 +233,6 @@ issubclass(class, base)
/* Instance objects */
-static object *instance_getattr PROTO((instanceobject *, char *));
-
static int
addaccess(class, inst)
classobject *class;
@@ -285,7 +293,7 @@ newinstanceobject(class, arg)
DECREF(inst);
return NULL;
}
- init = instance_getattr(inst, "__init__");
+ init = instance_getattr1(inst, "__init__");
if (init == NULL) {
err_clear();
if (arg != NULL && !(is_tupleobject(arg) &&
@@ -328,7 +336,7 @@ instance_dealloc(inst)
revive the object and save the current exception, if any. */
INCREF(inst);
err_get(&error_type, &error_value);
- if ((del = instance_getattr(inst, "__del__")) != NULL) {
+ if ((del = instance_getattr1(inst, "__del__")) != NULL) {
object *args = newtupleobject(0);
object *res = args;
if (res != NULL)
@@ -348,76 +356,6 @@ instance_dealloc(inst)
free((ANY *)inst);
}
-static object *instance_getattr1();
-static int instance_setattr1();
-
-static object *
-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;
@@ -479,59 +417,23 @@ instance_getattr(inst, name)
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 && (func = inst->in_class->cl_getattr) != NULL) {
+ object *args;
+#if 0
+ if (name[0] == '_' && name[1] == '_') {
+ int n = strlen(name);
+ if (name[n-1] == '_' && name[n-2] == '_') {
+ /* Don't mess with system attributes */
+ return NULL;
+ }
}
- }
- 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);
+#endif
+ args = mkvalue("(Os)", inst, name);
+ if (args == NULL)
return NULL;
- }
- arg = newstringobject(name);
- /*... and call it */
- res = call_object(func,arg);
- DECREF(arg);
- DECREF(func);
+ res = call_object(func, args);
+ DECREF(args);
}
return res;
}
@@ -543,13 +445,6 @@ instance_setattr1(inst, name, v)
object *v;
{
object *ac;
- if (name[0] == '_' && name[1] == '_') {
- int n = strlen(name);
- if (name[n-1] == '_' && name[n-2] == '_') {
- err_setstr(TypeError, "read-only special attribute");
- return -1;
- }
- }
ac = dictlookup(inst->in_dict, name);
if (ac != NULL && is_accessobject(ac))
return setaccessvalue(ac, getowner(), v);
@@ -570,49 +465,31 @@ instance_setattr(inst, name, v)
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 :-( */
+ object *func, *args, *res;
+ if (name[0] == '_' && name[1] == '_') {
+ int n = strlen(name);
+ if (name[n-1] == '_' && name[n-2] == '_') {
+ err_setstr(TypeError, "read-only special attribute");
return -1;
}
- DECREF(res);
}
+ if (v == NULL)
+ func = inst->in_class->cl_delattr;
+ else
+ func = inst->in_class->cl_setattr;
+ if (func == NULL)
+ return instance_setattr1(inst, name, v);
+ if (v == NULL)
+ args = mkvalue("(Os)", inst, name);
+ else
+ args = mkvalue("(OsO)", inst, name, v);
+ if (args == NULL)
+ return -1;
+ res = call_object(func, args);
+ DECREF(args);
+ if (res == NULL)
+ return -1;
+ DECREF(res);
return 0;
}
@@ -1107,7 +984,7 @@ static number_methods instance_as_number = {
(binaryfunc)instance_div, /*nb_divide*/
(binaryfunc)instance_mod, /*nb_remainder*/
(binaryfunc)instance_divmod, /*nb_divmod*/
- (binaryfunc)instance_pow, /*nb_power*/
+ (ternaryfunc)instance_pow, /*nb_power*/
(unaryfunc)instance_neg, /*nb_negative*/
(unaryfunc)instance_pos, /*nb_positive*/
(unaryfunc)instance_abs, /*nb_absolute*/