46
46
from .argparse_custom import DEFAULT_ARGUMENT_PARSER , CompletionItem
47
47
from .clipboard import can_clip , get_paste_buffer , write_to_paste_buffer
48
48
from .decorators import with_argparser
49
- from .exceptions import Cmd2ArgparseError , Cmd2ShlexError , EmbeddedConsoleExit , EmptyStatement , RedirectionError
49
+ from .exceptions import Cmd2ShlexError , EmbeddedConsoleExit , EmptyStatement , RedirectionError , SkipPostcommandHooks
50
50
from .history import History , HistoryItem
51
51
from .parsing import Macro , MacroArg , Statement , StatementParser , shlex_split
52
52
from .rl_utils import RlType , rl_get_point , rl_make_safe_prompt , rl_set_prompt , rl_type , rl_warning , vt100_support
@@ -1587,9 +1587,9 @@ def onecmd_plus_hooks(self, line: str, *, add_to_history: bool = True,
1587
1587
1588
1588
:param line: command line to run
1589
1589
:param add_to_history: If True, then add this command to history. Defaults to True.
1590
- :param raise_keyboard_interrupt: if True, then KeyboardInterrupt exceptions will be raised. This is used when
1591
- running commands in a loop to be able to stop the whole loop and not just
1592
- the current command. Defaults to False.
1590
+ :param raise_keyboard_interrupt: if True, then KeyboardInterrupt exceptions will be raised if stop isn't already
1591
+ True. This is used when running commands in a loop to be able to stop the whole
1592
+ loop and not just the current command. Defaults to False.
1593
1593
:param py_bridge_call: This should only ever be set to True by PyBridge to signify the beginning
1594
1594
of an app() call from Python. It is used to enable/disable the storage of the
1595
1595
command's stdout.
@@ -1667,26 +1667,35 @@ def onecmd_plus_hooks(self, line: str, *, add_to_history: bool = True,
1667
1667
if py_bridge_call :
1668
1668
# Stop saving command's stdout before command finalization hooks run
1669
1669
self .stdout .pause_storage = True
1670
- except KeyboardInterrupt as ex :
1671
- if raise_keyboard_interrupt :
1672
- raise ex
1673
- except (Cmd2ArgparseError , EmptyStatement ):
1670
+ except (SkipPostcommandHooks , EmptyStatement ):
1674
1671
# Don't do anything, but do allow command finalization hooks to run
1675
1672
pass
1676
1673
except Cmd2ShlexError as ex :
1677
1674
self .perror ("Invalid syntax: {}" .format (ex ))
1678
1675
except RedirectionError as ex :
1679
1676
self .perror (ex )
1677
+ except KeyboardInterrupt as ex :
1678
+ if raise_keyboard_interrupt and not stop :
1679
+ raise ex
1680
+ except SystemExit :
1681
+ stop = True
1680
1682
except Exception as ex :
1681
1683
self .pexcept (ex )
1682
1684
finally :
1683
- stop = self ._run_cmdfinalization_hooks (stop , statement )
1685
+ try :
1686
+ stop = self ._run_cmdfinalization_hooks (stop , statement )
1687
+ except KeyboardInterrupt as ex :
1688
+ if raise_keyboard_interrupt and not stop :
1689
+ raise ex
1690
+ except SystemExit :
1691
+ stop = True
1692
+ except Exception as ex :
1693
+ self .pexcept (ex )
1684
1694
1685
1695
return stop
1686
1696
1687
1697
def _run_cmdfinalization_hooks (self , stop : bool , statement : Optional [Statement ]) -> bool :
1688
1698
"""Run the command finalization hooks"""
1689
-
1690
1699
with self .sigint_protection :
1691
1700
if not sys .platform .startswith ('win' ) and self .stdin .isatty ():
1692
1701
# Before the next command runs, fix any terminal problems like those
@@ -1695,15 +1704,12 @@ def _run_cmdfinalization_hooks(self, stop: bool, statement: Optional[Statement])
1695
1704
proc = subprocess .Popen (['stty' , 'sane' ])
1696
1705
proc .communicate ()
1697
1706
1698
- try :
1699
- data = plugin .CommandFinalizationData (stop , statement )
1700
- for func in self ._cmdfinalization_hooks :
1701
- data = func (data )
1702
- # retrieve the final value of stop, ignoring any
1703
- # modifications to the statement
1704
- return data .stop
1705
- except Exception as ex :
1706
- self .pexcept (ex )
1707
+ data = plugin .CommandFinalizationData (stop , statement )
1708
+ for func in self ._cmdfinalization_hooks :
1709
+ data = func (data )
1710
+ # retrieve the final value of stop, ignoring any
1711
+ # modifications to the statement
1712
+ return data .stop
1707
1713
1708
1714
def runcmds_plus_hooks (self , cmds : List [Union [HistoryItem , str ]], * , add_to_history : bool = True ,
1709
1715
stop_on_keyboard_interrupt : bool = True ) -> bool :
@@ -3894,7 +3900,7 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:
3894
3900
3895
3901
IMPORTANT: This function will not print an alert unless it can acquire self.terminal_lock to ensure
3896
3902
a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
3897
- to guarantee the alert prints.
3903
+ to guarantee the alert prints and to avoid raising a RuntimeError .
3898
3904
3899
3905
:param alert_msg: the message to display to the user
3900
3906
:param new_prompt: if you also want to change the prompt that is displayed, then include it here
@@ -3956,7 +3962,7 @@ def async_update_prompt(self, new_prompt: str) -> None: # pragma: no cover
3956
3962
3957
3963
IMPORTANT: This function will not update the prompt unless it can acquire self.terminal_lock to ensure
3958
3964
a prompt is onscreen. Therefore it is best to acquire the lock before calling this function
3959
- to guarantee the prompt changes.
3965
+ to guarantee the prompt changes and to avoid raising a RuntimeError .
3960
3966
3961
3967
If user is at a continuation prompt while entering a multiline command, the onscreen prompt will
3962
3968
not change. However self.prompt will still be updated and display immediately after the multiline
@@ -3971,9 +3977,9 @@ def set_window_title(self, title: str) -> None: # pragma: no cover
3971
3977
3972
3978
Raises a `RuntimeError` if called while another thread holds `terminal_lock`.
3973
3979
3974
- IMPORTANT: This function will not set the title unless it can acquire self.terminal_lock to avoid
3975
- writing to stderr while a command is running. Therefore it is best to acquire the lock
3976
- before calling this function to guarantee the title changes.
3980
+ IMPORTANT: This function will not set the title unless it can acquire self.terminal_lock to avoid writing
3981
+ to stderr while a command is running. Therefore it is best to acquire the lock before calling
3982
+ this function to guarantee the title changes and to avoid raising a RuntimeError .
3977
3983
3978
3984
:param title: the new window title
3979
3985
"""
0 commit comments