From ae1a46a2ccf917317670b95fcf10b74322703ef4 Mon Sep 17 00:00:00 2001 From: pdelboca Date: Thu, 27 Jun 2024 12:13:50 +0200 Subject: [PATCH 01/21] Prepare server app for pyinstaller (no relative imports) --- server/__main__.py | 6 +++--- server/client.py | 4 ++-- server/config.py | 2 +- server/project.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/server/__main__.py b/server/__main__.py index 46f842621..8f1e99fff 100644 --- a/server/__main__.py +++ b/server/__main__.py @@ -1,8 +1,8 @@ import typer -from . import settings -from .config import Config -from .server import Server +from server import settings +from server.config import Config +from server.server import Server def main( diff --git a/server/client.py b/server/client.py index 49b00fad3..21f58050c 100644 --- a/server/client.py +++ b/server/client.py @@ -1,7 +1,7 @@ from typing import Any, Optional -from . import endpoints -from .project import Project +from server import endpoints +from server.project import Project class Client: diff --git a/server/config.py b/server/config.py index d027757b5..4e751efe8 100644 --- a/server/config.py +++ b/server/config.py @@ -2,7 +2,7 @@ import attrs -from . import settings +from server import settings @attrs.define(kw_only=True, repr=False) diff --git a/server/project.py b/server/project.py index 982e4e996..778b8e39d 100644 --- a/server/project.py +++ b/server/project.py @@ -5,8 +5,8 @@ from frictionless.resources import TextResource -from . import settings -from .stores import Config, Database, Filesystem, Metadata +from server import settings +from server.stores import Config, Database, Filesystem, Metadata class Project: From 3a1af09353a45eab7d04124f8e3bf6d50119bdef Mon Sep 17 00:00:00 2001 From: pdelboca Date: Thu, 27 Jun 2024 12:15:09 +0200 Subject: [PATCH 02/21] Add Pyinstaller dependency --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 3076d84ea..8e4479028 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,8 @@ dependencies = [ "pygithub==1.59.1", # Zenodo "pyzenodo3==1.0.2", + # PyInstaller + "pyinstaller==6.8.0" ] [tool.setuptools] From b453ac6d8463b39f6dc6a8791fa08f54a6469b3e Mon Sep 17 00:00:00 2001 From: pdelboca Date: Thu, 27 Jun 2024 12:31:45 +0200 Subject: [PATCH 03/21] Build server using pyinstaller --- build.py | 50 ++++++++------------------------------------------ 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/build.py b/build.py index a1d9f1640..1db7668c6 100644 --- a/build.py +++ b/build.py @@ -1,9 +1,6 @@ import os import shutil -import sys -import tarfile - -import fsspec +import PyInstaller.__main__ def build_assets(): @@ -17,47 +14,16 @@ def build_assets(): print(f"[assets] Copied '{source}' to '{target}'") -def build_runner(): - cache = ".cache" - target = "build/runner" - - os.makedirs(cache, exist_ok=True) - shutil.rmtree(target, ignore_errors=True) - - datemark = "20230826" - basepath = "https://github.com/indygreg/python-build-standalone/releases/download" - filetype = "x86_64-unknown-linux-gnu-install_only" - if sys.platform == "darwin": - filetype = "x86_64-apple-darwin-install_only" - if sys.platform == "win32": - filetype = "x86_64-pc-windows-msvc-shared-install_only" - filename = f"cpython-3.10.13+{datemark}-{filetype}.tar.gz" - - if not os.path.exists(f"{cache}/{filename}"): - local = fsspec.filesystem("file") - remote = fsspec.filesystem("http") - with local.open(f"{cache}/{filename}", "wb") as file_to: - with remote.open(f"{basepath}/{datemark}/{filename}", "rb") as file_from: - file_to.write(file_from.read()) - - with tarfile.open(f"{cache}/{filename}", "r:gz") as tar: - tar.extractall(cache) - shutil.move(f"{cache}/python", target) - - print(f"[runner] Copied 'runner' to '{target}'") - - def build_server(): - source = "server" - target = "build/server" - - shutil.rmtree(target, ignore_errors=True) - shutil.copytree(source, target) - - print(f"[server] Copied '{source}' to '{target}'") + PyInstaller.__main__.run([ + 'server/__main__.py', + '--onefile', + '--name', 'server', + '--collect-all', 'frictionless', + '--distpath', 'build/server' + ]) if __name__ == "__main__": build_assets() - build_runner() build_server() From 76ba81829543541c682a49ff5642d18e680dcd92 Mon Sep 17 00:00:00 2001 From: pdelboca Date: Thu, 27 Jun 2024 12:32:01 +0200 Subject: [PATCH 04/21] Run server using pyinstaller executable --- desktop/server.ts | 6 +----- desktop/settings.ts | 2 ++ desktop/system.ts | 6 +++--- desktop/window.ts | 9 --------- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/desktop/server.ts b/desktop/server.ts index 9b81eef22..66535f512 100644 --- a/desktop/server.ts +++ b/desktop/server.ts @@ -6,11 +6,7 @@ export async function runServer() { log.info(`[Run FastAPI server on port 4040`) // Start production server - const proc = spawnFile( - settings.PYTHON_TARGET, - ['-m', 'server', settings.APP_TMP, '--port', `4040`], - process.resourcesPath - ) + const proc = spawnFile(settings.SERVER_EXEC, [settings.APP_TMP]) return proc } diff --git a/desktop/settings.ts b/desktop/settings.ts index 235013b80..11d0eeaa3 100644 --- a/desktop/settings.ts +++ b/desktop/settings.ts @@ -18,3 +18,5 @@ export const APP_TMP = join(APP_HOME, 'tmp') export const PYTHON_SOURCE = join(APP_PYTHON, WIN ? 'python.exe' : 'bin/python3') export const PYTHON_TARGET = join(APP_PYTHON_VENV, WIN ? 'Scripts\\python.exe' : 'bin/python3') + +export const SERVER_EXEC = join(DIST_SERVER, WIN ? 'server.exe': 'server') diff --git a/desktop/system.ts b/desktop/system.ts index cbce1dcf6..e8400c652 100644 --- a/desktop/system.ts +++ b/desktop/system.ts @@ -10,10 +10,10 @@ export async function execFile(path: string, args: string[], cwd?: string) { return stdout } -export async function spawnFile(path: string, args: string[], cwd?: string) { - log.info('[spawnFile]', { path, args, cwd }) +export async function spawnFile(path: string, args: string[]) { + log.info('[spawnFile]', { path, args}) - const proc = cp.spawn(path, args, { cwd }) + const proc = cp.spawn(path, args) proc.stdout.on('data', (data) => log.info(data.toString().trim())) proc.stderr.on('data', (data) => log.error(data.toString().trim())) proc.on('close', (code) => { diff --git a/desktop/window.ts b/desktop/window.ts index 5d232d3f9..072b3fa83 100644 --- a/desktop/window.ts +++ b/desktop/window.ts @@ -60,17 +60,8 @@ export async function createWindow() { // mainWindow.webContents.openDevTools() if (!is.dev) { - log.info('Opening loading.html') - splashWindow.loadFile(resolve(__dirname, '..', 'client', 'loading.html')) - splashWindow.center() log.info('## Start server') - await resources.ensurePython() - await python.ensurePythonVirtualEnvironment() - splashWindow?.webContents.send('ensureLogs', "python") - await python.ensurePythonRequirements() - splashWindow?.webContents.send('ensureLogs', "requirements") await server.runServer() - splashWindow?.webContents.send('ensureLogs', "server") } loadingEvents.emit('finished') From 96ee0712041d02842a73ef9d285325d5dc91c076 Mon Sep 17 00:00:00 2001 From: pdelboca Date: Thu, 27 Jun 2024 13:44:48 +0200 Subject: [PATCH 05/21] Restore loading screen --- client/loading.html | 20 +------------------- desktop/window.ts | 3 +++ 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/client/loading.html b/client/loading.html index c0fa139fb..3cffe7f0a 100644 --- a/client/loading.html +++ b/client/loading.html @@ -6,22 +6,6 @@