1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """ A file containing different extension of the cmd basic python library"""
16
17
18 import cmd
19 import logging
20 import os
21 import pydoc
22 import re
23 import signal
24 import subprocess
25 import sys
26 import traceback
27 try:
28 import readline
29 GNU_SPLITTING = ('GNU' in readline.__doc__)
30 except:
31 readline = None
32 GNU_SPLITTING = True
33
34
35 logger = logging.getLogger('cmdprint')
36 logger_stderr = logging.getLogger('fatalerror')
37
38 try:
39 import madgraph.various.misc as misc
40 from madgraph import MG5DIR
41 MADEVENT = False
42 except ImportError, error:
43 try:
44 import internal.misc as misc
45 except:
46 raise error
47 MADEVENT = True
48
49
50 pjoin = os.path.join
53 """Class for run-time error"""
54
55 -def debug(debug_only=True):
56
57 def deco_debug(f):
58
59 if debug_only and not __debug__:
60 return f
61
62 def deco_f(*args, **opt):
63 try:
64 return f(*args, **opt)
65 except Exception, error:
66 logger.error(error)
67 logger.error(traceback.print_exc(file=sys.stdout))
68 return
69 return deco_f
70 return deco_debug
71
77 """Simple extension for the readline"""
78
82
84 """convert the multiple category in a formatted list understand by our
85 specific readline parser"""
86
87 if 'libedit' in readline.__doc__:
88
89 out = []
90 for name, opt in dico.items():
91 out += opt
92 return out
93
94
95 if not forceCategory and all(len(s) <= 1 for s in dico.values() ):
96 values = set((s[0] for s in dico.values() if len(s)==1))
97 if len(values) == 1:
98 return values
99
100
101 out = []
102 valid=0
103
104 for name, opt in dico.items():
105 if not opt:
106 continue
107 name = name.replace(' ', '_')
108 valid += 1
109 out.append(opt[0].rstrip()+'@@'+name+'@@')
110
111 d = {}
112 for x in opt:
113 d[x] = 1
114 opt = list(d.keys())
115 opt.sort()
116 out += opt
117
118 if not forceCategory and valid == 1:
119 out = out[1:]
120
121 return out
122
123 @debug()
125 """print auto-completions by category"""
126 if not hasattr(self, 'completion_prefix'):
127 self.completion_prefix = ''
128 longest_match_length += len(self.completion_prefix)
129 try:
130 if len(matches) == 1:
131 self.stdout.write(matches[0]+' ')
132 return
133 self.stdout.write('\n')
134 l2 = [a[-2:] for a in matches]
135 if '@@' in l2:
136 nb_column = self.getTerminalSize()//(longest_match_length+1)
137 pos=0
138 for val in self.completion_matches:
139 if val.endswith('@@'):
140 category = val.rsplit('@@',2)[1]
141 category = category.replace('_',' ')
142 self.stdout.write('\n %s:\n%s\n' % (category, '=' * (len(category)+2)))
143 start = 0
144 pos = 0
145 continue
146 elif pos and pos % nb_column ==0:
147 self.stdout.write('\n')
148 self.stdout.write(self.completion_prefix + val + \
149 ' ' * (longest_match_length +1 -len(val)))
150 pos +=1
151 self.stdout.write('\n')
152 else:
153
154 nb_column = self.getTerminalSize()//(longest_match_length+1)
155 for i,val in enumerate(matches):
156 if i and i%nb_column ==0:
157 self.stdout.write('\n')
158 self.stdout.write(self.completion_prefix + val + \
159 ' ' * (longest_match_length +1 -len(val)))
160 self.stdout.write('\n')
161
162 self.stdout.write(self.prompt+readline.get_line_buffer())
163 self.stdout.flush()
164 except Exception, error:
165 if __debug__:
166 logger.error(error)
167
169 def ioctl_GWINSZ(fd):
170 try:
171 import fcntl, termios, struct
172 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
173 '1234'))
174 except Exception:
175 return None
176 return cr
177 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
178 if not cr:
179 try:
180 fd = os.open(os.ctermid(), os.O_RDONLY)
181 cr = ioctl_GWINSZ(fd)
182 os.close(fd)
183 except Exception:
184 pass
185 if not cr:
186 try:
187 cr = (os.environ['LINES'], os.environ['COLUMNS'])
188 except Exception:
189 cr = (25, 80)
190 return int(cr[1])
191
193 """Return the next possible completion for 'text'.
194 If a command has not been entered, then complete against command list.
195 Otherwise try to call complete_<command> to get list of completions.
196 """
197
198 if state == 0:
199 import readline
200 origline = readline.get_line_buffer()
201 line = origline.lstrip()
202 stripped = len(origline) - len(line)
203 begidx = readline.get_begidx() - stripped
204 endidx = readline.get_endidx() - stripped
205
206 if ';' in line:
207 begin, line = line.rsplit(';',1)
208 begidx = begidx - len(begin) - 1
209 endidx = endidx - len(begin) - 1
210 if line[:begidx] == ' ' * begidx:
211 begidx=0
212
213 if begidx>0:
214 cmd, args, foo = self.parseline(line)
215 if cmd == '':
216 compfunc = self.completedefault
217 else:
218 try:
219 compfunc = getattr(self, 'complete_' + cmd)
220 except AttributeError, error:
221 misc.sprint(error)
222 compfunc = self.completedefault
223 except Exception, error:
224 misc.sprint(error)
225 else:
226 compfunc = self.completenames
227
228
229 if line and begidx > 2 and line[begidx-2:begidx] == '\ ':
230 Ntext = line.split(os.path.sep)[-1]
231 self.completion_prefix = Ntext.rsplit('\ ', 1)[0] + '\ '
232 to_rm = len(self.completion_prefix) - 1
233 Nbegidx = len(line.rsplit(os.path.sep, 1)[0]) + 1
234 data = compfunc(Ntext.replace('\ ', ' '), line, Nbegidx, endidx)
235 self.completion_matches = [p[to_rm:] for p in data
236 if len(p)>to_rm]
237
238 elif line and line[begidx-1] == '-':
239 try:
240 Ntext = line.split()[-1]
241 self.completion_prefix = Ntext.rsplit('-',1)[0] +'-'
242 to_rm = len(self.completion_prefix)
243 Nbegidx = len(line.rsplit(None, 1)[0])
244 data = compfunc(Ntext, line, Nbegidx, endidx)
245 self.completion_matches = [p[to_rm:] for p in data
246 if len(p)>to_rm]
247 except Exception, error:
248 print error
249 else:
250 self.completion_prefix = ''
251 self.completion_matches = compfunc(text, line, begidx, endidx)
252
253 self.completion_matches = [ l if l[-1] in [' ','@','=',os.path.sep]
254 else ((l + ' ') if not l.endswith('\\$') else l[:-2])
255 for l in self.completion_matches if l]
256
257 try:
258 return self.completion_matches[state]
259 except IndexError, error:
260
261
262
263 return None
264
265 @staticmethod
267 """Split a line of arguments"""
268
269 split = line.split()
270 out=[]
271 tmp=''
272 for data in split:
273 if data[-1] == '\\':
274 tmp += data[:-1]+' '
275 elif tmp:
276 tmp += data
277 tmp = os.path.expanduser(os.path.expandvars(tmp))
278 out.append(tmp)
279
280
281 tmp = ''
282 else:
283 out.append(data)
284 return out
285
286 @staticmethod
288 """Propose completions of text in list"""
289
290 if not text:
291 completions = list
292 else:
293 completions = [ f
294 for f in list
295 if f.startswith(text)
296 ]
297
298 return completions
299
300
301 @staticmethod
302 - def path_completion(text, base_dir = None, only_dirs = False,
303 relative=True):
304 """Propose completions of text to compose a valid path"""
305
306 if base_dir is None:
307 base_dir = os.getcwd()
308 base_dir = os.path.expanduser(os.path.expandvars(base_dir))
309
310 if text == '~':
311 text = '~/'
312 prefix, text = os.path.split(text)
313 prefix = os.path.expanduser(os.path.expandvars(prefix))
314 base_dir = os.path.join(base_dir, prefix)
315 if prefix:
316 prefix += os.path.sep
317
318 if only_dirs:
319 completion = [prefix + f
320 for f in os.listdir(base_dir)
321 if f.startswith(text) and \
322 os.path.isdir(os.path.join(base_dir, f)) and \
323 (not f.startswith('.') or text.startswith('.'))
324 ]
325 else:
326 completion = [ prefix + f
327 for f in os.listdir(base_dir)
328 if f.startswith(text) and \
329 os.path.isfile(os.path.join(base_dir, f)) and \
330 (not f.startswith('.') or text.startswith('.'))
331 ]
332
333 completion = completion + \
334 [prefix + f + os.path.sep
335 for f in os.listdir(base_dir)
336 if f.startswith(text) and \
337 os.path.isdir(os.path.join(base_dir, f)) and \
338 (not f.startswith('.') or text.startswith('.'))
339 ]
340
341 if relative:
342 completion += [prefix + f for f in ['.'+os.path.sep, '..'+os.path.sep] if \
343 f.startswith(text) and not prefix.startswith('.')]
344
345 completion = [a.replace(' ','\ ') for a in completion]
346 return completion
347
352 """Extension of the cmd object for only the check command"""
353
354 - def check_history(self, args):
355 """check the validity of line"""
356
357 if len(args) > 1:
358 self.help_history()
359 raise self.InvalidCmd('\"history\" command takes at most one argument')
360
361 if not len(args):
362 return
363
364 if args[0] =='.':
365 if not self._export_dir:
366 raise self.InvalidCmd("No default directory is defined for \'.\' option")
367 elif args[0] != 'clean':
368 dirpath = os.path.dirname(args[0])
369 if dirpath and not os.path.exists(dirpath) or \
370 os.path.isdir(args[0]):
371 raise self.InvalidCmd("invalid path %s " % dirpath)
372
374 """check that the line is compatible with save options"""
375
376 if len(args) > 2:
377 self.help_save()
378 raise self.InvalidCmd, 'too many arguments for save command.'
379
380 if len(args) == 2:
381 if args[0] != 'options':
382 self.help_save()
383 raise self.InvalidCmd, '\'%s\' is not recognized as first argument.' % \
384 args[0]
385 else:
386 args.pop(0)
387
389 """Extension of the cmd object for only the help command"""
390
392 logger.info("-- terminates the application",'$MG:color:BLUE')
393 logger.info("syntax: quit",'$MG:color:BLACK')
394
395 help_EOF = help_quit
396
397 - def help_history(self):
398 logger.info("-- interact with the command history.",'$MG:color:BLUE')
399 logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:color:BLACK')
400 logger.info(" > If FILEPATH is \'.\' and \'output\' is done,")
401 logger.info(" Cards/proc_card_mg5.dat will be used.")
402 logger.info(" > If FILEPATH is omitted, the history will be output to stdout.")
403 logger.info(" \"clean\" will remove all entries from the history.")
404
406 logger.info("-- access to the in-line help",'$MG:color:BLUE')
407 logger.info("syntax: help",'$MG:color:BLACK')
408
410 """help text for save"""
411 logger.info("-- save options configuration to filepath.",'$MG:color:BLUE')
412 logger.info("syntax: save [options] [FILEPATH]",'$MG:color:BLACK')
413
415 """help for display command"""
416 logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE')
417 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLACK')
418
427
428 - def complete_history(self, text, line, begidx, endidx):
429 "Complete the history command"
430
431 args = self.split_arg(line[0:begidx])
432
433
434 if args[-1].endswith(os.path.sep):
435 return self.path_completion(text,
436 os.path.join('.',*[a for a in args \
437 if a.endswith(os.path.sep)]))
438
439 if len(args) == 1:
440 return self.path_completion(text)
441
443 "Complete the save command"
444
445 args = self.split_arg(line[0:begidx])
446
447
448 if len(args) == 1:
449 return self.list_completion(text, ['options'])
450
451
452 if args[-1].endswith(os.path.sep):
453 return self.path_completion(text,
454 pjoin('.',*[a for a in args if a.endswith(os.path.sep)]),
455 only_dirs = True)
456
457
458 if len(args) == 2:
459 return self.path_completion(text)
460
461 -class Cmd(CheckCmd, HelpCmd, CompleteCmd, BasicCmd):
462 """Extension of the cmd.Cmd command line.
463 This extensions supports line breaking, history, comments,
464 internal call to cmdline, path completion,...
465 this class should be MG5 independent"""
466
467
468 next_possibility = {}
469 history_header = ""
470
471 _display_opts = ['options','variable']
472 allow_notification_center = True
473
475 """expected error for wrong command"""
476 pass
477
478 ConfigurationError = InvalidCmd
479
480 debug_output = 'debug'
481 error_debug = """Please report this bug to developers\n
482 More information is found in '%(debug)s'.\n
483 Please attach this file to your report."""
484 config_debug = error_debug
485
486 keyboard_stop_msg = """stopping all current operation
487 in order to quit the program please enter exit"""
488
489
491 """Init history and line continuation"""
492
493 self.log = True
494 self.history = []
495 self.save_line = ''
496 cmd.Cmd.__init__(self, *arg, **opt)
497 self.__initpos = os.path.abspath(os.getcwd())
498 self.child = None
499 self.mother = None
500 self.inputfile = None
501 self.haspiping = not sys.stdin.isatty()
502 self.stored_line = ''
503
504 if not hasattr(self, 'helporder'):
505 self.helporder = ['Documented commands']
506
508 """Hook method executed once when the cmdloop() method is called."""
509 if self.completekey:
510 try:
511 import readline
512 self.old_completer = readline.get_completer()
513 readline.set_completer(self.complete)
514 readline.parse_and_bind(self.completekey+": complete")
515 except ImportError:
516 pass
517 if readline and not 'libedit' in readline.__doc__:
518 readline.set_completion_display_matches_hook(self.print_suggestions)
519
520
522
523 self.preloop()
524 if intro is not None:
525 self.intro = intro
526 if self.intro:
527 print self.intro
528 stop = None
529 while not stop:
530 if self.cmdqueue:
531 line = self.cmdqueue[0]
532 del self.cmdqueue[0]
533 else:
534 if self.use_rawinput:
535 try:
536 line = raw_input(self.prompt)
537 except EOFError:
538 line = 'EOF'
539 else:
540 sys.stdout.write(self.prompt)
541 sys.stdout.flush()
542 line = sys.stdin.readline()
543 if not len(line):
544 line = 'EOF'
545 else:
546 line = line[:-1]
547 try:
548 line = self.precmd(line)
549 stop = self.onecmd(line)
550 except BaseException, error:
551 self.error_handling(error, line)
552 if isinstance(error, KeyboardInterrupt):
553 stop = True
554 finally:
555 stop = self.postcmd(stop, line)
556 self.postloop()
557
559 """avoid to have html opening / notification"""
560 self.allow_notification_center = False
561 try:
562 self.options['automatic_html_opening'] = False
563 self.options['notification_center'] = False
564
565 except:
566 pass
567
568
570 """ A suite of additional function needed for in the cmd
571 this implement history, line breaking, comment treatment,...
572 """
573
574 if not line:
575 return line
576
577
578 if self.save_line:
579 line = self.save_line + line
580 self.save_line = ''
581
582 line = line.lstrip()
583
584 if line.endswith('\\'):
585 self.save_line = line[:-1]
586 return ''
587
588
589 if '#' in line:
590 line = line.split('#')[0]
591
592
593 if ';' in line:
594 lines = line.split(';')
595 for subline in lines:
596 if not (subline.startswith("history") or subline.startswith('help') \
597 or subline.startswith('#*')):
598 self.history.append(subline)
599 stop = self.onecmd_orig(subline)
600 stop = self.postcmd(stop, subline)
601 return ''
602
603
604 self.history.append(line)
605 return line
606
607 - def postcmd(self,stop, line):
608 """ finishing a command
609 This looks if the command add a special post part."""
610
611 if line.strip():
612 try:
613 cmd, subline = line.split(None, 1)
614 except ValueError:
615 pass
616 else:
617 if hasattr(self,'post_%s' %cmd):
618 stop = getattr(self, 'post_%s' % cmd)(stop, subline)
619 return stop
620
622 """Define a sub cmd_interface"""
623
624
625 self.child = obj_instance
626 self.child.mother = self
627
628
629 self.child.allow_notification_center = self.allow_notification_center
630
631 if self.use_rawinput and interface:
632
633 obj_instance.cmdloop()
634 stop = obj_instance.postloop()
635 return stop
636 if self.inputfile:
637
638 obj_instance.inputfile = self.inputfile
639
640 obj_instance.haspiping = self.haspiping
641
642 if not interface:
643 return self.child
644
645
646
647
648 - def ask(self, question, default, choices=[], path_msg=None,
649 timeout = True, fct_timeout=None, ask_class=None, alias={},
650 first_cmd=None, text_format='4', **opt):
651 """ ask a question with some pre-define possibility
652 path info is
653 """
654
655 if path_msg:
656 path_msg = [path_msg]
657 else:
658 path_msg = []
659
660 if timeout:
661 try:
662 timeout = self.options['timeout']
663 except Exception:
664 pass
665
666
667 if choices + path_msg:
668 question += ' ['
669 question += "\033[%sm%s\033[0m, " % (text_format, default)
670 for data in choices[:9] + path_msg:
671 if default == data:
672 continue
673 else:
674 question += "%s, " % data
675
676 if len(choices) > 9:
677 question += '... , '
678 question = question[:-2]+']'
679 else:
680 question += "[\033[%sm%s\033[0m] " % (text_format, default)
681 if ask_class:
682 obj = ask_class
683 elif path_msg:
684 obj = OneLinePathCompletion
685 else:
686 obj = SmartQuestion
687
688 if alias:
689 choices += alias.keys()
690
691 question_instance = obj(question, allow_arg=choices, default=default,
692 mother_interface=self, **opt)
693
694 if first_cmd:
695 if isinstance(first_cmd, str):
696 question_instance.onecmd(first_cmd)
697 else:
698 for line in first_cmd:
699 question_instance.onecmd(line)
700 if not self.haspiping:
701 if hasattr(obj, "haspiping"):
702 obj.haspiping = self.haspiping
703
704
705
706
707 answer = self.check_answer_in_input_file(question_instance, default, path_msg)
708 if answer is not None:
709 if answer in alias:
710 answer = alias[answer]
711 if ask_class:
712 answer = question_instance.default(answer)
713 if hasattr(question_instance, 'check_answer_consistency'):
714 question_instance.check_answer_consistency()
715 return answer
716
717 question = question_instance.question
718 value = Cmd.timed_input(question, default, timeout=timeout,
719 fct=question_instance, fct_timeout=fct_timeout)
720
721 try:
722 if value in alias:
723 value = alias[value]
724 except TypeError:
725 pass
726 if value == default and ask_class:
727 value = question_instance.default(default)
728 return value
729
739
741 """check import command"""
742
743 if '-f' in args:
744 self.force = True
745 args.remove('-f')
746 if args[0] != 'command':
747 args.set(0, 'command')
748 if len(args) != 2:
749 raise self.InvalidCmd('import command requires one filepath argument')
750 if not os.path.exists(args[1]):
751 raise 'No such file or directory %s' % args[1]
752
753
809
811 """store a line of the input file which should be executed by the higher mother"""
812
813 if self.mother:
814 self.mother.store_line(line)
815 else:
816 self.stored_line = line
817
819 """return stored line and clean it"""
820 if self.mother:
821 value = self.mother.get_stored_line()
822 self.mother.stored_line = None
823 else:
824 value = self.stored_line
825 self.stored_line = None
826 return value
827
828
829
831 """ """
832
833 if self.child:
834 return self.child.nice_error_handling(error, line)
835
836 os.chdir(self.__initpos)
837
838 self.log = False
839 if os.path.exists(self.debug_output):
840 os.remove(self.debug_output)
841 try:
842 cmd.Cmd.onecmd(self, 'history %s' % self.debug_output.replace(' ', '\ '))
843 except Exception, error:
844 logger.error(error)
845
846 debug_file = open(self.debug_output, 'a')
847 traceback.print_exc(file=debug_file)
848
849 if self.history and line == self.history[-1]:
850 error_text = 'Command \"%s\" interrupted with error:\n' % line
851 elif self.history:
852 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
853 error_text += '\"%s\" with error:\n' % self.history[-1]
854 else:
855 error_text = ''
856 error_text += '%s : %s\n' % (error.__class__.__name__,
857 str(error).replace('\n','\n\t'))
858 error_text += self.error_debug % {'debug':self.debug_output}
859 logger_stderr.critical(error_text)
860
861
862
863 try:
864 self.do_display('options', debug_file)
865 except Exception, error:
866 debug_file.write('Fail to write options with error %s' % error)
867
868
869 for card in ['proc_card_mg5.dat','param_card.dat', 'run_card.dat']:
870 try:
871 ff = open(pjoin(self.me_dir, 'Cards', card))
872 debug_file.write(ff.read())
873 ff.close()
874 except Exception:
875 pass
876
877
878 if self.use_rawinput == False:
879 return True
880 return False
881
882
883
885 if self.child:
886 return self.child.nice_user_error(error, line)
887
888 os.chdir(self.__initpos)
889 if line == self.history[-1]:
890 error_text = 'Command \"%s\" interrupted with error:\n' % line
891 else:
892 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
893 error_text += '\"%s\" with error:\n' % self.history[-1]
894 error_text += '%s : %s' % (error.__class__.__name__,
895 str(error).replace('\n','\n\t'))
896 logger_stderr.error(error_text)
897
898 if self.use_rawinput == False:
899 return True
900
901 self.history.pop()
902 return False
903
905 if self.child:
906 return self.child.nice_user_error(error, line)
907
908 os.chdir(self.__initpos)
909 if not self.history or line == self.history[-1]:
910 error_text = 'Error detected in \"%s\"\n' % line
911 else:
912 error_text = 'Error detected in sub-command %s\n' % self.history[-1]
913 error_text += 'write debug file %s \n' % self.debug_output
914 self.log = False
915 cmd.Cmd.onecmd(self, 'history %s' % self.debug_output)
916 debug_file = open(self.debug_output, 'a')
917 traceback.print_exc(file=debug_file)
918 error_text += self.config_debug % {'debug' :self.debug_output}
919 error_text += '%s : %s' % (error.__class__.__name__,
920 str(error).replace('\n','\n\t'))
921 logger_stderr.error(error_text)
922
923
924 try:
925 self.do_display('options', debug_file)
926 except Exception, error:
927 debug_file.write('Fail to write options with error %s' % error)
928
929 if self.use_rawinput == False:
930 return True
931
932 if self.history:
933 self.history.pop()
934 return False
935
937 """Interpret the argument as though it had been typed in response
938 to the prompt.
939
940 The return value is a flag indicating whether interpretation of
941 commands by the interpreter should stop.
942
943 This allow to pass extra argument for internal call.
944 """
945 if '~/' in line and os.environ.has_key('HOME'):
946 line = line.replace('~/', '%s/' % os.environ['HOME'])
947 if '#' in line:
948 line = line.split('#')[0]
949
950 line = os.path.expandvars(line)
951 cmd, arg, line = self.parseline(line)
952 if not line:
953 return self.emptyline()
954 if cmd is None:
955 return self.default(line)
956 self.lastcmd = line
957 if cmd == '':
958 return self.default(line)
959 else:
960 try:
961 func = getattr(self, 'do_' + cmd)
962 except AttributeError:
963 return self.default(line)
964 return func(arg, **opt)
965
1002
1003
1004
1005 - def onecmd(self, line, **opt):
1006 """catch all error and stop properly command accordingly"""
1007
1008 try:
1009 return self.onecmd_orig(line, **opt)
1010 except BaseException, error:
1011 self.error_handling(error, line)
1012
1013
1015 """action to perform to close nicely on a keyboard interupt"""
1016 pass
1017
1018 - def exec_cmd(self, line, errorhandling=False, printcmd=True,
1019 precmd=False, postcmd=True, **opt):
1039
1041 """for third party call, call the line with pre and postfix treatment
1042 with global error handling"""
1043
1044 return self.exec_cmd(line, errorhandling=True, precmd=True)
1045
1047 """If empty line, do nothing. Default is repeat previous command."""
1048 pass
1049
1050 - def default(self, line, log=True):
1051 """Default action if line is not recognized"""
1052
1053
1054 if log:
1055 logger.warning("Command \"%s\" not recognized, please try again" % \
1056 line.split()[0])
1057 if line.strip() in ['q', '.q', 'stop']:
1058 logger.info("If you want to quit mg5 please type \"exit\".")
1059
1060 if self.history and self.history[-1] == line:
1061 self.history.pop()
1062
1063
1064
1065
1066
1067
1068 - def do_history(self, line):
1069 """write in a file the suite of command that was used"""
1070
1071 args = self.split_arg(line)
1072
1073 self.check_history(args)
1074
1075 if len(args) == 0:
1076 logger.info('\n'.join(self.history))
1077 return
1078 elif args[0] == 'clean':
1079 self.history = []
1080 logger.info('History is cleaned')
1081 return
1082 elif args[0] == '.':
1083 output_file = os.path.join(self._export_dir, 'Cards', \
1084 'proc_card_mg5.dat')
1085 output_file = open(output_file, 'w')
1086 else:
1087 output_file = open(args[0], 'w')
1088
1089
1090 text = self.get_history_header()
1091 text += ('\n'.join(self.history) + '\n')
1092
1093
1094 output_file.write(text)
1095 output_file.close()
1096
1097 if self.log:
1098 logger.info("History written to " + output_file.name)
1099
1100 - def compile(self, *args, **opts):
1104
1105 - def avoid_history_duplicate(self, line, no_break=[]):
1106 """remove all line in history (but the last) starting with line.
1107 up to the point when a line didn't start by something in no_break.
1108 (reading in reverse order)"""
1109
1110 new_history = []
1111 for i in range(1, len(self.history)+1):
1112 cur_line = self.history[-i]
1113 if i == 1:
1114 new_history.append(cur_line)
1115 elif not any((cur_line.startswith(text) for text in no_break)):
1116 to_add = self.history[:-i+1]
1117 to_add.reverse()
1118 new_history += to_add
1119 break
1120 elif cur_line.startswith(line):
1121 continue
1122 else:
1123 new_history.append(cur_line)
1124
1125 new_history.reverse()
1126 self.history[:] = new_history
1127
1128
1130
1131 if self.history:
1132 self.history.pop()
1133
1134
1135 previous_store_line = self.get_stored_line()
1136
1137
1138 if isinstance(filepath, str):
1139 commandline = open(filepath).readlines()
1140 else:
1141 commandline = filepath
1142 oldinputfile = self.inputfile
1143 oldraw = self.use_rawinput
1144 self.inputfile = (l for l in commandline)
1145 self.use_rawinput = False
1146
1147
1148
1149 for line in self.inputfile:
1150
1151 line = line.replace('\n', '').strip()
1152
1153 if line:
1154 self.exec_cmd(line, precmd=True)
1155 stored = self.get_stored_line()
1156 while stored:
1157 line = stored
1158 self.exec_cmd(line, precmd=True)
1159 stored = self.get_stored_line()
1160
1161
1162 if self.child:
1163 self.child.exec_cmd('quit')
1164 self.inputfile = oldinputfile
1165 self.use_rawinput = oldraw
1166
1167
1168 cmd = self
1169 while hasattr(cmd, 'mother') and cmd.mother:
1170 cmd = cmd.mother
1171 cmd.stored_line = previous_store_line
1172 return
1173
1175 """Default history header"""
1176
1177 return self.history_header
1178
1179 - def postloop(self):
1180 """ """
1181
1182 args = self.split_arg(self.lastcmd)
1183 if args and args[0] in ['quit','exit']:
1184 if 'all' in args:
1185 return True
1186 if len(args) >1 and args[1].isdigit():
1187 if args[1] not in ['0', '1']:
1188 return True
1189 return False
1190
1191
1192
1193
1194 @staticmethod
1201
1202 signal.signal(signal.SIGALRM, handle_alarm)
1203
1204 if fct is None:
1205 fct = raw_input
1206
1207 if timeout:
1208 signal.alarm(timeout)
1209 question += '[%ss to answer] ' % (timeout)
1210 try:
1211 result = fct(question)
1212 except TimeOutError:
1213 if noerror:
1214 logger.info('\nuse %s' % default)
1215 if fct_timeout:
1216 fct_timeout(True)
1217 return default
1218 else:
1219 signal.alarm(0)
1220 raise
1221 finally:
1222 signal.alarm(0)
1223 if fct_timeout:
1224 fct_timeout(False)
1225 return result
1226
1227
1228
1229
1230
1231
1232
1234 """Not in help: exit the mainloop() """
1235
1236 if self.child:
1237 self.child.exec_cmd('quit ' + line, printcmd=False)
1238 return
1239 elif self.mother:
1240 self.mother.child = None
1241 if line == 'all':
1242 pass
1243 elif line:
1244 level = int(line) - 1
1245 if level:
1246 self.mother.lastcmd = 'quit %s' % level
1247 logger.info(' ')
1248 return True
1249
1250
1251 do_EOF = do_quit
1252 do_exit = do_quit
1253
1255 """Not in help: propose some usefull possible action """
1256
1257
1258 if line:
1259 return cmd.Cmd.do_help(self, line)
1260
1261
1262 names = self.get_names()
1263 cmds = {}
1264 names.sort()
1265
1266 prevname = ''
1267 for name in names:
1268 if name[:3] == 'do_':
1269 if name == prevname:
1270 continue
1271 prevname = name
1272 cmdname=name[3:]
1273 try:
1274 doc = getattr(self.cmd, name).__doc__
1275 except Exception:
1276 doc = None
1277 if not doc:
1278 doc = getattr(self, name).__doc__
1279 if not doc:
1280 tag = "Documented commands"
1281 elif ':' in doc:
1282 tag = doc.split(':',1)[0]
1283 else:
1284 tag = "Documented commands"
1285 if tag in cmds:
1286 cmds[tag].append(cmdname)
1287 else:
1288 cmds[tag] = [cmdname]
1289
1290 self.stdout.write("%s\n"%str(self.doc_leader))
1291 for tag in self.helporder:
1292 if tag not in cmds:
1293 continue
1294 header = "%s (type help <topic>):" % tag
1295 self.print_topics(header, cmds[tag], 15,80)
1296 for name, item in cmds.items():
1297 if name in self.helporder:
1298 continue
1299 if name == "Not in help":
1300 continue
1301 header = "%s (type help <topic>):" % name
1302 self.print_topics(header, item, 15,80)
1303
1304
1305
1306 if len(self.history) == 0:
1307 last_action_2 = last_action = 'start'
1308 else:
1309 last_action_2 = last_action = 'none'
1310
1311 pos = 0
1312 authorize = self.next_possibility.keys()
1313 while last_action_2 not in authorize and last_action not in authorize:
1314 pos += 1
1315 if pos > len(self.history):
1316 last_action_2 = last_action = 'start'
1317 break
1318
1319 args = self.history[-1 * pos].split()
1320 last_action = args[0]
1321 if len(args)>1:
1322 last_action_2 = '%s %s' % (last_action, args[1])
1323 else:
1324 last_action_2 = 'none'
1325
1326 logger.info('Contextual Help')
1327 logger.info('===============')
1328 if last_action_2 in authorize:
1329 options = self.next_possibility[last_action_2]
1330 elif last_action in authorize:
1331 options = self.next_possibility[last_action]
1332 else:
1333 return
1334 text = 'The following command(s) may be useful in order to continue.\n'
1335 for option in options:
1336 text+='\t %s \n' % option
1337 logger.info(text)
1338
1340 """Advanced commands: basic display"""
1341
1342 args = self.split_arg(line)
1343
1344
1345 if len(args) == 0:
1346 self.help_display()
1347 raise self.InvalidCmd, 'display require at least one argument'
1348
1349 if args[0] == "options":
1350 outstr = "Value of current Options:\n"
1351 for key, value in self.options.items():
1352 outstr += '%25s \t:\t%s\n' %(key,value)
1353 output.write(outstr)
1354
1355 elif args[0] == "variable":
1356 outstr = "Value of Internal Variable:\n"
1357 try:
1358 var = eval(args[1])
1359 except Exception:
1360 outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1]
1361 else:
1362 outstr += 'GLOBAL:\n'
1363 outstr += misc.nice_representation(var, nb_space=4)
1364
1365 try:
1366 var = eval('self.%s' % args[1])
1367 except Exception:
1368 outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1]
1369 else:
1370 outstr += 'LOCAL:\n'
1371 outstr += misc.nice_representation(var, nb_space=4)
1372 split = args[1].split('.')
1373 for i, name in enumerate(split):
1374 try:
1375 __import__('.'.join(split[:i+1]))
1376 exec('%s=sys.modules[\'%s\']' % (split[i], '.'.join(split[:i+1])))
1377 except ImportError:
1378 try:
1379 var = eval(args[1])
1380 except Exception, error:
1381 outstr += 'EXTERNAL:\nVariable %s is not a external variable\n' % args[1]
1382 break
1383 else:
1384 outstr += 'EXTERNAL:\n'
1385 outstr += misc.nice_representation(var, nb_space=4)
1386 else:
1387 var = eval(args[1])
1388 outstr += 'EXTERNAL:\n'
1389 outstr += misc.nice_representation(var, nb_space=4)
1390
1391 pydoc.pager(outstr)
1392
1393
1394 - def do_save(self, line, check=True):
1395 """Save the configuration file"""
1396
1397 args = self.split_arg(line)
1398
1399 if check:
1400 Cmd.check_save(self, args)
1401
1402
1403 if'HOME' in os.environ and os.environ['HOME'] and \
1404 os.path.exists(pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')):
1405 base = pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')
1406 if hasattr(self, 'me_dir'):
1407 basedir = self.me_dir
1408 elif not MADEVENT:
1409 basedir = MG5DIR
1410 else:
1411 basedir = os.getcwd()
1412 elif MADEVENT:
1413
1414 for config_file in ['me5_configuration.txt', 'amcatnlo_configuration.txt']:
1415 if os.path.exists(pjoin(self.me_dir, 'Cards', config_file)):
1416 base = pjoin(self.me_dir, 'Cards', config_file)
1417 basedir = self.me_dir
1418 else:
1419 if hasattr(self, 'me_dir'):
1420 base = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1421 if len(args) == 0 and os.path.exists(base):
1422 self.write_configuration(base, base, self.me_dir)
1423 base = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
1424 basedir = MG5DIR
1425
1426 if len(args) == 0:
1427 args.append(base)
1428 self.write_configuration(args[0], base, basedir, self.options)
1429
1431 """Write the configuration file"""
1432
1433
1434
1435
1436 logger.info('save configuration file to %s' % filepath)
1437 to_write = to_keep.keys()
1438 text = ""
1439
1440 for line in file(basefile):
1441 if '=' in line:
1442 data, value = line.split('=',1)
1443 else:
1444 text += line
1445 continue
1446 data = data.strip()
1447 if data.startswith('#'):
1448 key = data[1:].strip()
1449 else:
1450 key = data
1451 if '#' in value:
1452 value, comment = value.split('#',1)
1453 else:
1454 comment = ''
1455 if key in to_keep:
1456 value = str(to_keep[key])
1457 else:
1458 text += line
1459 continue
1460 try:
1461 to_write.remove(key)
1462 except Exception:
1463 pass
1464 if '_path' in key:
1465
1466
1467 if not os.path.isabs(value):
1468 value = os.path.realpath(os.path.join(basedir, value))
1469 text += '%s = %s # %s \n' % (key, value, comment)
1470 for key in to_write:
1471 if key in to_keep:
1472 text += '%s = %s \n' % (key, to_keep[key])
1473
1474 if not MADEVENT:
1475 text += """\n# MG5 MAIN DIRECTORY\n"""
1476 text += "mg5_path = %s\n" % MG5DIR
1477
1478 writer = open(filepath,'w')
1479 writer.write(text)
1480 writer.close()
1481
1486 """CMD command with shell activate"""
1487
1488
1490 "Run a shell command"
1491
1492 if line.strip() is '':
1493 self.help_shell()
1494 else:
1495 logging.info("running shell command: " + line)
1496 subprocess.call(line, shell=True)
1497
1499 """ add path for shell """
1500
1501
1502
1503 if len(self.split_arg(line[0:begidx])) > 1 and line[begidx - 1] == os.path.sep:
1504 if not text:
1505 text = ''
1506 output = self.path_completion(text,
1507 base_dir=\
1508 self.split_arg(line[0:begidx])[-1])
1509 else:
1510 output = self.path_completion(text)
1511 return output
1512
1514 """help for the shell"""
1515 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')
1516 logger.info("syntax: shell CMD (or ! CMD)",'$MG:color:BLACK')
1517
1525 """ a class for answering a question with the path autocompletion"""
1526
1528 """Initializing before starting the main loop"""
1529 self.prompt = '>'
1530 self.value = None
1531 BasicCmd.preloop(self)
1532
1533
1534 - def __init__(self, question, allow_arg=[], default=None,
1535 mother_interface=None, *arg, **opt):
1536 self.question = question
1537 self.wrong_answer = 0
1538 self.allow_arg = [str(a) for a in allow_arg]
1539 self.history_header = ''
1540 self.default_value = str(default)
1541 self.mother_interface = mother_interface
1542 cmd.Cmd.__init__(self, *arg, **opt)
1543
1544 - def __call__(self, question, reprint_opt=True, **opts):
1545
1546 self.question = question
1547 for key,value in opts:
1548 setattr(self, key, value)
1549 if reprint_opt:
1550 print question
1551 return self.cmdloop()
1552
1553
1555 prev_timer = signal.alarm(0)
1556 if prev_timer:
1557 nb_back = len(line)
1558 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
1559 self.stdout.write(line)
1560 self.stdout.flush()
1561 try:
1562 out = {}
1563 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
1564 out[' Recognized command'] = BasicCmd.completenames(self, text)
1565
1566 return self.deal_multiple_categories(out)
1567 except Exception, error:
1568 print error
1569
1571
1572
1573 return dir(self)
1574
1575 - def onecmd(self, line, **opt):
1576 """catch all error and stop properly command accordingly
1577 Interpret the argument as though it had been typed in response
1578 to the prompt.
1579
1580 The return value is a flag indicating whether interpretation of
1581 commands by the interpreter should stop.
1582
1583 This allow to pass extra argument for internal call.
1584 """
1585 try:
1586 if '~/' in line and os.environ.has_key('HOME'):
1587 line = line.replace('~/', '%s/' % os.environ['HOME'])
1588 line = os.path.expandvars(line)
1589 cmd, arg, line = self.parseline(line)
1590 if not line:
1591 return self.emptyline()
1592 if cmd is None:
1593 return self.default(line)
1594 self.lastcmd = line
1595 if cmd == '':
1596 return self.default(line)
1597 else:
1598 try:
1599 func = getattr(self, 'do_' + cmd)
1600 except AttributeError:
1601 return self.default(line)
1602 return func(arg, **opt)
1603 except Exception as error:
1604 logger.warning(error)
1605
1606 - def reask(self, reprint_opt=True):
1607 pat = re.compile('\[(\d*)s to answer\]')
1608 prev_timer = signal.alarm(0)
1609
1610 if prev_timer:
1611 if pat.search(self.question):
1612 timeout = int(pat.search(self.question).groups()[0])
1613 else:
1614 timeout=20
1615 print
1616 signal.alarm(timeout)
1617 if reprint_opt:
1618 if not prev_timer:
1619 self.question = pat.sub('',self.question)
1620 print self.question
1621 return False
1622
1624 """Default action if line is not recognized"""
1625
1626 if line.strip() == '' and self.default_value is not None:
1627 self.value = self.default_value
1628 else:
1629 self.value = line
1630
1632 """If empty line, return default"""
1633
1634 if self.default_value is not None:
1635 self.value = self.default_value
1636
1637
1638 - def postcmd(self, stop, line):
1639
1640 try:
1641 if self.value in self.allow_arg:
1642 return True
1643 elif str(self.value) == 'EOF':
1644 self.value = self.default_value
1645 return True
1646 elif line and hasattr(self, 'do_%s' % line.split()[0]):
1647 return self.reask()
1648 elif self.value == 'repeat':
1649 return self.reask()
1650 elif len(self.allow_arg)==0:
1651 return True
1652 else:
1653 raise Exception
1654 except Exception,error:
1655 if self.wrong_answer < 100:
1656 self.wrong_answer += 1
1657 logger.warning("""%s not valid argument. Valid argument are in (%s).""" \
1658 % (self.value,','.join(self.allow_arg)))
1659 logger.warning('please retry')
1660 return False
1661 else:
1662 self.value = self.default_value
1663 return True
1664
1666 cmd.Cmd.cmdloop(self, intro)
1667 return self.value
1668
1674
1679 """ a class for answering a question with the path autocompletion"""
1680
1681 completion_prefix=''
1682
1684 prev_timer = signal.alarm(0)
1685 if prev_timer:
1686 nb_back = len(line)
1687 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
1688 self.stdout.write(line)
1689 self.stdout.flush()
1690
1691 try:
1692 out = {}
1693 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
1694 out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False)
1695 out[' Recognized command'] = BasicCmd.completenames(self, text)
1696
1697 return self.deal_multiple_categories(out)
1698 except Exception, error:
1699 print error
1700
1706
1708 prev_timer = signal.alarm(0)
1709 if prev_timer:
1710 nb_back = len(line)
1711 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
1712 self.stdout.write(line)
1713 self.stdout.flush()
1714 try:
1715 args = Cmd.split_arg(line[0:begidx])
1716 except Exception, error:
1717 print error
1718
1719
1720 if args[-1].endswith(os.path.sep):
1721
1722 return Cmd.path_completion(text,
1723 os.path.join('.',*[a for a in args \
1724 if a.endswith(os.path.sep)]))
1725 self.completenames(line+text)
1726
1727
1728 - def postcmd(self, stop, line):
1729 try:
1730 if self.value in self.allow_arg:
1731 return True
1732 elif self.value and os.path.isfile(self.value):
1733 return os.path.relpath(self.value)
1734 elif self.value and str(self.value) == 'EOF':
1735 self.value = self.default_value
1736 return True
1737 elif line and hasattr(self, 'do_%s' % line.split()[0]):
1738
1739 reprint_opt = True
1740 elif self.value == 'repeat':
1741 reprint_opt = True
1742 else:
1743 raise Exception
1744 except Exception, error:
1745 print """not valid argument. Valid argument are file path or value in (%s).""" \
1746 % ','.join(self.allow_arg)
1747 print 'please retry'
1748 reprint_opt = False
1749
1750 return self.reask(reprint_opt)
1751
1758
1759
1760
1761
1762 -class CmdFile(file):
1763 """ a class for command input file -in order to debug cmd \n problem"""
1764
1771
1773 """readline method treating correctly a line whithout \n at the end
1774 (add it)
1775 """
1776 if self.lines:
1777 line = self.lines.pop(0)
1778 else:
1779 return ''
1780
1781 if line.endswith('\n'):
1782 return line
1783 else:
1784 return line + '\n'
1785
1788
1791