コード例 #1
0
    def delete_not_possible_reasons(self):
        """A list of reasons why the context cannot be deleted.

        An empty list means that there are no reasons, so the delete
        can go ahead.
        """
        reasons = []
        celebrities = getUtility(ILaunchpadCelebrities)

        # We go through all of the conditions why the bug tracker
        # can't be deleted, and record reasons for all of them. We do
        # this so that users can discover the logic behind the
        # decision, and try something else, seek help, or give up as
        # appropriate. Just showing the first problem would stop users
        # from being able to help themselves.

        # Check that no products or projects use this bugtracker.
        pillars = (
            getUtility(IBugTrackerSet).getPillarsForBugtrackers(
                [self.context]).get(self.context, []))
        if len(pillars) > 0:
            reasons.append(
                'This is the bug tracker for %s.' % english_list(
                    sorted(pillar.title for pillar in pillars)))

        # Only admins and registry experts can delete bug watches en
        # masse.
        if not self.context.watches.is_empty():
            admin_teams = [celebrities.admin, celebrities.registry_experts]
            for team in admin_teams:
                if self.user.inTeam(team):
                    break
            else:
                reasons.append(
                    'There are linked bug watches and only members of %s '
                    'can delete them en masse.' % english_list(
                        sorted(team.title for team in admin_teams)))

        # Bugtrackers with imported messages cannot be deleted.
        if not self.context.imported_bug_messages.is_empty():
            reasons.append(
                'Bug comments have been imported via this bug tracker.')

        # If the bugtracker is a celebrity then we protect it from
        # deletion.
        celebrities_set = set(
            getattr(celebrities, name)
            for name in ILaunchpadCelebrities.names())
        if self.context in celebrities_set:
            reasons.append(
                'This bug tracker is protected from deletion.')

        return reasons
コード例 #2
0
    def main(self):
        selected_groups = self.args
        if len(selected_groups) == 0:
            self.parser.print_help()
            sys.exit(1)

        selected_job_sources = set()
        # Include job sources from selected groups.
        for group in selected_groups:
            selected_job_sources.update(self.grouped_sources[group])
        # Then, exclude job sources.
        for source in self.options.excluded_job_sources:
            if source not in selected_job_sources:
                self.logger.info(
                    '%r is not in %s' % (
                        source, english_list(selected_groups, "or")))
            else:
                selected_job_sources.remove(source)
        # Process job sources.
        command = os.path.join(
            os.path.dirname(sys.argv[0]), 'process-job-source.py')
        child_args = [command]
        if self.options.verbose:
            child_args.append('-v')
        children = []
        for job_source in selected_job_sources:
            child = subprocess.Popen(child_args + [job_source])
            children.append(child)
        if self.options.do_wait:
            for child in children:
                child.wait()
コード例 #3
0
    def main(self):
        selected_groups = self.args
        if len(selected_groups) == 0:
            self.parser.print_help()
            sys.exit(1)

        selected_job_sources = set()
        # Include job sources from selected groups.
        for group in selected_groups:
            selected_job_sources.update(self.grouped_sources[group])
        # Then, exclude job sources.
        for source in self.options.excluded_job_sources:
            if source not in selected_job_sources:
                self.logger.info('%r is not in %s' %
                                 (source, english_list(selected_groups, "or")))
            else:
                selected_job_sources.remove(source)
        # Process job sources.
        command = os.path.join(os.path.dirname(sys.argv[0]),
                               'process-job-source.py')
        child_args = [command]
        if self.options.verbose:
            child_args.append('-v')
        children = []
        for job_source in selected_job_sources:
            child = subprocess.Popen(child_args + [job_source])
            children.append(child)
        if self.options.do_wait:
            for child in children:
                child.wait()
コード例 #4
0
 def _add_english_condition(self, conditions, variable, description):
     if len(variable) > 0:
         conditions.append(u"the %s is %s" %
                           (description,
                            english_list(
                                (kind.title for kind in sorted(variable)),
                                conjunction=u"or")))
コード例 #5
0
def describe_grants(activity_value):
    if activity_value is not None:
        output = describe_git_permissions({
            permission for attr, permission in _activity_permissions.items()
            if activity_value.get(attr)})
    else:
        output = []
    return english_list(output)
