Skip to content

Commit a8ede1a

Browse files
committed
Updates as per the review/feedback comments
1 parent 0738778 commit a8ede1a

16 files changed

+38
-74
lines changed

Diff for: CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Version 2.0.0-beta
44

55
### Feature updates
6-
* `ensure_binary`, `ensure_str`, `ensure_text` and `assert_regex` utility methods have been migrated from `six.py` to `splunklib/utils.py`
6+
* `ensure_binary`, `ensure_str` and `assert_regex` utility methods have been migrated from `six.py` to `splunklib/utils.py`
77

88
### Major changes
99
* Removed Code specific to Python2

Diff for: Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ test_specific:
4444
.PHONY: test_smoke
4545
test_smoke:
4646
@echo "$(ATTN_COLOR)==> test_smoke $(NO_COLOR)"
47-
@tox -e py27,py37 -- -m smoke
47+
@tox -e py37,py39 -- -m smoke
4848

4949
.PHONY: test_no_app
5050
test_no_app:
5151
@echo "$(ATTN_COLOR)==> test_no_app $(NO_COLOR)"
52-
@tox -e py27,py37 -- -m "not app"
52+
@tox -e py37,py39 -- -m "not app"
5353

5454
.PHONY: test_smoke_no_app
5555
test_smoke_no_app:
5656
@echo "$(ATTN_COLOR)==> test_smoke_no_app $(NO_COLOR)"
57-
@tox -e py27,py37 -- -m "smoke and not app"
57+
@tox -e py37,py39 -- -m "smoke and not app"
5858

5959
.PHONY: env
6060
env:

Diff for: README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ The Splunk Enterprise SDK for Python contains library code, and it's examples ar
2525

2626
Here's what you need to get going with the Splunk Enterprise SDK for Python.
2727

28-
* Python 2.7+ or Python 3.7.
28+
* Python 3.7 or Python 3.9.
2929

30-
The Splunk Enterprise SDK for Python has been tested with Python v2.7 and v3.7.
30+
The Splunk Enterprise SDK for Python is compatible with python3 and has been tested with Python v3.7 and v3.9.
3131

32-
* Splunk Enterprise 9.0 or 8.2
32+
* Splunk Enterprise 9.2 or 8.2
3333

34-
The Splunk Enterprise SDK for Python has been tested with Splunk Enterprise 9.0, 8.2 and 8.1
34+
The Splunk Enterprise SDK for Python has been tested with Splunk Enterprise 9.2, 8.2 and 8.1
3535

