diff --git a/.changes/next-release/enhancement-paginator-44130.json b/.changes/next-release/enhancement-paginator-44130.json new file mode 100644 index 000000000000..1a47512834bf --- /dev/null +++ b/.changes/next-release/enhancement-paginator-44130.json @@ -0,0 +1,5 @@ +{ + "type": "enhancement", + "category": "paginator", + "description": "Add warning when a non-positive value is provided for the max-items pagination parameter." +} diff --git a/awscli/customizations/paginate.py b/awscli/customizations/paginate.py index c1400c5758e3..fe1f3f140112 100644 --- a/awscli/customizations/paginate.py +++ b/awscli/customizations/paginate.py @@ -24,8 +24,10 @@ """ import logging +import sys from functools import partial +from awscli.customizations.utils import uni_print from botocore import xform_name from botocore.exceptions import DataNotFoundError, PaginationError from botocore import model @@ -266,6 +268,11 @@ def __init__(self, name, documentation, parse_type, serialized_name): self._parse_type = parse_type self._required = False + def _emit_non_positive_max_items_warning(self): + uni_print( + "warning: Non-positive values for --max-items may result in undefined behavior.\n", + sys.stderr) + @property def cli_name(self): return '--' + self._name @@ -292,6 +299,8 @@ def add_to_parser(self, parser): def add_to_params(self, parameters, value): if value is not None: + if self._serialized_name == 'MaxItems' and int(value) <= 0: + self._emit_non_positive_max_items_warning() pagination_config = parameters.get('PaginationConfig', {}) pagination_config[self._serialized_name] = value parameters['PaginationConfig'] = pagination_config diff --git a/tests/unit/customizations/test_paginate.py b/tests/unit/customizations/test_paginate.py index e4e4e018975e..cb362a0fc631 100644 --- a/tests/unit/customizations/test_paginate.py +++ b/tests/unit/customizations/test_paginate.py @@ -10,6 +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. +import pytest + +from awscli.customizations.paginate import PageArgument from awscli.testutils import mock, unittest from botocore.exceptions import DataNotFoundError, PaginationError @@ -18,6 +21,9 @@ from awscli.customizations import paginate +@pytest.fixture +def max_items_page_arg(): + return PageArgument('max-items', 'documentation', int, 'MaxItems') class TestPaginateBase(unittest.TestCase): @@ -321,3 +327,20 @@ def test_can_handle_missing_page_size(self): del self.parsed_args.page_size self.assertIsNone(paginate.ensure_paging_params_not_set( self.parsed_args, {})) + + +class TestNonPositiveMaxItems: + def test_positive_integer_does_not_raise_warning(self, max_items_page_arg, capsys): + max_items_page_arg.add_to_params({}, 1) + captured = capsys.readouterr() + assert captured.err == "" + + def test_zero_raises_warning(self, max_items_page_arg, capsys): + max_items_page_arg.add_to_params({}, 0) + captured = capsys.readouterr() + assert "Non-positive values for --max-items" in captured.err + + def test_negative_integer_raises_warning(self, max_items_page_arg, capsys): + max_items_page_arg.add_to_params({}, -1) + captured = capsys.readouterr() + assert "Non-positive values for --max-items" in captured.err