diff --git a/awscli/argparser.py b/awscli/argparser.py index 6e1bd0478470..104fefdb7825 100644 --- a/awscli/argparser.py +++ b/awscli/argparser.py @@ -24,7 +24,7 @@ ) USAGE = ( "aws [options] [ ...] [parameters]\n" - "%s" % HELP_BLURB + f"{HELP_BLURB}" ) @@ -42,9 +42,7 @@ class CommandAction(argparse.Action): def __init__(self, option_strings, dest, command_table, **kwargs): self.command_table = command_table - super(CommandAction, self).__init__( - option_strings, dest, choices=self.choices, **kwargs - ) + super().__init__(option_strings, dest, choices=self.choices, **kwargs) def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values) @@ -78,14 +76,12 @@ def _check_value(self, action, value): if possible: extra = ['Maybe you meant:\n'] for word in possible: - extra.append(' * %s' % word) + extra.append(f' * {word}') msg.extend(extra) raise argparse.ArgumentError(action, '\n'.join(msg)) def parse_known_args(self, args, namespace=None): - parsed, remaining = super(CLIArgParser, self).parse_known_args( - args, namespace - ) + parsed, remaining = super().parse_known_args(args, namespace) terminal_encoding = getattr(sys.stdin, 'encoding', 'utf-8') if terminal_encoding is None: # In some cases, sys.stdin won't have an encoding set, @@ -117,7 +113,7 @@ def error(self, message): should raise an exception. """ usage_message = self.format_usage() - error_message = f'{self.prog}: error: {message}' + error_message = f'{self.prog}: [ERROR]: {message}' raise ArgParseException(f'{error_message}\n\n{usage_message}') @@ -132,7 +128,7 @@ def __init__( argument_table, prog=None, ): - super(MainArgParser, self).__init__( + super().__init__( formatter_class=self.Formatter, add_help=False, conflict_handler='resolve', @@ -145,7 +141,7 @@ def __init__( def _create_choice_help(self, choices): help_str = '' for choice in sorted(choices): - help_str += '* %s\n' % choice + help_str += f'* {choice}\n' return help_str def _build(self, command_table, version_string, argument_table): @@ -165,7 +161,7 @@ def _build(self, command_table, version_string, argument_table): class ServiceArgParser(CLIArgParser): def __init__(self, operations_table, service_name): - super(ServiceArgParser, self).__init__( + super().__init__( formatter_class=argparse.RawTextHelpFormatter, add_help=False, conflict_handler='resolve', @@ -187,7 +183,7 @@ def __init__(self, argument_table, command_table=None): # command_table is an optional subcommand_table. If it's passed # in, then we'll update the argparse to parse a 'subcommand' argument # and populate the choices field with the command table keys. - super(ArgTableArgParser, self).__init__( + super().__init__( formatter_class=self.Formatter, add_help=False, usage=USAGE, @@ -215,9 +211,7 @@ def parse_known_args(self, args, namespace=None): namespace.help = 'help' return namespace, [] else: - return super(ArgTableArgParser, self).parse_known_args( - args, namespace - ) + return super().parse_known_args(args, namespace) class SubCommandArgParser(ArgTableArgParser): @@ -230,9 +224,7 @@ class SubCommandArgParser(ArgTableArgParser): """ def parse_known_args(self, args, namespace=None): - parsed_args, remaining = super( - SubCommandArgParser, self - ).parse_known_args(args, namespace) + parsed_args, remaining = super().parse_known_args(args, namespace) if getattr(parsed_args, 'subcommand', None) is not None: new_args = self._remove_subcommand(args, parsed_args) return new_args, parsed_args.subcommand diff --git a/awscli/customizations/commands.py b/awscli/customizations/commands.py index c2c5f915e295..98192555d16e 100644 --- a/awscli/customizations/commands.py +++ b/awscli/customizations/commands.py @@ -138,9 +138,7 @@ def __call__(self, args, parsed_globals): # an arg parser and parse them. self._subcommand_table = self._build_subcommand_table() self._arg_table = self._build_arg_table() - event = 'before-building-argument-table-parser.%s' % ".".join( - self.lineage_names - ) + event = f'before-building-argument-table-parser.{".".join(self.lineage_names)}' self._session.emit( event, argument_table=self._arg_table, @@ -177,7 +175,7 @@ def __call__(self, args, parsed_globals): # a chance to process and override its value. if self._should_allow_plugins_override(cli_argument, value): override = self._session.emit_first_non_none_response( - 'process-cli-arg.%s.%s' % ('custom', self.name), + f'process-cli-arg.custom.{self.name}', cli_argument=cli_argument, value=value, operation=None, @@ -204,7 +202,7 @@ def __call__(self, args, parsed_globals): # function for this top level command. if remaining: raise ParamValidationError( - "Unknown options: %s" % ','.join(remaining) + f"Unknown options: {','.join(remaining)}" ) rc = self._run_main(parsed_args, parsed_globals) if rc is None: @@ -212,7 +210,7 @@ def __call__(self, args, parsed_globals): else: return rc - def _validate_value_against_schema(self, model, value): + def _validate_value_against_schema(self, model, value): ## noqa: F811 validate_parameters(value, model) def _should_allow_plugins_override(self, param, value): @@ -239,7 +237,7 @@ def _build_subcommand_table(self): subcommand_table[subcommand_name] = subcommand_class(self._session) name = '_'.join([c.name for c in self.lineage]) self._session.emit( - 'building-command-table.%s' % name, + f'building-command-table.{name}', command_table=subcommand_table, session=self._session, command_object=self, @@ -277,7 +275,7 @@ def _build_arg_table(self): arg_table = OrderedDict() name = '_'.join([c.name for c in self.lineage]) self._session.emit( - 'building-arg-table.%s' % name, arg_table=self.ARG_TABLE + f'building-arg-table.{name}', arg_table=self.ARG_TABLE ) for arg_data in self.ARG_TABLE: # If a custom schema was passed in, create the argument_model @@ -328,9 +326,9 @@ def lineage(self, value): def _raise_usage_error(self): lineage = ' '.join([c.name for c in self.lineage]) error_msg = ( - "usage: aws [options] %s " - "[parameters]\naws: error: too few arguments" - ) % lineage + f"usage: aws [options] {lineage} " + "[parameters]\naws: [ERROR]: too few arguments" + ) raise ParamValidationError(error_msg) def _add_customization_to_user_agent(self): @@ -348,9 +346,7 @@ def __init__( arg_table, event_handler_class=None, ): - super(BasicHelp, self).__init__( - session, command_object, command_table, arg_table - ) + super().__init__(session, command_object, command_table, arg_table) # This is defined in HelpCommand so we're matching the # casing here. if event_handler_class is None: @@ -414,7 +410,7 @@ def __call__(self, args, parsed_globals): class BasicDocHandler(OperationDocumentEventHandler): def __init__(self, help_command): - super(BasicDocHandler, self).__init__(help_command) + super().__init__(help_command) self.doc = help_command.doc def doc_description(self, help_command, **kwargs): @@ -424,9 +420,7 @@ def doc_description(self, help_command, **kwargs): def doc_synopsis_start(self, help_command, **kwargs): if not help_command.synopsis: - super(BasicDocHandler, self).doc_synopsis_start( - help_command=help_command, **kwargs - ) + super().doc_synopsis_start(help_command=help_command, **kwargs) else: self.doc.style.h2('Synopsis') self.doc.style.start_codeblock() @@ -447,14 +441,14 @@ def doc_synopsis_option(self, arg_name, help_command, **kwargs): ) self._documented_arg_groups.append(argument.group_name) elif argument.cli_type_name == 'boolean': - option_str = '%s' % argument.cli_name + option_str = f'{argument.cli_name}' elif argument.nargs == '+': - option_str = "%s [...]" % argument.cli_name + option_str = f"{argument.cli_name} [...]" else: - option_str = '%s ' % argument.cli_name + option_str = f'{argument.cli_name} ' if not (argument.required or argument.positional_arg): - option_str = '[%s]' % option_str - doc.writeln('%s' % option_str) + option_str = f'[{option_str}]' + doc.writeln(f'{option_str}') else: # A synopsis has been provided so we don't need to write @@ -463,9 +457,7 @@ def doc_synopsis_option(self, arg_name, help_command, **kwargs): def doc_synopsis_end(self, help_command, **kwargs): if not help_command.synopsis and not help_command.command_table: - super(BasicDocHandler, self).doc_synopsis_end( - help_command=help_command, **kwargs - ) + super().doc_synopsis_end(help_command=help_command, **kwargs) else: self.doc.style.end_codeblock() diff --git a/tests/functional/ddb/test_ddb.py b/tests/functional/ddb/test_ddb.py index 031398b69c85..8ca0bf6c9db2 100644 --- a/tests/functional/ddb/test_ddb.py +++ b/tests/functional/ddb/test_ddb.py @@ -18,6 +18,6 @@ def test_no_command_specified(self): _, stderr, _ = self.run_cmd('ddb', expected_rc=252) expected = ( "usage: aws [options] ddb " - "[parameters]\naws: error: too few arguments" + "[parameters]\naws: [ERROR]: too few arguments" ) self.assertIn(expected, stderr) diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py index 6bde90c4b81c..d34dc6ae023a 100644 --- a/tests/integration/test_cli.py +++ b/tests/integration/test_cli.py @@ -156,7 +156,7 @@ def test_param_with_bad_json(self): self.assertIn( "The filter 'bad-filter' is invalid", p.stderr, - "stdout: %s, stderr: %s" % (p.stdout, p.stderr), + f"stdout: {p.stdout}, stderr: {p.stderr}", ) def test_param_with_file(self): @@ -166,7 +166,7 @@ def test_param_with_file(self): with open(param_file, 'w') as f: f.write('[{"Name": "instance-id", "Values": ["i-123"]}]') self.addCleanup(os.remove, param_file) - p = aws('ec2 describe-instances --filters file://%s' % param_file) + p = aws(f'ec2 describe-instances --filters file://{param_file}') self.assertEqual(p.rc, 0) self.assertIn('Reservations', p.json) @@ -181,8 +181,7 @@ def test_streaming_output_operation(self): bucket=bucket_name, key='foobar', content='foobar contents' ) p = aws( - 's3api get-object --bucket %s --key foobar %s' - % (bucket_name, os.path.join(d, 'foobar')) + f's3api get-object --bucket {bucket_name} --key foobar {os.path.join(d, "foobar")}' ) self.assertEqual(p.rc, 0) with open(os.path.join(d, 'foobar')) as f: @@ -208,16 +207,15 @@ def test_no_sign_request(self): ) p = aws( - 's3api get-object --bucket %s --key foo %s' - % (bucket_name, os.path.join(d, 'foo')), + f's3api get-object --bucket {bucket_name} --key foo {os.path.join(d, "foo")}', env_vars=env_vars, ) # Should have credential issues. self.assertEqual(p.rc, 254) p = aws( - 's3api get-object --bucket %s --key foo ' - '%s --no-sign-request' % (bucket_name, os.path.join(d, 'foo')), + f's3api get-object --bucket {bucket_name} --key foo ' + f'{os.path.join(d, "foo")} --no-sign-request', env_vars=env_vars, ) @@ -238,10 +236,10 @@ def test_no_paginate_arg(self): self.put_object( bucket=bucket_name, key='foobar', content='foobar contents' ) - p = aws('s3api list-objects --bucket %s --no-paginate' % bucket_name) + p = aws(f's3api list-objects --bucket {bucket_name} --no-paginate') self.assertEqual(p.rc, 0, p.stdout + p.stderr) - p = aws('s3api list-objects --bucket %s' % bucket_name) + p = aws(f's3api list-objects --bucket {bucket_name}') self.assertEqual(p.rc, 0, p.stdout + p.stderr) def test_top_level_options_debug(self): @@ -261,7 +259,7 @@ def test_help_usage_top_level(self): ' [ ...] [parameters]', p.stderr, ) - self.assertIn('aws: error', p.stderr) + self.assertIn('aws: [ERROR]', p.stderr) def test_help_usage_service_level(self): p = aws('ec2') @@ -270,11 +268,11 @@ def test_help_usage_service_level(self): ' [ ...] [parameters]', p.stderr, ) - # python3: aws: error: the following arguments are required: operation - # python2: aws: error: too few arguments + # python3: aws: [ERROR]: the following arguments are required: operation + # python2: aws: [ERROR]: too few arguments # We don't care too much about the specific error message, as long # as it says we have a parse error. - self.assertIn('aws: error', p.stderr) + self.assertIn('aws: [ERROR]', p.stderr) def test_help_usage_operation_level(self): p = aws('ec2 start-instances') @@ -458,8 +456,8 @@ def test_no_pagination(self): self.put_object(bucket_name, 'foo2.txt', contents=b'bar') self.put_object(bucket_name, 'foo3.txt', contents=b'bar') p = aws( - 's3api list-objects --bucket %s ' - '--no-paginate --output json' % bucket_name + f's3api list-objects --bucket {bucket_name} ' + '--no-paginate --output json' ) # A really simple way to check that --no-paginate was # honored is to see if we have all the mirrored input @@ -476,8 +474,8 @@ def test_no_paginate_and_original_args(self): self.put_object(bucket_name, 'foo2.txt', contents=b'bar') self.put_object(bucket_name, 'foo3.txt', contents=b'bar') p = aws( - 's3api list-objects --bucket %s ' - '--max-keys 1 --no-paginate --output json' % bucket_name + f's3api list-objects --bucket {bucket_name} ' + '--max-keys 1 --no-paginate --output json' ) self.assert_no_errors(p) response_json = p.json @@ -489,8 +487,8 @@ def test_max_items(self): self.put_object(bucket_name, 'foo2.txt', contents=b'bar') self.put_object(bucket_name, 'foo3.txt', contents=b'bar') p = aws( - 's3api list-objects --bucket %s ' - '--max-items 1 --output json' % bucket_name + f's3api list-objects --bucket {bucket_name} ' + '--max-items 1 --output json' ) self.assert_no_errors(p) response_json = p.json @@ -500,8 +498,8 @@ def test_query(self): bucket_name = self.create_bucket() self.put_object(bucket_name, 'foo.txt', contents=b'bar') p = aws( - 's3api list-objects --bucket %s ' - '--query Contents[].Key --output json' % bucket_name + f's3api list-objects --bucket {bucket_name} ' + '--query Contents[].Key --output json' ) self.assert_no_errors(p) response_json = p.json @@ -522,8 +520,7 @@ def test_no_sign_requests(self): env['AWS_ACCESS_KEY_ID'] = 'foo' env['AWS_SECRET_ACCESS_KEY'] = 'bar' p = aws( - 's3api head-object --bucket %s --key public --no-sign-request' - % bucket_name, + f's3api head-object --bucket {bucket_name} --key public --no-sign-request', env_vars=env, ) self.assert_no_errors(p) @@ -532,8 +529,7 @@ def test_no_sign_requests(self): # Should fail because we're not signing the request but the object is # private. p = aws( - 's3api head-object --bucket %s --key private --no-sign-request' - % bucket_name, + f's3api head-object --bucket {bucket_name} --key private --no-sign-request', env_vars=env, ) self.assertEqual(p.rc, 254)