ATLAS Offline Software
Interactive.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 """Utilities for the interactive athena prompt."""
4 
5 import os
6 import sys
7 import re
8 import AthenaCommon.Utils.unixtools as unixtools
9 from AthenaCommon.Logging import log
10 
11 _shellCommands = [ 'echo', 'emacs', 'env', 'ls', 'less', 'more', 'pico', 'vi' ]
12 _unacceptable = [ 'false', 'true', 'sys' ]
13 _NAME = 'name'
14 _NAMEREX = re.compile( r"named? '?(?P<%s>[\w\d]+)'?" % _NAME )
15 
16 
17 
19  """Provide shell escapes from the prompt by catching name and syntax errors."""
20 
21  def __init__( self ):
22  self._orig_ehook = sys.excepthook
23  log.debug( 'shell short-cuts enabled' )
24 
25  def uninstall( self ):
26  sys.excepthook = self._orig_ehook
27  log.debug( 'shell short-cuts disabled' )
28 
29  def __call__( self, exctype, value, traceb ):
30  cmd = None
31 
32  # catch name and syntax errors to perform shell escapes if known
33  if isinstance( value, NameError ):
34  res = _NAMEREX.search( str(value) )
35  if res:
36  cmd = res.group( _NAME )
37 
38  # disallow selected commands/executables
39  if cmd in _unacceptable:
40  cmd = None
41 
42  elif isinstance( value, SyntaxError ):
43  cmd = value.text[:-1]
44 
45  # execute command, if any
46  if cmd is not None:
47  args = cmd.split()
48  exe = args[0]
49 
50  # special cases
51  if exe == 'cd' and len(args) == 2:
52  os.chdir( args[1] )
53  log.info( 'new directory: %s', os.getcwd() )
54  return
55 
56  if exe == 'help' and len(args) == 2:
57  import __main__
58  exec ('help( %s )' % args[1] in __main__.__dict__, __main__.__dict__)
59  return
60 
61  # cache shell command
62  if exe not in _shellCommands:
63  log.debug( 'accepting executable "%s"', exe )
64  if unixtools.which( exe ):
65  _shellCommands.append( exe )
66  else:
67  exe = None
68 
69  if exe is not None:
70  log.debug( 'executing shell command "%s"', cmd )
71  os.system( cmd )
72  return
73 
74  # nothing recognizable: normal exception processing
75  self._orig_ehook( exctype, value, traceb )
76 
77 
78 def configureInteractivePrompt(completionDict = None):
79  """Configure interactive prompt. The optional completionDict is used to
80  configure the readline completer."""
81 
82  # Athena-specific command history
83  import atexit
84  import readline
85  import rlcompleter # noqa: F401 (needed for completion)
86 
87  fhistory = os.path.expanduser( '~/.athena.history' )
88 
89  if completionDict is not None:
90  readline.set_completer(rlcompleter.Completer(completionDict).complete)
91 
92  readline.parse_and_bind( 'tab: complete' )
93  readline.parse_and_bind( 'set show-all-if-ambiguous On' )
94 
95  if os.path.exists( fhistory ):
96  readline.read_history_file( fhistory )
97 
98  readline.set_history_length( 1024 )
99 
100  # save history on exit
101  atexit.register( readline.write_history_file, fhistory )
102 
103  # enable shell commands in interactive prompt
104  sys.excepthook = ShellEscapes()
python.Interactive.ShellEscapes
LazyPython based hook for shell commands ====================================.
Definition: Interactive.py:18
python.Interactive.ShellEscapes.__init__
def __init__(self)
Definition: Interactive.py:21
python.Interactive.configureInteractivePrompt
def configureInteractivePrompt(completionDict=None)
Definition: Interactive.py:78
python.Interactive.ShellEscapes.uninstall
def uninstall(self)
Definition: Interactive.py:25
python.Interactive.ShellEscapes.__call__
def __call__(self, exctype, value, traceb)
Definition: Interactive.py:29
python.Interactive.ShellEscapes._orig_ehook
_orig_ehook
Definition: Interactive.py:22
str
Definition: BTagTrackIpAccessor.cxx:11