def render(self):
        """Render a page supporting XRDS discovery."""
        # While Zope doesn't care about extra slashes, such
        # differences result in different identity URLs.  To avoid
        # confusion, we redirect to our canonical URL if we aren't
        # already there.
        current_url = self._getURL()
        expected_url = canonical_url(self.context)
        if current_url != expected_url:
            self.request.response.redirect(expected_url)
            return ''

        if self.enable_xrds_discovery:
            # Tell the user agent that we do different things depending on
            # the value of the "Accept" header.
            self.request.response.setHeader('Vary', 'Accept')

            accept_content = self.request.get('HTTP_ACCEPT', '')
            acceptable = getAcceptable(accept_content,
                                       ['text/html', YADIS_CONTENT_TYPE])
            # Return the XRDS document if it is preferred to text/html.
            for mtype in acceptable:
                if mtype == 'text/html':
                    break
                elif mtype == YADIS_CONTENT_TYPE:
                    return self.xrds()
                else:
                    raise AssertionError(
                        'Unexpected acceptable content type: %s' % mtype)

            # Add a header pointing to the location of the XRDS document
            # and chain to the default render() method.
            self.request.response.setHeader(
                YADIS_HEADER_NAME, '%s/+xrds' % canonical_url(self.context))
        return super(XRDSContentNegotiationMixin, self).render()
 def _getTemplateParams(self, email, recipient):
     """See `BaseMailer`"""
     params = super(
         SourcePackageRecipeBuildMailer, self)._getTemplateParams(
             email, recipient)
     params.update({
         'status': self.build.status.title,
         'build_id': self.build.id,
         'distroseries': self.build.distroseries.name,
         'recipe': self.build.recipe.name,
         'recipe_owner': self.build.recipe.owner.name,
         'archive': self.build.archive.name,
         'archive_owner': self.build.archive.owner.name,
         'log_url': '',
         'component': self.build.current_component.name,
         'duration': '',
         'builder_url': '',
         'build_url': canonical_url(self.build),
         'upload_log_url': '',
     })
     if self.build.builder is not None:
         params['builder_url'] = canonical_url(self.build.builder)
     if self.build.duration is not None:
         duration_formatter = DurationFormatterAPI(self.build.duration)
         params['duration'] = duration_formatter.approximateduration()
     if self.build.log is not None:
         params['log_url'] = self.build.log.getURL()
     if self.build.upload_log is not None:
         params['upload_log_url'] = self.build.upload_log_url
     return params
 def test_binary_query_counts(self):
     query_baseline = 40
     # Assess the baseline.
     collector = QueryCollector()
     collector.register()
     self.addCleanup(collector.unregister)
     ppa = self.factory.makeArchive()
     viewer = self.factory.makePerson()
     browser = self.getUserBrowser(user=viewer)
     with person_logged_in(viewer):
         # The baseline has one package, because otherwise the
         # short-circuit prevents the packages iteration happening at
         # all and we're not actually measuring scaling
         # appropriately.
         pkg = self.factory.makeBinaryPackagePublishingHistory(
             archive=ppa)
         url = canonical_url(ppa) + "/+packages"
     browser.open(url)
     self.assertThat(collector, HasQueryCount(LessThan(query_baseline)))
     expected_count = collector.count
     # Use all new objects - avoids caching issues invalidating the
     # gathered metrics.
     login(ADMIN_EMAIL)
     ppa = self.factory.makeArchive()
     viewer = self.factory.makePerson()
     browser = self.getUserBrowser(user=viewer)
     with person_logged_in(viewer):
         for i in range(3):
             pkg = self.factory.makeBinaryPackagePublishingHistory(
                 archive=ppa, distroarchseries=pkg.distroarchseries)
         url = canonical_url(ppa) + "/+packages"
     browser.open(url)
     self.assertThat(collector, HasQueryCount(Equals(expected_count)))
    def processActiveMember(self):
        # This method checks the current status to ensure that we don't
        # crash because of users reposting a form.
        form = self.request.form
        context = self.context
        if form.get('deactivate'):
            if self.context.status == TeamMembershipStatus.DEACTIVATED:
                # This branch and redirect is necessary because
                # TeamMembership.setStatus() does not allow us to set an
                # already-deactivated account to deactivated, causing
                # double form posts to crash there. We instead manually
                # ensure that the double-post is harmless.
                self.request.response.redirect(
                    '%s/+members' % canonical_url(context.team))
                return
            new_status = TeamMembershipStatus.DEACTIVATED
        elif form.get('change'):
            if (form.get('admin') == "no" and
                context.status == TeamMembershipStatus.ADMIN):
                new_status = TeamMembershipStatus.APPROVED
            elif (form.get('admin') == "yes" and
                  context.status == TeamMembershipStatus.APPROVED):
                new_status = TeamMembershipStatus.ADMIN
            else:
                # No status change will happen
                new_status = self.context.status
        else:
            raise UnexpectedFormData(
                "None of the expected actions were found.")

        if self._setMembershipData(new_status):
            self.request.response.redirect(
                '%s/+members' % canonical_url(context.team))
