How can I do this?

25 views
Skip to first unread message

Michael Moore

unread,
Sep 19, 2012, 1:40:50 PM9/19/12
to pyjs-...@googlegroups.com
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.

Michael


C Anthony Risinger

unread,
Sep 20, 2012, 12:09:46 AM9/20/12
to pyjs-...@googlegroups.com
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

Michael Moore

unread,
Sep 20, 2012, 2:14:17 PM9/20/12
to pyjs-...@googlegroups.com
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



.


Reply all
Reply to author
Forward
0 new messages