コード例 #1
0
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     fields = [
         Choice(__name__='product',
                title=u'Project',
                required=True,
                vocabulary=self.getProductVocabulary()),
         Choice(__name__='distribution',
                title=u"Distribution",
                required=True,
                vocabulary=self.getDistributionVocabulary(),
                default=getUtility(ILaunchpadCelebrities).ubuntu),
         Choice(__name__='package',
                title=u"Package",
                required=False,
                vocabulary='BinaryAndSourcePackageName'),
     ]
     self.distribution_widget = CustomWidgetFactory(LaunchpadDropdownWidget)
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     IInputWidget,
                     prefix=self.name)
     self._widgets_set_up = True
コード例 #2
0
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
         # Replace the default field with a field that uses the better
         # vocabulary.
         package_vocab = 'DistributionSourcePackage'
     else:
         package_vocab = 'BinaryAndSourcePackageName'
     fields = [
         Choice(__name__='product',
                title=u'Project',
                required=True,
                vocabulary=self.getProductVocabulary()),
         Choice(__name__='distribution',
                title=u"Distribution",
                required=True,
                vocabulary=self.getDistributionVocabulary(),
                default=getUtility(ILaunchpadCelebrities).ubuntu),
         Choice(__name__='package',
                title=u"Package",
                required=False,
                vocabulary=package_vocab),
     ]
     self.distribution_widget = CustomWidgetFactory(LaunchpadDropdownWidget)
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     IInputWidget,
                     prefix=self.name)
     self._widgets_set_up = True
コード例 #3
0
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     if bool(getFeatureFlag("disclosure.dsp_picker.enabled")):
         # Replace the default field with a field that uses the better
         # vocabulary.
         package_vocab = "DistributionSourcePackage"
     else:
         package_vocab = "BinaryAndSourcePackageName"
     fields = [
         Choice(__name__="project",
                title=u"Project",
                required=True,
                vocabulary="Product"),
         Choice(__name__="distribution",
                title=u"Distribution",
                required=True,
                vocabulary="Distribution",
                default=getUtility(ILaunchpadCelebrities).ubuntu),
         Choice(__name__="package",
                title=u"Package",
                required=False,
                vocabulary=package_vocab),
     ]
     if not self._read_only:
         self.distribution_widget = CustomWidgetFactory(
             LaunchpadDropdownWidget)
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     self._sub_widget_interface,
                     prefix=self.name)
     self._widgets_set_up = True
コード例 #4
0
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     fields = [
         Choice(__name__="person",
                title=u"Person",
                required=False,
                vocabulary="ValidPersonOrTeam"),
     ]
     if self._read_only:
         self.person_widget = CustomWidgetFactory(
             GitGranteePersonDisplayWidget)
     else:
         self.person_widget = CustomWidgetFactory(
             PersonPickerWidget,
             # XXX cjwatson 2018-10-18: This is a little unfortunate, but
             # otherwise there's no spacing at all between the
             # (deliberately unlabelled) radio button and the text box.
             style="margin-left: 4px;")
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     self._sub_widget_interface,
                     prefix=self.name)
     self._widgets_set_up = True
コード例 #5
0
    def initialize(self):
        """See `LaunchpadView.initialize`."""
        review_status_field = copy_field(
            ICodeImport['review_status'], required=False, default=None)
        self.review_status_widget = CustomWidgetFactory(DropdownWidgetWithAny)
        setUpWidget(self, 'review_status',  review_status_field, IInputWidget)

        rcs_type_field = copy_field(
            ICodeImport['rcs_type'], required=False, default=None)
        self.rcs_type_widget = CustomWidgetFactory(DropdownWidgetWithAny)
        setUpWidget(self, 'rcs_type',  rcs_type_field, IInputWidget)

        # status should be None if either (a) there were no query arguments
        # supplied, i.e. the user browsed directly to this page (this is when
        # hasValidInput returns False) or (b) the user chose 'Any' in the
        # status widget (this is when hasValidInput returns True but
        # getInputValue returns None).
        review_status = None
        if self.review_status_widget.hasValidInput():
            review_status = self.review_status_widget.getInputValue()
        # Similar for 'type'
        rcs_type = None
        if self.rcs_type_widget.hasValidInput():
            rcs_type = self.rcs_type_widget.getInputValue()

        imports = self.context.search(
            review_status=review_status, rcs_type=rcs_type)

        self.batchnav = BatchNavigator(imports, self.request)
コード例 #6
0
ファイル: product.py プロジェクト: pombreda/UnnaturalCodeFork
 def renderValue(self, value):
     # Render the items with subordinate fields and support markup.
     self.bug_trackers = dict(self.renderItems(value))
     self.product = self.context.context
     # The view must also use GhostWidget for the 'remote_product' field.
     self.remote_product = copy_field(IProduct['remote_product'])
     self.remote_product_widget = CustomWidgetFactory(TextWidget)
     setUpWidget(self,
                 'remote_product',
                 self.remote_product,
                 IInputWidget,
                 prefix='field',
                 value=self.product.remote_product,
                 context=self.product)
     # The view must also use GhostWidget for the 'enable_bug_expiration'
     # field.
     self.enable_bug_expiration = copy_field(
         IProduct['enable_bug_expiration'])
     self.enable_bug_expiration_widget = CustomWidgetFactory(CheckBoxWidget)
     setUpWidget(self,
                 'enable_bug_expiration',
                 self.enable_bug_expiration,
                 IInputWidget,
                 prefix='field',
                 value=self.product.enable_bug_expiration,
                 context=self.product)
     return self.template()
コード例 #7
0
class BrandingChangeView(LaunchpadEditFormView):
    """This is a base class that MUST be subclassed for each object, because
    each object will have a different description for its branding that is
    part of its own interface.

    For each subclass, specify the schema ("IPerson") and the field_names
    (some subset of icon, logo, mugshot).
    """
    @property
    def label(self):
        return ('Change the images used to represent %s in Launchpad' %
                self.context.displayname)

    page_title = "Change branding"

    custom_widget_icon = CustomWidgetFactory(ImageChangeWidget,
                                             ImageChangeWidget.EDIT_STYLE)
    custom_widget_logo = CustomWidgetFactory(ImageChangeWidget,
                                             ImageChangeWidget.EDIT_STYLE)
    custom_widget_mugshot = CustomWidgetFactory(ImageChangeWidget,
                                                ImageChangeWidget.EDIT_STYLE)

    @action("Change Branding", name='change')
    def change_action(self, action, data):
        self.updateContextFromData(data)

    @property
    def next_url(self):
        return canonical_url(self.context)

    cancel_url = next_url