Example #5
0
    def duplicates(self):
        """Return a list of dicts of duplicates.

        Each dict contains the title that should be shown and the bug
        object itself. This allows us to protect private bugs using a
        title like 'Private Bug'.
        """
        duplicate_bugs = list(self.context.duplicates)
        current_task = self.current_bugtask
        dupes_in_current_context = dict(
            (bugtask.bug, bugtask)
            for bugtask in current_task.target.searchTasks(
                BugTaskSearchParams(self.user, bug=any(*duplicate_bugs))))
        dupes = []
        for bug in duplicate_bugs:
            dupe = {}
            try:
                dupe['title'] = bug.title
            except Unauthorized:
                dupe['title'] = 'Private Bug'
            dupe['id'] = bug.id
            # If the dupe has the same context as the one we're in, link
            # to that bug task directly.
            if bug in dupes_in_current_context:
                dupe['url'] = canonical_url(dupes_in_current_context[bug])
            else:
                dupe['url'] = canonical_url(bug)
            dupes.append(dupe)

        return dupes
Example #6
0
 def next_url(self):
     if self.context.active:
         return canonical_url(self.context)
     else:
         # If the project is inactive, we can't traverse to it
         # anymore.
         return canonical_url(getUtility(IProjectGroupSet))
Example #7
0
 def test_canonicalUrl(self):
     # The canonical_url of the merge diff is '+preview' after the
     # canonical_url of the merge proposal itself.
     mp = self._createProposalWithPreviewDiff()
     self.assertEqual(
         canonical_url(mp) + '/+preview-diff',
         canonical_url(mp.preview_diff))
    def test_forCreation_with_review_request_and_private_bug(self):
        """Correctly format list of reviewers and bug info.

        Private bugs should not be listed in the email unless authorised.
        """
        reviewer = self.factory.makePerson(name='review-person')
        bmp, subscriber = self.makeProposalWithSubscriber(reviewer=reviewer)

        # Create and subscribe the owner of the private bug
        private_bug_owner = self.factory.makePerson(email="*****@*****.**")
        bmp.source_branch.subscribe(private_bug_owner,
            BranchSubscriptionNotificationLevel.NOEMAIL, None,
            CodeReviewNotificationLevel.FULL, private_bug_owner)

        # Create and link the bugs to the branch
        bug = self.factory.makeBug(title='I am a bug')
        bugtask = bug.default_bugtask
        bmp.source_branch.linkBug(bug, bmp.registrant)
        private_bug = self.factory.makeBug(
            title='I am a private bug', owner=private_bug_owner,
            information_type=InformationType.USERDATA)
        private_bugtask = private_bug.default_bugtask
        with person_logged_in(private_bug_owner):
            bmp.source_branch.linkBug(private_bug, bmp.registrant)

        # Set up the mailer
        bmp.nominateReviewer(reviewer, bmp.registrant, None)
        mailer = BMPMailer.forCreation(bmp, bmp.registrant)

        # A non authorised email recipient doesn't see the private bug.
        ctrl = mailer.generateEmail('*****@*****.**', subscriber)
        expected = (
            '\nRequested reviews:'
            '\n  Review-person (review-person)'
            '\nRelated bugs:'
            '\n  %s'
            '\n  %s\n'
            '\nFor more details, see:\n'
            '%s'
            '\n--' % (bugtask.title, canonical_url(bugtask),
                      canonical_url(bmp)))
        self.assertIn(expected, ctrl.body)

        # An authorised email recipient does see the private bug.
        ctrl = mailer.generateEmail('*****@*****.**', private_bug_owner)
        expected = (
            '\nRequested reviews:'
            '\n  Review-person (review-person)'
            '\nRelated bugs:'
            '\n  %s'
            '\n  %s'
            '\n  %s'
            '\n  %s\n'
            '\nFor more details, see:\n'
            '%s'
            '\n--' % (bugtask.title, canonical_url(bugtask),
                      private_bugtask.title, canonical_url(private_bugtask),
                      canonical_url(bmp)))
        self.assertIn(expected, ctrl.body)
 def test_canonical_url(self):
     # The canonical URL of a GPG key is ???
     person = self.factory.makePerson()
     gpgkey = self.factory.makeGPGKey(person)
     self.assertEqual(
         '%s/+gpg-keys/%s' % (
             canonical_url(person, rootsite='api'), gpgkey.keyid),
         canonical_url(gpgkey))
 def test_token_for_different_target_dep_is_url(self):
     # The 'token' part of the term for a dependency candidate that has a
     # different target is the canonical url of the candidate.
     spec = self.factory.makeSpecification()
     candidate = self.factory.makeSpecification()
     vocab = self.getVocabularyForSpec(spec)
     term = vocab.getTermByToken(canonical_url(candidate))
     self.assertEqual(term.token, canonical_url(candidate))
 def test_more_private_bugs_query_count_is_constant(self):
     # This test tests that as we add more private bugs to a milestone
     # index page, the number of queries issued by the page does not
     # change. It also sets a cap on the queries for this page: if the
     # baseline were to increase, the test would fail. As the baseline
     # is very large already, if the test fails due to such a change,
     # please cut some more of the existing fat out of it rather than
     # increasing the cap.
     page_query_limit = 37
     product = self.factory.makeProduct()
     product_owner = product.owner
     login_person(product.owner)
     milestone = self.factory.makeMilestone(productseries=product.development_focus)
     bug1 = self.factory.makeBug(target=product, information_type=InformationType.USERDATA, owner=product.owner)
     bug1.bugtasks[0].transitionToMilestone(milestone, product.owner)
     # We look at the page as someone who is a member of a team and the
     # team is subscribed to the bugs, so that we don't get trivial
     # shortcuts avoiding queries : test the worst case.
     subscribed_team = self.factory.makeTeam(membership_policy=TeamMembershipPolicy.MODERATED)
     viewer = self.factory.makePerson()
     with person_logged_in(subscribed_team.teamowner):
         subscribed_team.addMember(viewer, subscribed_team.teamowner)
     bug1.subscribe(subscribed_team, product.owner)
     bug1_url = canonical_url(bug1)
     milestone_url = canonical_url(milestone)
     browser = self.getUserBrowser(user=viewer)
     # Seed the cookie cache and any other cross-request state we may gain
     # in future.  See lp.services.webapp.serssion: _get_secret.
     browser.open(milestone_url)
     collector = QueryCollector()
     collector.register()
     self.addCleanup(collector.unregister)
     browser.open(milestone_url)
     # Check that the test found the bug
     self.assertTrue(bug1_url in browser.contents)
     self.assertThat(collector, HasQueryCount(LessThan(page_query_limit)))
     with_1_private_bug = collector.count
     with_1_queries = ["%s: %s" % (pos, stmt[3]) for (pos, stmt) in enumerate(collector.queries)]
     login_person(product_owner)
     bug2 = self.factory.makeBug(target=product, information_type=InformationType.USERDATA, owner=product.owner)
     bug2.bugtasks[0].transitionToMilestone(milestone, product.owner)
     bug2.subscribe(subscribed_team, product.owner)
     bug2_url = canonical_url(bug2)
     bug3 = self.factory.makeBug(target=product, information_type=InformationType.USERDATA, owner=product.owner)
     bug3.bugtasks[0].transitionToMilestone(milestone, product.owner)
     bug3.subscribe(subscribed_team, product.owner)
     logout()
     browser.open(milestone_url)
     self.assertTrue(bug2_url in browser.contents)
     self.assertThat(collector, HasQueryCount(LessThan(page_query_limit)))
     with_3_private_bugs = collector.count
     with_3_queries = ["%s: %s" % (pos, stmt[3]) for (pos, stmt) in enumerate(collector.queries)]
     self.assertEqual(
         with_1_private_bug,
         with_3_private_bugs,
         "different query count: \n%s\n******************\n%s\n"
         % ("\n".join(with_1_queries), "\n".join(with_3_queries)),
     )
