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
--