コード例 #8
0
 def __init__(self, context, request):
     SimpleInputWidget.__init__(self, context, request)
     fields = form.Fields(
         Choice(__name__='action',
                source=self._getActionsVocabulary(),
                title=_('Action')),
         Datetime(__name__='announcement_date',
                  title=_('Date'),
                  required=False,
                  default=None))
     fields['action'].custom_widget = CustomWidgetFactory(
         LaunchpadRadioWidget)
     fields['announcement_date'].custom_widget = CustomWidgetFactory(
         DateTimeWidget)
     if IAnnouncement.providedBy(self.context.context):
         # we are editing an existing announcement
         data = {}
         date_announced = self.context.context.date_announced
         data['announcement_date'] = date_announced
         if date_announced is None:
             data['action'] = 'sometime'
         else:
             data['action'] = 'specific'
     else:
         data = {'action': 'immediately'}
     widgets = form.setUpWidgets(fields,
                                 self.name,
                                 context,
                                 request,
                                 ignore_request=False,
                                 data=data)
     self.action_widget = widgets['action']
     self.announcement_date_widget = widgets['announcement_date']
コード例 #9
0
class ProductReleaseEditView(LaunchpadEditFormView):
    """Edit view for ProductRelease objects"""

    schema = IProductRelease
    field_names = [
        "datereleased",
        "release_notes",
        "changelog",
        ]

    custom_widget_datereleased = DateTimeWidget
    custom_widget_release_notes = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)
    custom_widget_changelog = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)

    @property
    def label(self):
        """The form label."""
        return smartquote('Edit %s release details' % self.context.title)

    page_title = label

    @action('Change', name='change')
    def change_action(self, action, data):
        self.updateContextFromData(data)
        self.next_url = canonical_url(self.context)

    @property
    def cancel_url(self):
        return canonical_url(self.context)
コード例 #10
0
ファイル: sprint.py プロジェクト: pombredanne/launchpad-3
class SprintEditView(LaunchpadEditFormView):
    """Form for editing sprints"""

    schema = ISprint
    label = "Edit sprint details"

    field_names = [
        'name',
        'title',
        'summary',
        'home_page',
        'driver',
        'time_zone',
        'time_starts',
        'time_ends',
        'is_physical',
        'address',
    ]
    custom_widget_summary = CustomWidgetFactory(TextAreaWidget, height=5)
    custom_widget_time_starts = CustomWidgetFactory(DateTimeWidget,
                                                    display_zone=False)
    custom_widget_time_ends = CustomWidgetFactory(DateTimeWidget,
                                                  display_zone=False)
    custom_widget_address = CustomWidgetFactory(TextAreaWidget, height=3)

    def setUpWidgets(self):
        LaunchpadEditFormView.setUpWidgets(self)
        timeformat = '%Y-%m-%d %H:%M'
        self.widgets['time_starts'].timeformat = timeformat
        self.widgets['time_ends'].timeformat = timeformat
        time_zone_widget = self.widgets['time_zone']
        # What time zone are the start and end values relative to?
        if time_zone_widget.hasValidInput():
            tz = pytz.timezone(time_zone_widget.getInputValue())
        else:
            tz = pytz.timezone(self.context.time_zone)
        self.widgets['time_starts'].required_time_zone = tz
        self.widgets['time_ends'].required_time_zone = tz

    def validate(self, data):
        time_starts = data.get('time_starts')
        time_ends = data.get('time_ends')
        if time_starts and time_ends and time_ends < time_starts:
            self.setFieldError('time_ends',
                               "This event can't start after it ends")

    @action(_('Change'), name='change')
    def change_action(self, action, data):
        self.updateContextFromData(data)

    @property
    def next_url(self):
        return canonical_url(self.context)

    @property
    def cancel_url(self):
        return canonical_url(self.context)
コード例 #11
0
ファイル: bugtask.py プロジェクト: pombreda/UnnaturalCodeFork
 def __init__(self, field, vocabulary, request):
     RadioWidget.__init__(self, field, vocabulary, request)
     self.url_widget = CustomWidgetFactory(URIWidget)
     setUpWidget(self,
                 'url',
                 BugWatchEditForm['url'],
                 IInputWidget,
                 context=field.context)
     self.setUpJavascript()
コード例 #12
0
class BugSubscriptionFilterEditViewBase(LaunchpadEditFormView,
                                        AdvancedSubscriptionMixin):
    """Base class for edit or create views of `IBugSubscriptionFilter`."""

    schema = IBugSubscriptionFilter
    field_names = (
        "description",
        "statuses",
        "importances",
        "information_types",
        "tags",
        "find_all_tags",
        )

    custom_widget_description = CustomWidgetFactory(
        TextWidget, displayWidth=50)
    custom_widget_statuses = LabeledMultiCheckBoxWidget
    custom_widget_importances = LabeledMultiCheckBoxWidget
    custom_widget_information_types = LabeledMultiCheckBoxWidget
    custom_widget_tags = CustomWidgetFactory(
        BugTagsFrozenSetWidget, displayWidth=35)

    # Define in concrete subclass to be the target of the
    # structural subscription that we are modifying.
    target = None

    # This is used by the AdvancedSubscriptionMixin.
    current_user_subscription = None

    @cachedproperty
    def _bug_notification_level_descriptions(self):
        return bug_notification_level_description_mapping(
            'a bug in %s' % self.target.displayname)

    def setUpFields(self):
        """Set up fields for form.

        Overrides the usual implementation to also set up bug notification."""
        super(BugSubscriptionFilterEditViewBase, self).setUpFields()
        self._setUpBugNotificationLevelField()

    @property
    def next_url(self):
        """Return to the user's structural subscriptions page."""
        return canonical_url(
            self.user, view_name="+structural-subscriptions")

    cancel_url = next_url
