<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def perspective_commandline(self, op, bb_username, bb_password, ids, info):
 """ This performs the requested operations from the `buildbot user` call by calling the proper buildbot.db.users methods based on the operation. It yields a deferred instance with the results from the database methods. @param op: operation to perform (add, remove, update, get) @type op: string @param bb_username: username portion of auth credentials @type bb_username: string @param bb_password: hashed password portion of auth credentials @type bb_password: hashed string @param ids: user identifiers used to find existing users @type ids: list of strings or None @param info: type/value pairs for each user that will be added or updated in the database @type info: list of dictionaries or None @returns: results from db.users methods via deferred """

        log.msg("perspective_commandline called")
        results = []

        # pylint: disable=too-many-nested-blocks
        if ids:
            for user in ids:
                # get identifier, guaranteed to be in user from checks
                # done in C{scripts.runner}
                uid = yield self.master.db.users.identifierToUid(
                    identifier=user)

                result = None
                if op == 'remove':
                    if uid:
                        yield self.master.db.users.removeUser(uid)
                        result = user
                    else:
                        log.msg("Unable to find uid for identifier %s" % user)
                elif op == 'get':
                    if uid:
                        result = yield self.master.db.users.getUser(uid)
                    else:
                        log.msg("Unable to find uid for identifier %s" % user)

                results.append(result)
        else:
            for user in info:
                # get identifier, guaranteed to be in user from checks
                # done in C{scripts.runner}
                ident = user.pop('identifier')
                uid = yield self.master.db.users.identifierToUid(
                    identifier=ident)

                # if only an identifier was in user, we're updating only
                # the bb_username and bb_password.
                if not user:
                    if uid:
                        result = yield self.master.db.users.updateUser(
                            uid=uid,
                            identifier=ident,
                            bb_username=bb_username,
                            bb_password=bb_password)
                        results.append(ident)
                    else:
                        log.msg("Unable to find uid for identifier %s"
                                % user)
                else:
                    # when adding, we update the user after the first attr
                    once_through = False
                    for attr in user:
                        result = None
                        if op == 'update' or once_through:
                            if uid:
                                result = yield self.master.db.users.updateUser(
                                    uid=uid,
                                    identifier=ident,
                                    bb_username=bb_username,
                                    bb_password=bb_password,
                                    attr_type=attr,
                                    attr_data=user[attr])
                            else:
                                log.msg("Unable to find uid for identifier %s"
                                        % user)
                        elif op == 'add':
                            result = yield self.master.db.users.findUserByAttr(
                                identifier=ident,
                                attr_type=attr,
                                attr_data=user[attr])
                            once_through = True
                        results.append(ident)

                        # result is None from updateUser calls
                        if result:
                            results.append(result)
                            uid = result
        results = self.formatResults(op, results)
        return results