def assemble_body(blamer, spr, bprs, archive, distroseries, summary, changes,
                  action, previous_version=None):
    """Assemble the e-mail notification body."""
    if changes is None:
        changes = {}
    info = fetch_information(
        spr, bprs, changes, previous_version=previous_version)
    information = {
        'STATUS': ACTION_DESCRIPTIONS[action],
        'SUMMARY': summary,
        'DATE': 'Date: %s' % info['date'],
        'CHANGESFILE': info['changelog'],
        'DISTRO': distroseries.distribution.title,
        'ANNOUNCE': 'No announcement sent',
        'CHANGEDBY': '',
        'MAINTAINER': '',
        'ORIGIN': '',
        'SIGNER': '',
        'SPR_URL': '',
        'ARCHIVE_URL': '\n%s' % canonical_url(archive),
        'USERS_ADDRESS': config.launchpad.users_address,
        }
    if spr:
        # Yay, circular imports.
        from lp.soyuz.model.distroseriessourcepackagerelease import (
            DistroSeriesSourcePackageRelease,
            )
        dsspr = DistroSeriesSourcePackageRelease(distroseries, spr)
        information['SPR_URL'] = canonical_url(dsspr)
    changedby_displayname = info['changedby_displayname']
    if changedby_displayname:
        information['CHANGEDBY'] = '\nChanged-By: %s' % changedby_displayname
    origin = changes.get('Origin')
    if origin:
        information['ORIGIN'] = '\nOrigin: %s' % origin
    if action == 'unapproved':
        information['SUMMARY'] += (
            "\nThis upload awaits approval by a distro manager\n")
    if distroseries.changeslist:
        information['ANNOUNCE'] = "Announcing to %s" % (
            distroseries.changeslist)

    # Some syncs (e.g. from Debian) will involve packages whose
    # changed-by person was auto-created in LP and hence does not have a
    # preferred email address set.  We'll get a None here.
    changedby_person = email_to_person(info['changedby'])

    if blamer is not None and blamer != changedby_person:
        signer_signature = person_to_email(blamer)
        if signer_signature != info['changedby']:
            information['SIGNER'] = '\nSigned-By: %s' % signer_signature
    # Add maintainer if present and different from changed-by.
    maintainer = info['maintainer']
    changedby = info['changedby']
    if maintainer and maintainer != changedby:
        information['MAINTAINER'] = '\nMaintainer: %s' % maintainer
    return get_template(archive, action) % information