コード例 #13
0
class ProductReleaseAddViewBase(LaunchpadFormView):
    """Base class for creating a release from an existing or new milestone.

    Subclasses need to define the field_names a form action.
    """
    schema = IProductRelease

    custom_widget_datereleased = DateTimeWidget
    custom_widget_release_notes = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)
    custom_widget_changelog = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)

    def _prependKeepMilestoneActiveField(self):
        keep_milestone_active_checkbox = FormFields(
            Bool(
                __name__='keep_milestone_active',
                title=_("Keep the %s milestone active." % self.context.name),
                description=_(
                    "Only select this if bugs or blueprints still need "
                    "to be targeted to this project release's milestone.")),
            render_context=self.render_context)
        self.form_fields = keep_milestone_active_checkbox + self.form_fields

    def _createRelease(self, milestone, data):
        """Create product release for this milestone."""
        newrelease = milestone.createProductRelease(
            self.user, changelog=data['changelog'],
            release_notes=data['release_notes'],
            datereleased=data['datereleased'])
        # Set Milestone.active to false, since bugs & blueprints
        # should not be targeted to a milestone in the past.
        if data.get('keep_milestone_active') is False:
            milestone.active = False
        self.next_url = canonical_url(newrelease.milestone)
        notify(ObjectCreatedEvent(newrelease))

    @property
    def label(self):
        """The form label."""
        return smartquote('Create a new release for %s' %
                          self.context.product.displayname)

    page_title = label

    @property
    def cancel_url(self):
        return canonical_url(self.context)
コード例 #14
0
ファイル: product.py プロジェクト: pombreda/UnnaturalCodeFork
    def __init__(self, field, vocabulary, request):
        LaunchpadRadioWidget.__init__(self, field, vocabulary, request)

        # Bug tracker widget.
        self.bugtracker = Choice(
            vocabulary="WebBugTracker",
            __name__='bugtracker')
        self.bugtracker_widget = CustomWidgetFactory(BugTrackerPickerWidget)
        setUpWidget(
            self, 'bugtracker', self.bugtracker, IInputWidget,
            prefix=self.name, value=field.context.bugtracker,
            context=field.context)
        self.bugtracker_widget.onKeyPress = (
            "selectWidget('%s.2', event);" % self.name)

        # Upstream email address field and widget.
        ## This is to make email address bug trackers appear
        ## separately from the main bug tracker list.
        self.upstream_email_address = StrippedTextLine(
            required=False, constraint=email_validator,
            __name__='upstream_email_address')
        self.upstream_email_address_widget = (
            CustomWidgetFactory(StrippedTextWidget))
        setUpWidget(
            self, 'upstream_email_address', self.upstream_email_address,
            IInputWidget, prefix=self.name, value='',
            context=self.upstream_email_address.context)
        ## Select the corresponding radio option automatically if
        ## the user starts typing.
        if self.upstream_email_address_widget.extra is None:
            self.upstream_email_address_widget.extra = ''
        self.upstream_email_address_widget.extra += (
            ''' onkeypress="selectWidget('%s.3', event);"\n''' % self.name)
コード例 #15
0
 def __init__(self, field_name, widget, *args, **kwargs):
     self.field_name = field_name
     if widget is None:
         self.widget = None
     else:
         self.widget = CustomWidgetFactory(widget, *args, **kwargs)
     addClassAdvisor(self.advise)
コード例 #16
0
 def _setUpBugNotificationLevelField(self):
     """Set up the bug_notification_level field."""
     self.form_fields = self.form_fields.omit('bug_notification_level')
     self.form_fields += formlib.form.Fields(
         self._bug_notification_level_field)
     self.form_fields['bug_notification_level'].custom_widget = (
         CustomWidgetFactory(RadioWidget))
コード例 #17
0
ファイル: bugtask.py プロジェクト: pombreda/UnnaturalCodeFork
 def __init__(self, field, vocabulary, request):
     RadioWidget.__init__(self, field, vocabulary, request)
     self.url_widget = CustomWidgetFactory(URIWidget)
     setUpWidget(
         self, 'url', BugWatchEditForm['url'], IInputWidget,
         context=field.context)
     self.setUpJavascript()
コード例 #18
0
class ProductSeriesReviewView(LaunchpadEditFormView):
    """A view to review and change the series `IProduct` and name."""
    schema = IProductSeries
    field_names = ['product', 'name']
    custom_widget_name = CustomWidgetFactory(TextWidget, displayWidth=20)

    @property
    def label(self):
        """The form label."""
        return 'Administer %s %s series' % (self.context.product.displayname,
                                            self.context.name)

    page_title = label

    @property
    def cancel_url(self):
        """See `LaunchpadFormView`."""
        return canonical_url(self.context)

    @action(_('Change'), name='change')
    def change_action(self, action, data):
        """Update the series."""
        self.updateContextFromData(data)
        self.request.response.addInfoNotification(
            _('This Series has been changed'))
        self.next_url = canonical_url(self.context)
コード例 #19
0
ファイル: product.py プロジェクト: pombreda/UnnaturalCodeFork
 def __init__(self, field, vocabulary, request):
     super(LicenseWidget, self).__init__(field, vocabulary, request)
     # We want to put the license_info widget inside the licences widget's
     # HTML, for better alignment and JavaScript dynamism.  This is
     # accomplished by ghosting the form's license_info widget (see
     # lp/registry/browser/product.py and the GhostWidget implementation
     # below) and creating a custom widget here.  It's a pretty simple text
     # widget so create that now.  The fun part is that it's all within the
     # same form, so posts work correctly.
     self.license_info = Text(__name__='license_info')
     self.license_info_widget = CustomWidgetFactory(DescriptionWidget)
     # The initial value of the license_info widget will be taken from the
     # field's context when available.  This will be the IProduct when
     # we're editing an existing project, but when we're creating a new
     # one, it'll be an IProductSet, which does not have license_info.
     initial_value = getattr(field.context, 'license_info', None)
     setUpWidget(self,
                 'license_info',
                 self.license_info,
                 IInputWidget,
                 prefix='field',
                 value=initial_value,
                 context=field.context)
     self.source_package_release = None
     # These will get filled in by _categorize().  They are the number of
     # selected licences in the category.  The actual count doesn't matter,
     # since if it's greater than 0 it will start opened.  Note that we
     # always want the recommended licences to be opened, so we initialize
     # its value to 1.
     self.recommended_count = 1
     self.more_count = 0
     self.deprecated_count = 0
     self.special_count = 0
コード例 #20
0
class NameBlacklistAddView(NameBlacklistValidationMixin, LaunchpadFormView):
    """View for adding a blacklist expression."""

    schema = INameBlacklist
    field_names = ['regexp', 'admin', 'comment']
    label = "Add a new blacklist expression"
    page_title = label

    custom_widget_regexp = CustomWidgetFactory(TextWidget, displayWidth=60)

    @property
    def cancel_url(self):
        """See `LaunchpadFormView`."""
        return canonical_url(self.context)

    next_url = cancel_url

    @action("Add to blacklist", name='add')
    def add_action(self, action, data):
        name_blacklist_set = getUtility(INameBlacklistSet)
        name_blacklist_set.create(
            regexp=data['regexp'],
            comment=data['comment'],
            admin=data['admin'],
        )
        self.request.response.addInfoNotification(
            'Regular expression "%s" has been added to the name blacklist.' %
            data['regexp'])
