From 3f0ebb91ecccb279dd6cfbbaeafb497fc6b73c09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Mar 2026 17:13:18 +0000 Subject: [PATCH 1/5] Bump actions/checkout from 4 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index ec27754..4b43ce6 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python 3.10 uses: actions/setup-python@v3 with: From 81968e49c2694aa868547a5be4ea44b359b1128c Mon Sep 17 00:00:00 2001 From: Stefano Germano <2128484+stefanogermano@users.noreply.github.com> Date: Sat, 21 Mar 2026 23:47:49 +0100 Subject: [PATCH 2/5] Improved callback handling and other minor fixes --- embasp_server_executor/ese_websocket.py | 37 +++++++++++++++++-------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/embasp_server_executor/ese_websocket.py b/embasp_server_executor/ese_websocket.py index e874f58..ffde8e5 100644 --- a/embasp_server_executor/ese_websocket.py +++ b/embasp_server_executor/ese_websocket.py @@ -1,13 +1,13 @@ -from asyncio import set_event_loop, new_event_loop +from asyncio import new_event_loop, set_event_loop from datetime import datetime from urllib.parse import urlparse -from tornado.websocket import WebSocketHandler - from embasp.base.callback import Callback +from tornado.ioloop import IOLoop +from tornado.websocket import WebSocketHandler from .ese_config import config as ec -from .ese_utils import process_program_and_options, get_output_data +from .ese_utils import get_output_data, process_program_and_options class ESEWebSocket(WebSocketHandler, Callback): @@ -15,13 +15,15 @@ class ESEWebSocket(WebSocketHandler, Callback): This is the WebSocket handler class. It has been extended to call EmbASP when a message is received. """ - # Uncomment this if you want to test out the script on localhost + io_loop: IOLoop = None + def check_origin(self, origin): parsed_origin = urlparse(origin) - # # parsed_origin.netloc.lower() gives localhost:3333 return parsed_origin.hostname in ec.cors_origins def open(self): + # Capture the *current* IOLoop instance - this is the one running the WebSocket + self.io_loop = IOLoop.current() print("\n\n", datetime.now(), "\nWebSocket opened") def on_close(self): @@ -35,17 +37,30 @@ def callback(self, o): o_output, o_errors = "", "" if o.get_output() is not None: - if len(o.get_output()) > ec.max_chars_output: # Check if the solver output is too long + # Check if the solver output is too long + if len(o.get_output()) > ec.max_chars_output: o_output = (o.get_output()[:ec.max_chars_output] + "\n[...]\nDo you need more? Let us know") else: o_output = o.get_output() if o.get_errors() is not None: - if len(o.get_output()) > ec.max_chars_output: # Check if the solver output is too long + # Check if the solver error is too long + if len(o.get_errors()) > ec.max_chars_output: o_errors = (o.get_errors()[:ec.max_chars_output] + "\n[...]\nDo you need more? Let us know") else: o_errors = o.get_errors() - set_event_loop(new_event_loop()) - self.write_message(get_output_data(model=o_output, error=o_errors)) - print("Sent data", get_output_data(model=o_output, error=o_errors)) + # Use the stored loop + if self.io_loop is None: + print("Callback called before WebSocket opened!", file=sys.stderr) + return + + self.io_loop.add_callback(self._write_result, o_output, o_errors) + + def _write_result(self, model: str, error: str): + try: + data = get_output_data(model=model, error=error) + self.write_message(data) + print("Sent data", data) + except Exception as e: + print(f"Failed to write message: {e}", file=sys.stderr) From 6b5a576cc0bc71cb9d9b3c36606b141960bd3bbe Mon Sep 17 00:00:00 2001 From: Stefano Germano <2128484+stefanogermano@users.noreply.github.com> Date: Sun, 22 Mar 2026 00:00:32 +0100 Subject: [PATCH 3/5] Normalize CORS origin check Improve origin validation in ESEWebSocket.check_origin: parse and normalize hostnames (lowercase, strip trailing dots) when comparing against ec.cors_origins and guard the logic with a try/except that returns False on parse errors to avoid exceptions from malformed origins. Also add a FIXME comment to validate incoming JSON against a schema before processing, as a reminder to add structural validation later. --- embasp_server_executor/ese_utils.py | 1 + embasp_server_executor/ese_websocket.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/embasp_server_executor/ese_utils.py b/embasp_server_executor/ese_utils.py index e6ca32d..9cf99d2 100644 --- a/embasp_server_executor/ese_utils.py +++ b/embasp_server_executor/ese_utils.py @@ -120,6 +120,7 @@ def process_program_and_options(websocket, message: str): input_json = message websocket.write_message(get_output_data(model="Received command")) input_data = loads(input_json) + # FIXME As soon as we have the JSON schema, we should validate the input structure before processing `input_data` print("Message received: %s\n" % input_data) if not check_presence_of_parameters(input_data): diff --git a/embasp_server_executor/ese_websocket.py b/embasp_server_executor/ese_websocket.py index ffde8e5..eac63b0 100644 --- a/embasp_server_executor/ese_websocket.py +++ b/embasp_server_executor/ese_websocket.py @@ -18,8 +18,12 @@ class ESEWebSocket(WebSocketHandler, Callback): io_loop: IOLoop = None def check_origin(self, origin): - parsed_origin = urlparse(origin) - return parsed_origin.hostname in ec.cors_origins + try: + parsed_origin = urlparse(origin) + normalized_hostname = parsed_origin.hostname.lower().strip('.') + return normalized_hostname in (o.lower().strip('.') for o in ec.cors_origins) + except Exception: + return False def open(self): # Capture the *current* IOLoop instance - this is the one running the WebSocket From c1284d319643f8016086b6f7a1732d22f2943d8f Mon Sep 17 00:00:00 2001 From: Stefano Germano <2128484+stefanogermano@users.noreply.github.com> Date: Sun, 22 Mar 2026 14:47:01 +0100 Subject: [PATCH 4/5] CI: use Python 3.11 and add test executables Upgrade GitHub Actions to use Python 3.11, the latest version currently compatible with EmbASP and the one used by the Docker image. Updated actions to latest version. Add steps to install bubblewrap and download required test executables (timeout, clingo, dlv, dlv2, idlv) into executables/, set execute permissions. Re-enable the unittest run so tests can execute in CI. --- .github/workflows/python-app.yml | 45 +++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 4b43ce6..c40130b 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -19,10 +19,10 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Set up Python 3.10 - uses: actions/setup-python@v3 + - name: Set up Python 3.11 + uses: actions/setup-python@v6 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -35,10 +35,35 @@ jobs: # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics -# TODO to run tests we need bwrap, timeout and all executables: -# executables/clingo/clingo, executables/dlv/dlv, executables/dlv2/dlv2, executables/idlv/idlv -# sudo apt-get update -# sudo apt-get -y install bubblewrap -# - name: Test with unittest -# run: | -# python -m unittest discover -s tests -p '*_test.py' + - name: Install bwrap + run: | + sudo apt-get update + sudo apt-get -y install bubblewrap + - name: Download timeout + run: | + mkdir -p executables + wget https://github.com/DeMaCS-UNICAL/PythonESE/releases/download/v0.1.0/timeout -O executables/timeout + chmod +x executables/timeout + - name: Download clingo + run: | + mkdir -p executables/clingo + wget https://github.com/DeMaCS-UNICAL/EmbASP-test-resources/blob/master/asp/executables/clingo/clingo_linux?raw=true -O executables/clingo/clingo + chmod +x executables/clingo/clingo + - name: Download dlv + run: | + mkdir -p executables/dlv + wget https://github.com/DeMaCS-UNICAL/EmbASP-test-resources/blob/master/asp/executables/dlv/dlv.x86-64-linux-elf-static.bin?raw=true -O executables/dlv/dlv + chmod +x executables/dlv/dlv + - name: Download dlv2 + run: | + mkdir -p executables/dlv2 + wget https://github.com/DeMaCS-UNICAL/EmbASP-test-resources/blob/master/asp/executables/dlv2/dlv2.linux.64?raw=true -O executables/dlv2/dlv2 + chmod +x executables/dlv2/dlv2 + - name: Download idlv + run: | + mkdir -p executables/idlv + wget https://github.com/DeMaCS-UNICAL/EmbASP-test-resources/blob/master/datalog/executables/idlv/idlv.linux.64?raw=true -O executables/idlv/idlv + chmod +x executables/idlv/idlv + - name: Test with unittest + run: | + python -m unittest discover -s tests -p '*_test.py' From ee98c0eac522f109974c9082f0f6757ec5bc5141 Mon Sep 17 00:00:00 2001 From: Stefano Germano <2128484+stefanogermano@users.noreply.github.com> Date: Sun, 22 Mar 2026 15:29:00 +0100 Subject: [PATCH 5/5] Disable unittest step in CI workflow Comment out the 'Test with unittest' job step in the CI pipeline due to a bwrap permission error. --- .github/workflows/python-app.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index c40130b..616f22d 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -64,6 +64,6 @@ jobs: mkdir -p executables/idlv wget https://github.com/DeMaCS-UNICAL/EmbASP-test-resources/blob/master/datalog/executables/idlv/idlv.linux.64?raw=true -O executables/idlv/idlv chmod +x executables/idlv/idlv - - name: Test with unittest - run: | - python -m unittest discover -s tests -p '*_test.py' +# - name: Test with unittest +# run: | +# python -m unittest discover -s tests -p '*_test.py'