Example #13
0
 def test_canonical_url(self):
     # The canonical URL of a GPG key is ssh-keys
     person = self.factory.makePerson()
     with person_logged_in(person):
         sshkey = self.factory.makeSSHKey(person)
         self.assertEqual(
             '%s/+ssh-keys/%s' % (
                 canonical_url(person, rootsite='api'), sshkey.id),
             canonical_url(sshkey))
 def next_url(self):
     url = canonical_url(self.branch)
     # If the subscriber can no longer see the branch, redirect them away.
     service = getUtility(IService, 'sharing')
     ignored, branches, ignored = service.getVisibleArtifacts(
         self.person, branches=[self.branch], ignore_permissions=True)
     if not branches:
         url = canonical_url(self.branch.target)
     return url
 def test_excessive_comments_redirect_to_download(self):
     """View for excessive comments redirects to download page."""
     comment = self.factory.makeCodeReviewComment(body='x ' * 5001)
     view_url = canonical_url(comment)
     download_url = canonical_url(comment, view_name='+download')
     browser = self.getUserBrowser(view_url)
     self.assertNotEqual(view_url, browser.url)
     self.assertEqual(download_url, browser.url)
     self.assertEqual('x ' * 5001, browser.contents)
def get_series_branch_error(product, branch):
    """Check if the given branch is suitable for the given product.

    Returns an HTML error message on error, and None otherwise.
    """
    if branch.product != product:
        return structured(
            '<a href="%s">%s</a> is not a branch of <a href="%s">%s</a>.',
            canonical_url(branch), branch.unique_name, canonical_url(product),
            product.displayname)
