88import os
99import sys
1010import unittest
11+ from contextlib import redirect_stdout
12+ from io import StringIO
1113from unittest .mock import MagicMock , call , patch
1214
1315import pytest
@@ -21,6 +23,14 @@ def _restore_sys_modules():
2123 added = set (sys .modules .keys ()) - set (saved .keys ())
2224 for k in added :
2325 del sys .modules [k ]
26+ # Also drop the stale attribute from the parent package so that
27+ # mock.patch and a later re-import resolve to the same fresh module
28+ parent , _ , child = k .rpartition ("." )
29+ if parent and parent in sys .modules :
30+ try :
31+ delattr (sys .modules [parent ], child )
32+ except AttributeError :
33+ pass
2434 for k , v in saved .items ():
2535 if k not in sys .modules or sys .modules [k ] is not v :
2636 sys .modules [k ] = v
@@ -50,6 +60,20 @@ def test_parse_args_debug_flag(self):
5060 args = parse_arguments ()
5161 assert args .debug is True
5262
63+ def test_parse_args_version_flag (self ):
64+ """Test that --version prints the package version and exits."""
65+ from vocalinux .version import __version__
66+
67+ output = StringIO ()
68+ with patch .object (sys , "argv" , ["vocalinux" , "--version" ]):
69+ from vocalinux .main import parse_arguments
70+
71+ with redirect_stdout (output ), self .assertRaises (SystemExit ) as exit_context :
72+ parse_arguments ()
73+
74+ assert exit_context .exception .code == 0
75+ assert output .getvalue () == f"vocalinux { __version__ } \n "
76+
5377 def test_parse_args_model_argument (self ):
5478 """Test parsing with model argument."""
5579 with patch .object (sys , "argv" , ["vocalinux" , "--model" , "small" ]):
@@ -282,6 +306,25 @@ def test_main_single_instance_already_running(
282306 main ()
283307 assert exc_info .value .code == 1
284308
309+ def test_main_version_flag_with_lock_held (self ):
310+ """Test that --version works even when another instance holds the lock."""
311+ from vocalinux .main import main
312+ from vocalinux .version import __version__
313+
314+ mock_single_instance = MagicMock ()
315+ mock_single_instance .acquire_lock .return_value = False
316+
317+ output = StringIO ()
318+ with patch .dict (sys .modules , {"vocalinux.single_instance" : mock_single_instance }):
319+ with patch .object (sys , "argv" , ["vocalinux" , "--version" ]):
320+ with redirect_stdout (output ):
321+ with pytest .raises (SystemExit ) as exc_info :
322+ main ()
323+
324+ assert exc_info .value .code == 0
325+ assert output .getvalue () == f"vocalinux { __version__ } \n "
326+ mock_single_instance .acquire_lock .assert_not_called ()
327+
285328 @patch ("vocalinux.main.check_display_available" )
286329 @patch ("vocalinux.main.logging" )
287330 @patch ("vocalinux.main.check_dependencies" )
0 commit comments