Example #1
0
    def scan(self, cursor=0, pattern=None, count=None):
        """The :meth:`~tredis.RedisClient.scan` command and the closely related
        commands :meth:`~tredis.RedisClient.sscan`,
        :meth:`~tredis.RedisClient.hscan` and :meth:`~tredis.RedisClient.zscan`
        are used in order to incrementally iterate over a collection of
        elements.

        - :meth:`~tredis.RedisClient.scan` iterates the set of keys in the
          currently selected Redis database.
        - :meth:`~tredis.RedisClient.sscan` iterates elements of Sets types.
        - :meth:`~tredis.RedisClient.hscan` iterates fields of Hash types and
          their associated values.
        - :meth:`~tredis.RedisClient.zscan` iterates elements of Sorted Set
          types and their associated scores.

        **Basic usage**

        :meth:`~tredis.RedisClient.scan` is a cursor based iterator.
        This means that at every call of the command, the server returns an
        updated cursor that the user needs to use as the cursor argument in
        the next call.

        An iteration starts when the cursor is set to ``0``, and terminates
        when the cursor returned by the server is ``0``.

        For more information on :meth:`~tredis.RedisClient.scan`,
        visit the `Redis docs on scan <http://redis.io/commands/scan>`_.

        .. note::

           **Time complexity**: ``O(1)`` for every call. ``O(N)`` for a
           complete iteration, including enough command calls for the cursor to
           return back to ``0``. ``N`` is the number of elements inside the
           collection.

        :param int cursor: The server specified cursor value or ``0``
        :param pattern: An optional pattern to apply for key matching
        :type pattern: :class:`str`, :class:`bytes`
        :param int count: An optional amount of work to perform in the scan
        :rtype: int, list
        :returns: A tuple containing the cursor and the list of keys
        :raises: :exc:`~tredis.exceptions.RedisError`

        """

        def format_response(value):
            """Format the response from redis

            :param tuple value: The return response from redis
            :rtype: tuple(int, list)

            """
            return int(value[0]), value[1]

        command = [b'SCAN', ascii(cursor).encode('ascii')]
        if pattern:
            command += [b'MATCH', pattern]
        if count:
            command += [b'COUNT', ascii(count).encode('ascii')]
        return self._execute(command, format_callback=format_response)
Example #2
0
File: keys.py Project: den-t/tredis
    def wait(self, num_slaves, timeout=0):
        """his command blocks the current client until all the previous write
        commands are successfully transferred and acknowledged by at least the
        specified number of slaves. If the timeout, specified in milliseconds,
        is reached, the command returns even if the specified number of slaves
        were not yet reached.

        The command will always return the number of slaves that acknowledged
        the write commands sent before the :meth:`~tredis.RedisClient.wait`
        command, both in the case where the specified number of slaves are
        reached, or when the timeout is reached.

        .. note::

           **Time complexity**: ``O(1)``

        :param int num_slaves: Number of slaves to acknowledge previous writes
        :param int timeout: Timeout in milliseconds
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'WAIT', ascii(num_slaves).encode('ascii'),
                   ascii(timeout).encode('ascii')]
        return self._execute(command)
Example #3
0
    def set(self, key, value, ex=None, px=None, nx=False, xx=False):
        """Set key to hold the string value. If key already holds a value, it
        is overwritten, regardless of its type. Any previous time to live
        associated with the key is discarded on successful
        :meth:`~tredis.RedisClient.set` operation.

        If the value is not one of :class:`str`, :class:`bytes`, or
        :class:`int`, a :exc:`ValueError` will be raised.

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to remove
        :type key: :class:`str`, :class:`bytes`
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`, :class:`int`
        :param int ex: Set the specified expire time, in seconds
        :param int px: Set the specified expire time, in milliseconds
        :param bool nx: Only set the key if it does not already exist
        :param bool xx: Only set the key if it already exist
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`
        :raises: :exc:`ValueError`

        """
        command = [b'SET', key, value]
        if ex:
            command += [b'EX', ascii(ex).encode('ascii')]
        if px:
            command += [b'PX', ascii(px).encode('ascii')]
        if nx:
            command.append(b'NX')
        if xx:
            command.append(b'XX')
        return self._execute(command, b'OK')
Example #4
0
    def wait(self, num_slaves, timeout=0):
        """his command blocks the current client until all the previous write
        commands are successfully transferred and acknowledged by at least the
        specified number of slaves. If the timeout, specified in milliseconds,
        is reached, the command returns even if the specified number of slaves
        were not yet reached.

        The command will always return the number of slaves that acknowledged
        the write commands sent before the :meth:`~tredis.RedisClient.wait`
        command, both in the case where the specified number of slaves are
        reached, or when the timeout is reached.

        .. note::

           **Time complexity**: ``O(1)``

        :param int num_slaves: Number of slaves to acknowledge previous writes
        :param int timeout: Timeout in milliseconds
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [
            b'WAIT',
            ascii(num_slaves).encode('ascii'),
            ascii(timeout).encode('ascii')
        ]
        return self._execute(command)
