Skip to content

Commit b22afbf

Browse files
author
David Noble
committed
Fixed quote problem and added support for value formatting
The latter was required to write unit tests that validate the SearchCommandParser
1 parent 5c2ebc2 commit b22afbf

File tree

5 files changed

+79
-11
lines changed

5 files changed

+79
-11
lines changed

examples/searchcommands_app/bin/countmatches.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ def stream(self, records):
6666
count = 0.0
6767
for fieldname in self.fieldnames:
6868
matches = self.pattern.finditer(str(record[fieldname]))
69-
if matches:
70-
count += len(list(matches))
69+
count += len(list(matches))
7170
record[self.fieldname] = count
7271
yield record
7372

examples/searchcommands_app/default/commands.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
[countmatches]
55
filename = countmatches.py
66
supports_getinfo = true
7+
supports_rawargs = true
78

89
[simulate]
910
filename = simulate.py
1011
supports_getinfo = true
12+
supports_rawargs = true
1113

1214
[sum]
1315
filename = sum.py
1416
supports_getinfo = true
17+
supports_rawargs = true

splunklib/searchcommands/decorators.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,16 @@ def _reset(self, other):
200200
#region Types
201201

202202
class Encoder(JSONEncoder):
203+
def __init__(self, item):
204+
super(Option.Encoder, self).__init__()
205+
self.item = item
206+
203207
def default(self, o):
204-
return str(o)
208+
# Convert the value of a type unknown to the JSONEncoder
209+
validator = self.item.validator
210+
if validator is None:
211+
return str(o)
212+
return validator.format(o)
205213

206214
class Item(object):
207215
""" Presents an instance/class view over a search command `Option`
@@ -218,8 +226,8 @@ def __repr__(self):
218226
return str(self)
219227

220228
def __str__(self):
221-
encoder = Option.Encoder()
222-
text = '='.join([self._option.name, encoder.encode(self.value)])
229+
encoder = Option.Encoder(self)
230+
text = '='.join([self.name, encoder.encode(self.value)])
223231
return text
224232

225233
#region Properties

splunklib/searchcommands/search_command_internals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def replace(match):
352352
\s*$
353353
""", re.VERBOSE)
354354

355-
_escaped_quote_re = re.compile(r"""(\\\\|\\"|""|\\."|\\])""")
355+
_escaped_quote_re = re.compile(r"""(\\\\|\\"|""|\\."|\\)""")
356356

357357
_name_re = re.compile(r"""[_a-zA-Z][[_a-zA-Z0-9]+""")
358358

tests/test_searchcommands_app.py

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,31 @@
2020
import unittest
2121

2222
from subprocess import Popen
23-
import json
23+
import base64
2424
import os
2525
import shutil
2626
import testlib
2727

28+
from splunklib.searchcommands import \
29+
StreamingCommand, Configuration, Option, validators
30+
31+
@Configuration()
32+
class StubbedCommand(StreamingCommand):
33+
fieldname = Option(
34+
doc='''
35+
**Syntax:** **fieldname=***<fieldname>*
36+
**Description:** Name of the field that will hold the match count''',
37+
require=True, validate=validators.Fieldname())
38+
39+
pattern = Option(
40+
doc='''
41+
**Syntax:** **pattern=***<regular-expression>*
42+
**Description:** Regular expression pattern to match''',
43+
require=True, validate=validators.RegularExpression())
44+
45+
def stream(self, records):
46+
pass
47+
2848

2949
class TestSearchCommandsApp(testlib.SDKTestCase):
3050

@@ -37,15 +57,49 @@ def setUp(self):
3757
os.mkdir(path)
3858
return
3959

60+
def test_command_parser(self):
61+
from splunklib.searchcommands.search_command_internals import \
62+
SearchCommandParser
63+
64+
parser = SearchCommandParser()
65+
command = StubbedCommand()
66+
67+
parser.parse(
68+
[
69+
'fieldname=word_count',
70+
'pattern="\\\\w+"',
71+
'text_field_1',
72+
'text_field_2'
73+
],
74+
command)
75+
76+
command_line = str(command)
77+
self.assertEqual('stubbed fieldname="word_count" pattern="\\\\w+" text_field_1 text_field_2', command_line)
78+
return
79+
80+
def test_option_show_configuration(self):
81+
self._run(
82+
'simulate', [
83+
'csv=%s' % TestSearchCommandsApp._data_file("input/population.csv"),
84+
'duration=00:00:10',
85+
'interval=00:00:01',
86+
'rate=200',
87+
'seed=%s' % TestSearchCommandsApp._seed,
88+
'show_configuration=true'],
89+
__GETINFO__=(
90+
'input/population.csv',
91+
'output/samples.csv',
92+
'log/test_show_configuration.log'))
93+
return
94+
4095
def test_generating_command_in_isolation(self):
41-
encoder = json.JSONEncoder(ensure_ascii=False)
4296
self._run(
4397
'simulate', [
4498
'csv=%s' % TestSearchCommandsApp._data_file("input/population.csv"),
4599
'duration=00:00:10',
46100
'interval=00:00:01',
47101
'rate=200',
48-
'seed=%s' % encoder.encode(TestSearchCommandsApp._seed)],
102+
'seed=%s' % TestSearchCommandsApp._seed],
49103
__GETINFO__=(
50104
'input/population.csv',
51105
'output/samples.csv',
@@ -108,6 +162,8 @@ def test_streaming_command_on_server(self):
108162

109163
def _run(self, command, args, **kwargs):
110164
for operation in ['__GETINFO__', '__EXECUTE__']:
165+
if operation not in kwargs:
166+
continue
111167
files = kwargs[operation]
112168
process = TestSearchCommandsApp._start_process(
113169
['python', command + '.py', operation] + args,
@@ -133,9 +189,11 @@ def _start_process(cls, args, stdin, stdout, stderr):
133189

134190
package_directory = os.path.dirname(__file__)
135191
data_directory = os.path.join(package_directory, 'searchcommands_data')
136-
app_bin = os.path.join(os.path.dirname(package_directory), "examples/searchcommands_app/bin")
192+
app_bin = os.path.join(
193+
os.path.dirname(package_directory), "examples/searchcommands_app/bin")
137194

138-
_seed = '\xcd{\xf8\xc4\x1c8=\x88\nc\xe2\xc4\xee\xdb\xcal'
195+
_seed = base64.encodestring(
196+
'\xcd{\xf8\xc4\x1c8=\x88\nc\xe2\xc4\xee\xdb\xcal')
139197

140198
if __name__ == "__main__":
141199
unittest.main()

0 commit comments

Comments
 (0)