3636
If you haven't already installed Splunk Enterprise, download it [here](http://www.splunk.com/download).
3737
For more information, see the Splunk Enterprise [_Installation Manual_](https://docs.splunk.com/Documentation/Splunk/latest/Installation).
@@ -61,7 +61,7 @@ Install the sources you cloned from GitHub:
6161
You'll need `docker` and `docker-compose` to get up and running using this method.
6262

6363
```
64-
make up SPLUNK_VERSION=9.0
64+
make up SPLUNK_VERSION=9.2
6565
make wait_up
6666
make test
6767
make down
@@ -110,7 +110,7 @@ here is an example of .env file:
110110
# Access scheme (default: https)
111111
scheme=https
112112
# Your version of Splunk Enterprise
113-
version=9.0
113+
version=9.2
114114
# Bearer token for authentication
115115
#splunkToken=<Bearer-token>
116116
# Session key for authentication

Diff for: scripts/test_specific.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
echo "To run a specific test:"
2-
echo " tox -e py27,py37 [test_file_path]::[TestClassName]::[test_method]"
2+
echo " tox -e py37,py39 [test_file_path]::[TestClassName]::[test_method]"
33
echo "For Example, To run 'test_autologin' testcase from 'test_service.py' file run"
44
echo " tox -e py37 -- tests/test_service.py::ServiceTestCase::test_autologin"

Diff for: splunklib/binding.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def __new__(self, val='', skip_encode=False, encode_slash=False):
201201
return str.__new__(self, val)
202202
if encode_slash:
203203
return str.__new__(self, parse.quote_plus(val))
204-
# When subclassing str, just call str.__new__ method
204+
# When subclassing str, just call str.__new__ method
205205
# with your class and the value you want to have in the
206206
# new string.
207207
return str.__new__(self, parse.quote(val))

Diff for: splunklib/client.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1982,9 +1982,6 @@ def delete(self, username, realm=None):
19821982
:return: The `StoragePassword` collection.
19831983
:rtype: ``self``
19841984
"""
1985-
if self.service.namespace.owner == '-' or self.service.namespace.app == '-':
1986-
raise ValueError("app context must be specified when removing a password.")
1987-
19881985
if realm is None:
19891986
# This case makes the username optional, so
19901987
# the full name can be passed in as realm.
@@ -3751,7 +3748,7 @@ def update_accelerated_field(self, name, value):
37513748
:return: Result of POST request
37523749
"""
37533750
kwargs = {}
3754-
kwargs['accelerated_fields.' + name] = value if isinstance(value, str) else json.dumps(value)
3751+
kwargs['accelerated_fields.' + name] = json.dumps(value) if isinstance(value, dict) else value
37553752
return self.post(**kwargs)
37563753

37573754
def update_field(self, name, value):

Diff for: splunklib/modularinput/event.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from io import TextIOBase
1616
import xml.etree.ElementTree as ET
1717

18-
from splunklib.utils import ensure_text
18+
from splunklib.utils import ensure_str
1919

2020

2121
class Event:
@@ -105,7 +105,7 @@ def write_to(self, stream):
105105
ET.SubElement(event, "done")
106106

107107
if isinstance(stream, TextIOBase):
108-
stream.write(ensure_text(ET.tostring(event)))
108+
stream.write(ensure_str(ET.tostring(event)))
109109
else:
110110
stream.write(ET.tostring(event))
111111
stream.flush()

Diff for: splunklib/searchcommands/decorators.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# under the License.
1616

1717

18-
from collections import OrderedDict # must be python 2.7
18+
from collections import OrderedDict
1919
from inspect import getmembers, isclass, isfunction
2020

2121

Diff for: splunklib/searchcommands/internals.py

+3-19
Original file line numberDiff line numberDiff line change
@@ -40,30 +40,15 @@ def set_binary_mode(fh):
4040
""" Helper method to set up binary mode for file handles.
4141
Emphasis being sys.stdin, sys.stdout, sys.stderr.
4242
For python3, we want to return .buffer
43-
For python2+windows we want to set os.O_BINARY
4443
"""
45-
typefile = TextIOWrapper if sys.version_info >= (3, 0) else file
44+
typefile = TextIOWrapper
4645
# check for file handle
4746
if not isinstance(fh, typefile):
4847
return fh
4948

50-
# check for python3 and buffer
51-
if sys.version_info >= (3, 0) and hasattr(fh, 'buffer'):
49+
# check for buffer
50+
if hasattr(fh, 'buffer'):
5251
return fh.buffer
53-
# check for python3
54-
if sys.version_info >= (3, 0):
55-
pass
56-
# check for windows python2. SPL-175233 -- python3 stdout is already binary
57-
elif sys.platform == 'win32':
58-
# Work around the fact that on Windows '\n' is mapped to '\r\n'. The typical solution is to simply open files in
59-
# binary mode, but stdout is already open, thus this hack. 'CPython' and 'PyPy' work differently. We assume that
60-
# all other Python implementations are compatible with 'CPython'. This might or might not be a valid assumption.
61-
from platform import python_implementation
62-
implementation = python_implementation()
63-
if implementation == 'PyPy':
64-
return os.fdopen(fh.fileno(), 'wb', 0)
65-
import msvcrt
66-
msvcrt.setmode(fh.fileno(), os.O_BINARY)
6752
return fh
6853

6954

@@ -684,7 +669,6 @@ def _write_record(self, record):
684669
# We may be running under PyPy 2.5 which does not include the _json module
685670
_iterencode_json = JSONEncoder(separators=(',', ':')).iterencode
686671
else:
687-
# Creating _iterencode_json this way yields a two-fold performance improvement on Python 2.7.9 and 2.7.10
688672
from json.encoder import encode_basestring_ascii
689673

690674
@staticmethod

Diff for: splunklib/utils.py

-12
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,5 @@ def ensure_str(s, encoding='utf-8', errors='strict'):
4444
raise TypeError(f"not expecting type '{type(s)}'")
4545

4646

47-
def ensure_text(s, encoding='utf-8', errors='strict'):
48-
"""
49-
- `str` -> `str`
50-
- `bytes` -> decoded to `str`
51-
"""
52-
if isinstance(s, bytes):
53-
return s.decode(encoding, errors)
54-
if isinstance(s, str):
55-
return s
56-
raise TypeError(f"not expecting type '{type(s)}'")
57-
58-
5947
def assertRegex(self, *args, **kwargs):
6048
return getattr(self, "assertRegex")(*args, **kwargs)

Diff for: tests/README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
# Splunk Test Suite
22

33
The test suite uses Python's standard library and the built-in **unittest**
4-
library. If you're using Python 2.7 or Python 3.7, you're all set. However, if you are using
5-
Python 2.6, you'll also need to install the **unittest2** library to get the
6-
additional features that were added to Python 2.7 (just run `pip install
7-
unittest2` or `easy_install unittest2`).
4+
library. The Splunk Enterprise SDK for Python has been tested with Python v3.7
5+
and v3.9.
86

97
To run the unit tests, open a command prompt in the **/splunk-sdk-python**
108
directory and enter:

Diff for: tests/searchcommands/chunked_data_stream.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
import json
55

66
import splunklib.searchcommands.internals
7+
from splunklib.utils import ensure_binary, ensure_str
78

89

910
class Chunk:
1011
def __init__(self, version, meta, data):
11-
self.version = version
12+
self.version = ensure_str(version)
1213
self.meta = json.loads(meta)
1314
dialect = splunklib.searchcommands.internals.CsvDialect
1415
self.data = csv.DictReader(io.StringIO(data.decode("utf-8")),
@@ -20,9 +21,9 @@ def __init__(self, chunk_stream):
2021
self.chunk_stream = chunk_stream
2122

2223
def __next__(self):
23-
return next(self)
24+
return self.next()
2425

25-
def __next__(self):
26+
def next(self):
2627
try:
2728
return self.chunk_stream.read_chunk()
2829
except EOFError:
@@ -53,7 +54,7 @@ def read_chunk(self):
5354

5455

5556
def build_chunk(keyval, data=None):
56-
metadata = json.dumps(keyval).encode('utf-8')
57+
metadata = ensure_binary(json.dumps(keyval))
5758
data_output = _build_data_csv(data)
5859
return b"chunked 1.0,%d,%d\n%s%s" % (len(metadata), len(data_output), metadata, data_output)
5960

@@ -96,4 +97,4 @@ def _build_data_csv(data):
9697
writer.writeheader()
9798
for datum in data:
9899
writer.writerow(datum)
99-
return csvout.getvalue().encode('utf-8')
100+
return ensure_binary(csvout.getvalue())

Diff for: tests/test_binding.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from splunklib import binding
3333
from splunklib.binding import HTTPError, AuthenticationError, UrlEncoded
3434
from splunklib import data
35+
from splunklib.utils import ensure_str
3536

3637
import pytest
3738

@@ -963,7 +964,7 @@ def check_response(handler):
963964
length = int(handler.headers.get('content-length', 0))
964965
body = handler.rfile.read(length)
965966
assert handler.headers['content-type'] == 'application/x-www-form-urlencoded'
966-
assert body.decode('utf-8') in ['baz=baf&hep=cat', 'hep=cat&baz=baf']
967+
assert ensure_str(body) in ['baz=baf&hep=cat', 'hep=cat&baz=baf']
967968

968969
with MockServer(POST=check_response):
969970
ctx = binding.connect(port=9093, scheme='http', token="waffle")

Diff for: tests/test_collection.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def test_list(self):
8080
logging.debug(f"No entities in collection {coll_name}; skipping test.")
8181
found = [ent.name for ent in coll.list()][:10]
8282
self.assertEqual(expected, found,
83-
msg=f'on {coll_name} (expected {expected}, found {found})')
83+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
8484

8585
def test_list_with_count(self):
8686
N = 5
@@ -111,7 +111,7 @@ def test_list_with_search(self):
111111
# TODO: DVPL-5868 - This should use a real search instead of *. Otherwise the test passes trivially.
112112
found = [ent.name for ent in coll.list(search="*")]
113113
self.assertEqual(expected, found,
114-
msg=f'on {coll_name} (expected {expected}, found {found})')
114+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
115115

116116
def test_list_with_sort_dir(self):
117117
for coll_name in collections:
@@ -127,7 +127,7 @@ def test_list_with_sort_dir(self):
127127
found = [ent.name for ent in coll.list(**found_kwargs)]
128128

129129
self.assertEqual(sorted(expected), sorted(found),
130-
msg=f'on {coll_name} (expected {expected}, found {found})')
130+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
131131

132132
def test_list_with_sort_mode_auto(self):
133133
# The jobs collection requires special handling. The sort_dir kwarg is
@@ -151,7 +151,7 @@ def test_list_with_sort_mode_auto(self):
151151
else:
152152
found = [ent.name for ent in coll.list()]
153153

154-
self.assertEqual(expected, found, msg=f'on {coll_name} (expected {expected}, found {found})')
154+
self.assertEqual(expected, found, msg=f'on {coll_name} (expected: {expected}, found: {found})')
155155

156156
def test_list_with_sort_mode_alpha_case(self):
157157
for coll_name in collections:
@@ -166,7 +166,7 @@ def test_list_with_sort_mode_alpha_case(self):
166166
logging.debug(f"No entities in collection {coll_name}; skipping test.")
167167
expected = sorted(found)
168168
self.assertEqual(expected, found,
169-
msg=f'on {coll_name} (expected {expected}, found {found})')
169+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
170170

171171
def test_list_with_sort_mode_alpha(self):
172172
for coll_name in collections:
@@ -184,7 +184,7 @@ def test_list_with_sort_mode_alpha(self):
184184
logging.debug(f"No entities in collection {coll_name}; skipping test.")
185185
expected = sorted(found, key=str.lower)
186186
self.assertEqual(expected, found,
187-
msg=f'on {coll_name} (expected {expected}, found {found})')
187+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
188188

189189
def test_iteration(self):
190190
for coll_name in collections:
@@ -197,7 +197,7 @@ def test_iteration(self):
197197
for ent in coll.iter(pagesize=max(int(total / 5.0), 1), count=10):
198198
found.append(ent.name)
199199
self.assertEqual(expected, found,
200-
msg=f'on {coll_name} (expected {expected}, found {found})')
200+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
201201

202202
def test_paging(self):
203203
for coll_name in collections:
@@ -218,7 +218,7 @@ def test_paging(self):
218218
found.extend([ent.name for ent in page])
219219
logging.debug("Iterate: offset=%d/%d", offset, total)
220220
self.assertEqual(expected, found,
221-
msg=f'on {coll_name} (expected {expected}, found {found})')
221+
msg=f'on {coll_name} (expected: {expected}, found: {found})')
222222

223223
def test_getitem_with_nonsense(self):
224224
for coll_name in collections:

Diff for: tests/test_job.py

-5
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@
3030

3131
import pytest
3232

33-
# TODO: Determine if we should be importing ExpatError if ParseError is not available (e.g., on Python 2.6)
34-
# There's code below that now catches SyntaxError instead of ParseError. Should we be catching ExpathError instead?
35-
36-
# from xml.etree.ElementTree import ParseError
37-
3833

3934
class TestUtilities(testlib.SDKTestCase):
4035
def test_service_search(self):

Diff for: tests/testlib.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def to_bool(x):
5555
return True
5656
if x == '0':
5757
return False
58-
raise ValueError("Not a boolean value: %s", x)
58+
raise ValueError(f"Not a boolean value: {x}")
5959

6060

6161
def tmpname():

0 commit comments

Comments
 (0)