Example #17
0
 def _setBranchExists(self, existing_branch):
     """Set a field error indicating that the branch already exists."""
     self.setFieldError(
        'branch_name',
         structured("""
         There is already an existing import for
         <a href="%(product_url)s">%(product_name)s</a>
         with the name of
         <a href="%(branch_url)s">%(branch_name)s</a>.""",
                    product_url=canonical_url(existing_branch.target),
                    product_name=existing_branch.target.name,
                    branch_url=canonical_url(existing_branch),
                    branch_name=existing_branch.name))
Example #18
0
    def sendProfileCreatedEmail(self, profile, comment):
        """See ILoginToken."""
        template = get_email_template('profile-created.txt', app=MAIL_APP)
        replacements = {'token_url': canonical_url(self),
                        'requester': self.requester.displayname,
                        'comment': comment,
                        'profile_url': canonical_url(profile)}
        message = template % replacements

        headers = {'Reply-To': self.requester.preferredemail.email}
        from_name = "Launchpad"
        subject = "Launchpad profile"
        self._send_email(from_name, subject, message, headers=headers)
Example #19
0
    def process_form(self):
        """Largely copied from webapp/generalform.py, without the
        schema processing bits because we are not rendering the form in the
        usual way. Instead, we are creating our own form in the page
        template and interpreting it here.
        """
        form = self.request.form

        if 'SUBMIT_CANCEL' in form:
            self.status_message = 'Cancelled'
            self.request.response.redirect(
                canonical_url(self.context) + '/+specs')
            return

        if 'SUBMIT_ACCEPT' not in form and 'SUBMIT_DECLINE' not in form:
            self.status_message = ''
            return

        if self.request.method == 'POST':
            if 'speclink' not in form:
                self.status_message = (
                    'Please select specifications to accept or decline.')
                return
            # determine if we are accepting or declining
            if 'SUBMIT_ACCEPT' in form:
                assert 'SUBMIT_DECLINE' not in form
                action = 'Accepted'
            else:
                assert 'SUBMIT_DECLINE' in form
                action = 'Declined'

        selected_specs = form['speclink']
        if isinstance(selected_specs, unicode):
            # only a single item was selected, but we want to deal with a
            # list for the general case, so convert it to a list
            selected_specs = [selected_specs]

        if action == 'Accepted':
            action_fn = self.context.acceptSpecificationLinks
        else:
            action_fn = self.context.declineSpecificationLinks
        leftover = action_fn(selected_specs, self.user)

        # Status message like: "Accepted 27 specification(s)."
        self.status_message = '%s %d specification(s).' % (
            action, len(selected_specs))

        if leftover == 0:
            # they are all done, so redirect back to the spec listing page
            self.request.response.redirect(
                canonical_url(self.context) + '/+specs')
    def delete_action(self, action, data):
        # Although users will never be able to see/submit this form for a
        # mirror which has been probed already, they may have a stale page
        # and so we do this check here.
        if self.context.last_probe_record is not None:
            self.request.response.addInfoNotification(
                "This mirror has been probed and thus can't be deleted.")
            self.next_url = canonical_url(self.context)
            return

        self.next_url = canonical_url(self.context.distribution,
            view_name='+pendingreviewmirrors')
        self.request.response.addInfoNotification(
            "Mirror %s has been deleted." % self.context.title)
        self.context.destroySelf()
 def test_build_rescoring_view(self):
     # `BuildRescoringView` is used for setting new values to the
     # corresponding `BuildQueue.lastscore` record for a `Build`.
     # It redirects users to the `Build` page when the build cannot be
     # rescored.
     build = self.factory.makeBinaryPackageBuild(
         status=BuildStatus.FAILEDTOBUILD)
     self.assertFalse(build.can_be_rescored)
     view = create_initialized_view(build, name='+rescore')
     self.assertEquals(view.request.response.getStatus(), 302)
     self.assertEquals(view.request.response.getHeader('Location'),
         canonical_url(build))
     pending_build = self.factory.makeBinaryPackageBuild()
     view = create_initialized_view(pending_build, name='+rescore')
     self.assertEquals(view.cancel_url, canonical_url(pending_build))
 def branches(self):
     """Return a link to view the branches related to this series."""
     # Override to go to the branches for the product.
     text = 'Code'
     summary = 'View related branches of code'
     link = canonical_url(self.context.product, rootsite='code')
     return Link(link, text, summary=summary)