Example #5
0
    def getrange(self, key, start, end):
        """Returns the bit value at offset in the string value stored at key.

        When offset is beyond the string length, the string is assumed to be a
        contiguous space with 0 bits. When key does not exist it is assumed to
        be an empty string, so offset is always out of range and the value is
        also assumed to be a contiguous space with 0 bits.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(N)`` where ``N`` is the length of
           the returned string. The complexity is ultimately determined by the
           returned length, but because creating a substring from an existing
           string is very cheap, it can be considered ``O(1)`` for small
           strings.

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param int start: The start position to evaluate in the string
        :param int end: The end position to evaluate in the string
        :rtype: bytes|None
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'GETRANGE', key, ascii(start), ascii(end)])
Example #6
0
    def bitcount(self, key, start=None, end=None):
        """Count the number of set bits (population counting) in a string.

        By default all the bytes contained in the string are examined. It is
        possible to specify the counting operation only in an interval passing
        the additional arguments start and end.

        Like for the :meth:`~tredis.RedisClient.getrange` command start and
        end can contain negative values in order to index bytes starting from
        the end of the string, where ``-1`` is the last byte, ``-2`` is the
        penultimate, and so forth.

        Non-existent keys are treated as empty strings, so the command will
        return zero.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(N)``

        :param key: The key to get
        :type key: :class:`str`, :class:`bytes`
        :param int start: The start position to evaluate in the string
        :param int end: The end position to evaluate in the string
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`, :exc:`ValueError`

        """
        command = [b'BITCOUNT', key]
        if start is not None and end is None:
            raise ValueError('Can not specify start without an end')
        elif start is None and end is not None:
            raise ValueError('Can not specify start without an end')
        elif start is not None and end is not None:
            command += [ascii(start), ascii(end)]
        return self._execute(command)
Example #7
0
    def set(self, key, value, ex=None, px=None, nx=False, xx=False):
        """Set key to hold the string value. If key already holds a value, it
        is overwritten, regardless of its type. Any previous time to live
        associated with the key is discarded on successful
        :meth:`~tredis.RedisClient.set` operation.

        If the value is not one of :class:`str`, :class:`bytes`, or
        :class:`int`, a :exc:`ValueError` will be raised.

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to remove
        :type key: :class:`str`, :class:`bytes`
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`, :class:`int`
        :param int ex: Set the specified expire time, in seconds
        :param int px: Set the specified expire time, in milliseconds
        :param bool nx: Only set the key if it does not already exist
        :param bool xx: Only set the key if it already exist
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`
        :raises: :exc:`ValueError`

        """
        command = [b'SET', key, value]
        if ex:
            command += [b'EX', ascii(ex).encode('ascii')]
        if px:
            command += [b'PX', ascii(px).encode('ascii')]
        if nx:
            command.append(b'NX')
        if xx:
            command.append(b'XX')
        return self._execute(command, b'OK')
Example #8
0
    def getrange(self, key, start, end):
        """Returns the bit value at offset in the string value stored at key.

        When offset is beyond the string length, the string is assumed to be a
        contiguous space with 0 bits. When key does not exist it is assumed to
        be an empty string, so offset is always out of range and the value is
        also assumed to be a contiguous space with 0 bits.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(N)`` where ``N`` is the length of
           the returned string. The complexity is ultimately determined by the
           returned length, but because creating a substring from an existing
           string is very cheap, it can be considered ``O(1)`` for small
           strings.

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param int start: The start position to evaluate in the string
        :param int end: The end position to evaluate in the string
        :rtype: bytes|None
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'GETRANGE', key, ascii(start), ascii(end)])
Example #9
0
    def bitcount(self, key, start=None, end=None):
        """Count the number of set bits (population counting) in a string.

        By default all the bytes contained in the string are examined. It is
        possible to specify the counting operation only in an interval passing
        the additional arguments start and end.

        Like for the :meth:`~tredis.RedisClient.getrange` command start and
        end can contain negative values in order to index bytes starting from
        the end of the string, where ``-1`` is the last byte, ``-2`` is the
        penultimate, and so forth.

        Non-existent keys are treated as empty strings, so the command will
        return zero.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(N)``

        :param key: The key to get
        :type key: :class:`str`, :class:`bytes`
        :param int start: The start position to evaluate in the string
        :param int end: The end position to evaluate in the string
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`, :exc:`ValueError`

        """
        command = [b'BITCOUNT', key]
        if start is not None and end is None:
            raise ValueError('Can not specify start without an end')
        elif start is None and end is not None:
            raise ValueError('Can not specify start without an end')
        elif start is not None and end is not None:
            command += [ascii(start), ascii(end)]
        return self._execute(command)
Example #10
0
    def scan(self, cursor=0, pattern=None, count=None):
        """The :meth:`~tredis.RedisClient.scan` command and the closely related
        commands :meth:`~tredis.RedisClient.sscan`,
        :meth:`~tredis.RedisClient.hscan` and :meth:`~tredis.RedisClient.zscan`
        are used in order to incrementally iterate over a collection of
        elements.

        - :meth:`~tredis.RedisClient.scan` iterates the set of keys in the
          currently selected Redis database.
        - :meth:`~tredis.RedisClient.sscan` iterates elements of Sets types.
        - :meth:`~tredis.RedisClient.hscan` iterates fields of Hash types and
          their associated values.
        - :meth:`~tredis.RedisClient.zscan` iterates elements of Sorted Set
          types and their associated scores.

        **Basic usage**

        :meth:`~tredis.RedisClient.scan` is a cursor based iterator.
        This means that at every call of the command, the server returns an
        updated cursor that the user needs to use as the cursor argument in
        the next call.

        An iteration starts when the cursor is set to ``0``, and terminates
        when the cursor returned by the server is ``0``.

        For more information on :meth:`~tredis.RedisClient.scan`,
        visit the `Redis docs on scan <http://redis.io/commands/scan>`_.

        .. note::

           **Time complexity**: ``O(1)`` for every call. ``O(N)`` for a
           complete iteration, including enough command calls for the cursor to
           return back to ``0``. ``N`` is the number of elements inside the
           collection.

        :param int cursor: The server specified cursor value or ``0``
        :param pattern: An optional pattern to apply for key matching
        :type pattern: :class:`str`, :class:`bytes`
        :param int count: An optional amount of work to perform in the scan
        :rtype: int, list
        :returns: A tuple containing the cursor and the list of keys
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        def format_response(value):
            """Format the response from redis

            :param tuple value: The return response from redis
            :rtype: tuple(int, list)

            """
            return int(value[0]), value[1]

        command = [b'SCAN', ascii(cursor).encode('ascii')]
        if pattern:
            command += [b'MATCH', pattern]
        if count:
            command += [b'COUNT', ascii(count).encode('ascii')]
        print(command)
        return self._execute(command, format_callback=format_response)
Example #11
0
    def bitpos(self, key, bit, start=None, end=None):
        """Return the position of the first bit set to ``1`` or ``0`` in a
        string.

        The position is returned, thinking of the string as an array of bits
        from left to right, where the first byte's most significant bit is at
        position 0, the second byte's most significant bit is at position
        ``8``, and so forth.

        The same bit position convention is followed by
        :meth:`~tredis.RedisClient.getbit` and
        :meth:`~tredis.RedisClient.setbit`.

        By default, all the bytes contained in the string are examined. It is
        possible to look for bits only in a specified interval passing the
        additional arguments start and end (it is possible to just pass start,
        the operation will assume that the end is the last byte of the string.
        However there are semantic differences as explained later). The range
        is interpreted as a range of bytes and not a range of bits, so
        ``start=0`` and ``end=2`` means to look at the first three bytes.

        Note that bit positions are returned always as absolute values starting
        from bit zero even when start and end are used to specify a range.

        Like for the :meth:`~tredis.RedisClient.getrange` command start and
        end can contain negative values in order to index bytes starting from
        the end of the string, where ``-1`` is the last byte, ``-2`` is the
        penultimate, and so forth.

        Non-existent keys are treated as empty strings.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(N)``

        :param key: The key to get
        :type key: :class:`str`, :class:`bytes`
        :param int bit: The bit value to search for (``1`` or ``0``)
        :param int start: The start position to evaluate in the string
        :param int end: The end position to evaluate in the string
        :returns: The position of the first bit set to ``1`` or ``0``
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`, :exc:`ValueError`

        """
        if 0 < bit > 1:
            raise ValueError('bit must be 1 or 0, not {}'.format(bit))
        command = [b'BITPOS', key, ascii(bit)]
        if start is not None and end is None:
            raise ValueError('Can not specify start without an end')
        elif start is None and end is not None:
            raise ValueError('Can not specify start without an end')
        elif start is not None and end is not None:
            command += [ascii(start), ascii(end)]
        return self._execute(command)