コード例 #6
0
ファイル: branch.py プロジェクト: pombredanne/launchpad-3
    def register_action(self, action, data):
        """Register the new branch merge proposal."""

        registrant = self.user
        source_branch = self.context
        target_branch = data['target_branch']
        prerequisite_branch = data.get('prerequisite_branch')

        review_requests = []
        reviewer = data.get('reviewer')
        review_type = data.get('review_type')
        if reviewer is None:
            reviewer = target_branch.code_reviewer
        if reviewer is not None:
            review_requests.append((reviewer, review_type))

        branch_names = [branch.unique_name
                        for branch in [source_branch, target_branch]]
        visibility_info = getUtility(IBranchSet).getBranchVisibilityInfo(
            self.user, reviewer, branch_names)
        visible_branches = list(visibility_info['visible_branches'])
        if self.request.is_ajax and len(visible_branches) < 2:
            self.request.response.setStatus(400, "Branch Visibility")
            self.request.response.setHeader(
                'Content-Type', 'application/json')
            return simplejson.dumps({
                'person_name': visibility_info['person_name'],
                'branches_to_check': branch_names,
                'visible_branches': visible_branches,
            })

        try:
            proposal = source_branch.addLandingTarget(
                registrant=registrant, merge_target=target_branch,
                merge_prerequisite=prerequisite_branch,
                needs_review=data['needs_review'],
                description=data.get('comment'),
                review_requests=review_requests,
                commit_message=data.get('commit_message'))
            if len(visible_branches) < 2:
                invisible_branches = [branch.unique_name
                            for branch in [source_branch, target_branch]
                            if branch.unique_name not in visible_branches]
                self.request.response.addNotification(
                    'To ensure visibility, %s is now subscribed to: %s'
                    % (visibility_info['person_name'],
                       english_list(invisible_branches)))
            # Success so we do a client redirect to the new mp page.
            if self.request.is_ajax:
                self.request.response.setStatus(201)
                self.request.response.setHeader(
                    'Location', canonical_url(proposal))
                return None
            else:
                self.next_url = canonical_url(proposal)
        except InvalidBranchMergeProposal as error:
            self.addError(str(error))
コード例 #7
0
    def linkedMilestonesForSeries(self, series):
        """Return a string of linkified milestones in the series."""
        # Listify to remove repeated queries.
        milestones = list(series.milestones)
        if len(milestones) == 0:
            return ""

        linked_milestones = []
        for milestone in milestones:
            linked_milestones.append("<a href=%s>%s</a>" % (canonical_url(milestone), milestone.name))

        return english_list(linked_milestones)
コード例 #8
0
    def linkedMilestonesForSeries(self, series):
        """Return a string of linkified milestones in the series."""
        # Listify to remove repeated queries.
        milestones = list(series.milestones)
        if len(milestones) == 0:
            return ""

        linked_milestones = []
        for milestone in milestones:
            linked_milestones.append(
                "<a href=%s>%s</a>" %
                (canonical_url(milestone), milestone.name))

        return english_list(linked_milestones)
コード例 #9
0
 def conditions(self):
     """Descriptions of the bug subscription filter's conditions."""
     conditions = []
     bug_notification_level = self.context.bug_notification_level
     if bug_notification_level < BugNotificationLevel.COMMENTS:
         mapping = bug_notification_level_description_mapping('the bug')
         conditions.append(mapping[bug_notification_level].lower()[:-1])
     self._add_english_condition(conditions, self.context.statuses,
                                 'status')
     self._add_english_condition(conditions, self.context.importances,
                                 'importance')
     tags = self.context.tags
     if len(tags) > 0:
         conditions.append(u"the bug is tagged with %s" % english_list(
             sorted(tags),
             conjunction=(u"and" if self.context.find_all_tags else u"or")))
     self._add_english_condition(conditions, self.context.information_types,
                                 'information type')
     return conditions
コード例 #10
0
 def conditions(self):
     """Descriptions of the bug subscription filter's conditions."""
     conditions = []
     bug_notification_level = self.context.bug_notification_level
     if bug_notification_level < BugNotificationLevel.COMMENTS:
         mapping = bug_notification_level_description_mapping(
             'the bug')
         conditions.append(
             mapping[bug_notification_level].lower()[:-1])
     self._add_english_condition(
         conditions, self.context.statuses, 'status')
     self._add_english_condition(
         conditions, self.context.importances, 'importance')
     tags = self.context.tags
     if len(tags) > 0:
         conditions.append(
             u"the bug is tagged with %s" % english_list(
                 sorted(tags), conjunction=(
                     u"and" if self.context.find_all_tags else u"or")))
     self._add_english_condition(
         conditions, self.context.information_types, 'information type')
     return conditions