Example #23
0
 def __init__(self, context, request):
     redirected_context = context.default_bugtask
     viewname = getDefaultViewName(redirected_context, request)
     cache_view = getMultiAdapter(
         (redirected_context, request), name=viewname)
     super(BugWithoutContextView, self).__init__(
         canonical_url(redirected_context), request, cache_view=cache_view)
 def test_configure_codehosting_shown(self):
     # If the user has driver permissions, they are shown the configure
     # codehosting link.
     product = self.factory.makeProduct()
     browser = self.getUserBrowser(
         canonical_url(product, rootsite='code'), user=product.owner)
     self.assertTrue('Configure code hosting' in browser.contents)
Example #25
0
 def rescheduleAction(self, action, data):
     """Reschedule all the watches for the bugtracker."""
     self.context.resetWatches()
     self.request.response.addInfoNotification(
         "All bug watches on %s have been rescheduled." %
         self.context.title)
     self.next_url = canonical_url(self.context)
 def test_configure_codehosting_hidden(self):
     # If the user does not have driver permissions, they are not shown
     # the configure codehosting link.
     product = self.factory.makeProduct()
     browser = self.getUserBrowser(
         canonical_url(product, rootsite='code'))
     self.assertFalse('Configure code hosting' in browser.contents)
Example #27
0
def require_fresh_login(request, context, view_name):
    """Redirect request to login if the request is not recently logged in."""
    if not isFreshLogin(request):
        reauth_query = '+login?reauth=1'
        base_url = canonical_url(context, view_name=view_name)
        login_url = '%s/%s' % (base_url, reauth_query)
        request.response.redirect(login_url)
 def test_getTermByToken_by_url_disallows_context(self):
     # getTermByToken with the URL of the vocab's context raises
     # LookupError.
     spec = self.factory.makeSpecification()
     vocab = self.getVocabularyForSpec(spec)
     self.assertRaises(
         LookupError, vocab.getTermByToken, canonical_url(spec))
 def configure_bugtracker(self):
     text = 'Configure bug tracker'
     summary = 'Specify where bugs are tracked for this project'
     return Link(
         canonical_url(
             self.context.product, view_name='+configure-bugtracker'),
         text, summary, icon='edit')
    def direct_subscriber_data(self, question):
        """Get the direct subscriber data.

        This method is isolated from the subscriber_data_js so that query
        count testing can be done accurately and robustly.
        """
        data = []
        details = list(question.getDirectSubscribersWithDetails())
        for person, subscription in details:
            can_edit = subscription.canBeUnsubscribedByUser(self.user)
            if person.private and not can_edit:
                # Skip private teams user is not a member of.
                continue

            subscriber = {
                'name': person.name,
                'display_name': person.displayname,
                'web_link': canonical_url(person, rootsite='mainsite'),
                'self_link': absoluteURL(person, self.api_request),
                'is_team': person.is_team,
                'can_edit': can_edit
                }
            record = {
                'subscriber': subscriber,
                'subscription_level': 'Direct',
                }
            data.append(record)
        return data
