From a37e06a845f225755271b1a6e2dcf77c601c04fe Mon Sep 17 00:00:00 2001 From: Pranav Gaikwad Date: Wed, 4 Sep 2024 10:58:55 -0400 Subject: [PATCH] :bug: fix things for Windows Signed-off-by: Pranav Gaikwad --- playpen/README.md | 7 +++++++ playpen/build.spec | 2 +- playpen/client/rpc.py | 25 +++++++++++++++---------- playpen/rpc-client.py | 3 +++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/playpen/README.md b/playpen/README.md index 9275695a..dffbe956 100644 --- a/playpen/README.md +++ b/playpen/README.md @@ -12,6 +12,7 @@ The goals of this effort are: As of writing this, here's the progress we made on the goals above: - We have a JSON-RPC interface in front of the Client CLI. The JSON-RPC interface can be found in [./client/rpc.py](./client/rpc.py). It exposes `get_incident_solutions_for_file` function that generates a fix for one file. There are two example clients (Python and Javascript) we have written that talk with the interface over I/O streams. + - We have a `build.spec` file that builds the JSON-RPC client into a binary using PyInstaller. ### Building JSON-RPC interface into a binary @@ -36,6 +37,12 @@ pyinstaller build.spec Once successful, a binary will be generated at `./dist/cli`. +#### Building for different platforms + +We are using PyInstaller to create binaries. To create a binary for a certain platform / arch, we are building on the same platform + arch. As per our understanding, it is possible to potentially cross-compile for different architectures but not the platform itself. + +So far, we have successfully built and tested binaries for MacOS and Windows (built on respective machines). + ### Testing JSON-RPC binary Now that we have built our JSON-RPC interface into a binary, we will test it using a Python and a JS client that communicates. Both of these clients use a hardcoded path `./dist/cli` to run the JSON-RPC server. Make sure you have built the binary before moving forward. diff --git a/playpen/build.spec b/playpen/build.spec index 0d256c89..2fb63635 100644 --- a/playpen/build.spec +++ b/playpen/build.spec @@ -18,7 +18,7 @@ script_path = 'client/rpc.py' a = Analysis( [script_path], - pathex=[os.path.dirname(script_path)], + pathex=[os.path.dirname(script_path), '../'], binaries=[], datas=data_dirs, hiddenimports=["_ssl"], diff --git a/playpen/client/rpc.py b/playpen/client/rpc.py index 822da1c4..62a6b53a 100644 --- a/playpen/client/rpc.py +++ b/playpen/client/rpc.py @@ -2,6 +2,7 @@ """This module is intended to facilitate using Konveyor with LLMs.""" + import json import logging import os @@ -49,7 +50,6 @@ def run(self): if method: if rpc_id is not None: - # a call for method if method not in self.method_callbacks: raise ResponseError( ErrorCodes.MethodNotFound, @@ -70,6 +70,10 @@ def run(self): self.handle_result(rpc_id, result, error) except ResponseError as e: self.send_response(rpc_id, None, e) + except Exception as e: + self.send_response( + rpc_id, None, ResponseError(ErrorCodes.InternalError, str(e)) + ) class CustomRpcEndpoint(JsonRpcEndpoint): @@ -81,16 +85,16 @@ def __add_header(self, json_string: str): def send_request(self, message): json_string = json.dumps(message, cls=MyEncoder) jsonrpc_req = self.__add_header(json_string) - log.debug(f"Sending data over stdin {jsonrpc_req}") + log.debug(f"sending data over stdin {repr(jsonrpc_req)}") with self.write_lock: - self.stdin.write(jsonrpc_req) + self.stdin.buffer.write(jsonrpc_req.encode()) self.stdin.flush() def recv_response(self): with self.read_lock: message_size = None while True: - line = self.stdout.readline() + line = self.stdout.buffer.readline().decode("utf-8") if not line: return None if not line.endswith("\r\n") and not line.endswith("\n"): @@ -116,8 +120,8 @@ def recv_response(self): if not message_size: raise ResponseError(ErrorCodes.ParseError, "Bad header: missing size") - jsonrpc_res = self.stdout.read(message_size) - log.debug(f"Read data from stdout {jsonrpc_res}") + jsonrpc_res = self.stdout.buffer.read(message_size).decode("utf-8") + log.debug(f"read data from stdout {repr(jsonrpc_res)}") return json.loads(jsonrpc_res) @@ -206,7 +210,7 @@ def _validate_path(self, path: str, dir: bool = False) -> bool: class KaiClientRPCServer: def get_incident_solutions_for_file(self, **kwargs) -> str: rpc_params = RPCParams(**kwargs) - log.debug(f"got rpc params {rpc_params}") + log.debug(f"got rpc params {rpc_params._data}") config = get_config(rpc_params.config_path) setup_file_handler( @@ -270,7 +274,10 @@ def get_incident_solutions_for_file(self, **kwargs) -> str: return result.updated_file except Exception as e: trace.exception(-1, -1, e, traceback.format_exc()) - log.debug(f"error processing file: {e}") + log.debug(f"failed to generate fix: {e}") + raise ResponseError( + ErrorCodes.InternalError, f"failed to generate fix - {str(e)}" + ) from e finally: end = time.time() trace.end(end) @@ -278,8 +285,6 @@ def get_incident_solutions_for_file(self, **kwargs) -> str: f"END - completed in '{end-start}s: - App: '{rpc_params.app_name}', File: '{rpc_params.input_file_path}' with {len(incidents)} incidents'" ) - raise ResponseError("failed to generate fix") - def run_rpc_server(): # filter warnings so stdout is not polluted diff --git a/playpen/rpc-client.py b/playpen/rpc-client.py index 786a5aea..8546ba92 100644 --- a/playpen/rpc-client.py +++ b/playpen/rpc-client.py @@ -53,6 +53,9 @@ def main(): ) print(response) print("\nReceived response successfully!") + except Exception as e: + print(str(e)) + print("\nFailed to generate fix") finally: rpc_server.stdin.close() rpc_server.stdout.close()