예제 #1
0
    async def _login(self, iteration=0):
        """Reads challenge from line, generate response and check if
        everything is okay"""

        challenge = await self._getblock()

        response = self._challenge_response(challenge)
        await self._putblock(response)
        prompt = await self._getblock()
        prompt = prompt.strip()

        if len(prompt) == 0:
            # Empty response, server is happy
            pass
        elif prompt == MSG_OK:
            pass
        elif prompt.startswith(MSG_INFO):
            logger.info("%s" % prompt[1:])

        elif prompt.startswith(MSG_ERROR):
            logger.error(prompt[1:])
            raise DatabaseError(prompt[1:])

        elif prompt.startswith(MSG_REDIRECT):
            # a redirect can contain multiple redirects, for now we only use
            # the first
            redirect = prompt.split()[0][1:].split(":")
            if redirect[1] == "merovingian":
                logger.debug("restarting authentication")
                if iteration <= 10:
                    await self._login(iteration=iteration + 1)
                else:
                    raise OperationalError("maximal number of redirects "
                                           "reached (10)")

            elif redirect[1] == "monetdb":
                self.hostname = redirect[2][2:]
                self.port, self.database = redirect[3].split("/")
                self.port = int(self.port)
                logger.info("redirect to monetdb://%s:%s/%s" %
                            (self.hostname, self.port, self.database))
                self.writer.close()
                await self.writer.wait_closed()
                self.connect(
                    hostname=self.hostname,
                    port=self.port,
                    username=self.username,
                    password=self.password,
                    database=self.database,
                    language=self.language,
                )

            else:
                raise ProgrammingError("unknown redirect: %s" % prompt)

        else:
            raise ProgrammingError("unknown state: %s" % prompt)
예제 #2
0
def convert(data):
    """
    Return the appropriate convertion function based upon the python type.
    """
    if type(data) in mapping_dict:
        return mapping_dict[type(data)](data)
    else:
        for type_, func in mapping:
            if issubclass(type(data), type_):
                return func(data)
    raise ProgrammingError("type %s not supported as value" % type(data))
예제 #3
0
def convert(data, type_code):
    """
    Calls the appropriate convertion function based upon the python type
    """

    # null values should always be replaced by None type
    if data == "nil":
        return None
    try:
        return mapping[type_code](data)
    except KeyError:
        raise ProgrammingError("type %s is not supported" % type_code)
예제 #4
0
def _extract_timezone(data):
    sign_symbol = data[-6]

    if sign_symbol == '+':
        sign = 1
    elif sign_symbol == '-':
        sign = -1
    else:
        raise ProgrammingError("no + or - in %s" % data)

    return data[:-6], datetime.timedelta(hours=sign * int(data[-5:-3]),
                                         minutes=sign * int(data[-2:]))
예제 #5
0
    async def cmd(self, operation):
        """ put a mapi command on the line"""
        logger.debug("executing command %s" % operation)

        if self.state != STATE_READY:
            raise (ProgrammingError, "Not connected")

        if not bool(re.match("create|drop", operation, re.I)):
            await self._putblock(operation)
            response = await self._getblock()
        else:
            await lock.acquire()
            try:
                await self._putblock(operation)
                response = await self._getblock()
            finally:
                lock.release()
        if not len(response):
            return ""
        elif response.startswith(MSG_OK):
            return response[3:].strip() or ""
        if response == MSG_MORE:
            # tell server it isn't going to get more
            return self.cmd("")
        # print(operation+": "+response)
        # If we are performing an update test for errors such as a failed
        # transaction.

        # We are splitting the response into lines and checking each one if it
        # starts with MSG_ERROR. If this is the case, find which line records
        # the error and use it to call handle_error.
        if response[:2] == MSG_QUPDATE:
            lines = response.split("\n")
            if any([l.startswith(MSG_ERROR) for l in lines]):
                index = next(i for i, v in enumerate(lines)
                             if v.startswith(MSG_ERROR))
                exception, msg = handle_error(lines[index][1:])
                raise exception('\n'.join(lines))

        if response[0] in [MSG_Q, MSG_HEADER, MSG_TUPLE]:
            return response
        elif response[0] == MSG_ERROR:
            exception, msg = handle_error(response[1:])
            raise exception(msg)
        elif response[0] == MSG_INFO:
            logger.info("%s" % (response[1:]))
        elif self.language == "control" and not self.hostname:
            if response.startswith("OK"):
                return response[2:].strip() or ""
            else:
                return response
        else:
            raise ProgrammingError("unknown state: %s" % response)
예제 #6
0
    def read_response(self):
        response = self._getblock()
        if not len(response):
            return ""
        if response.startswith(MSG_OK):
            return response[3:].strip() or ""
        if response == MSG_MORE:
            # tell server it isn't going to get more
            return self.cmd("")

        # If we are performing an update test for errors such as a failed
        # transaction.

        # We are splitting the response into lines and checking each one if it
        # starts with MSG_ERROR. If this is the case, find which line records
        # the error and use it to call handle_error.
        if response[:2] == MSG_QUPDATE:
            lines = response.split(b'\n')
            if any([l.startswith(MSG_ERROR) for l in lines]):
                index = next(i for i, v in enumerate(lines)
                             if v.startswith(MSG_ERROR))
                exception, string = handle_error(lines[index][1:])
                raise exception(string)

        if response[0:1] in [
                MSG_Q, MSG_HEADER, MSG_TUPLE, MSG_NEW_RESULT_HEADER,
                MSG_INITIAL_RESULT_CHUNK, MSG_RESULT_CHUNK
        ]:
            return response
        elif response[0:1] == MSG_ERROR:
            exception, string = handle_error(response[1:])
            raise exception(string)
        elif response[0:1] == MSG_INFO:
            logger.info("%s" % (response[1:]))
        elif self.language == 'control' and not self.hostname:
            if response.startswith("OK"):
                return response[2:].strip() or ""
            else:
                return response
        else:
            raise ProgrammingError("unknown state: %s" % response)
예제 #7
0
 def _command(self, operation):
     if self._mapi.state != mapi.STATE_READY:
         raise ProgrammingError("Not connected")
     self._mapi._putblock(operation)