def _read_response()

in redis/_parsers/resp3.py [0:0]


    def _read_response(self, disable_decoding=False, push_request=False):
        raw = self._buffer.readline()
        if not raw:
            raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR)

        byte, response = raw[:1], raw[1:]

        # server returned an error
        if byte in (b"-", b"!"):
            if byte == b"!":
                response = self._buffer.read(int(response))
            response = response.decode("utf-8", errors="replace")
            error = self.parse_error(response)
            # if the error is a ConnectionError, raise immediately so the user
            # is notified
            if isinstance(error, ConnectionError):
                raise error
            # otherwise, we're dealing with a ResponseError that might belong
            # inside a pipeline response. the connection's read_response()
            # and/or the pipeline's execute() will raise this error if
            # necessary, so just return the exception instance here.
            return error
        # single value
        elif byte == b"+":
            pass
        # null value
        elif byte == b"_":
            return None
        # int and big int values
        elif byte in (b":", b"("):
            return int(response)
        # double value
        elif byte == b",":
            return float(response)
        # bool value
        elif byte == b"#":
            return response == b"t"
        # bulk response
        elif byte == b"$":
            response = self._buffer.read(int(response))
        # verbatim string response
        elif byte == b"=":
            response = self._buffer.read(int(response))[4:]
        # array response
        elif byte == b"*":
            response = [
                self._read_response(disable_decoding=disable_decoding)
                for _ in range(int(response))
            ]
        # set response
        elif byte == b"~":
            # redis can return unhashable types (like dict) in a set,
            # so we return sets as list, all the time, for predictability
            response = [
                self._read_response(disable_decoding=disable_decoding)
                for _ in range(int(response))
            ]
        # map response
        elif byte == b"%":
            # We cannot use a dict-comprehension to parse stream.
            # Evaluation order of key:val expression in dict comprehension only
            # became defined to be left-right in version 3.8
            resp_dict = {}
            for _ in range(int(response)):
                key = self._read_response(disable_decoding=disable_decoding)
                resp_dict[key] = self._read_response(
                    disable_decoding=disable_decoding, push_request=push_request
                )
            response = resp_dict
        # push response
        elif byte == b">":
            response = [
                self._read_response(
                    disable_decoding=disable_decoding, push_request=push_request
                )
                for _ in range(int(response))
            ]
            response = self.handle_push_response(
                response, disable_decoding, push_request
            )
            if not push_request:
                return self._read_response(
                    disable_decoding=disable_decoding, push_request=push_request
                )
            else:
                return response
        else:
            raise InvalidResponse(f"Protocol Error: {raw!r}")

        if isinstance(response, bytes) and disable_decoding is False:
            response = self.encoder.decode(response)
        return response