TransWarp preview release (AOP tools only)
It's here... the first preview release of TransWarp. The bad news is, it only contains working versions of the aspect-oriented programming tools (the rest of the package is in flux). The good news is: 1. It's a *robust* working version, with 114 unit tests to prove it, and 2. There's state-of-the-art documentation, including such cutting-edge technology as tutorials, and super-simple examples. :) You can find the software at: http://www.zope.org/Members/pje/TransWarp/ and the online documentation at: http://www.zope.org/Members/pje/Wikis/TransWarp/ Comments welcome. Enjoy.
This looks very interesting, Phillip. I haven't downloaded the package yet, but I read the wiki and it finally made sense once I understood the goal (I think): TW lets you set up the class inheritance hierarchy at runtime. In normal OO methodology, you can only extend classes. With TW, you can also slip your own version of a base class into a class hierarchy (without actually modifying the Python class hierarchy, of course.) What is your vision of integrating AOP into a persistent object system? Would one drop in an object that modifies the class loading mechanism so that the classes come from a TW component rather than Python modules? Shane "Phillip J. Eby" wrote:
It's here... the first preview release of TransWarp. The bad news is, it only contains working versions of the aspect-oriented programming tools (the rest of the package is in flux). The good news is:
1. It's a *robust* working version, with 114 unit tests to prove it, and
2. There's state-of-the-art documentation, including such cutting-edge technology as tutorials, and super-simple examples. :)
You can find the software at:
http://www.zope.org/Members/pje/TransWarp/
and the online documentation at:
http://www.zope.org/Members/pje/Wikis/TransWarp/
Comments welcome. Enjoy.
At 09:37 AM 3/1/01 -0500, Shane Hathaway wrote:
This looks very interesting, Phillip. I haven't downloaded the package yet, but I read the wiki and it finally made sense once I understood the goal (I think): TW lets you set up the class inheritance hierarchy at runtime. In normal OO methodology, you can only extend classes. With TW, you can also slip your own version of a base class into a class hierarchy (without actually modifying the Python class hierarchy, of course.)
That's a good way of describing the *function* of the AOP part of TransWarp. The goal is not so much to set up the inheritance hierarchy at runtime, as to allow you to configure various versions of the same component, and to write seperately-managed "aspects" for different areas of concern. The targeted time is not really "runtime" so much as "build time". Runtime is a side-effect of how it's done, and it can be useful for things like selecting an OS-specific or other environment-sensitive aspect at application startup. But the main goals of the AOP portion are being able to instantiate customized versions of "third-party" components, and to be able to mix-and-match implementations for different areas of concern. For example, wxPython vs. Tkinter vs. Win32, SQL vs LDAP vs ZODB, and so on. TransWarp in the larger picture will also deal with generative programming; the UML-driven parts will generate aspects that contain structural information (inheritance, associations, aggregations, attributes, etc.) that can then be merged with non-structural aspects. The ability to "set up the class inheritance hierarchy at runtime" provided by the AOP tools will then allow you to define what an "attribute" is, and give it publishability, security permissions, or a GUI rendering. There is actually code in the preview release to do this structural generation for the UML metamodel (if loaded from MMX format), and it's even rudimentarily tested (one unit test that just makes sure it doesn't blow up altogether) but the "StructuralModel" aspects that implement attributes and associations are currently broken, not yet updated for the true AOP model. Earlier versions of TransWarp did class generation as an integral part of the GP system, not as a GP+AOP system, and I'm still adapting a lot of stuff to take advantage of AOP and to use a cleaner metadata mechanism.
What is your vision of integrating AOP into a persistent object system? Would one drop in an object that modifies the class loading mechanism so that the classes come from a TW component rather than Python modules?
Not necessary. If you dig into the TransWarpFAQ page in the Wiki, you'll see a question that explains how to make TW-generated classes work with pickle and cPickle. It just requires one additional argument at aspect-weaving time, to specify the module which the generated classes should be registered with. This means that TW's AOP features are functional right now, today, with ZODB. (As long as the classes are generated in good ol' Python module files.) Now, as to whether TW will be fully compatible with Zope 3 "persistent modules", that's a different question. In the conversation I had with Jim in January, based on his description of the module refresh mechanism and of import proxies, I would say that TW-generated classes would not properly refresh when a persistent module that they were dependent on changed. (Because TW will generate new class objects from the imported classes rather than referencing them via the proxy.) But that's based on a very early notion of how Z3 persistent modules would work. One reason I've been racing like mad to get the preview release out is so that, after seeing the usefulness of TW for the Zope 3 component architecture, y'all might be interested in considering implementations for module persistence besides proxying. :) IMHO, a "rollback importer" approach ala unittest might be better suited for TW-ish components, and have fewer weird side effects for persistent modules generally. I don't like unittest's mechanism for *doing* the rollback, and Zope would need a thread-specific version of sys.modules, as well as a mechanism to purge the cache of any objects which were loaded after any of the purged modules, but I think the basic idea is sound.
"Phillip J. Eby" wrote:
At 09:37 AM 3/1/01 -0500, Shane Hathaway wrote:
What is your vision of integrating AOP into a persistent object system? Would one drop in an object that modifies the class loading mechanism so that the classes come from a TW component rather than Python modules?
Not necessary. If you dig into the TransWarpFAQ page in the Wiki, you'll see a question that explains how to make TW-generated classes work with pickle and cPickle. It just requires one additional argument at aspect-weaving time, to specify the module which the generated classes should be registered with. This means that TW's AOP features are functional right now, today, with ZODB. (As long as the classes are generated in good ol' Python module files.)
Okay, here's how I think AOP could be applied to a current project. We've been separating concerns in the PTK/CMF for the last year now. We've been moving as many responsibilities of the content objects as possible into per-portal "service" objects. The services provide user interface, discussion capability, workflow integration, etc. In doing so, IMHO we've lost a little simplicity. In the current way of doing things, content objects should not know about their own workflow, instead they should be associated with a portal-specific type object and the type object is associated with a set of workflows. And the user interface depends heavily on acquisition now. Now, let's say that instead everything were reintegrated into the content objects using aspects. To retain flexibility, different portals would weave the content objects in different ways because of variations in user interface, workflow, etc. Would this be a good application for TW? This could be achieved by generating a new Python module for each portal instance, but that would mean sys.modules would have to be pre-loaded with the information about each portal instance and that's not the ZODB way. It would be better to create a new class loader that can weave a new class on the fly based on persisted component metadata. Note that class loading is currently quite simple; see lib/python/Zope/ClassLoader.py (sp?). It could bear some complexity. :-)
Now, as to whether TW will be fully compatible with Zope 3 "persistent modules", that's a different question. In the conversation I had with Jim in January, based on his description of the module refresh mechanism and of import proxies, I would say that TW-generated classes would not properly refresh when a persistent module that they were dependent on changed. (Because TW will generate new class objects from the imported classes rather than referencing them via the proxy.) But that's based on a very early notion of how Z3 persistent modules would work.
I don't see how persistent modules can work unless they are highly restricted. The idea is that modules would be "executed" only once then the result of that execution would be stored in the ZODB. But there are a *lot* of things that can't be persisted, like thread locks. You'll have a hard time persisting a module like this: import thread lock = thread.allocate_lock() def foo(): lock.acquire() try: print 'got the lock' finally: lock.release() Maybe this has been solved, I don't know.
One reason I've been racing like mad to get the preview release out is so that, after seeing the usefulness of TW for the Zope 3 component architecture, y'all might be interested in considering implementations for module persistence besides proxying. :) IMHO, a "rollback importer" approach ala unittest might be better suited for TW-ish components, and have fewer weird side effects for persistent modules generally. I don't like unittest's mechanism for *doing* the rollback, and Zope would need a thread-specific version of sys.modules, as well as a mechanism to purge the cache of any objects which were loaded after any of the purged modules, but I think the basic idea is sound.
Hmm. I'm afraid I don't see how TW helps with module persistence. Shane
From: Shane Hathaway <shane@digicool.com>
I don't see how persistent modules can work unless they are highly restricted. The idea is that modules would be "executed" only once then the result of that execution would be stored in the ZODB.
Alternatively, you compile the module and store the marshalled code, and you execute it in a special environment every time the Module object is loaded. Cheers, Evan @ digicool & 4-am
On Fri, 2 Mar 2001, Shane Hathaway wrote:
"Phillip J. Eby" wrote:
One reason I've been racing like mad to get the preview release out is so that, after seeing the usefulness of TW for the Zope 3 component architecture, y'all might be interested in considering implementations for module persistence besides proxying. :) IMHO, a "rollback importer" approach ala unittest might be better suited for TW-ish components, and have fewer weird side effects for persistent modules generally. I don't like unittest's mechanism for *doing* the rollback, and Zope would need a thread-specific version of sys.modules, as well as a mechanism to purge the cache of any objects which were loaded after any of the purged modules, but I think the basic idea is sound.
Hmm. I'm afraid I don't see how TW helps with module persistence.
I could be wrong, but I didn't read what Phillip wrote as saying he was suggesting TransWarp as a player in the Module Persistence implementation, but rather that he wanted people to see the value of TransWarp first hand so that they would want to make sure that Module Persistence and TransWarp could play together.... --RDM
At 12:39 PM 3/2/01 -0500, Shane Hathaway wrote:
We've been separating concerns in the PTK/CMF for the last year now. We've been moving as many responsibilities of the content objects as possible into per-portal "service" objects. The services provide user interface, discussion capability, workflow integration, etc.
In doing so, IMHO we've lost a little simplicity. In the current way of doing things, content objects should not know about their own workflow, instead they should be associated with a portal-specific type object and the type object is associated with a set of workflows. And the user interface depends heavily on acquisition now.
Now, let's say that instead everything were reintegrated into the content objects using aspects. To retain flexibility, different portals would weave the content objects in different ways because of variations in user interface, workflow, etc. Would this be a good application for TW?
Absolutely. And as you've probably guessed, you can insert the implementations at whatever level of the class hierarchy - insert global policies into a base ContentObject, override them at a more detailed level, whatever.
This could be achieved by generating a new Python module for each portal instance, but that would mean sys.modules would have to be pre-loaded with the information about each portal instance and that's not the ZODB way. It would be better to create a new class loader that can weave a new class on the fly based on persisted component metadata. Note that class loading is currently quite simple; see lib/python/Zope/ClassLoader.py (sp?). It could bear some complexity. :-)
There's actually a simpler way. Aspect objects can be pickled as long as all the objects in them can be pickled. Which means that as long as all their methods are Zope objects, and all the nested classes are also Aspect objects, you can save an aspect into the ZODB, and load it at a future time. Further, since adding aspects together makes new aspects, you can save the combined aspects, so you only have to perform one call to transform the aspect into a family of classes. That still means some load-time complexity, however. I haven't given a whole lot of though to through-the-web use of TransWarp's AOP stuff; I've mainly thought of it as being a "Product"-level tool. But I imagine you could perhaps make some sort of "ZAspects" (ala ZClasses) that wrap through-the-webness onto aspects. (Of course, if you can do through-the-web modules, no special magic is required.) Actually, any Python class or ExtensionClass can be used as part of a TW aspect, so you could in fact use ZClasses as part of an aspect right now, if you wanted to. Handling the class hierarchy of a ZClass could be tricky, though, if you wanted to be able to deal with them as a class family. ZClasses have so many parent classes by default. It would be interesting if you could take an arbitrary Zope service object (like a portal), and go to its "Aspects" tab, and add or remove aspects to be woven with its class family. But I suspect it will be a long time before I'll have a need for that personally or professionally, as I am focused primarily on TransWarp as a CASE tool and Python application toolkit at present.
participants (4)
-
Evan Simpson -
Phillip J. Eby -
R. David Murray -
Shane Hathaway