From ccbeeea5da33d5ca879dc8fee75d29fb10713e68 Mon Sep 17 00:00:00 2001 From: bhagyashris Date: Thu, 21 Sep 2017 16:09:01 +0530 Subject: [PATCH] Add method validate_integer Method validate_integer() is used in Cinder[1], Nova[2] and Masakari[3]. So it's a good candidate to add this method in Oslo.utils. [1] https://github.com/openstack/cinder/blob/master/cinder/utils.py#L1032 [2] https://github.com/openstack/nova/blob/master/nova/utils.py#L846 [3] https://github.com/openstack/masakari/blob/master/masakari/utils.py#L244 Change-Id: I9086b9057e24aa4747a81507ab14aad60e39ab40 --- oslo_utils/strutils.py | 29 +++++++++++++++++++++++++++ oslo_utils/tests/test_strutils.py | 33 +++++++++++++++++++++++++++++++ test-requirements.txt | 1 + 3 files changed, 63 insertions(+) diff --git a/oslo_utils/strutils.py b/oslo_utils/strutils.py index 7376ce0d..be17ba8a 100644 --- a/oslo_utils/strutils.py +++ b/oslo_utils/strutils.py @@ -438,6 +438,35 @@ def check_string_length(value, name=None, min_length=0, max_length=None): raise ValueError(msg) +def validate_integer(value, name, min_value=None, max_value=None): + """Make sure that value is a valid integer, potentially within range. + + :param value: value of the integer + :param name: name of the integer + :param min_value: min_value of the integer + :param max_value: max_value of the integer + :returns: integer + """ + try: + value = int(str(value)) + except (ValueError, UnicodeEncodeError): + msg = _('%(value_name)s must be an integer' + ) % {'value_name': name} + raise ValueError(msg) + + if min_value is not None and value < min_value: + msg = _('%(value_name)s must be >= %(min_value)d' + ) % {'value_name': name, 'min_value': min_value} + raise ValueError(msg) + + if max_value is not None and value > max_value: + msg = _('%(value_name)s must be <= %(max_value)d' + ) % {'value_name': name, 'max_value': max_value} + raise ValueError(msg) + + return value + + def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): """Validate and split the given HTTP request path. diff --git a/oslo_utils/tests/test_strutils.py b/oslo_utils/tests/test_strutils.py index ebc40024..0dae6938 100644 --- a/oslo_utils/tests/test_strutils.py +++ b/oslo_utils/tests/test_strutils.py @@ -18,6 +18,7 @@ import copy import math +import ddt import mock from oslotest import base as test_base import six @@ -804,3 +805,35 @@ class SplitByCommas(test_base.BaseTestCase): def test_with_escaped_quotes_in_row_inside_quoted(self): self.check(['a"b""c', 'd'], r'"a\"b\"\"c",d') + + +@ddt.ddt +class ValidateIntegerTestCase(test_base.BaseTestCase): + + @ddt.unpack + @ddt.data({"value": 42, "name": "answer", "output": 42}, + {"value": "42", "name": "answer", "output": 42}, + {"value": "7", "name": "lucky", "output": 7, + "min_value": 7, "max_value": 8}, + {"value": 7, "name": "lucky", "output": 7, + "min_value": 6, "max_value": 7}, + {"value": 300, "name": "Spartaaa!!!", "output": 300, + "min_value": 300}, + {"value": "300", "name": "Spartaaa!!!", "output": 300, + "max_value": 300}) + def test_valid_inputs(self, output, value, name, **kwargs): + self.assertEqual(strutils.validate_integer(value, name, + **kwargs), output) + + @ddt.unpack + @ddt.data({"value": "im-not-an-int", "name": ''}, + {"value": 3.14, "name": "Pie"}, + {"value": "299", "name": "Sparta no-show", + "min_value": 300, "max_value": 300}, + {"value": 55, "name": "doing 55 in a 54", + "max_value": 54}, + {"value": six.unichr(129), "name": "UnicodeError", + "max_value": 1000}) + def test_invalid_inputs(self, value, name, **kwargs): + self.assertRaises(ValueError, strutils.validate_integer, + value, name, **kwargs) diff --git a/test-requirements.txt b/test-requirements.txt index 5fdac01f..4fc97aca 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -10,6 +10,7 @@ testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=1.4.0 # MIT oslotest>=1.10.0 # Apache-2.0 +ddt>=1.0.1 # MIT # when we can require tox>= 1.4, this can go into tox.ini: # [testenv:cover]