From 6a9c77b969d1a29f435837469c17b915f0c80065 Mon Sep 17 00:00:00 2001 From: David Poncelow Date: Thu, 3 Sep 2020 16:36:39 -0700 Subject: [PATCH 1/8] a test to confirm errors in searchcommands with multibyte data --- tests/data/custom_search/multibyte_input.gz | Bin 0 -> 26288 bytes .../test_multibyte_processing.py | 26 ++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/data/custom_search/multibyte_input.gz create mode 100644 tests/searchcommands/test_multibyte_processing.py diff --git a/tests/data/custom_search/multibyte_input.gz b/tests/data/custom_search/multibyte_input.gz new file mode 100644 index 0000000000000000000000000000000000000000..6659838645d74235f202553a8f147e54e5821319 GIT binary patch literal 26288 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¥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 BMHc`7 literal 0 HcmV?d00001 diff --git a/tests/searchcommands/test_multibyte_processing.py b/tests/searchcommands/test_multibyte_processing.py new file mode 100644 index 000000000..f5f7deb10 --- /dev/null +++ b/tests/searchcommands/test_multibyte_processing.py @@ -0,0 +1,26 @@ +from splunklib.searchcommands import StreamingCommand, Configuration, dispatch +import gzip +import os +import io +import sys + + +def build_test_command(): + @Configuration() + class TestSearchCommand(StreamingCommand): + def stream(self, records): + for record in records: + yield record + return TestSearchCommand() + + +def get_input_file(name): + return "tests/data/custom_search/" + name + ".gz" + + +def test_multibyte_chunked(capsys): + data = gzip.open(get_input_file("multibyte_input")) + if sys.version_info.major >= 3: + data = io.TextIOWrapper(data) + cmd = build_test_command() + cmd._process_protocol_v2(sys.argv, data, sys.stdout) From 0780fc1878e2de0effd0bbfaa45a963a2c73b4b6 Mon Sep 17 00:00:00 2001 From: Amy Sutedja Date: Thu, 3 Sep 2020 17:44:52 -0700 Subject: [PATCH 2/8] Fix for multibyte inputs to custom search commands --- splunklib/searchcommands/search_command.py | 20 +++++++--- tests/searchcommands/test_search_command.py | 42 +++++++++++++-------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/splunklib/searchcommands/search_command.py b/splunklib/searchcommands/search_command.py index 47d1016a5..84c4d5fd7 100644 --- a/splunklib/searchcommands/search_command.py +++ b/splunklib/searchcommands/search_command.py @@ -852,15 +852,23 @@ def _execute(self, ifile, process): @staticmethod def _read_chunk(ifile): # noinspection PyBroadException + if six.PY2: + istream = ifile + else: + try: + istream = ifile.buffer + except AttributeError as error: + raise RuntimeError('Failed to get underlying buffer: {}'.format(error)) + try: - header = ifile.readline() + header = istream.readline() except Exception as error: raise RuntimeError('Failed to read transport header: {}'.format(error)) if not header: return None - match = SearchCommand._header.match(header) + match = SearchCommand._header.match(six.ensure_str(header)) if match is None: raise RuntimeError('Failed to parse transport header: {}'.format(header)) @@ -870,14 +878,14 @@ def _read_chunk(ifile): body_length = int(body_length) try: - metadata = ifile.read(metadata_length) + metadata = istream.read(metadata_length) except Exception as error: raise RuntimeError('Failed to read metadata of length {}: {}'.format(metadata_length, error)) decoder = MetadataDecoder() try: - metadata = decoder.decode(metadata) + metadata = decoder.decode(six.ensure_str(metadata)) except Exception as error: raise RuntimeError('Failed to parse metadata of length {}: {}'.format(metadata_length, error)) @@ -887,11 +895,11 @@ def _read_chunk(ifile): body = "" try: if body_length > 0: - body = ifile.read(body_length) + body = istream.read(body_length) except Exception as error: raise RuntimeError('Failed to read body of length {}: {}'.format(body_length, error)) - return metadata, body + return metadata, six.ensure_str(body) _header = re.compile(r'chunked\s+1.0\s*,\s*(\d+)\s*,\s*(\d+)\s*\n') diff --git a/tests/searchcommands/test_search_command.py b/tests/searchcommands/test_search_command.py index 1ebb29fb9..b648b39ab 100755 --- a/tests/searchcommands/test_search_command.py +++ b/tests/searchcommands/test_search_command.py @@ -33,8 +33,21 @@ import os import re +from io import TextIOWrapper + import pytest +def build_command_input(getinfo_metadata, execute_metadata, execute_body): + header = ('chunked 1.0,{},0\n{}'.format(len(six.ensure_binary(getinfo_metadata)), getinfo_metadata) + + 'chunked 1.0,{},{}\n{}{}'.format(len(six.ensure_binary(execute_metadata)), len(six.ensure_binary(execute_body)), execute_metadata, execute_body)) + + ifile = BytesIO(six.ensure_binary(header)) + + if not six.PY2: + ifile = TextIOWrapper(ifile) + + return ifile + @Configuration() class TestCommand(SearchCommand): @@ -428,11 +441,9 @@ def test_process_scpv2(self): show_configuration=('true' if show_configuration is True else 'false')) execute_metadata = '{"action":"execute","finished":true}' - execute_body = 'test\r\ndata\r\n' + execute_body = 'test\r\ndata\r\n测试\r\n' - ifile = StringIO( - 'chunked 1.0,{},0\n{}'.format(len(getinfo_metadata), getinfo_metadata) + - 'chunked 1.0,{},{}\n{}{}'.format(len(execute_metadata), len(execute_body), execute_metadata, execute_body)) + ifile = build_command_input(getinfo_metadata, execute_metadata, execute_body) command = TestCommand() result = BytesIO() @@ -455,12 +466,17 @@ def test_process_scpv2(self): self.assertEqual(command.required_option_1, 'value_1') self.assertEqual(command.required_option_2, 'value_2') - self.assertEqual( + expected = ( 'chunked 1.0,68,0\n' '{"inspector":{"messages":[["INFO","test command configuration: "]]}}\n' - 'chunked 1.0,17,23\n' + 'chunked 1.0,17,32\n' '{"finished":true}test,__mv_test\r\n' - 'data,\r\n', + 'data,\r\n' + '测试,\r\n' + ) + + self.assertEqual( + expected, result.getvalue().decode('utf-8')) self.assertEqual(command.protocol_version, 2) @@ -620,11 +636,9 @@ def test_process_scpv2(self): show_configuration=show_configuration) execute_metadata = '{"action":"execute","finished":true}' - execute_body = 'test\r\ndata\r\n' + execute_body = 'test\r\ndata\r\n测试\r\n' - ifile = StringIO( - 'chunked 1.0,{},0\n{}'.format(len(getinfo_metadata), getinfo_metadata) + - 'chunked 1.0,{},{}\n{}{}'.format(len(execute_metadata), len(execute_body), execute_metadata, execute_body)) + ifile = build_command_input(getinfo_metadata, execute_metadata, execute_body) command = TestCommand() result = BytesIO() @@ -666,11 +680,9 @@ def test_process_scpv2(self): show_configuration=('true' if show_configuration is True else 'false')) execute_metadata = '{"action":"execute","finished":true}' - execute_body = 'action\r\nraise_exception\r\n' + execute_body = 'action\r\nraise_exception\r\n测试\r\n' - ifile = StringIO( - 'chunked 1.0,{},0\n{}'.format(len(getinfo_metadata), getinfo_metadata) + - 'chunked 1.0,{},{}\n{}{}'.format(len(execute_metadata), len(execute_body), execute_metadata, execute_body)) + ifile = build_command_input(getinfo_metadata, execute_metadata, execute_body) command = TestCommand() result = BytesIO() From 253784c6f7b918bbc8ef02d9a8358f0866756087 Mon Sep 17 00:00:00 2001 From: Amy Sutedja Date: Thu, 3 Sep 2020 19:33:14 -0700 Subject: [PATCH 3/8] Multibyte test cleanup --- .../searchcommands/test_multibyte_processing.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/searchcommands/test_multibyte_processing.py b/tests/searchcommands/test_multibyte_processing.py index f5f7deb10..5a19220dd 100644 --- a/tests/searchcommands/test_multibyte_processing.py +++ b/tests/searchcommands/test_multibyte_processing.py @@ -1,9 +1,11 @@ -from splunklib.searchcommands import StreamingCommand, Configuration, dispatch -import gzip -import os import io +import gzip import sys +from os import path + +from splunklib import six +from splunklib.searchcommands import StreamingCommand, Configuration def build_test_command(): @Configuration() @@ -13,14 +15,13 @@ def stream(self, records): yield record return TestSearchCommand() - def get_input_file(name): - return "tests/data/custom_search/" + name + ".gz" - + return path.join( + path.dirname(path.dirname(__file__)), 'data', 'custom_search', name + '.gz') -def test_multibyte_chunked(capsys): +def test_multibyte_chunked(): data = gzip.open(get_input_file("multibyte_input")) - if sys.version_info.major >= 3: + if not six.PY2: data = io.TextIOWrapper(data) cmd = build_test_command() cmd._process_protocol_v2(sys.argv, data, sys.stdout) From 8dec1678e4e1643580c63bf4a961ad0abe41c686 Mon Sep 17 00:00:00 2001 From: Amy Sutedja Date: Fri, 4 Sep 2020 13:37:22 -0700 Subject: [PATCH 4/8] Cleaner naming and semantics for custom search command input streams --- .../searchcommands/generating_command.py | 2 +- splunklib/searchcommands/search_command.py | 26 ++++++++++++------- tests/searchcommands/test_search_command.py | 6 ++--- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/splunklib/searchcommands/generating_command.py b/splunklib/searchcommands/generating_command.py index 56bf42338..f3fa72baf 100644 --- a/splunklib/searchcommands/generating_command.py +++ b/splunklib/searchcommands/generating_command.py @@ -204,7 +204,7 @@ def _execute(self, ifile, process): """ if self._protocol_version == 2: - result = self._read_chunk(ifile) + result = self._read_chunk(self._as_binary_stream(ifile)) if not result: return diff --git a/splunklib/searchcommands/search_command.py b/splunklib/searchcommands/search_command.py index 84c4d5fd7..e31ee8961 100644 --- a/splunklib/searchcommands/search_command.py +++ b/splunklib/searchcommands/search_command.py @@ -656,7 +656,7 @@ def _process_protocol_v2(self, argv, ifile, ofile): # noinspection PyBroadException try: debug('Reading metadata') - metadata, body = self._read_chunk(ifile) + metadata, body = self._read_chunk(self._as_binary_stream(ifile)) action = getattr(metadata, 'action', None) @@ -850,15 +850,20 @@ def _execute(self, ifile, process): self.finish() @staticmethod - def _read_chunk(ifile): - # noinspection PyBroadException + def _as_binary_stream(ifile): if six.PY2: - istream = ifile - else: - try: - istream = ifile.buffer - except AttributeError as error: - raise RuntimeError('Failed to get underlying buffer: {}'.format(error)) + return ifile + + try: + return ifile.buffer + except AttributeError as error: + raise RuntimeError('Failed to get underlying buffer: {}'.format(error)) + + @staticmethod + def _read_chunk(istream): + # noinspection PyBroadException + if not six.PY2: + assert issubclass(type(istream), (io.BufferedIOBase, io.RawIOBase)), 'Stream must be binary' try: header = istream.readline() @@ -930,9 +935,10 @@ def _records_protocol_v1(self, ifile): yield record def _records_protocol_v2(self, ifile): + istream = self._as_binary_stream(ifile) while True: - result = self._read_chunk(ifile) + result = self._read_chunk(istream) if not result: return diff --git a/tests/searchcommands/test_search_command.py b/tests/searchcommands/test_search_command.py index b648b39ab..9f9ee8d4a 100755 --- a/tests/searchcommands/test_search_command.py +++ b/tests/searchcommands/test_search_command.py @@ -38,10 +38,10 @@ import pytest def build_command_input(getinfo_metadata, execute_metadata, execute_body): - header = ('chunked 1.0,{},0\n{}'.format(len(six.ensure_binary(getinfo_metadata)), getinfo_metadata) + - 'chunked 1.0,{},{}\n{}{}'.format(len(six.ensure_binary(execute_metadata)), len(six.ensure_binary(execute_body)), execute_metadata, execute_body)) + input = ('chunked 1.0,{},0\n{}'.format(len(six.ensure_binary(getinfo_metadata)), getinfo_metadata) + + 'chunked 1.0,{},{}\n{}{}'.format(len(six.ensure_binary(execute_metadata)), len(six.ensure_binary(execute_body)), execute_metadata, execute_body)) - ifile = BytesIO(six.ensure_binary(header)) + ifile = BytesIO(six.ensure_binary(input)) if not six.PY2: ifile = TextIOWrapper(ifile) From 5d5eb8acc812099e6b35484385b6044aa8e59231 Mon Sep 17 00:00:00 2001 From: Amy Sutedja Date: Fri, 4 Sep 2020 14:25:24 -0700 Subject: [PATCH 5/8] Better type assertion --- splunklib/searchcommands/search_command.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/splunklib/searchcommands/search_command.py b/splunklib/searchcommands/search_command.py index e31ee8961..8ec82bba0 100644 --- a/splunklib/searchcommands/search_command.py +++ b/splunklib/searchcommands/search_command.py @@ -862,8 +862,7 @@ def _as_binary_stream(ifile): @staticmethod def _read_chunk(istream): # noinspection PyBroadException - if not six.PY2: - assert issubclass(type(istream), (io.BufferedIOBase, io.RawIOBase)), 'Stream must be binary' + assert isinstance(istream.read(0), six.binary_type), 'Stream must be binary' try: header = istream.readline() From 27f92a54989a20e137ddd9076899f87896acb42a Mon Sep 17 00:00:00 2001 From: David Poncelow Date: Tue, 8 Sep 2020 14:25:05 -0700 Subject: [PATCH 6/8] add test for v1 search commands --- tests/searchcommands/test_multibyte_processing.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/searchcommands/test_multibyte_processing.py b/tests/searchcommands/test_multibyte_processing.py index 5a19220dd..4d6127fe9 100644 --- a/tests/searchcommands/test_multibyte_processing.py +++ b/tests/searchcommands/test_multibyte_processing.py @@ -7,21 +7,33 @@ from splunklib import six from splunklib.searchcommands import StreamingCommand, Configuration + def build_test_command(): @Configuration() class TestSearchCommand(StreamingCommand): def stream(self, records): for record in records: yield record + return TestSearchCommand() + def get_input_file(name): return path.join( path.dirname(path.dirname(__file__)), 'data', 'custom_search', name + '.gz') + def test_multibyte_chunked(): data = gzip.open(get_input_file("multibyte_input")) if not six.PY2: data = io.TextIOWrapper(data) cmd = build_test_command() cmd._process_protocol_v2(sys.argv, data, sys.stdout) + + +def test_v1_searchcommand(): + data = gzip.open(get_input_file("v1_search_input")) + if not six.PY2: + data = io.TextIOWrapper(data) + cmd = build_test_command() + cmd._process_protocol_v1(["test_script.py", "__EXECUTE__"], data, sys.stdout) From f15390b895ce325f156527ab48a422b068eb0cb8 Mon Sep 17 00:00:00 2001 From: David Poncelow Date: Tue, 8 Sep 2020 15:27:01 -0700 Subject: [PATCH 7/8] add test data for previous test --- tests/data/custom_search/v1_search_input.gz | Bin 0 -> 63222 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/custom_search/v1_search_input.gz diff --git a/tests/data/custom_search/v1_search_input.gz b/tests/data/custom_search/v1_search_input.gz new file mode 100644 index 0000000000000000000000000000000000000000..d1dcf2819e135dd3756a36515d11650df2784945 GIT binary patch literal 63222 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 Date: Tue, 8 Sep 2020 17:53:28 -0700 Subject: [PATCH 8/8] Version 1.6.14 --- CHANGELOG.md | 17 +++++++++++------ README.md | 2 +- examples/searchcommands_app/setup.py | 10 +++++----- splunklib/__init__.py | 2 +- splunklib/binding.py | 2 +- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f28c9fe..45f88f519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,17 @@ # Splunk SDK for Python Changelog +## Version 1.6.14 + +### Bug fix +* `SearchCommand` now correctly supports multibyte characters in Python 3. + ## Version 1.6.13 ### Bug fix -* Fixed regression in mod inputs which resulted in error ’file' object has no attribute 'readable’, by not forcing to text/bytes in mod inputs event writer any longer. +* Fixed regression in mod inputs which resulted in error ’file' object has no attribute 'readable’, by not forcing to text/bytes in mod inputs event writer any longer. ### Minor changes -* Minor updates to the splunklib search commands to support Python3 +* Minor updates to the splunklib search commands to support Python3 ## Version 1.6.12 @@ -22,25 +27,25 @@ ### Bug Fix -* Fix custom search command V2 failures on Windows for Python3 +* Fix custom search command V2 failures on Windows for Python3 ## Version 1.6.10 ### Bug Fix -* Fix long type gets wrong values on windows for python 2 +* Fix long type gets wrong values on windows for python 2 ## Version 1.6.9 ### Bug Fix -* Fix buffered input in python 3 +* Fix buffered input in python 3 ## Version 1.6.8 ### Bug Fix -* Fix custom search command on python 3 on windows +* Fix custom search command on python 3 on windows ## Version 1.6.7 diff --git a/README.md b/README.md index 92c7220c0..3f429825e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # The Splunk Software Development Kit for Python -#### Version 1.6.13 +#### Version 1.6.14 The Splunk Software Development Kit (SDK) for Python contains library code and examples designed to enable developers to build applications using Splunk. diff --git a/examples/searchcommands_app/setup.py b/examples/searchcommands_app/setup.py index 359199a37..ec2118dd0 100755 --- a/examples/searchcommands_app/setup.py +++ b/examples/searchcommands_app/setup.py @@ -111,8 +111,8 @@ def splunk_restart(uri, auth): class AnalyzeCommand(Command): - """ - setup.py command to run code coverage of the test suite. + """ + setup.py command to run code coverage of the test suite. """ description = 'Create an HTML coverage report from running the full test suite.' @@ -367,8 +367,8 @@ def _link_debug_client(self): class TestCommand(Command): - """ - setup.py command to run the whole test suite. + """ + setup.py command to run the whole test suite. """ description = 'Run full test suite.' @@ -439,7 +439,7 @@ def run(self): setup( description='Custom Search Command examples', name=os.path.basename(project_dir), - version='1.6.13', + version='1.6.14', author='Splunk, Inc.', author_email='devinfo@splunk.com', url='http://github.com/splunk/splunk-sdk-python', diff --git a/splunklib/__init__.py b/splunklib/__init__.py index e4cde3bdc..a879ab9d1 100644 --- a/splunklib/__init__.py +++ b/splunklib/__init__.py @@ -16,5 +16,5 @@ from __future__ import absolute_import from splunklib.six.moves import map -__version_info__ = (1, 6, 13) +__version_info__ = (1, 6, 14) __version__ = ".".join(map(str, __version_info__)) diff --git a/splunklib/binding.py b/splunklib/binding.py index 81780c6ed..e7336f2a1 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -1378,7 +1378,7 @@ def request(url, message, **kwargs): head = { "Content-Length": str(len(body)), "Host": host, - "User-Agent": "splunk-sdk-python/1.6.13", + "User-Agent": "splunk-sdk-python/1.6.14", "Accept": "*/*", "Connection": "Close", } # defaults