Re: Models...
Magnus Lie Hetland <[email protected]>
| Newsgroups | gmane.comp.python.anygui.devel |
|---|---|
| Message-ID | <[email protected]> |
Dallas Johnston <[email protected]>: > > Hello all, > > I have spent some time today on the Models, implementing a slightly > modified version of my delegate idea. Instead of having an actual > class do the delegation, which would break encapsulation =), I have > delegated (irony intended) all the model management code to the > Proxy class. > > In fact, due to Proxy handling all the lower level push/pull > functionality, there really was no other clean way to deal with it. > Also, by thus having Proxy marshal values into the Models, Attribs > becomes *far* less complicated, and the Wrappers pushing values up > into the Proxy causes Proxy to update all related models =). This sounds good (without having done any detailed thinking on the subject ;) > As of now, BooleanModel works like a charm, Great! > but there are still very > menial bugs to iron out, and I need to get some sleep. > > Only one question though... from the test_modv3.py it seems that the > use of the model is inconsistent. For example, the calls to > link(newbtn.on, printit2) and log('printit2:',newbtn.on) seem to > represent the presence of slight confusion in the mind of the author > with regard to what newbtn.on is supposed to represent in each call. > In the first case, newbtn.on is assumed to return the actual model > object, whereas the second case is expecting the value that the > model represents. Well, the __repr__ of a model should mimic the value it represents (or so, I think, was the idea). So for a BooleanModel, __str__ should either be '1' or '0'... Or perhaps 'True' of 'False', even... Also, int(BooleanModel()) should return 0 etc. The models should behave much like the values they represent/contain. > And discerning wich of these expectations is in fact based in a more > credible comprehension of the matter is a little more than subtle. Hm. The point is that button.on can contain any Boolean value, whether it be an int, a bool, a BooleanModel, or whatever. Basically, the button shouldn't worry (except for some special-case code for in-place editing geared towards models). > In reality, if you are wanting to retrieve the value that he model > represents, then 'val = widget.property', where 'property' is a > model, proves the more appealing idiom. I don't think so... Assuming that by "widget" you mean a proxy, I think that proxy.property should always return the value of the given property. If that value happens to be of a Model class, the instance should be returned anyway. If you choose to treat it as a Boolean value, it the BooleanModel instance should behave accordingly. > However, when one wants to > call a user-provided method on the model, which is the real purpose > of user-provided models, then a call like > 'widget.property.calculate()' will fail miserably, as > 'widget.__getattr__' will have returned the value that 'property' > represents. I *absolutely* don't want this sort of behaviour. The following should hold (for objects that can be modified in-place): >>> proxy.attr = value >>> proxy.attr is value 1 If value is a model, that shouldn't make a bit of difference. The only special-casing of models is handled by the in-place modification (which uses the value attribute when available) and the assignee protocol. Nothing else should be needed. ... except for one thing... ;) In proxy.pull(), all attributes should be modified in-place (if possible) by the value returned from the wrapper. This ensures that models aren't replaced etc. (Not sure if this is correctly implemented at the moment -- I seem to recall Samuele pointing out some errors there). So, the following should work: >>> proxy.width = model = NumberModel() >>> # User modifies proxy graphically >>> proxy.pull('width') # proxy.width is modified in-place >>> # model will now trigger an update in its views But what about proxy.push()? Samuele brought this up: We might end up with Models in the Wrapper's setters. We might accept this, assuming that the setters will do any necessary coercing (such as using list(model) or int(model) etc.) -- I think this is a reasonable approach -- or we might try to do the coercion before passing the value to the wrapper. The only reasonable thing we can do there (as I see it) is to try to use foobar.value (for an object foobar) if it exists... But, as I said, I think it is better to require the Wrapper to make fewer assumptions about the values it receives; e.g. a coordinate will be number-like, but not necessarily an int. If the back-end needs an int, then the setter should be implemented something like: def setX(self, x): if self.widget is not None: self.widget.x = int(x) (assuming that we keep the "wrapper is not None"-checking in the Wrapper). The more I think about it, the more I'm convinced that this is the way to do it. > And I cannot refer to the old version of Attribs.py without mucking > about with cvs, so I'll have to look into it tomorrow. > > cheers all, > --Dallas -- Magnus Lie Hetland Practical Python The Anygui Project http://hetland.org http://ppython.com http://anygui.org ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf