def create(self, request, reviewers, *args, **kwargs):
        bugzilla = Bugzilla(get_bugzilla_api_key(request.user))
        new_reviewers = [u.strip() for u in reviewers.split(',') if u.strip()]
        invalid_reviewers = []
        for reviewer in new_reviewers:
            try:
                bugzilla.get_user_from_irc_nick(reviewer)
            except User.DoesNotExist:
                invalid_reviewers.append(reviewer)

        if invalid_reviewers:
            # Because this isn't called through Review Board's built-in
            # backbone system, it's dramatically simpler to return just the
            # intended error message instead of categorising the errors by
            # field.
            if len(invalid_reviewers) == 1:
                return INVALID_FORM_DATA.with_message(
                    "The reviewer '%s' was not found" % invalid_reviewers[0])
            else:
                return INVALID_FORM_DATA.with_message(
                    "The reviewers '%s' were not found"
                    % "', '".join(invalid_reviewers))

        return 200, {}
    def create(self, request, parent_request_id, reviewers, *args, **kwargs):
        try:
            parent_rr = ReviewRequest.objects.get(pk=parent_request_id)
        except ReviewRequest.DoesNotExist:
            return DOES_NOT_EXIST

        if not (parent_rr.is_accessible_by(request.user)
                or parent_rr.is_mutable_by(request.user)):
            return PERMISSION_DENIED

        if not is_parent(parent_rr):
            return NOT_PARENT

        # Validate and expand the new reviewer list.

        bugzilla = Bugzilla(get_bugzilla_api_key(request.user))
        child_reviewers = json.loads(reviewers)
        invalid_reviewers = []
        for child_rrid in child_reviewers:
            users = []
            for username in child_reviewers[child_rrid]:
                try:
                    users.append(bugzilla.get_user_from_irc_nick(username))
                except User.DoesNotExist:
                    invalid_reviewers.append(username)
            child_reviewers[child_rrid] = users

        if invalid_reviewers:
            # Because this isn't called through Review Board's built-in
            # backbone system, it's dramatically simpler to return just the
            # intended error message instead of categorising the errors by
            # field.
            if len(invalid_reviewers) == 1:
                return INVALID_FORM_DATA.with_message(
                    "The reviewer '%s' was not found" % invalid_reviewers[0])
            else:
                return INVALID_FORM_DATA.with_message(
                    "The reviewers '%s' were not found" %
                    "', '".join(invalid_reviewers))

        # Review Board only supports the submitter updating a review
        # request.  In order for this to work, we publish these changes
        # in Review Board under the review submitter's account, and
        # set an extra_data field which instructs our bugzilla
        # connector to use this request's user when adjusting flags.
        #
        # Updating the review request requires creating a draft and
        # publishing it, so we have to be careful to not overwrite
        # existing drafts.

        try:
            with transaction.atomic():
                for rr in itertools.chain([parent_rr],
                                          gen_child_rrs(parent_rr)):
                    if rr.get_draft() is not None:
                        return REVIEW_REQUEST_UPDATE_NOT_ALLOWED.with_message(
                            "Unable to update reviewers as the review "
                            "request has pending changes (the patch author "
                            "has a draft)")

                try:
                    for child_rr in gen_child_rrs(parent_rr):
                        if str(child_rr.id) in child_reviewers:
                            if not child_rr.is_accessible_by(request.user):
                                return PERMISSION_DENIED.with_message(
                                    "You do not have permission to update "
                                    "reviewers on review request %s" %
                                    child_rr.id)

                            draft = ReviewRequestDraft.create(child_rr)
                            draft.target_people.clear()
                            for user in child_reviewers[str(child_rr.id)]:
                                draft.target_people.add(user)

                    set_publish_as(parent_rr, request.user)
                    parent_rr_draft = ReviewRequestDraft.create(parent_rr)
                    update_parent_rr_reviewers(parent_rr_draft)
                    parent_rr.publish(user=parent_rr.submitter)
                finally:
                    clear_publish_as(parent_rr)

        except PublishError as e:
            logging.error("failed to update reviewers on %s: %s" %
                          (parent_rr.id, str(e)))
            return PUBLISH_ERROR.with_message(str(e))

        return 200, {}
    def create(self, request, parent_request_id, reviewers, *args, **kwargs):
        try:
            parent_rr = ReviewRequest.objects.get(pk=parent_request_id)
        except ReviewRequest.DoesNotExist:
            return DOES_NOT_EXIST

        if not (parent_rr.is_accessible_by(request.user)
                or parent_rr.is_mutable_by(request.user)):
            return PERMISSION_DENIED

        if not is_parent(parent_rr):
            return NOT_PARENT

        # Validate and expand the new reviewer list.

        bugzilla = Bugzilla(get_bugzilla_api_key(request.user))
        child_reviewers = json.loads(reviewers)
        invalid_reviewers = []
        for child_rrid in child_reviewers:
            users = []
            for username in child_reviewers[child_rrid]:
                try:
                    users.append(bugzilla.get_user_from_irc_nick(username))
                except User.DoesNotExist:
                    invalid_reviewers.append(username)
            child_reviewers[child_rrid] = users

        if invalid_reviewers:
            # Because this isn't called through Review Board's built-in
            # backbone system, it's dramatically simpler to return just the
            # intended error message instead of categorising the errors by
            # field.
            if len(invalid_reviewers) == 1:
                return INVALID_FORM_DATA.with_message(
                    "The reviewer '%s' was not found" % invalid_reviewers[0])
            else:
                return INVALID_FORM_DATA.with_message(
                    "The reviewers '%s' were not found"
                    % "', '".join(invalid_reviewers))

        # Review Board only supports the submitter updating a review
        # request.  In order for this to work, we publish these changes
        # in Review Board under the review submitter's account, and
        # set an extra_data field which instructs our bugzilla
        # connector to use this request's user when adjusting flags.
        #
        # Updating the review request requires creating a draft and
        # publishing it, so we have to be careful to not overwrite
        # existing drafts.

        try:
            with transaction.atomic():
                for rr in itertools.chain([parent_rr],
                                          gen_child_rrs(parent_rr)):
                    if rr.get_draft() is not None:
                        return REVIEW_REQUEST_UPDATE_NOT_ALLOWED.with_message(
                            "Unable to update reviewers as the review "
                            "request has pending changes (the patch author "
                            "has a draft)")

                try:
                    for child_rr in gen_child_rrs(parent_rr):
                        if str(child_rr.id) in child_reviewers:
                            if not child_rr.is_accessible_by(request.user):
                                return PERMISSION_DENIED.with_message(
                                    "You do not have permission to update "
                                    "reviewers on review request %s"
                                    % child_rr.id)

                            draft = ReviewRequestDraft.create(child_rr)
                            draft.target_people.clear()
                            for user in child_reviewers[str(child_rr.id)]:
                                draft.target_people.add(user)

                    set_publish_as(parent_rr, request.user)
                    parent_rr_draft = ReviewRequestDraft.create(parent_rr)
                    update_parent_rr_reviewers(parent_rr_draft)
                    parent_rr.publish(user=parent_rr.submitter)
                finally:
                    clear_publish_as(parent_rr)

        except PublishError as e:
                logging.error("failed to update reviewers on %s: %s"
                              % (parent_rr.id, str(e)))
                return PUBLISH_ERROR.with_message(str(e))

        return 200, {}