Skip to content
Open
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
19 changes: 19 additions & 0 deletions go_server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func main() {
Utils.CreateHandleFunc("get_server_health", handleGetServerHealth)
Utils.CreateHandleFunc("removeId/", handleRemoveId)
Utils.CreateHandleFunc("clearAll", handleClearAll)
Utils.CreateHandleFunc("update_python_env", handleUpdatePythonEnv)

// We check if the conda environment was passed as an argument
condaEnv := os.Getenv("MED_ENV")
Expand Down Expand Up @@ -97,6 +98,24 @@ func convScript2JsonStr(script Utils.ScriptInfo) (string, error) {
return jsonData, nil
}

// handleUpdatePythonEnv updates the python environment (MED_ENV) used by StartPythonScripts.
func handleUpdatePythonEnv(jsonConfig string, id string) (string, error) {
config, err := Utils.JsonStr2map(jsonConfig)
if err != nil {
return "", err
}
pythonPath, ok := config["pythonPath"].(string)
if !ok || pythonPath == "" {
return "", fmt.Errorf("no pythonPath provided")
}
if _, err := os.Stat(pythonPath); err != nil {
return "", fmt.Errorf("python executable not found at: %s", pythonPath)
}
os.Setenv("MED_ENV", pythonPath)
log.Println("Python environment updated to: " + pythonPath)
return "Python environment set to " + pythonPath, nil
}

// handleRemoveId handles the request to remove the id from the scripts
func handleRemoveId(jsonConfig string, id string) (string, error) {
ok := Utils.KillScript(id)
Expand Down
16 changes: 15 additions & 1 deletion main/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,23 @@ if (isProd) {
console.log("process.resourcesPath: ", process.resourcesPath)
console.log(MEDconfig.runServerAutomatically ? "Server will start automatically here (in background of the application)" : "Server must be started manually")
let bundledPythonPath = getBundledPythonEnvironment()
// The user-defined python path (condaPath in settings.json) takes precedence over the bundled python
let resolvedPythonPath = bundledPythonPath
try {
const settingsFilePath = path.join(app.getPath("userData"), "settings.json")
if (fs.existsSync(settingsFilePath)) {
const savedSettings = JSON.parse(fs.readFileSync(settingsFilePath, "utf8"))
if (savedSettings.condaPath) {
resolvedPythonPath = savedSettings.condaPath
}
}
} catch (error) {
console.warn("Could not read settings.json to resolve the python path: ", error)
}
console.log("Python path passed to the server: ", resolvedPythonPath)
if (MEDconfig.runServerAutomatically) {
// Start the Go server – Python path is optional (passed if available)
runServer(isProd, serverPort, serverProcess, serverState, bundledPythonPath)
runServer(isProd, serverPort, serverProcess, serverState, resolvedPythonPath)
.then((process) => {
serverProcess = process
console.log("Server process started: ", serverProcess)
Expand Down
62 changes: 50 additions & 12 deletions renderer/components/mainPages/settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Column } from "primereact/column"
import { WorkspaceContext } from "../workspace/workspaceContext"
import FirstSetupModal from "../generalPurpose/installation/firstSetupModal"
import { requestBackend } from "../../utilities/requests"
import { cond } from "lodash"
const util = require("util")
const exec = util.promisify(require("child_process").exec)

Expand Down Expand Up @@ -74,16 +75,27 @@ const SettingsPage = ({pageId = "settings", checkJupyterIsRunning, startJupyterS
checkServer()
checkMongoIsRunning()
getJupyterStatus()
let condaCustomPath = null
ipcRenderer.invoke("get-settings").then((receivedSettings) => {
console.log("received settings", receivedSettings)
setSettings(receivedSettings)
if (receivedSettings?.condaPath) {
if (receivedSettings?.condaPath && receivedSettings?.condaPath !== condaPath) {
condaCustomPath = receivedSettings?.condaPath
setCondaPath(receivedSettings?.condaPath)
}
if (receivedSettings?.seed) {
setSeed(receivedSettings?.seed)
}
})
ipcRenderer.invoke("getBundledPythonEnvironment").then((res) => {
console.log("Python embedded: ", res)
if (res !== null && !condaCustomPath) {
ipcRenderer.invoke("getInstalledPythonPackages", res).then((pythonPackages) => {
console.log("Installed Python Packages: ", pythonPackages)
setPythonEmbedded({ pythonEmbedded: res, pythonPackages: pythonPackages })
})
}
})
}, [])

/**
Expand Down Expand Up @@ -111,6 +123,31 @@ const SettingsPage = ({pageId = "settings", checkJupyterIsRunning, startJupyterS
}, 1000)
}

/**
* Notify the running Go server that the python environment changed (updates its MED_ENV),
* so that python scripts launched after this call use the new interpreter
* @param {String} newPath - Path to the python executable
* @returns {void}
*/
const updatePythonEnvOnServer = (newPath) => {
if (!newPath) return
requestBackend(
port,
"update_python_env",
{ pythonPath: newPath, pageId: pageId },
(data) => {
if (data?.error) {
console.warn("Python environment update rejected by the server: ", data.error)
} else {
console.log("Python environment update response: ", data)
}
},
(error) => {
console.error("Failed to update the python environment on the server: ", error)
}
)
}

/**
* Check if the server is running every 5 seconds
*/
Expand All @@ -126,27 +163,22 @@ const SettingsPage = ({pageId = "settings", checkJupyterIsRunning, startJupyterS
ipcRenderer.invoke("getBundledPythonEnvironment").then((res) => {
console.log("Python embedded: ", res)

if (res !== null) {
if (res !== null && res !== pythonEmbedded && !condaPath) {
ipcRenderer.invoke("getInstalledPythonPackages", res).then((pythonPackages) => {
console.log("Installed Python Packages: ", pythonPackages)
setPythonEmbedded({ pythonEmbedded: res, pythonPackages: pythonPackages })
})
}
}
else if (condaPath && condaPath !== pythonEmbedded?.pythonEmbedded) {
setPythonEmbedded({...pythonEmbedded, pythonEmbedded:condaPath} )
}
})
}, 5000)
return () => clearInterval(interval)
})

useEffect(() => {
ipcRenderer.invoke("getBundledPythonEnvironment").then((res) => {
console.log("Python embedded: ", res)
if (res !== null) {
ipcRenderer.invoke("getInstalledPythonPackages", res).then((pythonPackages) => {
console.log("Installed Python Packages: ", pythonPackages)
setPythonEmbedded({ pythonEmbedded: res, pythonPackages: pythonPackages })
})
}
})

}, [])

const getJupyterStatus = async () => {
Expand Down Expand Up @@ -317,14 +349,20 @@ const SettingsPage = ({pageId = "settings", checkJupyterIsRunning, startJupyterS
onChange={(e) => {
setCondaPath(e.target.value)
saveSettings({ ...settings, condaPath: e.target.value })
clearTimeout(window.updatePythonEnvTimeout)
window.updatePythonEnvTimeout = setTimeout(() => {
updatePythonEnvOnServer(e.target.value)
}, 1000)
}}
/>
<a
onClick={() => {
ipcRenderer.invoke("open-dialog-exe").then((path) => {
console.log("path", path)
setCondaPath(path)
setPythonEmbedded({...pythonEmbedded, pythonEmbedded:path} )
saveSettings({ ...settings, condaPath: path })
updatePythonEnvOnServer(path)
})
}}
>
Expand Down