This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: AE Inheritance fixes
Type: Stage:
Components: macOS Versions: Python 2.3
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: jackjansen Nosy List: dsposx, jackjansen
Priority: normal Keywords: patch

Created on 2003-03-13 00:07 by dsposx, last changed 2022-04-10 16:07 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
aeInheritanceFix.diff dsposx, 2003-03-13 00:08
Messages (8)
msg43014 - (view) Author: Donovan Preston (dsposx) Date: 2003-03-13 00:07
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)
msg43015 - (view) Author: Donovan Preston (dsposx) Date: 2003-03-13 00:08
Logged In: YES 
user_id=111050

Attaching diff.
msg43016 - (view) Author: Donovan Preston (dsposx) Date: 2003-03-13 00:08
Logged In: YES 
user_id=111050

Whoops. Have to click the checkbox.
msg43017 - (view) Author: Jack Jansen (jackjansen) * (Python committer) Date: 2003-03-16 22:42
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...
msg43018 - (view) Author: Donovan Preston (dsposx) Date: 2003-03-18 18:00
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.
msg43019 - (view) Author: Jack Jansen (jackjansen) * (Python committer) Date: 2003-03-21 16:53
Logged In: YES 
user_id=45365

Donovan,
I checked your fixes in, but possibly a bit premature: things broke. For example, running findertools.py as main program (a simple test of the scripting infrastructure) will now fail for me, in getbaseclasses(writing_code). And that seems correct: writing_code is an NProperty, not a ComponentItem.

Before you fix things: please check out a fresh tree. I seriously hacked gensuitemodule after applying your mods (it can now run non-interactive on MacOSX).
msg43020 - (view) Author: Donovan Preston (dsposx) Date: 2003-03-21 22:36
Logged In: YES 
user_id=111050

I am surprised I didn't have the same problem -- I should have. I suppose that's why I had the if hasattr in the first version of getbaseclasses. Changing

if not v._propdict:

to

if not getattr(v, '_propdict', None):

Would probably work. I am going to PyCon next week, so I will have more free time to work on non-directly-work related items. I'll do a fresh checkout and build of framework python, and experiment with the latest gensuitemoudle etc.

Donovan
msg43021 - (view) Author: Jack Jansen (jackjansen) * (Python committer) Date: 2003-03-23 22:20
Logged In: YES 
user_id=45365

That fixed it, with a similar fix for _privpropdict.
History
Date User Action Args
2022-04-10 16:07:38adminsetgithub: 38155
2003-03-13 00:07:04dsposxcreate