ATLAS Offline Software
Loading...
Searching...
No Matches
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
5import os
6import sys
7import re
8import AthenaCommon.Utils.unixtools as unixtools
9from 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
78def 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()
LazyPython based hook for shell commands ====================================.
__call__(self, exctype, value, traceb)
configureInteractivePrompt(completionDict=None)