From 49eb2704289b50a77036a157b94e424535433b5b Mon Sep 17 00:00:00 2001 From: LeSingh1 Date: Sun, 31 May 2026 22:49:16 -0700 Subject: [PATCH] Fix None injection for hoisted binary arguments InjectingArgument.add_to_params used `pass` instead of `return` in the None guard, so when an optional hoisted argument was omitted the code still injected the wrapped member with a None value. The sibling OriginalArgument.add_to_params returns on None, which is the intended behavior. This affects `aws translate import-terminology` (--data-file) and `aws translate translate-document` (--document-content): leaving the optional arg off produced parameters like {'TerminologyData': {'File': None}} instead of an empty mapping. Added unit tests covering the None case, the wrapping case, and the merge-with-existing case. --- .../next-release/bugfix-binaryhoist-None.json | 5 +++ awscli/customizations/binaryhoist.py | 2 +- tests/unit/customizations/test_binaryhoist.py | 43 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 .changes/next-release/bugfix-binaryhoist-None.json create mode 100644 tests/unit/customizations/test_binaryhoist.py diff --git a/.changes/next-release/bugfix-binaryhoist-None.json b/.changes/next-release/bugfix-binaryhoist-None.json new file mode 100644 index 000000000000..4bfc9c291a5e --- /dev/null +++ b/.changes/next-release/bugfix-binaryhoist-None.json @@ -0,0 +1,5 @@ +{ + "type": "bugfix", + "category": "translate", + "description": "Fixed a bug where omitting an optional hoisted binary argument (such as ``--data-file`` for ``aws translate import-terminology`` or ``--document-content`` for ``aws translate translate-document``) would inject a ``None`` member into the request parameters instead of leaving them empty." +} diff --git a/awscli/customizations/binaryhoist.py b/awscli/customizations/binaryhoist.py index e4835a3a4b48..2ac5a6cab27e 100644 --- a/awscli/customizations/binaryhoist.py +++ b/awscli/customizations/binaryhoist.py @@ -33,7 +33,7 @@ def __init__(self, serialized_name, original_member_name, **kwargs): def add_to_params(self, parameters, value): if value is None: - pass + return wrapped_value = {self._original_member_name: value} if parameters.get(self._serialized_name): parameters[self._serialized_name].update(wrapped_value) diff --git a/tests/unit/customizations/test_binaryhoist.py b/tests/unit/customizations/test_binaryhoist.py new file mode 100644 index 000000000000..89450597e807 --- /dev/null +++ b/tests/unit/customizations/test_binaryhoist.py @@ -0,0 +1,43 @@ +# Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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.testutils import unittest +from awscli.customizations.binaryhoist import InjectingArgument + + +class TestInjectingArgument(unittest.TestCase): + def setUp(self): + self.argument = InjectingArgument( + 'TerminologyData', + 'File', + name='data-file', + cli_type_name='blob', + required=False, + ) + + def test_none_value_does_not_add_to_params(self): + parameters = {} + self.argument.add_to_params(parameters, None) + self.assertEqual(parameters, {}) + + def test_value_is_wrapped_in_serialized_member(self): + parameters = {} + self.argument.add_to_params(parameters, b'data') + self.assertEqual(parameters, {'TerminologyData': {'File': b'data'}}) + + def test_value_merges_with_existing_serialized_arg(self): + parameters = {'TerminologyData': {'Format': 'CSV'}} + self.argument.add_to_params(parameters, b'data') + self.assertEqual( + parameters, + {'TerminologyData': {'Format': 'CSV', 'File': b'data'}}, + )