diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index f6ebb948..51d80671 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -14,15 +14,15 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} @@ -37,16 +37,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: '19' + node-version: '20' - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./frontend/node_modules key: node-modules-${{ hashFiles('./frontend/package-lock.json') }} @@ -61,27 +61,27 @@ jobs: needs: [ python, node ] steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Get python packages from cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} id: cache - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: '19' + node-version: '20' - name: Get node from cache id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./frontend/node_modules key: node-modules-${{ hashFiles('./frontend/package-lock.json') }} @@ -102,7 +102,7 @@ jobs: kill -9 $PID - name: Upload frontend to GitHub - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: retention-days: 7 name: frontend-${{ github.sha }} @@ -114,15 +114,15 @@ jobs: needs: python steps: - name: Checking out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Get python packages from cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} @@ -133,7 +133,7 @@ jobs: run: python -m build --sdist --wheel --outdir dist/; - name: Upload backend to GitHub - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: retention-days: 7 name: backend-${{ github.sha }} @@ -145,19 +145,19 @@ jobs: needs: build-backend steps: - name: Checking out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: backend-${{ github.sha }} - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Get python packages from cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} @@ -184,23 +184,23 @@ jobs: needs: [ build-backend, frontend ] steps: - name: Checking out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get backend artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: backend-${{ github.sha }} - name: Get frontend artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: frontend-${{ github.sha }} - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Get python packages from cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index 0069c117..99a39130 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -64,12 +64,12 @@ jobs: uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Cache conda env - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} diff --git a/backend/setup.cfg b/backend/setup.cfg index 5bbae3ce..44610ab7 100644 --- a/backend/setup.cfg +++ b/backend/setup.cfg @@ -29,6 +29,9 @@ install_requires = [options.packages.find] where = src +[options.package_data] +viasp = server/colorPalette.json + [options.entry_points] console_scripts = viasp_server = viasp.__main__:backend diff --git a/backend/src/viasp/server/static/colorPalette.json b/backend/src/viasp/server/colorPalette.json similarity index 100% rename from backend/src/viasp/server/static/colorPalette.json rename to backend/src/viasp/server/colorPalette.json diff --git a/backend/src/viasp/server/startup.py b/backend/src/viasp/server/startup.py index 46cead12..1ae05822 100644 --- a/backend/src/viasp/server/startup.py +++ b/backend/src/viasp/server/startup.py @@ -15,6 +15,7 @@ import shutil from subprocess import Popen from time import time +import json import viasp_dash from dash import Dash, jupyter_dash @@ -22,15 +23,15 @@ from viasp import clingoApiClient from viasp.shared.defaults import (DEFAULT_BACKEND_HOST, DEFAULT_BACKEND_PORT, - DEFAULT_BACKEND_PROTOCOL, CLINGRAPH_PATH, - GRAPH_PATH, PROGRAM_STORAGE_PATH, STDIN_TMP_STORAGE_PATH, - COLOR_PALETTE) + DEFAULT_BACKEND_PROTOCOL, CLINGRAPH_PATH, + GRAPH_PATH, PROGRAM_STORAGE_PATH, + STDIN_TMP_STORAGE_PATH, COLOR_PALETTE_PATH) def run(host=DEFAULT_BACKEND_HOST, port=DEFAULT_BACKEND_PORT): """ create the dash app, set layout and start the backend on host:port """ - + # if running in binder, get proxy information # and set the backend URL, which will be used # by the frontend @@ -40,17 +41,16 @@ def run(host=DEFAULT_BACKEND_HOST, port=DEFAULT_BACKEND_PORT): _default_server_url = _jupyter_config['server_url'] _default_requests_pathname_prefix = ( - _jupyter_config['base_subpath'].rstrip('/') + '/proxy/' + str(port) - ) + _jupyter_config['base_subpath'].rstrip('/') + '/proxy/' + + str(port)) - backend_url = _default_server_url+_default_requests_pathname_prefix + backend_url = _default_server_url + _default_requests_pathname_prefix elif 'google.colab' in sys.modules: - from google.colab.output import eval_js # type: ignore - backend_url=eval_js(f"google.colab.kernel.proxyPort({port})") + from google.colab.output import eval_js # type: ignore + backend_url = eval_js(f"google.colab.kernel.proxyPort({port})") else: backend_url = f"{DEFAULT_BACKEND_PROTOCOL}://{host}:{port}" - command = ["viasp_server", "--host", host, "--port", str(port)] # if 'ipykernel_launcher.py' in sys.argv[0]: @@ -60,12 +60,12 @@ def run(host=DEFAULT_BACKEND_HOST, port=DEFAULT_BACKEND_PORT): log = open('viasp.log', 'w', encoding="utf-8") viasp_backend = Popen(command, stdout=log, stderr=log) + color_palette = json.load( + open(COLOR_PALETTE_PATH, "r")) app = Dash(__name__) - app.layout = viasp_dash.ViaspDash( - id="myID", - backendURL=backend_url, - colorPalette=COLOR_PALETTE - ) + app.layout = viasp_dash.ViaspDash(id="myID", + backendURL=backend_url, + colorPalette=color_palette) app.title = "viASP" # make sure the backend is up, before continuing with other modules diff --git a/backend/src/viasp/shared/defaults.py b/backend/src/viasp/shared/defaults.py index 65bfe650..ae8cf87d 100644 --- a/backend/src/viasp/shared/defaults.py +++ b/backend/src/viasp/shared/defaults.py @@ -1,6 +1,5 @@ import pathlib import os -import json DEFAULT_BACKEND_PROTOCOL = "http" DEFAULT_BACKEND_HOST = "localhost" @@ -9,8 +8,9 @@ DEFAULT_BACKEND_URL = f"{DEFAULT_BACKEND_PROTOCOL}://{DEFAULT_BACKEND_HOST}:{DEFAULT_BACKEND_PORT}" SHARED_PATH = pathlib.Path(__file__).parent.resolve() GRAPH_PATH = SHARED_PATH / "viasp_graph_storage.db" -STATIC_PATH = pathlib.Path(__file__).parent.parent.resolve() / "server/static/" +SERVER_PATH = pathlib.Path(__file__).parent.parent.resolve() / "server/" +STATIC_PATH = os.path.join(SERVER_PATH, "static") CLINGRAPH_PATH = os.path.join(STATIC_PATH, "clingraph") PROGRAM_STORAGE_PATH = SHARED_PATH / "prg.lp" STDIN_TMP_STORAGE_PATH = SHARED_PATH / "viasp_stdin_tmp.lp" -COLOR_PALETTE = json.load(open(os.path.join(STATIC_PATH, "colorPalette.json"), "r")) \ No newline at end of file +COLOR_PALETTE_PATH = SERVER_PATH / "colorPalette.json" diff --git a/backend/test/conftest.py b/backend/test/conftest.py index 9d25ddfb..9236eb86 100644 --- a/backend/test/conftest.py +++ b/backend/test/conftest.py @@ -146,23 +146,40 @@ def client_with_a_single_node_graph(get_sort_program_and_get_all_graphs, a_1) -> @pytest.fixture(params=["program_simple", "program_multiple_sorts", "program_recursive"]) -def client_with_a_graph(request, get_sort_program_and_get_all_graphs) -> Generator[Tuple[FlaskClient, ProgramAnalyzer, List[Tuple[Mapping, str, str, int]], str], Any, Any]: +def client_with_a_graph( + request, get_sort_program_and_get_all_graphs +) -> Generator[Tuple[FlaskClient, ProgramAnalyzer, List[Tuple[ + Mapping, str, str, int]], str], Any, Any]: app = create_app_with_registered_blueprints(app_bp, api_bp, dag_bp) program = request.getfixturevalue(request.param) - serializable_graphs, analyzer = get_sort_program_and_get_all_graphs(program) + serializable_graphs, analyzer = get_sort_program_and_get_all_graphs( + program) with app.test_client() as client: for serializable_graph, hash, sorted_program, _ in serializable_graphs: - client.post("graph", json={"data": serializable_graph, "hash": hash, "sort": sorted_program}) + client.post("graph", + json={ + "data": serializable_graph, + "hash": hash, + "sort": sorted_program + }) yield client, analyzer, serializable_graphs, program + _ = client.delete("/control/clingraph") + _ = client.post("/control/models/clear") + _ = client.delete("/graph/clear") @pytest.fixture -def client_with_a_clingraph(client_with_a_graph, get_clingo_stable_models) -> Generator[Tuple[FlaskClient, ProgramAnalyzer, List[Tuple[Mapping, str, str, int]], str], Any, Any]: +def client_with_a_clingraph( + client_with_a_graph, get_clingo_stable_models +) -> Generator[Tuple[FlaskClient, ProgramAnalyzer, List[Tuple[ + Mapping, str, str, int]], str], Any, Any]: client, analyzer, serializable_graphs, program = client_with_a_graph - _ = client.delete("/control/clingraph") serialized = get_clingo_stable_models(program) - _ = client.post("/control/models", json=serialized, headers={'Content-Type': 'application/json'}) + print(f"Marking models: {serialized}", flush=True) + _ = client.post("/control/models", + json=serialized, + headers={'Content-Type': 'application/json'}) yield client, analyzer, serializable_graphs, program diff --git a/backend/test/test_clingraph.py b/backend/test/test_clingraph.py index 2307af4d..77259d80 100644 --- a/backend/test/test_clingraph.py +++ b/backend/test/test_clingraph.py @@ -98,13 +98,15 @@ def test_clingraph_edges(client_with_a_clingraph): assert res.status_code == 200 assert res.data == b'ok' + res = client.post(f"/graph/edges", + json={ + "shownRecursion": [], + "usingClingraph": "true" + }) + assert res.status_code == 200 + assert type(res.json) == list if "{b(X)}" in program: - res = client.post(f"/graph/edges", - json={ - "shownRecursion": [], - "usingClingraph": "true" - }) - assert res.status_code == 200 - assert type(res.json) == list # program_simple and program_multiple_sorts assert len(res.json) == 12 + else: + assert len(res.json) == 2 diff --git a/docs/viasp/colorPalette.rst b/docs/viasp/colorPalette.rst index 059559ae..39aa8289 100644 --- a/docs/viasp/colorPalette.rst +++ b/docs/viasp/colorPalette.rst @@ -2,7 +2,7 @@ Color Palette ================= -The color Palette of viASP's frontend is defined by the file `/server/static/colorPalette.json`. +The color Palette of viASP's frontend is defined by the file `/server/colorPalette.json`. The default file contains the following JSON object: diff --git a/examples/quickstart.py b/examples/quickstart.py index 32a0ac8a..11d5ddd3 100644 --- a/examples/quickstart.py +++ b/examples/quickstart.py @@ -19,6 +19,10 @@ def main(): ctl.viasp.mark(m) print(handle.get()) ctl.viasp.show() + ctl.viasp.clingraph(viz_encoding="viz_hamiltonian.lp", + engine="dot", + graphviz_type="graph") + app = startup.run() diff --git a/frontend/src/demo/App.js b/frontend/src/demo/App.js index 53c62914..d2732c11 100644 --- a/frontend/src/demo/App.js +++ b/frontend/src/demo/App.js @@ -1,6 +1,6 @@ /* eslint no-magic-numbers: 0 */ import React from 'react'; -import colorPaletteData from '../../../backend/src/viasp/server/static/colorPalette.json'; +import colorPaletteData from '../../../backend/src/viasp/server/colorPalette.json'; import { ViaspDash } from '../lib';