Bengt Richter wrote:
On Fri, 21 Jan 2005 20:23:58 -0500, "Mike C. Fletcher" <[EMAIL PROTECTED]> wrote:
On Thu, 20 Jan 2005 11:24:12 -0000, "Mark English" <[EMAIL PROTECTED]> wrote:
...
Does the BasicProperty base class effectively register itself as an observerBasicProperty itself doesn't register as an observable/observer, BasicProperty is the lowest-level of the software stack, so it allows you to override and provide notification (e.g. using PyDispatcher) on property-setting. ConflictSolver (old project to create a room scheduler) used that to do automatic updating of widgets in the wxPython UI based on Model changes (though I don't remember if it was per-property or per-object). My goal for the wxoo project was to provide hooks in the wxPython GUI designers for dropping in property sheets and/or property-aware controls such that you would have the equivalent of "data aware" controls in VB or Access (keeping in mind that BasicProperty properties can also represent fields in database rows).
of subclass properties and automatically update widgets etc., a la Delphi
data-driven visual components? I've thought of doing a light-weight form
extension class that would use a text (maybe CSV) definition to control
contruction, and easy programmatic manipulation by python of the definition
parameters, like a stripped-down version of the text view of Delphi forms.
It could also be done via Tkinter, to prototype it. It would be interesting
to allow dragging widgets and edges around in Tkinter and round-trip the parameter
changes automatically into the text representation. A little (well, ok, a fair amount ;-)
further and you'd have a drag-n-drop GUI design tool. But don't hold your breath ;-)
Aside:
The VRML97 field class in OpenGLContext does notifications for every set (using PyDispatcher), btw. It's a little more limited in its scope (focus on 3D data-types), but the effect is what allows the scenegraph to cache and then rebuild its internal rendering structures with very low overhead.
...
Not as such, that is, not a workaround, and it shouldn't be keyword based ;) .Anyway, if you aren't interested in BasicProperty for this task; another project on which I work, PyDispatcher provides fairly robust mechanism (called robustApply) for providing a set of possible arguments and using inspect to pick out which names match the parameters for a function in order to pass them in to the function/method/callable object. That said, doing this for __init__'s with attribute values from an object's dictionary doesn't really seem like the proper way to approach the problem.Sounds like a workaround for parameter passing that maybe should have been
keyword-based?
The problem with using keyword-based passing is that every method needs to be written with this awareness of the keyword-handling structures. You spread pointless implementation details throughout your codebase. PyDispatcher lets you write very natural functions for dealing with events without having every function use **named parameters.
I've now written quite a few such systems, and I'm currently balanced between two approaches; that taken in PyDispatcher (define only natural parameters, have the system figure out how to deliver them to you), and that taken in OpenGLContext (define an event-class hierarchy which encapsulates all information about the events).
The PyDispatcher approach is nice in that it makes simple things very simple. You want access to the "lastValue" parameter in the "environment" of the event and nothing else, you define your function like so:
def handler( lastValue ): print 'got last value', lastValue
which works very nicely when you're early in the development of a system, or are linking multiple systems. There's no need to do all sorts of extra work defining event hierarchies, you can often leave given handlers entirely alone during refactoring if they aren't dealing with the changed properties in the event-environment.
The OpenGLContext approach is more appropriate when you have a large system (such as OpenGLContext), where defining an event class is a trivial task compared to the total system expenditure. It allows for such things as putting methods on the event objects to make debugging easy, and providing common functionality. It starts to show it's worth when you start needing to reason about the phenomena of events themselves, rather than just about the phenomena the events represent (e.g. when you need to cache, delay, or reorder events).
The named argument passing approach has the disadvantage that every function must be written with knowledge of that use of named arguments:
def handler( lastValue, **named ): print 'got last value', lastValue
when using such systems in the past I've often wound up with errors deep in an application where some seldom-called callback didn't have a **named parameter, so the system would abort (well, log an error) trying to call it.
Is it a huge overhead? No. But its unnecessary if you've got a tool that takes care of that "implementation-level" detail for you. Compared to robustApply, the difference is pretty minimal. If you define a **named parameter, for instance, you will get the remainder of the robustApply environment passed in.
In another lifetime, you could imagine these systems being written as wrappers that added a nested scope around the definition of the function such that the scope forwarded unresolved name references to the environment of the event (non-lexical scoping), but that would lack the explicitness of passing in the arguments from the environment and would, I suppose be evil in a quite non-trivial way.
Peace, and have fun, Mike
________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com
-- http://mail.python.org/mailman/listinfo/python-list