Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
300 changes: 66 additions & 234 deletions .basedpyright/baseline.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ lint: lint-python # TODO: Add mbake
.PHONY: lint-python
lint-python:
$(UV_RUN_CMD) basedpyright
# $(UV_RUN_CMD) ruff check --fix-only
$(UV_RUN_CMD) ruff check --fix-only
$(UV_RUN_CMD) ruff format

UV_RUN_CMD := uv run --frozen --no-config
Expand All @@ -37,7 +37,7 @@ ci-lint: ci-lint-python # TODO: Add mbake
.PHONY: ci-lint-python
ci-lint-python:
$(UV_RUN_CMD) basedpyright
# $(UV_RUN_CMD) ruff check
$(UV_RUN_CMD) ruff check
$(UV_RUN_CMD) ruff format --check

.PHONY: clean
Expand Down
2 changes: 1 addition & 1 deletion splunklib/ai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
__all__ = [
"Agent",
"AnthropicModel",
"OpenAIModel",
"GoogleModel",
"OpenAIModel",
"create_structured_prompt",
"detect_injection",
"truncate_input",
Expand Down
4 changes: 1 addition & 3 deletions splunklib/ai/engines/langchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1859,9 +1859,7 @@ def check_tool_name(type: str, name: str) -> None:

last_ai_message: AIMessage | None = None
for message in messages:
if type(message) is HumanMessage:
check_no_pending_calls()
elif type(message) is SystemMessage:
if type(message) is HumanMessage or type(message) is SystemMessage:
check_no_pending_calls()
elif type(message) is AIMessage:
last_ai_message = message
Expand Down
34 changes: 18 additions & 16 deletions splunklib/ai/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,22 +296,24 @@ async def connect_remote_mcp(
mcp_url = f"{management_url}/services/mcp"
mcp_token = await asyncio.to_thread(lambda: _get_mcp_token(splunk_username, service))
if mcp_token is not None:
async with streamable_http_client(
url=mcp_url,
http_client=httpx.AsyncClient(
headers={
"x-splunk-trace-id": trace_id,
"x-splunk-app-id": app_id,
},
auth=_MCPAuth(f"Bearer {mcp_token}"),
verify=False,
follow_redirects=True,
timeout=httpx.Timeout(_MCP_DEFAULT_TIMEOUT, read=_MCP_DEFAULT_SSE_READ_TIMEOUT),
),
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
yield session
async with (
streamable_http_client(
url=mcp_url,
http_client=httpx.AsyncClient(
headers={
"x-splunk-trace-id": trace_id,
"x-splunk-app-id": app_id,
},
auth=_MCPAuth(f"Bearer {mcp_token}"),
verify=False,
follow_redirects=True,
timeout=httpx.Timeout(_MCP_DEFAULT_TIMEOUT, read=_MCP_DEFAULT_SSE_READ_TIMEOUT),
),
) as (read, write, _),
ClientSession(read, write) as session,
):
await session.initialize()
yield session
else:
yield None

Expand Down
12 changes: 6 additions & 6 deletions splunklib/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@

__all__ = [
"AuthenticationError",
"connect",
"Context",
"handler",
"HTTPError",
"UrlEncoded",
"_NoAuthenticationToken",
"_encode",
"_make_cookie_header",
"_NoAuthenticationToken",
"connect",
"handler",
"namespace",
]

Expand Down Expand Up @@ -102,7 +102,7 @@ def mask_sensitive_data(data):
if not isinstance(data, dict):
try:
data = json.loads(data)
except Exception as ex:
except Exception:
return data

# json.loads will return "123"(str) as 123(int), so return the data if it's not 'dict' type
Expand Down Expand Up @@ -252,7 +252,7 @@ def __mod__(self, fields):
raise TypeError("Cannot interpolate into a UrlEncoded object.")

def __repr__(self):
return f"UrlEncoded({repr(parse.unquote(str(self)))})"
return f"UrlEncoded({parse.unquote(str(self))!r})"


@contextmanager
Expand Down Expand Up @@ -1619,7 +1619,7 @@ def request(self, url, message, **kwargs):
time.sleep(self.retryDelay)
self.retries -= 1
response = record(response)
if 400 <= response.status:
if response.status >= 400:
raise HTTPError(response)

# Update the cookie with any HTTP request
Expand Down
30 changes: 15 additions & 15 deletions splunklib/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ def restart(self, timeout=None):
continue
else:
return result
except Exception as e:
except Exception:
sleep(1)
raise Exception("Operation time out.")

Expand Down Expand Up @@ -1053,7 +1053,7 @@ def __init__(self, service, path, **kwargs):
Endpoint.__init__(self, service, path)
self._state = None
if not kwargs.get("skip_refresh", False):
self.refresh(kwargs.get("state", None)) # "Prefresh"
self.refresh(kwargs.get("state")) # "Prefresh"

def __contains__(self, item):
try:
Expand Down Expand Up @@ -1645,7 +1645,7 @@ def iter(self, offset=0, count=None, pagesize=None, **kwargs):
fetched += N
for item in items:
yield item
if pagesize is None or N < pagesize:
if pagesize is None or pagesize > N:
break
offset += N
logger.debug(
Expand Down Expand Up @@ -1945,7 +1945,7 @@ def create(self, name):
# a ConfigurationFile (which is a Collection) instead of some
# Entity.
if not isinstance(name, str):
raise ValueError(f"Invalid name: {repr(name)}")
raise ValueError(f"Invalid name: {name!r}")
response = self.post(__conf=name)
if response.status == 303:
return self[name]
Expand Down Expand Up @@ -1996,7 +1996,7 @@ class StoragePassword(Entity):
"""This class contains a storage password."""

def __init__(self, service, path, **kwargs):
state = kwargs.get("state", None)
state = kwargs.get("state")
kwargs["skip_refresh"] = kwargs.get("skip_refresh", state is not None)
super().__init__(service, path, **kwargs)
self._state = state
Expand Down Expand Up @@ -2047,7 +2047,7 @@ def create(self, password, username, realm=None):
:return: The :class:`StoragePassword` object created.
"""
if not isinstance(username, str):
raise ValueError(f"Invalid name: {repr(username)}")
raise ValueError(f"Invalid name: {username!r}")

if realm is None:
response = self.post(password=password, name=username)
Expand Down Expand Up @@ -2202,8 +2202,8 @@ def attach(self, host=None, source=None, sourcetype=None):
# the input mode
sock = self.service.connect()
headers = [
f"POST {str(self.service._abspath(path))} HTTP/1.1\r\n".encode("utf-8"),
f"Host: {self.service.host}:{int(self.service.port)}\r\n".encode("utf-8"),
f"POST {self.service._abspath(path)!s} HTTP/1.1\r\n".encode(),
f"Host: {self.service.host}:{int(self.service.port)}\r\n".encode(),
b"Accept-Encoding: identity\r\n",
cookie_or_auth_header.encode("utf-8"),
b"X-Splunk-Input-Mode: Streaming\r\n",
Expand Down Expand Up @@ -2806,14 +2806,14 @@ def list(self, *kinds, **kwargs):
entities = entities[kwargs["offset"] :]
if "count" in kwargs:
entities = entities[: kwargs["count"]]
if kwargs.get("sort_mode", None) == "alpha":
if kwargs.get("sort_mode") == "alpha":
sort_field = kwargs.get("sort_field", "name")
if sort_field == "name":
f = lambda x: x.name.lower()
else:
f = lambda x: x[sort_field].lower()
entities = sorted(entities, key=f)
if kwargs.get("sort_mode", None) == "alpha_case":
if kwargs.get("sort_mode") == "alpha_case":
sort_field = kwargs.get("sort_field", "name")
if sort_field == "name":
f = lambda x: x.name
Expand Down Expand Up @@ -3199,10 +3199,10 @@ def create(self, query, **kwargs):

:return: The :class:`Job`.
"""
if kwargs.get("exec_mode", None) == "oneshot":
if kwargs.get("exec_mode") == "oneshot":
raise TypeError("Cannot specify exec_mode=oneshot; use the oneshot method instead.")
response = self.post(search=query, **kwargs)
sid = _load_sid(response, kwargs.get("output_mode", None))
sid = _load_sid(response, kwargs.get("output_mode"))
return Job(self.service, sid)

def export(self, query, **params):
Expand Down Expand Up @@ -3421,7 +3421,7 @@ def dispatch(self, **kwargs):
:return: The :class:`Job`.
"""
response = self.post("dispatch", **kwargs)
sid = _load_sid(response, kwargs.get("output_mode", None))
sid = _load_sid(response, kwargs.get("output_mode"))
return Job(self.service, sid)

@property
Expand Down Expand Up @@ -3737,7 +3737,7 @@ def create(self, username, password, roles, **params):
hilda = users.create("hilda", "anotherpassword", roles=["user", "power"])
"""
if not isinstance(username, str):
raise ValueError(f"Invalid username: {str(username)}")
raise ValueError(f"Invalid username: {username!s}")
username = username.lower()
self.post(name=username, password=password, roles=roles, **params)
# splunkd doesn't return the user in the POST response body,
Expand Down Expand Up @@ -3859,7 +3859,7 @@ def create(self, name, **params):
paltry = roles.create("paltry", imported_roles="user", defaultApp="search")
"""
if not isinstance(name, str):
raise ValueError(f"Invalid role name: {str(name)}")
raise ValueError(f"Invalid role name: {name!s}")
name = name.lower()
self.post(name=name, **params)
# splunkd doesn't return the user in the POST response body,
Expand Down
2 changes: 1 addition & 1 deletion splunklib/modularinput/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ def parse_xml_data(parent_node, child_node_tag):
data[child_name] = {"__app": child.get("app", None)}
for param in child:
data[child_name][param.get("name")] = parse_parameters(param)
elif "item" == parent_node.tag:
elif parent_node.tag == "item":
data[child_name] = parse_parameters(child)
return data
2 changes: 1 addition & 1 deletion splunklib/searchcommands/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def _get_specification(self):
try:
specification = ConfigurationSettingsType.specification_matrix[name]
except KeyError:
raise AttributeError(f"Unknown configuration setting: {name}={repr(self._value)}")
raise AttributeError(f"Unknown configuration setting: {name}={self._value!r}")

return ConfigurationSettingsType.validate_configuration_setting, specification

Expand Down
12 changes: 6 additions & 6 deletions splunklib/searchcommands/external_search_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
class ExternalSearchCommand:
def __init__(self, path, argv=None, environ=None):
if not isinstance(path, (bytes, str)):
raise ValueError(f"Expected a string value for path, not {repr(path)}")
raise ValueError(f"Expected a string value for path, not {path!r}")

self._logger = getLogger(self.__class__.__name__)
self._path = str(path)
Expand All @@ -45,22 +45,22 @@ def __init__(self, path, argv=None, environ=None):

@property
def argv(self):
return getattr(self, "_argv")
return self._argv

@argv.setter
def argv(self, value):
if not (value is None or isinstance(value, (list, tuple))):
raise ValueError(f"Expected a list, tuple or value of None for argv, not {repr(value)}")
raise ValueError(f"Expected a list, tuple or value of None for argv, not {value!r}")
self._argv = value

@property
def environ(self):
return getattr(self, "_environ")
return self._environ

@environ.setter
def environ(self, value):
if not (value is None or isinstance(value, dict)):
raise ValueError(f"Expected a dictionary value for environ, not {repr(value)}")
raise ValueError(f"Expected a dictionary value for environ, not {value!r}")
self._environ = value

@property
Expand All @@ -83,7 +83,7 @@ def execute(self):
self._execute(self._path, self._argv, self._environ)
except:
error_type, error, tb = sys.exc_info()
message = f"Command execution failed: {str(error)}"
message = f"Command execution failed: {error!s}"
self._logger.error(message + "\nTraceback:\n" + "".join(traceback.format_tb(tb)))
sys.exit(1)

Expand Down
10 changes: 5 additions & 5 deletions splunklib/searchcommands/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,11 @@ class ConfigurationSettingsType(type):
"""

def __new__(mcs, module, name, bases):
mcs = super(ConfigurationSettingsType, mcs).__new__(mcs, str(name), bases, {})
mcs = super().__new__(mcs, str(name), bases, {})
return mcs

def __init__(cls, module, name, bases):
super(ConfigurationSettingsType, cls).__init__(name, bases, None)
super().__init__(name, bases, None)
cls.__module__ = module

@staticmethod
Expand All @@ -265,9 +265,9 @@ def validate_configuration_setting(specification, name, value):
type_names = specification.type.__name__
else:
type_names = ", ".join(map(lambda t: t.__name__, specification.type))
raise ValueError(f"Expected {type_names} value, not {name}={repr(value)}")
raise ValueError(f"Expected {type_names} value, not {name}={value!r}")
if specification.constraint and not specification.constraint(value):
raise ValueError(f"Illegal value: {name}={repr(value)}")
raise ValueError(f"Illegal value: {name}={value!r}")
return value

specification = namedtuple(
Expand Down Expand Up @@ -549,7 +549,7 @@ def _write_record(self, record):
if fieldnames is None:
self._fieldnames = fieldnames = list(record.keys())
self._fieldnames.extend([i for i in self.custom_fields if i not in self._fieldnames])
value_list = map(lambda fn: (str(fn), str("__mv_") + str(fn)), fieldnames)
value_list = map(lambda fn: (str(fn), "__mv_" + str(fn)), fieldnames)
self._writerow(list(chain.from_iterable(value_list)))

get_value = record.get
Expand Down
2 changes: 1 addition & 1 deletion splunklib/searchcommands/reporting_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def _has_custom_method(self, method_name):
def prepare(self):
if self.phase == "map":
if self._has_custom_method("map"):
phase_method = getattr(self.__class__, "map")
phase_method = self.__class__.map
self._configuration = phase_method.ConfigurationSettings(self)
else:
self._configuration = self.ConfigurationSettings(self)
Expand Down
11 changes: 5 additions & 6 deletions splunklib/searchcommands/search_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# Absolute imports

import csv
import io
import os
import re
import sys
Expand Down Expand Up @@ -279,11 +278,11 @@ def search_results_info(self):
path = os.path.join(dispatch_dir, "info.csv")

try:
with io.open(path, "r") as f:
with open(path) as f:
reader = csv.reader(f, dialect=CsvDialect)
fields = next(reader)
values = next(reader)
except IOError as error:
except OSError as error:
if error.errno == 2:
self.logger.error(
f"Search results info file {json_encode_string(path)} does not exist."
Expand Down Expand Up @@ -606,10 +605,10 @@ def _prepare_recording(self, argv, ifile, ofile):
# Save a splunk command line because it is useful for developing tests

with open(recording + ".splunk_cmd", "wb") as f:
f.write("splunk cmd python ".encode())
f.write(b"splunk cmd python ")
f.write(os.path.basename(argv[0]).encode())
for arg in islice(argv, 1, len(argv)):
f.write(" ".encode())
f.write(b" ")
f.write(arg.encode())

return ifile, ofile
Expand Down Expand Up @@ -1048,7 +1047,7 @@ def _report_unexpected_error(self):

filename = origin.tb_frame.f_code.co_filename
lineno = origin.tb_lineno
message = f'{error_type.__name__} at "{filename}", line {str(lineno)} : {error}'
message = f'{error_type.__name__} at "{filename}", line {lineno!s} : {error}'

environment.splunklib_logger.error(
message + "\nTraceback:\n" + "".join(traceback.format_tb(tb))
Expand Down
Loading
Loading