# Path: aredis/connection.py
# class ClusterConnection(Connection):
#     "Manages TCP communication to and from a Redis server"
#     description = "ClusterConnection<host={host},port={port}>"
# 
#     def __init__(self, *args, **kwargs):
#         self.readonly = kwargs.pop('readonly', False)
#         super(ClusterConnection, self).__init__(*args, **kwargs)
# 
#     async def on_connect(self):
#         """
#         Initialize the connection, authenticate and select a database and send READONLY if it is
#         set during object initialization.
#         """
#         if self.db:
#             warnings.warn('SELECT DB is not allowed in cluster mode')
#             self.db = ''
#         await super(ClusterConnection, self).on_connect()
#         if self.readonly:
#             await self.send_command('READONLY')
#             if nativestr(await self.read_response()) != 'OK':
#                 raise ConnectionError('READONLY command failed')
# 
# Path: aredis/exceptions.py
# class LockError(RedisError, ValueError):
#     """Errors acquiring or releasing a lock"""
#     # NOTE: For backwards compatability, this class derives from ValueError.
#     # This was originally chosen to behave like threading.Lock.
#     pass
# 
# class WatchError(RedisError):
#     pass
# 
# Path: aredis/utils.py
# def b(x):
#     return x.encode('latin-1') if not isinstance(x, bytes) else x
# 
# class dummy:
#     """
#     Instances of this class can be used as an attribute container.
#     """
# 
#     def __init__(self):
#         self.token = None
# 
#     def set(self, value):
#         self.token = value
# 
#     def get(self):
#         return self.token


import asyncio
import time as mod_time
import uuid
import warnings
import contextvars
from aredis.connection import ClusterConnection
from aredis.exceptions import LockError, WatchError
from aredis.utils import b, dummy
            # we'll handle this when we call pexpire()
            expiration = 0
        pipe.multi()
        await pipe.pexpire(self.name, expiration + int(additional_time * 1000))

        try:
            response = await pipe.execute()
        except WatchError:
            # someone else acquired the lock
            raise LockError("Cannot extend a lock that's no longer owned")
        if not response[0]:
            # pexpire returns False if the key doesn't exist
            raise LockError("Cannot extend a lock that's no longer owned")
        return True


class LuaLock(Lock):
    """
    A lock implementation that uses Lua scripts rather than pipelines
    and watches.
    """
    lua_release = None
    lua_extend = None

    # KEYS[1] - lock name
    # ARGS[1] - token
    # return 1 if the lock was released, otherwise 0
    LUA_RELEASE_SCRIPT = """
        local token = redis.call('get', KEYS[1])
        if not token or token ~= ARGV[1] then

# Path: aredis/connection.py
# class ClusterConnection(Connection):
#     "Manages TCP communication to and from a Redis server"
#     description = "ClusterConnection<host={host},port={port}>"
# 
#     def __init__(self, *args, **kwargs):
#         self.readonly = kwargs.pop('readonly', False)
#         super(ClusterConnection, self).__init__(*args, **kwargs)
# 
#     async def on_connect(self):
#         """
#         Initialize the connection, authenticate and select a database and send READONLY if it is
#         set during object initialization.
#         """
#         if self.db:
#             warnings.warn('SELECT DB is not allowed in cluster mode')
#             self.db = ''
#         await super(ClusterConnection, self).on_connect()
#         if self.readonly:
#             await self.send_command('READONLY')
#             if nativestr(await self.read_response()) != 'OK':
#                 raise ConnectionError('READONLY command failed')
# 
# Path: aredis/exceptions.py
# class LockError(RedisError, ValueError):
#     """Errors acquiring or releasing a lock"""
#     # NOTE: For backwards compatability, this class derives from ValueError.
#     # This was originally chosen to behave like threading.Lock.
#     pass
# 
# class WatchError(RedisError):
#     pass
# 
# Path: aredis/utils.py
# def b(x):
#     return x.encode('latin-1') if not isinstance(x, bytes) else x
# 
# class dummy:
#     """
#     Instances of this class can be used as an attribute container.
#     """
# 
#     def __init__(self):
#         self.token = None
# 
#     def set(self, value):
#         self.token = value
# 
#     def get(self):
#         return self.token


# Path: aredis/lock.py
import asyncio
import time as mod_time
import uuid
import warnings
import contextvars
from aredis.connection import ClusterConnection
from aredis.exceptions import LockError, WatchError
from aredis.utils import b, dummy

            # we'll handle this when we call pexpire()
            expiration = 0
        pipe.multi()
        await pipe.pexpire(self.name, expiration + int(additional_time * 1000))

        try:
            response = await pipe.execute()
        except WatchError:
            # someone else acquired the lock
            raise LockError("Cannot extend a lock that's no longer owned")
        if not response[0]:
            # pexpire returns False if the key doesn't exist
            raise LockError("Cannot extend a lock that's no longer owned")
        return True


class LuaLock(Lock):
    """
    A lock implementation that uses Lua scripts rather than pipelines
    and watches.
    """
    lua_release = None
    lua_extend = None

    # KEYS[1] - lock name
    # ARGS[1] - token
    # return 1 if the lock was released, otherwise 0
    LUA_RELEASE_SCRIPT = """
        local token = redis.call('get', KEYS[1])
        if not token or token ~= ARGV[1] then

            return 0