Skip to content

Commit 47da5c1

Browse files
Merge pull request #2 from julianneswinoga/bugfix/js/fix-windows-platformio
Bugfix/js/fix windows platformio
2 parents f430418 + 5668fad commit 47da5c1

12 files changed

Lines changed: 194 additions & 199 deletions

.github/workflows/build-and-release.yaml

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defaults:
55
shell: bash
66

77
jobs:
8-
build-pyinstaller:
8+
build-windows:
99
runs-on: 'windows-2022'
1010

1111
steps:
@@ -22,22 +22,51 @@ jobs:
2222
with:
2323
venv-bin-dir: Scripts # idk why windows does this different
2424

25-
- name: Upgrade pip
26-
run: pip install --upgrade pip
25+
26+
- run: mkdir dist/
27+
- name: Download python embedded
28+
run: curl -L "https://www.python.org/ftp/python/3.10.7/python-3.10.7-embed-amd64.zip" -o python-embedded.zip
29+
- name: Unzip python embedded
30+
run: unzip python-embedded.zip -d dist/.python_local
31+
- name: Modify python embedded to allow pip to run # See https://stackoverflow.com/questions/42666121/pip-with-embedded-python
32+
run: rm dist/.python_local/python310._pth
33+
- name: Download get-pip.py
34+
run: curl -L "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
35+
working-directory: dist/.python_local
36+
- name: Run get-pip.py
37+
run: ./python.exe ./get-pip.py
38+
working-directory: dist/.python_local
2739
- name: Install requirements
28-
run: pip install --requirement requirements-dev.txt
29-
- name: Run PyInstaller
30-
run: pyinstaller OATFWGUI.spec
31-
- name: Move out of OATFWGUI folder
32-
run: mv ./dist/OATFWGUI/* ./dist && rmdir ./dist/OATFWGUI
40+
run: dist/.python_local/python.exe -m pip install --requirement requirements.txt
41+
- name: Copy sourcecode into dist
42+
run: cp -rv OATFWGUI/ dist/
43+
- name: Copy bootstrap script into dist
44+
run: cp -v scripts/OATFWGUI_Windows.bat dist/
45+
- name: Prune unused windows files
46+
run: |
47+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/lupdate.exe
48+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/Qt*Designer*
49+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/Qt*Quick*
50+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/Qt*Qml*
51+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/Qt*Sql*
52+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/Qt*Xml*
53+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/Qt*DBus*
54+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/linguist.exe
55+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/designer.exe
56+
rm -v ./dist/.python_local/Lib/site-packages/PySide6/qmllint.exe
57+
rm -rv ./dist/.python_local/Lib/site-packages/PySide6/translations
58+
rm -rv ./dist/.python_local/Lib/site-packages/PySide6/examples
59+
rm -rv ./dist/.python_local/Lib/site-packages/PySide6/qml
3360
3461
- name: Smoke test
35-
run: ./dist/OATFWGUI.exe --no-gui
62+
run: ./dist/OATFWGUI_Windows.bat --no-gui
3663

3764
- name: Retrieve version
3865
id: version
39-
run: echo "::set-output name=VERSION::$(./dist/OATFWGUI.exe --version)"
66+
run: echo "::set-output name=VERSION::$(./dist/OATFWGUI_Windows.bat --version | tail -1)"
4067

68+
- name: Remove local .platformio
69+
run: rm -r ./dist/.platformio
4170
# Work around stupid issue that GHA can't store file permissions on artifacts
4271
- name: Store which files are executable
4372
run: pushd dist/ && find . -type f -executable -print > restore_executable_permissions.txt && popd
@@ -90,7 +119,7 @@ jobs:
90119
publish-release:
91120
# only publish release on tags
92121
if: ${{ startsWith(github.ref, 'refs/tags/') == true }}
93-
needs: [build-pyinstaller, build-virtualenv]
122+
needs: [build-windows, build-virtualenv]
94123
runs-on: 'ubuntu-20.04'
95124

96125
steps:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*.zip
22
*venv*/
33
.idea/
4+
.platformio/
45
*.log
56
build_*/
67
dist*/