Example #12
0
    def bitpos(self, key, bit, start=None, end=None):
        """Return the position of the first bit set to ``1`` or ``0`` in a
        string.

        The position is returned, thinking of the string as an array of bits
        from left to right, where the first byte's most significant bit is at
        position 0, the second byte's most significant bit is at position
        ``8``, and so forth.

        The same bit position convention is followed by
        :meth:`~tredis.RedisClient.getbit` and
        :meth:`~tredis.RedisClient.setbit`.

        By default, all the bytes contained in the string are examined. It is
        possible to look for bits only in a specified interval passing the
        additional arguments start and end (it is possible to just pass start,
        the operation will assume that the end is the last byte of the string.
        However there are semantic differences as explained later). The range
        is interpreted as a range of bytes and not a range of bits, so
        ``start=0`` and ``end=2`` means to look at the first three bytes.

        Note that bit positions are returned always as absolute values starting
        from bit zero even when start and end are used to specify a range.

        Like for the :meth:`~tredis.RedisClient.getrange` command start and
        end can contain negative values in order to index bytes starting from
        the end of the string, where ``-1`` is the last byte, ``-2`` is the
        penultimate, and so forth.

        Non-existent keys are treated as empty strings.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(N)``

        :param key: The key to get
        :type key: :class:`str`, :class:`bytes`
        :param int bit: The bit value to search for (``1`` or ``0``)
        :param int start: The start position to evaluate in the string
        :param int end: The end position to evaluate in the string
        :returns: The position of the first bit set to ``1`` or ``0``
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`, :exc:`ValueError`

        """
        if 0 < bit > 1:
            raise ValueError('bit must be 1 or 0, not {}'.format(bit))
        command = [b'BITPOS', key, ascii(bit)]
        if start is not None and end is None:
            raise ValueError('Can not specify start without an end')
        elif start is None and end is not None:
            raise ValueError('Can not specify start without an end')
        elif start is not None and end is not None:
            command += [ascii(start), ascii(end)]
        return self._execute(command)
Example #13
0
    def migrate(self,
                host,
                port,
                key,
                destination_db,
                timeout,
                copy=False,
                replace=False):
        """Atomically transfer a key from a source Redis instance to a
        destination Redis instance. On success the key is deleted from the
        original instance and is guaranteed to exist in the target instance.

        The command is atomic and blocks the two instances for the time
        required to transfer the key, at any given time the key will appear to
        exist in a given instance or in the other instance, unless a timeout
        error occurs.

        .. note::

           **Time complexity**: This command actually executes a DUMP+DEL in
           the source instance, and a RESTORE in the target instance. See the
           pages of these commands for time complexity. Also an ``O(N)`` data
           transfer between the two instances is performed.

        :param host: The host to migrate the key to
        :type host: bytes, str
        :param int port: The port to connect on
        :param key: The key to migrate
        :type key: bytes, str
        :param int destination_db: The database number to select
        :param int timeout: The maximum idle time in milliseconds
        :param bool copy: Do not remove the key from the local instance
        :param bool replace: Replace existing key on the remote instance
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [
            b'MIGRATE', host,
            ascii(port).encode('ascii'), key,
            ascii(destination_db).encode('ascii'),
            ascii(timeout).encode('ascii')
        ]
        if copy is True:
            command.append(b'COPY')
        if replace is True:
            command.append(b'REPLACE')
        return self._execute(command, b'OK')
Example #14
0
    def migrate(self,
                host,
                port,
                key,
                destination_db,
                timeout,
                copy=False,
                replace=False):
        """Atomically transfer a key from a source Redis instance to a
        destination Redis instance. On success the key is deleted from the
        original instance and is guaranteed to exist in the target instance.

        The command is atomic and blocks the two instances for the time
        required to transfer the key, at any given time the key will appear to
        exist in a given instance or in the other instance, unless a timeout
        error occurs.

        .. note::

           **Time complexity**: This command actually executes a DUMP+DEL in
           the source instance, and a RESTORE in the target instance. See the
           pages of these commands for time complexity. Also an ``O(N)`` data
           transfer between the two instances is performed.

        :param host: The host to migrate the key to
        :type host: bytes, str
        :param int port: The port to connect on
        :param key: The key to migrate
        :type key: bytes, str
        :param int destination_db: The database number to select
        :param int timeout: The maximum idle time in milliseconds
        :param bool copy: Do not remove the key from the local instance
        :param bool replace: Replace existing key on the remote instance
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [
            b'MIGRATE', host,
            ascii(port).encode('ascii'), key,
            ascii(destination_db).encode('ascii'),
            ascii(timeout).encode('ascii')
        ]
        if copy is True:
            command.append(b'COPY')
        if replace is True:
            command.append(b'REPLACE')
        return self._execute(command, b'OK')
