From eaca3bdd563cfea6dd9a3a2f425074a306c4309b Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Thu, 16 Jul 2026 23:12:42 +0200 Subject: [PATCH 1/7] Update dependencies and add missing plaform specific readline implementations Signed-off-by: Sebastian Schildt --- kuksa-client/requirements.txt | 24 +++++----- kuksa-client/setup.cfg | 2 + kuksa-client/test-requirements.txt | 71 +++++++++++++++--------------- 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/kuksa-client/requirements.txt b/kuksa-client/requirements.txt index 5903ec8..f222ebe 100644 --- a/kuksa-client/requirements.txt +++ b/kuksa-client/requirements.txt @@ -1,32 +1,36 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.14 # by the following command: # # pip-compile setup.cfg # -attrs==24.2.0 +attrs==26.1.0 # via cmd2 cmd2==1.5.0 # via kuksa_client (setup.cfg) colorama==0.4.6 # via cmd2 -grpcio==1.68.0 +gnureadline==8.3.3 ; sys_platform == "darwin" + # via kuksa_client (setup.cfg) +grpcio==1.82.1 # via grpcio-tools grpcio-tools==1.68.0 # via kuksa_client (setup.cfg) -jsonpath-ng==1.7.0 +jsonpath-ng==1.8.0 # via kuksa_client (setup.cfg) -ply==3.11 - # via jsonpath-ng protobuf==5.29.6 - # via grpcio-tools + # via + # grpcio-tools + # kuksa_client (setup.cfg) pygments==2.20.0 # via kuksa_client (setup.cfg) -pyperclip==1.9.0 +pyperclip==1.11.0 # via cmd2 -wcwidth==0.2.13 +typing-extensions==4.16.0 + # via grpcio +wcwidth==0.8.2 # via cmd2 -websockets==14.1 +websockets==16.1 # via kuksa_client (setup.cfg) # The following packages are considered to be unsafe in a requirements file: diff --git a/kuksa-client/setup.cfg b/kuksa-client/setup.cfg index 9374d62..fdb90b2 100644 --- a/kuksa-client/setup.cfg +++ b/kuksa-client/setup.cfg @@ -31,6 +31,8 @@ install_requires = grpcio-tools == 1.68.0 protobuf>=5.29.6, <6.0dev jsonpath-ng >= 1.5.3 + gnureadline >= 8.2; sys_platform == "darwin" + pyreadline; sys_platform == "win32" packages = find: [options.extras_require] diff --git a/kuksa-client/test-requirements.txt b/kuksa-client/test-requirements.txt index c6cb6ad..2f7ea79 100644 --- a/kuksa-client/test-requirements.txt +++ b/kuksa-client/test-requirements.txt @@ -1,78 +1,77 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.14 # by the following command: # # pip-compile --extra=test --output-file=test-requirements.txt setup.cfg # -astroid==3.3.5 +astroid==4.0.4 # via pylint -attrs==24.2.0 +attrs==26.1.0 # via cmd2 cmd2==1.5.0 # via kuksa_client (setup.cfg) colorama==0.4.6 # via cmd2 -coverage[toml]==7.6.7 +coverage[toml]==7.15.2 # via pytest-cov -dill==0.3.9 +dill==0.4.1 # via pylint -exceptiongroup==1.2.2 - # via pytest -grpcio==1.68.0 +gnureadline==8.3.3 ; sys_platform == "darwin" + # via kuksa_client (setup.cfg) +grpcio==1.82.1 # via grpcio-tools grpcio-tools==1.68.0 # via kuksa_client (setup.cfg) -iniconfig==2.0.0 +iniconfig==2.3.0 # via pytest -isort==5.13.2 +isort==8.0.1 # via pylint -jsonpath-ng==1.7.0 +jsonpath-ng==1.8.0 # via kuksa_client (setup.cfg) mccabe==0.7.0 # via pylint -packaging==24.2 +packaging==26.2 # via pytest -platformdirs==4.3.6 +platformdirs==4.10.0 # via pylint -pluggy==1.5.0 - # via pytest -ply==3.11 - # via jsonpath-ng +pluggy==1.6.0 + # via + # pytest + # pytest-cov protobuf==5.29.6 - # via grpcio-tools + # via + # grpcio-tools + # kuksa_client (setup.cfg) pygments==2.20.0 + # via + # kuksa_client (setup.cfg) + # pytest +pylint==4.0.6 # via kuksa_client (setup.cfg) -pylint==3.3.1 - # via kuksa_client (setup.cfg) -pyperclip==1.9.0 +pyperclip==1.11.0 # via cmd2 -pytest==9.0.3 +pytest==9.1.1 # via # kuksa_client (setup.cfg) # pytest-asyncio # pytest-cov # pytest-mock # pytest-timeout -pytest-asyncio==1.3.0 +pytest-asyncio==1.4.0 # via kuksa_client (setup.cfg) -pytest-cov==6.0.0 +pytest-cov==7.1.0 # via kuksa_client (setup.cfg) -pytest-mock==3.14.0 +pytest-mock==3.15.1 # via kuksa_client (setup.cfg) -pytest-timeout==2.3.1 +pytest-timeout==2.4.0 # via kuksa_client (setup.cfg) -tomli==2.1.0 - # via - # coverage - # pylint - # pytest -tomlkit==0.13.2 +tomlkit==0.15.0 # via pylint -typing-extensions==4.12.2 - # via astroid -wcwidth==0.2.13 +typing-extensions==4.16.0 + # via grpcio +wcwidth==0.8.2 # via cmd2 -websockets==14.1 +websockets==16.1 # via kuksa_client (setup.cfg) # The following packages are considered to be unsafe in a requirements file: From ae866e8e0f681c70cb749cd454e8a8772bfa1b82 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Thu, 16 Jul 2026 23:23:39 +0200 Subject: [PATCH 2/7] Update cmd2 to be compatible with Python 3.14 (dropping 3.10 support) Signed-off-by: Sebastian Schildt --- kuksa-client/kuksa_client/__main__.py | 43 +++++++++++---------------- kuksa-client/setup.cfg | 4 +-- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/kuksa-client/kuksa_client/__main__.py b/kuksa-client/kuksa_client/__main__.py index 69a83e0..0db1d74 100755 --- a/kuksa-client/kuksa_client/__main__.py +++ b/kuksa-client/kuksa_client/__main__.py @@ -33,10 +33,10 @@ from pygments import formatters from cmd2 import Cmd from cmd2 import CompletionItem +from cmd2 import Completions from cmd2 import with_argparser from cmd2 import with_category from cmd2 import constants -from cmd2.utils import basic_complete from urllib.parse import urlparse from kuksa_client import KuksaClientThread @@ -108,31 +108,24 @@ def refresh_metadata(self): def path_completer(self, text, line, begidx, endidx): if not self.connection_established(): - return None + return Completions() if len(self.pathCompletionItems) == 0: self.refresh_metadata() - # Normalize the delimiter used delimiter = "." if "/" in text: delimiter = "/" text = text.replace(delimiter, ".") - # Generate the list of all possible completions self.pathCompletionItems = [] for path in self.metadata.keys(): - # Compare case insensitive if path.lower().startswith(text.lower()): if delimiter != ".": path = path.replace(".", delimiter) - self.pathCompletionItems.append(path) + self.pathCompletionItems.append(CompletionItem(path)) - # Generate the list of completions to display - self.display_matches = display_completions(self.pathCompletionItems, delimiter) - - # Return all completions - return self.pathCompletionItems + return Cmd.basic_complete(text, line, begidx, endidx, self.pathCompletionItems) def subscribeCallback(self, logPath, resp): if logPath is None: @@ -152,7 +145,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): self.pathCompletionItems = [] for sub_id in self.subscribeIds: self.pathCompletionItems.append(CompletionItem(sub_id)) - return basic_complete(text, line, begidx, endidx, self.pathCompletionItems) + return Cmd.basic_complete(text, line, begidx, endidx, self.pathCompletionItems) COMM_SETUP_COMMANDS = "Communication Set-up Commands" VSS_COMMANDS = "Kuksa Interaction Commands (Supported by both KUKSA Databroker and KUKSA Server)" @@ -175,12 +168,12 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_authorize.add_argument( "token_or_tokenfile", help="JWT(or the file storing the token) for authorizing the client.", - completer_method=tokenfile_completer_method, + completer=tokenfile_completer_method, ) ap_setValue = argparse.ArgumentParser() ap_setValue.add_argument( - "Path", help="Path to be set", completer_method=path_completer + "Path", help="Path to be set", completer=path_completer ) ap_setValue.add_argument("Value", nargs="+", help="Value to be set") ap_setValue.add_argument( @@ -200,7 +193,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_getValue = argparse.ArgumentParser() ap_getValue.add_argument( - "Path", help="Path to be read", completer_method=path_completer + "Path", help="Path to be read", completer=path_completer ) ap_getValue.add_argument( "-a", "--attribute", help="Attribute to be get", default="value" @@ -211,7 +204,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): "Path", help="Path whose value is to be read", nargs="+", - completer_method=path_completer, + completer=path_completer, ) ap_getValues.add_argument( "-a", "--attribute", help="Attribute to be get", default="value" @@ -221,7 +214,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_setTargetValue.add_argument( "Path", help="Path whose target value to be set", - completer_method=path_completer, + completer=path_completer, ) ap_setTargetValue.add_argument("Value", help="Value to be set") @@ -237,7 +230,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_getTargetValue.add_argument( "Path", help="Path whose target value is to be read", - completer_method=path_completer, + completer=path_completer, ) ap_getTargetValues = argparse.ArgumentParser() @@ -245,12 +238,12 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): "Path", help="Path whose target value is to be read", nargs="+", - completer_method=path_completer, + completer=path_completer, ) ap_subscribe = argparse.ArgumentParser() ap_subscribe.add_argument( - "Path", help="Path to subscribe to", completer_method=path_completer + "Path", help="Path to subscribe to", completer=path_completer ) ap_subscribe.add_argument( "-a", "--attribute", help="Attribute to subscribe to", default="value" @@ -265,7 +258,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_subscribeMultiple = argparse.ArgumentParser() ap_subscribeMultiple.add_argument( - "Path", help="Path to subscribe to", nargs="+", completer_method=path_completer + "Path", help="Path to subscribe to", nargs="+", completer=path_completer ) ap_subscribeMultiple.add_argument( "-a", "--attribute", help="Attribute to subscribe to", default="value" @@ -281,18 +274,18 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_unsubscribe.add_argument( "SubscribeId", help="Corresponding subscription Id", - completer_method=subscriptionIdCompleter, + completer=subscriptionIdCompleter, ) ap_getMetaData = argparse.ArgumentParser() ap_getMetaData.add_argument( "Path", help="Path whose metadata is to be read", - completer_method=path_completer, + completer=path_completer, ) ap_updateMetaData = argparse.ArgumentParser() ap_updateMetaData.add_argument( - "Path", help="Path whose MetaData is to update", completer_method=path_completer + "Path", help="Path whose MetaData is to update", completer=path_completer ) ap_updateMetaData.add_argument( "Json", @@ -308,7 +301,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ap_updateVSSTree.add_argument( "Json", help="Json tree to update VSS", - completer_method=jsonfile_completer_method, + completer=jsonfile_completer_method, ) # Constructor, request names after protocol to avoid errors diff --git a/kuksa-client/setup.cfg b/kuksa-client/setup.cfg index fdb90b2..4c1e0e9 100644 --- a/kuksa-client/setup.cfg +++ b/kuksa-client/setup.cfg @@ -22,10 +22,10 @@ license_files = LICENSE [options] -python_requires = >=3.8 +python_requires = >=3.11 install_requires = websockets >= 10.1 - cmd2 >= 1.4, <2.0 + cmd2 >= 4.0, <5.0 pygments >= 2.15 # Make sure to use the same version criteria in pyproject.toml and update requirements.txt after changing grpcio-tools == 1.68.0 From e590759657c5066b567155b0b05a380724000324 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Thu, 16 Jul 2026 23:40:04 +0200 Subject: [PATCH 3/7] Accomodate cmd2 API changes Signed-off-by: Sebastian Schildt --- kuksa-client/kuksa_client/__main__.py | 41 ++++++++++++++------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/kuksa-client/kuksa_client/__main__.py b/kuksa-client/kuksa_client/__main__.py index 0db1d74..1754303 100755 --- a/kuksa-client/kuksa_client/__main__.py +++ b/kuksa-client/kuksa_client/__main__.py @@ -32,6 +32,7 @@ from pygments import lexers from pygments import formatters from cmd2 import Cmd +from cmd2 import Cmd2ArgumentParser from cmd2 import CompletionItem from cmd2 import Completions from cmd2 import with_argparser @@ -125,7 +126,7 @@ def path_completer(self, text, line, begidx, endidx): path = path.replace(".", delimiter) self.pathCompletionItems.append(CompletionItem(path)) - return Cmd.basic_complete(text, line, begidx, endidx, self.pathCompletionItems) + return self.basic_complete(text, line, begidx, endidx, self.pathCompletionItems) def subscribeCallback(self, logPath, resp): if logPath is None: @@ -145,22 +146,22 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): self.pathCompletionItems = [] for sub_id in self.subscribeIds: self.pathCompletionItems.append(CompletionItem(sub_id)) - return Cmd.basic_complete(text, line, begidx, endidx, self.pathCompletionItems) + return self.basic_complete(text, line, begidx, endidx, self.pathCompletionItems) COMM_SETUP_COMMANDS = "Communication Set-up Commands" VSS_COMMANDS = "Kuksa Interaction Commands (Supported by both KUKSA Databroker and KUKSA Server)" VSS_COMMANDS_SERVER = "Kuksa Interaction Commands (Only supported by KUKSA Server)" INFO_COMMANDS = "Info Commands" - ap_connect = argparse.ArgumentParser() + ap_connect = Cmd2ArgumentParser() ap_connect.add_argument( "server", help=f"VSS server to connect to. Format: protocol://host[:port]. \ Supported protocols: [grpc, grpcs, ws, wss]. Example: {DEFAULT_KUKSA_ADDRESS}", ) - ap_disconnect = argparse.ArgumentParser() - ap_authorize = argparse.ArgumentParser() + ap_disconnect = Cmd2ArgumentParser() + ap_authorize = Cmd2ArgumentParser() tokenfile_completer_method = functools.partial( Cmd.path_complete, path_filter=lambda path: (os.path.isdir(path) or path.endswith(".token")), @@ -171,7 +172,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): completer=tokenfile_completer_method, ) - ap_setValue = argparse.ArgumentParser() + ap_setValue = Cmd2ArgumentParser() ap_setValue.add_argument( "Path", help="Path to be set", completer=path_completer ) @@ -180,7 +181,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): "-a", "--attribute", help="Attribute to be set", default="value" ) - ap_setValues = argparse.ArgumentParser() + ap_setValues = Cmd2ArgumentParser() ap_setValues.add_argument( "Path=Value", help="Path and new value this path is to be set with", @@ -191,7 +192,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): "-a", "--attribute", help="Attribute to be set", default="value" ) - ap_getValue = argparse.ArgumentParser() + ap_getValue = Cmd2ArgumentParser() ap_getValue.add_argument( "Path", help="Path to be read", completer=path_completer ) @@ -199,7 +200,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): "-a", "--attribute", help="Attribute to be get", default="value" ) - ap_getValues = argparse.ArgumentParser() + ap_getValues = Cmd2ArgumentParser() ap_getValues.add_argument( "Path", help="Path whose value is to be read", @@ -210,7 +211,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): "-a", "--attribute", help="Attribute to be get", default="value" ) - ap_setTargetValue = argparse.ArgumentParser() + ap_setTargetValue = Cmd2ArgumentParser() ap_setTargetValue.add_argument( "Path", help="Path whose target value to be set", @@ -218,7 +219,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): ) ap_setTargetValue.add_argument("Value", help="Value to be set") - ap_setTargetValues = argparse.ArgumentParser() + ap_setTargetValues = Cmd2ArgumentParser() ap_setTargetValues.add_argument( "Path=Value", help="Path and new target value this path is to be set with", @@ -226,14 +227,14 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): type=assignment_statement, ) - ap_getTargetValue = argparse.ArgumentParser() + ap_getTargetValue = Cmd2ArgumentParser() ap_getTargetValue.add_argument( "Path", help="Path whose target value is to be read", completer=path_completer, ) - ap_getTargetValues = argparse.ArgumentParser() + ap_getTargetValues = Cmd2ArgumentParser() ap_getTargetValues.add_argument( "Path", help="Path whose target value is to be read", @@ -241,7 +242,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): completer=path_completer, ) - ap_subscribe = argparse.ArgumentParser() + ap_subscribe = Cmd2ArgumentParser() ap_subscribe.add_argument( "Path", help="Path to subscribe to", completer=path_completer ) @@ -256,7 +257,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): action="store_true", ) - ap_subscribeMultiple = argparse.ArgumentParser() + ap_subscribeMultiple = Cmd2ArgumentParser() ap_subscribeMultiple.add_argument( "Path", help="Path to subscribe to", nargs="+", completer=path_completer ) @@ -270,20 +271,20 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): action="store_true", ) - ap_unsubscribe = argparse.ArgumentParser() + ap_unsubscribe = Cmd2ArgumentParser() ap_unsubscribe.add_argument( "SubscribeId", help="Corresponding subscription Id", completer=subscriptionIdCompleter, ) - ap_getMetaData = argparse.ArgumentParser() + ap_getMetaData = Cmd2ArgumentParser() ap_getMetaData.add_argument( "Path", help="Path whose metadata is to be read", completer=path_completer, ) - ap_updateMetaData = argparse.ArgumentParser() + ap_updateMetaData = Cmd2ArgumentParser() ap_updateMetaData.add_argument( "Path", help="Path whose MetaData is to update", completer=path_completer ) @@ -293,7 +294,7 @@ def subscriptionIdCompleter(self, text, line, begidx, endidx): " `updateVSSTree` instead.", ) - ap_updateVSSTree = argparse.ArgumentParser() + ap_updateVSSTree = Cmd2ArgumentParser() jsonfile_completer_method = functools.partial( Cmd.path_complete, path_filter=lambda path: (os.path.isdir(path) or path.endswith(".json")), @@ -653,7 +654,7 @@ def main(): kuksa_logger = KuksaLogger() kuksa_logger.init_logging() - parser = argparse.ArgumentParser() + parser = Cmd2ArgumentParser() parser.add_argument( "server", nargs="?", From 6d9b0b7120b1019dea77eb9bcc8e5c57dc801623 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Thu, 16 Jul 2026 23:41:16 +0200 Subject: [PATCH 4/7] Update Python version in CI to new minimum 3.11 Signed-off-by: Sebastian Schildt --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7b9e32c..145f92d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,7 +40,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies with pip run: | cd kuksa-client From b457d1bc710593d79812c0a24d3766529c8b07fe Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Thu, 16 Jul 2026 23:53:48 +0200 Subject: [PATCH 5/7] Fix pre-commit Signed-off-by: Sebastian Schildt --- kuksa-client/kuksa_client/__main__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/kuksa-client/kuksa_client/__main__.py b/kuksa-client/kuksa_client/__main__.py index 1754303..fb0bb24 100755 --- a/kuksa-client/kuksa_client/__main__.py +++ b/kuksa-client/kuksa_client/__main__.py @@ -17,7 +17,6 @@ # SPDX-License-Identifier: Apache-2.0 ######################################################################## -import argparse import functools import json import logging.config From 680e4c1f626a1a72b745287553eaa80f1e1b2cc3 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 17 Jul 2026 09:04:28 +0200 Subject: [PATCH 6/7] Updated grpcio and protobuf dependencies Signed-off-by: Sebastian Schildt --- kuksa-client/Dockerfile | 8 ++++---- kuksa-client/pyproject.toml | 3 ++- kuksa-client/requirements.txt | 28 +++++++++++++++++++--------- kuksa-client/setup.cfg | 4 ++-- kuksa-client/test-requirements.txt | 27 ++++++++++++++++++--------- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/kuksa-client/Dockerfile b/kuksa-client/Dockerfile index 5bc1a0b..c36ab57 100644 --- a/kuksa-client/Dockerfile +++ b/kuksa-client/Dockerfile @@ -9,7 +9,7 @@ # Note: This dockerfile needs to be executed one level above in the root folder -FROM python:3.10-slim-bookworm AS build +FROM python:3.14-slim-trixie AS build # binutils is required by pyinstaller to strip any .so libs that are collected # git is used to determine & embed version information during build time RUN apt update && apt -yy install binutils git @@ -30,11 +30,11 @@ RUN rm -rf dist RUN pyinstaller --collect-data kuksa_client --add-data=/kuksa-python-sdk/kuksa-client/kuksa:kuksa --add-data=/kuksa-python-sdk/kuksa-client/sdv:sdv --clean -s /usr/local/bin/kuksa-client -# Debian 12 is bookworm, so the glibc version matches. Distroless is a lot smaller than +# Debian 13 is trixie, so the glibc version matches. Distroless is a lot smaller than # Debian slim versions # For development add :debug like this -# FROM gcr.io/distroless/base-debian12:debug to get a busybox shell as well -FROM gcr.io/distroless/base-debian12 +# FROM gcr.io/distroless/base-debian13:debug to get a busybox shell as well +FROM gcr.io/distroless/base-debian13 COPY --from=build /dist/kuksa-client /kuksa-client diff --git a/kuksa-client/pyproject.toml b/kuksa-client/pyproject.toml index b7a8cdb..7b8d3f0 100644 --- a/kuksa-client/pyproject.toml +++ b/kuksa-client/pyproject.toml @@ -1,7 +1,8 @@ [build-system] requires = [ # Make sure to use the same exact version criteria in setup.cfg and update requirements.txt after changing - "grpcio-tools==1.68.0", + "grpcio-tools==1.82.1", + "protobuf>=7.35.1,<8.0.0", "setuptools>=77", "setuptools-git-versioning", "wheel", diff --git a/kuksa-client/requirements.txt b/kuksa-client/requirements.txt index f222ebe..d591e1e 100644 --- a/kuksa-client/requirements.txt +++ b/kuksa-client/requirements.txt @@ -4,32 +4,42 @@ # # pip-compile setup.cfg # -attrs==26.1.0 - # via cmd2 -cmd2==1.5.0 +cmd2==4.1.2 # via kuksa_client (setup.cfg) -colorama==0.4.6 - # via cmd2 gnureadline==8.3.3 ; sys_platform == "darwin" # via kuksa_client (setup.cfg) grpcio==1.82.1 # via grpcio-tools -grpcio-tools==1.68.0 +grpcio-tools==1.82.1 # via kuksa_client (setup.cfg) jsonpath-ng==1.8.0 # via kuksa_client (setup.cfg) -protobuf==5.29.6 +markdown-it-py==4.2.0 + # via rich +mdurl==0.1.2 + # via markdown-it-py +prompt-toolkit==3.0.52 + # via cmd2 +protobuf==7.35.1 # via # grpcio-tools # kuksa_client (setup.cfg) pygments==2.20.0 - # via kuksa_client (setup.cfg) + # via + # kuksa_client (setup.cfg) + # rich pyperclip==1.11.0 # via cmd2 +rich==15.0.0 + # via + # cmd2 + # rich-argparse +rich-argparse==1.8.0 + # via cmd2 typing-extensions==4.16.0 # via grpcio wcwidth==0.8.2 - # via cmd2 + # via prompt-toolkit websockets==16.1 # via kuksa_client (setup.cfg) diff --git a/kuksa-client/setup.cfg b/kuksa-client/setup.cfg index 4c1e0e9..9f3ef19 100644 --- a/kuksa-client/setup.cfg +++ b/kuksa-client/setup.cfg @@ -28,8 +28,8 @@ install_requires = cmd2 >= 4.0, <5.0 pygments >= 2.15 # Make sure to use the same version criteria in pyproject.toml and update requirements.txt after changing - grpcio-tools == 1.68.0 - protobuf>=5.29.6, <6.0dev + grpcio-tools == 1.82.1 + protobuf>=7.35.1, <8.0.0 jsonpath-ng >= 1.5.3 gnureadline >= 8.2; sys_platform == "darwin" pyreadline; sys_platform == "win32" diff --git a/kuksa-client/test-requirements.txt b/kuksa-client/test-requirements.txt index 2f7ea79..d15ae0f 100644 --- a/kuksa-client/test-requirements.txt +++ b/kuksa-client/test-requirements.txt @@ -6,12 +6,8 @@ # astroid==4.0.4 # via pylint -attrs==26.1.0 - # via cmd2 -cmd2==1.5.0 +cmd2==4.1.2 # via kuksa_client (setup.cfg) -colorama==0.4.6 - # via cmd2 coverage[toml]==7.15.2 # via pytest-cov dill==0.4.1 @@ -20,7 +16,7 @@ gnureadline==8.3.3 ; sys_platform == "darwin" # via kuksa_client (setup.cfg) grpcio==1.82.1 # via grpcio-tools -grpcio-tools==1.68.0 +grpcio-tools==1.82.1 # via kuksa_client (setup.cfg) iniconfig==2.3.0 # via pytest @@ -28,8 +24,12 @@ isort==8.0.1 # via pylint jsonpath-ng==1.8.0 # via kuksa_client (setup.cfg) +markdown-it-py==4.2.0 + # via rich mccabe==0.7.0 # via pylint +mdurl==0.1.2 + # via markdown-it-py packaging==26.2 # via pytest platformdirs==4.10.0 @@ -38,7 +38,9 @@ pluggy==1.6.0 # via # pytest # pytest-cov -protobuf==5.29.6 +prompt-toolkit==3.0.52 + # via cmd2 +protobuf==7.35.1 # via # grpcio-tools # kuksa_client (setup.cfg) @@ -46,6 +48,7 @@ pygments==2.20.0 # via # kuksa_client (setup.cfg) # pytest + # rich pylint==4.0.6 # via kuksa_client (setup.cfg) pyperclip==1.11.0 @@ -65,12 +68,18 @@ pytest-mock==3.15.1 # via kuksa_client (setup.cfg) pytest-timeout==2.4.0 # via kuksa_client (setup.cfg) -tomlkit==0.15.0 +rich==15.0.0 + # via + # cmd2 + # rich-argparse +rich-argparse==1.8.0 + # via cmd2 +tomlkit==0.15.1 # via pylint typing-extensions==4.16.0 # via grpcio wcwidth==0.8.2 - # via cmd2 + # via prompt-toolkit websockets==16.1 # via kuksa_client (setup.cfg) From 07b3174263c14982c7d7391824f6b3316d31dc94 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 17 Jul 2026 09:42:36 +0200 Subject: [PATCH 7/7] Fix v1/v2 switivhing logic for subscribe in CLI client and fix subscription rendering due to changed cmd2 API Signed-off-by: Sebastian Schildt --- kuksa-client/kuksa_client/__main__.py | 13 ++++++------- kuksa-client/kuksa_client/cli_backend/grpc.py | 19 ++++++++++++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/kuksa-client/kuksa_client/__main__.py b/kuksa-client/kuksa_client/__main__.py index fb0bb24..6c2c009 100755 --- a/kuksa-client/kuksa_client/__main__.py +++ b/kuksa-client/kuksa_client/__main__.py @@ -129,14 +129,13 @@ def path_completer(self, text, line, begidx, endidx): def subscribeCallback(self, logPath, resp): if logPath is None: - with self.terminal_lock: - self.async_alert( - highlight( - json.dumps(json.loads(resp), indent=2), - lexers.JsonLexer(), - formatters.TerminalFormatter(), - ) + self.add_alert( + msg=highlight( + json.dumps(json.loads(resp), indent=2), + lexers.JsonLexer(), + formatters.TerminalFormatter(), ) + ) else: with logPath.open("a", encoding="utf-8") as logFile: logFile.write(resp + "\n") diff --git a/kuksa-client/kuksa_client/cli_backend/grpc.py b/kuksa-client/kuksa_client/cli_backend/grpc.py index 85081b4..f0d1586 100644 --- a/kuksa-client/kuksa_client/cli_backend/grpc.py +++ b/kuksa-client/kuksa_client/cli_backend/grpc.py @@ -30,6 +30,8 @@ import os import logging +import grpc + from kuksa_client import cli_backend import kuksa_client.grpc import kuksa_client.grpc.aio @@ -45,7 +47,7 @@ def wrapper(updates: Iterable[EntryUpdate]) -> None: try: callback(json.dumps([update.to_dict() for update in updates], cls=DatabrokerEncoder)) except Exception as e: - logger.error("Callback could not be executed", e) + logger.error("Callback could not be executed: %s", e) return wrapper @@ -196,8 +198,8 @@ def subscribeMultiple(self, paths: Iterable[str], callback, attribute="value", t for path in paths ] requestArgs = { + "paths": list(paths), "entries": entries, - "try_v2": True, "callback": callback_wrapper(callback), } return self._sendReceiveMsg(("subscribe", requestArgs), timeout) @@ -261,9 +263,16 @@ async def _grpcHandler(self, vss_client: kuksa_client.grpc.aio.VSSClient): resp = await vss_client.authorize(str(requestArgs["token"])) elif call == "subscribe": callback = requestArgs.pop('callback') - subscriber_response_stream = vss_client.subscribe( - **requestArgs) - resp = await subscriber_manager.add_subscriber(subscriber_response_stream, callback) + paths = requestArgs.pop('paths') + entries = requestArgs.pop('entries') + try: + subscriber_response_stream = vss_client.v2_subscribe(paths=paths) + resp = await subscriber_manager.add_subscriber(subscriber_response_stream, callback) + except kuksa_client.grpc.VSSClientError as exc: + if exc.error["code"] != grpc.StatusCode.UNIMPLEMENTED.value[0]: + raise + subscriber_response_stream = vss_client.subscribe(entries=entries) + resp = await subscriber_manager.add_subscriber(subscriber_response_stream, callback) resp = {"subscriptionId": str(resp)} elif call == "unsubscribe": resp = await subscriber_manager.remove_subscriber(**requestArgs)