コード例 #21
0
    def setUpWidgets(self, context=None):
        """Set up the widgets using the view's form fields and the context.

        If no context is given, the view's context is used."""
        for field in self.form_fields:
            # Honour the custom_widget value if it was already set.  This is
            # important for some existing forms.
            if field.custom_widget is None:
                widget = getattr(self, 'custom_widget_%s' % field.__name__,
                                 None)
                if widget is not None:
                    if IWidgetFactory.providedBy(widget):
                        field.custom_widget = widget
                    else:
                        # Allow views to save some typing in common cases.
                        field.custom_widget = CustomWidgetFactory(widget)
        if context is None:
            context = self.context
        self.widgets = form.setUpWidgets(self.form_fields,
                                         self.prefix,
                                         context,
                                         self.request,
                                         data=self.initial_values,
                                         adapters=self.adapters,
                                         ignore_request=False)
        for field_name, help_link in self.help_links.iteritems():
            self.widgets[field_name].help_link = help_link
コード例 #22
0
    def widget(self, _context, field, **kw):
        attrs = kw
        class_ = attrs.pop("class_", None)
        # Try to do better than accepting the string value by looking through
        # the interfaces and trying to find the field, so that we can use
        # 'fromUnicode()'
        if isinstance(class_, type):
            ifaces = implementedBy(class_)
            for name, value in kw.items():
                for iface in ifaces:
                    if name in iface:
                        attrs[name] = iface[name].fromUnicode(value)
                        break
        if class_ is None:
            # The _default_widget_factory is required to allow the
            # <widget> directive to be given without a "class"
            # attribute.  This can be used to override some of the
            # presentational attributes of the widget implementation.
            class_ = self._default_widget_factory

        # don't wrap a factory into a factory
        if IWidgetFactory.providedBy(class_):
            factory = class_
        else:
            factory = CustomWidgetFactory(class_, **attrs)

        self._widgets[field+'_widget'] = factory
コード例 #23
0
ファイル: test_add.py プロジェクト: xhw807602352/flask_Demo
class V(object):
    name_widget = CustomWidgetFactory(Text)
    first_widget = CustomWidgetFactory(Text)
    last_widget = CustomWidgetFactory(Text)
    email_widget = CustomWidgetFactory(Text)
    address_widget = CustomWidgetFactory(Text)
    getfoo_widget = CustomWidgetFactory(Text)
    extra1_widget = CustomWidgetFactory(Text)
    extra2_widget = CustomWidgetFactory(Text)
コード例 #24
0
class LanguageAdminView(LaunchpadEditFormView):
    """Handle an admin form submission."""

    rootsite = 'translations'

    schema = ILanguage

    custom_widget_countries = CustomWidgetFactory(LabeledMultiCheckBoxWidget,
                                                  orientation='vertical')

    field_names = [
        'code', 'englishname', 'nativename', 'pluralforms', 'pluralexpression',
        'visible', 'direction', 'countries'
    ]

    page_title = "Change details"

    @property
    def label(self):
        """The form label"""
        return "Edit %s in Launchpad" % describe_language(self.context)

    @property
    def cancel_url(self):
        """See LaunchpadFormView."""
        return canonical_url(self.context, rootsite=self.rootsite)

    @property
    def next_url(self):
        return canonical_url(self.context, rootsite=self.rootsite)

    @action("Admin Language", name="admin")
    def admin_action(self, action, data):
        self.updateContextFromData(data)

    def _validateCode(self, new_code):
        """Validate a change in language code."""
        language_set = getUtility(ILanguageSet)
        if language_set.getLanguageByCode(new_code) is not None:
            self.setFieldError('code',
                               'There is already a language with that code.')

    def _validatePluralData(self, pluralforms, pluralexpression):
        """Validate plural expression and number of plural forms."""
        try:
            make_friendly_plural_forms(pluralexpression, pluralforms)
        except BadPluralExpression as e:
            self.setFieldError('pluralexpression', str(e))

    def validate(self, data):
        new_code = data.get('code')
        if new_code != self.context.code:
            self._validateCode(new_code)

        pluralexpression = data.get('pluralexpression')
        pluralforms = data.get('pluralforms')
        if pluralexpression is not None:
            self._validatePluralData(pluralforms, pluralexpression)
コード例 #25
0
    def setUpFields(self):
        """See `LaunchpadFormView`."""
        super(BugSubscriptionSubscribeSelfView, self).setUpFields()
        if self.user is None:
            return

        self.form_fields += formlib.form.Fields(self._subscription_field)
        self._setUpBugNotificationLevelField()
        self.form_fields['subscription'].custom_widget = CustomWidgetFactory(
            RadioWidget)
コード例 #26
0
ファイル: builder.py プロジェクト: pombredanne/launchpad-3
class BuilderSetAddView(LaunchpadFormView):
    """View class for adding new Builders."""

    schema = IBuilder

    label = "Register a new build machine"

    field_names = [
        'name', 'title', 'processors', 'url', 'active', 'virtualized',
        'vm_host', 'vm_reset_protocol', 'owner'
        ]
    custom_widget_owner = HiddenUserWidget
    custom_widget_url = CustomWidgetFactory(TextWidget, displayWidth=30)
    custom_widget_vm_host = CustomWidgetFactory(TextWidget, displayWidth=30)
    custom_widget_processors = LabeledMultiCheckBoxWidget

    @action(_('Register builder'), name='register')
    def register_action(self, action, data):
        """Register a new builder."""
        builder = getUtility(IBuilderSet).new(
            processors=data.get('processors'),
            url=data.get('url'),
            name=data.get('name'),
            title=data.get('title'),
            owner=data.get('owner'),
            active=data.get('active'),
            virtualized=data.get('virtualized'),
            vm_host=data.get('vm_host'),
            vm_reset_protocol=data.get('vm_reset_protocol'),
            )
        notify(ObjectCreatedEvent(builder))
        self.next_url = canonical_url(builder)

    @property
    def page_title(self):
        """Return a relevant page title for this view."""
        return self.label

    @property
    def cancel_url(self):
        """Canceling the add action should go back to the build farm."""
        return canonical_url(self.context)
