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 if hasattr(error, 'filename'):
849 debug_file.write("Related File: %s\n" % error.filename)
850
851 if self.history and line == self.history[-1]:
852 error_text = 'Command \"%s\" interrupted with error:\n' % line
853 elif self.history:
854 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
855 error_text += '\"%s\" with error:\n' % self.history[-1]
856 else:
857 error_text = ''
858 error_text += '%s : %s\n' % (error.__class__.__name__,
859 str(error).replace('\n','\n\t'))
860 error_text += self.error_debug % {'debug':self.debug_output}
861 logger_stderr.critical(error_text)
862
863
864
865 try:
866 self.do_display('options', debug_file)
867 except Exception, error:
868 debug_file.write('Fail to write options with error %s' % error)
869
870
871 for card in ['proc_card_mg5.dat','param_card.dat', 'run_card.dat']:
872 try:
873 ff = open(pjoin(self.me_dir, 'Cards', card))
874 debug_file.write(ff.read())
875 ff.close()
876 except Exception:
877 pass
878
879
880 if self.use_rawinput == False:
881 return True
882 return False
883
884
885
887 if self.child:
888 return self.child.nice_user_error(error, line)
889
890 os.chdir(self.__initpos)
891 if line == self.history[-1]:
892 error_text = 'Command \"%s\" interrupted with error:\n' % line
893 else:
894 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
895 error_text += '\"%s\" with error:\n' % self.history[-1]
896 error_text += '%s : %s' % (error.__class__.__name__,
897 str(error).replace('\n','\n\t'))
898 logger_stderr.error(error_text)
899
900 if self.use_rawinput == False:
901 return True
902
903 self.history.pop()
904 return False
905
907 if self.child:
908 return self.child.nice_user_error(error, line)
909
910 os.chdir(self.__initpos)
911 if not self.history or line == self.history[-1]:
912 error_text = 'Error detected in \"%s\"\n' % line
913 else:
914 error_text = 'Error detected in sub-command %s\n' % self.history[-1]
915 error_text += 'write debug file %s \n' % self.debug_output
916 self.log = False
917 cmd.Cmd.onecmd(self, 'history %s' % self.debug_output)
918 debug_file = open(self.debug_output, 'a')
919 traceback.print_exc(file=debug_file)
920 error_text += self.config_debug % {'debug' :self.debug_output}
921 error_text += '%s : %s' % (error.__class__.__name__,
922 str(error).replace('\n','\n\t'))
923 logger_stderr.error(error_text)
924
925
926 try:
927 self.do_display('options', debug_file)
928 except Exception, error:
929 debug_file.write('Fail to write options with error %s' % error)
930
931 if self.use_rawinput == False:
932 return True
933
934 if self.history:
935 self.history.pop()
936 return False
937
939 """Interpret the argument as though it had been typed in response
940 to the prompt.
941
942 The return value is a flag indicating whether interpretation of
943 commands by the interpreter should stop.
944
945 This allow to pass extra argument for internal call.
946 """
947 if '~/' in line and os.environ.has_key('HOME'):
948 line = line.replace('~/', '%s/' % os.environ['HOME'])
949 if '#' in line:
950 line = line.split('#')[0]
951
952 line = os.path.expandvars(line)
953 cmd, arg, line = self.parseline(line)
954 if not line:
955 return self.emptyline()
956 if cmd is None:
957 return self.default(line)
958 self.lastcmd = line
959 if cmd == '':
960 return self.default(line)
961 else:
962 try:
963 func = getattr(self, 'do_' + cmd)
964 except AttributeError:
965 return self.default(line)
966 return func(arg, **opt)
967
1004
1005
1006
1007 - def onecmd(self, line, **opt):
1008 """catch all error and stop properly command accordingly"""
1009
1010 try:
1011 return self.onecmd_orig(line, **opt)
1012 except BaseException, error:
1013 self.error_handling(error, line)
1014
1015
1017 """action to perform to close nicely on a keyboard interupt"""
1018 pass
1019
1020 - def exec_cmd(self, line, errorhandling=False, printcmd=True,
1021 precmd=False, postcmd=True, **opt):
1041
1043 """for third party call, call the line with pre and postfix treatment
1044 with global error handling"""
1045
1046 return self.exec_cmd(line, errorhandling=True, precmd=True)
1047
1049 """If empty line, do nothing. Default is repeat previous command."""
1050 pass
1051
1052 - def default(self, line, log=True):
1053 """Default action if line is not recognized"""
1054
1055
1056 if log:
1057 logger.warning("Command \"%s\" not recognized, please try again" % \
1058 line.split()[0])
1059 if line.strip() in ['q', '.q', 'stop']:
1060 logger.info("If you want to quit mg5 please type \"exit\".")
1061
1062 if self.history and self.history[-1] == line:
1063 self.history.pop()
1064
1065
1066
1067
1068
1069
1070 - def do_history(self, line):
1071 """write in a file the suite of command that was used"""
1072
1073 args = self.split_arg(line)
1074
1075 self.check_history(args)
1076
1077 if len(args) == 0:
1078 logger.info('\n'.join(self.history))
1079 return
1080 elif args[0] == 'clean':
1081 self.history = []
1082 logger.info('History is cleaned')
1083 return
1084 elif args[0] == '.':
1085 output_file = os.path.join(self._export_dir, 'Cards', \
1086 'proc_card_mg5.dat')
1087 output_file = open(output_file, 'w')
1088 else:
1089 output_file = open(args[0], 'w')
1090
1091
1092 text = self.get_history_header()
1093 text += ('\n'.join(self.history) + '\n')
1094
1095
1096 output_file.write(text)
1097 output_file.close()
1098
1099 if self.log:
1100 logger.info("History written to " + output_file.name)
1101
1102 - def compile(self, *args, **opts):
1106
1107 - def avoid_history_duplicate(self, line, no_break=[]):
1108 """remove all line in history (but the last) starting with line.
1109 up to the point when a line didn't start by something in no_break.
1110 (reading in reverse order)"""
1111
1112 new_history = []
1113 for i in range(1, len(self.history)+1):
1114 cur_line = self.history[-i]
1115 if i == 1:
1116 new_history.append(cur_line)
1117 elif not any((cur_line.startswith(text) for text in no_break)):
1118 to_add = self.history[:-i+1]
1119 to_add.reverse()
1120 new_history += to_add
1121 break
1122 elif cur_line.startswith(line):
1123 continue
1124 else:
1125 new_history.append(cur_line)
1126
1127 new_history.reverse()
1128 self.history[:] = new_history
1129
1130
1132
1133 if self.history:
1134 self.history.pop()
1135
1136
1137 previous_store_line = self.get_stored_line()
1138
1139
1140 if isinstance(filepath, str):
1141 commandline = open(filepath).readlines()
1142 else:
1143 commandline = filepath
1144 oldinputfile = self.inputfile
1145 oldraw = self.use_rawinput
1146 self.inputfile = (l for l in commandline)
1147 self.use_rawinput = False
1148
1149
1150
1151 for line in self.inputfile:
1152
1153 line = line.replace('\n', '').strip()
1154
1155 if line:
1156 self.exec_cmd(line, precmd=True)
1157 stored = self.get_stored_line()
1158 while stored:
1159 line = stored
1160 self.exec_cmd(line, precmd=True)
1161 stored = self.get_stored_line()
1162
1163
1164 if self.child:
1165 self.child.exec_cmd('quit')
1166 self.inputfile = oldinputfile
1167 self.use_rawinput = oldraw
1168
1169
1170 cmd = self
1171 while hasattr(cmd, 'mother') and cmd.mother:
1172 cmd = cmd.mother
1173 cmd.stored_line = previous_store_line
1174 return
1175
1177 """Default history header"""
1178
1179 return self.history_header
1180
1181 - def postloop(self):
1182 """ """
1183
1184 args = self.split_arg(self.lastcmd)
1185 if args and args[0] in ['quit','exit']:
1186 if 'all' in args:
1187 return True
1188 if len(args) >1 and args[1].isdigit():
1189 if args[1] not in ['0', '1']:
1190 return True
1191 return False
1192
1193
1194
1195
1196 @staticmethod
1203
1204 signal.signal(signal.SIGALRM, handle_alarm)
1205
1206 if fct is None:
1207 fct = raw_input
1208
1209 if timeout:
1210 signal.alarm(timeout)
1211 question += '[%ss to answer] ' % (timeout)
1212 try:
1213 result = fct(question)
1214 except TimeOutError:
1215 if noerror:
1216 logger.info('\nuse %s' % default)
1217 if fct_timeout:
1218 fct_timeout(True)
1219 return default
1220 else:
1221 signal.alarm(0)
1222 raise
1223 finally:
1224 signal.alarm(0)
1225 if fct_timeout:
1226 fct_timeout(False)
1227 return result
1228
1229
1230
1231
1232
1233
1234
1236 """Not in help: exit the mainloop() """
1237
1238 if self.child:
1239 self.child.exec_cmd('quit ' + line, printcmd=False)
1240 return
1241 elif self.mother:
1242 self.mother.child = None
1243 if line == 'all':
1244 pass
1245 elif line:
1246 level = int(line) - 1
1247 if level:
1248 self.mother.lastcmd = 'quit %s' % level
1249 logger.info(' ')
1250 return True
1251
1252
1253 do_EOF = do_quit
1254 do_exit = do_quit
1255
1257 """Not in help: propose some usefull possible action """
1258
1259
1260 if line:
1261 return cmd.Cmd.do_help(self, line)
1262
1263
1264 names = self.get_names()
1265 cmds = {}
1266 names.sort()
1267
1268 prevname = ''
1269 for name in names:
1270 if name[:3] == 'do_':
1271 if name == prevname:
1272 continue
1273 prevname = name
1274 cmdname=name[3:]
1275 try:
1276 doc = getattr(self.cmd, name).__doc__
1277 except Exception:
1278 doc = None
1279 if not doc:
1280 doc = getattr(self, name).__doc__
1281 if not doc:
1282 tag = "Documented commands"
1283 elif ':' in doc:
1284 tag = doc.split(':',1)[0]
1285 else:
1286 tag = "Documented commands"
1287 if tag in cmds:
1288 cmds[tag].append(cmdname)
1289 else:
1290 cmds[tag] = [cmdname]
1291
1292 self.stdout.write("%s\n"%str(self.doc_leader))
1293 for tag in self.helporder:
1294 if tag not in cmds:
1295 continue
1296 header = "%s (type help <topic>):" % tag
1297 self.print_topics(header, cmds[tag], 15,80)
1298 for name, item in cmds.items():
1299 if name in self.helporder:
1300 continue
1301 if name == "Not in help":
1302 continue
1303 header = "%s (type help <topic>):" % name
1304 self.print_topics(header, item, 15,80)
1305
1306
1307
1308 if len(self.history) == 0:
1309 last_action_2 = last_action = 'start'
1310 else:
1311 last_action_2 = last_action = 'none'
1312
1313 pos = 0
1314 authorize = self.next_possibility.keys()
1315 while last_action_2 not in authorize and last_action not in authorize:
1316 pos += 1
1317 if pos > len(self.history):
1318 last_action_2 = last_action = 'start'
1319 break
1320
1321 args = self.history[-1 * pos].split()
1322 last_action = args[0]
1323 if len(args)>1:
1324 last_action_2 = '%s %s' % (last_action, args[1])
1325 else:
1326 last_action_2 = 'none'
1327
1328 logger.info('Contextual Help')
1329 logger.info('===============')
1330 if last_action_2 in authorize:
1331 options = self.next_possibility[last_action_2]
1332 elif last_action in authorize:
1333 options = self.next_possibility[last_action]
1334 else:
1335 return
1336 text = 'The following command(s) may be useful in order to continue.\n'
1337 for option in options:
1338 text+='\t %s \n' % option
1339 logger.info(text)
1340
1342 """Advanced commands: basic display"""
1343
1344 args = self.split_arg(line)
1345
1346
1347 if len(args) == 0:
1348 self.help_display()
1349 raise self.InvalidCmd, 'display require at least one argument'
1350
1351 if args[0] == "options":
1352 outstr = "Value of current Options:\n"
1353 for key, value in self.options.items():
1354 outstr += '%25s \t:\t%s\n' %(key,value)
1355 output.write(outstr)
1356
1357 elif args[0] == "variable":
1358 outstr = "Value of Internal Variable:\n"
1359 try:
1360 var = eval(args[1])
1361 except Exception:
1362 outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1]
1363 else:
1364 outstr += 'GLOBAL:\n'
1365 outstr += misc.nice_representation(var, nb_space=4)
1366
1367 try:
1368 var = eval('self.%s' % args[1])
1369 except Exception:
1370 outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1]
1371 else:
1372 outstr += 'LOCAL:\n'
1373 outstr += misc.nice_representation(var, nb_space=4)
1374 split = args[1].split('.')
1375 for i, name in enumerate(split):
1376 try:
1377 __import__('.'.join(split[:i+1]))
1378 exec('%s=sys.modules[\'%s\']' % (split[i], '.'.join(split[:i+1])))
1379 except ImportError:
1380 try:
1381 var = eval(args[1])
1382 except Exception, error:
1383 outstr += 'EXTERNAL:\nVariable %s is not a external variable\n' % args[1]
1384 break
1385 else:
1386 outstr += 'EXTERNAL:\n'
1387 outstr += misc.nice_representation(var, nb_space=4)
1388 else:
1389 var = eval(args[1])
1390 outstr += 'EXTERNAL:\n'
1391 outstr += misc.nice_representation(var, nb_space=4)
1392
1393 pydoc.pager(outstr)
1394
1395
1396 - def do_save(self, line, check=True):
1397 """Save the configuration file"""
1398
1399 args = self.split_arg(line)
1400
1401 if check:
1402 Cmd.check_save(self, args)
1403
1404
1405 if'HOME' in os.environ and os.environ['HOME'] and \
1406 os.path.exists(pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')):
1407 base = pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')
1408 if hasattr(self, 'me_dir'):
1409 basedir = self.me_dir
1410 elif not MADEVENT:
1411 basedir = MG5DIR
1412 else:
1413 basedir = os.getcwd()
1414 elif MADEVENT:
1415
1416 for config_file in ['me5_configuration.txt', 'amcatnlo_configuration.txt']:
1417 if os.path.exists(pjoin(self.me_dir, 'Cards', config_file)):
1418 base = pjoin(self.me_dir, 'Cards', config_file)
1419 basedir = self.me_dir
1420 else:
1421 if hasattr(self, 'me_dir'):
1422 base = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1423 if len(args) == 0 and os.path.exists(base):
1424 self.write_configuration(base, base, self.me_dir)
1425 base = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
1426 basedir = MG5DIR
1427
1428 if len(args) == 0:
1429 args.append(base)
1430 self.write_configuration(args[0], base, basedir, self.options)
1431
1433 """Write the configuration file"""
1434
1435
1436
1437
1438 logger.info('save configuration file to %s' % filepath)
1439 to_write = to_keep.keys()
1440 text = ""
1441
1442 for line in file(basefile):
1443 if '=' in line:
1444 data, value = line.split('=',1)
1445 else:
1446 text += line
1447 continue
1448 data = data.strip()
1449 if data.startswith('#'):
1450 key = data[1:].strip()
1451 else:
1452 key = data
1453 if '#' in value:
1454 value, comment = value.split('#',1)
1455 else:
1456 comment = ''
1457 if key in to_keep:
1458 value = str(to_keep[key])
1459 else:
1460 text += line
1461 continue
1462 try:
1463 to_write.remove(key)
1464 except Exception:
1465 pass
1466 if '_path' in key:
1467
1468
1469 if not os.path.isabs(value):
1470 value = os.path.realpath(os.path.join(basedir, value))
1471 text += '%s = %s # %s \n' % (key, value, comment)
1472 for key in to_write:
1473 if key in to_keep:
1474 text += '%s = %s \n' % (key, to_keep[key])
1475
1476 if not MADEVENT:
1477 text += """\n# MG5 MAIN DIRECTORY\n"""
1478 text += "mg5_path = %s\n" % MG5DIR
1479
1480 writer = open(filepath,'w')
1481 writer.write(text)
1482 writer.close()
1483
1488 """CMD command with shell activate"""
1489
1490
1492 "Run a shell command"
1493
1494 if line.strip() is '':
1495 self.help_shell()
1496 else:
1497 logging.info("running shell command: " + line)
1498 subprocess.call(line, shell=True)
1499
1501 """ add path for shell """
1502
1503
1504
1505 if len(self.split_arg(line[0:begidx])) > 1 and line[begidx - 1] == os.path.sep:
1506 if not text:
1507 text = ''
1508 output = self.path_completion(text,
1509 base_dir=\
1510 self.split_arg(line[0:begidx])[-1])
1511 else:
1512 output = self.path_completion(text)
1513 return output
1514
1516 """help for the shell"""
1517 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')
1518 logger.info("syntax: shell CMD (or ! CMD)",'$MG:color:BLACK')
1519
1527 """ a class for answering a question with the path autocompletion"""
1528
1530 """Initializing before starting the main loop"""
1531 self.prompt = '>'
1532 self.value = None
1533 BasicCmd.preloop(self)
1534
1535
1536 - def __init__(self, question, allow_arg=[], default=None,
1537 mother_interface=None, *arg, **opt):
1538 self.question = question
1539 self.wrong_answer = 0
1540 self.allow_arg = [str(a) for a in allow_arg]
1541 self.history_header = ''
1542 self.default_value = str(default)
1543 self.mother_interface = mother_interface
1544 cmd.Cmd.__init__(self, *arg, **opt)
1545
1546 - def __call__(self, question, reprint_opt=True, **opts):
1547
1548 self.question = question
1549 for key,value in opts:
1550 setattr(self, key, value)
1551 if reprint_opt:
1552 print question
1553 return self.cmdloop()
1554
1555
1557 prev_timer = signal.alarm(0)
1558 if prev_timer:
1559 nb_back = len(line)
1560 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
1561 self.stdout.write(line)
1562 self.stdout.flush()
1563 try:
1564 out = {}
1565 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
1566 out[' Recognized command'] = BasicCmd.completenames(self, text)
1567
1568 return self.deal_multiple_categories(out)
1569 except Exception, error:
1570 print error
1571
1573
1574
1575 return dir(self)
1576
1577 - def onecmd(self, line, **opt):
1578 """catch all error and stop properly command accordingly
1579 Interpret the argument as though it had been typed in response
1580 to the prompt.
1581
1582 The return value is a flag indicating whether interpretation of
1583 commands by the interpreter should stop.
1584
1585 This allow to pass extra argument for internal call.
1586 """
1587 try:
1588 if '~/' in line and os.environ.has_key('HOME'):
1589 line = line.replace('~/', '%s/' % os.environ['HOME'])
1590 line = os.path.expandvars(line)
1591 cmd, arg, line = self.parseline(line)
1592 if not line:
1593 return self.emptyline()
1594 if cmd is None:
1595 return self.default(line)
1596 self.lastcmd = line
1597 if cmd == '':
1598 return self.default(line)
1599 else:
1600 try:
1601 func = getattr(self, 'do_' + cmd)
1602 except AttributeError:
1603 return self.default(line)
1604 return func(arg, **opt)
1605 except Exception as error:
1606 logger.warning(error)
1607
1608 - def reask(self, reprint_opt=True):
1609 pat = re.compile('\[(\d*)s to answer\]')
1610 prev_timer = signal.alarm(0)
1611
1612 if prev_timer:
1613 if pat.search(self.question):
1614 timeout = int(pat.search(self.question).groups()[0])
1615 else:
1616 timeout=20
1617 print
1618 signal.alarm(timeout)
1619 if reprint_opt:
1620 if not prev_timer:
1621 self.question = pat.sub('',self.question)
1622 print self.question
1623 return False
1624
1626 """Default action if line is not recognized"""
1627
1628 if line.strip() == '' and self.default_value is not None:
1629 self.value = self.default_value
1630 else:
1631 self.value = line
1632
1634 """If empty line, return default"""
1635
1636 if self.default_value is not None:
1637 self.value = self.default_value
1638
1639
1640 - def postcmd(self, stop, line):
1641
1642 try:
1643 if self.value in self.allow_arg:
1644 return True
1645 elif str(self.value) == 'EOF':
1646 self.value = self.default_value
1647 return True
1648 elif line and hasattr(self, 'do_%s' % line.split()[0]):
1649 return self.reask()
1650 elif self.value == 'repeat':
1651 return self.reask()
1652 elif len(self.allow_arg)==0:
1653 return True
1654 else:
1655 raise Exception
1656 except Exception,error:
1657 if self.wrong_answer < 100:
1658 self.wrong_answer += 1
1659 logger.warning("""%s not valid argument. Valid argument are in (%s).""" \
1660 % (self.value,','.join(self.allow_arg)))
1661 logger.warning('please retry')
1662 return False
1663 else:
1664 self.value = self.default_value
1665 return True
1666
1668 cmd.Cmd.cmdloop(self, intro)
1669 return self.value
1670
1676
1681 """ a class for answering a question with the path autocompletion"""
1682
1683 completion_prefix=''
1684
1686 prev_timer = signal.alarm(0)
1687 if prev_timer:
1688 nb_back = len(line)
1689 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
1690 self.stdout.write(line)
1691 self.stdout.flush()
1692
1693 try:
1694 out = {}
1695 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
1696 out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False)
1697 out[' Recognized command'] = BasicCmd.completenames(self, text)
1698
1699 return self.deal_multiple_categories(out)
1700 except Exception, error:
1701 print error
1702
1708
1710 prev_timer = signal.alarm(0)
1711 if prev_timer:
1712 nb_back = len(line)
1713 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
1714 self.stdout.write(line)
1715 self.stdout.flush()
1716 try:
1717 args = Cmd.split_arg(line[0:begidx])
1718 except Exception, error:
1719 print error
1720
1721
1722 if args[-1].endswith(os.path.sep):
1723
1724 return Cmd.path_completion(text,
1725 os.path.join('.',*[a for a in args \
1726 if a.endswith(os.path.sep)]))
1727 self.completenames(line+text)
1728
1729
1730 - def postcmd(self, stop, line):
1731 try:
1732 if self.value in self.allow_arg:
1733 return True
1734 elif self.value and os.path.isfile(self.value):
1735 return os.path.relpath(self.value)
1736 elif self.value and str(self.value) == 'EOF':
1737 self.value = self.default_value
1738 return True
1739 elif line and hasattr(self, 'do_%s' % line.split()[0]):
1740
1741 reprint_opt = True
1742 elif self.value == 'repeat':
1743 reprint_opt = True
1744 else:
1745 raise Exception
1746 except Exception, error:
1747 print """not valid argument. Valid argument are file path or value in (%s).""" \
1748 % ','.join(self.allow_arg)
1749 print 'please retry'
1750 reprint_opt = False
1751
1752 return self.reask(reprint_opt)
1753
1760
1761
1762
1763
1764 -class CmdFile(file):
1765 """ a class for command input file -in order to debug cmd \n problem"""
1766
1773
1775 """readline method treating correctly a line whithout \n at the end
1776 (add it)
1777 """
1778 if self.lines:
1779 line = self.lines.pop(0)
1780 else:
1781 return ''
1782
1783 if line.endswith('\n'):
1784 return line
1785 else:
1786 return line + '\n'
1787
1790
1793