Example #15
0
File: sets.py Project: den-t/tredis
    def spop(self, key, count=None):
        """Removes and returns one or more random elements from the set value
        store at key.

        This operation is similar to :meth:`~tredis.RedisClient.srandmember`,
        that returns one or more random elements from a set but does not remove
        it.

        The count argument will be available in a later version and is not
        available in 2.6, 2.8, 3.0

        Redis 3.2 will be the first version where an optional count argument
        can be passed to :meth:`~tredis.RedisClient.spop` in order to retrieve
        multiple elements in a single call. The implementation is already
        available in the unstable branch.

        .. note::

           **Time complexity**: Without the count argument ``O(1)``, otherwise
           ``O(N)`` where ``N`` is the absolute value of the passed count.

        :param key: The key to get one or more random members from
        :type key: :class:`str`, :class:`bytes`
        :param int count: The number of members to return
        :rtype: bytes, list
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'SPOP', key]
        if count:  # pragma: nocover
            command.append(ascii(count).encode('ascii'))
        return self._execute(command)
Example #16
0
    def setex(self, key, seconds, value):
        """Set key to hold the string value and set key to timeout after a
        given number of seconds.

        :meth:`~tredis.RedisClient.setex` is atomic, and can be reproduced by
        using :meth:`~tredis.RedisClient.set` and
        :meth:`~tredis.RedisClient.expire` inside an
        :meth:`~tredis.RedisClient.multi` /
        :meth:`~tredis.RedisClient.exec` block. It is provided as a faster
        alternative to the given sequence of operations, because this operation
        is very common when Redis is used as a cache.

        An error is returned when seconds is invalid.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to set
        :type key: :class:`str`, :class:`bytes`
        :param int seconds: Number of seconds for TTL
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'SETEX', key, ascii(seconds), value], b'OK')
Example #17
0
    def srandmember(self, key, count=None):
        """When called with just the key argument, return a random element from
        the set value stored at key.

        Starting from Redis version 2.6, when called with the additional count
        argument, return an array of count distinct elements if count is
        positive. If called with a negative count the behavior changes and the
        command is allowed to return the same element multiple times. In this
        case the number of returned elements is the absolute value of the
        specified count.

        When called with just the key argument, the operation is similar to
        :meth:`~tredis.RedisClient.spop`, however while
        :meth:`~tredis.RedisClient.spop` also removes the randomly selected
        element from the set, :meth:`~tredis.RedisClient.srandmember` will just
        return a random element without altering the original set in any way.

        .. note::

           **Time complexity**: Without the count argument ``O(1)``, otherwise
           ``O(N)`` where ``N`` is the absolute value of the passed count.

        :param key: The key to get one or more random members from
        :type key: :class:`str`, :class:`bytes`
        :param int count: The number of members to return
        :rtype: bytes, list
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'SRANDMEMBER', key]
        if count:
            command.append(ascii(count).encode('ascii'))
        return self._execute(command)
Example #18
0
    def spop(self, key, count=None):
        """Removes and returns one or more random elements from the set value
        store at key.

        This operation is similar to :meth:`~tredis.RedisClient.srandmember`,
        that returns one or more random elements from a set but does not remove
        it.

        The count argument will be available in a later version and is not
        available in 2.6, 2.8, 3.0

        Redis 3.2 will be the first version where an optional count argument
        can be passed to :meth:`~tredis.RedisClient.spop` in order to retrieve
        multiple elements in a single call. The implementation is already
        available in the unstable branch.

        .. note::

           **Time complexity**: Without the count argument ``O(1)``, otherwise
           ``O(N)`` where ``N`` is the absolute value of the passed count.

        :param key: The key to get one or more random members from
        :type key: :class:`str`, :class:`bytes`
        :param int count: The number of members to return
        :rtype: bytes, list
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'SPOP', key]
        if count:  # pragma: nocover
            command.append(ascii(count).encode('ascii'))
        return self._execute(command)
Example #19
0
    def setex(self, key, seconds, value):
        """Set key to hold the string value and set key to timeout after a
        given number of seconds.

        :meth:`~tredis.RedisClient.setex` is atomic, and can be reproduced by
        using :meth:`~tredis.RedisClient.set` and
        :meth:`~tredis.RedisClient.expire` inside an
        :meth:`~tredis.RedisClient.multi` /
        :meth:`~tredis.RedisClient.exec` block. It is provided as a faster
        alternative to the given sequence of operations, because this operation
        is very common when Redis is used as a cache.

        An error is returned when seconds is invalid.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to set
        :type key: :class:`str`, :class:`bytes`
        :param int seconds: Number of seconds for TTL
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'SETEX', key, ascii(seconds), value], b'OK')
Example #20
0
File: sets.py Project: den-t/tredis
    def srandmember(self, key, count=None):
        """When called with just the key argument, return a random element from
        the set value stored at key.

        Starting from Redis version 2.6, when called with the additional count
        argument, return an array of count distinct elements if count is
        positive. If called with a negative count the behavior changes and the
        command is allowed to return the same element multiple times. In this
        case the number of returned elements is the absolute value of the
        specified count.

        When called with just the key argument, the operation is similar to
        :meth:`~tredis.RedisClient.spop`, however while
        :meth:`~tredis.RedisClient.spop` also removes the randomly selected
        element from the set, :meth:`~tredis.RedisClient.srandmember` will just
        return a random element without altering the original set in any way.

        .. note::

           **Time complexity**: Without the count argument ``O(1)``, otherwise
           ``O(N)`` where ``N`` is the absolute value of the passed count.

        :param key: The key to get one or more random members from
        :type key: :class:`str`, :class:`bytes`
        :param int count: The number of members to return
        :rtype: bytes, list
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'SRANDMEMBER', key]
        if count:
            command.append(ascii(count).encode('ascii'))
        return self._execute(command)
Example #21
0
File: server.py Project: gmr/tredis
    def select(self, index=0):
        """Select the DB with having the specified zero-based numeric index.
        New connections always use DB ``0``.

        :param int index: The database to select
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'SELECT', ascii(index).encode('ascii')], b'OK')
Example #22
0
    def select(self, index=0):
        """Select the DB with having the specified zero-based numeric index.
        New connections always use DB ``0``.

        :param int index: The database to select
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'SELECT', ascii(index).encode('ascii')], b'OK')
Example #23
0
    def _encode_resp(self, value):
        """Dynamically build the RESP payload based upon the list provided.

        :param mixed value: The list of command parts to encode
        :rtype: bytes

        """
        if isinstance(value, bytes):
            return b''.join([b'$', ascii(len(value)).encode('ascii'), CRLF,
                             value, CRLF])
        elif isinstance(value, str):  # pragma: nocover
            return self._encode_resp(value.encode('utf-8'))
        elif isinstance(value, int):
            return self._encode_resp(ascii(value).encode('ascii'))
        elif isinstance(value, list):
            output = [b'*', ascii(len(value)).encode('ascii'), CRLF]
            for item in value:
                output.append(self._encode_resp(item))
            return b''.join(output)
        else:
            raise ValueError('Unsupported type: {0}'.format(type(value)))
