Skip to content

Commit

Permalink
Updates as per the review/feedback comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ashah-splunk committed Feb 7, 2024
1 parent 0738778 commit a8ede1a
Show file tree
Hide file tree
Showing 16 changed files with 38 additions and 74 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Version 2.0.0-beta

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

### Major changes
* Removed Code specific to Python2
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,17 @@ test_specific:
.PHONY: test_smoke
test_smoke:
@echo "$(ATTN_COLOR)==> test_smoke $(NO_COLOR)"
@tox -e py27,py37 -- -m smoke
@tox -e py37,py39 -- -m smoke

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

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

.PHONY: env
env:
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ The Splunk Enterprise SDK for Python contains library code, and it's examples ar

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

* Python 2.7+ or Python 3.7.
* Python 3.7 or Python 3.9.

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

* Splunk Enterprise 9.0 or 8.2
* Splunk Enterprise 9.2 or 8.2

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

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

```
make up SPLUNK_VERSION=9.0
make up SPLUNK_VERSION=9.2
make wait_up
make test
make down
Expand Down Expand Up @@ -110,7 +110,7 @@ here is an example of .env file:
# Access scheme (default: https)
scheme=https
# Your version of Splunk Enterprise
version=9.0
version=9.2
# Bearer token for authentication
#splunkToken=<Bearer-token>
# Session key for authentication
Expand Down
2 changes: 1 addition & 1 deletion scripts/test_specific.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
echo "To run a specific test:"
echo " tox -e py27,py37 [test_file_path]::[TestClassName]::[test_method]"
echo " tox -e py37,py39 [test_file_path]::[TestClassName]::[test_method]"
echo "For Example, To run 'test_autologin' testcase from 'test_service.py' file run"
echo " tox -e py37 -- tests/test_service.py::ServiceTestCase::test_autologin"
2 changes: 1 addition & 1 deletion splunklib/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def __new__(self, val='', skip_encode=False, encode_slash=False):
return str.__new__(self, val)
if encode_slash:
return str.__new__(self, parse.quote_plus(val))
# When subclassing str, just call str.__new__ method
# When subclassing str, just call str.__new__ method
# with your class and the value you want to have in the
# new string.
return str.__new__(self, parse.quote(val))
Expand Down
5 changes: 1 addition & 4 deletions splunklib/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1982,9 +1982,6 @@ def delete(self, username, realm=None):
:return: The `StoragePassword` collection.
:rtype: ``self``
"""
if self.service.namespace.owner == '-' or self.service.namespace.app == '-':
raise ValueError("app context must be specified when removing a password.")

if realm is None:
# This case makes the username optional, so
# the full name can be passed in as realm.
Expand Down Expand Up @@ -3751,7 +3748,7 @@ def update_accelerated_field(self, name, value):
:return: Result of POST request
"""
kwargs = {}
kwargs['accelerated_fields.' + name] = value if isinstance(value, str) else json.dumps(value)
kwargs['accelerated_fields.' + name] = json.dumps(value) if isinstance(value, dict) else value
return self.post(**kwargs)

def update_field(self, name, value):
Expand Down
4 changes: 2 additions & 2 deletions splunklib/modularinput/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from io import TextIOBase
import xml.etree.ElementTree as ET

from splunklib.utils import ensure_text
from splunklib.utils import ensure_str


class Event:
Expand Down Expand Up @@ -105,7 +105,7 @@ def write_to(self, stream):
ET.SubElement(event, "done")

if isinstance(stream, TextIOBase):
stream.write(ensure_text(ET.tostring(event)))
stream.write(ensure_str(ET.tostring(event)))
else:
stream.write(ET.tostring(event))
stream.flush()
2 changes: 1 addition & 1 deletion splunklib/searchcommands/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# under the License.


from collections import OrderedDict # must be python 2.7
from collections import OrderedDict
from inspect import getmembers, isclass, isfunction


Expand Down
22 changes: 3 additions & 19 deletions splunklib/searchcommands/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,15 @@ def set_binary_mode(fh):
""" Helper method to set up binary mode for file handles.
Emphasis being sys.stdin, sys.stdout, sys.stderr.
For python3, we want to return .buffer
For python2+windows we want to set os.O_BINARY
"""
typefile = TextIOWrapper if sys.version_info >= (3, 0) else file
typefile = TextIOWrapper
# check for file handle
if not isinstance(fh, typefile):
return fh

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


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

@staticmethod
Expand Down
12 changes: 0 additions & 12 deletions splunklib/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,5 @@ def ensure_str(s, encoding='utf-8', errors='strict'):
raise TypeError(f"not expecting type '{type(s)}'")


def ensure_text(s, encoding='utf-8', errors='strict'):
"""
- `str` -> `str`
- `bytes` -> decoded to `str`
"""
if isinstance(s, bytes):
return s.decode(encoding, errors)
if isinstance(s, str):
return s
raise TypeError(f"not expecting type '{type(s)}'")


def assertRegex(self, *args, **kwargs):
return getattr(self, "assertRegex")(*args, **kwargs)
6 changes: 2 additions & 4 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Splunk Test Suite

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

To run the unit tests, open a command prompt in the **/splunk-sdk-python**
directory and enter:
Expand Down
11 changes: 6 additions & 5 deletions tests/searchcommands/chunked_data_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import json

import splunklib.searchcommands.internals
from splunklib.utils import ensure_binary, ensure_str


class Chunk:
def __init__(self, version, meta, data):
self.version = version
self.version = ensure_str(version)
self.meta = json.loads(meta)
dialect = splunklib.searchcommands.internals.CsvDialect
self.data = csv.DictReader(io.StringIO(data.decode("utf-8")),
Expand All @@ -20,9 +21,9 @@ def __init__(self, chunk_stream):
self.chunk_stream = chunk_stream

def __next__(self):
return next(self)
return self.next()

def __next__(self):
def next(self):
try:
return self.chunk_stream.read_chunk()
except EOFError:
Expand Down Expand Up @@ -53,7 +54,7 @@ def read_chunk(self):


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

Expand Down Expand Up @@ -96,4 +97,4 @@ def _build_data_csv(data):
writer.writeheader()
for datum in data:
writer.writerow(datum)
return csvout.getvalue().encode('utf-8')
return ensure_binary(csvout.getvalue())
3 changes: 2 additions & 1 deletion tests/test_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from splunklib import binding
from splunklib.binding import HTTPError, AuthenticationError, UrlEncoded
from splunklib import data
from splunklib.utils import ensure_str

import pytest

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

with MockServer(POST=check_response):
ctx = binding.connect(port=9093, scheme='http', token="waffle")
Expand Down
16 changes: 8 additions & 8 deletions tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_list(self):
logging.debug(f"No entities in collection {coll_name}; skipping test.")
found = [ent.name for ent in coll.list()][:10]
self.assertEqual(expected, found,
msg=f'on {coll_name} (expected {expected}, found {found})')
msg=f'on {coll_name} (expected: {expected}, found: {found})')

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

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

self.assertEqual(sorted(expected), sorted(found),
msg=f'on {coll_name} (expected {expected}, found {found})')
msg=f'on {coll_name} (expected: {expected}, found: {found})')

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

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

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

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

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

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

def test_getitem_with_nonsense(self):
for coll_name in collections:
Expand Down
5 changes: 0 additions & 5 deletions tests/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@

import pytest

# TODO: Determine if we should be importing ExpatError if ParseError is not available (e.g., on Python 2.6)
# There's code below that now catches SyntaxError instead of ParseError. Should we be catching ExpathError instead?

# from xml.etree.ElementTree import ParseError


class TestUtilities(testlib.SDKTestCase):
def test_service_search(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/testlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def to_bool(x):
return True
if x == '0':
return False
raise ValueError("Not a boolean value: %s", x)
raise ValueError(f"Not a boolean value: {x}")


def tmpname():
Expand Down

0 comments on commit a8ede1a

Please sign in to comment.