Skip to content

Commit 42f7140

Browse files
authored
Merge pull request #460 from CCPBioSim/357-general-improve-local-version
Show Local Version in Splash Screen and Add `--version` CLI Flag
2 parents 77ae581 + 8dc363d commit 42f7140

6 files changed

Lines changed: 62 additions & 14 deletions

File tree

‎CodeEntropy/cli.py‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@
44
correlation entropy workflow.
55
66
The entry point is intentionally small and only responsible for:
7-
1) Creating a job folder.
8-
2) Constructing a CodeEntropyRunner.
9-
3) Executing the entropy workflow.
10-
4) Handling fatal errors with a non-zero exit code.
7+
1) Handling informational flags such as ``--version``.
8+
2) Creating a job folder.
9+
3) Constructing a CodeEntropyRunner.
10+
4) Executing the entropy workflow.
11+
5) Handling fatal errors with a non-zero exit code.
1112
"""
1213

1314
from __future__ import annotations
1415

1516
import logging
1617

18+
from CodeEntropy.config.argparse import ConfigResolver
1719
from CodeEntropy.config.runtime import CodeEntropyRunner
1820

1921
logger = logging.getLogger(__name__)
@@ -22,9 +24,15 @@
2224
def main() -> None:
2325
"""Run the entropy workflow.
2426
27+
Arguments are parsed before any side effects so that informational flags such
28+
as ``--version`` and ``--help`` exit without creating a job folder or
29+
rendering the splash screen.
30+
2531
Raises:
2632
SystemExit: Exits with status code 1 on any unhandled exception.
2733
"""
34+
ConfigResolver().build_parser().parse_known_args()
35+
2836
folder = CodeEntropyRunner.create_job_folder()
2937

3038
try:

‎CodeEntropy/config/argparse.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
import yaml
3333

34+
from CodeEntropy import __version__
3435
from CodeEntropy.core.dask_clusters import HPCDaskManager
3536

3637
logger = logging.getLogger(__name__)
@@ -318,6 +319,11 @@ def build_parser(self) -> argparse.ArgumentParser:
318319
parser = argparse.ArgumentParser(
319320
description="CodeEntropy: entropy calculation with the MCC method."
320321
)
322+
parser.add_argument(
323+
"--version",
324+
action="version",
325+
version=f"CodeEntropy {__version__}",
326+
)
321327

322328
for name, spec in self._arg_specs.items():
323329
arg_name = f"--{name}"

‎CodeEntropy/config/runtime.py‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from rich.table import Table
3333
from rich.text import Text
3434

35+
from CodeEntropy import __version__
3536
from CodeEntropy.config.argparse import ConfigResolver
3637
from CodeEntropy.core.dask_clusters import HPCDaskManager
3738
from CodeEntropy.core.logging import LoggingConfig
@@ -135,20 +136,21 @@ def load_citation_data(self) -> dict[str, Any] | None:
135136
return None
136137

137138
def show_splash(self) -> None:
138-
"""Render a Rich splash screen with optional citation metadata."""
139+
"""Render a Rich splash screen.
140+
141+
The version shown is that of the locally installed package. Remaining
142+
metadata (authors, description, URL) comes from the online citation file
143+
when it is reachable.
144+
"""
139145
citation = self.load_citation_data()
146+
version_text = Align.center(Text(f"Version {__version__}", style="green"))
140147

141148
if citation:
142149
ascii_title = text2art(citation.get("title", "CodeEntropy"))
143150
ascii_render = Align.center(Text(ascii_title, style="bold white"))
144151

145-
version = citation.get("version", "?")
146-
release_date = citation.get("date-released", "?")
147152
url = citation.get("url", citation.get("repository-code", ""))
148153

149-
version_text = Align.center(
150-
Text(f"Version {version} | Released {release_date}", style="green")
151-
)
152154
url_text = Align.center(Text(url, style="blue underline"))
153155

154156
abstract = citation.get("abstract", "No description available.")
@@ -193,7 +195,7 @@ def show_splash(self) -> None:
193195
else:
194196
ascii_title = text2art("CodeEntropy")
195197
ascii_render = Align.center(Text(ascii_title, style="bold white"))
196-
splash_content = Group(ascii_render)
198+
splash_content = Group(ascii_render, Rule(style="cyan"), version_text)
197199

198200
splash_panel = Panel(
199201
splash_content,

‎tests/unit/CodeEntropy/cli/test_cli.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,17 @@ def test_main_logs_and_exits_nonzero_on_exception(monkeypatch):
3636

3737
assert exc.value.code == 1
3838
fake_runner.run_entropy_workflow.assert_called_once_with()
39+
40+
41+
def test_main_version_flag_exits_before_creating_job_folder(monkeypatch, capsys):
42+
fake_runner_cls = MagicMock()
43+
monkeypatch.setattr(entry, "CodeEntropyRunner", fake_runner_cls)
44+
monkeypatch.setattr("sys.argv", ["CodeEntropy", "--version"])
45+
46+
with pytest.raises(SystemExit) as exc:
47+
entry.main()
48+
49+
assert exc.value.code == 0
50+
assert "CodeEntropy" in capsys.readouterr().out
51+
fake_runner_cls.create_job_folder.assert_not_called()
52+
fake_runner_cls.assert_not_called()

‎tests/unit/CodeEntropy/config/argparse/test_argparse_build_parser.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import pytest
2+
3+
from CodeEntropy import __version__
14
from CodeEntropy.config.argparse import ConfigResolver
25

36

@@ -37,3 +40,13 @@ def test_build_parser_nargs_plus_parses_top_traj_file_list():
3740
args = parser.parse_args(["--top_traj_file", "a.tpr", "b.trr"])
3841

3942
assert args.top_traj_file == ["a.tpr", "b.trr"]
43+
44+
45+
def test_version_flag_prints_installed_version_and_exits(capsys):
46+
parser = ConfigResolver().build_parser()
47+
48+
with pytest.raises(SystemExit) as exc:
49+
parser.parse_args(["--version"])
50+
51+
assert exc.value.code == 0
52+
assert f"CodeEntropy {__version__}" in capsys.readouterr().out

‎tests/unit/CodeEntropy/config/runtime/test_show_splash.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
from rich.console import Console
55

6+
from CodeEntropy import __version__
7+
68

79
def test_show_splash_with_citation(runner):
810
citation = {
@@ -26,8 +28,8 @@ def test_show_splash_with_citation(runner):
2628
out = buf.getvalue()
2729

2830
assert "Welcome to CodeEntropy" in out
29-
assert "Version 1.0" in out
30-
assert "2025-01-01" in out
31+
assert f"Version {__version__}" in out
32+
assert "Version 1.0" not in out
3133
assert "https://example.com" in out
3234
assert "This is a test abstract." in out
3335
assert "Alice Smith" in out
@@ -43,4 +45,7 @@ def test_show_splash_without_citation(runner):
4345
):
4446
runner.show_splash()
4547

46-
assert "Welcome to CodeEntropy" in buf.getvalue()
48+
out = buf.getvalue()
49+
50+
assert "Welcome to CodeEntropy" in out
51+
assert f"Version {__version__}" in out

0 commit comments

Comments
 (0)