コード例 #27
0
ファイル: image.py プロジェクト: pombreda/UnnaturalCodeFork
 def __init__(self, context, request, style):
     SimpleInputWidget.__init__(self, context, request)
     self.style = style
     fields = form.Fields(
         Choice(__name__='action',
                source=self._getActionsVocabulary(),
                title=_('Action')), Bytes(__name__='image',
                                          title=_('Image')))
     fields['action'].custom_widget = CustomWidgetFactory(
         LaunchpadRadioWidget)
     fields['image'].custom_widget = CustomWidgetFactory(
         LaunchpadFileWidget, displayWidth=15)
     widgets = form.setUpWidgets(fields,
                                 self.name,
                                 context,
                                 request,
                                 ignore_request=False,
                                 data={'action': 'keep'})
     self.action_widget = widgets['action']
     self.image_widget = widgets['image']
コード例 #28
0
ファイル: product.py プロジェクト: pombreda/UnnaturalCodeFork
    def __init__(self, field, vocabulary, request):
        LaunchpadRadioWidget.__init__(self, field, vocabulary, request)

        # Bug tracker widget.
        self.bugtracker = Choice(vocabulary="WebBugTracker",
                                 __name__='bugtracker')
        self.bugtracker_widget = CustomWidgetFactory(BugTrackerPickerWidget)
        setUpWidget(self,
                    'bugtracker',
                    self.bugtracker,
                    IInputWidget,
                    prefix=self.name,
                    value=field.context.bugtracker,
                    context=field.context)
        self.bugtracker_widget.onKeyPress = ("selectWidget('%s.2', event);" %
                                             self.name)

        # Upstream email address field and widget.
        ## This is to make email address bug trackers appear
        ## separately from the main bug tracker list.
        self.upstream_email_address = StrippedTextLine(
            required=False,
            constraint=email_validator,
            __name__='upstream_email_address')
        self.upstream_email_address_widget = (
            CustomWidgetFactory(StrippedTextWidget))
        setUpWidget(self,
                    'upstream_email_address',
                    self.upstream_email_address,
                    IInputWidget,
                    prefix=self.name,
                    value='',
                    context=self.upstream_email_address.context)
        ## Select the corresponding radio option automatically if
        ## the user starts typing.
        if self.upstream_email_address_widget.extra is None:
            self.upstream_email_address_widget.extra = ''
        self.upstream_email_address_widget.extra += (
            ''' onkeypress="selectWidget('%s.3', event);"\n''' % self.name)
コード例 #29
0
class ProductSeriesEditView(LaunchpadEditFormView):
    """A View to edit the attributes of a series."""
    schema = IProductSeries
    field_names = ['name', 'summary', 'status', 'branch', 'releasefileglob']
    custom_widget_summary = CustomWidgetFactory(TextAreaWidget,
                                                height=7,
                                                width=62)
    custom_widget_releasefileglob = CustomWidgetFactory(StrippedTextWidget,
                                                        displayWidth=40)

    @property
    def label(self):
        """The form label."""
        return 'Edit %s %s series' % (self.context.product.displayname,
                                      self.context.name)

    page_title = label

    def validate(self, data):
        """See `LaunchpadFormView`."""
        branch = data.get('branch')
        if branch is not None:
            message = get_series_branch_error(self.context.product, branch)
            if message:
                self.setFieldError('branch', message)

    @action(_('Change'), name='change')
    def change_action(self, action, data):
        """Update the series."""
        self.updateContextFromData(data)

    @property
    def next_url(self):
        """See `LaunchpadFormView`."""
        return canonical_url(self.context)

    cancel_url = next_url
コード例 #30
0
    def test_customWidgetFactory(self):
        """Verify that the widget can be constructed via the CustomWidgetFactory
        (Issue #293)
        """

        value_type = TextLine(__name__=u'bar')
        self.field = List(__name__=u'foo', value_type=value_type)
        request = TestRequest()

        # set up the custom widget factory and verify that it works
        sw = CustomWidgetFactory(ListSequenceWidget)
        widget = sw(self.field, request)
        assert widget.subwidget is None
        assert widget.context.value_type is value_type

        # set up a variant that specifies the subwidget to use and verify it
        class PollOption(object):
            pass

        ow = CustomWidgetFactory(ObjectWidget, PollOption)
        sw = CustomWidgetFactory(ListSequenceWidget, subwidget=ow)
        widget = sw(self.field, request)
        assert widget.subwidget is ow
        assert widget.context.value_type is value_type
コード例 #31
0
    def setUpSubWidgets(self):
        if self._widgets_set_up:
            return
        fields = [
            TextLine(__name__="track",
                     title=u"Track",
                     required=False,
                     description=_(
                         "Track defines a series for your software. "
                         "If not specified, the default track ('latest') is "
                         "assumed.")),
            List(
                __name__="risks",
                title=u"Risk",
                required=False,
                value_type=Choice(vocabulary="SnapStoreChannel"),
                description=_("Risks denote the stability of your software.")),
            TextLine(
                __name__="branch",
                title=u"Branch",
                required=False,
                description=_(
                    "Branches provide users with an easy way to test bug "
                    "fixes.  They are temporary and created on demand.  If "
                    "not specified, no branch is used.")),
        ]

        self.risks_widget = CustomWidgetFactory(LabeledMultiCheckBoxWidget)
        for field in fields:
            setUpWidget(self,
                        field.__name__,
                        field,
                        IInputWidget,
                        prefix=self.name)
        self.risks_widget.orientation = 'horizontal'
        self._widgets_set_up = True
コード例 #32
0
    def test_subwidget(self):
        """This test verifies that the specified subwidget is not ignored.
        (Issue #293)
        """
        self.field = List(__name__=u'foo',
                          value_type=TextLine(__name__=u'bar'))
        request = TestRequest()

        class PollOption(object):
            pass

        ow = CustomWidgetFactory(ObjectWidget, PollOption)
        widget = SequenceWidget(self.field,
                                self.field.value_type,
                                request,
                                subwidget=ow)
        assert widget.subwidget is ow
コード例 #33
0
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     fields = [
         Choice(
             __name__='product', title=u'Project',
             required=True, vocabulary=self.getProductVocabulary()),
         Choice(
             __name__='distribution', title=u"Distribution",
             required=True, vocabulary=self.getDistributionVocabulary(),
             default=getUtility(ILaunchpadCelebrities).ubuntu),
         Choice(
             __name__='package', title=u"Package",
             required=False, vocabulary='BinaryAndSourcePackageName'),
         ]
     self.distribution_widget = CustomWidgetFactory(
         LaunchpadDropdownWidget)
     for field in fields:
         setUpWidget(
             self, field.__name__, field, IInputWidget, prefix=self.name)
     self._widgets_set_up = True
