Skip to content

Commit

Permalink
* Lots of small changes related to access.
Browse files Browse the repository at this point in the history
* Added "access *: ...", made access work for class methods.
* Introduced subclass check: make sure that when calling
  ClassName.methodname(instance, ...), the instance is an instance of
  ClassName or of a subclass thereof (this might break some old code!)
  • Loading branch information
gvanrossum committed May 21, 1993
1 parent 81daa32 commit b3f7258
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 48 deletions.
2 changes: 1 addition & 1 deletion Grammar/Grammar
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ return_stmt: 'return' [testlist]
raise_stmt: 'raise' test [',' test]
import_stmt: 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
global_stmt: 'global' NAME (',' NAME)*
access_stmt: 'access' NAME (',' NAME)* ':' accesstype (',' accesstype)*
access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*
accesstype: NAME+
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
# but can't be because that would create undesirable reserved words!
Expand Down
1 change: 1 addition & 0 deletions Include/accessobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ int setaccessvalue PROTO((object *, object *, object *));

void setaccessowner PROTO((object *, object *));
object *cloneaccessobject PROTO((object *));
int hasaccessvalue PROTO((object *));

extern typeobject Anynumbertype, Anysequencetype, Anymappingtype;
12 changes: 7 additions & 5 deletions Include/classobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

/* Class object interface */

/*
Classes are really hacked in at the last moment.
It should be possible to use other object types as base classes,
but currently it isn't. We'll see if we can fix that later, sigh...
*/
/* Revealing some structures (not for general use) */

typedef struct {
OB_HEAD
Expand All @@ -37,6 +33,12 @@ typedef struct {
object *cl_name; /* A string */
} classobject;

typedef struct {
OB_HEAD
classobject *in_class; /* The class object */
object *in_dict; /* A dictionary */
} instanceobject;

extern typeobject Classtype, Instancetype, Instancemethodtype;

#define is_classobject(op) ((op)->ob_type == &Classtype)
Expand Down
13 changes: 12 additions & 1 deletion Objects/accessobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ setaccessowner(op, class)
ap->ac_class = class;
}

int
hasaccessvalue(op)
object *op;
{
if (!is_accessobject(op))
return 0;
return ((accessobject *)op)->ac_value != NULL;
}

