Skip to content

Commit 9cff2e2

Browse files
author
David Noble
committed
DVPL-3648: splunklib.searchcommands | decorators.Option class should render Duration values in '%H:%M:%S' format, not as an integer number of seconds
Validated with automated unit tests and ad-hoc integration testing Signed-off-by: David Noble <[email protected]>
1 parent bfbf463 commit 9cff2e2

File tree

2 files changed

+70
-15
lines changed

2 files changed

+70
-15
lines changed

splunklib/searchcommands/validators.py

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15-
from time import strptime
1615
import os
1716
import re
1817
import sys
@@ -58,20 +57,6 @@ def __call__(self, value):
5857
return value
5958

6059

61-
class Duration(Validator):
62-
""" Validates duration option values.
63-
64-
"""
65-
def __call__(self, value):
66-
if value is not None:
67-
try:
68-
value = strptime(value, '%H:%M:%S')
69-
except ValueError as e:
70-
raise ValueError(str(e).capitalize())
71-
value = 3600 * value.tm_hour + 60 * value.tm_min + value.tm_sec
72-
return value
73-
74-
7560
class Fieldname(Validator):
7661
""" Validates field name option values.
7762
@@ -131,6 +116,44 @@ def __call__(self, value):
131116
return value
132117

133118

119+
class Duration(Validator):
120+
""" Validates duration option values.
121+
122+
"""
123+
def __call__(self, value):
124+
125+
if value is None:
126+
return None
127+
128+
try:
129+
p = value.split(':', 2)
130+
_60 = Duration._60
131+
_unsigned = Duration._unsigned
132+
if len(p) == 1:
133+
result = _unsigned(p[0])
134+
if len(p) == 2:
135+
result = 60 * _unsigned(p[0]) + _60(p[1])
136+
if len(p) == 3:
137+
result = 3600 * _unsigned(p[0]) + 60 * _60(p[1]) + _60(p[2])
138+
except ValueError:
139+
raise ValueError("Invalid duration value: %s", value)
140+
141+
return result
142+
143+
def format(self, value):
144+
145+
value = int(value)
146+
147+
s = value % 60
148+
m = value / 60 % 60
149+
h = value / (60 * 60)
150+
151+
return '%02d:%02d:%02d' % (h, m, s)
152+
153+
_60 = Integer(0, 59)
154+
_unsigned = Integer(0)
155+
156+
134157
class OptionName(Validator):
135158
""" Validates option names.
136159

tests/test_searchcommands_validators.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import unittest
2121

2222
from splunklib.searchcommands import validators
23+
from time import gmtime, strftime, strptime
2324
import os
2425

2526

@@ -29,6 +30,37 @@ def setUp(self):
2930
super(TestSearchCommandsValidators, self).setUp()
3031
return
3132

33+
def test_duration(self):
34+
35+
# Duration validator should parse and format time intervals of the form
36+
# HH:MM:SS
37+
38+
validator = validators.Duration()
39+
40+
for seconds in range(0, 25 * 60 * 60, 17):
41+
value = str(seconds)
42+
self.assertEqual(validator(value), seconds)
43+
self.assertEqual(validator(validator.format(seconds)), seconds)
44+
value = '%d:%02d' % (seconds / 60, seconds % 60)
45+
self.assertEqual(validator(value), seconds)
46+
self.assertEqual(validator(validator.format(seconds)), seconds)
47+
value = '%d:%02d:%02d' % (seconds / 3600, (seconds / 60) % 60, seconds % 60)
48+
self.assertEqual(validator(value), seconds)
49+
self.assertEqual(validator(validator.format(seconds)), seconds)
50+
51+
self.assertEqual(validator('23:00:00'), 23 * 60 * 60)
52+
self.assertEqual(validator('00:59:00'), 59 * 60)
53+
self.assertEqual(validator('00:00:59'), 59)
54+
55+
self.assertEqual(validator.format(23 * 60 * 60), '23:00:00')
56+
self.assertEqual(validator.format(59 * 60), '00:59:00')
57+
self.assertEqual(validator.format(59), '00:00:59')
58+
59+
self.assertRaises(ValueError, validator, '00:60:00')
60+
self.assertRaises(ValueError, validator, '00:00:60')
61+
62+
return
63+
3264
def test_file(self):
3365

3466
# Create a file on $SPLUNK_HOME/var/run/splunk

0 commit comments

Comments
 (0)