E&S CVS Commit: PEAK - Refactored to allow "lazy" metadata computation, using bindings.

pje at eby-sarna.com pje at eby-sarna.com
Fri Nov 29 17:21:00 EST 2002

Module Name:	PEAK
Committed By:	pje
Date:		Fri Nov 29 22:20:23 UTC 2002

Modified Files:
	PEAK: setup.py
	PEAK/src/peak/binding: once.py
	PEAK/src/peak/metamodels/tests: General.py
	PEAK/src/peak/metamodels/uml: MetaModel.py
	PEAK/src/peak/model: api.py
	PEAK/src/peak/storage: xmi.py
Added Files:
	PEAK/src/peak/binding: data_desc.c data_desc.pyx py_obj.h

Log Message:
Refactored to allow "lazy" metadata computation, using bindings.
This means that you can use attribute bindings in metaclasses to assemble
metadata registries, such as those needed for XMI.

Unfortunately, for this to work on types, I had to change the fundamental
implementation of attribute bindings to a new implementation in Pyrex/C.
The problem is that only *data* descriptors from a metaclass are invoked
if there is an attribute value available in the type's dictionary or the
dictionary of one of its base types.  This means that trying to have
'Once' bindings that attach to classes via their metaclass, is inherently
unstable unless you make use of the bindings in strict reverse __mro__
order!  This problem has actually existed ever since I added the ability
to use bindings in metaclasses, but because of the way things were being
used, it "just happened" to look like it was working.

So I had to make 'Once' a data descriptor; unfortunately this means that
it has to check whether the value appears in the object's dictionary
*every* time the attribute is accessed.  That's still doable from Python,
but the bigger problem is that type dictionaries aren't accessible from
pure Python code, and the only way to implement the __set__ function on
a 'Once' descriptor is by writing to the dictionary.  So I wrote a Pyrex
extension type to support getting at the object's true dictionary, and
to implement a (relatively) fast __get__ method.  The result seems to
perform about as well as the old version, although I'm tempted to redo
some of it in pure C to get rid of a lot of overhead that would be
avoidable if Pyrex properly supported the '__get__' signature for
extension types.

Up next: standardizing the metaclass naming convention, documenting all this
stuff, then maybe on to XMI writing...

To view diffs of this commit, you can use the following URL(s):

To generate a diff of this commit:
cvs rdiff -r1.40 -r1.41 PEAK/setup.py
cvs rdiff -r0 -r1.1 PEAK/src/peak/binding/data_desc.c \
    PEAK/src/peak/binding/data_desc.pyx PEAK/src/peak/binding/py_obj.h
cvs rdiff -r1.29 -r1.30 PEAK/src/peak/binding/once.py
cvs rdiff -r1.15 -r1.16 PEAK/src/peak/metamodels/tests/General.py
cvs rdiff -r1.10 -r1.11 PEAK/src/peak/metamodels/uml/MetaModel.py
cvs rdiff -r1.56 -r1.57 PEAK/src/peak/model/api.py
cvs rdiff -r1.3 -r1.4 PEAK/src/peak/storage/xmi.py

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

More information about the source-changes mailing list