object *
getaccessvalue(op, class)
object *op;
Expand Down Expand Up @@ -268,7 +277,9 @@ access_repr(ap)
char buf[300];
classobject *class = (classobject *)ap->ac_class;
typeobject *type = ap->ac_type;
sprintf(buf, "<access object, class %.100s, type %.100s, mode 0%o>",
sprintf(buf,
"<access object, value 0x%lx, class %.100s, type %.100s, mode %04o>",
(long)(ap->ac_value),
class ? getstringvalue(class->cl_name) : "-",
type ? type->tp_name : "-",
ap->ac_mode);
Expand Down
70 changes: 39 additions & 31 deletions Objects/classobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,24 @@ class_getattr(op, name)
return v;
}
v = class_lookup(op, name, &class);
if (v != NULL) {
if (is_accessobject(v))
v = getaccessvalue(v, getclass());
else if (is_funcobject(v))
v = newinstancemethodobject(v, (object *)NULL,
if (v == NULL) {
err_setstr(AttributeError, name);
return NULL;
}
if (is_accessobject(v)) {
v = getaccessvalue(v, getclass());
if (v == NULL)
return NULL;
}
else
INCREF(v);
if (is_funcobject(v)) {
object *w = newinstancemethodobject(v, (object *)NULL,
(object *)class);
else
INCREF(v);
return v;
DECREF(v);
v = w;
}
err_setstr(AttributeError, name);
return NULL;
return v;
}

static int
Expand Down Expand Up @@ -217,12 +223,6 @@ issubclass(class, base)

/* Instance objects */

typedef struct {
OB_HEAD
classobject *in_class; /* The class object */
object *in_dict; /* A dictionary */
} instanceobject;

static object *instance_getattr PROTO((instanceobject *, char *));

static int
Expand All @@ -241,8 +241,11 @@ addaccess(class, inst)

pos = 0;
while (mappinggetnext(class->cl_dict, &pos, &key, &value)) {
object *v;
if (!is_accessobject(value))
continue;
if (hasaccessvalue(value))
continue;
ac = dict2lookup(inst->in_dict, key);
if (ac != NULL && is_accessobject(ac)) {
err_setval(ConflictError, key);
Expand Down Expand Up @@ -361,22 +364,27 @@ instance_getattr(inst, name)
return (object *)inst->in_class;
}
v = dictlookup(inst->in_dict, name);
if (v != NULL) {
if (is_accessobject(v))
v = getaccessvalue(v, getclass());
else
INCREF(v);
return v;
if (v == NULL) {
v = class_lookup(inst->in_class, name, &class);
if (v == NULL) {
err_setstr(AttributeError, name);
return NULL;
}
}
v = class_lookup(inst->in_class, name, &class);
if (v == NULL)
goto error;
if (is_funcobject(v))
return newinstancemethodobject(v, (object *)inst,
(object *)class);
error:
err_setstr(AttributeError, name);
return NULL;
if (is_accessobject(v)) {
v = getaccessvalue(v, getclass());
if (v == NULL)
return NULL;
}
else
INCREF(v);
if (is_funcobject(v)) {
object *w = newinstancemethodobject(v, (object *)inst,
(object *)class);
DECREF(v);
v = w;
}
return v;
}

static int
Expand Down
4 changes: 2 additions & 2 deletions Objects/methodobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ meth_repr(m)
{
char buf[200];
if (m->m_self == NULL)
sprintf(buf, "<built-in function '%.80s'>", m->m_name);
sprintf(buf, "<built-in function %.80s>", m->m_name);
else
sprintf(buf,
"<built-in method '%.80s' of %.80s object at %lx>",
"<built-in method %.80s of %.80s object at %lx>",
m->m_name, m->m_self->ob_type->tp_name,
(long)m->m_self);
return newstringobject(buf);
Expand Down
57 changes: 49 additions & 8 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ static int import_from PROTO((object *, object *, object *));
static object *build_class PROTO((object *, object *, object *));
static void locals_2_fast PROTO((frameobject *, int));
static void fast_2_locals PROTO((frameobject *));
static int access_statement PROTO((object *, int, frameobject *));
static int access_statement PROTO((object *, object *, frameobject *));


/* Pointer to current frame, used to link new frames to */
Expand Down Expand Up @@ -184,7 +184,8 @@ eval_code(co, globals, locals, class, arg)
object *trace = NULL; /* Trace function or NULL */
object *retval; /* Return value iff why == WHY_RETURN */
char *name; /* Name used by some instructions */
int needmerge = 0;
int needmerge = 0; /* Set if need to merge locals back at end */
int defmode = 0; /* Default access mode for new variables */
#ifdef LLTRACE
int lltrace;
#endif
Expand Down Expand Up @@ -760,7 +761,22 @@ eval_code(co, globals, locals, class, arg)
w = GETNAMEV(oparg);
v = POP();
u = dict2lookup(f->f_locals, w);
if (u != NULL && is_accessobject(u)) {
if (u == NULL) {
if (defmode != 0) {
if (v != None)
u = (object *)v->ob_type;
else
u = NULL;
x = newaccessobject(v, class,
(typeobject *)u,
defmode);
DECREF(v);
if (x == NULL)
break;
v = x;
}
}
else if (is_accessobject(u)) {
err = setaccessvalue(u, class, v);
DECREF(v);
break;
Expand Down Expand Up @@ -1190,7 +1206,10 @@ eval_code(co, globals, locals, class, arg)
case ACCESS_MODE:
v = POP();
w = GETNAMEV(oparg);
err = access_statement(w, (int)getintvalue(v), f);
if (getstringvalue(w)[0] == '*')
defmode = getintvalue(v);
else
err = access_statement(w, v, f);
DECREF(v);
break;

Expand Down Expand Up @@ -1995,7 +2014,28 @@ call_function(func, arg)
object *self = instancemethodgetself(func);
class = instancemethodgetclass(func);
func = instancemethodgetfunc(func);
if (self != NULL) {
if (self == NULL) {
/* Unbound methods must be called with an instance of
the class (or a derived class) as first argument */
if (arg != NULL && is_tupleobject(arg) &&
gettuplesize(arg) >= 1) {
self = gettupleitem(arg, 0);
if (self != NULL &&
is_instanceobject(self) &&
issubclass((object *)
(((instanceobject *)self)->in_class),
class))
/* self = self */ ;
else
self = NULL;
}
if (self == NULL) {
err_setstr(TypeError,
"unbound method must be called with class instance argument");
return NULL;
}
}
else {
int argcount;
if (arg == NULL)
argcount = 0;
Expand Down Expand Up @@ -2380,11 +2420,12 @@ build_class(methods, bases, name)
}

static int
access_statement(name, mode, f)
access_statement(name, vmode, f)
object *name;
int mode;
object *vmode;
frameobject *f;
{
int mode = getintvalue(vmode);
object *value, *ac;
typeobject *type;
int fastind, ret;
Expand Down Expand Up @@ -2415,7 +2456,7 @@ access_statement(name, mode, f)
type = value->ob_type;
else
type = NULL;
ac = newaccessobject(value, (object*)NULL, type, mode);
ac = newaccessobject(value, f->f_class, type, mode);
if (ac == NULL)
return -1;
if (fastind >= 0)
Expand Down

0 comments on commit b3f7258

Please sign in to comment.