def add(self, persons, reason, header): """See `INotificationRecipientSet`.""" from zope.security.proxy import removeSecurityProxy from lp.registry.model.person import get_recipients if IPerson.providedBy(persons): persons = [persons] for person in persons: assert IPerson.providedBy(person), ( 'You can only add() an IPerson: %r' % person) # If the person already has a rationale, keep the first one. if person in self._personToRationale: continue self._personToRationale[person] = reason, header for receiving_person in get_recipients(person): # Bypass zope's security because IEmailAddress.email is not # public. preferred_email = removeSecurityProxy( receiving_person).preferredemail email = str(preferred_email.email) self._receiving_people.add((email, receiving_person)) old_person = self._emailToPerson.get(email) # Only associate this email to the person, if there was # no association or if the previous one was to a team and # the newer one is to a person. if (old_person is None or (old_person.is_team and not person.is_team)): self._emailToPerson[email] = person
def faq_edited(faq, event): """Assign karma to user who edited a FAQ.""" user = IPerson(event.user) old_faq = event.object_before_modification context = get_karma_context_parameters(faq.target) if old_faq.content != faq.content or old_faq.title != faq.title: user.assignKarma('faqedited', **context)
def get_string_representation(obj): """Returns a string representation of an object. It can be used as oldvalue and newvalue. Returns None if no representation can be made. """ if IPerson.providedBy(obj): return obj.name if IBug.providedBy(obj): return str(obj.id) elif ISourcePackageRelease.providedBy(obj): return "%s %s" % (obj.sourcepackagename.name, obj.version) elif IProductRelease.providedBy(obj): return "%s %s" % (obj.product.name, obj.version) elif IMilestone.providedBy(obj): return obj.name elif isinstance(obj, BaseItem): return obj.title elif isinstance(obj, basestring): return obj elif isinstance(obj, bool): return str(obj) else: return None
def notify_bugtask_deleted(bugtask, event): """A bugtask has been deleted (removed from a bug). bugtask must be in IBugTask. event must be anIObjectDeletedEvent. """ bugtask.bug.addChange(BugTaskDeleted(UTC_NOW, IPerson(event.user), bugtask))
def createPositiveResponse(self): """Create a positive assertion OpenIDResponse. This method should be called to create the response to successful checkid requests. If the trust root for the request is in openid_sreg_trustroots, then additional user information is included with the response. """ assert self.account is not None, ( 'Must be logged in for positive OpenID response') assert self.openid_request is not None, ( 'No OpenID request to respond to.') if not self.isIdentityOwner(): return self.createFailedResponse() if self.openid_request.idSelect(): response = self.openid_request.answer( True, identity=self.user_identity_url) else: response = self.openid_request.answer(True) person = IPerson(self.account) sreg_fields = dict(nickname=person.name, email=person.preferredemail.email, fullname=self.account.displayname) sreg_request = SRegRequest.fromOpenIDRequest(self.openid_request) sreg_response = SRegResponse.extractResponse(sreg_request, sreg_fields) response.addExtension(sreg_response) return response
def merge_proposal_modified(merge_proposal, event): """Notify branch subscribers when merge proposals are updated.""" # Check the user. if event.user is None: return if isinstance(event.user, UnauthenticatedPrincipal): from_person = None else: from_person = IPerson(event.user) # If the merge proposal was work in progress, then we don't want to send # out an email as the needs review email will cover that. old_status = event.object_before_modification.queue_status if old_status == BranchMergeProposalStatus.WORK_IN_PROGRESS: # Unless the new status is merged. If this occurs we really should # send out an email. if merge_proposal.queue_status != BranchMergeProposalStatus.MERGED: return # Create a delta of the changes. If there are no changes to report, then # we're done. delta = BranchMergeProposalNoPreviewDiffDelta.construct( event.object_before_modification, merge_proposal) if delta is None: return changes = text_delta(delta, delta.delta_values, delta.new_values, delta.interface) # Now create the job to send the email. getUtility(IMergeProposalUpdatedEmailJobSource).create( merge_proposal, changes, from_person)
def test_unseen_identity(self): # When we get a positive assertion about an identity URL we've never # seen, we automatically register an account with that identity # because someone who registered on login.lp.net or login.u.c should # be able to login here without any further steps. identifier = u'4w7kmzU' account_set = getUtility(IAccountSet) self.assertRaises(LookupError, account_set.getByOpenIDIdentifier, identifier) openid_response = FakeOpenIDResponse('http://testopenid.dev/+id/%s' % identifier, status=SUCCESS, email='*****@*****.**', full_name='Foo User') with SRegResponse_fromSuccessResponse_stubbed(): view, html = self._createAndRenderView(openid_response) self.assertTrue(view.login_called) account = account_set.getByOpenIDIdentifier(identifier) self.assertIsNot(None, account) self.assertEqual(AccountStatus.ACTIVE, account.status) person = IPerson(account, None) self.assertIsNot(None, person) self.assertEqual('Foo User', person.displayname) self.assertEqual('*****@*****.**', removeSecurityProxy(person.preferredemail).email) # We also update the last_write flag in the session, to make sure # further requests use the master DB and thus see the newly created # stuff. self.assertLastWriteIsSet(view.request)
def bugtask_modified(bugtask, event): """Check changes made to <bugtask> and assign karma to user if needed.""" user = IPerson(event.user) task_delta = event.object.getDelta(event.object_before_modification) if task_delta is None: return actionname_status_mapping = { BugTaskStatus.FIXRELEASED: 'bugfixed', BugTaskStatus.INVALID: 'bugrejected', BugTaskStatus.CONFIRMED: 'bugaccepted', BugTaskStatus.TRIAGED: 'bugaccepted', } if task_delta.status: new_status = task_delta.status['new'] actionname = actionname_status_mapping.get(new_status) if actionname is not None: if actionname == 'bugfixed' and bugtask.assignee is not None: _assign_karma_using_bugtask_context( bugtask.assignee, bugtask, actionname) else: _assign_karma_using_bugtask_context(user, bugtask, actionname) if task_delta.importance is not None: _assign_karma_using_bugtask_context( user, bugtask, 'bugtaskimportancechanged')
def branch_merge_modified(proposal, event): """Assign karma to the user who approved or rejected the merge.""" if event.user is None or isinstance(event.user, UnauthenticatedPrincipal): # Some modification events have no associated user context. In # these cases there's no karma to assign. return if proposal.source_git_repository is not None: target = proposal.source_git_repository.namespace else: target = proposal.source_branch.target user = IPerson(event.user) old_status = event.object_before_modification.queue_status new_status = proposal.queue_status in_progress_states = (BranchMergeProposalStatus.WORK_IN_PROGRESS, BranchMergeProposalStatus.NEEDS_REVIEW) if ((new_status == BranchMergeProposalStatus.CODE_APPROVED) and (old_status in (in_progress_states))): if user == proposal.registrant: target.assignKarma(user, 'branchmergeapprovedown') else: target.assignKarma(user, 'branchmergeapproved') elif ((new_status == BranchMergeProposalStatus.REJECTED) and (old_status in (in_progress_states))): if user == proposal.registrant: target.assignKarma(user, 'branchmergerejectedown') else: target.assignKarma(user, 'branchmergerejected') else: # Only care about approved and rejected right now. pass
def __init__(self, context=None): """Pass a Person as context, or anything else for the current user.""" super(HostedBranchRestrictedOnOwnerVocabulary, self).__init__(context) if IPerson.providedBy(self.context): self.user = self.context else: self.user = getUtility(ILaunchBag).user
def template(self): # Check for the magical "index" added by the browser:page template # machinery. If it exists this is actually the # zope.browserpage.simpleviewclass.simple class that is magically # mixed in by the browser:page zcml directive the template defined in # the directive should be used. if safe_hasattr(self, 'index'): return super(HasSpecificationsView, self).template # Sprints and Persons don't have a usage enum for blueprints, so we # have to fallback to the default. if (ISprint.providedBy(self.context) or IPerson.providedBy(self.context)): return self.default_template # ProjectGroups are a special case, as their products may be a # combination of usage settings. To deal with this, check all # products via the involvment menu. if (IProjectGroup.providedBy(self.context) or IProjectGroupSeries.providedBy(self.context)): involvement = getMultiAdapter((self.context, self.request), name='+get-involved') if service_uses_launchpad(involvement.blueprints_usage): return self.default_template else: return self.not_launchpad_template # Otherwise, determine usage and provide the correct template. service_usage = IServiceUsage(self.context) if service_uses_launchpad(service_usage.blueprints_usage): return self.default_template else: return self.not_launchpad_template
def template(self): # Check for the magical "index" added by the browser:page template # machinery. If it exists this is actually the # zope.browserpage.simpleviewclass.simple class that is magically # mixed in by the browser:page zcml directive the template defined in # the directive should be used. if safe_hasattr(self, 'index'): return super(HasSpecificationsView, self).template # Sprints and Persons don't have a usage enum for blueprints, so we # have to fallback to the default. if (ISprint.providedBy(self.context) or IPerson.providedBy(self.context)): return self.default_template # ProjectGroups are a special case, as their products may be a # combination of usage settings. To deal with this, check all # products via the involvment menu. if (IProjectGroup.providedBy(self.context) or IProjectGroupSeries.providedBy(self.context)): involvement = getMultiAdapter( (self.context, self.request), name='+get-involved') if service_uses_launchpad(involvement.blueprints_usage): return self.default_template else: return self.not_launchpad_template # Otherwise, determine usage and provide the correct template. service_usage = IServiceUsage(self.context) if service_uses_launchpad(service_usage.blueprints_usage): return self.default_template else: return self.not_launchpad_template
def notify_bugtask_added(bugtask, event): """Notify CC'd list that this bug has been marked as needing fixing somewhere else. bugtask must be in IBugTask. event must be an IObjectModifiedEvent. """ bugtask.bug.addChange(BugTaskAdded(UTC_NOW, IPerson(event.user), bugtask))
def record_cve_unlinked_from_bug(bug, event): """Record when a CVE is unlinked from a bug.""" if not ICve.providedBy(event.other_object): return bug.addChange( CveUnlinkedFromBug(when=None, person=IPerson(event.user), cve=event.other_object))
def record_bug_added(bug, object_created_event): activity = getUtility(IBugActivitySet).new(bug=bug.id, datechanged=UTC_NOW, person=IPerson( object_created_event.user), whatchanged="bug", message="added bug") bug.addCommentNotification(bug.initial_message, activity=activity)
def notify_bug_modified(bug, event): """Handle bug change events.""" bug_delta = get_bug_delta(old_bug=event.object_before_modification, new_bug=event.object, user=IPerson(event.user)) if bug_delta is not None: add_bug_change_notifications(bug_delta)
def record_cve_linked_to_bug(bug, event): """Record when a CVE is linked to a bug.""" if not ICve.providedBy(event.other_object): return bug.addChange( CveLinkedToBug(when=None, person=IPerson(event.user), cve=event.other_object))
def is_public_person_or_closed_team(person): """Return True if person is a Person or not an open or delegated team.""" from lp.registry.interfaces.person import IPerson if not IPerson.providedBy(person): return False if not person.is_team: return person.visibility == PersonVisibility.PUBLIC return person.membership_policy in EXCLUSIVE_TEAM_POLICY
def create(cls, minor_person, major_person, metadata, requester=None): """See `IPersonTransferJob`.""" if not IPerson.providedBy(minor_person): raise TypeError("minor_person must be IPerson: %s" % repr(minor_person)) if not IPerson.providedBy(major_person): raise TypeError("major_person must be IPerson: %s" % repr(major_person)) job = PersonTransferJob( minor_person=minor_person, major_person=major_person, job_type=cls.class_job_type, metadata=metadata, requester=requester) derived = cls(job) derived.celeryRunOnCommit() return derived
def send_branch_modified_notifications(branch, event): """Notify the related people that a branch has been modified.""" user = IPerson(event.user) branch_delta = BranchDelta.construct(event.object_before_modification, branch, user) if branch_delta is None: return getUtility(IBranchModifiedMailJobSource).create(branch, user, branch_delta)
def __contains__(self, person_or_email): """See `INotificationRecipientSet`.""" if zope_isinstance(person_or_email, (str, unicode)): return person_or_email in self._emailToPerson elif IPerson.providedBy(person_or_email): return person_or_email in self._personToRationale else: return False
def specification_update_lifecycle_status(spec, event): """Mark the specification as started and/or complete if appropriate. Does nothing if there is no user associated with the event. """ if event.user is None: return spec.updateLifecycleStatus(IPerson(event.user))
def test_checkAuthenticated_for_full_fledged_account(self): # AuthorizationBase.checkAuthenticated should delegate to # checkAuthenticated() when the given account can be adapted # into an IPerson. full_fledged_account = self.factory.makePerson().account adapter = FakeSecurityAdapter() adapter.checkAuthenticated(IPerson(full_fledged_account)) self.assertVectorEqual((1, adapter.checkAuthenticated.call_count), (0, adapter.checkUnauthenticated.call_count))
def record_merge_proposal_unlinked_from_bug(bug, event): """Record when a merge proposal is unlinked from a bug.""" if not IBranchMergeProposal.providedBy(event.other_object): return bug.addChange( MergeProposalUnlinkedFromBug(when=None, person=IPerson(event.user), merge_proposal=event.other_object, bug=event.object))
def send_git_repository_modified_notifications(repository, event): """Notify the related people that a Git repository has been modified.""" user = IPerson(event.user) repository_delta = GitRepositoryDelta.construct( event.object_before_modification, repository, user) if repository_delta is None: return getUtility(IGitRepositoryModifiedMailJobSource).create( repository, user, repository_delta)
def send_branch_modified_notifications(branch, event): """Notify the related people that a branch has been modifed.""" user = IPerson(event.user) branch_delta = BranchDelta.construct(event.object_before_modification, branch, user) if branch_delta is None: return mailer = BranchMailer.forBranchModified(branch, user, branch_delta) mailer.sendAll()
def record_merge_proposal_linked_to_bug(bug, event): """Record when a merge proposal is linked to a bug.""" if not IBranchMergeProposal.providedBy(event.other_object): return bug.addChange( MergeProposalLinkedToBug(when=None, person=IPerson(event.user), merge_proposal=event.other_object, bug=event.object))
def record_bugsubscription_added(bugsubscription_added, object_created_event): subscribed_user = bugsubscription_added.person if subscribed_user.visibility == PersonVisibility.PUBLIC: getUtility(IBugActivitySet).new( bug=bugsubscription_added.bug, datechanged=UTC_NOW, person=IPerson(object_created_event.user), whatchanged='bug', message='added subscriber %s' % subscribed_user.displayname)
def remove(self, persons): """See `INotificationRecipientSet`.""" from zope.security.proxy import removeSecurityProxy from lp.registry.model.person import get_recipients if IPerson.providedBy(persons): persons = [persons] for person in persons: assert IPerson.providedBy(person), ( 'You can only remove() an IPerson: %r' % person) if person in self._personToRationale: del self._personToRationale[person] for removed_person in get_recipients(person): # Bypass zope's security because IEmailAddress.email is # not public. preferred_email = removeSecurityProxy( removed_person.preferredemail) email = str(preferred_email.email) self._receiving_people.discard((email, removed_person)) del self._emailToPerson[email]
def expose_user_administered_teams_to_js(request, user, context, absoluteURL=absoluteURL): """Make the list of teams the user administers available to JavaScript.""" # XXX: Robert Collins workaround multiple calls making this cause # timeouts: see bug 788510. objects = IJSONRequestCache(request).objects if 'administratedTeams' in objects: return info = [] api_request = IWebServiceClientRequest(request) is_distro = IDistribution.providedBy(context) if is_distro: # If the context is a distro AND a bug supervisor is set then we only # allow subscriptions from members of the bug supervisor team. bug_supervisor = context.bug_supervisor else: bug_supervisor = None if user is not None: administrated_teams = set(user.administrated_teams) if administrated_teams: # Get this only if we need to. membership = set(user.teams_participated_in) # Only consider teams the user is both in and administers: # If the user is not a member of the team itself, then # skip it, because structural subscriptions and their # filters can only be edited by the subscriber. # This can happen if the user is an owner but not a member. administers_and_in = membership.intersection(administrated_teams) list( getUtility(IPersonSet).getPrecachedPersonsFromIDs( [team.id for team in administers_and_in], need_preferred_email=True)) # If the requester is the user, they're at least an admin in # all of these teams. Precache launchpad.(Limited)View so we # can see the necessary attributes. current_user = IPerson(get_current_principal(), None) if current_user is not None and user == current_user: for perm in ('launchpad.View', 'launchpad.LimitedView'): precache_permission_for_objects(None, perm, administers_and_in) for team in sorted(administers_and_in, key=attrgetter('name')): if (bug_supervisor is not None and not team.inTeam(bug_supervisor)): continue info.append({ 'has_preferredemail': team.preferredemail is not None, 'link': absoluteURL(team, api_request), 'title': team.unique_displayname, 'url': canonical_url(team), }) objects['administratedTeams'] = info
def maybeRestrictToTeam(self, request): restrict_to_team = config.launchpad.restrict_to_team if not restrict_to_team: return restrictedlogin = '******' restrictedinfo = '+restricted-info' # Always allow access to +restrictedlogin and +restrictedinfo. traversal_stack = request.getTraversalStack() if (traversal_stack == [restrictedlogin] or traversal_stack == [restrictedinfo]): return principal = request.principal team = getUtility(IPersonSet).getByName(restrict_to_team) if team is None: raise AssertionError( 'restrict_to_team "%s" not found' % restrict_to_team) elif not ITeam.providedBy(team): raise AssertionError( 'restrict_to_team "%s" is not a team' % restrict_to_team) if IUnauthenticatedPrincipal.providedBy(principal): location = '/%s' % restrictedlogin else: # We have a team we can work with. user = IPerson(principal) if (user.inTeam(team) or user.inTeam(getUtility(ILaunchpadCelebrities).admin)): return else: location = '/%s' % restrictedinfo non_restricted_url = self.getNonRestrictedURL(request) if non_restricted_url is not None: location += '?production=%s' % urllib.quote(non_restricted_url) request.response.setResult('') request.response.redirect(location, temporary_if_possible=True) # Quash further traversal. request.setTraversalStack([])
def maybeRestrictToTeam(self, request): restrict_to_team = config.launchpad.restrict_to_team if not restrict_to_team: return restrictedlogin = '******' restrictedinfo = '+restricted-info' # Always allow access to +restrictedlogin and +restrictedinfo. traversal_stack = request.getTraversalStack() if (traversal_stack == [restrictedlogin] or traversal_stack == [restrictedinfo]): return principal = request.principal team = getUtility(IPersonSet).getByName(restrict_to_team) if team is None: raise AssertionError('restrict_to_team "%s" not found' % restrict_to_team) elif not ITeam.providedBy(team): raise AssertionError('restrict_to_team "%s" is not a team' % restrict_to_team) if IUnauthenticatedPrincipal.providedBy(principal): location = '/%s' % restrictedlogin else: # We have a team we can work with. user = IPerson(principal) if (user.inTeam(team) or user.inTeam(getUtility(ILaunchpadCelebrities).admin)): return else: location = '/%s' % restrictedinfo non_restricted_url = self.getNonRestrictedURL(request) if non_restricted_url is not None: location += '?production=%s' % urllib.quote(non_restricted_url) request.response.setResult('') request.response.redirect(location, temporary_if_possible=True) # Quash further traversal. request.setTraversalStack([])
def git_rule_modified(rule, event): """Update date_last_modified when a GitRule is modified. This method is registered as a subscriber to `IObjectModifiedEvent` events on Git repository rules. """ if event.edited_fields: user = IPerson(event.user) getUtility(IGitActivitySet).logRuleChanged( event.object_before_modification, rule, user) removeSecurityProxy(rule).date_last_modified = UTC_NOW
def get_git_namespace(target, owner): if IProduct.providedBy(target): return getUtility(IGitNamespaceSet).get(owner, project=target) elif IDistributionSourcePackage.providedBy(target): return getUtility(IGitNamespaceSet).get( owner, distribution=target.distribution, sourcepackagename=target.sourcepackagename) elif target is None or IPerson.providedBy(target): return getUtility(IGitNamespaceSet).get(owner) else: raise AssertionError("No Git namespace defined for %s" % target)
def test_branch_list_recipes_link(self): # The link to the source package recipes is always displayed. page = self.get_branch_list_page() recipes_matcher = soupmatchers.HTMLContains( soupmatchers.Tag( 'Source package recipes link', 'a', text='Source package recipes', attrs={'href': self.base_url + '/+recipes'})) if IPerson.providedBy(self.default_target): self.assertThat(page, recipes_matcher) else: self.assertThat(page, Not(recipes_matcher))
def question_modified(question, event): """Check changes made to <question> and assign karma to user if needed.""" user = IPerson(event.user) old_question = event.object_before_modification if old_question.description != question.description: assignKarmaUsingQuestionContext( user, question, 'questiondescriptionchanged') if old_question.title != question.title: assignKarmaUsingQuestionContext( user, question, 'questiontitlechanged')
def getProposalsForContext(context, status=None, visible_by_user=None): """See `IBranchMergeProposalGetter`.""" collection = getUtility(IAllBranches).visibleByUser(visible_by_user) if context is None: pass elif IProduct.providedBy(context): collection = collection.inProduct(context) elif IPerson.providedBy(context): collection = collection.ownedBy(context) else: raise BadBranchMergeProposalSearchContext(context) return collection.getMergeProposals(status)
def setRenderedValue(self, value): """See IWidget.""" self.setUpSubWidgets() if IBranchTarget.providedBy(value): if IProduct.providedBy(value.context): self.default_option = 'product' self.product_widget.setRenderedValue(value.context) return elif IPerson.providedBy(value.context): self.default_option = 'personal' return else: raise AssertionError('Not a valid value: %r' % value)
def spec_modified(spec, event): """Check changes made to the spec and assign karma if needed.""" user = IPerson(event.user) spec_delta = event.object.getDelta(event.object_before_modification, user) if spec_delta is None: return # easy 1-1 mappings from attribute changing to karma attrs_actionnames = { 'title': 'spectitlechanged', 'summary': 'specsummarychanged', 'specurl': 'specurlchanged', 'priority': 'specpriority', 'productseries': 'specseries', 'distroseries': 'specseries', 'milestone': 'specmilestone', } for attr, actionname in attrs_actionnames.items(): if getattr(spec_delta, attr, None) is not None: user.assignKarma( actionname, product=spec.product, distribution=spec.distribution)
def getReason(self, person_or_email): """See `INotificationRecipientSet`.""" if zope_isinstance(person_or_email, basestring): try: person = self._emailToPerson[person_or_email] except KeyError: raise UnknownRecipientError(person_or_email) elif IPerson.providedBy(person_or_email): person = person_or_email else: raise AssertionError( 'Not an IPerson or email address: %r' % person_or_email) try: return self._personToRationale[person] except KeyError: raise UnknownRecipientError(person)
def __init__(self, search_text=None, owner=None, sort=None, product=None, distribution=None, project=None): """Initialize a new FAQ search. See `IFAQCollection`.searchFAQs for the basic parameters description. Additional parameters: :param product: The product in which to search for FAQs. :param distribution: The distribution in which to search for FAQs. :param project: The project in which to search for FAQs. """ if search_text is not None: assert isinstance(search_text, basestring), ( 'search_text should be a string, not %s' % type(search_text)) self.search_text = search_text if owner is not None: assert IPerson.providedBy(owner), ( 'owner should be an IPerson, not %s' % type(owner)) self.owner = owner if sort is not None: assert sort in FAQSort.items, ( 'sort should be an item from FAQSort, not %s' % type(sort)) self.sort = sort if product is not None: assert IProduct.providedBy(product), ( 'product should be an IProduct, not %s' % type(product)) assert distribution is None and project is None, ( 'can only use one of product, distribution, or project') self.product = product if distribution is not None: assert IDistribution.providedBy(distribution), ( 'distribution should be an IDistribution, %s' % type(distribution)) assert product is None and project is None, ( 'can only use one of product, distribution, or project') self.distribution = distribution if project is not None: assert IProjectGroup.providedBy(project), ( 'project should be an IProjectGroup, not %s' % type(project)) assert product is None and distribution is None, ( 'can only use one of product, distribution, or project') self.project = project
def get_person_bugtasks_search_params(user, context, **kwargs): """Returns a list of `BugTaskSearchParams` which can be used to search for all tasks related to a user given by `context`. Which tasks are related to a user? * the user has to be either assignee or owner of this task OR * the user has to be subscriber or commenter to the underlying bug OR * the user is reporter of the underlying bug, but this condition is automatically fulfilled by the first one as each new bug always get one task owned by the bug reporter """ from lp.registry.interfaces.person import IPerson assert IPerson.providedBy(context), "Context argument needs to be IPerson" relevant_fields = ('assignee', 'bug_subscriber', 'owner', 'bug_commenter', 'structural_subscriber') search_params = [] for key in relevant_fields: # all these parameter default to None user_param = kwargs.get(key) if user_param is None or user_param == context: # we are only creating a `BugTaskSearchParams` object if # the field is None or equal to the context arguments = kwargs.copy() arguments[key] = context if key == 'owner': # Specify both owner and bug_reporter to try to # prevent the same bug (but different tasks) # being displayed. # see `PersonRelatedBugTaskSearchListingView.searchUnbatched` arguments['bug_reporter'] = context search_params.append( BugTaskSearchParams.fromSearchForm(user, **arguments)) if len(search_params) == 0: # unable to search for related tasks to user_context because user # modified the query in an invalid way by overwriting all user # related parameters raise IllegalRelatedBugTasksParams( ('Cannot search for related tasks to \'%s\', at least one ' 'of these parameter has to be empty: %s' % (context.name, ", ".join(relevant_fields)))) return search_params
def create(cls, member, team, reviewer, old_status, new_status, last_change_comment=None): if not ITeam.providedBy(team): raise TypeError('team must be ITeam: %s' % repr(team)) if not IPerson.providedBy(reviewer): raise TypeError('reviewer must be IPerson: %s' % repr(reviewer)) if old_status not in TeamMembershipStatus: raise TypeError("old_status must be TeamMembershipStatus: %s" % repr(old_status)) if new_status not in TeamMembershipStatus: raise TypeError("new_status must be TeamMembershipStatus: %s" % repr(new_status)) metadata = { 'reviewer': reviewer.id, 'old_status': old_status.name, 'new_status': new_status.name, 'last_change_comment': last_change_comment, } return super(MembershipNotificationJob, cls).create( minor_person=member, major_person=team, metadata=metadata)
def new(owner, title, content, keywords=keywords, date_created=None, product=None, distribution=None): """Factory method to create a new FAQ. Ensure that only one of product or distribution is given. """ if not IPerson.providedBy(owner): raise AssertionError( 'owner parameter should be an IPerson, not %s' % type(owner)) if product is not None and distribution is not None: raise AssertionError( "only one of product or distribution should be provided") if product is None and distribution is None: raise AssertionError("product or distribution must be provided") if date_created is None: date_created = DEFAULT faq = FAQ( owner=owner, title=title, content=content, keywords=keywords, date_created=date_created, product=product, distribution=distribution) notify(ObjectCreatedEvent(faq)) return faq
def initialize(self): if IPerson.providedBy(self.context): self.is_person = True elif IDistribution.providedBy(self.context): self.is_target = True self.is_pillar = True self.show_series = True elif IProduct.providedBy(self.context): self.is_target = True self.is_pillar = True self.has_wiki = True self.show_series = True elif IProjectGroup.providedBy(self.context): self.is_project = True self.is_pillar = True self.has_wiki = True self.show_target = True self.show_series = True elif IProjectGroupSeries.providedBy(self.context): self.show_milestone = True self.show_target = True self.show_series = True elif (IProductSeries.providedBy(self.context) or IDistroSeries.providedBy(self.context)): self.is_series = True self.show_milestone = True elif ISprint.providedBy(self.context): self.is_sprint = True self.show_target = True else: raise AssertionError('Unknown blueprint listing site.') if IHasDrivers.providedBy(self.context): self.has_drivers = True self.batchnav = BatchNavigator( self.specs, self.request, size=config.launchpad.default_batch_size)
def get_person_picker_entry_metadata(picker_entry): """Return the picker entry meta for a given result value.""" if picker_entry is not None and IPerson.providedBy(picker_entry): return "team" if picker_entry.is_team else "person" return None
def is_public_person(person): """Return True if the person is public.""" from lp.registry.interfaces.person import IPerson if not IPerson.providedBy(person): return False return person.visibility == PersonVisibility.PUBLIC
def getForDistroSeries(distro_series, difference_type=None, name_filter=None, status=None, child_version_higher=False, parent_series=None, packagesets=None, changed_by=None): """See `IDistroSeriesDifferenceSource`.""" if isinstance(status, DBItem): status = (status,) if IPerson.providedBy(changed_by): changed_by = (changed_by,) # Aliases, to improve readability. DSD = DistroSeriesDifference PSS = PackagesetSources SPN = SourcePackageName SPPH = SourcePackagePublishingHistory SPR = SourcePackageRelease TP = TeamParticipation conditions = [ DSD.derived_series == distro_series, DSD.source_package_name == SPN.id, # For ordering. ] if difference_type is not None: conditions.append(DSD.difference_type == difference_type) if status is not None: conditions.append(DSD.status.is_in(tuple(status))) if child_version_higher: conditions.append(DSD.source_version > DSD.parent_source_version) if parent_series: conditions.append(DSD.parent_series == parent_series.id) # Take a copy of the conditions specified thus far. basic_conditions = list(conditions) if name_filter: name_matches = [SPN.name == name_filter] try: packageset = getUtility(IPackagesetSet).getByName( name_filter, distroseries=distro_series) except NoSuchPackageSet: packageset = None if packageset is not None: name_matches.append( DSD.source_package_name_id.is_in( Select(PSS.sourcepackagename_id, PSS.packageset == packageset))) conditions.append(Or(*name_matches)) if packagesets is not None: set_ids = [packageset.id for packageset in packagesets] conditions.append( DSD.source_package_name_id.is_in( Select(PSS.sourcepackagename_id, PSS.packageset_id.is_in(set_ids)))) store = IStore(DSD) columns = (DSD, SPN.name) differences = store.find(columns, And(*conditions)) if changed_by is not None: # Identify all DSDs referring to SPRs created by changed_by for # this distroseries. The set of DSDs for the given distroseries # can then be discovered as the intersection between this set and # the already established differences. differences_changed_by_conditions = And( basic_conditions, SPPH.archiveID == distro_series.main_archive.id, SPPH.distroseriesID == distro_series.id, SPPH.sourcepackagereleaseID == SPR.id, SPPH.status.is_in(active_publishing_status), SPR.creatorID == TP.personID, SPR.sourcepackagenameID == DSD.source_package_name_id, TP.teamID.is_in(person.id for person in changed_by)) differences_changed_by = store.find( columns, differences_changed_by_conditions) differences = differences.intersection(differences_changed_by) differences = differences.order_by(SPN.name) def pre_iter_hook(rows): # Each row is (dsd, spn.name). Modify the results in place. rows[:] = (dsd for (dsd, spn_name) in rows) # Eager load everything to do with DSDs. return eager_load_dsds(rows) return DecoratedResultSet(differences, pre_iter_hook=pre_iter_hook)
def _get_person_celebrities(self, is_team): for name in ILaunchpadCelebrities.names(): attr = getattr(self.celebs, name) if IPerson.providedBy(attr) and attr.is_team == is_team: yield (name, attr)