Skip to content

Commit e10e9dd

Browse files
committed
Add: --version CLI flag and fix version string inconsistency
Remove hardcoded __version__ = "0.1.0" in __init__.py that was overwriting the canonical version from __version__.py. Add -V/--version flag to the CLI entry point. Add test coverage for --version, --csv, and --top CLI flags. https://claude.ai/code/session_017K4SRdDU2vdt93ErnwYM8t
1 parent af69aee commit e10e9dd

File tree

3 files changed

+117
-2
lines changed

3 files changed

+117
-2
lines changed

python/flexaidds/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,3 @@
7676
"VibrationalEntropy",
7777
])
7878

79-
__version__ = "0.1.0"

python/flexaidds/__main__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pathlib import Path
2020
from typing import Optional
2121

22+
from .__version__ import __version__
2223
from .results import load_results
2324

2425

@@ -27,6 +28,11 @@ def build_parser() -> argparse.ArgumentParser:
2728
prog="python -m flexaidds",
2829
description="Inspect FlexAID∆S docking result directories from Python.",
2930
)
31+
parser.add_argument(
32+
"-V", "--version",
33+
action="version",
34+
version=f"%(prog)s {__version__}",
35+
)
3036
parser.add_argument("results_dir", type=Path, help="Directory containing docking result PDB files")
3137
parser.add_argument(
3238
"--json",

python/tests/test_cli.py

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
"""Tests for flexaidds.__main__ – CLI entry point.
22
3-
Covers build_parser() and the two output branches of main():
3+
Covers build_parser() and the output branches of main():
44
- human-readable summary (default)
55
- machine-readable JSON (--json flag)
6+
- CSV export (--csv flag)
7+
- top-N filtering (--top flag)
8+
- version display (--version flag)
69
"""
710

811
from __future__ import annotations
@@ -196,3 +199,110 @@ def test_json_source_dir_is_string(self, tmp_path, monkeypatch, capsys):
196199
main()
197200
parsed = json.loads(capsys.readouterr().out)
198201
assert isinstance(parsed["source_dir"], str)
202+
203+
204+
# ===========================================================================
205+
# --version flag
206+
# ===========================================================================
207+
208+
class TestMainVersionOutput:
209+
def test_version_flag_prints_version(self, capsys):
210+
from flexaidds.__version__ import __version__
211+
parser = build_parser()
212+
with pytest.raises(SystemExit) as exc_info:
213+
parser.parse_args(["--version"])
214+
assert exc_info.value.code == 0
215+
out = capsys.readouterr().out
216+
assert __version__ in out
217+
218+
def test_short_version_flag(self, capsys):
219+
from flexaidds.__version__ import __version__
220+
parser = build_parser()
221+
with pytest.raises(SystemExit) as exc_info:
222+
parser.parse_args(["-V"])
223+
assert exc_info.value.code == 0
224+
out = capsys.readouterr().out
225+
assert __version__ in out
226+
227+
228+
# ===========================================================================
229+
# main() – CSV output
230+
# ===========================================================================
231+
232+
class TestMainCsvOutput:
233+
def _make_dir(self, tmp_path: Path) -> Path:
234+
_write_pdb(
235+
tmp_path / "mode_1_pose_1.pdb",
236+
["binding_mode = 1", "pose_rank = 1", "CF = -42.5",
237+
"free_energy = -41.0", "temperature = 300.0"],
238+
)
239+
_write_pdb(
240+
tmp_path / "mode_2_pose_1.pdb",
241+
["binding_mode = 2", "pose_rank = 1", "CF = -35.0",
242+
"temperature = 300.0"],
243+
)
244+
return tmp_path
245+
246+
def test_returns_zero(self, tmp_path, monkeypatch):
247+
d = self._make_dir(tmp_path)
248+
csv_out = tmp_path / "out.csv"
249+
monkeypatch.setattr(sys, "argv", ["flexaidds", str(d), "--csv", str(csv_out)])
250+
assert main() == 0
251+
252+
def test_creates_csv_file(self, tmp_path, monkeypatch):
253+
d = self._make_dir(tmp_path)
254+
csv_out = tmp_path / "out.csv"
255+
monkeypatch.setattr(sys, "argv", ["flexaidds", str(d), "--csv", str(csv_out)])
256+
main()
257+
assert csv_out.exists()
258+
259+
def test_csv_has_header_and_rows(self, tmp_path, monkeypatch):
260+
d = self._make_dir(tmp_path)
261+
csv_out = tmp_path / "out.csv"
262+
monkeypatch.setattr(sys, "argv", ["flexaidds", str(d), "--csv", str(csv_out)])
263+
main()
264+
lines = csv_out.read_text().strip().splitlines()
265+
assert len(lines) == 3 # header + 2 modes
266+
assert "mode_id" in lines[0]
267+
268+
def test_csv_confirmation_message(self, tmp_path, monkeypatch, capsys):
269+
d = self._make_dir(tmp_path)
270+
csv_out = tmp_path / "out.csv"
271+
monkeypatch.setattr(sys, "argv", ["flexaidds", str(d), "--csv", str(csv_out)])
272+
main()
273+
out = capsys.readouterr().out
274+
assert "2" in out # n_modes in confirmation
275+
assert str(csv_out) in out
276+
277+
278+
# ===========================================================================
279+
# main() – --top flag
280+
# ===========================================================================
281+
282+
class TestMainTopFlag:
283+
def _make_dir(self, tmp_path: Path) -> Path:
284+
for i in range(1, 4):
285+
_write_pdb(
286+
tmp_path / f"mode_{i}_pose_1.pdb",
287+
[f"binding_mode = {i}", "pose_rank = 1",
288+
f"CF = {-40.0 + i}", f"free_energy = {-39.0 + i}",
289+
"temperature = 300.0"],
290+
)
291+
return tmp_path
292+
293+
def test_top_limits_table_rows(self, tmp_path, monkeypatch, capsys):
294+
d = self._make_dir(tmp_path)
295+
monkeypatch.setattr(sys, "argv", ["flexaidds", str(d), "--top", "1"])
296+
main()
297+
out = capsys.readouterr().out
298+
assert "Binding modes: 3" in out
299+
300+
def test_top_default_is_none(self, tmp_path):
301+
parser = build_parser()
302+
args = parser.parse_args([str(tmp_path)])
303+
assert args.top is None
304+
305+
def test_top_parsed_as_int(self, tmp_path):
306+
parser = build_parser()
307+
args = parser.parse_args([str(tmp_path), "--top", "5"])
308+
assert args.top == 5

0 commit comments

Comments
 (0)