コード例 #34
0
ファイル: product.py プロジェクト: pombreda/UnnaturalCodeFork
class ProductBugTrackerWidget(LaunchpadRadioWidget):
    """Widget for selecting a product bug tracker."""

    _joinButtonToMessageTemplate = u'%s&nbsp;%s'
    template = ViewPageTemplateFile('templates/product-bug-tracker.pt')

    def __init__(self, field, vocabulary, request):
        LaunchpadRadioWidget.__init__(self, field, vocabulary, request)

        # Bug tracker widget.
        self.bugtracker = Choice(
            vocabulary="WebBugTracker",
            __name__='bugtracker')
        self.bugtracker_widget = CustomWidgetFactory(BugTrackerPickerWidget)
        setUpWidget(
            self, 'bugtracker', self.bugtracker, IInputWidget,
            prefix=self.name, value=field.context.bugtracker,
            context=field.context)
        self.bugtracker_widget.onKeyPress = (
            "selectWidget('%s.2', event);" % self.name)

        # Upstream email address field and widget.
        ## This is to make email address bug trackers appear
        ## separately from the main bug tracker list.
        self.upstream_email_address = StrippedTextLine(
            required=False, constraint=email_validator,
            __name__='upstream_email_address')
        self.upstream_email_address_widget = (
            CustomWidgetFactory(StrippedTextWidget))
        setUpWidget(
            self, 'upstream_email_address', self.upstream_email_address,
            IInputWidget, prefix=self.name, value='',
            context=self.upstream_email_address.context)
        ## Select the corresponding radio option automatically if
        ## the user starts typing.
        if self.upstream_email_address_widget.extra is None:
            self.upstream_email_address_widget.extra = ''
        self.upstream_email_address_widget.extra += (
            ''' onkeypress="selectWidget('%s.3', event);"\n''' % self.name)

    def _renderItem(self, index, text, value, name, cssClass, checked=False):
        # This form has a custom need to render their labels separately,
        # because of a Firefox problem: see comment in renderItems.
        kw = {}
        if checked:
            kw['checked'] = 'checked'
        id = '%s.%s' % (name, index)
        elem = renderElement(u'input',
                             value=value,
                             name=name,
                             id=id,
                             cssClass=cssClass,
                             type='radio',
                             **kw)
        return '%s&nbsp;%s' % (elem, text)

    def _toFieldValue(self, form_value):
        if form_value == "malone":
            return self.context.malone_marker
        elif form_value == "external":
            return self.bugtracker_widget.getInputValue()
        elif form_value == "external-email":
            email_address = self.upstream_email_address_widget.getInputValue()
            if email_address is None or len(email_address) == 0:
                self.upstream_email_address_widget._error = (
                    LaunchpadValidationError(
                        'Please enter an email address.'))
                raise self.upstream_email_address_widget._error
            bugtracker = getUtility(IBugTrackerSet).ensureBugTracker(
                'mailto:%s' % email_address, getUtility(ILaunchBag).user,
                BugTrackerType.EMAILADDRESS)
            return bugtracker
        elif form_value == "project":
            return None

    def getInputValue(self):
        return self._toFieldValue(self._getFormInput())

    def setRenderedValue(self, value):
        self._data = value
        if value is not self.context.malone_marker:
            self.bugtracker_widget.setRenderedValue(value)

    def _renderLabel(self, text, index):
        """Render a label for the option with the specified index."""
        option_id = '%s.%s' % (self.name, index)
        return u'<label for="%s" style="font-weight: normal">%s</label>' % (
            option_id, text)

    def error(self):
        """Concatenate errors from this widget and sub-widgets."""
        errors = [super(ProductBugTrackerWidget, self).error(),
                  self.upstream_email_address_widget.error()]
        return '; '.join(err for err in errors if len(err) > 0)

    def renderItems(self, value):
        """Custom-render the radio-buttons and dependent widgets.

        Some of the radio options have dependent widgets: the bug
        tracker drop-down box, and the email address text field. To
        render these in the correct place we must override the default
        rendering of `LaunchpadRadioWidget`.

        We must also make sure that these dependent widgets are
        populated with the correct information, specifically the bug
        tracker selected, or the email address where bugs must be
        reported.
        """
        field = self.context
        product = field.context
        if value == self._missing:
            value = field.missing_value

        # Bugs tracked in Launchpad Bugs.
        malone_item_arguments = dict(
            index=0, text=self._renderLabel("In Launchpad", 0),
            value="malone", name=self.name, cssClass=self.cssClass)

        # Project or somewhere else.
        project = product.project
        if project is None or project.bugtracker is None:
            project_bugtracker_caption = "Somewhere else"
        else:
            project_bugtracker_caption = structured(
                'In the %s bug tracker (<a href="%s">%s</a>)</label>',
                project.displayname, canonical_url(project.bugtracker),
                project.bugtracker.title).escapedtext
        project_bugtracker_arguments = dict(
            index=1, text=self._renderLabel(project_bugtracker_caption, 1),
            value="project", name=self.name, cssClass=self.cssClass)

        # External bug tracker.
        ## The bugtracker widget can't be within the <label> tag,
        ## since Firefox doesn't cope with it well.
        external_bugtracker_text = "%s %s" % (
            self._renderLabel("In a registered bug tracker:", 2),
            self.bugtracker_widget())
        external_bugtracker_arguments = dict(
            index=2, text=external_bugtracker_text,
            value="external", name=self.name, cssClass=self.cssClass)

        # Upstream email address (special-case bug tracker).
        if (IBugTracker.providedBy(value) and
            value.bugtrackertype == BugTrackerType.EMAILADDRESS):
            self.upstream_email_address_widget.setRenderedValue(
                value.baseurl.lstrip('mailto:'))
        external_bugtracker_email_text = "%s %s" % (
            self._renderLabel("By emailing an upstream bug contact:\n", 3),
            self.upstream_email_address_widget())
        external_bugtracker_email_arguments = dict(
            index=3, text=external_bugtracker_email_text,
            value="external-email", name=self.name, cssClass=self.cssClass)

        # All the choices arguments in order.
        all_arguments = {
            'launchpad': malone_item_arguments,
            'external_bugtracker': external_bugtracker_arguments,
            'external_email': external_bugtracker_email_arguments,
            'unknown': project_bugtracker_arguments,
            }

        # Figure out the selected choice.
        if value == field.malone_marker:
            selected = malone_item_arguments
        elif value != self.context.missing_value:
            # value will be 'external-email' if there was an error on
            # upstream_email_address_widget.
            if (value == 'external-email' or (
                    IBugTracker.providedBy(value) and
                    value.bugtrackertype == BugTrackerType.EMAILADDRESS)):
                selected = external_bugtracker_email_arguments
            else:
                selected = external_bugtracker_arguments
        else:
            selected = project_bugtracker_arguments

        # Render.
        for name, arguments in all_arguments.items():
            if arguments is selected:
                render = self.renderSelectedItem
            else:
                render = self.renderItem
            yield (name, render(**arguments))

    def renderValue(self, value):
        # Render the items with subordinate fields and support markup.
        self.bug_trackers = dict(self.renderItems(value))
        self.product = self.context.context
        # The view must also use GhostWidget for the 'remote_product' field.
        self.remote_product = copy_field(IProduct['remote_product'])
        self.remote_product_widget = CustomWidgetFactory(TextWidget)
        setUpWidget(
            self, 'remote_product', self.remote_product, IInputWidget,
            prefix='field', value=self.product.remote_product,
            context=self.product)
        # The view must also use GhostWidget for the 'enable_bug_expiration'
        # field.
        self.enable_bug_expiration = copy_field(
            IProduct['enable_bug_expiration'])
        self.enable_bug_expiration_widget = CustomWidgetFactory(
            CheckBoxWidget)
        setUpWidget(
            self, 'enable_bug_expiration', self.enable_bug_expiration,
            IInputWidget, prefix='field',
            value=self.product.enable_bug_expiration, context=self.product)
        return self.template()
