From f8375c55125c4ace1245d47da81a80f0e3248121 Mon Sep 17 00:00:00 2001 From: "Toni M. Brotons" <10654467+toni-neurosc@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:54:07 +0100 Subject: [PATCH] Add scan JSON and port selection to App --- gui_dev/package.json | 1 + gui_dev/src/main.jsx | 11 +++++++ gui_dev/vite.config.js | 1 - py_neuromodulation/gui/backend/app_manager.py | 33 ++++++++++++++++--- py_neuromodulation/stream/settings.py | 1 - .../utils/pydantic_extensions.py | 3 +- py_neuromodulation/utils/types.py | 2 +- 7 files changed, 43 insertions(+), 9 deletions(-) diff --git a/gui_dev/package.json b/gui_dev/package.json index 0e31e9cc..6c65000b 100644 --- a/gui_dev/package.json +++ b/gui_dev/package.json @@ -37,6 +37,7 @@ "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", "prettier": "^3.3.3", + "react-scan": "^0.0.31", "vite": "^5.4.11" } } diff --git a/gui_dev/src/main.jsx b/gui_dev/src/main.jsx index f4524069..fde760f2 100644 --- a/gui_dev/src/main.jsx +++ b/gui_dev/src/main.jsx @@ -1,7 +1,18 @@ +if (JSON.parse(import.meta.env.VITE_REACT_SCAN) === true) { + import("react-scan").then(({ scan }) => { + scan({ + enabled: true, + log: true, // logs render info to console + }); + }); +} + import { StrictMode } from "react"; import ReactDOM from "react-dom/client"; import { App } from "./App.jsx"; +// Set up react-scan + // Ignore React 19 warning about accessing element.ref const originalConsoleError = console.error; console.error = (message, ...messageArgs) => { diff --git a/gui_dev/vite.config.js b/gui_dev/vite.config.js index f38a5299..1d6fd6b3 100644 --- a/gui_dev/vite.config.js +++ b/gui_dev/vite.config.js @@ -50,7 +50,6 @@ export default defineConfig(() => { }, }, server: { - port: 54321, proxy: { "/api": { target: `http://localhost:${BACKEND_PORT}`, diff --git a/py_neuromodulation/gui/backend/app_manager.py b/py_neuromodulation/gui/backend/app_manager.py index a9829ccd..7f46163f 100644 --- a/py_neuromodulation/gui/backend/app_manager.py +++ b/py_neuromodulation/gui/backend/app_manager.py @@ -18,6 +18,9 @@ # Shared memory configuration ARRAY_SIZE = 1000 # Adjust based on your needs +SERVER_PORT = 50001 +DEV_SERVER_PORT = 54321 + def create_backend() -> "PyNMBackend": from .app_pynm import PyNMState @@ -26,7 +29,12 @@ def create_backend() -> "PyNMBackend": return PyNMBackend(pynm_state=PyNMState()) -def run_vite(shutdown_event: "Event", debug: bool = False) -> None: +def run_vite( + shutdown_event: "Event", + debug: bool = False, + scan: bool = False, + dev_port: int = DEV_SERVER_PORT, +) -> None: """Run Vite in a separate shell""" import subprocess @@ -38,6 +46,8 @@ def run_vite(shutdown_event: "Event", debug: bool = False) -> None: logging.DEBUG if debug else logging.INFO, ) + os.environ["VITE_REACT_SCAN"] = "true" if scan else "false" + def output_reader(shutdown_event: "Event", process: subprocess.Popen): logger.debug("Initialized output stream") color = ansi_color(color="magenta", bright=True, styles=["BOLD"]) @@ -70,7 +80,7 @@ def read_stream(stream, stream_name): subprocess_flags = subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0 process = subprocess.Popen( - "bun run dev", + "bun run dev --port " + str(dev_port), cwd="gui_dev", stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -175,7 +185,13 @@ class AppManager: LAUNCH_FLAG = "PYNM_RUNNING" def __init__( - self, debug: bool = False, dev: bool = True, run_in_webview=False + self, + debug: bool = False, + dev: bool = True, + run_in_webview=False, + scan=False, + server_port=SERVER_PORT, + dev_port=DEV_SERVER_PORT, ) -> None: """_summary_ @@ -190,6 +206,10 @@ def __init__( self.debug = debug self.dev = dev self.run_in_webview = run_in_webview + self.scan = scan + self.server_port = server_port + self.dev_port = dev_port + self._reset() # Prevent launching multiple instances of the app due to multiprocessing # This allows the absence of a main guard in the main script @@ -269,7 +289,12 @@ def launch(self) -> None: self.logger.info("Starting Vite server...") self.tasks["vite"] = mp.Process( target=run_vite, - kwargs={"shutdown_event": self.shutdown_event, "debug": self.debug}, + kwargs={ + "shutdown_event": self.shutdown_event, + "debug": self.debug, + "scan": self.scan, + "dev_port": self.dev_port, + }, name="Vite", ) diff --git a/py_neuromodulation/stream/settings.py b/py_neuromodulation/stream/settings.py index 764ee547..79f9985b 100644 --- a/py_neuromodulation/stream/settings.py +++ b/py_neuromodulation/stream/settings.py @@ -6,7 +6,6 @@ from pydantic.functional_validators import ModelWrapValidatorHandler from py_neuromodulation import logger, user_features -from types import SimpleNamespace from py_neuromodulation.utils.types import ( BoolSelector, diff --git a/py_neuromodulation/utils/pydantic_extensions.py b/py_neuromodulation/utils/pydantic_extensions.py index ee89ccea..461291fd 100644 --- a/py_neuromodulation/utils/pydantic_extensions.py +++ b/py_neuromodulation/utils/pydantic_extensions.py @@ -11,7 +11,7 @@ Sequence, ) from typing_extensions import Unpack, TypedDict -from pydantic import BaseModel, ConfigDict, model_validator, model_serializer +from pydantic import BaseModel, model_validator, model_serializer from pydantic_core import ( ErrorDetails, @@ -414,7 +414,6 @@ def rewrite_error_locations(self, handler): loc = loc[:root_idx] + loc[root_idx + 1 :] err["loc"] = tuple(loc) errors.append(err) - print(errors) raise ValidationError.from_exception_data( title="ValidationError", line_errors=errors ) diff --git a/py_neuromodulation/utils/types.py b/py_neuromodulation/utils/types.py index 13b2923e..59ed7201 100644 --- a/py_neuromodulation/utils/types.py +++ b/py_neuromodulation/utils/types.py @@ -1,6 +1,6 @@ from os import PathLike from math import isnan -from typing import Literal, TYPE_CHECKING, Any, TypeVar +from typing import Literal, TYPE_CHECKING, Any from pydantic import BaseModel, ConfigDict, model_validator from .pydantic_extensions import NMBaseModel, NMSequenceModel, NMField from abc import abstractmethod