Example #31
0
 def traverse(self, name):
     # Raise a 404 on an invalid distribution name
     distribution = self.context.getByName(name)
     if distribution is None:
         raise NotFoundError(name)
     return self.redirectSubTree(canonical_url(distribution))
Example #32
0
 def __init__(self, context, request):
     LaunchpadFormView.__init__(self, context, request)
     self.next_url = self.cancel_url = (
         canonical_url(ICanonicalUrlData(context).inside))
Example #33
0
 def nextUrlForInconsistentPatchFlags(self, attachment):
     """The next_url value used for an inconistent patch flag."""
     return canonical_url(attachment) + '/+confirm-is-patch'
Example #34
0
    def traverse(self, name):
        """Traverse the paths of a feed.

        If a query string is provided it is normalized.  'bugs' paths and
        persons ('~') are special cased.
        """
        # Normalize the query string so caching is more effective.  This is
        # done by simply sorting the entries.

        # XXX bac 20071019, we would like to normalize with respect to case
        # too but cannot due to a problem with the bug search requiring status
        # values to be of a particular case.  See bug 154562.
        query_string = self.request.get('QUERY_STRING', '')
        fields = sorted(query_string.split('&'))
        normalized_query_string = '&'.join(fields)
        if query_string != normalized_query_string:
            # We must empty the traversal stack to prevent an error
            # when calling RedirectionView.publishTraverse().
            self.request.setTraversalStack([])
            target = "%s%s?%s" % (self.request.getApplicationURL(),
                                  self.request['PATH_INFO'],
                                  normalized_query_string)
            redirect = RedirectionView(target, self.request, 301)
            return redirect

        # Handle the three formats of urls:
        # http://feeds.launchpad.net/bugs/latest-bugs.atom
        # http://feeds.launchpad.net/bugs/+bugs.atom?...
        # http://feeds.launchpad.net/bugs/1/bug.atom
        if name == 'bugs':
            stack = self.request.getTraversalStack()
            if len(stack) == 0:
                raise NotFound(self, '', self.request)
            bug_id = stack.pop()
            if bug_id.startswith('+'):
                if config.launchpad.is_bug_search_feed_active:
                    return getUtility(IBugTaskSet)
                else:
                    raise Unauthorized("Bug search feed deactivated")
            elif bug_id.startswith('latest-bugs.'):
                return getUtility(IMaloneApplication)
            else:
                self.request.stepstogo.consume()
                return getUtility(IBugSet).getByNameOrID(bug_id)

        # Redirect to the canonical name before doing the lookup.
        if canonical_name(name) != name:
            return self.redirectSubTree(canonical_url(self.context) +
                                        canonical_name(name),
                                        status=301)

        try:
            if name.startswith('~'):
                # Handle persons and teams.
                # http://feeds.launchpad.net/~salgado/latest-bugs.html
                person = getUtility(IPersonSet).getByName(name[1:])
                return person
            else:
                # Otherwise, handle products, projects, and distros
                return getUtility(IPillarNameSet)[name]
        except NotFoundError:
            raise NotFound(self, name, self.request)
Example #35
0
 def redirect_imports(self):
     """Redirect /translations/imports to Translations root site."""
     target_url = canonical_url(
         getUtility(ILaunchpadRoot), rootsite='translations')
     return self.redirectSubTree(
         target_url + '+imports', status=301)
