Passing context through/around/across webform

So I've started to move Payago (formerly Go) towards compatibility with Nevow 0.3's API changes; the biggest impact has been the ubiquitous context, and not being able to rely on a Page having self.context. Previously, I had _many_ TypedInterfaces which did something along the lines of: class ICanDoSomething(TypedInterface): def doSomething(self, arg = Choice(choicesAttribute='choices')): pass doSomething = autocallable(doSomething) class MyPage(Page): __implements__ = ICanDoSomething def _get_choices(self): ## do something involving self.context return some_list choices = property(_get_choices) Now, with the ubiquitous context changes, self.context doesn't exist. (Makes you wonder what "ubiquitous" really means.) So there are a couple solutions that I've thought of: 1. Make annotate.Choice support 'choicesMethod', which would take context as an argument. This seems very difficult because not only webform, but Typed.coerce(), would have to be able to retrieve the context. Then we'd have to support Deferreds, because some crazy person would obviously want that at some point. ;) I tried to write a patch, and it got ugly. 2. Set self.context whenever Page.locateChild or Page.renderHTTP is called. This is a lot simpler, but it seems like a hack to me, and I'm not sure whether this will _always_ work. What do other people think? Is option #1 easier to implement than I'm thinking? Is option #2 safer than it seems to me? Is there an option #3 that I don't see right now? -- Alex Levy WWW: http://mesozoic.geecs.org/ "Never let your sense of morals prevent you from doing what is right." -- Salvor Hardin, Isaac Asimov's _Foundation_

Here's my horribly hacked up copy of Choice that works for what I need. The changes from the normal Choice are that choicesAttribute is really choicesMethod, and that it's supposed to return a list of (id, text), and the ids are used as the keys sent to the client, instead of the offset in the list. Offset in the list is worthless to me, because the list is dynamically generated and won't be consistent. class ChoiceTuple(Typed): """Allow the user to pick from a list of "choices", or a list of choices found by accessing the list in the attribute "choicesAttribute" of the object we are configuring. The elements of the list will be rendered by calling "str". """ def __init__(self, choices=None, choicesAttribute=None, *args, **kw): Typed.__init__(self, *args, **kw) if choices is None: self.choices = () else: self.choices = choices self.choicesAttribute = choicesAttribute def coerce(self, val, binding): """Coerce a value with the help of an object, which is the object we are configuring. """ try: val = int(val) except ValueError: raise InputError("%r is an invalid choice." % val) return val class ChoiceTupleRenderer(webform.BaseInputRenderer): def input(self, context, slot, data, name, value): tv = data.typedValue if tv.choicesAttribute: choices = getattr(context.locate(iformless.IConfigurable).boundTo, tv.choicesAttribute)(context, data) else: choices = tv.choices if isinstance(choices, defer.Deferred): return choices.addCallback(self.input2, context, slot, data, name, value) self.input2(choices, context, slot, data, name, value) def input2(self, choices, context, slot, data, name, value): numChoices = len(choices) if numChoices == 0: return None selecter = tags.select(id=formutils.keyToXMLID(context.key), name=name) for key, val in choices: if key == value: selecter[tags.option(value=str(key), selected="selected")[str(val)]] else: selecter[tags.option(value=str(key))[str(val)]] return slot[selecter]

James Y Knight wrote:
Here's my horribly hacked up copy of Choice that works for what I need. The changes from the normal Choice are that choicesAttribute is really choicesMethod, and that it's supposed to return a list of (id, text),
Sounds like you should use dict instead of a list. Otherwise there could be duplicate ids.

On Tue, Oct 19, 2004 at 07:27:57PM +0300, Tommi Virtanen wrote:
James Y Knight wrote:
Here's my horribly hacked up copy of Choice that works for what I need. The changes from the normal Choice are that choicesAttribute is really choicesMethod, and that it's supposed to return a list of (id, text),
Sounds like you should use dict instead of a list. Otherwise there could be duplicate ids.
This is true, except that you will sometimes need a way to specify what order the items appear in -- which might mean a (dict, list) tuple, or something of the sort. I'm having some initial success with this approach in Payago, and if I come up with something generic enough to be useful to others, I'll post it back here. The real problem is getting the context object passed down to the Typed.coerce call, so that you don't have to implement code to "retrieve my (dict, list) and check for the key" in a million different places. -- Alex Levy WWW: http://mesozoic.geecs.org/ "Never let your sense of morals prevent you from doing what is right." -- Salvor Hardin, Isaac Asimov's _Foundation_

On Oct 19, 2004, at 12:27 PM, Tommi Virtanen wrote:
James Y Knight wrote:
Here's my horribly hacked up copy of Choice that works for what I need. The changes from the normal Choice are that choicesAttribute is really choicesMethod, and that it's supposed to return a list of (id, text),
Sounds like you should use dict instead of a list. Otherwise there could be duplicate ids.
But since I provide the list, I can guarantee that there aren't. And I need the ordering. And even if there are duplicates, it's not a horrible thing. It just means there'll be two entries in the menu that mean the same thing. Under some conditions you might even want that. James

James Y Knight wrote:
But since I provide the list, I can guarantee that there aren't. And I need the ordering. And even if there are duplicates, it's not a horrible thing. It just means there'll be two entries in the menu that mean the same thing. Under some conditions you might even want that.
For the sake of argument, I can't think of _any_ circumstances where I'd want two different objects associated with the same key. Can you? How would you go about determining which object was actually chosen? -- Alex Levy WWW: http://mesozoic.geecs.org "Never let your sense of morals prevent you from doing what is right." -- Salvor Hardin, Isaac Asimov's _Foundation_

On Oct 20, 2004, at 10:04 AM, Alex Levy wrote:
James Y Knight wrote:
But since I provide the list, I can guarantee that there aren't. And I need the ordering. And even if there are duplicates, it's not a horrible thing. It just means there'll be two entries in the menu that mean the same thing. Under some conditions you might even want that.
For the sake of argument, I can't think of _any_ circumstances where I'd want two different objects associated with the same key. Can you? How would you go about determining which object was actually chosen?
Well, I think it's a silly thing to argue about since the most important part is the ordering. The ability to have duplicates kinda just falls out of that. But, here goes, anyways. Two strings, presented to the user, with the same meaning. You wouldn't determine which was chosen, what with them having the same meaning and all. This example has two sets of duplicate keys, just for extra points. United States of America shows up in the alphabetized list, and in a separate section at the top. The blank entry shows up first, and between the initial countries and the rest. Choose your Country: USA [United States of America] Canada Afganistan Algeria United Kingdom United States of America Uruguay Zimbabwe James
participants (3)
-
Alex Levy
-
James Y Knight
-
Tommi Virtanen