コード例 #35
0
ファイル: bugtask.py プロジェクト: pombreda/UnnaturalCodeFork
class BugTaskBugWatchWidget(RadioWidget):
    """A widget for linking a bug watch to a bug task."""

    def __init__(self, field, vocabulary, request):
        RadioWidget.__init__(self, field, vocabulary, request)
        self.url_widget = CustomWidgetFactory(URIWidget)
        setUpWidget(
            self, 'url', BugWatchEditForm['url'], IInputWidget,
            context=field.context)
        self.setUpJavascript()

    def setUpJavascript(self):
        """Set up JS to select the "new bugwatch" option automatically."""
        select_js = "selectWidget('%s.%s', event)" % (
            self.name, self._new_bugwatch_value)
        self.url_widget.extra = 'onKeyPress="%s"' % select_js

    def setPrefix(self, prefix):
        RadioWidget.setPrefix(self, prefix)
        self.url_widget.setPrefix(prefix)
        self.setUpJavascript()

    _messageNoValue = "None, the status of the bug is updated manually."
    _new_bugwatch_value = 'NEW'

    def _toFieldValue(self, form_value):
        """Convert the textual token to a field value.

        If the form value is _new_bugwatch_value, create a new bug
        watch, otherwise look up an existing one.
        """
        if form_value == self._new_bugwatch_value:
            try:
                url = self.url_widget.getInputValue()
                bugtracker, remote_bug = getUtility(
                    IBugWatchSet).extractBugTrackerAndBug(url)
                bugtask = self.context.context
                return bugtask.bug.addWatch(
                    bugtracker, remote_bug, getUtility(ILaunchBag).user)
            except WidgetInputError as error:
                # Prefix the error with the widget name, since the error
                # will be display at the top of the page, and not right
                # next to the widget.
                raise WidgetInputError(
                    self.context.__name__, self.label,
                    'Remote Bug: %s' % error.doc())
            except (NoBugTrackerFound, UnrecognizedBugTrackerURL) as error:
                raise WidgetInputError(
                    self.context.__name__, self.label,
                    'Invalid bug tracker URL.')
        else:
            return RadioWidget._toFieldValue(self, form_value)

    def _getFormValue(self):
        """Return the form value.

        We have to override this method in this class since the original
        one uses getInputValue(), which it shouldn't do.
        """
        if not self._renderedValueSet():
            return self.request.form_ng.getOne(self.name, self._missing)
        else:
            return self._toFormValue(self._data)

    def _div(self, cssClass, contents, **kw):
        """Don't render a div tag."""
        return contents

    def _joinButtonToMessage(self, option_tag, label, input_id):
        """Join the input tag with the label."""
        row_template = get_widget_template('bugtask-bugwatch-widget.txt')
        return row_template % {
            'input_tag': option_tag,
            'input_id': input_id,
            'input_label': label}

    #XXX: Bjorn Tillenius 2006-04-26:
    #     This method is mostly copied from RadioWidget.renderItems() and
    #     modified to actually work. RadioWidget.renderItems() should be
    #     fixed upstream so that we can override it and only do the last
    #     part locally, the part after "# Add an option for creating...".
    #     http://www.zope.org/Collectors/Zope3-dev/592
    def renderItems(self, value):
        """Render the items with with the correct radio button selected."""
        # XXX: Bjorn Tillenius 2006-04-26
        #      This works around the fact that we incorrectly gets the form
        #      value instead of a valid field value.
        if value == self._missing:
            value = self.context.missing_value
        elif (isinstance(value, basestring) and
              value != self._new_bugwatch_value):
            value = self._toFieldValue(value)
        # check if we want to select first item, the previously selected item
        # or the "nothing selected" item.
        nothing_selected = None
        if (value == self.context.missing_value
            and getattr(self, 'firstItem', False)
            and len(self.vocabulary) > 0
            and self.context.required):
            # Grab the first item from the iterator:
            values = [iter(self.vocabulary).next().value]
        elif value != self.context.missing_value:
            values = [value]
        else:
            # the "nothing selected" option will be checked
            nothing_selected = 'checked'
            values = []

        items = self.renderItemsWithValues(values)
        if not self.context.required:
            kwargs = {
                'index': None,
                'text': self.translate(self._messageNoValue),
                'value': '',
                'name': self.name,
                'cssClass': self.cssClass}
            if nothing_selected:
                option = self.renderSelectedItem(**kwargs)
            else:
                option = self.renderItem(**kwargs)
            items.insert(0, option)

        # Add an option for creating a new bug watch.
        option_text = (
            '<div>URL: %s</div>' % self.url_widget())
        if value == self._new_bugwatch_value:
            option = self.renderSelectedItem(
                self._new_bugwatch_value, option_text,
                self._new_bugwatch_value, self.name, self.cssClass)
        else:
            option = self.renderItem(
                self._new_bugwatch_value, option_text,
                self._new_bugwatch_value, self.name, self.cssClass)
        items.append(option)

        return items

    def renderItem(self, index, text, value, name, cssClass):
        """Render an item.

        We override this method to use the _joinButtonToMessage method
        instead of the _joinButtonToMessageTemplate which doesn't have
        access to the id.
        """
        id = '%s.%s' % (name, index)
        elem = renderElement(u'input',
                             value=value,
                             name=name,
                             id=id,
                             cssClass=cssClass,
                             type='radio')
        return self._joinButtonToMessage(elem, text, input_id=id)

    def renderSelectedItem(self, index, text, value, name, cssClass):
        """Render a selected item.

        We override this method to use the _joinButtonToMessage method
        instead of the _joinButtonToMessageTemplate which doesn't have
        access to the id.
        """
        id = '%s.%s' % (name, index)
        elem = renderElement(u'input',
                             value=value,
                             name=name,
                             id=id,
                             cssClass=cssClass,
                             checked="checked",
                             type='radio')
        return self._joinButtonToMessage(elem, text, input_id=id)

    def renderValue(self, value):
        """Render the widget with the selected value.

        The original renderValue separates the items with either
        '&nbsp;' or '<br />' which isn't suitable for us.
        """
        rendered_items = self.renderItems(value)
        return renderElement(
            'table', cssClass=self.cssClass,
            contents='\n'.join(rendered_items))