Example #24
0
    def setbit(self, key, offset, bit):
        """Sets or clears the bit at offset in the string value stored at key.

        The bit is either set or cleared depending on value, which can be
        either 0 or 1. When key does not exist, a new string value is created.
        The string is grown to make sure it can hold a bit at offset. The
        offset argument is required to be greater than or equal to 0, and
        smaller than 2 :sup:`32` (this limits bitmaps to 512MB). When the
        string at key is grown, added bits are set to 0.

        .. warning:: When setting the last possible bit (offset equal to
           2 :sup:`32` -1) and the string value stored at key does not yet hold
           a string value, or holds a small string value, Redis needs to
           allocate all intermediate memory which can block the server for some
           time. On a 2010 MacBook Pro, setting bit number 2 :sup:`32` -1
           (512MB allocation) takes ~300ms, setting bit number 2 :sup:`30` -1
           (128MB allocation) takes ~80ms, setting bit number 2 :sup:`28` -1
           (32MB allocation) takes ~30ms and setting bit number 2 :sup:`26` -1
           (8MB allocation) takes ~8ms. Note that once this first allocation is
           done, subsequent calls to :meth:`~tredis.RedisClient.setbit` for the
           same key will not have the allocation overhead.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param int offset: The bit offset to fetch the bit from
        :param int bit: The value (``0`` or ``1``) to set for the bit
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        if 0 < bit > 1:
            raise ValueError('bit must be 1 or 0, not {}'.format(bit))
        return self._execute([b'SETBIT', key, ascii(offset), ascii(bit)])
Example #25
0
    def setbit(self, key, offset, bit):
        """Sets or clears the bit at offset in the string value stored at key.

        The bit is either set or cleared depending on value, which can be
        either 0 or 1. When key does not exist, a new string value is created.
        The string is grown to make sure it can hold a bit at offset. The
        offset argument is required to be greater than or equal to 0, and
        smaller than 2 :sup:`32` (this limits bitmaps to 512MB). When the
        string at key is grown, added bits are set to 0.

        .. warning:: When setting the last possible bit (offset equal to
           2 :sup:`32` -1) and the string value stored at key does not yet hold
           a string value, or holds a small string value, Redis needs to
           allocate all intermediate memory which can block the server for some
           time. On a 2010 MacBook Pro, setting bit number 2 :sup:`32` -1
           (512MB allocation) takes ~300ms, setting bit number 2 :sup:`30` -1
           (128MB allocation) takes ~80ms, setting bit number 2 :sup:`28` -1
           (32MB allocation) takes ~30ms and setting bit number 2 :sup:`26` -1
           (8MB allocation) takes ~8ms. Note that once this first allocation is
           done, subsequent calls to :meth:`~tredis.RedisClient.setbit` for the
           same key will not have the allocation overhead.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param int offset: The bit offset to fetch the bit from
        :param int bit: The value (``0`` or ``1``) to set for the bit
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        if 0 < bit > 1:
            raise ValueError('bit must be 1 or 0, not {}'.format(bit))
        return self._execute([b'SETBIT', key, ascii(offset), ascii(bit)])
Example #26
0
File: keys.py Project: den-t/tredis
    def pexpire(self, key, timeout):
        """This command works exactly like :meth:`~tredis.RedisClient.pexpire`
        but the time to live of the key is specified in milliseconds instead of
        seconds.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timeout: The number of milliseconds to set the timeout to
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'PEXPIRE', key, ascii(timeout).encode('ascii')], 1)
Example #27
0
    def pexpire(self, key, timeout):
        """This command works exactly like :meth:`~tredis.RedisClient.pexpire`
        but the time to live of the key is specified in milliseconds instead of
        seconds.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timeout: The number of milliseconds to set the timeout to
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'PEXPIRE', key, ascii(timeout).encode('ascii')], 1)
Example #28
0
File: keys.py Project: den-t/tredis
    def pexpireat(self, key, timestamp):
        """:meth:`~tredis.RedisClient.pexpireat` has the same effect and
        semantic as :meth:`~tredis.RedisClient.expireat`, but the Unix time
        at which the key will expire is specified in milliseconds instead of
        seconds.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timestamp: The expiration UNIX epoch value in milliseconds
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'PEXPIREAT', key, ascii(timestamp).encode('ascii')], 1)
Example #29
0
    def select(self, index=0):
        """Select the DB with having the specified zero-based numeric index.
        New connections always use DB ``0``.

        :param int index: The database to select
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`
        :raises: :exc:`~tredis.exceptions.InvalidClusterCommand`

        """
        if self._clustering:
            raise exceptions.InvalidClusterCommand
        future = self._execute(
            [b'SELECT', ascii(index).encode('ascii')], b'OK')

        def on_selected(f):
            self._connection.database = index

        self.io_loop.add_future(future, on_selected)
        return future
Example #30
0
    def select(self, index=0):
        """Select the DB with having the specified zero-based numeric index.
        New connections always use DB ``0``.

        :param int index: The database to select
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`
        :raises: :exc:`~tredis.exceptions.InvalidClusterCommand`

        """
        if self._clustering:
            raise exceptions.InvalidClusterCommand
        future = self._execute(
            [b'SELECT', ascii(index).encode('ascii')], b'OK')

        def on_selected(f):
            self._connection.database = index

        self.io_loop.add_future(future, on_selected)
        return future
Example #31
0
    def getbit(self, key, offset):
        """Returns the bit value at offset in the string value stored at key.

        When offset is beyond the string length, the string is assumed to be a
        contiguous space with 0 bits. When key does not exist it is assumed to
        be an empty string, so offset is always out of range and the value is
        also assumed to be a contiguous space with 0 bits.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param int offset: The bit offset to fetch the bit from
        :rtype: bytes|None
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'GETBIT', key, ascii(offset)])
Example #32
0
File: keys.py Project: den-t/tredis
    def move(self, key, db):
        """Move key from the currently selected database (see
        :meth:`~tredis.RedisClient.select`) to the specified destination
        database. When key already exists in the destination database, or it
        does not exist in the source database, it does nothing. It is possible
        to use :meth:`~tredis.RedisClient.move` as a locking primitive because
        of this.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to move
        :type key: :class:`str`, :class:`bytes`
        :param int db: The database number
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'MOVE', key, ascii(db).encode('ascii')], 1)
Example #33
0
    def psetex(self, key, milliseconds, value):
        """:meth:`~tredis.RedisClient.psetex` works exactly like
        :meth:`~tredis.RedisClient.psetex` with the sole difference that the
        expire time is specified in milliseconds instead of seconds.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to set
        :type key: :class:`str`, :class:`bytes`
        :param int milliseconds: Number of milliseconds for TTL
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'PSETEX', key, ascii(milliseconds), value], b'OK')
Example #34
0
    def psetex(self, key, milliseconds, value):
        """:meth:`~tredis.RedisClient.psetex` works exactly like
        :meth:`~tredis.RedisClient.psetex` with the sole difference that the
        expire time is specified in milliseconds instead of seconds.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to set
        :type key: :class:`str`, :class:`bytes`
        :param int milliseconds: Number of milliseconds for TTL
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'PSETEX', key, ascii(milliseconds), value],
                             b'OK')
Example #35
0
    def pexpireat(self, key, timestamp):
        """:meth:`~tredis.RedisClient.pexpireat` has the same effect and
        semantic as :meth:`~tredis.RedisClient.expireat`, but the Unix time
        at which the key will expire is specified in milliseconds instead of
        seconds.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timestamp: The expiration UNIX epoch value in milliseconds
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'PEXPIREAT', key,
             ascii(timestamp).encode('ascii')], 1)
