The Bug Watch Widget ==================== There's a custom widget used to link a bug watch to a bug task. It's a simple RadioWidget with some modifications. First we need to bind a BugWatch field to a bug task. Let's bind it to the Debian task in bug 1 >>> login('test@canonical.com') >>> from lp.bugs.interfaces.bug import IBugSet, IBugTask >>> bug_one = getUtility(IBugSet).get(1) >>> bugwatch_field = IBugTask['bugwatch'] >>> debian_task = bug_one.bugtasks[2] >>> debian_task.bugtargetname u'mozilla-firefox (Debian)' >>> bugwatch_field = bugwatch_field.bind(debian_task) Now we can create a widget using a test request: >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest >>> from lp.bugs.browser.widgets.bugtask import BugTaskBugWatchWidget >>> request = LaunchpadTestRequest() >>> bugwatch_widget = BugTaskBugWatchWidget( ... bugwatch_field, bugwatch_field.vocabulary, request) We can assume that RadioWidget works probably, so let's look at what we changed; renderItems(). It renders all the items of the widget, with the one representing the value passed to the method as selected. It also renders an option for creating a new bug watch. Let's define a helper function to make it easier to see what's going on. >>> from BeautifulSoup import BeautifulSoup >>> def print_item(item): ... soup = BeautifulSoup(item) ... input_td, label_td = soup('td') ... if input_td.input.get('checked'): ... selected = 'SELECTED' ... else: ... selected = 'NOT SELECTED' ... print "%s: %s" % (selected, label_td.label) Now if we pass None to renderItems(), the first radio button will be selected. >>> for item in bugwatch_widget.renderItems(None): ... print_item(item) SELECTED: None, the status of the bug is updated manually... NOT SELECTED: The Mozilla.org Bug Tracker #123543... NOT SELECTED: The Mozilla.org Bug Tracker #2000... NOT SELECTED: The Mozilla.org Bug Tracker #42... NOT SELECTED: Debian Bug tracker #304014... NOT SELECTED:
URL:
If we pass a bug watch to renderItems(), the corresponding radio button will be selected. >>> mozilla_bugwatch = bug_one.watches[0] >>> mozilla_bugwatch.title u'The Mozilla.org Bug Tracker #123543' >>> for item in bugwatch_widget.renderItems(mozilla_bugwatch): ... print_item(item) NOT SELECTED: None, the status of the bug is updated manuall... SELECTED: The Mozilla.org Bug Tracker #123543... NOT SELECTED: The Mozilla.org Bug Tracker #2000... NOT SELECTED: The Mozilla.org Bug Tracker #42... NOT SELECTED: Debian Bug tracker #304014... NOT SELECTED:
URL:
If we pass _new_bugwatch_value to renderItems(), the corresponding radio button will be selected. >>> new_bugwatch_value = bugwatch_widget._new_bugwatch_value >>> for item in bugwatch_widget.renderItems(new_bugwatch_value): ... print_item(item) NOT SELECTED: None, the status of the bug is updated manuall... NOT SELECTED: The Mozilla.org Bug Tracker #123543... NOT SELECTED: The Mozilla.org Bug Tracker #2000... NOT SELECTED: The Mozilla.org Bug Tracker #42... NOT SELECTED: Debian Bug tracker #304014... SELECTED:
URL:
Now let's use the widget to actually create a new bug watch. First let's take a look at which bug watches are currently associated with the bug. >>> for bug_watch in bug_one.watches: ... print "%s: #%s" % ( ... bug_watch.bugtracker.title, bug_watch.remotebug) The Mozilla.org Bug Tracker: #123543 The Mozilla.org Bug Tracker: #2000 The Mozilla.org Bug Tracker: #42 Debian Bug tracker: #304014 Now let's create a new bug watch, pointing at bug #84 in the Gnome tracker. >>> NEW = BugTaskBugWatchWidget._new_bugwatch_value >>> request = LaunchpadTestRequest(form={ ... 'field.bugwatch': NEW, 'field.url': ( ... u'http://bugzilla.gnome.org/bugs/show_bug.cgi?id=84')}) >>> bugwatch_widget = BugTaskBugWatchWidget( ... bugwatch_field, bugwatch_field.vocabulary, request) >>> bugwatch = bugwatch_widget.getInputValue() >>> bugwatch.bugtracker.title u'GnomeGBug GTracker' >>> bugwatch.remotebug u'84' >>> for bug_watch in bug_one.watches: ... print "%s: #%s" % ( ... bug_watch.bugtracker.title, bug_watch.remotebug) The Mozilla.org Bug Tracker: #123543 The Mozilla.org Bug Tracker: #2000 The Mozilla.org Bug Tracker: #42 GnomeGBug GTracker: #84 Debian Bug tracker: #304014 If we try to create a bug watch that already exists, the existing bug watch is being returned, and no new bug watch is created. >>> request = LaunchpadTestRequest(form={ ... 'field.bugwatch': NEW, 'field.url': ( ... u'http://bugzilla.gnome.org/bugs/show_bug.cgi?id=84')}) >>> bugwatch_widget = BugTaskBugWatchWidget( ... bugwatch_field, bugwatch_field.vocabulary, request) >>> bugwatch = bugwatch_widget.getInputValue() >>> bugwatch.bugtracker.title u'GnomeGBug GTracker' >>> bugwatch.remotebug u'84' >>> for bug_watch in bug_one.watches: ... print "%s: #%s" % ( ... bug_watch.bugtracker.title, bug_watch.remotebug) The Mozilla.org Bug Tracker: #123543 The Mozilla.org Bug Tracker: #2000 The Mozilla.org Bug Tracker: #42 GnomeGBug GTracker: #84 Debian Bug tracker: #304014 If we enter a URL that doesn't match an existing bug tracker, a WidgetInputError is being raised. >>> request = LaunchpadTestRequest(form={ ... 'field.bugwatch': NEW, ... 'field.url': 'http://not.a.bug.tracker/'}) >>> bugwatch_widget = BugTaskBugWatchWidget( ... bugwatch_field, bugwatch_field.vocabulary, request) >>> bugwatch = bugwatch_widget.getInputValue() Traceback (most recent call last): ... WidgetInputError:... In order to make the widget not raise on error on 'NEW', which is not part of the vocabulary, we've overridden _toFieldValue(), so that when it's passed 'NEW', it will return the newly created bug watch. >>> request = LaunchpadTestRequest(form={ ... 'field.bugwatch': NEW, 'field.url': ( ... 'http://bugzilla.gnome.org/bugs/show_bug.cgi?id=177')}) >>> bugwatch_widget = BugTaskBugWatchWidget( ... bugwatch_field, bugwatch_field.vocabulary, request) >>> bugwatch = bugwatch_widget._toFieldValue(NEW)