Skip to content
Merged
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
41 changes: 33 additions & 8 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v3
- uses: actions/checkout@v6
- 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
Expand All @@ -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: 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'
1 change: 1 addition & 0 deletions embasp_server_executor/ese_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
45 changes: 32 additions & 13 deletions embasp_server_executor/ese_websocket.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
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):
"""
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
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
self.io_loop = IOLoop.current()
print("\n\n", datetime.now(), "\nWebSocket opened")

def on_close(self):
Expand All @@ -35,17 +41,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)
Loading