Skip to content

Commit

Permalink
Merge pull request #384 from VatsalJagani/float-validator-for-custom-…
Browse files Browse the repository at this point in the history
…commands

Added Float parameter validator for custom search commands.
  • Loading branch information
ashah-splunk authored Dec 9, 2021
2 parents a17e0cd + 3687786 commit da36226
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/searchcommands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ splunklib.searchcommands
:members:
:inherited-members:

.. autoclass:: Float
:members:
:inherited-members:

.. autoclass:: RegularExpression
:members:
:inherited-members:
Expand Down
44 changes: 43 additions & 1 deletion splunklib/searchcommands/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,48 @@ def format(self, value):
return None if value is None else six.text_type(int(value))


class Float(Validator):
""" Validates float option values.
"""
def __init__(self, minimum=None, maximum=None):
if minimum is not None and maximum is not None:
def check_range(value):
if not (minimum <= value <= maximum):
raise ValueError('Expected float in the range [{0},{1}], not {2}'.format(minimum, maximum, value))
return
elif minimum is not None:
def check_range(value):
if value < minimum:
raise ValueError('Expected float in the range [{0},+∞], not {1}'.format(minimum, value))
return
elif maximum is not None:
def check_range(value):
if value > maximum:
raise ValueError('Expected float in the range [-∞,{0}], not {1}'.format(maximum, value))
return
else:
def check_range(value):
return

self.check_range = check_range
return

def __call__(self, value):
if value is None:
return None
try:
value = float(value)
except ValueError:
raise ValueError('Expected float value, not {}'.format(json_encode_string(value)))

self.check_range(value)
return value

def format(self, value):
return None if value is None else six.text_type(float(value))


class Duration(Validator):
""" Validates duration option values.
Expand Down Expand Up @@ -391,4 +433,4 @@ def format(self, value):
return self.__call__(value)


__all__ = ['Boolean', 'Code', 'Duration', 'File', 'Integer', 'List', 'Map', 'RegularExpression', 'Set']
__all__ = ['Boolean', 'Code', 'Duration', 'File', 'Integer', 'Float', 'List', 'Map', 'RegularExpression', 'Set']
18 changes: 16 additions & 2 deletions tests/searchcommands/test_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ class TestSearchCommand(SearchCommand):
**Syntax:** **integer=***<value>*
**Description:** An integer value''',
require=True, validate=validators.Integer())

float = Option(
doc='''
**Syntax:** **float=***<value>*
**Description:** An float value''',
validate=validators.Float())

required_float = Option(
doc='''
**Syntax:** **float=***<value>*
**Description:** An float value''',
require=True, validate=validators.Float())

map = Option(
doc='''
Expand Down Expand Up @@ -408,6 +420,7 @@ def test_option(self):
'fieldname': u'some.field_name',
'file': six.text_type(repr(__file__)),
'integer': 100,
'float': 99.9,
'logging_configuration': environment.logging_configuration,
'logging_level': u'WARNING',
'map': 'foo',
Expand All @@ -421,6 +434,7 @@ def test_option(self):
'required_fieldname': u'some.field_name',
'required_file': six.text_type(repr(__file__)),
'required_integer': 100,
'required_float': 99.9,
'required_map': 'foo',
'required_match': u'123-45-6789',
'required_optionname': u'some_option_name',
Expand Down Expand Up @@ -452,10 +466,10 @@ def test_option(self):

expected = (
'foo="f" boolean="f" code="foo == \\"bar\\"" duration="24:59:59" fieldname="some.field_name" '
'file=' + json_encode_string(__file__) + ' integer="100" map="foo" match="123-45-6789" '
'file=' + json_encode_string(__file__) + ' integer="100" float="99.9" map="foo" match="123-45-6789" '
'optionname="some_option_name" record="f" regularexpression="\\\\s+" required_boolean="f" '
'required_code="foo == \\"bar\\"" required_duration="24:59:59" required_fieldname="some.field_name" '
'required_file=' + json_encode_string(__file__) + ' required_integer="100" required_map="foo" '
'required_file=' + json_encode_string(__file__) + ' required_integer="100" required_float="99.9" required_map="foo" '
'required_match="123-45-6789" required_optionname="some_option_name" required_regularexpression="\\\\s+" '
'required_set="bar" set="bar" show_configuration="f"')

Expand Down
59 changes: 59 additions & 0 deletions tests/searchcommands/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,65 @@ def test(integer):
self.assertRaises(ValueError, validator.__call__, maxsize + 1)

return

def test_float(self):
# Float validator test

maxsize = sys.maxsize
minsize = -(sys.maxsize - 1)

validator = validators.Float()

def test(float_val):
try:
float_val = float(float_val)
except ValueError:
assert False
for s in str(float_val), six.text_type(float_val):
value = validator.__call__(s)
self.assertEqual(value, float_val)
self.assertIsInstance(value, float)
self.assertEqual(validator.format(float_val), six.text_type(float_val))

test(2 * minsize)
test(minsize)
test(-1)
test(0)
test(-1.12345)
test(0.0001)
test(100101.011)
test(2 * maxsize)
test('18.32123')
self.assertRaises(ValueError, validator.__call__, 'Splunk!')

validator = validators.Float(minimum=0)
self.assertEqual(validator.__call__(0), 0)
self.assertEqual(validator.__call__(1.154), 1.154)
self.assertEqual(validator.__call__(888.51), 888.51)
self.assertEqual(validator.__call__(2 * maxsize), float(2 * maxsize))
self.assertRaises(ValueError, validator.__call__, -1)
self.assertRaises(ValueError, validator.__call__, -1111.00578)
self.assertRaises(ValueError, validator.__call__, -0.005)

validator = validators.Float(minimum=1, maximum=maxsize)
self.assertEqual(validator.__call__(1), float(1))
self.assertEqual(validator.__call__(100.111), 100.111)
self.assertEqual(validator.__call__(9999.0), 9999.0)
self.assertEqual(validator.__call__(maxsize), float(maxsize))
self.assertRaises(ValueError, validator.__call__, 0)
self.assertRaises(ValueError, validator.__call__, 0.9999)
self.assertRaises(ValueError, validator.__call__, -199)
self.assertRaises(ValueError, validator.__call__, maxsize + 1)

validator = validators.Float(minimum=-1, maximum=1)
self.assertEqual(validator.__call__(0), float(0))
self.assertEqual(validator.__call__(0.123456), 0.123456)
self.assertEqual(validator.__call__(-0.012), -0.012)
self.assertRaises(ValueError, validator.__call__, -1.1)
self.assertRaises(ValueError, validator.__call__, 100.123456)
self.assertRaises(ValueError, validator.__call__, maxsize + 1)

return

def test_list(self):

Expand Down

0 comments on commit da36226

Please sign in to comment.