diff options
author | Aarni Koskela <akx@iki.fi> | 2021-11-30 17:20:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-30 17:20:43 +0200 |
commit | fbe87acf96aab583975ed3371423eb20602eccaf (patch) | |
tree | b873c3356b9c96e826c4ab0bb3efc339a00838e4 /redis | |
parent | 4db85ef574a64a2b230a3ae1ff19c9d04065a114 (diff) | |
download | redis-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-x | redis/client.py | 18 | ||||
-rw-r--r-- | redis/cluster.py | 134 | ||||
-rw-r--r-- | redis/commands/cluster.py | 20 | ||||
-rw-r--r-- | redis/commands/core.py | 45 | ||||
-rw-r--r-- | redis/commands/helpers.py | 2 | ||||
-rw-r--r-- | redis/commands/json/path.py | 2 | ||||
-rw-r--r-- | redis/commands/parser.py | 5 | ||||
-rw-r--r-- | redis/commands/search/__init__.py | 2 | ||||
-rw-r--r-- | redis/commands/search/aggregation.py | 27 | ||||
-rw-r--r-- | redis/commands/search/commands.py | 2 | ||||
-rw-r--r-- | redis/commands/search/document.py | 4 | ||||
-rw-r--r-- | redis/commands/search/field.py | 2 | ||||
-rw-r--r-- | redis/commands/search/indexDefinition.py | 5 | ||||
-rw-r--r-- | redis/commands/search/query.py | 10 | ||||
-rw-r--r-- | redis/commands/search/querystring.py | 22 | ||||
-rw-r--r-- | redis/commands/search/reducers.py | 24 | ||||
-rw-r--r-- | redis/commands/search/result.py | 4 | ||||
-rw-r--r-- | redis/commands/search/suggestion.py | 4 | ||||
-rw-r--r-- | redis/commands/timeseries/info.py | 2 | ||||
-rwxr-xr-x | redis/connection.py | 65 | ||||
-rw-r--r-- | redis/sentinel.py | 28 |
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" |