ATLAS Offline Software
Loading...
Searching...
No Matches
AtlCoolConsole.py
Go to the documentation of this file.
1#!/usr/bin/env python
2# version modified by Richard Hawkings from COOl1.3.2 distribution
3# original by Sven Schmitt (Abstracture/Mainz)
4
5import sys
6import code
7import readline
8import atexit
9import os
10import re
11import logging
12
13log = logging.getLogger( __name__ )
14log.setLevel( logging.INFO )
15
16handler = logging.StreamHandler()
17format = "%(levelname)s:%(name)s: %(message)s"
18handler.setFormatter( logging.Formatter( format ) )
19log.addHandler( handler )
20
21
22historyFile = '.coolconsole_hist'
23
24class HistoryConsole(code.InteractiveConsole):
25 """
26 This class extends InteractiveConsole with command line history. The
27 history can be accessed with the usual CURSOR UP keystroke. It is also
28 stored to a file '%s' in the user's home directory.
29 """ % historyFile
30
31 def __init__( self,
32 locals = None,
33 filename = "<console>",
34 histfile = os.path.join( os.environ["HOME"], historyFile) ):
35 code.InteractiveConsole.__init__( self )
36 self.init_history( histfile )
37
38 def init_history( self, histfile ):
39 readline.parse_and_bind( "tab: complete" )
40 readline.set_history_length( 100 )
41 if hasattr( readline, "read_history_file" ):
42 try:
43 readline.read_history_file( histfile )
44 except IOError:
45 pass
46 atexit.register( self.save_history, histfile )
47
48 def save_history( self, histfile ):
49 readline.write_history_file( histfile )
50
51
52
54
55 commands = { 'help' : 'help overview',
56 'less' : 'list contents of folders, e.g. less "/a"',
57 'more' : 'list contents of folders (ATLAS specific)',
58 'ls' : 'list contents of foldersets, e.g. ls "/"',
59 'll' : 'list contents of foldersets with entry count',
60 'exit' : 'quit the interpreter session',
61 'quit' : 'alias for exit',
62 'open' : "open the specified database, "
63 "e.g. open 'sqlite://...'",
64 'cd' : 'change directory',
65 'pwd' : 'print current directory',
66 'rmdir' : 'remove a folder or folderset',
67 'usetag' : 'set subsequent list operations (less) to use given COOL tag',
68 'usechan' : 'set subsequent list operations (less) to display given COOL channel number only',
69 'userunlumi' : 'set limits for run/lumi blocks in more/less',
70 'usetimes' : 'set limits for timestamps in more/less',
71 'pws' : 'print current tag and channel selections used by less',
72 'listtags' : 'list tags in folder / folder set',
73 'listchans' : 'list channels in folder',
74 'listinfo' : 'list info about folder (type, columns)',
75 'filtertags' : 'list tags in folder / folder set with filtering',
76 'settag' : 'set hierarchical tag for a folder+parent',
77 'settginfo' : 'set tag description string',
78 'setchan' : 'set channel name/description',
79 'clonetag' : 'clone data from one tag to another',
80 'setdesc' : 'set folder description (meta-data) string',
81 'rmtag' : 'remove tag or hierarchical tag relation to a parent',
82 'locktag' : 'lock a tag so the contents cannot be changed',
83 'headtag' : 'apply HEAD-style tag to a folder',
84 'tracetags': 'list tags defined in subfolders for parent'
85 }
86
87 banner = "Welcome to AtlCoolConsole. Type 'help' for instructions."
88
89 def __init__( self, connectString = None ):
90 HistoryConsole.__init__( self )
91 self.connectString = connectString
92
93
94 def interact( self ):
95 self.push( 'from CoolConvUtilities import AtlCoolTool' )
96 if connectString is not None:
97 self.push( 'this = AtlCoolTool.AtlCoolTool("%s")' % self.connectString )
98 self.push( 'print (this)' )
99 else:
100 print ( "Not connected. Use the 'open' command to connect to "
101 "a database." )
102 HistoryConsole.interact( self, self.banner )
103
104
105 def parseLine( self, line ):
106 for command in self.commands.keys():
107 #res = re.search( '^' + command + '\s*(?P<remainder>.*)', line )
108 res=re.search( '^' + command + r'($|\s+(?P<remainder>.*))', line )
109 if res is not None:
110 return command, res.group('remainder') or ""
111 return None, line
112
113
114 def createInterpreterCommand( self, command, argumentString ):
115 if command == 'less':
116 return self.command_less( argumentString )
117 elif command == 'more':
118 return self.command_more( argumentString )
119 elif command == 'ls':
120 return self.command_ls( argumentString,False )
121 elif command == 'll':
122 return self.command_ls( argumentString,True )
123 elif command == 'help':
124 return self.command_help( argumentString )
125 elif command == 'exit':
126 return self.command_exit()
127 elif command == 'quit':
128 return self.command_exit()
129 elif command == 'open':
130 return self.command_open( argumentString )
131 elif command =='listtags':
132 return self.command_lstags( argumentString )
133 elif command =='filtertags':
134 return self.command_filtertags( argumentString )
135 elif command =='listchans':
136 return self.command_listchans( argumentString )
137 elif command =='listinfo':
138 return self.command_listinfo( argumentString )
139 elif command =='rmdir':
140 return self.command_rmdir( argumentString )
141 elif command =='usetag':
142 return self.command_usetag( argumentString )
143 elif command =='usechan':
144 return self.command_usechan( argumentString )
145 elif command =='settag':
146 return self.command_settag( argumentString )
147 elif command =='settginfo':
148 return self.command_settginfo( argumentString )
149 elif command =='setchan':
150 return self.command_setchan( argumentString )
151 elif command =='userunlumi':
152 return self.command_userunlumi( argumentString )
153 elif command =='usetimes':
154 return self.command_usetimes( argumentString )
155 elif command =='clonetag':
156 return self.command_clonetag( argumentString )
157 elif command =='rmtag':
158 return self.command_rmtag( argumentString )
159 elif command =='locktag':
160 return self.command_locktag( argumentString )
161 elif command =='headtag':
162 return self.command_headtag( argumentString )
163 elif command =='tracetags':
164 return self.command_tracetags( argumentString )
165 elif command == 'setdesc':
166 return self.command_setdesc( argumentString )
167 elif command =='cd':
168 return self.command_cd( argumentString )
169 elif command =='pwd':
170 return self.command_pwd()
171 elif command =='pws':
172 return self.command_pws()
173 else:
174 return None
175
176
177 def command_less( self, argumentString ):
178 if argumentString is None:
179 raise Exception( "usage: less <folder>" )
180 argumentString = argumentString.strip()
181 nodes = argumentString.split()
182 cmds = []
183 for node in nodes:
184 cmds.append( 'this.less("%s", header=True)' % node )
185 return ';'.join( cmds )
186
187 def command_more( self, argumentString ):
188 if argumentString is None:
189 raise Exception( "usage: more <folder>" )
190 argumentString = argumentString.strip()
191 nodes = argumentString.split()
192 cmds = []
193 for node in nodes:
194 cmds.append( 'this.more("%s", header=True)' % node )
195 return ';'.join( cmds )
196
197
198 def command_ls( self, argumentString, doCount=False ):
199 if argumentString is None: argumentString = '.'
200 argumentString = argumentString.strip()
201 if argumentString == '': argumentString = '.'
202 nodes = argumentString.split()
203 cmds = []
204 tof='False'
205 if (doCount): tof='True'
206 for node in nodes:
207 cmds.append( 'this.ls("%s", header=True, doCount=%s)' % (node,tof) )
208 return ';'.join( cmds )
209
210 def command_pwd(self):
211 return ';'.join(['this.pwd()'])
212
213 def command_pws(self):
214 return ';'.join(['this.pws()'])
215
216 def command_lstags( self, argumentString ):
217 if argumentString is None: argumentString = '.'
218 argumentString = argumentString.strip()
219 if argumentString is None: argumentString = '.'
220 nodes = argumentString.split()
221 cmds = []
222 for node in nodes:
223 cmds.append( 'this.lstags("%s")' % node )
224 return ';'.join( cmds )
225
226 def command_filtertags(self,argumentString):
227 if argumentString is None or argumentString=="": argumentString = '.'
228 argumentString = argumentString.strip()
229 if argumentString is None: argumentString = '.'
230 args = argumentString.split()
231 node=args[0]
232 pattern=""
233 if len(args)>1:
234 pattern=args[1]
235 cmds = []
236 cmds.append('this.lstags("%s",pattern="%s")' % (node,pattern))
237 return ';'.join(cmds)
238
239
240 def command_listchans( self, argumentString ):
241 if argumentString is None: argumentString = '.'
242 argumentString = argumentString.strip()
243 if argumentString is None: argumentString = '.'
244 nodes = argumentString.split()
245 cmds = []
246 for node in nodes:
247 cmds.append( 'this.listchans("%s")' % node )
248 return ';'.join( cmds )
249
250 def command_listinfo( self, argumentString ):
251 if argumentString is None: argumentString = '.'
252 argumentString = argumentString.strip()
253 if argumentString is None: argumentString = '.'
254 nodes = argumentString.split()
255 cmds = []
256 for node in nodes:
257 cmds.append( 'this.listinfo("%s")' % node )
258 return ';'.join( cmds )
259
260 def command_rmdir(self, argumentString ):
261 argumentString = argumentString.strip()
262 cmds=[]
263 cmds.append('this.rmdir("%s")' % argumentString)
264 return ';'.join( cmds )
265
266 def command_usetag(self, argumentString ):
267 argumentString = argumentString.strip()
268 cmds=[]
269 cmds.append('this.usetag("%s")' % argumentString)
270 return ';'.join( cmds )
271
272 def command_usechan(self, argumentString ):
273 argumentString = argumentString.strip()
274 cmds=[]
275 cmds.append('this.usechan("%s")' % argumentString)
276 return ';'.join( cmds )
277
278 def command_cd( self, argumentString ):
279 if argumentString is None: argumentString ='/'
280 argumentString = argumentString.strip()
281 if argumentString == '': argumentString = '/'
282 cmds=[]
283 cmds.append('this.cd("%s")' % argumentString)
284 return ';'.join( cmds )
285
286 def command_settag(self,argumentString):
287 args=argumentString.split()
288 if len(args)<3:
289 print ('Usage: settag <folder> <foldertag> <parenttag>')
290 return ''
291 cmds=[]
292 cmds.append('this.settag("%s")' % argumentString)
293 return ';'.join(cmds)
294
295 def command_settginfo(self,argumentString):
296 args=argumentString.split()
297 if len(args)<2:
298 print ('Usage: settginfo <folder> <tag> <description>')
299 return ''
300 cmds=[]
301 cmds.append('this.settginfo("%s")' % argumentString)
302 return ';'.join(cmds)
303
304 def command_setchan(self,argumentString):
305 args=argumentString.split()
306 if len(args)<3:
307 print ('Usage: setchan <folder> <chanID> <chanName> {<chanDescr>}')
308 return ''
309 cmds=[]
310 cmds.append('this.setchan("%s")' % argumentString)
311 return ';'.join(cmds)
312
313 def command_userunlumi(self,argumentString):
314 args=argumentString.split()
315 if len(args)!=1 and len(args)<4:
316 print ('Usage: userunlumi <run1> {<LB1> <run2> <LB2>}')
317 return ''
318 cmds=[]
319 cmds.append('this.userunlumi("%s")' % argumentString)
320 return ';'.join(cmds)
321
322 def command_usetimes(self,argumentString):
323 args=argumentString.split()
324 if len(args)<2:
325 print ('Usage: usetimes <time1> <time2>')
326 return ''
327 cmds=[]
328 cmds.append('this.usetimes("%s")' % argumentString)
329 return ';'.join(cmds)
330
331 def command_clonetag(self,argumentString):
332 args=argumentString.split()
333 if len(args)<3:
334 print ('Usage: clonetag <folder> <sourcetag> <desttag>')
335 return ''
336 cmds=[]
337 cmds.append('this.clonetag("%s")' % argumentString)
338 return ';'.join(cmds)
339
340
341 def command_rmtag(self,argumentString):
342 args=argumentString.split()
343 if len(args)<2:
344 print ('Usage: rmtag <folder> <leaf or parent tag>')
345 return ''
346 cmds=[]
347 cmds.append('this.rmtag("%s")' % argumentString)
348 return ';'.join(cmds)
349
350 def command_locktag(self,argumentString):
351 args=argumentString.split()
352 if len(args)<2:
353 print ('Usage: locktag <folder> <tag> {action=l|p|u|r}')
354 return ''
355 cmds=[]
356 cmds.append('this.locktag("%s")' % argumentString)
357 return ';'.join(cmds)
358
359 def command_headtag(self,argumentString):
360 args=argumentString.split()
361 if len(args)<2:
362 print ('Usage: headtag <folder> <tag>')
363 return ''
364 cmds=[]
365 cmds.append('this.headtag("%s")' % argumentString)
366 return ';'.join(cmds)
367
368
369 def command_tracetags(self,argumentString):
370 args=argumentString.split()
371 if len(args)<2:
372 print ('Usage: tracetags <folder> <foldertag>')
373 return ''
374 cmds=[]
375 cmds.append('this.tracetags("%s")' % argumentString)
376 return ';'.join(cmds)
377
378
379 def command_setdesc( self, argumentString ):
380 args=argumentString.split()
381 if len(args)<1:
382 print ('Usage: setdesc <folder> {<newdesc>}')
383 return ''
384 cmds=[]
385 cmds.append('this.setdesc("%s")' % argumentString)
386 return ';'.join(cmds)
387
388
389 def command_help( self, argumentString ):
390 if argumentString is not None and argumentString != '':
391 # we have a python "help(...)" command most likely
392 # we only want to intercept "help", therefore return the original
393 return 'help ' + argumentString
394 print ('Available commands:')
395 keys = list(self.commands.keys())
396 keys.sort()
397 for key in keys:
398 print (' %(key)-8s : %(value)s' % { 'key' : key,
399 'value' : self.commands[key] })
400 print ("These commands are shortcuts that are forwarded to a CoolTool")
401 print ("instance 'this', referring to the currently connected database.")
402 print ("Since this environment is a fully functional python shell,")
403 print ("'this' can be used like any python object, e.g.:")
404 print (" this.ls( '/' )")
405 return ''
406
407
408 def command_exit( self ):
409 return 'import sys ; sys.exit(0)'
410
411
412 def command_open( self, argumentString ):
413 log.debug( 'argumentString: ' + argumentString )
414 if ( not argumentString.startswith('"') and
415 not argumentString.startswith("'") ):
416 argumentString = "'" + argumentString + "'"
417 log.debug( 'argumentString: ' + argumentString )
418 return 'this = AtlCoolTool.AtlCoolTool(%s)' % argumentString
419
420
421 def push(self, line):
422 command, remainder = self.parseLine( line )
423 log.debug( 'command: %s' % command )
424 log.debug( 'remainder: %s' % remainder )
425
426 res = self.createInterpreterCommand( command, remainder )
427 if res is not None:
428 log.debug( 'command: "%s"' % res )
429 interpreterCommand = res
430 else:
431 interpreterCommand = line
432
433 #HistoryConsole.push( self, 'print "cmd: %s"' % interpreterCommand )
434 return HistoryConsole.push( self, interpreterCommand )
435
436
437
438
439if __name__ == '__main__':
440
441
442 usage = ( 'Usage: %s <connect string>\n'
443 '\t<connect string>: a RAL connect string\n'
444 ) % sys.argv[0]
445
446
447 if len( sys.argv ) == 2:
448 connectString = sys.argv[1]
449 else:
450 connectString = None
451
452 tool = AtlCoolConsole( connectString )
453 tool.interact()
454
455
command_headtag(self, argumentString)
command_ls(self, argumentString, doCount=False)
command_locktag(self, argumentString)
command_setdesc(self, argumentString)
command_listinfo(self, argumentString)
__init__(self, connectString=None)
command_less(self, argumentString)
command_usechan(self, argumentString)
command_filtertags(self, argumentString)
command_rmtag(self, argumentString)
command_open(self, argumentString)
command_settginfo(self, argumentString)
command_userunlumi(self, argumentString)
command_more(self, argumentString)
createInterpreterCommand(self, command, argumentString)
command_clonetag(self, argumentString)
command_tracetags(self, argumentString)
command_rmdir(self, argumentString)
command_lstags(self, argumentString)
command_listchans(self, argumentString)
command_settag(self, argumentString)
command_cd(self, argumentString)
command_setchan(self, argumentString)
command_usetimes(self, argumentString)
command_usetag(self, argumentString)
command_help(self, argumentString)
__init__(self, locals=None, filename="<console>", histfile=os.path.join(os.environ["HOME"], historyFile))