OATFWGUI.spec

Lines changed: 0 additions & 66 deletions
This file was deleted.

OATFWGUI/external_processes.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import sys
2+
import logging
3+
from typing import List, Dict, Optional
4+
from pathlib import Path
5+
6+
from PySide6.QtCore import Slot, QProcess, QStandardPaths
7+
8+
log = logging.getLogger('')
9+
10+
11+
class ExternalProcess:
12+
def __init__(self, proc_name, base_args):
13+
self.proc_name = proc_name
14+
self.base_args = base_args
15+
16+
self.stdout_text = ''
17+
self.stderr_text = ''
18+
self.state = QProcess.NotRunning
19+
20+
self.qproc: Optional[QProcess] = None
21+
22+
def start(self, extra_args: List[str], finish_signal: Optional):
23+
self.qproc = QProcess()
24+
self.qproc.setProgram(self.proc_name)
25+
self.qproc.setArguments(self.base_args)
26+
27+
# signals
28+
self.qproc.readyReadStandardOutput.connect(self.handle_stdout)
29+
self.qproc.readyReadStandardError.connect(self.handle_stderr)
30+
self.qproc.stateChanged.connect(self.handle_state)
31+
32+
all_args = self.base_args + extra_args
33+
self.qproc.setArguments(all_args)
34+
self.qproc.finished.connect(finish_signal)
35+
log.info(f'Starting {self.proc_name} with args: {all_args}')
36+
self.qproc.start()
37+
# Not sure why, but the process doesn't start without these
38+
proc_started = self.qproc.waitForStarted(10 * 1000)
39+
if not proc_started:
40+
log.warning(f'{self.proc_name}:did not start')
41+
# Basically infinite timeout to wait for the process to finish
42+
proc_finished = self.qproc.waitForFinished(999 * 60 * 1000)
43+
if not proc_finished:
44+
log.warning(f'{self.proc_name}:did not finish')
45+
self.cleanup()
46+
47+
def cleanup(self):
48+
self.stdout_text = ''
49+
self.stderr_text = ''
50+
self.qproc.deleteLater()
51+
52+
@Slot()
53+
def handle_stderr(self):
54+
data = self.qproc.readAllStandardError()
55+
stderr = bytes(data).decode("utf8")
56+
self.stderr_text += stderr
57+
log.error(stderr)
58+
59+
@Slot()
60+
def handle_stdout(self):
61+
data = self.qproc.readAllStandardOutput()
62+
stdout = bytes(data).decode("utf8")
63+
self.stdout_text += stdout
64+
log.info(stdout)
65+
66+
@Slot()
67+
def handle_state(self, state):
68+
state_name = {
69+
QProcess.NotRunning: 'Not running',
70+
QProcess.Starting: 'Starting',
71+
QProcess.Running: 'Running',
72+
}.get(state)
73+
self.state = state
74+
log.info(f'{self.proc_name}:State changed: {state_name}')
75+
76+
77+
# Global dict to be modified after we can verify the external process exists
78+
external_processes: Dict[str, ExternalProcess] = {}
79+
80+
81+
def add_external_process(proc_name: str, prog_name: str, base_args: List[str]):
82+
log.debug(f'Adding external process {proc_name} ({prog_name}, {base_args})')
83+
84+
exe_path = QStandardPaths.findExecutable(prog_name)
85+
log.debug(f'Path is {exe_path}')
86+
if exe_path == '':
87+
log.fatal(f'Could not find {proc_name}!')
88+
sys.exit(1)
89+
90+
external_processes[proc_name] = ExternalProcess(prog_name, base_args)
91+
92+
93+
main_script_parent_dir: Optional[Path] = None
94+
95+
96+
def get_install_dir(cache=True) -> Path:
97+
global main_script_parent_dir
98+
if main_script_parent_dir is None or not cache:
99+
main_script_path = Path(__file__)
100+
main_script_parent_dir = main_script_path.parent.parent.resolve()
101+
log.debug(f'Install directory is {main_script_parent_dir}')
102+
return main_script_parent_dir

0 commit comments

Comments
 (0)