On Wed, Sep 19, 2012 at 9:09 PM, C Anthony Risinger <[email protected]> wrote:
> On Wed, Sep 19, 2012 at 12:40 PM, Michael Moore > <[email protected]> wrote: > > I am getting an error. > > > > newsink AttributeError: '<AlphaListBoxsetup object>' has no attribute > > 'onalphaItemSelected' > > > > class AlphaListBoxsetup(SimplePanel): > > def __init__(self): > > SimplePanel.__init__(self) > > self.list1=ListBox() > > self.list1.setVisibleItemCount(8) > > A.alpha.sort() > > for item in A.alpha: > > self.list1.addItem(item) > > self.add(self.list1) > > self.list1.addChangeListener(getattr(self, > 'onalphaItemSelected')) > > > > def generic(self): > > item = self.list1.getItemText(self.list1.getSelectedIndex()) > > Window.alert("You selected %s from the stack Alphabetic" %(item)) > > generic.__name__ = 'onalphaItemSelected' > > locals()['onalphaItemSelected'] = generic > > > > is the relevant code. Of course, with the def generic() line changed to > def > > onalphaItemSelected(), it works just fine. > > > > I have a situation where I do not know until runtime how many listboxes > with > > selections I need to produce. This may be an area where Python will and > > Pyjs won't, but in Python that code should allow the generation of > functions > > with names set from strings. Immediate mode example follows: > > > >>>>> def generic(x): > > .... return x**2 > > .... > >>>>> globals()['squareit']=generic > >>>>> squareit(25) > > 625 > >>>>> def generic(x): > > .... return x**3 > > .... > >>>>> globals()['cubeit']=generic > >>>>> squareit(25) > > 625 > >>>>> cubeit(25) > > 15625 > >>>>> > > > > > > This allows the definition of functions whose names are generated by code > > without resorting to metaprogramming with exec, but it seems not to work > in > > Pyjs. > > > > Any suggestions for accomplishing this? I have a group of scripts to be > > picked to be part of a workflow, and I have one list where they are in > > alphabetical order, then another list of those used most frequently, then > > another list of those concerned with just alignment, and so on. Many > tags > > are possible and more functional tags may be added to the script nodes at > > any time, so when the list of scripts is pulled from the database, the > tags > > are basically a list for each script that defines every folder in which > the > > script name should appear. I have no difficulty generating that on the > > controller, but when I shoot that information over as a JSON object, I > have > > to manufacture a stack panel full of lists and allow one choice from one > > selected list. > > i can't get too in depth with your code here, but since a few of your > other posts have similar issue i thought i would try and alleviate > some of your pain. > > first off, avoid unnecessary logic during class creation. try using > setattr() after the fact, or using the 3-arg type() class constructor. > this is a scoping problem/bug in pyjs ... do the logic outside class > creation. > > tbh, i'm not sure the status of globals() and locals() off-hand, but > neither are required for dynamic creation of object members ... ever. > using them for such makes the code less understandable, and may rely > on implementation details, eg. for locals(): > > Note The contents of this dictionary should not be modified; changes > may not affect the values of local and free variables used by the > interpreter. > > ... straight from python 2.7 docs. globals is simply the __dict__ of > a module, so: > > import moduleX > setattr(moduleX, some_identifier_that_is_dynamic, func) > > ... is exactly the same as performing: > > globals()[some_identifier_that_is_dynamic] = func > > ... from within `moduleX`. while i'm not sure off-hand pyjs will > tolerate it, i have in the past imported the current module, and > setattr() on itself ... you simply can't use symbols that have not > been created yet. for example, to maintain backward compatibility, i > did this in pyjd/__init__.py: > > #TODO: very ugly to self-import and setattr(self) ... remove ASAP! > import pyjd > [...] > for key, value in _manager._conf.iteritems(): > setattr(pyjd, key, value) > > ... in short, there is nothing here that setattr()/getattr() cannot > handle; i think if you reorganize a bit, and shoot for less exotic > patterns, you will have no trouble squeezing all the dynamism you can > handle from pyjs ;-) > > -- > > C Anthony > > > Many thanks for your suggestions. I did try them, and within the > constraints of how I may organize this app, I can't seem to get Pyjs to > accept the setattr(). That is OK. All the other dynamics are there, and > they communicate through a blank module used as a singleton. I got the > onClick (not the preferred Button('Title', getattr('onTitleClick', self) > but the Button('Title', self) and the onClick(self))functioning as a > dispatcher. Retrieving text from the button took a bit of study but > str(buttonobject.getHTML())) works. If I leave this app in other hands, > the only rewrite for later expansion will be on the stackpanel (adding > classes for each new category), and the expanded app will work without that > addition. With a list like this, who needs any of the other toolkits? Dojo, if you know it, might be a little faster to put together simpler apps, but if you need to push the envelope, Pyjs is the bees knees. Besides that, it works with Pyramid and Pypy, and this list makes it something superior. Michael . > > --
