summaryrefslogtreecommitdiff
path: root/redis
diff options
context:
space:
mode:
authorAarni Koskela <akx@iki.fi>2021-11-30 17:20:43 +0200
committerGitHub <noreply@github.com>2021-11-30 17:20:43 +0200
commitfbe87acf96aab583975ed3371423eb20602eccaf (patch)
treeb873c3356b9c96e826c4ab0bb3efc339a00838e4 /redis
parent4db85ef574a64a2b230a3ae1ff19c9d04065a114 (diff)
downloadredis-py-fbe87acf96aab583975ed3371423eb20602eccaf.tar.gz
Pyupgrade + flynt + f-strings (#1759)
@akx Thank you so much for this! Thanks again for introducing me to a new tool that I'm sliding into my workflow as well.
Diffstat (limited to 'redis')
-rwxr-xr-xredis/client.py18
-rw-r--r--redis/cluster.py134
-rw-r--r--redis/commands/cluster.py20
-rw-r--r--redis/commands/core.py45
-rw-r--r--redis/commands/helpers.py2
-rw-r--r--redis/commands/json/path.py2
-rw-r--r--redis/commands/parser.py5
-rw-r--r--redis/commands/search/__init__.py2
-rw-r--r--redis/commands/search/aggregation.py27
-rw-r--r--redis/commands/search/commands.py2
-rw-r--r--redis/commands/search/document.py4
-rw-r--r--redis/commands/search/field.py2
-rw-r--r--redis/commands/search/indexDefinition.py5
-rw-r--r--redis/commands/search/query.py10
-rw-r--r--redis/commands/search/querystring.py22
-rw-r--r--redis/commands/search/reducers.py24
-rw-r--r--redis/commands/search/result.py4
-rw-r--r--redis/commands/search/suggestion.py4
-rw-r--r--redis/commands/timeseries/info.py2
-rwxr-xr-xredis/connection.py65
-rw-r--r--redis/sentinel.py28
21 files changed, 201 insertions, 226 deletions
diff --git a/redis/client.py b/redis/client.py
index 0ae64be..9f2907e 100755
--- a/redis/client.py
+++ b/redis/client.py
@@ -629,7 +629,7 @@ def parse_set_result(response, **options):
return response and str_if_bytes(response) == 'OK'
-class Redis(RedisModuleCommands, CoreCommands, SentinelCommands, object):
+class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
"""
Implementation of the Redis protocol.
@@ -918,7 +918,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands, object):
self.__class__.RESPONSE_CALLBACKS)
def __repr__(self):
- return "%s<%s>" % (type(self).__name__, repr(self.connection_pool))
+ return f"{type(self).__name__}<{repr(self.connection_pool)}>"
def set_response_callback(self, command, callback):
"Set a custom Response Callback"
@@ -1141,7 +1141,7 @@ class Monitor:
# check that monitor returns 'OK', but don't return it to user
response = self.connection.read_response()
if not bool_ok(response):
- raise RedisError('MONITOR failed: %s' % response)
+ raise RedisError(f'MONITOR failed: {response}')
return self
def __exit__(self, *args):
@@ -1517,12 +1517,10 @@ class PubSub:
exception_handler=None):
for channel, handler in self.channels.items():
if handler is None:
- raise PubSubError("Channel: '%s' has no handler registered" %
- channel)
+ raise PubSubError(f"Channel: '{channel}' has no handler registered")
for pattern, handler in self.patterns.items():
if handler is None:
- raise PubSubError("Pattern: '%s' has no handler registered" %
- pattern)
+ raise PubSubError(f"Pattern: '{pattern}' has no handler registered")
thread = PubSubWorkerThread(
self,
@@ -1807,8 +1805,10 @@ class Pipeline(Redis):
def annotate_exception(self, exception, number, command):
cmd = ' '.join(map(safe_str, command))
- msg = 'Command # %d (%s) of pipeline caused error: %s' % (
- number, cmd, exception.args[0])
+ msg = (
+ f'Command # {number} ({cmd}) of pipeline '
+ f'caused error: {exception.args[0]}'
+ )
exception.args = (msg,) + exception.args[1:]
def parse_response(self, connection, command_name, **options):
diff --git a/redis/cluster.py b/redis/cluster.py
index 91a4d55..c1853aa 100644
--- a/redis/cluster.py
+++ b/redis/cluster.py
@@ -42,7 +42,7 @@ log = logging.getLogger(__name__)
def get_node_name(host, port):
- return '{0}:{1}'.format(host, port)
+ return f'{host}:{port}'
def get_connection(redis_node, *args, **options):
@@ -200,7 +200,7 @@ class ClusterParser(DefaultParser):
})
-class RedisCluster(ClusterCommands, object):
+class RedisCluster(ClusterCommands):
RedisClusterRequestTTL = 16
PRIMARIES = "primaries"
@@ -451,7 +451,7 @@ class RedisCluster(ClusterCommands, object):
"2. list of startup nodes, for example:\n"
" RedisCluster(startup_nodes=[ClusterNode('localhost', 6379),"
" ClusterNode('localhost', 6378)])")
- log.debug("startup_nodes : {0}".format(startup_nodes))
+ log.debug(f"startup_nodes : {startup_nodes}")
# Update the connection arguments
# Whenever a new connection is established, RedisCluster's on_connect
# method should be run
@@ -602,7 +602,7 @@ class RedisCluster(ClusterCommands, object):
slot_cache = self.nodes_manager.slots_cache.get(slot)
if slot_cache is None or len(slot_cache) == 0:
raise SlotNotCoveredError(
- 'Slot "{0}" is not covered by the cluster.'.format(slot)
+ f'Slot "{slot}" is not covered by the cluster.'
)
if replica and len(self.nodes_manager.slots_cache[slot]) < 2:
return None
@@ -631,7 +631,7 @@ class RedisCluster(ClusterCommands, object):
"the default node was not changed.")
return False
self.nodes_manager.default_node = node
- log.info("Changed the default cluster node to {0}".format(node))
+ log.info(f"Changed the default cluster node to {node}")
return True
def pubsub(self, node=None, host=None, port=None, **kwargs):
@@ -678,8 +678,7 @@ class RedisCluster(ClusterCommands, object):
# get the nodes group for this command if it was predefined
command_flag = self.command_flags.get(command)
if command_flag:
- log.debug("Target node/s for {0}: {1}".
- format(command, command_flag))
+ log.debug(f"Target node/s for {command}: {command_flag}")
if command_flag == self.__class__.RANDOM:
# return a random node
return [self.get_random_node()]
@@ -700,7 +699,7 @@ class RedisCluster(ClusterCommands, object):
slot = self.determine_slot(*args)
node = self.nodes_manager.get_node_from_slot(
slot, self.read_from_replicas and command in READ_COMMANDS)
- log.debug("Target for {0}: slot {1}".format(args, slot))
+ log.debug(f"Target for {args}: slot {slot}")
return [node]
def _should_reinitialized(self):
@@ -741,7 +740,7 @@ class RedisCluster(ClusterCommands, object):
raise RedisClusterException(
"No way to dispatch this command to Redis Cluster. "
"Missing key.\nYou can execute the command by specifying "
- "target nodes.\nCommand: {0}".format(args)
+ f"target nodes.\nCommand: {args}"
)
if len(keys) > 1:
@@ -749,8 +748,9 @@ class RedisCluster(ClusterCommands, object):
# the same slot
slots = {self.keyslot(key) for key in keys}
if len(slots) != 1:
- raise RedisClusterException("{0} - all keys must map to the "
- "same key slot".format(args[0]))
+ raise RedisClusterException(
+ f"{args[0]} - all keys must map to the same key slot"
+ )
return slots.pop()
else:
# single key command
@@ -775,12 +775,12 @@ class RedisCluster(ClusterCommands, object):
# rc.cluster_save_config(rc.get_primaries())
nodes = target_nodes.values()
else:
- raise TypeError("target_nodes type can be one of the "
- "followings: node_flag (PRIMARIES, "
- "REPLICAS, RANDOM, ALL_NODES),"
- "ClusterNode, list<ClusterNode>, or "
- "dict<any, ClusterNode>. The passed type is {0}".
- format(type(target_nodes)))
+ raise TypeError(
+ "target_nodes type can be one of the following: "
+ "node_flag (PRIMARIES, REPLICAS, RANDOM, ALL_NODES),"
+ "ClusterNode, list<ClusterNode>, or dict<any, ClusterNode>. "
+ f"The passed type is {type(target_nodes)}"
+ )
return nodes
def execute_command(self, *args, **kwargs):
@@ -824,8 +824,7 @@ class RedisCluster(ClusterCommands, object):
*args, **kwargs, nodes_flag=target_nodes)
if not target_nodes:
raise RedisClusterException(
- "No targets were found to execute"
- " {} command on".format(args))
+ f"No targets were found to execute {args} command on")
for node in target_nodes:
res[node.name] = self._execute_command(
node, *args, **kwargs)
@@ -868,9 +867,10 @@ class RedisCluster(ClusterCommands, object):
command in READ_COMMANDS)
moved = False
- log.debug("Executing command {0} on target node: {1} {2}".
- format(command, target_node.server_type,
- target_node.name))
+ log.debug(
+ f"Executing command {command} on target node: "
+ f"{target_node.server_type} {target_node.name}"
+ )
redis_node = self.get_redis_connection(target_node)
connection = get_connection(redis_node, *args, **kwargs)
if asking:
@@ -952,7 +952,7 @@ class RedisCluster(ClusterCommands, object):
raise e
except ResponseError as e:
message = e.__str__()
- log.exception("ResponseError: {0}".format(message))
+ log.exception(f"ResponseError: {message}")
raise e
except BaseException as e:
log.exception("BaseException")
@@ -995,7 +995,7 @@ class RedisCluster(ClusterCommands, object):
return res
-class ClusterNode(object):
+class ClusterNode:
def __init__(self, host, port, server_type=None, redis_connection=None):
if host == 'localhost':
host = socket.gethostbyname(host)
@@ -1007,13 +1007,13 @@ class ClusterNode(object):
self.redis_connection = redis_connection
def __repr__(self):
- return '[host={0},port={1},' \
- 'name={2},server_type={3},redis_connection={4}]' \
- .format(self.host,
- self.port,
- self.name,
- self.server_type,
- self.redis_connection)
+ return (
+ f'[host={self.host},'
+ f'port={self.port},'
+ f'name={self.name},'
+ f'server_type={self.server_type},'
+ f'redis_connection={self.redis_connection}]'
+ )
def __eq__(self, obj):
return isinstance(obj, ClusterNode) and obj.name == self.name
@@ -1135,9 +1135,8 @@ class NodesManager:
if self.slots_cache.get(slot) is None or \
len(self.slots_cache[slot]) == 0:
raise SlotNotCoveredError(
- 'Slot "{0}" not covered by the cluster. '
- '"require_full_coverage={1}"'.format(
- slot, self._require_full_coverage)
+ f'Slot "{slot}" not covered by the cluster. '
+ f'"require_full_coverage={self._require_full_coverage}"'
)
if read_from_replicas is True:
@@ -1196,7 +1195,7 @@ class NodesManager:
except Exception as e:
raise RedisClusterException(
'ERROR sending "config get cluster-require-full-coverage"'
- ' command to redis server: {0}, {1}'.format(node.name, e)
+ f' command to redis server: {node.name}, {e}'
)
# at least one node should have cluster-require-full-coverage yes
@@ -1269,7 +1268,7 @@ class NodesManager:
msg = e.__str__
log.exception('An exception occurred while trying to'
' initialize the cluster using the seed node'
- ' {0}:\n{1}'.format(startup_node.name, msg))
+ f' {startup_node.name}:\n{msg}')
continue
except ResponseError as e:
log.exception(
@@ -1283,15 +1282,13 @@ class NodesManager:
else:
raise RedisClusterException(
'ERROR sending "cluster slots" command to redis '
- 'server: {0}. error: {1}'.format(
- startup_node, message)
+ f'server: {startup_node}. error: {message}'
)
except Exception as e:
message = e.__str__()
raise RedisClusterException(
'ERROR sending "cluster slots" command to redis '
- 'server: {0}. error: {1}'.format(
- startup_node, message)
+ f'server: {startup_node}. error: {message}'
)
# CLUSTER SLOTS command results in the following output:
@@ -1342,17 +1339,16 @@ class NodesManager:
else:
# Validate that 2 nodes want to use the same slot cache
# setup
- if tmp_slots[i][0].name != target_node.name:
+ tmp_slot = tmp_slots[i][0]
+ if tmp_slot.name != target_node.name:
disagreements.append(
- '{0} vs {1} on slot: {2}'.format(
- tmp_slots[i][0].name, target_node.name, i)
+ f'{tmp_slot.name} vs {target_node.name} on slot: {i}'
)
if len(disagreements) > 5:
raise RedisClusterException(
- 'startup_nodes could not agree on a valid'
- ' slots cache: {0}'.format(
- ", ".join(disagreements))
+ f'startup_nodes could not agree on a valid '
+ f'slots cache: {", ".join(disagreements)}'
)
if not startup_nodes_reachable:
@@ -1370,9 +1366,8 @@ class NodesManager:
# Despite the requirement that the slots be covered, there
# isn't a full coverage
raise RedisClusterException(
- 'All slots are not covered after query all startup_nodes.'
- ' {0} of {1} covered...'.format(
- len(self.slots_cache), REDIS_CLUSTER_HASH_SLOTS)
+ f'All slots are not covered after query all startup_nodes. '
+ f'{len(self.slots_cache)} of {REDIS_CLUSTER_HASH_SLOTS} covered...'
)
elif not fully_covered and not self._require_full_coverage:
# The user set require_full_coverage to False.
@@ -1389,8 +1384,7 @@ class NodesManager:
'cluster-require-full-coverage configuration to no on '
'all of the cluster nodes if you wish the cluster to '
'be able to serve without being fully covered.'
- ' {0} of {1} covered...'.format(
- len(self.slots_cache), REDIS_CLUSTER_HASH_SLOTS)
+ f'{len(self.slots_cache)} of {REDIS_CLUSTER_HASH_SLOTS} covered...'
)
# Set the tmp variables to the real variables
@@ -1495,8 +1489,7 @@ class ClusterPubSub(PubSub):
"""
if node is None or redis_cluster.get_node(node_name=node.name) is None:
raise RedisClusterException(
- "Node {0}:{1} doesn't exist in the cluster"
- .format(host, port))
+ f"Node {host}:{port} doesn't exist in the cluster")
def execute_command(self, *args, **kwargs):
"""
@@ -1585,7 +1578,7 @@ class ClusterPipeline(RedisCluster):
def __repr__(self):
"""
"""
- return "{0}".format(type(self).__name__)
+ return f"{type(self).__name__}"
def __enter__(self):
"""
@@ -1645,8 +1638,10 @@ class ClusterPipeline(RedisCluster):
Provides extra context to the exception prior to it being handled
"""
cmd = ' '.join(map(safe_str, command))
- msg = 'Command # %d (%s) of pipeline caused error: %s' % (
- number, cmd, exception.args[0])
+ msg = (
+ f'Command # {number} ({cmd}) of pipeline '
+ f'caused error: {exception.args[0]}'
+ )
exception.args = (msg,) + exception.args[1:]
def execute(self, raise_on_error=True):
@@ -1813,8 +1808,8 @@ class ClusterPipeline(RedisCluster):
# if we have more commands to attempt, we've run into problems.
# collect all the commands we are allowed to retry.
# (MOVED, ASK, or connection errors or timeout errors)
- attempt = sorted([c for c in attempt
- if isinstance(c.result, ERRORS_ALLOW_RETRY)],
+ attempt = sorted((c for c in attempt
+ if isinstance(c.result, ERRORS_ALLOW_RETRY)),
key=lambda x: x.position)
if attempt and allow_redirections:
# RETRY MAGIC HAPPENS HERE!
@@ -1835,12 +1830,12 @@ class ClusterPipeline(RedisCluster):
# If a lot of commands have failed, we'll be setting the
# flag to rebuild the slots table from scratch.
# So MOVED errors should correct themselves fairly quickly.
- msg = 'An exception occurred during pipeline execution. ' \
- 'args: {0}, error: {1} {2}'.\
- format(attempt[-1].args,
- type(attempt[-1].result).__name__,
- str(attempt[-1].result))
- log.exception(msg)
+ log.exception(
+ f'An exception occurred during pipeline execution. '
+ f'args: {attempt[-1].args}, '
+ f'error: {type(attempt[-1].result).__name__} '
+ f'{str(attempt[-1].result)}'
+ )
self.reinitialize_counter += 1
if self._should_reinitialized():
self.nodes_manager.initialize()
@@ -1848,8 +1843,7 @@ class ClusterPipeline(RedisCluster):
try:
# send each command individually like we
# do in the main client.
- c.result = super(ClusterPipeline, self). \
- execute_command(*c.args, **c.options)
+ c.result = super().execute_command(*c.args, **c.options)
except RedisError as e:
c.result = e
@@ -1933,8 +1927,8 @@ def block_pipeline_command(func):
def inner(*args, **kwargs):
raise RedisClusterException(
- "ERROR: Calling pipelined function {0} is blocked when "
- "running redis in cluster mode...".format(func.__name__))
+ f"ERROR: Calling pipelined function {func.__name__} is blocked when "
+ f"running redis in cluster mode...")
return inner
@@ -1977,7 +1971,7 @@ ClusterPipeline.readwrite = block_pipeline_command(RedisCluster.readwrite)
ClusterPipeline.readonly = block_pipeline_command(RedisCluster.readonly)
-class PipelineCommand(object):
+class PipelineCommand:
"""
"""
@@ -1992,7 +1986,7 @@ class PipelineCommand(object):
self.asking = False
-class NodeCommands(object):
+class NodeCommands:
"""
"""
diff --git a/redis/commands/cluster.py b/redis/commands/cluster.py
index 6c7740d..e6b0a08 100644
--- a/redis/commands/cluster.py
+++ b/redis/commands/cluster.py
@@ -228,8 +228,7 @@ class ClusterManagementCommands:
if _type is not None:
client_types = ('normal', 'master', 'slave', 'pubsub')
if str(_type).lower() not in client_types:
- raise DataError("CLIENT KILL type must be one of %r" % (
- client_types,))
+ raise DataError(f"CLIENT KILL type must be one of {client_types!r}")
args.extend((b'TYPE', _type))
if skipme is not None:
if not isinstance(skipme, bool):
@@ -267,8 +266,7 @@ class ClusterManagementCommands:
if _type is not None:
client_types = ('normal', 'master', 'replica', 'pubsub')
if str(_type).lower() not in client_types:
- raise DataError("CLIENT LIST _type must be one of %r" % (
- client_types,))
+ raise DataError(f"CLIENT LIST _type must be one of {client_types!r}")
return self.execute_command('CLIENT LIST',
b'TYPE',
_type,
@@ -302,7 +300,7 @@ class ClusterManagementCommands:
"""
replies = ['ON', 'OFF', 'SKIP']
if reply not in replies:
- raise DataError('CLIENT REPLY must be one of %r' % replies)
+ raise DataError(f'CLIENT REPLY must be one of {replies!r}')
return self.execute_command("CLIENT REPLY", reply,
target_nodes=target_nodes)
@@ -640,11 +638,10 @@ class ClusterManagementCommands:
# check validity
supported_algo = ['LCS']
if algo not in supported_algo:
- raise DataError("The supported algorithms are: %s"
- % (', '.join(supported_algo)))
+ supported_algos_str = ', '.join(supported_algo)
+ raise DataError(f"The supported algorithms are: {supported_algos_str}")
if specific_argument not in ['keys', 'strings']:
- raise DataError("specific_argument can be only"
- " keys or strings")
+ raise DataError("specific_argument can be only keys or strings")
if len and idx:
raise DataError("len and idx cannot be provided together.")
@@ -788,8 +785,7 @@ class ClusterCommands(ClusterManagementCommands, ClusterMultiKeyCommands,
if option:
if option.upper() not in ['FORCE', 'TAKEOVER']:
raise RedisError(
- 'Invalid option for CLUSTER FAILOVER command: {0}'.format(
- option))
+ f'Invalid option for CLUSTER FAILOVER command: {option}')
else:
return self.execute_command('CLUSTER FAILOVER', option,
target_nodes=target_node)
@@ -880,7 +876,7 @@ class ClusterCommands(ClusterManagementCommands, ClusterMultiKeyCommands,
raise RedisError('For "stable" state please use '
'cluster_setslot_stable')
else:
- raise RedisError('Invalid slot state: {0}'.format(state))
+ raise RedisError(f'Invalid slot state: {state}')
def cluster_setslot_stable(self, slot_id):
"""
diff --git a/redis/commands/core.py b/redis/commands/core.py
index 64e3b6d..0285f80 100644
--- a/redis/commands/core.py
+++ b/redis/commands/core.py
@@ -227,8 +227,8 @@ class ACLCommands:
elif password.startswith(b'-'):
pieces.append(b'<%s' % password[1:])
else:
- raise DataError('Password %d must be prefixeed with a '
- '"+" to add or a "-" to remove' % i)
+ raise DataError(f'Password {i} must be prefixed with a '
+ f'"+" to add or a "-" to remove')
if hashed_passwords:
# as most users will have only one password, allow remove_passwords
@@ -241,8 +241,8 @@ class ACLCommands:
elif hashed_password.startswith(b'-'):
pieces.append(b'!%s' % hashed_password[1:])
else:
- raise DataError('Hashed %d password must be prefixeed '
- 'with a "+" to add or a "-" to remove' % i)
+ raise DataError(f'Hashed password {i} must be prefixed with a '
+ f'"+" to add or a "-" to remove')
if nopass:
pieces.append(b'nopass')
@@ -260,16 +260,18 @@ class ACLCommands:
elif category.startswith(b'-'):
pieces.append(b'-@%s' % category[1:])
else:
- raise DataError('Category "%s" must be prefixed with '
- '"+" or "-"'
- % encoder.decode(category, force=True))
+ raise DataError(
+ f'Category "{encoder.decode(category, force=True)}" '
+ 'must be prefixed with "+" or "-"'
+ )
if commands:
for cmd in commands:
cmd = encoder.encode(cmd)
if not cmd.startswith(b'+') and not cmd.startswith(b'-'):
- raise DataError('Command "%s" must be prefixed with '
- '"+" or "-"'
- % encoder.decode(cmd, force=True))
+ raise DataError(
+ f'Command "{encoder.decode(cmd, force=True)}" '
+ 'must be prefixed with "+" or "-"'
+ )
pieces.append(cmd)
if keys:
@@ -342,8 +344,7 @@ class ManagementCommands:
if _type is not None:
client_types = ('normal', 'master', 'slave', 'pubsub')
if str(_type).lower() not in client_types:
- raise DataError("CLIENT KILL type must be one of %r" % (
- client_types,))
+ raise DataError(f"CLIENT KILL type must be one of {client_types!r}")
args.extend((b'TYPE', _type))
if skipme is not None:
if not isinstance(skipme, bool):
@@ -388,8 +389,7 @@ class ManagementCommands:
if _type is not None:
client_types = ('normal', 'master', 'replica', 'pubsub')
if str(_type).lower() not in client_types:
- raise DataError("CLIENT LIST _type must be one of %r" % (
- client_types,))
+ raise DataError(f"CLIENT LIST _type must be one of {client_types!r}")
args.append(b'TYPE')
args.append(_type)
if not isinstance(client_id, list):
@@ -434,7 +434,7 @@ class ManagementCommands:
"""
replies = ['ON', 'OFF', 'SKIP']
if reply not in replies:
- raise DataError('CLIENT REPLY must be one of %r' % replies)
+ raise DataError(f'CLIENT REPLY must be one of {replies!r}')
return self.execute_command("CLIENT REPLY", reply)
def client_id(self):
@@ -551,7 +551,7 @@ class ManagementCommands:
return self.execute_command('CONFIG REWRITE')
def cluster(self, cluster_arg, *args):
- return self.execute_command('CLUSTER %s' % cluster_arg.upper(), *args)
+ return self.execute_command(f'CLUSTER {cluster_arg.upper()}', *args)
def dbsize(self):
"""
@@ -1086,7 +1086,7 @@ class BasicKeyCommands:
For more information check https://redis.io/commands/getex
"""
- opset = set([ex, px, exat, pxat])
+ opset = {ex, px, exat, pxat}
if len(opset) > 2 or len(opset) > 1 and persist:
raise DataError("``ex``, ``px``, ``exat``, ``pxat``, "
"and ``persist`` are mutually exclusive.")
@@ -1554,11 +1554,10 @@ class BasicKeyCommands:
# check validity
supported_algo = ['LCS']
if algo not in supported_algo:
- raise DataError("The supported algorithms are: %s"
- % (', '.join(supported_algo)))
+ supported_algos_str = ', '.join(supported_algo)
+ raise DataError(f"The supported algorithms are: {supported_algos_str}")
if specific_argument not in ['keys', 'strings']:
- raise DataError("specific_argument can be only"
- " keys or strings")
+ raise DataError("specific_argument can be only keys or strings")
if len and idx:
raise DataError("len and idx cannot be provided together.")
@@ -3466,8 +3465,8 @@ class HashCommands:
For more information check https://redis.io/commands/hmset
"""
warnings.warn(
- '%s.hmset() is deprecated. Use %s.hset() instead.'
- % (self.__class__.__name__, self.__class__.__name__),
+ f'{self.__class__.__name__}.hmset() is deprecated. '
+ f'Use {self.__class__.__name__}.hset() instead.',
DeprecationWarning,
stacklevel=2,
)
diff --git a/redis/commands/helpers.py b/redis/commands/helpers.py
index 5e8ff49..dc5705b 100644
--- a/redis/commands/helpers.py
+++ b/redis/commands/helpers.py
@@ -113,4 +113,4 @@ def quote_string(v):
v = v.replace('"', '\\"')
- return '"{}"'.format(v)
+ return f'"{v}"'
diff --git a/redis/commands/json/path.py b/redis/commands/json/path.py
index 6d87045..f0a413a 100644
--- a/redis/commands/json/path.py
+++ b/redis/commands/json/path.py
@@ -1,4 +1,4 @@
-class Path(object):
+class Path:
"""This class represents a path in a JSON value."""
strPath = ""
diff --git a/redis/commands/parser.py b/redis/commands/parser.py
index d8b0327..26b190c 100644
--- a/redis/commands/parser.py
+++ b/redis/commands/parser.py
@@ -46,8 +46,9 @@ class CommandsParser:
# version has changed, the commands may not be current
self.initialize(redis_conn)
if cmd_name not in self.commands:
- raise RedisError("{0} command doesn't exist in Redis "
- "commands".format(cmd_name.upper()))
+ raise RedisError(
+ f"{cmd_name.upper()} command doesn't exist in Redis commands"
+ )
command = self.commands.get(cmd_name)
if 'movablekeys' in command['flags']:
diff --git a/redis/commands/search/__init__.py b/redis/commands/search/__init__.py
index 8320ad4..a30cebe 100644
--- a/redis/commands/search/__init__.py
+++ b/redis/commands/search/__init__.py
@@ -7,7 +7,7 @@ class Search(SearchCommands):
It abstracts the API of the module and lets you just use the engine.
"""
- class BatchIndexer(object):
+ class BatchIndexer:
"""
A batch indexer allows you to automatically batch
document indexing in pipelines, flushing it every N documents.
diff --git a/redis/commands/search/aggregation.py b/redis/commands/search/aggregation.py
index 3d71329..b1ac6b0 100644
--- a/redis/commands/search/aggregation.py
+++ b/redis/commands/search/aggregation.py
@@ -1,7 +1,7 @@
FIELDNAME = object()
-class Limit(object):
+class Limit:
def __init__(self, offset=0, count=0):
self.offset = offset
self.count = count
@@ -13,7 +13,7 @@ class Limit(object):
return []
-class Reducer(object):
+class Reducer:
"""
Base reducer object for all reducers.
@@ -55,7 +55,7 @@ class Reducer(object):
return self._args
-class SortDirection(object):
+class SortDirection:
"""
This special class is used to indicate sort direction.
"""
@@ -82,7 +82,7 @@ class Desc(SortDirection):
DIRSTRING = "DESC"
-class Group(object):
+class Group:
"""
This object automatically created in the `AggregateRequest.group_by()`
"""
@@ -109,7 +109,7 @@ class Group(object):
return ret
-class Projection(object):
+class Projection:
"""
This object automatically created in the `AggregateRequest.apply()`
"""
@@ -126,7 +126,7 @@ class Projection(object):
return ret
-class SortBy(object):
+class SortBy:
"""
This object automatically created in the `AggregateRequest.sort_by()`
"""
@@ -151,7 +151,7 @@ class SortBy(object):
return ret
-class AggregateRequest(object):
+class AggregateRequest:
"""
Aggregation request which can be passed to `Client.aggregate`.
"""
@@ -370,7 +370,7 @@ class AggregateRequest(object):
return ret
-class Cursor(object):
+class Cursor:
def __init__(self, cid):
self.cid = cid
self.max_idle = 0
@@ -385,16 +385,15 @@ class Cursor(object):
return args
-class AggregateResult(object):
+class AggregateResult:
def __init__(self, rows, cursor, schema):
self.rows = rows
self.cursor = cursor
self.schema = schema
def __repr__(self):
- return "<{} at 0x{:x} Rows={}, Cursor={}>".format(
- self.__class__.__name__,
- id(self),
- len(self.rows),
- self.cursor.cid if self.cursor else -1,
+ cid = self.cursor.cid if self.cursor else -1
+ return (
+ f"<{self.__class__.__name__} at 0x{id(self):x} "
+ f"Rows={len(self.rows)}, Cursor={cid}>"
)
diff --git a/redis/commands/search/commands.py b/redis/commands/search/commands.py
index ed58255..c19cb93 100644
--- a/redis/commands/search/commands.py
+++ b/redis/commands/search/commands.py
@@ -348,7 +348,7 @@ class SearchCommands:
# convert the query from a text to a query object
query = Query(query)
if not isinstance(query, Query):
- raise ValueError("Bad query type %s" % type(query))
+ raise ValueError(f"Bad query type {type(query)}")
args += query.get_args()
return args, query
diff --git a/redis/commands/search/document.py b/redis/commands/search/document.py
index 0d4255d..5b30505 100644
--- a/redis/commands/search/document.py
+++ b/redis/commands/search/document.py
@@ -1,4 +1,4 @@
-class Document(object):
+class Document:
"""
Represents a single document in a result set
"""
@@ -10,4 +10,4 @@ class Document(object):
setattr(self, k, v)
def __repr__(self):
- return "Document %s" % self.__dict__
+ return f"Document {self.__dict__}"
diff --git a/redis/commands/search/field.py b/redis/commands/search/field.py
index 45114a4..076c872 100644
--- a/redis/commands/search/field.py
+++ b/redis/commands/search/field.py
@@ -1,4 +1,4 @@
-class Field(object):
+class Field:
NUMERIC = "NUMERIC"
TEXT = "TEXT"
diff --git a/redis/commands/search/indexDefinition.py b/redis/commands/search/indexDefinition.py
index 4fbc609..0c7a3b0 100644
--- a/redis/commands/search/indexDefinition.py
+++ b/redis/commands/search/indexDefinition.py
@@ -8,7 +8,7 @@ class IndexType(Enum):
JSON = 2
-class IndexDefinition(object):
+class IndexDefinition:
"""IndexDefinition is used to define a index definition for automatic
indexing on Hash or Json update."""
@@ -38,8 +38,7 @@ class IndexDefinition(object):
elif index_type is IndexType.JSON:
self.args.extend(["ON", "JSON"])
elif index_type is not None:
- raise RuntimeError("index_type must be one of {}".
- format(list(IndexType)))
+ raise RuntimeError(f"index_type must be one of {list(IndexType)}")
def _appendPrefix(self, prefix):
"""Append PREFIX."""
diff --git a/redis/commands/search/query.py b/redis/commands/search/query.py
index 85a8255..5534f7b 100644
--- a/redis/commands/search/query.py
+++ b/redis/commands/search/query.py
@@ -1,4 +1,4 @@
-class Query(object):
+class Query:
"""
Query is used to build complex queries that have more parameters than just
the query string. The query string is set in the constructor, and other
@@ -291,7 +291,7 @@ class Query(object):
return self
-class Filter(object):
+class Filter:
def __init__(self, keyword, field, *args):
self.args = [keyword, field] + list(args)
@@ -303,8 +303,8 @@ class NumericFilter(Filter):
def __init__(self, field, minval, maxval, minExclusive=False,
maxExclusive=False):
args = [
- minval if not minExclusive else "({}".format(minval),
- maxval if not maxExclusive else "({}".format(maxval),
+ minval if not minExclusive else f"({minval}",
+ maxval if not maxExclusive else f"({maxval}",
]
Filter.__init__(self, "FILTER", field, *args)
@@ -320,6 +320,6 @@ class GeoFilter(Filter):
Filter.__init__(self, "GEOFILTER", field, lon, lat, radius, unit)
-class SortbyField(object):
+class SortbyField:
def __init__(self, field, asc=True):
self.args = [field, "ASC" if asc else "DESC"]
diff --git a/redis/commands/search/querystring.py b/redis/commands/search/querystring.py
index aecd3b8..ffba542 100644
--- a/redis/commands/search/querystring.py
+++ b/redis/commands/search/querystring.py
@@ -61,7 +61,7 @@ def geo(lat, lon, radius, unit="km"):
return GeoValue(lat, lon, radius, unit)
-class Value(object):
+class Value:
@property
def combinable(self):
"""
@@ -134,7 +134,7 @@ class GeoValue(Value):
self.unit = unit
-class Node(object):
+class Node:
def __init__(self, *children, **kwparams):
"""
Create a node
@@ -197,13 +197,11 @@ class Node(object):
def join_fields(self, key, vals):
if len(vals) == 1:
- return [BaseNode("@{}:{}".format(key, vals[0].to_string()))]
+ return [BaseNode(f"@{key}:{vals[0].to_string()}")]
if not vals[0].combinable:
- return [BaseNode("@{}:{}".format(key,
- v.to_string())) for v in vals]
+ return [BaseNode(f"@{key}:{v.to_string()}") for v in vals]
s = BaseNode(
- "@{}:({})".format(key,
- self.JOINSTR.join(v.to_string() for v in vals))
+ f"@{key}:({self.JOINSTR.join(v.to_string() for v in vals)})"
)
return [s]
@@ -220,9 +218,7 @@ class Node(object):
def to_string(self, with_parens=None):
with_parens = self._should_use_paren(with_parens)
pre, post = ("(", ")") if with_parens else ("", "")
- return "{}{}{}".format(
- pre, self.JOINSTR.join(n.to_string() for n in self.params), post
- )
+ return f"{pre}{self.JOINSTR.join(n.to_string() for n in self.params)}{post}"
def _should_use_paren(self, optval):
if optval is not None:
@@ -235,7 +231,7 @@ class Node(object):
class BaseNode(Node):
def __init__(self, s):
- super(BaseNode, self).__init__()
+ super().__init__()
self.s = str(s)
def to_string(self, with_parens=None):
@@ -268,7 +264,7 @@ class DisjunctNode(IntersectNode):
def to_string(self, with_parens=None):
with_parens = self._should_use_paren(with_parens)
- ret = super(DisjunctNode, self).to_string(with_parens=False)
+ ret = super().to_string(with_parens=False)
if with_parens:
return "(-" + ret + ")"
else:
@@ -294,7 +290,7 @@ class OptionalNode(IntersectNode):
def to_string(self, with_parens=None):
with_parens = self._should_use_paren(with_parens)
- ret = super(OptionalNode, self).to_string(with_parens=False)
+ ret = super().to_string(with_parens=False)
if with_parens:
return "(~" + ret + ")"
else:
diff --git a/redis/commands/search/reducers.py b/redis/commands/search/reducers.py
index 6cbbf2f..41ed11a 100644
--- a/redis/commands/search/reducers.py
+++ b/redis/commands/search/reducers.py
@@ -3,7 +3,7 @@ from .aggregation import Reducer, SortDirection
class FieldOnlyReducer(Reducer):
def __init__(self, field):
- super(FieldOnlyReducer, self).__init__(field)
+ super().__init__(field)
self._field = field
@@ -15,7 +15,7 @@ class count(Reducer):
NAME = "COUNT"
def __init__(self):
- super(count, self).__init__()
+ super().__init__()
class sum(FieldOnlyReducer):
@@ -26,7 +26,7 @@ class sum(FieldOnlyReducer):
NAME = "SUM"
def __init__(self, field):
- super(sum, self).__init__(field)
+ super().__init__(field)
class min(FieldOnlyReducer):
@@ -37,7 +37,7 @@ class min(FieldOnlyReducer):
NAME = "MIN"
def __init__(self, field):
- super(min, self).__init__(field)
+ super().__init__(field)
class max(FieldOnlyReducer):
@@ -48,7 +48,7 @@ class max(FieldOnlyReducer):
NAME = "MAX"
def __init__(self, field):
- super(max, self).__init__(field)
+ super().__init__(field)
class avg(FieldOnlyReducer):
@@ -59,7 +59,7 @@ class avg(FieldOnlyReducer):
NAME = "AVG"
def __init__(self, field):
- super(avg, self).__init__(field)
+ super().__init__(field)
class tolist(FieldOnlyReducer):
@@ -70,7 +70,7 @@ class tolist(FieldOnlyReducer):
NAME = "TOLIST"
def __init__(self, field):
- super(tolist, self).__init__(field)
+ super().__init__(field)
class count_distinct(FieldOnlyReducer):
@@ -82,7 +82,7 @@ class count_distinct(FieldOnlyReducer):
NAME = "COUNT_DISTINCT"
def __init__(self, field):
- super(count_distinct, self).__init__(field)
+ super().__init__(field)
class count_distinctish(FieldOnlyReducer):
@@ -104,7 +104,7 @@ class quantile(Reducer):
NAME = "QUANTILE"
def __init__(self, field, pct):
- super(quantile, self).__init__(field, str(pct))
+ super().__init__(field, str(pct))
self._field = field
@@ -116,7 +116,7 @@ class stddev(FieldOnlyReducer):
NAME = "STDDEV"
def __init__(self, field):
- super(stddev, self).__init__(field)
+ super().__init__(field)
class first_value(Reducer):
@@ -155,7 +155,7 @@ class first_value(Reducer):
args = [field]
if fieldstrs:
args += ["BY"] + fieldstrs
- super(first_value, self).__init__(*args)
+ super().__init__(*args)
self._field = field
@@ -174,5 +174,5 @@ class random_sample(Reducer):
**size**: Return this many items (can be less)
"""
args = [field, str(size)]
- super(random_sample, self).__init__(*args)
+ super().__init__(*args)
self._field = field
diff --git a/redis/commands/search/result.py b/redis/commands/search/result.py
index 9cd922a..57ba53d 100644
--- a/redis/commands/search/result.py
+++ b/redis/commands/search/result.py
@@ -2,7 +2,7 @@ from .document import Document
from ._util import to_string
-class Result(object):
+class Result:
"""
Represents the result of a search query, and has an array of Document
objects
@@ -70,4 +70,4 @@ class Result(object):
self.docs.append(doc)
def __repr__(self):
- return "Result{%d total, docs: %s}" % (self.total, self.docs)
+ return f"Result{{{self.total} total, docs: {self.docs}}}"
diff --git a/redis/commands/search/suggestion.py b/redis/commands/search/suggestion.py
index 3401af9..6d295a6 100644
--- a/redis/commands/search/suggestion.py
+++ b/redis/commands/search/suggestion.py
@@ -1,7 +1,7 @@
from ._util import to_string
-class Suggestion(object):
+class Suggestion:
"""
Represents a single suggestion being sent or returned from the
autocomplete server
@@ -16,7 +16,7 @@ class Suggestion(object):
return self.string
-class SuggestionParser(object):
+class SuggestionParser:
"""
Internal class used to parse results from the `SUGGET` command.
This needs to consume either 1, 2, or 3 values at a time from
diff --git a/redis/commands/timeseries/info.py b/redis/commands/timeseries/info.py
index 3b89503..2b8acd1 100644
--- a/redis/commands/timeseries/info.py
+++ b/redis/commands/timeseries/info.py
@@ -2,7 +2,7 @@ from .utils import list_to_dict
from ..helpers import nativestr
-class TSInfo(object):
+class TSInfo:
"""
Hold information and statistics on the time-series.
Can be created using ``tsinfo`` command
diff --git a/redis/connection.py b/redis/connection.py
index 6ff3650..ef3a667 100755
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -107,8 +107,8 @@ class Encoder:
elif not isinstance(value, str):
# a value we don't know how to deal with. throw an error
typename = type(value).__name__
- raise DataError("Invalid input of type: '%s'. Convert to a "
- "bytes, string, int or float first." % typename)
+ raise DataError(f"Invalid input of type: '{typename}'. "
+ f"Convert to a bytes, string, int or float first.")
if isinstance(value, str):
value = value.encode(self.encoding, self.encoding_errors)
return value
@@ -214,8 +214,7 @@ class SocketBuffer:
allowed = NONBLOCKING_EXCEPTION_ERROR_NUMBERS.get(ex.__class__, -1)
if not raise_on_timeout and ex.errno == allowed:
return False
- raise ConnectionError("Error while reading from socket: %s" %
- (ex.args,))
+ raise ConnectionError(f"Error while reading from socket: {ex.args}")
finally:
if custom_timeout:
sock.settimeout(self.socket_timeout)
@@ -323,7 +322,7 @@ class PythonParser(BaseParser):
byte, response = raw[:1], raw[1:]
if byte not in (b'-', b'+', b':', b'$', b'*'):
- raise InvalidResponse("Protocol Error: %r" % raw)
+ raise InvalidResponse(f"Protocol Error: {raw!r}")
# server returned an error
if byte == b'-':
@@ -445,8 +444,7 @@ class HiredisParser(BaseParser):
allowed = NONBLOCKING_EXCEPTION_ERROR_NUMBERS.get(ex.__class__, -1)
if not raise_on_timeout and ex.errno == allowed:
return False
- raise ConnectionError("Error while reading from socket: %s" %
- (ex.args,))
+ raise ConnectionError(f"Error while reading from socket: {ex.args}")
finally:
if custom_timeout:
sock.settimeout(self._socket_timeout)
@@ -538,8 +536,8 @@ class Connection:
self._buffer_cutoff = 6000
def __repr__(self):
- repr_args = ','.join(['%s=%s' % (k, v) for k, v in self.repr_pieces()])
- return '%s<%s>' % (self.__class__.__name__, repr_args)
+ repr_args = ','.join([f'{k}={v}' for k, v in self.repr_pieces()])
+ return f'{self.__class__.__name__}<{repr_args}>'
def repr_pieces(self):
pieces = [
@@ -579,7 +577,7 @@ class Connection:
sock = self._connect()
except socket.timeout:
raise TimeoutError("Timeout connecting to server")
- except socket.error as e:
+ except OSError as e:
raise ConnectionError(self._error_message(e))
self._sock = sock
@@ -646,11 +644,12 @@ class Connection:
# args for socket.error can either be (errno, "message")
# or just "message"
if len(exception.args) == 1:
- return "Error connecting to %s:%s. %s." % \
- (self.host, self.port, exception.args[0])
+ return f"Error connecting to {self.host}:{self.port}. {exception.args[0]}."
else:
- return "Error %s connecting to %s:%s. %s." % \
- (exception.args[0], self.host, self.port, exception.args[1])
+ return (
+ f"Error {exception.args[0]} connecting to "
+ f"{self.host}:{self.port}. {exception.args[1]}."
+ )
def on_connect(self):
"Initialize the connection, authenticate and select a database"
@@ -734,15 +733,14 @@ class Connection:
except socket.timeout:
self.disconnect()
raise TimeoutError("Timeout writing to socket")
- except socket.error as e:
+ except OSError as e:
self.disconnect()
if len(e.args) == 1:
errno, errmsg = 'UNKNOWN', e.args[0]
else:
errno = e.args[0]
errmsg = e.args[1]
- raise ConnectionError("Error %s while writing to socket. %s." %
- (errno, errmsg))
+ raise ConnectionError(f"Error {errno} while writing to socket. {errmsg}.")
except BaseException:
self.disconnect()
raise
@@ -767,12 +765,12 @@ class Connection:
)
except socket.timeout:
self.disconnect()
- raise TimeoutError("Timeout reading from %s:%s" %
- (self.host, self.port))
- except socket.error as e:
+ raise TimeoutError(f"Timeout reading from {self.host}:{self.port}")
+ except OSError as e:
self.disconnect()
- raise ConnectionError("Error while reading from %s:%s : %s" %
- (self.host, self.port, e.args))
+ raise ConnectionError(
+ f"Error while reading from {self.host}:{self.port}"
+ f" : {e.args}")
except BaseException:
self.disconnect()
raise
@@ -867,8 +865,7 @@ class SSLConnection(Connection):
}
if ssl_cert_reqs not in CERT_REQS:
raise RedisError(
- "Invalid SSL Certificate Requirements Flag: %s" %
- ssl_cert_reqs)
+ f"Invalid SSL Certificate Requirements Flag: {ssl_cert_reqs}")
ssl_cert_reqs = CERT_REQS[ssl_cert_reqs]
self.cert_reqs = ssl_cert_reqs
self.ca_certs = ssl_ca_certs
@@ -947,11 +944,12 @@ class UnixDomainSocketConnection(Connection):
# args for socket.error can either be (errno, "message")
# or just "message"
if len(exception.args) == 1:
- return "Error connecting to unix socket: %s. %s." % \
- (self.path, exception.args[0])
+ return f"Error connecting to unix socket: {self.path}. {exception.args[0]}."
else:
- return "Error %s connecting to unix socket: %s. %s." % \
- (exception.args[0], self.path, exception.args[1])
+ return (
+ f"Error {exception.args[0]} connecting to unix socket: "
+ f"{self.path}. {exception.args[1]}."
+ )
FALSE_STRINGS = ('0', 'F', 'FALSE', 'N', 'NO')
@@ -990,7 +988,7 @@ def parse_url(url):
kwargs[name] = parser(value)
except (TypeError, ValueError):
raise ValueError(
- "Invalid value for `%s` in connection URL." % name
+ f"Invalid value for `{name}` in connection URL."
)
else:
kwargs[name] = value
@@ -1023,9 +1021,8 @@ def parse_url(url):
if url.scheme == 'rediss':
kwargs['connection_class'] = SSLConnection
else:
- valid_schemes = 'redis://, rediss://, unix://'
raise ValueError('Redis URL must specify one of the following '
- 'schemes (%s)' % valid_schemes)
+ 'schemes (redis://, rediss://, unix://)')
return kwargs
@@ -1109,9 +1106,9 @@ class ConnectionPool:
self.reset()
def __repr__(self):
- return "%s<%s>" % (
- type(self).__name__,
- repr(self.connection_class(**self.connection_kwargs)),
+ return (
+ f"{type(self).__name__}"
+ f"<{repr(self.connection_class(**self.connection_kwargs))}>"
)
def reset(self):
diff --git a/redis/sentinel.py b/redis/sentinel.py
index 3efd58f..06877bd 100644
--- a/redis/sentinel.py
+++ b/redis/sentinel.py
@@ -24,9 +24,9 @@ class SentinelManagedConnection(Connection):
def __repr__(self):
pool = self.connection_pool
- s = '%s<service=%s%%s>' % (type(self).__name__, pool.service_name)
+ s = f'{type(self).__name__}<service={pool.service_name}%s>'
if self.host:
- host_info = ',host=%s,port=%s' % (self.host, self.port)
+ host_info = f',host={self.host},port={self.port}'
s = s % host_info
return s
@@ -91,11 +91,8 @@ class SentinelConnectionPool(ConnectionPool):
self.sentinel_manager = sentinel_manager
def __repr__(self):
- return "%s<service=%s(%s)" % (
- type(self).__name__,
- self.service_name,
- self.is_master and 'master' or 'slave',
- )
+ role = 'master' if self.is_master else 'slave'
+ return f"{type(self).__name__}<service={self.service_name}({role})"
def reset(self):
super().reset()
@@ -106,7 +103,7 @@ class SentinelConnectionPool(ConnectionPool):
check = not self.is_master or \
(self.is_master and
self.master_address == (connection.host, connection.port))
- parent = super(SentinelConnectionPool, self)
+ parent = super()
return check and parent.owns_connection(connection)
def get_master_address(self):
@@ -136,10 +133,10 @@ class SentinelConnectionPool(ConnectionPool):
yield self.get_master_address()
except MasterNotFoundError:
pass
- raise SlaveNotFoundError('No slave found for %r' % (self.service_name))
+ raise SlaveNotFoundError(f'No slave found for {self.service_name!r}')
-class Sentinel(SentinelCommands, object):
+class Sentinel(SentinelCommands):
"""
Redis Sentinel cluster client
@@ -205,13 +202,10 @@ class Sentinel(SentinelCommands, object):
def __repr__(self):
sentinel_addresses = []
for sentinel in self.sentinels:
- sentinel_addresses.append('%s:%s' % (
- sentinel.connection_pool.connection_kwargs['host'],
- sentinel.connection_pool.connection_kwargs['port'],
+ sentinel_addresses.append('{host}:{port}'.format_map(
+ sentinel.connection_pool.connection_kwargs,
))
- return '%s<sentinels=[%s]>' % (
- type(self).__name__,
- ','.join(sentinel_addresses))
+ return f'{type(self).__name__}<sentinels=[{",".join(sentinel_addresses)}]>'
def check_master_state(self, state, service_name):
if not state['is_master'] or state['is_sdown'] or state['is_odown']:
@@ -240,7 +234,7 @@ class Sentinel(SentinelCommands, object):
self.sentinels[0], self.sentinels[sentinel_no] = (
sentinel, self.sentinels[0])
return state['ip'], state['port']
- raise MasterNotFoundError("No master found for %r" % (service_name,))
+ raise MasterNotFoundError(f"No master found for {service_name!r}")
def filter_slaves(self, slaves):
"Remove slaves that are in an ODOWN or SDOWN state"