[Patches] [ python-Patches-702620 ] AE Inheritance fixes

SourceForge.net noreply@sourceforge.net
Tue, 18 Mar 2003 10:00:55 -0800


Patches item #702620, was opened at 2003-03-12 15:07
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=702620&group_id=5470

Category: Macintosh
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Submitted By: Donovan Preston (dsposx)
Assigned to: Jack Jansen (jackjansen)
Summary: AE Inheritance fixes

Initial Comment:
A while ago, I submitted a patch that attempted to make modules generated by gensuitemodule inheritance aware. It was quite a hack, but it did the job. Some patches to cvs in the meantime have made this stop working for me. Here are my attempted fixes.

If for some reason there's some use case besides mine where this implementation doesn't work, I'd like to know about it so we can come up with an implementation that works everywhere :)

1) We don't ever want an _instance_ of ComponentItem to have a personal _propdict and _elemdict. They need to inherit these attributes from the class, which was set up in the __init__.py to have the correct entries. Thus, I moved the initialization of _propdict
and _elemdict out of __init__ and into the class definition.

2) getbaseclasses needs to look through the inheritance tree specified by _superclassnames and for each class in the tree, copy _privpropdict and _privelemdict to _propdict and _elemdict. Then, it needs to copy _propdict and _elemdict from each superclass into it's own _propdict and _elemdict, where ComponentItem.__getattr__ will find it. Making these into flat dictionaries on each class that include all of the properties and elements from the superclasses greatly speeds up execution time, since only a single, non-recursive lookup is required, and the only recursion occurs at import time.

Here's a detailed description of what getbaseclasses does:

## v should be a class object.
## Why did I name it 'v'? :(

def getbaseclasses(v):

## Have we already set up the _propdict and _elemdict 
## for this class object? If so, don't do it again.

	if not v._propdict:

## This step is required so we get a fresh dictionary on
## this class object, and don't mutate the one on
## ComponentItem or one of our superclasses

		v._propdict = {}
		v._elemdict = {}

## Run through all of the strings in _superclassnames
## evaluating them to get a class object.

		for superclassname in getattr(v, '_superclassnames', []):
			superclass = eval(superclassname)

## Immediately recurse into getbaseclasses, so that
## the base class _propdict and _elemdict is set up
## properly before we copy it's entries into ours.

			getbaseclasses(superclass)

## Copy all of the entries from this base class into
## our _propdict and _elemdict so that we get a flat
## dictionary of all of the elements and properties
## that should be available to instances of this class.

			v._propdict.update(getattr(superclass, '_propdict', {}))
			v._elemdict.update(getattr(superclass, '_elemdict', {}))

## Finally, copy those properties and elements that
## are defined directly on this class object in 
## _privpropdict and _privelemdict into the
## _propdict and _elemdict that
## ComponentItem.__getattr__ looks in.
## Note that if we entered getbaseclasses through the
## recursion above, our subclass will then copy our
## _propdict and _elemdict into it's own after we exit
## the recursion, giving it a copy of all the properties 
## and elements defined on the superclass object.

		v._propdict.update(v._privpropdict)
		v._elemdict.update(v._privelemdict)

----------------------------------------------------------------------

>Comment By: Donovan Preston (dsposx)
Date: 2003-03-18 09:00

Message:
Logged In: YES 
user_id=111050

Jack,
Thanks for taking a look at this.

You are correct, if a class has no properties then v._propdict will still be empty, and we will do unneccessary work the next time getbaseclasses is called. I suppose it could be "if not v._propdict and not v._elemdict:" which would reduce the unnecessary work down to when a base class has neither properties nor elements; frankly the if is not really required at all; it was just an attempt to prevent work that has already been performed from being performed again unnecessarily. Suggestions welcome.

Re _superclassnames, like everything else done with gensuitemodule, we need to be really careful about circular references, references to things that haven't been defined yet, etc. Everything generated by gensuitemodule is either a ComponentItem or an NProperty, and they don't actually inherit from each other in Python because doing so would be too hairy. So we can't use __bases__ because there is none :-)

The thing about _superclassnames is that it's just what it sounds like; a list of strings that indicate superclasses of the current class. By deferring getbaseclasses to import time, we ensure all of the base classes are defined by then.

----------------------------------------------------------------------

Comment By: Jack Jansen (jackjansen)
Date: 2003-03-16 13:42

Message:
Logged In: YES 
user_id=45365

Donovan,
in as far as I understand the matter (in which area you are clearly my superior:-) I think the idea of the fix is correct, but I have one misgiving: if a class has no properties then v._propdict will still be empty after getbaseclasses(). This will result in the next call of getbaseclasses (if this class is the base class of another) going through the motions again.

Is this a problem?

Also, do we really need _superclassnames, can't we do this with __bases__? I vaguely remember we went through this issue before, but I can't remember fully...

----------------------------------------------------------------------

Comment By: Donovan Preston (dsposx)
Date: 2003-03-12 15:08

Message:
Logged In: YES 
user_id=111050

Whoops. Have to click the checkbox.

----------------------------------------------------------------------

Comment By: Donovan Preston (dsposx)
Date: 2003-03-12 15:08

Message:
Logged In: YES 
user_id=111050

Attaching diff.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=702620&group_id=5470