Example #36
0
 def answers_url(self):
     return canonical_url(
         getUtility(ILaunchpadCelebrities).launchpad,
         rootsite='answers')
Example #37
0
 def next_url(self):
     return canonical_url(self.current_bugtask)
Example #38
0
 def href(self):
     return urlappend(canonical_url(self.context, rootsite="feeds"),
                      'revisions.atom')
Example #39
0
 def traverse(self, name):
     try:
         return super(DistributionNavigation, self).traverse(name)
     except NotFoundError:
         resolved = self.context.resolveSeriesAlias(name)
         return self.redirectSubTree(canonical_url(resolved), status=303)
Example #40
0
 def initialize(self):
     """See `LaunchpadFormView`."""
     filebug_url = "%s/+filebug" % canonical_url(self.context.product)
     self.request.response.redirect(filebug_url)
Example #41
0
 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)
Example #42
0
 def href(self):
     return urlappend(canonical_url(self.context, rootsite="feeds"),
                      'branch.atom')
Example #43
0
 def linked_packages_message(self):
     url = canonical_url(self.context.product, view_name="+packages")
     return ("You cannot delete a series that is linked to packages in "
             "distributions. You can remove the links from the "
             '<a href="%s">project packaging</a> page.' % url)
Example #44
0
 def request_import_link(self):
     """A link to the page for requesting a new code import."""
     return canonical_url(self.context.product,
                          view_name='+new-import',
                          rootsite='code')
Example #45
0
 def getNominationEditLink(self):
     """Return a link to the nomination edit form."""
     return (
         "%s/nominations/%d/+editstatus" %
         (canonical_url(getUtility(ILaunchBag).bugtask), self.context.id))
Example #46
0
 def launchpad_users_team(self):
     """The url of the launchpad-users team."""
     team = getUtility(IPersonSet).getByName('launchpad-users')
     return canonical_url(team)
Example #47
0
 def redirect_source(self):
     return canonical_url(self.context)
 def referrer_url(self):
     referrer = self.request.getHeader('referer')
     if referrer != canonical_url(self.context):
         return referrer
     else:
         return None
Example #49
0
 def change_action(self, action, data):
     self.updateContextFromData(data)
     self.next_url = canonical_url(self.context)
Example #50
0
 def action_url(self):
     return "%s/nominations/%d/+editstatus" % (canonical_url(
         self.current_bugtask), self.context.id)
 def _composeProductSeriesLink(self, productseries):
     """Produce HTML to link to `productseries`."""
     return '<a href="%s">%s</a>' % (canonical_url(
         productseries, rootsite='translations'), productseries.name)
Example #52
0
 def __init__(self, context, request):
     target = canonical_url(
         context, rootsite='translations', view_name='+translations')
     super(TranslationsRedirectView, self).__init__(
         target, request, status=301)
Example #53
0
 def cancel_url(self):
     return canonical_url(self.context)
Example #54
0
 def href(self):
     return urlappend(canonical_url(self.context, rootsite='feeds'),
                      'latest-bugs.atom')
Example #55
0
 def cancel_url(self):
     return canonical_url(self.context.specification)
Example #56
0
 def cancel_url(self):
     """See `LaunchpadFormView`."""
     return canonical_url(getUtility(IKarmaActionSet))
Example #57
0
 def href(self):
     if IAnnouncementSet.providedBy(self.context):
         return urlappend(self.rooturl, 'announcements.atom')
     else:
         return urlappend(canonical_url(self.context, rootsite='feeds'),
                          'announcements.atom')
Example #58
0
 def cancel_url(self):
     """Return the URL for the current context."""
     return canonical_url(self.context)
Example #59
0
 def cancel_url(self):
     """See `LaunchpadFormView`."""
     return canonical_url(self.context)
Example #60
0
 def next_url(self):
     return canonical_url(getUtility(ILaunchBag).bugtask)