From 843f61cb317ae98f142c73194fae11ab277319ae Mon Sep 17 00:00:00 2001 From: jonathan343 Date: Mon, 3 Feb 2025 10:38:49 -0500 Subject: [PATCH] Clean up and PR feedback. --- botocore/parsers.py | 8 ++++---- tests/unit/test_protocols.py | 39 +++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/botocore/parsers.py b/botocore/parsers.py index 819dbfd8bb..7393fb51dd 100644 --- a/botocore/parsers.py +++ b/botocore/parsers.py @@ -204,7 +204,7 @@ class ResponseParser: EVENT_STREAM_PARSER_CLS = None # This is a list of known values for the "location" key in the # serialization dict. The location key tells us where in the response - # to parse the value. + # to parse the value. Locations not in this list will be ignored. KNOWN_LOCATIONS = ('statusCode', 'header', 'headers') def __init__(self, timestamp_parser=None, blob_parser=None): @@ -590,7 +590,7 @@ def _do_parse(self, response, shape): return self._parse_body_as_xml(response, shape, inject_metadata=True) def _parse_body_as_xml(self, response, shape, inject_metadata=True): - xml_contents = response['body'] or b'' + xml_contents = response['body'] root = self._parse_xml_string_to_dom(xml_contents) parsed = {} if shape is not None: @@ -723,7 +723,7 @@ def _do_error_parse(self, response, shape): if ':' in code: code = code.split(':', 1)[0] if '#' in code: - code = code.split('#', 1)[1] + code = code.rsplit('#', 1)[1] if 'x-amzn-query-error' in headers: code = self._do_query_compatible_error_parse( code, headers, error @@ -1044,7 +1044,7 @@ def _inject_error_code(self, error, response): if ':' in code: code = code.split(':', 1)[0] if '#' in code: - code = code.split('#', 1)[1] + code = code.rsplit('#', 1)[1] error['Error']['Code'] = code def _handle_boolean(self, shape, value): diff --git a/tests/unit/test_protocols.py b/tests/unit/test_protocols.py index dcb3fee127..a2b85790c9 100644 --- a/tests/unit/test_protocols.py +++ b/tests/unit/test_protocols.py @@ -47,7 +47,7 @@ To run a single test case in a suite (useful when debugging a single test), you can set the BOTOCORE_TEST_ID env var with the ``suite_id:test_id`` syntax. - BOTOCORE_TEST_ID=5:1 pytest test/unit/test_protocols.py + BOTOCORE_TEST_ID=5:1 pytest tests/unit/test_protocols.py """ @@ -99,9 +99,6 @@ } PROTOCOL_TEST_BLACKLIST = ['Idempotency token auto fill'] IGNORE_LIST_FILENAME = "protocol-tests-ignore-list.json" -PROTOCOL_TEST_IGNORE_LIST_PATH = os.path.join(TEST_DIR, IGNORE_LIST_FILENAME) -with open(PROTOCOL_TEST_IGNORE_LIST_PATH) as f: - PROTOCOL_TEST_IGNORE_LIST = json.load(f) class TestType(Enum): @@ -112,6 +109,12 @@ class TestType(Enum): OUTPUT = "output" +def get_protocol_test_ignore_list(): + ignore_list_path = os.path.join(TEST_DIR, IGNORE_LIST_FILENAME) + with open(ignore_list_path) as f: + return json.load(f) + + def _compliance_tests(test_type=None): inp = test_type is None or test_type is TestType.INPUT out = test_type is None or test_type is TestType.OUTPUT @@ -211,7 +214,9 @@ def test_output_compliance(json_description, case, basename): body_bytes = case['response']['body'].encode('utf-8') case['response']['body'] = body_bytes else: - case['response']['body'] = b'' + case['response']['body'] = ( + b'' if protocol != "query" else b'' + ) # We need the headers to be case insensitive # If a test case doesn't define response headers, set it to an empty `HeadersDict`. case['response']['headers'] = HeadersDict( @@ -534,20 +539,18 @@ def _should_ignore_test(protocol, test_type, suite, case): :return: True if the protocol test should be ignored, False otherwise. :rtype: bool """ - ignore_list = PROTOCOL_TEST_IGNORE_LIST.get('general', {}).get( - test_type, {} - ) - ignore_suites = ignore_list.get('suites', []) - ignore_cases = ignore_list.get('cases', []) - - if suite in ignore_suites or case in ignore_cases: + # Get test suites and cases to ignore for all protocols. + ignore_list = get_protocol_test_ignore_list() + general_ignore_list = ignore_list.get('general', {}).get(test_type, {}) + general_suites = general_ignore_list.get('suites', []) + general_cases = general_ignore_list.get('cases', []) + if suite in general_suites or case in general_cases: return True + # Get test suites and cases to ignore for a specific protocol. protocol_ignore_list = ( - PROTOCOL_TEST_IGNORE_LIST.get('protocols', {}) - .get(protocol, {}) - .get(test_type, {}) + ignore_list.get('protocols', {}).get(protocol, {}).get(test_type, {}) ) - protocol_ignore_suites = protocol_ignore_list.get('suites', []) - protocol_ignore_cases = protocol_ignore_list.get('cases', []) - return suite in protocol_ignore_suites or case in protocol_ignore_cases + protocol_suites = protocol_ignore_list.get('suites', []) + protocol_cases = protocol_ignore_list.get('cases', []) + return suite in protocol_suites or case in protocol_cases