コード例 #36
0
class LaunchpadTargetWidget(BrowserWidget, InputWidget):
    """Widget for selecting a product, distribution or package target."""

    implements(IAlwaysSubmittedWidget, IMultiLineWidgetLayout, IInputWidget)

    template = ViewPageTemplateFile('templates/launchpad-target.pt')
    default_option = "package"
    _widgets_set_up = False

    def getDistributionVocabulary(self):
        return 'Distribution'
    
    def getProductVocabulary(self):
        return 'Product'

    def setUpSubWidgets(self):
        if self._widgets_set_up:
            return
        fields = [
            Choice(
                __name__='product', title=u'Project',
                required=True, vocabulary=self.getProductVocabulary()),
            Choice(
                __name__='distribution', title=u"Distribution",
                required=True, vocabulary=self.getDistributionVocabulary(),
                default=getUtility(ILaunchpadCelebrities).ubuntu),
            Choice(
                __name__='package', title=u"Package",
                required=False, vocabulary='BinaryAndSourcePackageName'),
            ]
        self.distribution_widget = CustomWidgetFactory(
            LaunchpadDropdownWidget)
        for field in fields:
            setUpWidget(
                self, field.__name__, field, IInputWidget, prefix=self.name)
        self._widgets_set_up = True

    def setUpOptions(self):
        """Set up options to be rendered."""
        self.options = {}
        for option in ['package', 'product']:
            attributes = dict(
                type='radio', name=self.name, value=option,
                id='%s.option.%s' % (self.name, option))
            if self.request.form_ng.getOne(
                     self.name, self.default_option) == option:
                attributes['checked'] = 'checked'
            self.options[option] = renderElement('input', **attributes)
        self.package_widget.onKeyPress = (
            "selectWidget('%s.option.package', event)" % self.name)
        self.product_widget.onKeyPress = (
            "selectWidget('%s.option.product', event)" % self.name)

    def hasInput(self):
        return self.name in self.request.form

    def hasValidInput(self):
        """See zope.formlib.interfaces.IInputWidget."""
        try:
            self.getInputValue()
            return True
        except (InputErrors, UnexpectedFormData):
            return False

    def getInputValue(self):
        """See zope.formlib.interfaces.IInputWidget."""
        self.setUpSubWidgets()
        form_value = self.request.form_ng.getOne(self.name)
        if form_value == 'product':
            try:
                return self.product_widget.getInputValue()
            except MissingInputError:
                self._error = WidgetInputError(
                    self.name, self.label,
                    LaunchpadValidationError('Please enter a project name'))
                raise self._error
            except ConversionError:
                entered_name = self.request.form_ng.getOne(
                    "%s.product" % self.name)
                self._error = WidgetInputError(
                    self.name, self.label,
                    LaunchpadValidationError(
                        "There is no project named '%s' registered in"
                        " Launchpad" % entered_name))
                raise self._error
        elif form_value == 'package':
            try:
                distribution = self.distribution_widget.getInputValue()
            except ConversionError:
                entered_name = self.request.form_ng.getOne(
                    "%s.distribution" % self.name)
                self._error = WidgetInputError(
                    self.name, self.label,
                    LaunchpadValidationError(
                        "There is no distribution named '%s' registered in"
                        " Launchpad" % entered_name))
                raise self._error
            if self.package_widget.hasInput():
                try:
                    package_name = self.package_widget.getInputValue()
                    if package_name is None:
                        return distribution
                    if IDistributionSourcePackage.providedBy(package_name):
                        dsp = package_name
                    else:
                        source_name = (
                            distribution.guessPublishedSourcePackageName(
                                package_name.name))
                        dsp = distribution.getSourcePackage(source_name)
                except (ConversionError, NotFoundError):
                    entered_name = self.request.form_ng.getOne(
                        '%s.package' % self.name)
                    self._error = WidgetInputError(
                        self.name, self.label,
                        LaunchpadValidationError(
                            "There is no package named '%s' published in %s."
                            % (entered_name, distribution.displayname)))
                    raise self._error
                return dsp
            else:
                return distribution
        else:
            raise UnexpectedFormData("No valid option was selected.")

    def setRenderedValue(self, value):
        """See IWidget."""
        self.setUpSubWidgets()
        if IProduct.providedBy(value):
            self.default_option = 'product'
            self.product_widget.setRenderedValue(value)
        elif IDistribution.providedBy(value):
            self.default_option = 'package'
            self.distribution_widget.setRenderedValue(value)
        elif IDistributionSourcePackage.providedBy(value):
            self.default_option = 'package'
            self.distribution_widget.setRenderedValue(value.distribution)
            self.package_widget.setRenderedValue(value.sourcepackagename)
        else:
            raise AssertionError('Not a valid value: %r' % value)

    def __call__(self):
        """See zope.formlib.interfaces.IBrowserWidget."""
        self.setUpSubWidgets()
        self.setUpOptions()
        return self.template()