コード例 #11
0
ファイル: snap.py プロジェクト: pombredanne/launchpad-3
    def requestBuild(self, data):
        """User action for requesting a number of builds.

        We raise exceptions for most errors, but if there's already a
        pending build for a particular architecture, we simply record that
        so that other builds can be queued and a message displayed to the
        caller.
        """
        informational = {}
        builds = []
        already_pending = []
        for arch in data['distro_arch_series']:
            try:
                build = self.context.requestBuild(
                    self.user, data['archive'], arch, data['pocket'],
                    channels=data['channels'])
                builds.append(build)
            except SnapBuildAlreadyPending:
                already_pending.append(arch)
        if already_pending:
            informational['already_pending'] = (
                "An identical build is already pending for %s." %
                english_list(arch.architecturetag for arch in already_pending))
        return builds, informational
コード例 #12
0
 def _add_english_condition(self, conditions, variable, description):
     if len(variable) > 0:
         conditions.append(
             u"the %s is %s" % (description, english_list(
                 (kind.title for kind in sorted(variable)),
                 conjunction=u"or")))
コード例 #13
0
ファイル: builder.py プロジェクト: pombredanne/launchpad-3
 def processors_text(self):
     return english_list(p.name for p in self.context.processors)
コード例 #14
0
ファイル: gitref.py プロジェクト: pombredanne/launchpad-3
    def register_action(self, action, data):
        """Register the new merge proposal."""

        registrant = self.user
        source_ref = self.context
        target_ref = data['target_git_repository'].getRefByPath(
            data['target_git_path'])
        if (data.get('prerequisite_git_repository') is not None and
                data.get('prerequisite_git_path') is not None):
            prerequisite_ref = (
                data['prerequisite_git_repository'].getRefByPath(
                    data['prerequisite_git_path']))
        else:
            prerequisite_ref = None

        review_requests = []
        reviewer = data.get('reviewer')
        review_type = data.get('review_type')
        if reviewer is None:
            reviewer = target_ref.code_reviewer
        if reviewer is not None:
            review_requests.append((reviewer, review_type))

        repository_names = [
            ref.repository.unique_name for ref in (source_ref, target_ref)]
        repository_set = getUtility(IGitRepositorySet)
        visibility_info = repository_set.getRepositoryVisibilityInfo(
            self.user, reviewer, repository_names)
        visible_repositories = list(visibility_info['visible_repositories'])
        if self.request.is_ajax and len(visible_repositories) < 2:
            self.request.response.setStatus(400, "Repository Visibility")
            self.request.response.setHeader(
                'Content-Type', 'application/json')
            return json.dumps({
                'person_name': visibility_info['person_name'],
                'repositories_to_check': repository_names,
                'visible_repositories': visible_repositories,
            })

        try:
            proposal = source_ref.addLandingTarget(
                registrant=registrant, merge_target=target_ref,
                merge_prerequisite=prerequisite_ref,
                needs_review=data['needs_review'],
                description=data.get('comment'),
                review_requests=review_requests,
                commit_message=data.get('commit_message'))
            if len(visible_repositories) < 2:
                invisible_repositories = [
                    ref.repository.unique_name
                    for ref in (source_ref, target_ref)
                    if ref.repository.unique_name not in visible_repositories]
                self.request.response.addNotification(
                    'To ensure visibility, %s is now subscribed to: %s'
                    % (visibility_info['person_name'],
                       english_list(invisible_repositories)))
            # Success so we do a client redirect to the new mp page.
            if self.request.is_ajax:
                self.request.response.setStatus(201)
                self.request.response.setHeader(
                    'Location', canonical_url(proposal))
                return None
            else:
                self.next_url = canonical_url(proposal)
        except InvalidBranchMergeProposal as error:
            self.addError(str(error))
コード例 #15
0
 def __init__(self, duplicates):
     super(DuplicateBuildOnError, self).__init__(
         "{} {} present in the 'build-on' of multiple items".format(
             english_list(duplicates),
             "is" if len(duplicates) == 1 else "are"))