From bd2e088d614daef5b8a1408b1e68aa1f02b2909c Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Fri, 27 Feb 2026 09:37:12 -0800 Subject: [PATCH 1/9] Add logic for configure get --- awscli/customizations/configure/__init__.py | 3 +- awscli/customizations/configure/get.py | 64 +++++++++++- tests/functional/configure/test_configure.py | 14 +++ .../unit/customizations/configure/test_get.py | 97 +++++++++++++++++++ 4 files changed, 175 insertions(+), 3 deletions(-) diff --git a/awscli/customizations/configure/__init__.py b/awscli/customizations/configure/__init__.py index c8ea5b6fa999..2bb51b16e7b0 100644 --- a/awscli/customizations/configure/__init__.py +++ b/awscli/customizations/configure/__init__.py @@ -10,9 +10,10 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. - from awscli.compat import shlex +# A map between the command line parameter name and the Python object name +# For allowed sub-section types NOT_SET = '' PREDEFINED_SECTION_NAMES = 'plugins' # A map between the command line parameter name and the name used diff --git a/awscli/customizations/configure/get.py b/awscli/customizations/configure/get.py index 74c9efb66255..bbb25b77470f 100644 --- a/awscli/customizations/configure/get.py +++ b/awscli/customizations/configure/get.py @@ -11,11 +11,14 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. import logging +import re import sys from awscli.customizations.commands import BasicCommand +from awscli.customizations.exceptions import ParamValidationError +from awscli.customizations.utils import validate_mutually_exclusive -from . import PREDEFINED_SECTION_NAMES +from . import PREDEFINED_SECTION_NAMES, SUBSECTION_TYPE_ALLOWLIST LOG = logging.getLogger(__name__) @@ -35,6 +38,18 @@ class ConfigureGetCommand(BasicCommand): 'cli_type_name': 'string', 'positional_arg': True, }, + { + 'name': 'sso-session', + 'help_text': 'The name of the SSO session sub-section to retrieve from.', + 'action': 'store', + 'cli_type_name': 'string', + }, + { + 'name': 'services', + 'help_text': 'The name of the services sub-section to retrieve from.', + 'action': 'store', + 'cli_type_name': 'string', + }, ] def __init__(self, session, stream=None, error_stream=None): @@ -46,10 +61,34 @@ def __init__(self, session, stream=None, error_stream=None): self._stream = stream self._error_stream = error_stream + def _get_subsection_config_name_from_args(self, args): + # Validate mutual exclusivity of sub-section type parameters + groups = [[v['param_name']] for v in SUBSECTION_TYPE_ALLOWLIST.values()] + validate_mutually_exclusive(args, *groups) + + subsection_name = None + subsection_config_name = None + + for section_properties in SUBSECTION_TYPE_ALLOWLIST.values(): + param_value = getattr(args, section_properties['param_name']) + if param_value is not None: + subsection_name = param_value + subsection_config_name = section_properties['full_config_name'] + break + + return (subsection_config_name, subsection_name) + def _run_main(self, args, parsed_globals): varname = args.varname + section_type, section_name = self._get_subsection_config_name_from_args(args) - if '.' not in varname: + if section_type: + value = self._get_subsection_property( + section_type.replace("-", "_"), + section_name, + varname + ) + elif '.' not in varname: # get_scoped_config() returns the config variables in the config # file (not the logical_var names), which is what we want. config = self._session.get_scoped_config() @@ -121,3 +160,24 @@ def _get_dotted_config_value(self, varname): except AttributeError: value = None return value + + def _get_subsection_property(self, section_type, section_name, varname): + full_config = self._session.full_config + + if section_type not in full_config: + return None + + section_type_config = full_config[section_type] + section_config = section_type_config.get(section_name, None) + + # Handle nested properties + if '.' in varname: + parts = varname.split('.') + if len(parts) == 2: + value = section_config.get(parts[0]) + if isinstance(value, dict): + return value.get(parts[1]) + else: + return None + else: + return section_config.get(varname) diff --git a/tests/functional/configure/test_configure.py b/tests/functional/configure/test_configure.py index fc53f68e37fb..c32d4cdb86af 100644 --- a/tests/functional/configure/test_configure.py +++ b/tests/functional/configure/test_configure.py @@ -129,6 +129,20 @@ def test_get_fq_with_quoted_profile_name(self): ) self.assertEqual(stdout.strip(), "testing_access_key") + def test_get_command_with_subsection_set(self): + self.set_config_file_contents( + "\n" + "[default]\n" + "aws_access_key_id=default_access_key\n" + "\n" + "[sso-session my-sso-session]\n" + "sso_region = us-west-2\n" + ) + stdout, _, _ = self.run_cmd( + "configure get --sso-session my-sso-session sso_region", + ) + self.assertEqual(stdout.strip(), "us-west-2") + def test_set_with_config_file_no_exist(self): self.run_cmd("configure set region us-west-1") self.assertEqual( diff --git a/tests/unit/customizations/configure/test_get.py b/tests/unit/customizations/configure/test_get.py index d1e7cd6d92ba..a5407b9638d8 100644 --- a/tests/unit/customizations/configure/test_get.py +++ b/tests/unit/customizations/configure/test_get.py @@ -143,3 +143,100 @@ def test_get_non_string_returns_error(self): self.assertEqual(rc, 1) self.assertEqual(stream.getvalue(), '') self.assertEqual(error_stream.getvalue(), '') + + +class TestConfigureGetCommandSubSections(unittest.TestCase): + def create_command(self, session): + stdout = StringIO() + stderr = StringIO() + command = ConfigureGetCommand(session, stdout, stderr) + return stdout, stderr, command + + def test_get_simple_property(self): + session = FakeSession({}) + session.full_config = { + 'sso_sessions': { + 'my-session': { + 'sso_region': 'us-west-2', + 'sso_start_url': 'https://example.awsapps.com/start' + } + } + } + stream, error_stream, config_get = self.create_command(session) + rc = config_get(args=['--sso-session', 'my-session', 'sso_region'], + parsed_globals=None) + rendered = stream.getvalue() + self.assertEqual(rendered.strip(), 'us-west-2') + self.assertEqual(rc, 0) + + + def test_get_nested_property(self): + session = FakeSession({}) + session.full_config = { + 'services': { + 'my-services': { + 's3': { + 'endpoint_url': 'http://localhost:4566', + } + } + } + } + stream, error_stream, config_get = self.create_command(session) + rc = config_get(args=['--services', 'my-services', 's3.endpoint_url'], + parsed_globals=None) + rendered = stream.getvalue() + self.assertEqual(rendered.strip(), 'http://localhost:4566') + self.assertEqual(rc, 0) + + def test_non_existent_subsection_returns_exit_code_1(self): + session = FakeSession({}) + session.full_config = {} + stream, error_stream, config_get = self.create_command(session) + rc = config_get(args=['--sso-session', 'non-existent', 'sso_region'], + parsed_globals=None) + + self.assertEqual(rc, 1) + self.assertEqual(stream.getvalue(), '') + + def test_non_existent_property_returns_exit_code_1(self): + session = FakeSession({}) + session.full_config = { + 'sso_sessions': { + 'my-session': { + 'sso_region': 'us-west-2' + } + } + } + stream, error_stream, config_get = self.create_command(session) + rc = config_get(args=['--sso-session', 'my-session', 'non_existent_property'], + parsed_globals=None) + + self.assertEqual(rc, 1) + self.assertEqual(stream.getvalue(), '') + + def test_no_output_to_stdout_for_non_existent_items(self): + session = FakeSession({}) + session.full_config = {} + stream, error_stream, config_get = self.create_command(session) + + rc = config_get(args=['--sso-session', 'non-existent', 'sso_region'], + parsed_globals=None) + self.assertEqual(rc, 1) + self.assertEqual(stream.getvalue(), '') + + def test_no_output_to_stdout_for_non_existent_items_existing_subsection(self): + session = FakeSession({}) + + session.full_config = { + 'sso"sessions': { + 'my-session': { + 'sso_region': 'us-west-2' + } + } + } + + stream, error_stream, config_get = self.create_command(session) + rc = config_get(args=['--sso-session', 'my-session', 'non_existent'], + parsed_globals=None) + self.assertEqual(rc, 1) + self.assertEqual(stream.getvalue(), '') From 8dfc72bef2e620038cccb08caf1317025463dc3f Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Tue, 17 Mar 2026 11:56:42 -0700 Subject: [PATCH 2/9] Improve logic for getting subsection Rename and add more test cases to cover non-exsistent subsections and nested properties. --- awscli/customizations/configure/get.py | 37 +++++++++++----- tests/functional/configure/test_configure.py | 45 +++++++++++++++++++- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/awscli/customizations/configure/get.py b/awscli/customizations/configure/get.py index bbb25b77470f..09c8918791cc 100644 --- a/awscli/customizations/configure/get.py +++ b/awscli/customizations/configure/get.py @@ -40,13 +40,13 @@ class ConfigureGetCommand(BasicCommand): }, { 'name': 'sso-session', - 'help_text': 'The name of the SSO session sub-section to retrieve from.', + 'help_text': 'The name of the sub-section to configure.', 'action': 'store', 'cli_type_name': 'string', }, { 'name': 'services', - 'help_text': 'The name of the services sub-section to retrieve from.', + 'help_text': 'The name of the sub-section to configure.', 'action': 'store', 'cli_type_name': 'string', }, @@ -61,20 +61,35 @@ def __init__(self, session, stream=None, error_stream=None): self._stream = stream self._error_stream = error_stream + def _subsection_parameter_to_argument_name(self, parameter_name): + return parameter_name.replace("-", "_") + def _get_subsection_config_name_from_args(self, args): # Validate mutual exclusivity of sub-section type parameters - groups = [[v['param_name']] for v in SUBSECTION_TYPE_ALLOWLIST.values()] + groups = [ + [self._subsection_parameter_to_argument_name(key)] + for key in SUBSECTION_TYPE_ALLOWLIST.keys() + ] validate_mutually_exclusive(args, *groups) subsection_name = None subsection_config_name = None - for section_properties in SUBSECTION_TYPE_ALLOWLIST.values(): - param_value = getattr(args, section_properties['param_name']) - if param_value is not None: - subsection_name = param_value - subsection_config_name = section_properties['full_config_name'] - break + for ( + section_type, + section_properties, + ) in SUBSECTION_TYPE_ALLOWLIST.items(): + cli_parameter_name = self._subsection_parameter_to_argument_name( + section_type + ) + + if hasattr(args, cli_parameter_name): + subsection_name = getattr(args, cli_parameter_name) + if subsection_name is not None: + subsection_config_name = section_properties[ + 'full_config_name' + ] + break return (subsection_config_name, subsection_name) @@ -163,10 +178,10 @@ def _get_dotted_config_value(self, varname): def _get_subsection_property(self, section_type, section_name, varname): full_config = self._session.full_config - + if section_type not in full_config: return None - + section_type_config = full_config[section_type] section_config = section_type_config.get(section_name, None) diff --git a/tests/functional/configure/test_configure.py b/tests/functional/configure/test_configure.py index c32d4cdb86af..e2aab34c3f2c 100644 --- a/tests/functional/configure/test_configure.py +++ b/tests/functional/configure/test_configure.py @@ -129,7 +129,7 @@ def test_get_fq_with_quoted_profile_name(self): ) self.assertEqual(stdout.strip(), "testing_access_key") - def test_get_command_with_subsection_set(self): + def test_get_command_with_subsection(self): self.set_config_file_contents( "\n" "[default]\n" @@ -143,6 +143,49 @@ def test_get_command_with_subsection_set(self): ) self.assertEqual(stdout.strip(), "us-west-2") + def test_get_command_with_subsection_nested_property(self): + self.set_config_file_contents( + "\n" + "[default]\n" + "aws_access_key_id=default_access_key\n" + "\n" + "[services my-services]\n" + "ec2 = \n" + " endpoint_url = http://localhost:4567/" + ) + stdout, _, _ = self.run_cmd( + "configure get --services my-services ec2.endpoint_url", + ) + self.assertEqual(stdout.strip(), "http://localhost:4567/") + + def test_get_command_with_nonexisting_subsection(self): + self.set_config_file_contents( + "\n" + "[default]\n" + "aws_access_key_id=default_access_key\n" + "\n" + ) + _, stderr, _ = self.run_cmd( + "configure get --sso-session my-sso-session sso_region", + expected_rc=255, + ) + self.assertIn("could not be found", stderr) + + def test_get_command_with_subsection_set_nonexisting_subsection(self): + self.set_config_file_contents( + "\n" + "[default]\n" + "aws_access_key_id=default_access_key\n" + "\n" + "[sso-session my-sso-session]\n" + "sso_region = us-west-2\n" + ) + _, stderr, _ = self.run_cmd( + "configure get --services my-services ec2.endpoint_url", + expected_rc=255, + ) + self.assertIn("could not be found", stderr) + def test_set_with_config_file_no_exist(self): self.run_cmd("configure set region us-west-1") self.assertEqual( From 401de0f2df59b66d2ec20b0c92719faa1c029382 Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Tue, 17 Mar 2026 12:23:15 -0700 Subject: [PATCH 3/9] Add examples using sub-sections --- awscli/examples/configure/get/_examples.rst | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/awscli/examples/configure/get/_examples.rst b/awscli/examples/configure/get/_examples.rst index 48190ef82a93..f0f0226fb460 100644 --- a/awscli/examples/configure/get/_examples.rst +++ b/awscli/examples/configure/get/_examples.rst @@ -9,6 +9,23 @@ Suppose you had the following config file:: aws_secret_access_key=testing_secret_key region=us-west-2 + [profile my-dev-profile] + services = my-services + sso_session = my-sso + sso_account_id = 123456789011 + sso_role_name = readOnly + region = us-west-2 + output = json + + [sso-session my-sso] + sso_region = us-east-1 + sso_start_url = https://my-sso-portal.awsapps.com/start + sso_registration_scopes = sso:account:access + + [services my-services] + ec2 = + endpoint_url = http://localhost:4567/ + The following commands would have the corresponding output:: $ aws configure get aws_access_key_id @@ -27,3 +44,13 @@ The following commands would have the corresponding output:: $ $ echo $? 1 + + $ aws configure get --profile my-dev-profile sso_account_id + 123456789011 + + $ aws configure get --sso-session my-sso-session sso_region + us-east-1 + + $ aws configure get --services my-services ec2.endpoint_url + http://localhost:4567 + From 139528d0a9f207eeb7f8a4d17c2247d2847df1c8 Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Tue, 17 Mar 2026 12:37:32 -0700 Subject: [PATCH 4/9] Add error on non-existent sub-section --- awscli/customizations/configure/__init__.py | 3 +++ awscli/customizations/configure/get.py | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/awscli/customizations/configure/__init__.py b/awscli/customizations/configure/__init__.py index 2bb51b16e7b0..34ccc9abe0a0 100644 --- a/awscli/customizations/configure/__init__.py +++ b/awscli/customizations/configure/__init__.py @@ -45,6 +45,9 @@ class SectionNotFoundError(Exception): pass +class SubsectionNotFoundError(Exception): + pass + def mask_value(current_value): if current_value is None: return 'None' diff --git a/awscli/customizations/configure/get.py b/awscli/customizations/configure/get.py index 09c8918791cc..5be1ca1ee50e 100644 --- a/awscli/customizations/configure/get.py +++ b/awscli/customizations/configure/get.py @@ -18,7 +18,7 @@ from awscli.customizations.exceptions import ParamValidationError from awscli.customizations.utils import validate_mutually_exclusive -from . import PREDEFINED_SECTION_NAMES, SUBSECTION_TYPE_ALLOWLIST +from . import PREDEFINED_SECTION_NAMES, SUBSECTION_TYPE_ALLOWLIST, SubsectionNotFoundError LOG = logging.getLogger(__name__) @@ -180,11 +180,14 @@ def _get_subsection_property(self, section_type, section_name, varname): full_config = self._session.full_config if section_type not in full_config: - return None + raise SubsectionNotFoundError(f"The config sub-section ({section_name}) could not be found ") section_type_config = full_config[section_type] section_config = section_type_config.get(section_name, None) + if section_config is None: + raise SubsectionNotFoundError(f"The config sub-section ({section_name}) could not be found ") + # Handle nested properties if '.' in varname: parts = varname.split('.') From 8891587286efddd000a0e4f036ab0e14457b7b0e Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Wed, 18 Mar 2026 12:57:27 -0700 Subject: [PATCH 5/9] Add a test for a non-existent profile A missing case, adding it for consistency with test for a non-existent sub-section. --- tests/functional/configure/test_configure.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/functional/configure/test_configure.py b/tests/functional/configure/test_configure.py index e2aab34c3f2c..7d0f4c8b1231 100644 --- a/tests/functional/configure/test_configure.py +++ b/tests/functional/configure/test_configure.py @@ -84,6 +84,19 @@ def test_get_command_with_profile_set(self): ) self.assertEqual(stdout.strip(), "testing_access_key") + def test_get_command_with_nonexisting_profile(self): + self.set_config_file_contents( + "\n" + "[default]\n" + "aws_access_key_id=default_access_key\n" + "\n" + ) + _, stderr, _ = self.run_cmd( + "configure get --profile doesntexist sso_region", + expected_rc=255, + ) + self.assertIn("could not be found", stderr) + def test_get_with_fq_name(self): # test get configs with fully qualified name. self.set_config_file_contents( From f6070c9fb0234884e7a9777c688730c6ba4aaf49 Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Wed, 18 Mar 2026 13:00:03 -0700 Subject: [PATCH 6/9] Remove duplicate tests These are better tested with functional tests. --- .../unit/customizations/configure/test_get.py | 43 ++----------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/tests/unit/customizations/configure/test_get.py b/tests/unit/customizations/configure/test_get.py index a5407b9638d8..8baefb5f4cea 100644 --- a/tests/unit/customizations/configure/test_get.py +++ b/tests/unit/customizations/configure/test_get.py @@ -188,55 +188,18 @@ def test_get_nested_property(self): self.assertEqual(rendered.strip(), 'http://localhost:4566') self.assertEqual(rc, 0) - def test_non_existent_subsection_returns_exit_code_1(self): - session = FakeSession({}) - session.full_config = {} - stream, error_stream, config_get = self.create_command(session) - rc = config_get(args=['--sso-session', 'non-existent', 'sso_region'], - parsed_globals=None) - - self.assertEqual(rc, 1) - self.assertEqual(stream.getvalue(), '') - def test_non_existent_property_returns_exit_code_1(self): session = FakeSession({}) session.full_config = { 'sso_sessions': { 'my-session': { - 'sso_region': 'us-west-2' + 'sso_region': 'us-west-2' } } } - stream, error_stream, config_get = self.create_command(session) + stream, _, config_get = self.create_command(session) rc = config_get(args=['--sso-session', 'my-session', 'non_existent_property'], - parsed_globals=None) - - self.assertEqual(rc, 1) - self.assertEqual(stream.getvalue(), '') - - def test_no_output_to_stdout_for_non_existent_items(self): - session = FakeSession({}) - session.full_config = {} - stream, error_stream, config_get = self.create_command(session) - - rc = config_get(args=['--sso-session', 'non-existent', 'sso_region'], - parsed_globals=None) - self.assertEqual(rc, 1) - self.assertEqual(stream.getvalue(), '') - - def test_no_output_to_stdout_for_non_existent_items_existing_subsection(self): - session = FakeSession({}) - - session.full_config = { - 'sso"sessions': { - 'my-session': { - 'sso_region': 'us-west-2' - } - } - } + parsed_globals=None) - stream, error_stream, config_get = self.create_command(session) - rc = config_get(args=['--sso-session', 'my-session', 'non_existent'], - parsed_globals=None) self.assertEqual(rc, 1) self.assertEqual(stream.getvalue(), '') From 5610a841033ffcc4060c4466a9261d456ed63760 Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Wed, 18 Mar 2026 13:12:49 -0700 Subject: [PATCH 7/9] Reword help text --- awscli/customizations/configure/get.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/awscli/customizations/configure/get.py b/awscli/customizations/configure/get.py index 5be1ca1ee50e..ccf2e0b465e2 100644 --- a/awscli/customizations/configure/get.py +++ b/awscli/customizations/configure/get.py @@ -40,13 +40,13 @@ class ConfigureGetCommand(BasicCommand): }, { 'name': 'sso-session', - 'help_text': 'The name of the sub-section to configure.', + 'help_text': 'The name of the sub-section from which to retrieve a value.', 'action': 'store', 'cli_type_name': 'string', }, { 'name': 'services', - 'help_text': 'The name of the sub-section to configure.', + 'help_text': 'The name of the sub-section from which to retrieve a value.', 'action': 'store', 'cli_type_name': 'string', }, From 76b0a24f2e3fe25b7bb6f3e660ccdc54de52568e Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Wed, 18 Mar 2026 13:13:28 -0700 Subject: [PATCH 8/9] Use f-strings --- awscli/customizations/configure/get.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/awscli/customizations/configure/get.py b/awscli/customizations/configure/get.py index ccf2e0b465e2..2b16d7216380 100644 --- a/awscli/customizations/configure/get.py +++ b/awscli/customizations/configure/get.py @@ -111,7 +111,7 @@ def _run_main(self, args, parsed_globals): else: value = self._get_dotted_config_value(varname) - LOG.debug('Config value retrieved: %s' % value) + LOG.debug(f'Config value retrieved: {value}') if isinstance(value, str): self._stream.write(value) @@ -121,8 +121,8 @@ def _run_main(self, args, parsed_globals): # TODO: add support for this. We would need to print it off in # the same format as the config file. self._error_stream.write( - 'varname (%s) must reference a value, not a section or ' - 'sub-section.' % varname + f'varname ({varname}) must reference a value, not a section ' + 'or sub-section.' ) return 1 else: From 945b158c2ec338f0e6ea3f335401d4a8490220a1 Mon Sep 17 00:00:00 2001 From: Kenneth Daily Date: Wed, 18 Mar 2026 13:14:33 -0700 Subject: [PATCH 9/9] Formatting and unused imports --- awscli/customizations/configure/__init__.py | 4 ++-- awscli/customizations/configure/get.py | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/awscli/customizations/configure/__init__.py b/awscli/customizations/configure/__init__.py index 34ccc9abe0a0..52232354b3d2 100644 --- a/awscli/customizations/configure/__init__.py +++ b/awscli/customizations/configure/__init__.py @@ -10,10 +10,9 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. + from awscli.compat import shlex -# A map between the command line parameter name and the Python object name -# For allowed sub-section types NOT_SET = '' PREDEFINED_SECTION_NAMES = 'plugins' # A map between the command line parameter name and the name used @@ -48,6 +47,7 @@ class SectionNotFoundError(Exception): class SubsectionNotFoundError(Exception): pass + def mask_value(current_value): if current_value is None: return 'None' diff --git a/awscli/customizations/configure/get.py b/awscli/customizations/configure/get.py index 2b16d7216380..c226a981b873 100644 --- a/awscli/customizations/configure/get.py +++ b/awscli/customizations/configure/get.py @@ -11,14 +11,16 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. import logging -import re import sys from awscli.customizations.commands import BasicCommand -from awscli.customizations.exceptions import ParamValidationError from awscli.customizations.utils import validate_mutually_exclusive -from . import PREDEFINED_SECTION_NAMES, SUBSECTION_TYPE_ALLOWLIST, SubsectionNotFoundError +from . import ( + PREDEFINED_SECTION_NAMES, + SUBSECTION_TYPE_ALLOWLIST, + SubsectionNotFoundError, +) LOG = logging.getLogger(__name__) @@ -53,7 +55,7 @@ class ConfigureGetCommand(BasicCommand): ] def __init__(self, session, stream=None, error_stream=None): - super(ConfigureGetCommand, self).__init__(session) + super().__init__(session) if stream is None: stream = sys.stdout if error_stream is None: @@ -180,13 +182,17 @@ def _get_subsection_property(self, section_type, section_name, varname): full_config = self._session.full_config if section_type not in full_config: - raise SubsectionNotFoundError(f"The config sub-section ({section_name}) could not be found ") + raise SubsectionNotFoundError( + f"The config sub-section ({section_name}) could not be found" + ) section_type_config = full_config[section_type] section_config = section_type_config.get(section_name, None) if section_config is None: - raise SubsectionNotFoundError(f"The config sub-section ({section_name}) could not be found ") + raise SubsectionNotFoundError( + f"The config sub-section ({section_name}) could not be found" + ) # Handle nested properties if '.' in varname: