Skip to content

Commit 1029829

Browse files
authored
Merge pull request #242 from CompOmics/fix/report-gui-fixes
Fixes for report, GUI, and PyInstaller
2 parents 5407855 + 46db0a9 commit 1029829

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ jobs:
4545
run: uv run ms2rescore --help
4646

4747
test-windows-installer:
48+
# Only run on push to main (e.g., after PR merge)
49+
if: ${{ github.ref == 'refs/heads/main' }}
4850
runs-on: windows-latest
4951
steps:
5052
- uses: actions/checkout@v4

ms2rescore.spec

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,13 @@ while requirements:
4545
checked.add(requirement)
4646
module_version = importlib.metadata.version(re.match(r"^[\w\-]+", requirement)[0])
4747
try:
48-
datas_, binaries_, hidden_imports_ = collect_all(requirement, include_py_files=True)
48+
# Use filter to exclude problematic xgboost.testing module
49+
filter_func = lambda name: not name.startswith("xgboost.testing") if requirement == "xgboost" else True
50+
datas_, binaries_, hidden_imports_ = collect_all(
51+
requirement,
52+
include_py_files=True,
53+
filter_submodules=filter_func
54+
)
4955
except (ImportError, RuntimeError) as e:
5056
# Skip packages that fail to collect (e.g., xgboost.testing requires hypothesis)
5157
print(f"Warning: Failed to collect {requirement}: {e}")
@@ -61,6 +67,18 @@ while requirements:
6167

6268
hidden_imports = sorted([h for h in hidden_imports if "tests" not in h.split(".")])
6369
hidden_imports = [h for h in hidden_imports if "__pycache__" not in h]
70+
71+
# Add hdf5plugin imports to fix runtime import issues
72+
hidden_imports.extend([
73+
"hdf5plugin.plugins.bshuf",
74+
"hdf5plugin.plugins.blosc",
75+
"hdf5plugin.plugins.blosc2",
76+
"hdf5plugin.plugins.lz4",
77+
"hdf5plugin.plugins.fcidecomp",
78+
"hdf5plugin.plugins.zfp",
79+
"hdf5plugin.plugins.zstd",
80+
])
81+
6482
datas = [
6583
d
6684
for d in datas

ms2rescore/gui/__main__.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@
22

33
import multiprocessing
44
import os
5-
import contextlib
5+
import sys
66

77
from ms2rescore.gui.app import app
88

99

1010
def main():
1111
"""Entrypoint for MS²Rescore GUI."""
1212
multiprocessing.freeze_support()
13-
# Redirect stdout when running GUI (packaged app might not have console attached)
14-
with contextlib.redirect_stdout(open(os.devnull, "w")):
15-
app()
13+
14+
# Fix for PyInstaller windowed mode: sys.stdout/stderr can be None
15+
# This causes issues with libraries that try to write to stdout (e.g., Keras progress bars)
16+
if sys.stdout is None:
17+
sys.stdout = open(os.devnull, "w")
18+
if sys.stderr is None:
19+
sys.stderr = open(os.devnull, "w")
20+
21+
app()
1622

1723

1824
if __name__ == "__main__":

ms2rescore/gui/app.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,23 @@ def _check_updates_sync(root):
859859
pass
860860

861861

862+
def _setup_logging(log_level: str, log_file: str):
863+
"""Setup file logging for GUI."""
864+
log_level_map = {
865+
"critical": logging.CRITICAL,
866+
"error": logging.ERROR,
867+
"warning": logging.WARNING,
868+
"info": logging.INFO,
869+
"debug": logging.DEBUG,
870+
}
871+
file_handler = logging.FileHandler(log_file, mode="w", encoding="utf-8")
872+
file_handler.setFormatter(
873+
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
874+
)
875+
file_handler.setLevel(log_level_map.get(log_level, logging.INFO))
876+
logging.getLogger().addHandler(file_handler)
877+
878+
862879
def function(config):
863880
"""Function to be executed in a separate process."""
864881
config = config.copy()
@@ -867,6 +884,12 @@ def function(config):
867884
else:
868885
config_list = [config]
869886
config = parse_configurations(config_list)
887+
888+
# Set up file logging for GUI
889+
_setup_logging(
890+
config["ms2rescore"]["log_level"], config["ms2rescore"]["output_path"] + ".log.txt"
891+
)
892+
870893
rescore(configuration=config)
871894
if config["ms2rescore"]["write_report"]:
872895
webbrowser.open_new_tab(config["ms2rescore"]["output_path"] + ".report.html")

ms2rescore/report/generate.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import plotly.express as px
1313
import psm_utils.io
1414
from jinja2 import Environment, FileSystemLoader
15+
from plotly.offline import get_plotlyjs_version
1516
from psm_utils.psm_list import PSMList
1617

1718
try:
@@ -93,6 +94,7 @@ def generate_report(
9394
log_context = _get_log_context(files)
9495

9596
context = {
97+
"plotlyjs_version": get_plotlyjs_version(),
9698
"metadata": {
9799
"generated_on": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
98100
"ms2rescore_version": ms2rescore.__version__, # TODO: Write during run?
@@ -418,8 +420,10 @@ def _render_and_write(output_path_prefix: str, **context):
418420
"""Render template with context and write to HTML file."""
419421
report_path = Path(output_path_prefix + ".report.html").resolve()
420422
logger.info("Writing report to %s", report_path.as_posix())
421-
template_dir = Path(__file__).parent / "templates"
422-
env = Environment(loader=FileSystemLoader(template_dir, encoding="utf-8"))
423+
424+
# Use importlib.resources for PyInstaller compatibility
425+
template_dir = importlib.resources.files(templates)
426+
env = Environment(loader=FileSystemLoader(str(template_dir), encoding="utf-8"))
423427
template = env.get_template("base.html")
424428
with open(report_path, "w", encoding="utf-8") as f:
425429
f.write(template.render(**context))

ms2rescore/report/templates/base.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Oswald:wght@400;500;600;700&display=swap" rel="stylesheet" />
1212
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/font-awesome.min.css" />
1313
<script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
14-
<script type="text/javascript" src="https://cdn.plot.ly/plotly-2.25.2.min.js" charset="utf-8"></script>
14+
<script type="text/javascript" src="https://cdn.plot.ly/plotly-{{ plotlyjs_version }}.min.js" charset="utf-8"></script>
1515
{% include 'style.html' %}
1616
</head>
1717
<body>

0 commit comments

Comments
 (0)