def execute(self, bug, current_event): """See IEmailCommand.""" if isinstance(bug, CreateBugParams): # Return the input because there is not yet a bug to # unsubscribe too. return bug, current_event string_args = list(self.string_args) if len(string_args) == 1: person = get_person_or_team(string_args.pop()) elif len(string_args) == 0: # Subscribe the sender of the email. person = getUtility(ILaunchBag).user else: raise EmailProcessingError( get_error_message('unsubscribe-too-many-arguments.txt', error_templates=error_templates)) if bug.isSubscribed(person): try: bug.unsubscribe(person, getUtility(ILaunchBag).user) except UserCannotUnsubscribePerson: raise EmailProcessingError( get_error_message('user-cannot-unsubscribe.txt', error_templates=error_templates, person=person.displayname)) if bug.isSubscribedToDupes(person): bug.unsubscribeFromDupes(person, person) return bug, current_event
def execute(self, context): """Extract the vote and tags from the args.""" if len(self.string_args) == 0: raise EmailProcessingError( get_error_message('num-arguments-mismatch.txt', command_name='review', num_arguments_expected='one or more', num_arguments_got='0')) vote_string = self.string_args[0] vote_tag_list = self.string_args[1:] try: context.vote = CodeReviewVote.items[vote_string.upper()] except KeyError: # If the word doesn't match, check aliases that we allow. context.vote = self._vote_alias.get(vote_string) if context.vote is None: # Replace the _ with - in the names of the items. # Slightly easier to type and read. valid_votes = ', '.join( sorted(v.name.lower().replace('_', '-') for v in CodeReviewVote.items.items)) raise EmailProcessingError( get_error_message('dbschema-command-wrong-argument.txt', command_name='review', arguments=valid_votes, example_argument='needs-fixing')) if len(vote_tag_list) > 0: context.vote_tags = ' '.join(vote_tag_list)
def execute(self, context, current_event): """See IEmailCommand.""" if isinstance(context, CreateBugParams): # No one intentially reports a duplicate bug. Bug email commands # support CreateBugParams, so in this case, just return. return context, current_event self._ensureNumberOfArguments() [bug_id] = self.string_args if bug_id != 'no': try: bug = getUtility(IBugSet).getByNameOrID(bug_id) except NotFoundError: raise EmailProcessingError( get_error_message('no-such-bug.txt', error_templates=error_templates, bug_id=bug_id)) else: # 'no' is a special value for unmarking a bug as a duplicate. bug = None duplicate_field = IBug['duplicateof'].bind(context) try: duplicate_field.validate(bug) except ValidationError as error: raise EmailProcessingError(error.doc()) context_snapshot = Snapshot(context, providing=providedBy(context)) context.markAsDuplicate(bug) current_event = ObjectModifiedEvent(context, context_snapshot, 'duplicateof') notify(current_event) return bug, current_event
def execute(self, context): """Update the status of the merge proposal.""" # Only accepts approved, and rejected for now. self._ensureNumberOfArguments() new_status = self.string_args[0].lower() # Grab the latest rev_id from the source branch. # This is what the browser code does right now. rev_id = context.merge_proposal.source_branch.last_scanned_id try: if new_status in ('approved', 'approve'): if context.vote is None: context.vote = CodeReviewVote.APPROVE context.merge_proposal.approveBranch(context.user, rev_id) elif new_status in ('rejected', 'reject'): if context.vote is None: context.vote = CodeReviewVote.DISAPPROVE context.merge_proposal.rejectBranch(context.user, rev_id) else: raise EmailProcessingError( get_error_message('dbschema-command-wrong-argument.txt', command_name=self.name, arguments='approved, rejected', example_argument='approved')) except (UserNotBranchReviewer, Unauthorized): raise EmailProcessingError( get_error_message( 'user-not-reviewer.txt', error_templates=error_templates, command_name=self.name, target=context.merge_proposal.target_branch.bzr_identity))
def execute(self, bug, current_event): """See `IEmailCommand`.""" # Tags are always lowercase. string_args = [arg.lower() for arg in self.string_args] if bug.tags is None: tags = [] else: tags = list(bug.tags) for arg in string_args: # Are we adding or removing a tag? if arg.startswith('-'): remove = True tag = arg[1:] else: remove = False tag = arg # Tag must be a valid name. if not valid_name(tag): raise EmailProcessingError( get_error_message('invalid-tag.txt', error_templates=error_templates, tag=tag)) if remove: try: tags.remove(tag) except ValueError: raise EmailProcessingError( get_error_message('unassigned-tag.txt', error_templates=error_templates, tag=tag)) else: tags.append(arg) bug.tags = tags return bug, current_event
def execute(self, parsed_msg, filealias): """See IBugEmailCommand.""" self._ensureNumberOfArguments() bugid = self.string_args[0] if bugid == 'new': message = getUtility(IMessageSet).fromEmail( parsed_msg.as_string(), owner=getUtility(ILaunchBag).user, filealias=filealias, parsed_message=parsed_msg) description = message.text_contents if description.strip() == '': # The report for a new bug must contain an affects command, # since the bug must have at least one task raise EmailProcessingError(get_error_message( 'no-affects-target-on-submit.txt', error_templates=error_templates), stop_processing=True) # Check the message validator. validator = IBugAddForm['comment'].validate try: validator(description) except TooLong: raise EmailProcessingError( 'The description is too long. If you have lots of ' 'text to add, use an attachment instead.', stop_processing=True) except ValidationError as e: # More a just in case than any real expectation of getting # something. raise EmailProcessingError(str(e), stop_processing=True) params = CreateBugParams(msg=message, title=message.title, owner=getUtility(ILaunchBag).user) return params, None else: try: bugid = int(bugid) except ValueError: raise EmailProcessingError( get_error_message('bug-argument-mismatch.txt', error_templates=error_templates)) try: bug = getUtility(IBugSet).get(bugid) except NotFoundError: bug = None if bug is None or not check_permission('launchpad.View', bug): raise EmailProcessingError( get_error_message('no-such-bug.txt', error_templates=error_templates, bug_id=bugid)) return bug, None
def execute(self, bug, current_event): """See IEmailCommand.""" if bug is None: raise EmailProcessingError(get_error_message( 'command-with-no-bug.txt', error_templates=error_templates), stop_processing=True) # Do a manual control of the number of arguments, in order to # provide a better error message than the default one. if len(self.string_args) > 1: raise EmailProcessingError( get_error_message('summary-too-many-arguments.txt', error_templates=error_templates)) if isinstance(bug, CreateBugParams): bug.title = self.string_args[0] return bug, current_event return EditEmailCommand.execute(self, bug, current_event)
def setAttributeValue(self, context, attr_name, attr_value): """See EmailCommand.""" user = getUtility(ILaunchBag).user if not context.canTransitionToStatus(attr_value, user): raise EmailProcessingError( 'The status cannot be changed to %s because you are not ' 'the maintainer, driver or bug supervisor for %s.' % (attr_value.name.lower(), context.pillar.displayname)) context.transitionToStatus(attr_value, user)
def execute(self, bug, current_event): """See IEmailCommand.""" [cve_sequence] = self.string_args cve = getUtility(ICveSet)[cve_sequence] if cve is None: raise EmailProcessingError('Launchpad can\'t find the CVE "%s".' % cve_sequence) if isinstance(bug, CreateBugParams): bug.cve = cve return bug, current_event bug.linkCVE(cve, getUtility(ILaunchBag).user) return bug, current_event
def _ensureNumberOfArguments(self): """Check that the number of arguments is correct. Raise an EmailProcessingError """ if self._numberOfArguments is not None: num_arguments_got = len(self.string_args) if self._numberOfArguments != num_arguments_got: raise EmailProcessingError( get_error_message( 'num-arguments-mismatch.txt', command_name=self.name, num_arguments_expected=self._numberOfArguments, num_arguments_got=num_arguments_got))
def execute(self, context, current_event): """See `IEmailCommand`. Much of this method was lifted from `EditEmailCommand.execute`. """ # Parse args. self._ensureNumberOfArguments() [security_flag] = self.string_args if security_flag == 'yes': security_related = True elif security_flag == 'no': security_related = False else: raise EmailProcessingError(get_error_message( 'security-parameter-mismatch.txt', error_templates=error_templates), stop_processing=True) if isinstance(context, CreateBugParams): if security_related: context.information_type = InformationType.PRIVATESECURITY return context, current_event # Take a snapshot. edited = False edited_fields = set() if IObjectModifiedEvent.providedBy(current_event): context_snapshot = current_event.object_before_modification edited_fields.update(current_event.edited_fields) else: context_snapshot = Snapshot(context, providing=providedBy(context)) # Apply requested changes. user = getUtility(ILaunchBag).user if security_related: if context.setPrivate(True, user): edited = True edited_fields.add('private') if context.security_related != security_related: context.setSecurityRelated(security_related, user) edited = True edited_fields.add('security_related') # Update the current event. if edited and not IObjectCreatedEvent.providedBy(current_event): current_event = ObjectModifiedEvent(context, context_snapshot, list(edited_fields)) return context, current_event
def convertArguments(self, context): """See EmailCommand.""" user = getUtility(ILaunchBag).user milestone_name = self.string_args[0] if milestone_name == '-': # Remove milestone return {self.name: None} elif context.userHasBugSupervisorPrivileges(user): milestone = context.pillar.getMilestone(milestone_name) if milestone is None: raise EmailProcessingError( "The milestone %s does not exist for %s. Note that " "milestones are not automatically created from emails; " "they must be created on the website." % (milestone_name, context.pillar.title)) else: return {self.name: milestone} else: raise EmailProcessingError( "You do not have permission to set the milestone for %s. " "Only owners, drivers and bug supervisors may assign " "milestones." % (context.pillar.title, ))
def parseReviewRequest(klass, op_name, string_args): if len(string_args) == 0: raise EmailProcessingError( get_error_message('num-arguments-mismatch.txt', command_name=op_name, num_arguments_expected='one or more', num_arguments_got='0')) # Pop the first arg as the reviewer. reviewer = get_person_or_team(string_args.pop(0)) if len(string_args) > 0: review_tags = ' '.join(string_args) else: review_tags = None return (reviewer, review_tags)
def execute(self, context, current_event): """See `IEmailCommand`. Much of this method has been lifted from `EditEmailCommand.execute`. """ # Parse args. self._ensureNumberOfArguments() private_arg = self.string_args[0] if private_arg == 'yes': private = True elif private_arg == 'no': private = False else: raise EmailProcessingError(get_error_message( 'private-parameter-mismatch.txt', error_templates=error_templates), stop_processing=True) if isinstance(context, CreateBugParams): if private: # "private yes" forces it to Private if it isn't already. if (context.information_type is None or context.information_type in PUBLIC_INFORMATION_TYPES): context.information_type = InformationType.USERDATA elif context.information_type != InformationType.PRIVATESECURITY: # "private no" forces it to Public, except we always # force new security bugs to be private. context.information_type = InformationType.PUBLIC return context, current_event # Snapshot. edited_fields = set() if IObjectModifiedEvent.providedBy(current_event): context_snapshot = current_event.object_before_modification edited_fields.update(current_event.edited_fields) else: context_snapshot = Snapshot(context, providing=providedBy(context)) # Apply requested changes. edited = context.setPrivate(private, getUtility(ILaunchBag).user) # Update the current event. if edited and not IObjectCreatedEvent.providedBy(current_event): edited_fields.add('private') current_event = ObjectModifiedEvent(context, context_snapshot, list(edited_fields)) return context, current_event
def get_person_or_team(person_name_or_email): """Get the `Person` from the vocabulary. :raises: EmailProcessingError if person not found. """ # Avoid circular import problems. from lp.registry.vocabularies import ValidPersonOrTeamVocabulary valid_person_vocabulary = ValidPersonOrTeamVocabulary() try: person_term = valid_person_vocabulary.getTermByToken( person_name_or_email) except LookupError: raise EmailProcessingError( get_error_message( 'no-such-person.txt', name_or_email=person_name_or_email)) return person_term.value
def execute(self, bug, current_event): """See IEmailCommand.""" string_args = list(self.string_args) # preserve compatibility with the original command that let you # specify a subscription type if len(string_args) == 2: # Remove the subscription_name string_args.pop() user = getUtility(ILaunchBag).user if len(string_args) == 1: person = get_person_or_team(string_args.pop()) elif len(string_args) == 0: # Subscribe the sender of the email. person = user else: raise EmailProcessingError( get_error_message('subscribe-too-many-arguments.txt', error_templates=error_templates)) if isinstance(bug, CreateBugParams): if len(bug.subscribers) == 0: bug.subscribers = [person] else: bug.subscribers.append(person) return bug, current_event if bug.isSubscribed(person): # but we still need to find the subscription for bugsubscription in bug.subscriptions: if bugsubscription.person == person: break else: bugsubscription = bug.subscribe(person, user) notify(ObjectCreatedEvent(bugsubscription)) return bug, current_event
def convertArguments(self, context): """See EmailCommand.""" item_name = self.string_args[0] dbschema = self.dbschema try: dbitem = dbschema.items[item_name.upper()] except KeyError: dbitem = None if dbitem is None or dbitem.name == 'UNKNOWN': possible_items = [ item.name.lower() for item in dbschema.items if item.name != 'UNKNOWN' ] possible_values = ', '.join(possible_items) raise EmailProcessingError( get_error_message('dbschema-command-wrong-argument.txt', command_name=self.name, arguments=possible_values, example_argument=possible_items[0])) return {self.name: dbitem}
def execute(self, bug, bug_event): """See IEmailCommand.""" if bug is None: raise EmailProcessingError(get_error_message( 'command-with-no-bug.txt', error_templates=error_templates), stop_processing=True) string_args = list(self.string_args) try: path = string_args.pop(0) except IndexError: raise EmailProcessingError(get_error_message( 'affects-no-arguments.txt', error_templates=error_templates), stop_processing=True) try: bug_target = self.getBugTarget(path) except BugTargetNotFound as error: raise EmailProcessingError(unicode(error), stop_processing=True) event = None if isinstance(bug, CreateBugParams): # Enough information has been gathered to create a new bug. # If a series task is requested, create the non-series # equivalent here. The series will be nominated/targeted in # the remainder of the method. if ISeriesBugTarget.providedBy(bug_target): bug.target = bug_target.bugtarget_parent else: bug.target = bug_target bug, bug_event = getUtility(IBugSet).createBug(bug, notify_event=False) event = ObjectCreatedEvent(bug.bugtasks[0]) # Continue because the bug_target may be a subordinate bugtask. bugtask = bug.getBugTask(bug_target) if (bugtask is None and IDistributionSourcePackage.providedBy(bug_target)): # If there's a distribution task with no source package, use # that one. bugtask = bug.getBugTask(bug_target.distribution) if bugtask is not None: bugtask_before_edit = Snapshot(bugtask, providing=IBugTask) bugtask.transitionToTarget(bug_target, getUtility(ILaunchBag).user) event = ObjectModifiedEvent(bugtask, bugtask_before_edit, ['sourcepackagename']) if bugtask is None: try: bugtask = self._create_bug_task(bug, bug_target) except IllegalTarget as e: raise EmailProcessingError(get_error_message( 'cannot-add-task.txt', error_templates=error_templates, bug_id=bug.id, target_name=bug_target.name, reason=e[0]), stop_processing=True) event = ObjectCreatedEvent(bugtask) return bugtask, event, bug_event
def execute(self, context, current_event): raise EmailProcessingError( get_error_message('bug-importance.txt', error_templates=error_templates, argument=self.name))