Example #36
0
    def move(self, key, db):
        """Move key from the currently selected database (see
        :meth:`~tredis.RedisClient.select`) to the specified destination
        database. When key already exists in the destination database, or it
        does not exist in the source database, it does nothing. It is possible
        to use :meth:`~tredis.RedisClient.move` as a locking primitive because
        of this.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to move
        :type key: :class:`str`, :class:`bytes`
        :param int db: The database number
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'MOVE', key, ascii(db).encode('ascii')], 1)
Example #37
0
    def getbit(self, key, offset):
        """Returns the bit value at offset in the string value stored at key.

        When offset is beyond the string length, the string is assumed to be a
        contiguous space with 0 bits. When key does not exist it is assumed to
        be an empty string, so offset is always out of range and the value is
        also assumed to be a contiguous space with 0 bits.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param int offset: The bit offset to fetch the bit from
        :rtype: bytes|None
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'GETBIT', key, ascii(offset)])
Example #38
0
    def expire(self, key, timeout):
        """Set a timeout on key. After the timeout has expired, the key will
        automatically be deleted. A key with an associated timeout is often
        said to be volatile in Redis terminology.

        The timeout is cleared only when the key is removed using the
        :meth:`~tredis.RedisClient.delete` method or overwritten using the
        :meth:`~tredis.RedisClient.set` or :meth:`~tredis.RedisClient.getset`
        methods. This means that all the operations that conceptually alter the
        value stored at the key without replacing it with a new one will leave
        the timeout untouched. For instance, incrementing the value of a key
        with :meth:`~tredis.RedisClient.incr`, pushing a new value into a
        list with :meth:`~tredis.RedisClient.lpush`, or altering the field
        value of a hash with :meth:`~tredis.RedisClient.hset` are all
        operations that will leave the timeout untouched.

        The timeout can also be cleared, turning the key back into a persistent
        key, using the :meth:`~tredis.RedisClient.persist` method.

        If a key is renamed with :meth:`~tredis.RedisClient.rename`,
        the associated time to live is transferred to the new key name.

        If a key is overwritten by :meth:`~tredis.RedisClient.rename`, like in
        the case of an existing key ``Key_A`` that is overwritten by a call
        like ``client.rename(Key_B, Key_A)`` it does not matter if the original
        ``Key_A`` had a timeout associated or not, the new key ``Key_A`` will
        inherit all the characteristics of ``Key_B``.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timeout: The number of seconds to set the timeout to
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'EXPIRE', key, ascii(timeout).encode('ascii')], 1)
Example #39
0
    def setrange(self, key, offset, value):
        """Overwrites part of the string stored at key, starting at the
        specified offset, for the entire length of value. If the offset is
        larger than the current length of the string at key, the string is
        padded with zero-bytes to make offset fit. Non-existing keys are
        considered as empty strings, so this command will make sure it holds a
        string large enough to be able to set value at offset.

        .. note:: The maximum offset that you can set is 2 :sup:`29` -1
           (536870911), as Redis Strings are limited to 512 megabytes. If you
           need to grow beyond this size, you can use multiple keys.

        .. warning:: When setting the last possible byte and the string value
           stored at key does not yet hold a string value, or holds a small
           string value, Redis needs to allocate all intermediate memory which
           can block the server for some time. On a 2010 MacBook Pro, setting
           byte number 536870911 (512MB allocation) takes ~300ms, setting byte
           number 134217728 (128MB allocation) takes ~80ms, setting bit number
           33554432 (32MB allocation) takes ~30ms and setting bit number
           8388608 (8MB allocation) takes ~8ms. Note that once this first
           allocation is done, subsequent calls to
           :meth:`~tredis.RedisClient.setrange` for the same key will not have
           the allocation overhead.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``, not counting the time taken to
           copy the new string in place. Usually, this string is very small so
           the amortized complexity is ``O(1)``. Otherwise, complexity is
           ``O(M)`` with ``M`` being the length of the value argument.

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`, :class:`int`
        :returns: The length of the string after it was modified by the command
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'SETRANGE', key, ascii(offset), value])
Example #40
0
    def setrange(self, key, offset, value):
        """Overwrites part of the string stored at key, starting at the
        specified offset, for the entire length of value. If the offset is
        larger than the current length of the string at key, the string is
        padded with zero-bytes to make offset fit. Non-existing keys are
        considered as empty strings, so this command will make sure it holds a
        string large enough to be able to set value at offset.

        .. note:: The maximum offset that you can set is 2 :sup:`29` -1
           (536870911), as Redis Strings are limited to 512 megabytes. If you
           need to grow beyond this size, you can use multiple keys.

        .. warning:: When setting the last possible byte and the string value
           stored at key does not yet hold a string value, or holds a small
           string value, Redis needs to allocate all intermediate memory which
           can block the server for some time. On a 2010 MacBook Pro, setting
           byte number 536870911 (512MB allocation) takes ~300ms, setting byte
           number 134217728 (128MB allocation) takes ~80ms, setting bit number
           33554432 (32MB allocation) takes ~30ms and setting bit number
           8388608 (8MB allocation) takes ~8ms. Note that once this first
           allocation is done, subsequent calls to
           :meth:`~tredis.RedisClient.setrange` for the same key will not have
           the allocation overhead.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``, not counting the time taken to
           copy the new string in place. Usually, this string is very small so
           the amortized complexity is ``O(1)``. Otherwise, complexity is
           ``O(M)`` with ``M`` being the length of the value argument.

        :param key: The key to get the bit from
        :type key: :class:`str`, :class:`bytes`
        :param value: The value to set
        :type value: :class:`str`, :class:`bytes`, :class:`int`
        :returns: The length of the string after it was modified by the command
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'SETRANGE', key, ascii(offset), value])
Example #41
0
File: keys.py Project: den-t/tredis
    def expire(self, key, timeout):
        """Set a timeout on key. After the timeout has expired, the key will
        automatically be deleted. A key with an associated timeout is often
        said to be volatile in Redis terminology.

        The timeout is cleared only when the key is removed using the
        :meth:`~tredis.RedisClient.delete` method or overwritten using the
        :meth:`~tredis.RedisClient.set` or :meth:`~tredis.RedisClient.getset`
        methods. This means that all the operations that conceptually alter the
        value stored at the key without replacing it with a new one will leave
        the timeout untouched. For instance, incrementing the value of a key
        with :meth:`~tredis.RedisClient.incr`, pushing a new value into a
        list with :meth:`~tredis.RedisClient.lpush`, or altering the field
        value of a hash with :meth:`~tredis.RedisClient.hset` are all
        operations that will leave the timeout untouched.

        The timeout can also be cleared, turning the key back into a persistent
        key, using the :meth:`~tredis.RedisClient.persist` method.

        If a key is renamed with :meth:`~tredis.RedisClient.rename`,
        the associated time to live is transferred to the new key name.

        If a key is overwritten by :meth:`~tredis.RedisClient.rename`, like in
        the case of an existing key ``Key_A`` that is overwritten by a call
        like ``client.rename(Key_B, Key_A)`` it does not matter if the original
        ``Key_A`` had a timeout associated or not, the new key ``Key_A`` will
        inherit all the characteristics of ``Key_B``.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timeout: The number of seconds to set the timeout to
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'EXPIRE', key, ascii(timeout).encode('ascii')], 1)
Example #42
0
    def restore(self, key, ttl, value, replace=False):
        """Create a key associated with a value that is obtained by
        deserializing the provided serialized value (obtained via
        :meth:`~tredis.RedisClient.dump`).

        If ``ttl`` is ``0`` the key is created without any expire, otherwise
        the specified expire time (in milliseconds) is set.

        :meth:`~tredis.RedisClient.restore` will return a
        ``Target key name is busy`` error when key already exists unless you
        use the :meth:`~tredis.RedisClient.restore` modifier (Redis 3.0 or
        greater).

        :meth:`~tredis.RedisClient.restore` checks the RDB version and data
        checksum. If they don't match an error is returned.

        .. note::

           **Time complexity**: ``O(1)`` to create the new key and additional
           ``O(N*M)`` to reconstruct the serialized value, where ``N`` is the
           number of Redis objects composing the value and ``M`` their average
           size. For small string values the time complexity is thus
           ``O(1)+O(1*M)`` where ``M`` is small, so simply ``O(1)``. However
           for sorted set values the complexity is ``O(N*M*log(N))`` because
           inserting values into sorted sets is ``O(log(N))``.

        :param key: The key to get the TTL for
        :type key: :class:`str`, :class:`bytes`
        :param int ttl: The number of seconds to set the timeout to
        :param value: The value to restore to the key
        :type value: :class:`str`, :class:`bytes`
        :param bool replace: Replace a pre-existing key
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'RESTORE', key, ascii(ttl).encode('ascii'), value]
        if replace:
            command.append(b'REPLACE')
        return self._execute(command, b'OK')
Example #43
0
File: keys.py Project: den-t/tredis
    def restore(self, key, ttl, value, replace=False):
        """Create a key associated with a value that is obtained by
        deserializing the provided serialized value (obtained via
        :meth:`~tredis.RedisClient.dump`).

        If ``ttl`` is ``0`` the key is created without any expire, otherwise
        the specified expire time (in milliseconds) is set.

        :meth:`~tredis.RedisClient.restore` will return a
        ``Target key name is busy`` error when key already exists unless you
        use the :meth:`~tredis.RedisClient.restore` modifier (Redis 3.0 or
        greater).

        :meth:`~tredis.RedisClient.restore` checks the RDB version and data
        checksum. If they don't match an error is returned.

        .. note::

           **Time complexity**: ``O(1)`` to create the new key and additional
           ``O(N*M)`` to reconstruct the serialized value, where ``N`` is the
           number of Redis objects composing the value and ``M`` their average
           size. For small string values the time complexity is thus
           ``O(1)+O(1*M)`` where ``M`` is small, so simply ``O(1)``. However
           for sorted set values the complexity is ``O(N*M*log(N))`` because
           inserting values into sorted sets is ``O(log(N))``.

        :param key: The key to get the TTL for
        :type key: :class:`str`, :class:`bytes`
        :param int ttl: The number of seconds to set the timeout to
        :param value: The value to restore to the key
        :type value: :class:`str`, :class:`bytes`
        :param bool replace: Replace a pre-existing key
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        command = [b'RESTORE', key, ascii(ttl).encode('ascii'), value]
        if replace:
            command.append(b'REPLACE')
        return self._execute(command, b'OK')
Example #44
0
File: keys.py Project: den-t/tredis
    def expireat(self, key, timestamp):
        """:meth:`~tredis.RedisClient.expireat` has the same effect and
        semantic as :meth:`~tredis.RedisClient.expire`, but instead of
        specifying the number of seconds representing the TTL (time to live),
        it takes an absolute Unix timestamp (seconds since January 1, 1970).

        Please for the specific semantics of the command refer to the
        documentation of :meth:`~tredis.RedisClient.expire`.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timestamp: The UNIX epoch value for the expiration
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'EXPIREAT', key, ascii(timestamp).encode('ascii')], 1)
Example #45
0
    def incrby(self, key, increment):
        """Increments the number stored at key by increment. If the key does
        not exist, it is set to 0 before performing the operation. An error is
        returned if the key contains a value of the wrong type or contains a
        string that can not be represented as integer. This operation is
        limited to 64 bit signed integers.

        See :meth:`~tredis.RedisClient.incr` for extra information on
        increment/decrement operations.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to increment
        :type key: :class:`str`, :class:`bytes`
        :param int increment: The amount to increment by
        :returns: The value of key after the increment
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'INCRBY', key, ascii(increment)])
Example #46
0
    def incrby(self, key, increment):
        """Increments the number stored at key by increment. If the key does
        not exist, it is set to 0 before performing the operation. An error is
        returned if the key contains a value of the wrong type or contains a
        string that can not be represented as integer. This operation is
        limited to 64 bit signed integers.

        See :meth:`~tredis.RedisClient.incr` for extra information on
        increment/decrement operations.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to increment
        :type key: :class:`str`, :class:`bytes`
        :param int increment: The amount to increment by
        :returns: The value of key after the increment
        :rtype: int
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'INCRBY', key, ascii(increment)])
Example #47
0
    def expireat(self, key, timestamp):
        """:meth:`~tredis.RedisClient.expireat` has the same effect and
        semantic as :meth:`~tredis.RedisClient.expire`, but instead of
        specifying the number of seconds representing the TTL (time to live),
        it takes an absolute Unix timestamp (seconds since January 1, 1970).

        Please for the specific semantics of the command refer to the
        documentation of :meth:`~tredis.RedisClient.expire`.

        .. note::

           **Time complexity**: ``O(1)``

        :param key: The key to set an expiration for
        :type key: :class:`str`, :class:`bytes`
        :param int timestamp: The UNIX epoch value for the expiration
        :rtype: bool
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute(
            [b'EXPIREAT', key,
             ascii(timestamp).encode('ascii')], 1)
Example #48
0
    def incrbyfloat(self, key, increment):
        """Increment the string representing a floating point number stored at
        key by the specified increment. If the key does not exist, it is set to
        0 before performing the operation. An error is returned if one of the
        following conditions occur:

          - The key contains a value of the wrong type (not a string).
          - The current key content or the specified increment are not
            parsable as a double precision floating point number.

        If the command is successful the new incremented value is stored as the
        new value of the key (replacing the old one), and returned to the
        caller as a string.

        Both the value already contained in the string key and the increment
        argument can be optionally provided in exponential notation, however
        the value computed after the increment is stored consistently in the
        same format, that is, an integer number followed (if needed) by a dot,
        and a variable number of digits representing the decimal part of the
        number. Trailing zeroes are always removed.

        The precision of the output is fixed at 17 digits after the decimal
        point regardless of the actual internal precision of the computation.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to increment
        :type key: :class:`str`, :class:`bytes`
        :param float increment: The amount to increment by
        :returns: The value of key after the increment
        :rtype: bytes
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'INCRBYFLOAT', key, ascii(increment)])
Example #49
0
    def incrbyfloat(self, key, increment):
        """Increment the string representing a floating point number stored at
        key by the specified increment. If the key does not exist, it is set to
        0 before performing the operation. An error is returned if one of the
        following conditions occur:

          - The key contains a value of the wrong type (not a string).
          - The current key content or the specified increment are not
            parsable as a double precision floating point number.

        If the command is successful the new incremented value is stored as the
        new value of the key (replacing the old one), and returned to the
        caller as a string.

        Both the value already contained in the string key and the increment
        argument can be optionally provided in exponential notation, however
        the value computed after the increment is stored consistently in the
        same format, that is, an integer number followed (if needed) by a dot,
        and a variable number of digits representing the decimal part of the
        number. Trailing zeroes are always removed.

        The precision of the output is fixed at 17 digits after the decimal
        point regardless of the actual internal precision of the computation.

        .. versionadded:: 0.2.0

        .. note:: **Time complexity**: ``O(1)``

        :param key: The key to increment
        :type key: :class:`str`, :class:`bytes`
        :param float increment: The amount to increment by
        :returns: The value of key after the increment
        :rtype: bytes
        :raises: :exc:`~tredis.exceptions.RedisError`

        """
        return self._execute([b'INCRBYFLOAT', key, ascii(increment)])
Example #50
0
        def on_connect(response):
            """Invoked when the socket stream has connected

            :param response: The connection response future
            :type response: :class:`~tornado.concurrent.Future`

            """
            exc = response.exception()
            if exc:
                return future.set_exception(exceptions.ConnectError(str(exc)))

            self._stream = response.result()
            self._stream.set_close_callback(self._on_closed)
            if not self._default_db:
                return future.set_result(True)

            def on_written():
                select_future = concurrent.TracebackFuture()
                self._get_response(select_future)
                self._ioloop.add_future(select_future, on_selected)

            LOGGER.debug('Selecting the default db: %r', self._default_db)
            command = self._build_command(['SELECT', ascii(self._default_db)])
            self._stream.write(command, on_written)
Example #51
0
File: keys.py Project: den-t/tredis
    def sort(self,
             key,
             by=None,
             external=None,
             offset=0,
             limit=None,
             order=None,
             alpha=False,
             store_as=None):
        """Returns or stores the elements contained in the list, set or sorted
        set at key. By default, sorting is numeric and elements are compared by
        their value interpreted as double precision floating point number.

        The ``external`` parameter is used to specify the
        `GET <http://redis.io/commands/sort#retrieving-external-keys>_`
        parameter for retrieving external keys. It can be a single string
        or a list of strings.

        .. note::

           **Time complexity**: ``O(N+M*log(M))`` where ``N`` is the number of
           elements in the list or set to sort, and ``M`` the number of
           returned elements. When the elements are not sorted, complexity is
           currently ``O(N)`` as there is a copy step that will be avoided in
           next releases.

        :param key: The key to get the refcount for
        :type key: :class:`str`, :class:`bytes`

        :param by: The optional pattern for external sorting keys
        :type by: :class:`str`, :class:`bytes`
        :param external: Pattern or list of patterns to return external keys
        :type external: :class:`str`, :class:`bytes`, list
        :param int offset: The starting offset when using limit
        :param int limit: The number of elements to return
        :param order: The sort order - one of ``ASC`` or ``DESC``
        :type order: :class:`str`, :class:`bytes`
        :param bool alpha: Sort the results lexicographically
        :param store_as: When specified, the key to store the results as
        :type store_as: :class:`str`, :class:`bytes`, None
        :rtype: list|int
        :raises: :exc:`~tredis.exceptions.RedisError`
        :raises: :exc:`ValueError`

        """
        if order and order not in [b'ASC', b'DESC', 'ASC', 'DESC']:
            raise ValueError('invalid sort order "{}"'.format(order))

        command = [b'SORT', key]
        if by:
            command += [b'BY', by]
        if external and isinstance(external, list):
            for entry in external:
                command += [b'GET', entry]
        elif external:
            command += [b'GET', external]
        if limit:
            command += [b'LIMIT', ascii(offset).encode('utf-8'),
                        ascii(limit).encode('utf-8')]
        if order:
            command.append(order)
        if alpha is True:
            command.append(b'ALPHA')
        if store_as:
            command += [b'STORE', store_as]

        return self._execute(command)
Example #52
0
    def sort(self,
             key,
             by=None,
             external=None,
             offset=0,
             limit=None,
             order=None,
             alpha=False,
             store_as=None):
        """Returns or stores the elements contained in the list, set or sorted
        set at key. By default, sorting is numeric and elements are compared by
        their value interpreted as double precision floating point number.

        The ``external`` parameter is used to specify the
        `GET <http://redis.io/commands/sort#retrieving-external-keys>_`
        parameter for retrieving external keys. It can be a single string
        or a list of strings.

        .. note::

           **Time complexity**: ``O(N+M*log(M))`` where ``N`` is the number of
           elements in the list or set to sort, and ``M`` the number of
           returned elements. When the elements are not sorted, complexity is
           currently ``O(N)`` as there is a copy step that will be avoided in
           next releases.

        :param key: The key to get the refcount for
        :type key: :class:`str`, :class:`bytes`

        :param by: The optional pattern for external sorting keys
        :type by: :class:`str`, :class:`bytes`
        :param external: Pattern or list of patterns to return external keys
        :type external: :class:`str`, :class:`bytes`, list
        :param int offset: The starting offset when using limit
        :param int limit: The number of elements to return
        :param order: The sort order - one of ``ASC`` or ``DESC``
        :type order: :class:`str`, :class:`bytes`
        :param bool alpha: Sort the results lexicographically
        :param store_as: When specified, the key to store the results as
        :type store_as: :class:`str`, :class:`bytes`, None
        :rtype: list|int
        :raises: :exc:`~tredis.exceptions.RedisError`
        :raises: :exc:`ValueError`

        """
        if order and order not in [b'ASC', b'DESC', 'ASC', 'DESC']:
            raise ValueError('invalid sort order "{}"'.format(order))

        command = [b'SORT', key]
        if by:
            command += [b'BY', by]
        if external and isinstance(external, list):
            for entry in external:
                command += [b'GET', entry]
        elif external:
            command += [b'GET', external]
        if limit:
            command += [
                b'LIMIT',
                ascii(offset).encode('utf-8'),
                ascii(limit).encode('utf-8')
            ]
        if order:
            command.append(order)
        if alpha is True:
            command.append(b'ALPHA')
        if store_as:
            command += [b'STORE', store_as]

        return self._execute(command)