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 logging
19 import math
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 logger_tuto = logging.getLogger('tutorial')
38 logger_plugin = logging.getLogger('tutorial_plugin')
39
40 try:
41 import madgraph.various.misc as misc
42 from madgraph import MG5DIR, MadGraph5Error
43 MADEVENT = False
44 except ImportError, error:
45 try:
46 import internal.misc as misc
47 except:
48 raise error
49
50 MADEVENT = True
51
52
53 pjoin = os.path.join
56 """Class for run-time error"""
57
58 -def debug(debug_only=True):
59
60 def deco_debug(f):
61
62 if debug_only and not __debug__:
63 return f
64
65 def deco_f(*args, **opt):
66 try:
67 return f(*args, **opt)
68 except Exception, error:
69 logger.error(error)
70 logger.error(traceback.print_exc(file=sys.stdout))
71 return
72 return deco_f
73 return deco_debug
74
75 import string
76
77
78 __all__ = ["Cmd"]
79 PROMPT = '(Cmd) '
80 IDENTCHARS = string.ascii_letters + string.digits + '_'
82 """A simple framework for writing line-oriented command interpreters.
83
84 These are often useful for test harnesses, administrative tools, and
85 prototypes that will later be wrapped in a more sophisticated interface.
86
87 A Cmd instance or subclass instance is a line-oriented interpreter
88 framework. There is no good reason to instantiate Cmd itself; rather,
89 it's useful as a superclass of an interpreter class you define yourself
90 in order to inherit Cmd's methods and encapsulate action methods.
91
92 """
93 prompt = PROMPT
94 identchars = IDENTCHARS
95 ruler = '='
96 lastcmd = ''
97 intro = None
98 doc_leader = ""
99 doc_header = "Documented commands (type help <topic>):"
100 misc_header = "Miscellaneous help topics:"
101 undoc_header = "Undocumented commands:"
102 nohelp = "*** No help on %s"
103 use_rawinput = 1
104
105 - def __init__(self, completekey='tab', stdin=None, stdout=None,**opt):
106 """Instantiate a line-oriented interpreter framework.
107
108 The optional argument 'completekey' is the readline name of a
109 completion key; it defaults to the Tab key. If completekey is
110 not None and the readline module is available, command completion
111 is done automatically. The optional arguments stdin and stdout
112 specify alternate input and output file objects; if not specified,
113 sys.stdin and sys.stdout are used.
114
115 """
116 import sys
117 if stdin is not None:
118 self.stdin = stdin
119 else:
120 self.stdin = sys.stdin
121 if stdout is not None:
122 self.stdout = stdout
123 else:
124 self.stdout = sys.stdout
125 self.cmdqueue = []
126 self.completekey = completekey
127 self.cmd_options = opt
128
130 """Repeatedly issue a prompt, accept input, parse an initial prefix
131 off the received input, and dispatch to action methods, passing them
132 the remainder of the line as argument.
133
134 """
135
136 self.preloop()
137 if self.use_rawinput and self.completekey:
138 try:
139 import readline
140 self.old_completer = readline.get_completer()
141 readline.set_completer(self.complete)
142 readline.parse_and_bind(self.completekey+": complete")
143 except ImportError:
144 pass
145 try:
146 if intro is not None:
147 self.intro = intro
148 if self.intro:
149 self.stdout.write(str(self.intro)+"\n")
150 stop = None
151 while not stop:
152 if self.cmdqueue:
153 line = self.cmdqueue.pop(0)
154 else:
155 if self.use_rawinput:
156 try:
157 line = raw_input(self.prompt)
158 except EOFError:
159 line = 'EOF'
160 else:
161 self.stdout.write(self.prompt)
162 self.stdout.flush()
163 line = self.stdin.readline()
164 if not len(line):
165 line = 'EOF'
166 else:
167 line = line.rstrip('\r\n')
168 line = self.precmd(line)
169 stop = self.onecmd(line)
170 stop = self.postcmd(stop, line)
171 self.postloop()
172 finally:
173 if self.use_rawinput and self.completekey:
174 try:
175 import readline
176 readline.set_completer(self.old_completer)
177 except ImportError:
178 pass
179
180
182 """Hook method executed just before the command line is
183 interpreted, but after the input prompt is generated and issued.
184
185 """
186 return line
187
188 - def postcmd(self, stop, line):
189 """Hook method executed just after a command dispatch is finished."""
190 return stop
191
193 """Hook method executed once when the cmdloop() method is called."""
194 pass
195
196 - def postloop(self):
197 """Hook method executed once when the cmdloop() method is about to
198 return.
199
200 """
201 pass
202
204 """Parse the line into a command name and a string containing
205 the arguments. Returns a tuple containing (command, args, line).
206 'command' and 'args' may be None if the line couldn't be parsed.
207 """
208 line = line.strip()
209 if not line:
210 return None, None, line
211 elif line[0] == '?':
212 line = 'help ' + line[1:]
213 elif line[0] == '!':
214 if hasattr(self, 'do_shell'):
215 line = 'shell ' + line[1:]
216 else:
217 return None, None, line
218 i, n = 0, len(line)
219 while i < n and line[i] in self.identchars: i = i+1
220 cmd, arg = line[:i], line[i:].strip()
221 return cmd, arg, line
222
224 """Interpret the argument as though it had been typed in response
225 to the prompt.
226
227 This may be overridden, but should not normally need to be;
228 see the precmd() and postcmd() methods for useful execution hooks.
229 The return value is a flag indicating whether interpretation of
230 commands by the interpreter should stop.
231
232 """
233 cmd, arg, line = self.parseline(line)
234 if not line:
235 return self.emptyline()
236 if cmd is None:
237 return self.default(line)
238 self.lastcmd = line
239 if cmd == '':
240 return self.default(line)
241 else:
242 try:
243 func = getattr(self, 'do_' + cmd)
244 except AttributeError:
245 return self.default(line)
246 return func(arg)
247
249 """Called when an empty line is entered in response to the prompt.
250
251 If this method is not overridden, it repeats the last nonempty
252 command entered.
253
254 """
255 if self.lastcmd:
256 return self.onecmd(self.lastcmd)
257
259 """Called on an input line when the command prefix is not recognized.
260
261 If this method is not overridden, it prints an error message and
262 returns.
263
264 """
265 self.stdout.write('*** Unknown syntax: %s\n'%line)
266
268 """Method called to complete an input line when no command-specific
269 complete_*() method is available.
270
271 By default, it returns an empty list.
272
273 """
274 return []
275
277 dotext = 'do_'+text
278
279 done = set()
280
281 return [a[3:] for a in self.get_names()
282 if a.startswith(dotext) and a not in done and not done.add(a)]
283
285 """Return the next possible completion for 'text'.
286
287 If a command has not been entered, then complete against command list.
288 Otherwise try to call complete_<command> to get list of completions.
289 """
290 if state == 0:
291 import readline
292 origline = readline.get_line_buffer()
293 line = origline.lstrip()
294 stripped = len(origline) - len(line)
295 begidx = readline.get_begidx() - stripped
296 endidx = readline.get_endidx() - stripped
297 if begidx>0:
298 cmd, args, foo = self.parseline(line)
299 if cmd == '':
300 compfunc = self.completedefault
301 else:
302 try:
303 compfunc = getattr(self, 'complete_' + cmd)
304 except AttributeError:
305 compfunc = self.completedefault
306 else:
307 compfunc = self.completenames
308 self.completion_matches = compfunc(text, line, begidx, endidx)
309 try:
310 return self.completion_matches[state]
311 except IndexError:
312 return None
313
315
316
317 names = []
318 classes = [self.__class__]
319 while classes:
320 aclass = classes.pop(0)
321 if aclass.__bases__:
322 classes = classes + list(aclass.__bases__)
323 names = names + dir(aclass)
324 return names
325
328
330 if arg:
331
332 try:
333 func = getattr(self, 'help_' + arg)
334 except AttributeError:
335 try:
336 doc=getattr(self, 'do_' + arg).__doc__
337 if doc:
338 self.stdout.write("%s\n"%str(doc))
339 return
340 except AttributeError:
341 pass
342 self.stdout.write("%s\n"%str(self.nohelp % (arg,)))
343 return
344 func()
345 else:
346 names = self.get_names()
347 cmds_doc = []
348 cmds_undoc = []
349 help = {}
350 for name in names:
351 if name[:5] == 'help_':
352 help[name[5:]]=1
353 names.sort()
354
355 prevname = ''
356 for name in names:
357 if name[:3] == 'do_':
358 if name == prevname:
359 continue
360 prevname = name
361 cmd=name[3:]
362 if cmd in help:
363 cmds_doc.append(cmd)
364 del help[cmd]
365 elif getattr(self, name).__doc__:
366 cmds_doc.append(cmd)
367 else:
368 cmds_undoc.append(cmd)
369 self.stdout.write("%s\n"%str(self.doc_leader))
370 self.print_topics(self.doc_header, cmds_doc, 15,80)
371 self.print_topics(self.misc_header, help.keys(),15,80)
372 self.print_topics(self.undoc_header, cmds_undoc, 15,80)
373
381
383 """Display a list of strings as a compact set of columns.
384
385 Each column is only as wide as necessary.
386 Columns are separated by two spaces (one was not legible enough).
387 """
388 if not list:
389 self.stdout.write("<empty>\n")
390 return
391 nonstrings = [i for i in range(len(list))
392 if not isinstance(list[i], str)]
393 if nonstrings:
394 raise TypeError, ("list[i] not a string for i in %s" %
395 ", ".join(map(str, nonstrings)))
396 size = len(list)
397 if size == 1:
398 self.stdout.write('%s\n'%str(list[0]))
399 return
400
401 for nrows in range(1, len(list)):
402 ncols = (size+nrows-1) // nrows
403 colwidths = []
404 totwidth = -2
405 for col in range(ncols):
406 colwidth = 0
407 for row in range(nrows):
408 i = row + nrows*col
409 if i >= size:
410 break
411 x = list[i]
412 colwidth = max(colwidth, len(x))
413 colwidths.append(colwidth)
414 totwidth += colwidth + 2
415 if totwidth > displaywidth:
416 break
417 if totwidth <= displaywidth:
418 break
419 else:
420 nrows = len(list)
421 ncols = 1
422 colwidths = [0]
423 for row in range(nrows):
424 texts = []
425 for col in range(ncols):
426 i = row + nrows*col
427 if i >= size:
428 x = ""
429 else:
430 x = list[i]
431 texts.append(x)
432 while texts and not texts[-1]:
433 del texts[-1]
434 for col in range(len(texts)):
435 texts[col] = texts[col].ljust(colwidths[col])
436 self.stdout.write("%s\n"%str(" ".join(texts)))
437
438
439
440
441
442
443
444 -class BasicCmd(OriginalCmd):
445 """Simple extension for the readline"""
446
448 """ This has been refactorized here so that it can be called when another
449 program called by MG5 (such as MadAnalysis5) changes this attribute of readline"""
450 if readline:
451 if not 'libedit' in readline.__doc__:
452 readline.set_completion_display_matches_hook(self.print_suggestions)
453 else:
454 readline.set_completion_display_matches_hook()
455
459
461 """convert the multiple category in a formatted list understand by our
462 specific readline parser"""
463
464 if not formatting:
465 return dico
466
467 if 'libedit' in readline.__doc__:
468
469 out = []
470 for name, opt in dico.items():
471 out += opt
472 return list(set(out))
473
474
475 if not forceCategory and all(len(s) <= 1 for s in dico.values() ):
476 values = set((s[0] for s in dico.values() if len(s)==1))
477 if len(values) == 1:
478 return values
479
480
481 out = []
482 valid=0
483
484 for name, opt in dico.items():
485 if not opt:
486 continue
487 name = name.replace(' ', '_')
488 valid += 1
489 out.append(opt[0].rstrip()+'@@'+name+'@@')
490
491 d = {}
492 for x in opt:
493 d[x] = 1
494 opt = list(d.keys())
495 opt.sort()
496 out += opt
497
498 if not forceCategory and valid == 1:
499 out = out[1:]
500
501 return out
502
503 @debug()
505 """print auto-completions by category"""
506 if not hasattr(self, 'completion_prefix'):
507 self.completion_prefix = ''
508 longest_match_length += len(self.completion_prefix)
509 try:
510 if len(matches) == 1:
511 self.stdout.write(matches[0]+' ')
512 return
513 self.stdout.write('\n')
514 l2 = [a[-2:] for a in matches]
515 if '@@' in l2:
516 nb_column = self.getTerminalSize()//(longest_match_length+1)
517 pos=0
518 for val in self.completion_matches:
519 if val.endswith('@@'):
520 category = val.rsplit('@@',2)[1]
521 category = category.replace('_',' ')
522 self.stdout.write('\n %s:\n%s\n' % (category, '=' * (len(category)+2)))
523 start = 0
524 pos = 0
525 continue
526 elif pos and pos % nb_column ==0:
527 self.stdout.write('\n')
528 self.stdout.write(self.completion_prefix + val + \
529 ' ' * (longest_match_length +1 -len(val)))
530 pos +=1
531 self.stdout.write('\n')
532 else:
533
534 nb_column = self.getTerminalSize()//(longest_match_length+1)
535 for i,val in enumerate(matches):
536 if i and i%nb_column ==0:
537 self.stdout.write('\n')
538 self.stdout.write(self.completion_prefix + val + \
539 ' ' * (longest_match_length +1 -len(val)))
540 self.stdout.write('\n')
541
542 self.stdout.write(self.prompt+readline.get_line_buffer())
543 self.stdout.flush()
544 except Exception, error:
545 if __debug__:
546 logger.error(error)
547
549 def ioctl_GWINSZ(fd):
550 try:
551 import fcntl, termios, struct
552 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
553 '1234'))
554 except Exception:
555 return None
556 return cr
557 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
558 if not cr:
559 try:
560 fd = os.open(os.ctermid(), os.O_RDONLY)
561 cr = ioctl_GWINSZ(fd)
562 os.close(fd)
563 except Exception:
564 pass
565 if not cr:
566 try:
567 cr = (os.environ['LINES'], os.environ['COLUMNS'])
568 except Exception:
569 cr = (25, 80)
570 return int(cr[1])
571
573 """Return the next possible completion for 'text'.
574 If a command has not been entered, then complete against command list.
575 Otherwise try to call complete_<command> to get list of completions.
576 """
577 if state == 0:
578 import readline
579 origline = readline.get_line_buffer()
580 line = origline.lstrip()
581 stripped = len(origline) - len(line)
582 begidx = readline.get_begidx() - stripped
583 endidx = readline.get_endidx() - stripped
584
585 if ';' in line:
586 begin, line = line.rsplit(';',1)
587 begidx = begidx - len(begin) - 1
588 endidx = endidx - len(begin) - 1
589 if line[:begidx] == ' ' * begidx:
590 begidx=0
591
592 if begidx>0:
593 cmd, args, foo = self.parseline(line)
594 if cmd == '':
595 compfunc = self.completedefault
596 else:
597 try:
598 compfunc = getattr(self, 'complete_' + cmd)
599 except AttributeError, error:
600 compfunc = self.completedefault
601 except Exception, error:
602 misc.sprint(error)
603 else:
604 compfunc = self.completenames
605
606
607 if line and begidx > 2 and line[begidx-2:begidx] == '\ ':
608 Ntext = line.split(os.path.sep)[-1]
609 self.completion_prefix = Ntext.rsplit('\ ', 1)[0] + '\ '
610 to_rm = len(self.completion_prefix) - 1
611 Nbegidx = len(line.rsplit(os.path.sep, 1)[0]) + 1
612 data = compfunc(Ntext.replace('\ ', ' '), line, Nbegidx, endidx)
613 self.completion_matches = [p[to_rm:] for p in data
614 if len(p)>to_rm]
615
616 elif line and line[begidx-1] in ['-',"=",':']:
617 try:
618 sep = line[begidx-1]
619 Ntext = line.split()[-1]
620 self.completion_prefix = Ntext.rsplit(sep,1)[0] + sep
621 to_rm = len(self.completion_prefix)
622 Nbegidx = len(line.rsplit(None, 1)[0])
623 data = compfunc(Ntext, line, Nbegidx, endidx)
624 self.completion_matches = [p[to_rm:] for p in data
625 if len(p)>to_rm]
626 except Exception, error:
627 print error
628 else:
629 self.completion_prefix = ''
630 self.completion_matches = compfunc(text, line, begidx, endidx)
631
632 self.completion_matches = [ l if l[-1] in [' ','@','=',os.path.sep]
633 else ((l + ' ') if not l.endswith('\\$') else l[:-2])
634 for l in self.completion_matches if l]
635
636 try:
637 return self.completion_matches[state]
638 except IndexError, error:
639
640
641
642 return None
643
644 @staticmethod
646 """Split a line of arguments"""
647
648 split = re.findall(r"(?:[^\s'\"]|(?:'|\")(?:\\.|[^\"'])*(?:\"|'))+",line)
649
650 out=[]
651 tmp=''
652 for data in split:
653 if data[-1] == '\\':
654 tmp += data[:-1]+' '
655 elif tmp:
656 tmp += data
657 tmp = os.path.expanduser(os.path.expandvars(tmp))
658 out.append(tmp)
659
660
661 tmp = ''
662 else:
663 out.append(data)
664 return out
665
666 @staticmethod
668 """Propose completions of text in list"""
669
670 if not text:
671 completions = list
672 else:
673 completions = [ f
674 for f in list
675 if f.startswith(text)
676 ]
677
678 return completions
679
680
681 @staticmethod
682 - def path_completion(text, base_dir = None, only_dirs = False,
683 relative=True):
684 """Propose completions of text to compose a valid path"""
685
686 if base_dir is None:
687 base_dir = os.getcwd()
688 base_dir = os.path.expanduser(os.path.expandvars(base_dir))
689
690 if text == '~':
691 text = '~/'
692 prefix, text = os.path.split(text)
693 prefix = os.path.expanduser(os.path.expandvars(prefix))
694 base_dir = os.path.join(base_dir, prefix)
695 if prefix:
696 prefix += os.path.sep
697
698 if only_dirs:
699 completion = [prefix + f + os.path.sep
700 for f in os.listdir(base_dir)
701 if f.startswith(text) and \
702 os.path.isdir(os.path.join(base_dir, f)) and \
703 (not f.startswith('.') or text.startswith('.'))
704 ]
705 else:
706 completion = [ prefix + f
707 for f in os.listdir(base_dir)
708 if f.startswith(text) and \
709 os.path.isfile(os.path.join(base_dir, f)) and \
710 (not f.startswith('.') or text.startswith('.'))
711 ]
712
713 completion = completion + \
714 [prefix + f + os.path.sep
715 for f in os.listdir(base_dir)
716 if f.startswith(text) and \
717 os.path.isdir(os.path.join(base_dir, f)) and \
718 (not f.startswith('.') or text.startswith('.'))
719 ]
720
721 if relative:
722 completion += [prefix + f for f in ['.'+os.path.sep, '..'+os.path.sep] if \
723 f.startswith(text) and not prefix.startswith('.')]
724
725 completion = [a.replace(' ','\ ') for a in completion]
726 return completion
727
732 """Extension of the cmd object for only the check command"""
733
734 - def check_history(self, args):
735 """check the validity of line"""
736
737 if len(args) > 1:
738 self.help_history()
739 raise self.InvalidCmd('\"history\" command takes at most one argument')
740
741 if not len(args):
742 return
743
744 if args[0] =='.':
745 if not self._export_dir:
746 raise self.InvalidCmd("No default directory is defined for \'.\' option")
747 elif args[0] != 'clean':
748 dirpath = os.path.dirname(args[0])
749 if dirpath and not os.path.exists(dirpath) or \
750 os.path.isdir(args[0]):
751 raise self.InvalidCmd("invalid path %s " % dirpath)
752
754 """check that the line is compatible with save options"""
755
756 if len(args) > 2:
757 self.help_save()
758 raise self.InvalidCmd, 'too many arguments for save command.'
759
760 if len(args) == 2:
761 if args[0] != 'options':
762 self.help_save()
763 raise self.InvalidCmd, '\'%s\' is not recognized as first argument.' % \
764 args[0]
765 else:
766 args.pop(0)
767
769 """Extension of the cmd object for only the help command"""
770
772 logger.info("-- terminates the application",'$MG:color:BLUE')
773 logger.info("syntax: quit",'$MG:BOLD')
774
775 help_EOF = help_quit
776
777 - def help_history(self):
778 logger.info("-- interact with the command history.",'$MG:color:BLUE')
779 logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:BOLD')
780 logger.info(" > If FILEPATH is \'.\' and \'output\' is done,")
781 logger.info(" Cards/proc_card_mg5.dat will be used.")
782 logger.info(" > If FILEPATH is omitted, the history will be output to stdout.")
783 logger.info(" \"clean\" will remove all entries from the history.")
784
786 logger.info("-- access to the in-line help",'$MG:color:BLUE')
787 logger.info("syntax: help",'$MG:BOLD')
788
790 """help text for save"""
791 logger.info("-- save options configuration to filepath.",'$MG:color:BLUE')
792 logger.info("syntax: save [options] [FILEPATH]",'$MG:BOLD')
793
795 """help for display command"""
796 logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE')
797 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:BOLD')
798
807
808 - def complete_history(self, text, line, begidx, endidx):
809 "Complete the history command"
810
811 args = self.split_arg(line[0:begidx])
812
813
814 if args[-1].endswith(os.path.sep):
815 return self.path_completion(text,
816 os.path.join('.',*[a for a in args \
817 if a.endswith(os.path.sep)]))
818
819 if len(args) == 1:
820 return self.path_completion(text)
821
840
841 -class Cmd(CheckCmd, HelpCmd, CompleteCmd, BasicCmd):
842 """Extension of the cmd.Cmd command line.
843 This extensions supports line breaking, history, comments,
844 internal call to cmdline, path completion,...
845 this class should be MG5 independent"""
846
847
848 next_possibility = {}
849 history_header = ""
850
851 _display_opts = ['options','variable']
852 allow_notification_center = True
853
855 """expected error for wrong command"""
856 pass
857
858 ConfigurationError = InvalidCmd
859
860 debug_output = 'debug'
861 error_debug = """Please report this bug to developers\n
862 More information is found in '%(debug)s'.\n
863 Please attach this file to your report."""
864 config_debug = error_debug
865
866 keyboard_stop_msg = """stopping all current operation
867 in order to quit the program please enter exit"""
868
869 if MADEVENT:
870 plugin_path = []
871 else:
872 plugin_path = [pjoin(MG5DIR, 'PLUGIN')]
873 if 'PYTHONPATH' in os.environ:
874 for PluginCandidate in os.environ['PYTHONPATH'].split(':'):
875 try:
876 dirlist = os.listdir(PluginCandidate)
877 except OSError:
878 continue
879 for onedir in dirlist:
880 if onedir == 'MG5aMC_PLUGIN':
881 plugin_path.append(pjoin(PluginCandidate, 'MG5aMC_PLUGIN'))
882 break
883 else:
884 continue
885 break
886
888 """Init history and line continuation"""
889
890 self.log = True
891 self.history = []
892 self.save_line = ''
893 super(Cmd, self).__init__(*arg, **opt)
894 self.__initpos = os.path.abspath(os.getcwd())
895 self.child = None
896 self.mother = None
897 self.inputfile = None
898 self.haspiping = not sys.stdin.isatty()
899 self.stored_line = ''
900
901 if not hasattr(self, 'helporder'):
902 self.helporder = ['Documented commands']
903
905 """Hook method executed once when the cmdloop() method is called."""
906 if self.completekey:
907 try:
908 import readline
909 self.old_completer = readline.get_completer()
910 readline.set_completer(self.complete)
911 readline.parse_and_bind(self.completekey+": complete")
912 except ImportError:
913 readline = None
914 pass
915 if readline and not 'libedit' in readline.__doc__:
916 readline.set_completion_display_matches_hook(self.print_suggestions)
917
918
920
921 self.preloop()
922 if intro is not None:
923 self.intro = intro
924 if self.intro:
925 print self.intro
926 stop = None
927 while not stop:
928 if self.cmdqueue:
929 line = self.cmdqueue[0]
930 del self.cmdqueue[0]
931 else:
932 if self.use_rawinput:
933 try:
934 line = raw_input(self.prompt)
935 except EOFError:
936 line = 'EOF'
937 else:
938 sys.stdout.write(self.prompt)
939 sys.stdout.flush()
940 line = sys.stdin.readline()
941 if not len(line):
942 line = 'EOF'
943 else:
944 line = line[:-1]
945 try:
946 line = self.precmd(line)
947 stop = self.onecmd(line)
948 except BaseException, error:
949 self.error_handling(error, line)
950 if isinstance(error, KeyboardInterrupt):
951 stop = True
952 finally:
953 stop = self.postcmd(stop, line)
954 self.postloop()
955
957 """avoid to have html opening / notification"""
958 self.allow_notification_center = False
959 try:
960 self.options['automatic_html_opening'] = False
961 self.options['notification_center'] = False
962
963 except:
964 pass
965
966
968 """ A suite of additional function needed for in the cmd
969 this implement history, line breaking, comment treatment,...
970 """
971
972 if not line:
973 return line
974
975
976 if self.save_line:
977 line = self.save_line + line
978 self.save_line = ''
979
980 line = line.lstrip()
981
982 if line.endswith('\\'):
983 self.save_line = line[:-1]
984 return ''
985
986
987 if '#' in line:
988 line = line.split('#')[0]
989
990
991 if ';' in line:
992 lines = line.split(';')
993 for subline in lines:
994 if not (subline.startswith("history") or subline.startswith('help') \
995 or subline.startswith('#*')):
996 self.history.append(subline)
997 stop = self.onecmd_orig(subline)
998 stop = self.postcmd(stop, subline)
999 return ''
1000
1001
1002 self.history.append(line)
1003 return line
1004
1005 - def postcmd(self,stop, line):
1006 """ finishing a command
1007 This looks if the command add a special post part."""
1008
1009 if line.strip():
1010 try:
1011 cmd, subline = line.split(None, 1)
1012 except ValueError:
1013 pass
1014 else:
1015 if hasattr(self,'post_%s' %cmd):
1016 stop = getattr(self, 'post_%s' % cmd)(stop, subline)
1017 return stop
1018
1043
1044
1045
1046
1047 - def ask(self, question, default, choices=[], path_msg=None,
1048 timeout = True, fct_timeout=None, ask_class=None, alias={},
1049 first_cmd=None, text_format='4', force=False,
1050 return_instance=False, **opt):
1051 """ ask a question with some pre-define possibility
1052 path info is
1053 """
1054
1055 if path_msg:
1056 path_msg = [path_msg]
1057 else:
1058 path_msg = []
1059
1060 if timeout is True:
1061 try:
1062 timeout = self.options['timeout']
1063 except Exception:
1064 pass
1065
1066
1067 if choices + path_msg:
1068 question += ' ['
1069 question += "\033[%sm%s\033[0m, " % (text_format, default)
1070 for data in choices[:9] + path_msg:
1071 if default == data:
1072 continue
1073 else:
1074 question += "%s, " % data
1075
1076 if len(choices) > 9:
1077 question += '... , '
1078 question = question[:-2]+']'
1079 else:
1080 question += "[\033[%sm%s\033[0m] " % (text_format, default)
1081 if ask_class:
1082 obj = ask_class
1083 elif path_msg:
1084 obj = OneLinePathCompletion
1085 else:
1086 obj = SmartQuestion
1087
1088 if alias:
1089 choices += alias.keys()
1090
1091 question_instance = obj(question, allow_arg=choices, default=default,
1092 mother_interface=self, **opt)
1093
1094 if first_cmd:
1095 if isinstance(first_cmd, str):
1096 question_instance.onecmd(first_cmd)
1097 else:
1098 for line in first_cmd:
1099 question_instance.onecmd(line)
1100 if not self.haspiping:
1101 if hasattr(obj, "haspiping"):
1102 obj.haspiping = self.haspiping
1103
1104 if force:
1105 answer = default
1106 else:
1107 answer = self.check_answer_in_input_file(question_instance, default, path_msg)
1108 if answer is not None:
1109 if answer in alias:
1110 answer = alias[answer]
1111 if ask_class:
1112 line=answer
1113 answer = question_instance.default(line)
1114 question_instance.postcmd(answer, line)
1115 if not return_instance:
1116 return question_instance.answer
1117 else:
1118 return question_instance.answer , question_instance
1119 if hasattr(question_instance, 'check_answer_consistency'):
1120 question_instance.check_answer_consistency()
1121 if not return_instance:
1122 return answer
1123 else:
1124 return answer, question_instance
1125
1126 question = question_instance.question
1127 if not force:
1128 value = Cmd.timed_input(question, default, timeout=timeout,
1129 fct=question_instance, fct_timeout=fct_timeout)
1130 else:
1131 value = default
1132
1133 try:
1134 if value in alias:
1135 value = alias[value]
1136 except TypeError:
1137 pass
1138
1139 if value == default and ask_class:
1140 value = question_instance.default(default)
1141
1142 if not return_instance:
1143 return value
1144 else:
1145 return value, question_instance
1146
1156
1157
1159 """check import command"""
1160
1161 if '-f' in args:
1162 self.force = True
1163 args.remove('-f')
1164 if args[0] != 'command':
1165 args.set(0, 'command')
1166 if len(args) != 2:
1167 raise self.InvalidCmd('import command requires one filepath argument')
1168 if not os.path.exists(args[1]):
1169 raise 'No such file or directory %s' % args[1]
1170
1171
1255
1257 """store a line of the input file which should be executed by the higher mother"""
1258
1259 if self.mother:
1260 self.mother.store_line(line)
1261 else:
1262 self.stored_line = line
1263
1265 """return stored line and clean it"""
1266 if self.mother:
1267 value = self.mother.get_stored_line()
1268 self.mother.stored_line = None
1269 else:
1270 value = self.stored_line
1271 self.stored_line = None
1272 return value
1273
1274
1275
1277 """ """
1278
1279 if self.child:
1280 return self.child.nice_error_handling(error, line)
1281
1282 os.chdir(self.__initpos)
1283
1284 self.log = False
1285 if os.path.exists(self.debug_output):
1286 os.remove(self.debug_output)
1287 try:
1288 super(Cmd,self).onecmd('history %s' % self.debug_output.replace(' ', '\ '))
1289 except Exception, error:
1290 logger.error(error)
1291
1292 debug_file = open(self.debug_output, 'a')
1293 traceback.print_exc(file=debug_file)
1294 if hasattr(error, 'filename'):
1295 debug_file.write("Related File: %s\n" % error.filename)
1296
1297 if self.history and line == self.history[-1]:
1298 error_text = 'Command \"%s\" interrupted with error:\n' % line
1299 elif self.history:
1300 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
1301 error_text += '\"%s\" with error:\n' % self.history[-1]
1302 else:
1303 error_text = ''
1304 error_text += '%s : %s\n' % (error.__class__.__name__,
1305 str(error).replace('\n','\n\t'))
1306 error_text += self.error_debug % {'debug':self.debug_output}
1307 logger_stderr.critical(error_text)
1308
1309
1310
1311 try:
1312 self.do_display('options', debug_file)
1313 except Exception, error:
1314 debug_file.write('Fail to write options with error %s' % error)
1315
1316
1317 for card in ['proc_card_mg5.dat','param_card.dat', 'run_card.dat']:
1318 try:
1319 ff = open(pjoin(self.me_dir, 'Cards', card))
1320 debug_file.write(ff.read())
1321 ff.close()
1322 except Exception:
1323 pass
1324
1325 if hasattr(self, 'options') and 'crash_on_error' in self.options:
1326 if self.options['crash_on_error'] is True:
1327 logger.info('stop computation due to crash_on_error=True')
1328 sys.exit(str(error))
1329 elif self.options['crash_on_error'] == 'never':
1330 return False
1331
1332
1333 if self.use_rawinput == False or self.inputfile:
1334 return True
1335 elif self.mother:
1336 if self.mother.use_rawinput is False:
1337 return True
1338
1339 elif self.mother.mother:
1340 if self.mother.mother.use_rawinput is False:
1341 return True
1342
1343 return False
1344
1345
1346
1348 if self.child:
1349 return self.child.nice_user_error(error, line)
1350
1351
1352 os.chdir(self.__initpos)
1353 if not self.history or line == self.history[-1]:
1354 error_text = 'Command \"%s\" interrupted with error:\n' % line
1355 else:
1356 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
1357 error_text += '\"%s\" with error:\n' % self.history[-1]
1358 error_text += '%s : %s' % (error.__class__.__name__,
1359 str(error).replace('\n','\n\t'))
1360 logger_stderr.error(error_text)
1361
1362 if hasattr(self, 'options') and 'crash_on_error' in self.options:
1363 if self.options['crash_on_error'] is True:
1364 logger.info('stop computation due to crash_on_error=True')
1365 sys.exit(str(error))
1366 elif self.options['crash_on_error'] == 'never':
1367 self.history.pop()
1368 return False
1369
1370
1371 if self.use_rawinput == False or self.inputfile:
1372 return True
1373 elif self.mother:
1374 if self.mother.use_rawinput is False:
1375 return True
1376 elif self.mother.mother:
1377 if self.mother.mother.use_rawinput is False:
1378 return True
1379
1380
1381 self.history.pop()
1382 return False
1383
1385 if self.child:
1386 return self.child.nice_user_error(error, line)
1387
1388
1389 os.chdir(self.__initpos)
1390 if not self.history or line == self.history[-1]:
1391 error_text = 'Error detected in \"%s\"\n' % line
1392 else:
1393 error_text = 'Error detected in sub-command %s\n' % self.history[-1]
1394 error_text += 'write debug file %s \n' % self.debug_output
1395 self.log = False
1396 super(Cmd,self).onecmd('history %s' % self.debug_output)
1397 debug_file = open(self.debug_output, 'a')
1398 traceback.print_exc(file=debug_file)
1399 error_text += self.config_debug % {'debug' :self.debug_output}
1400 error_text += '%s : %s' % (error.__class__.__name__,
1401 str(error).replace('\n','\n\t'))
1402 logger_stderr.error(error_text)
1403
1404
1405 try:
1406 self.do_display('options', debug_file)
1407 except Exception, error:
1408 debug_file.write('Fail to write options with error %s' % error)
1409
1410 if hasattr(self, 'options') and 'crash_on_error' in self.options:
1411 if self.options['crash_on_error'] is True:
1412 logger.info('stop computation due to crash_on_error=True')
1413 sys.exit(str(error))
1414 elif self.options['crash_on_error'] == 'never':
1415 if self.history:
1416 self.history.pop()
1417 return False
1418
1419
1420
1421
1422 if self.use_rawinput == False or self.inputfile:
1423 return True
1424 elif self.mother:
1425 if self.mother.use_rawinput is False:
1426 return True
1427 elif self.mother.mother:
1428 if self.mother.mother.use_rawinput is False:
1429 return True
1430
1431
1432 if self.history:
1433 self.history.pop()
1434 return False
1435
1437 """Interpret the argument as though it had been typed in response
1438 to the prompt.
1439
1440 The return value is a flag indicating whether interpretation of
1441 commands by the interpreter should stop.
1442
1443 This allow to pass extra argument for internal call.
1444 """
1445 if '~/' in line and os.environ.has_key('HOME'):
1446 line = line.replace('~/', '%s/' % os.environ['HOME'])
1447 if '#' in line:
1448 line = line.split('#')[0]
1449
1450 line = os.path.expandvars(line)
1451 cmd, arg, line = self.parseline(line)
1452 if not line:
1453 return self.emptyline()
1454 if cmd is None:
1455 return self.default(line)
1456 self.lastcmd = line
1457 if cmd == '':
1458 return self.default(line)
1459 else:
1460 try:
1461 func = getattr(self, 'do_' + cmd)
1462 except AttributeError:
1463 return self.default(line)
1464 return func(arg, **opt)
1465
1508
1509
1510
1511 - def onecmd(self, line, **opt):
1512 """catch all error and stop properly command accordingly"""
1513
1514 try:
1515 return self.onecmd_orig(line, **opt)
1516 except BaseException, error:
1517 return self.error_handling(error, line)
1518
1519
1521 """action to perform to close nicely on a keyboard interupt"""
1522 pass
1523
1524 - def exec_cmd(self, line, errorhandling=False, printcmd=True,
1525 precmd=False, postcmd=True,
1526 child=True, **opt):
1548
1550 """for third party call, call the line with pre and postfix treatment
1551 with global error handling"""
1552
1553 return self.exec_cmd(line, errorhandling=True, precmd=True)
1554
1556 """If empty line, do nothing. Default is repeat previous command."""
1557 pass
1558
1559 - def default(self, line, log=True):
1560 """Default action if line is not recognized"""
1561
1562
1563 if log:
1564 logger.warning("Command \"%s\" not recognized, please try again" % \
1565 line.split()[0])
1566 if line.strip() in ['q', '.q', 'stop']:
1567 logger.info("If you want to quit mg5 please type \"exit\".")
1568
1569 if self.history and self.history[-1] == line:
1570 self.history.pop()
1571
1572
1573 - def do_history(self, line):
1574 """write in a file the suite of command that was used"""
1575
1576 args = self.split_arg(line)
1577
1578 self.check_history(args)
1579
1580 if len(args) == 0:
1581 logger.info('\n'.join(self.history))
1582 return
1583 elif args[0] == 'clean':
1584 self.history = []
1585 logger.info('History is cleaned')
1586 return
1587 elif args[0] == '.':
1588 output_file = os.path.join(self._export_dir, 'Cards', \
1589 'proc_card_mg5.dat')
1590 output_file = open(output_file, 'w')
1591 else:
1592 output_file = open(args[0], 'w')
1593
1594
1595 text = self.get_history_header()
1596 text += ('\n'.join(self.history) + '\n')
1597
1598
1599 output_file.write(text)
1600 output_file.close()
1601
1602 if self.log:
1603 logger.info("History written to " + output_file.name)
1604
1605 - def compile(self, *args, **opts):
1609
1610 - def avoid_history_duplicate(self, line, no_break=[]):
1611 """remove all line in history (but the last) starting with line.
1612 up to the point when a line didn't start by something in no_break.
1613 (reading in reverse order)"""
1614
1615 new_history = []
1616 for i in range(1, len(self.history)+1):
1617 cur_line = self.history[-i]
1618 if i == 1:
1619 new_history.append(cur_line)
1620 elif not any((cur_line.startswith(text) for text in no_break)):
1621 to_add = self.history[:-i+1]
1622 to_add.reverse()
1623 new_history += to_add
1624 break
1625 elif cur_line.startswith(line):
1626 continue
1627 else:
1628 new_history.append(cur_line)
1629
1630 new_history.reverse()
1631 self.history[:] = new_history
1632
1633
1635
1636 if self.history:
1637 self.history.pop()
1638
1639
1640
1641 previous_store_line = self.get_stored_line()
1642
1643
1644 if isinstance(filepath, str):
1645 commandline = open(filepath).readlines()
1646 else:
1647 commandline = filepath
1648 oldinputfile = self.inputfile
1649 oldraw = self.use_rawinput
1650 self.inputfile = (l for l in commandline)
1651 self.use_rawinput = False
1652
1653
1654
1655 for line in self.inputfile:
1656
1657
1658 line = line.replace('\n', '').strip()
1659
1660 if line:
1661 self.exec_cmd(line, precmd=True)
1662 stored = self.get_stored_line()
1663 while stored:
1664 line = stored
1665 self.exec_cmd(line, precmd=True)
1666 stored = self.get_stored_line()
1667
1668
1669 if self.child:
1670 self.child.exec_cmd('quit')
1671 self.inputfile = oldinputfile
1672 self.use_rawinput = oldraw
1673
1674
1675 cmd = self
1676 while hasattr(cmd, 'mother') and cmd.mother:
1677 cmd = cmd.mother
1678 cmd.stored_line = previous_store_line
1679 return
1680
1682 """Default history header"""
1683
1684 return self.history_header
1685
1686 - def postloop(self):
1687 """ """
1688
1689 if self.use_rawinput and self.completekey:
1690 try:
1691 import readline
1692 readline.set_completer(self.old_completer)
1693 del self.old_completer
1694 except ImportError:
1695 pass
1696 except AttributeError:
1697 pass
1698
1699 args = self.split_arg(self.lastcmd)
1700 if args and args[0] in ['quit','exit']:
1701 if 'all' in args:
1702 return True
1703 if len(args) >1 and args[1].isdigit():
1704 if args[1] not in ['0', '1']:
1705 return True
1706
1707 return False
1708
1709
1710
1711
1712 @staticmethod
1719
1720 signal.signal(signal.SIGALRM, handle_alarm)
1721
1722 if fct is None:
1723 fct = raw_input
1724
1725 if timeout:
1726 signal.alarm(timeout)
1727 question += '[%ss to answer] ' % (timeout)
1728 try:
1729 result = fct(question)
1730 except TimeOutError:
1731 if noerror:
1732 logger.info('\nuse %s' % default)
1733 if fct_timeout:
1734 fct_timeout(True)
1735 return default
1736 else:
1737 signal.alarm(0)
1738 raise
1739 finally:
1740 signal.alarm(0)
1741 if fct_timeout:
1742 fct_timeout(False)
1743 return result
1744
1745
1746
1747
1748
1749
1750
1752 """Not in help: exit the mainloop() """
1753
1754 if self.child:
1755 self.child.exec_cmd('quit ' + line, printcmd=False)
1756 return
1757 elif self.mother:
1758 self.mother.child = None
1759 if line == 'all':
1760 self.mother.do_quit('all')
1761 pass
1762 elif line:
1763 level = int(line) - 1
1764 if level:
1765 self.mother.lastcmd = 'quit %s' % level
1766 elif self.inputfile:
1767 for line in self.inputfile:
1768 logger.warning('command not executed: %s' % line.replace('\n',''))
1769
1770 return True
1771
1772
1773 do_EOF = do_quit
1774 do_exit = do_quit
1775
1777 """Not in help: propose some usefull possible action """
1778
1779
1780 if line:
1781 return super(Cmd, self).do_help(line)
1782
1783
1784 names = self.get_names()
1785 cmds = {}
1786 names.sort()
1787
1788 prevname = ''
1789 for name in names:
1790 if name[:3] == 'do_':
1791 if name == prevname:
1792 continue
1793 prevname = name
1794 cmdname=name[3:]
1795 try:
1796 doc = getattr(self.cmd, name).__doc__
1797 except Exception:
1798 doc = None
1799 if not doc:
1800 doc = getattr(self, name).__doc__
1801 if not doc:
1802 tag = "Documented commands"
1803 elif ':' in doc:
1804 tag = doc.split(':',1)[0]
1805 else:
1806 tag = "Documented commands"
1807 if tag in cmds:
1808 cmds[tag].append(cmdname)
1809 else:
1810 cmds[tag] = [cmdname]
1811
1812 self.stdout.write("%s\n"%str(self.doc_leader))
1813 for tag in self.helporder:
1814 if tag not in cmds:
1815 continue
1816 header = "%s (type help <topic>):" % tag
1817 self.print_topics(header, cmds[tag], 15,80)
1818 for name, item in cmds.items():
1819 if name in self.helporder:
1820 continue
1821 if name == "Not in help":
1822 continue
1823 header = "%s (type help <topic>):" % name
1824 self.print_topics(header, item, 15,80)
1825
1826
1827
1828 if len(self.history) == 0:
1829 last_action_2 = last_action = 'start'
1830 else:
1831 last_action_2 = last_action = 'none'
1832
1833 pos = 0
1834 authorize = self.next_possibility.keys()
1835 while last_action_2 not in authorize and last_action not in authorize:
1836 pos += 1
1837 if pos > len(self.history):
1838 last_action_2 = last_action = 'start'
1839 break
1840
1841 args = self.history[-1 * pos].split()
1842 last_action = args[0]
1843 if len(args)>1:
1844 last_action_2 = '%s %s' % (last_action, args[1])
1845 else:
1846 last_action_2 = 'none'
1847
1848 logger.info('Contextual Help')
1849 logger.info('===============')
1850 if last_action_2 in authorize:
1851 options = self.next_possibility[last_action_2]
1852 elif last_action in authorize:
1853 options = self.next_possibility[last_action]
1854 else:
1855 return
1856 text = 'The following command(s) may be useful in order to continue.\n'
1857 for option in options:
1858 text+='\t %s \n' % option
1859 logger.info(text)
1860
1862 """Advanced commands: basic display"""
1863
1864 args = self.split_arg(line)
1865
1866
1867 if len(args) == 0:
1868 self.help_display()
1869 raise self.InvalidCmd, 'display require at least one argument'
1870
1871 if args[0] == "options":
1872 outstr = "Value of current Options:\n"
1873 for key, value in self.options.items():
1874 outstr += '%25s \t:\t%s\n' %(key,value)
1875 output.write(outstr)
1876
1877 elif args[0] == "variable":
1878 outstr = "Value of Internal Variable:\n"
1879 try:
1880 var = eval(args[1])
1881 except Exception:
1882 outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1]
1883 else:
1884 outstr += 'GLOBAL:\n'
1885 outstr += misc.nice_representation(var, nb_space=4)
1886
1887 try:
1888 var = eval('self.%s' % args[1])
1889 except Exception:
1890 outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1]
1891 else:
1892 outstr += 'LOCAL:\n'
1893 outstr += misc.nice_representation(var, nb_space=4)
1894 split = args[1].split('.')
1895 for i, name in enumerate(split):
1896 try:
1897 __import__('.'.join(split[:i+1]))
1898 exec('%s=sys.modules[\'%s\']' % (split[i], '.'.join(split[:i+1])))
1899 except ImportError:
1900 try:
1901 var = eval(args[1])
1902 except Exception, error:
1903 outstr += 'EXTERNAL:\nVariable %s is not a external variable\n' % args[1]
1904 break
1905 else:
1906 outstr += 'EXTERNAL:\n'
1907 outstr += misc.nice_representation(var, nb_space=4)
1908 else:
1909 var = eval(args[1])
1910 outstr += 'EXTERNAL:\n'
1911 outstr += misc.nice_representation(var, nb_space=4)
1912
1913 pydoc.pager(outstr)
1914
1915
1916 - def do_save(self, line, check=True):
1917 """Save the configuration file"""
1918
1919 args = self.split_arg(line)
1920
1921 if check:
1922 Cmd.check_save(self, args)
1923
1924
1925 if 'HOME' in os.environ and os.environ['HOME'] and \
1926 os.path.exists(pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')):
1927 base = pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')
1928 if hasattr(self, 'me_dir'):
1929 basedir = self.me_dir
1930 elif not MADEVENT:
1931 basedir = MG5DIR
1932 else:
1933 basedir = os.getcwd()
1934 elif MADEVENT:
1935
1936 for config_file in ['me5_configuration.txt', 'amcatnlo_configuration.txt']:
1937 if os.path.exists(pjoin(self.me_dir, 'Cards', config_file)):
1938 base = pjoin(self.me_dir, 'Cards', config_file)
1939 basedir = self.me_dir
1940 else:
1941 if hasattr(self, 'me_dir'):
1942 base = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1943 if len(args) == 0 and os.path.exists(base):
1944 self.write_configuration(base, base, self.me_dir)
1945 base = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
1946 basedir = MG5DIR
1947
1948 if len(args) == 0:
1949 args.append(base)
1950 self.write_configuration(args[0], base, basedir, self.options)
1951
1953 """Write the configuration file"""
1954
1955
1956
1957
1958 logger.info('save configuration file to %s' % filepath)
1959 to_write = to_keep.keys()
1960 text = ""
1961 has_mg5_path = False
1962
1963 for line in file(basefile):
1964 if '=' in line:
1965 data, value = line.split('=',1)
1966 else:
1967 text += line
1968 continue
1969 data = data.strip()
1970 if data.startswith('#'):
1971 key = data[1:].strip()
1972 else:
1973 key = data
1974 if '#' in value:
1975 value, comment = value.split('#',1)
1976 else:
1977 comment = ''
1978 if key in to_keep:
1979 value = str(to_keep[key])
1980 else:
1981 text += line
1982 continue
1983 if key == 'mg5_path':
1984 has_mg5_path = True
1985 try:
1986 to_write.remove(key)
1987 except Exception:
1988 pass
1989 if '_path' in key:
1990
1991
1992 if not os.path.isabs(value):
1993 value = os.path.realpath(os.path.join(basedir, value))
1994 text += '%s = %s # %s \n' % (key, value, comment)
1995 for key in to_write:
1996 if key in to_keep:
1997 text += '%s = %s \n' % (key, to_keep[key])
1998
1999 if not MADEVENT and not has_mg5_path:
2000 text += """\n# MG5 MAIN DIRECTORY\n"""
2001 text += "mg5_path = %s\n" % MG5DIR
2002
2003 writer = open(filepath,'w')
2004 writer.write(text)
2005 writer.close()
2006
2011 """CMD command with shell activate"""
2012
2013
2015 "Run a shell command"
2016
2017 if line.strip() is '':
2018 self.help_shell()
2019 else:
2020 logging.info("running shell command: " + line)
2021 subprocess.call(line, shell=True)
2022
2037
2039 """help for the shell"""
2040 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')
2041 logger.info("syntax: shell CMD (or ! CMD)",'$MG:BOLD')
2042
2046
2050 """ a class for answering a question with the path autocompletion"""
2051
2052 allowpath = False
2054 """Initializing before starting the main loop"""
2055 self.prompt = '>'
2056 self.value = None
2057 BasicCmd.preloop(self)
2058
2059 @property
2062
2063 - def __init__(self, question, allow_arg=[], default=None,
2064 mother_interface=None, *arg, **opt):
2065
2066 self.question = question
2067 self.wrong_answer = 0
2068 self.allow_arg = [str(a) for a in allow_arg]
2069 self.history_header = ''
2070 self.default_value = str(default)
2071 self.mother_interface = mother_interface
2072
2073 if 'case' in opt:
2074 self.casesensitive = opt['case']
2075 del opt['case']
2076 elif 'casesensitive' in opt:
2077 self.casesensitive = opt['casesensitive']
2078 del opt['casesensitive']
2079 else:
2080 self.casesensistive = True
2081 super(SmartQuestion, self).__init__(*arg, **opt)
2082
2083 - def __call__(self, question, reprint_opt=True, **opts):
2084
2085 self.question = question
2086 for key,value in opts:
2087 setattr(self, key, value)
2088 if reprint_opt:
2089 print question
2090 logger_tuto.info("Need help here? type 'help'", '$MG:BOLD')
2091 logger_plugin.info("Need help here? type 'help'" , '$MG:BOLD')
2092 return self.cmdloop()
2093
2094
2096 prev_timer = signal.alarm(0)
2097 if prev_timer:
2098 nb_back = len(line)
2099 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2100 self.stdout.write(line)
2101 self.stdout.flush()
2102 try:
2103 out = {}
2104 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
2105 out[' Recognized command'] = super(SmartQuestion, self).completenames(text,line, *ignored)
2106
2107 return self.deal_multiple_categories(out)
2108 except Exception, error:
2109 print error
2110
2111 completedefault = completenames
2112
2114
2115
2116 return dir(self)
2117
2118 - def onecmd(self, line, **opt):
2119 """catch all error and stop properly command accordingly
2120 Interpret the argument as though it had been typed in response
2121 to the prompt.
2122
2123 The return value is a flag indicating whether interpretation of
2124 commands by the interpreter should stop.
2125
2126 This allow to pass extra argument for internal call.
2127 """
2128 try:
2129 if '~/' in line and os.environ.has_key('HOME'):
2130 line = line.replace('~/', '%s/' % os.environ['HOME'])
2131 line = os.path.expandvars(line)
2132 cmd, arg, line = self.parseline(line)
2133 if not line:
2134 return self.emptyline()
2135 if cmd is None:
2136 return self.default(line)
2137 self.lastcmd = line
2138 if cmd == '':
2139 return self.default(line)
2140 else:
2141 try:
2142 func = getattr(self, 'do_' + cmd)
2143 except AttributeError:
2144 return self.default(line)
2145 return func(arg, **opt)
2146 except Exception as error:
2147 logger.warning(error)
2148 if __debug__:
2149 raise
2150
2151 - def reask(self, reprint_opt=True):
2152 pat = re.compile('\[(\d*)s to answer\]')
2153 prev_timer = signal.alarm(0)
2154
2155 if prev_timer:
2156 if pat.search(self.question):
2157 timeout = int(pat.search(self.question).groups()[0])
2158 signal.alarm(timeout)
2159 if reprint_opt:
2160 if not prev_timer:
2161 self.question = pat.sub('',self.question)
2162 print self.question.encode('utf8')
2163
2164 if self.mother_interface:
2165 answer = self.mother_interface.check_answer_in_input_file(self, 'EOF',
2166 path=self.allowpath)
2167 if answer:
2168 stop = self.default(answer)
2169 self.postcmd(stop, answer)
2170 return False
2171
2172 return False
2173
2175
2176 text=line
2177 out ={}
2178 out['Options'] = Cmd.list_completion(text, self.allow_arg)
2179 out['command'] = BasicCmd.completenames(self, text)
2180
2181 if not text:
2182 if out['Options']:
2183 logger.info( "Here is the list of all valid options:", '$MG:BOLD')
2184 logger.info( " "+ "\n ".join(out['Options']))
2185 if out['command']:
2186 logger.info( "Here is the list of command available:", '$MG:BOLD')
2187 logger.info( " "+ "\n ".join(out['command']))
2188 else:
2189 if out['Options']:
2190 logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:BOLD')
2191 logger.info( " "+ "\n ".join(out['Options']))
2192 if out['command']:
2193 logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:BOLD')
2194 logger.info( " "+ "\n ".join(out['command']))
2195 elif not out['Options']:
2196 logger.info( "No possibility starting with \'%s\'" % text, '$MG:BOLD')
2197 logger.info( "You can type help XXX, to see all command starting with XXX", '$MG:BOLD')
2201
2203 """Default action if line is not recognized"""
2204
2205 if line.strip() == '' and self.default_value is not None:
2206 self.value = self.default_value
2207 else:
2208 self.value = line
2209
2211 """If empty line, return default"""
2212
2213 if self.default_value is not None:
2214 self.value = self.default_value
2215
2216
2217 - def postcmd(self, stop, line):
2218
2219 try:
2220 if self.value in self.allow_arg:
2221 return True
2222 elif str(self.value) == 'EOF':
2223 self.value = self.default_value
2224 return True
2225 elif line and hasattr(self, 'do_%s' % line.split()[0]):
2226 return self.reask()
2227 elif self.value in ['repeat', 'reask']:
2228 return self.reask()
2229 elif len(self.allow_arg)==0:
2230 return True
2231 elif ' ' in line.strip() and '=' in self.value:
2232 line,n = re.subn(r'\s*=\s*', '=', line)
2233 if n:
2234 self.default(line)
2235 return self.postcmd(stop, line)
2236 if not self.casesensitive:
2237 for ans in self.allow_arg:
2238 if ans.lower() == self.value.lower():
2239 self.value = ans
2240 return True
2241 break
2242 else:
2243 raise Exception
2244
2245
2246 else:
2247 raise Exception
2248 except Exception,error:
2249 if self.wrong_answer < 100:
2250 self.wrong_answer += 1
2251 logger.warning("""%s not valid argument. Valid argument are in (%s).""" \
2252 % (self.value,','.join(self.allow_arg)))
2253 logger.warning('please retry')
2254 return False
2255 else:
2256 self.value = self.default_value
2257 return True
2258
2262
2268
2273 """ a class for answering a question with the path autocompletion"""
2274
2275 completion_prefix=''
2276 allowpath=True
2277
2278 - def completenames(self, text, line, begidx, endidx, formatting=True):
2279 prev_timer = signal.alarm(0)
2280 if prev_timer:
2281 nb_back = len(line)
2282 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2283 self.stdout.write(line)
2284 self.stdout.flush()
2285
2286 try:
2287 out = {}
2288 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
2289 out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False)
2290 out[' Recognized command'] = BasicCmd.completenames(self, text, line, begidx, endidx)
2291
2292 return self.deal_multiple_categories(out, formatting)
2293 except Exception, error:
2294 print error
2295
2301
2303 prev_timer = signal.alarm(0)
2304 if prev_timer:
2305 nb_back = len(line)
2306 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2307 self.stdout.write(line)
2308 self.stdout.flush()
2309 try:
2310 args = Cmd.split_arg(line[0:begidx])
2311 except Exception, error:
2312 print error
2313
2314
2315 if args[-1].endswith(os.path.sep):
2316
2317 return Cmd.path_completion(text,
2318 os.path.join('.',*[a for a in args \
2319 if a.endswith(os.path.sep)]),
2320 begidx, endidx)
2321 return self.completenames(text, line, begidx, endidx)
2322
2323
2324 - def postcmd(self, stop, line):
2325 try:
2326 if self.value in self.allow_arg:
2327 return True
2328 elif self.value and os.path.isfile(self.value):
2329 return os.path.relpath(self.value)
2330 elif self.value and str(self.value) == 'EOF':
2331 self.value = self.default_value
2332 return True
2333 elif line and hasattr(self, 'do_%s' % line.split()[0]):
2334
2335 reprint_opt = True
2336 elif self.value in ['repeat', 'reask']:
2337 reprint_opt = True
2338 else:
2339 raise Exception
2340 except Exception, error:
2341 print """not valid argument. Valid argument are file path or value in (%s).""" \
2342 % ','.join(self.allow_arg)
2343 print 'please retry'
2344 reprint_opt = False
2345
2346 if line != 'EOF':
2347 return self.reask(reprint_opt)
2348
2355
2359 """A class for asking a question on which program to run.
2360 This is the abstract class
2361
2362 Behavior for each switch can be customize via:
2363 set_default_XXXX() -> set default value
2364 This is super-seeded by self.default_switch if that attribute is defined (and has a key for XXXX)
2365 get_allowed_XXXX() -> return list of possible value
2366 check_value_XXXX(value) -> return True/False if the user can set such value
2367 switch_off_XXXXX() -> set it off (called for special mode)
2368 color_for_XXXX(value) -> return the representation on the screen for value
2369 get_cardcmd_for_XXXX(value)> return the command to run to customize the cards to
2370 match the status
2371 print_options_XXXX() -> return the text to disply below "other options"
2372 default is other possible value (ordered correctly)
2373
2374 consistency_XX_YY(val_XX, val_YY)
2375 -> XX is the new key set by the user to a new value val_XX
2376 -> YY is another key set by the user.
2377 -> return value should be None or "replace_YY"
2378
2379 consistency_XX(val_XX):
2380 check the consistency of the other switch given the new status of this one.
2381 return a dict {key:replaced_value} or {} if nothing to do
2382
2383 user typing "NAME" will result to a call to self.ans_NAME(None)
2384 user typing "NAME=XX" will result to a call to self.ans_NAME('XX')
2385
2386 Note on case sensitivity:
2387 -------------------------
2388 the XXX is displayed with the case in self.to_control
2389 but ALL functions should use the lower case version.
2390 for key associated to get_allowed_keys(),
2391 if (user) value not in that list.
2392 -> try to find the first entry matching up to the case
2393 for ans_XXX, set the value to lower case, but if case_XXX is set to True
2394 """
2395
2396 case_sensitive = False
2397 quit_on = ['0','done', 'EOF','','auto']
2398
2399 - def __init__(self, to_control, motherinstance, *args, **opts):
2400 """to_control is a list of ('KEY': 'Choose the shower/hadronization program')
2401 """
2402
2403 self.to_control = to_control
2404 self.mother_interface = motherinstance
2405 self.inconsistent_keys = {}
2406
2407
2408 self.inconsistent_details = {}
2409 self.last_changed = []
2410
2411
2412 self.switch = {}
2413 for key, _ in to_control:
2414 self.switch[key.lower()] = 'temporary'
2415
2416 self.set_default_switch()
2417 question = self.create_question()
2418
2419
2420 allowed_args = [ `i`+';' for i in range(1, 1+len(self.to_control))]
2421 for key in self.switch:
2422 allowed_args += ['%s=%s;' % (key,s) for s in self.get_allowed(key)]
2423
2424 allowed_args += [key[4:]+';' for key in dir(self) if key.startswith('ans_')]
2425 allowed_args += [arg[:-1] for arg in allowed_args if arg[-1] == ';']
2426 if 'allow_arg' in opts:
2427 allowed_args += opts['allow_arg']
2428 del opts['allow_arg']
2429
2430 allowed_args +=["0", "done"]
2431 SmartQuestion.__init__(self, question, allowed_args, *args, **opts)
2432 self.options = self.mother_interface.options
2433
2460
2461
2462
2463
2464
2466
2467 for key,_ in self.to_control:
2468 key = key.lower()
2469 if hasattr(self, 'default_switch') and key in self.default_switch:
2470 self.switch[key] = self.default_switch[key]
2471 continue
2472 if hasattr(self, 'set_default_%s' % key):
2473 getattr(self, 'set_default_%s' % key)()
2474 else:
2475 self.default_switch_for(key)
2476
2478 """use this if they are no dedicated function for such key"""
2479
2480 if hasattr(self, 'get_allowed_%s' % key):
2481 return getattr(self, 'get_allowed_%s' % key)()[0]
2482 else:
2483 self.switch[key] = 'OFF'
2484
2486 """set all valid parameter to OFF --call before special keyword--
2487 """
2488
2489 for key in self.switch:
2490 if hasattr(self, 'switch_off_%s' % key):
2491 getattr(self, 'switch_off_%s' % key)()
2492 elif self.check_value(key, self.switch[key]):
2493 self.switch[key] = 'OFF'
2494 self.inconsistent_details = {}
2495 self.inconsistent_keys = {}
2496
2497
2499 """return True/False if the value is a correct value to be set by the USER.
2500 other value than those can be set by the system --like-- Not available.
2501 This does not check the full consistency of the switch
2502 """
2503
2504 if hasattr(self, 'check_value_%s' % key):
2505 return getattr(self, 'check_value_%s' % key)(value)
2506 elif value in self.get_allowed(key):
2507 return True
2508 else:
2509 return False
2510
2511
2513 """ return the list of command that need to be run to have a consistent
2514 set of cards with the switch value choosen """
2515
2516 switch = self.answer
2517 cmd= []
2518 for key in self.switch:
2519 if hasattr(self, 'get_cardcmd_for_%s' % key):
2520 cmd += getattr(self, 'get_cardcmd_for_%s' % key)(switch[key])
2521 return cmd
2522
2523
2525 """return the list of possible value for key"""
2526
2527 if hasattr(self, 'get_allowed_%s' % key):
2528 return getattr(self, 'get_allowed_%s' % key)()
2529 else:
2530 return ['ON', 'OFF']
2531
2532 - def default(self, line, raise_error=False):
2533 """Default action if line is not recognized"""
2534
2535 line=line.strip().replace('@', '__at__')
2536 if ';' in line:
2537 for l in line.split(';'):
2538 if l:
2539 out = self.default(l)
2540 return out
2541
2542 if '=' in line:
2543 base, value = line.split('=',1)
2544 base = base.strip()
2545 value = value.strip()
2546
2547 if base.isdigit() :
2548 try:
2549 base = self.to_control[int(base)-1][0]
2550 except:
2551 pass
2552 elif ' ' in line:
2553 base, value = line.split(' ', 1)
2554 elif hasattr(self, 'ans_%s' % line.lower()):
2555 base, value = line.lower(), None
2556 elif line.isdigit() and line in [`i` for i in range(1, len(self.to_control)+1)]:
2557
2558 base = self.to_control[int(line)-1][0].lower()
2559 return self.default(base)
2560 elif line.lower() in self.switch:
2561
2562 base = line.lower()
2563 try:
2564 cur = self.get_allowed(base).index(self.switch[base])
2565 except:
2566 if self.get_allowed(base):
2567 value = self.get_allowed(base)[0]
2568 else:
2569 logger.warning('Can not switch "%s" to another value via number', base)
2570 self.value='reask'
2571 return
2572 else:
2573 try:
2574 value = self.get_allowed(base)[cur+1]
2575 except IndexError:
2576 value = self.get_allowed(base)[0]
2577 if value == "OFF" and cur == 0:
2578 logger.warning("Invalid action: %s" % self.print_options(base))
2579 elif cur == 0:
2580 logger.warning("Can not change value for this parameter")
2581
2582
2583 elif line in ['', 'done', 'EOF', 'eof','0']:
2584 super(ControlSwitch, self).default(line)
2585 return self.answer
2586 elif line in 'auto':
2587 self.switch['dynamical'] = True
2588 return super(ControlSwitch, self).default(line)
2589 elif line.startswith('set ') and not hasattr(self.__class__, 'do_set'):
2590 raise NotValidInput('unknow command: %s. Did you mean \"%s\"' % (line, line[4:]))
2591 elif raise_error:
2592 raise NotValidInput('unknow command: %s' % line)
2593 else:
2594 logger.warning('unknow command: %s' % line)
2595 self.value = 'reask'
2596 return
2597
2598 self.value = 'reask'
2599 base = base.lower()
2600 if hasattr(self, 'ans_%s' % base):
2601 if value and not self.is_case_sensitive(base):
2602 value = value.lower()
2603 getattr(self, 'ans_%s' % base)(value)
2604 elif base in self.switch:
2605 self.set_switch(base, value)
2606 elif line.startswith('set ') and not hasattr(self.__class__, 'do_set'):
2607 raise NotValidInput('Not valid command: %s. Did you mean \"%s\"' % (line, line[4:]))
2608 elif raise_error:
2609 raise NotValidInput('Not valid command: %s' % line)
2610 else:
2611 logger.warning('Not valid command: %s' % line)
2612
2614 """check if a key is case sensitive"""
2615
2616 case = self.case_sensitive
2617 if hasattr(self, 'case_%s' % key):
2618 case = getattr(self, 'case_%s' % key)
2619 return case
2620
2621 - def onecmd(self, line, **opt):
2626
2627 @property
2629
2630
2631 for key,_ in self.to_control:
2632 if not self.check_value(key, self.switch[key]):
2633 self.switch[key] = 'OFF'
2634
2635 if not self.inconsistent_keys:
2636 return self.switch
2637 else:
2638 out = dict(self.switch)
2639 out.update(self.inconsistent_keys)
2640 return out
2641
2642 - def postcmd(self, stop, line):
2643
2644
2645
2646 try:
2647 out = super(ControlSwitch,self).postcmd(stop, line)
2648 except AttributeError:
2649 pass
2650 if out:
2651 return out
2652
2653 line = line.strip()
2654 if ';' in line:
2655 line= [l for l in line.split(';') if l][-1]
2656 if line in self.quit_on or self.value in self.quit_on:
2657 return True
2658 if self.value != 'reask':
2659 self.create_question()
2660 return self.reask(True)
2661 return
2662
2664 """change a switch to a given value"""
2665
2666 assert key in self.switch
2667
2668 if hasattr(self, 'ans_%s' % key):
2669 if not self.is_case_sensitive(key):
2670 value = value.lower()
2671 return getattr(self, 'ans_%s' % key)(value)
2672
2673 if not self.is_case_sensitive(key) and value not in self.get_allowed(key):
2674 lower = [t.lower() for t in self.get_allowed(key)]
2675 try:
2676 ind = lower.index(value.lower())
2677 except ValueError:
2678 pass
2679 else:
2680 value = self.get_allowed(key)[ind]
2681
2682 check = self.check_value(key, value)
2683 if not check:
2684 logger.warning('"%s" not valid option for "%s"', value, key)
2685 return
2686 if isinstance(check, str):
2687 value = check
2688
2689 self.switch[key] = value
2690
2691 if user:
2692 self.check_consistency(key, value)
2693
2695
2696 if not keys:
2697 self.inconsistent_keys = {}
2698 self.inconsistent_details = {}
2699 elif isinstance(keys, list):
2700 for key in keys:
2701 if key in self.inconsistent_keys:
2702 del self.inconsistent_keys[keys]
2703 del self.inconsistent_details[keys]
2704 else:
2705 if keys in self.inconsistent_keys:
2706 del self.inconsistent_keys[keys]
2707 del self.inconsistent_details[keys]
2708
2710 """check the consistency of the new flag with the old ones"""
2711
2712
2713 if key in self.last_changed:
2714 self.last_changed.remove(key)
2715 self.last_changed.append(key)
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729 if hasattr(self, 'consistency_%s' % key):
2730 rules = dict([(key2, None) for key2 in self.switch])
2731 rules.update(getattr(self, 'consistency_%s' % key)(value, self.switch))
2732 else:
2733 rules = {}
2734 for key2,value2 in self.switch.items():
2735 if hasattr(self, 'consistency_%s_%s' % (key,key2)):
2736 rules[key2] = getattr(self, 'consistency_%s_%s' % (key,key2))(value, value2)
2737
2738
2739 if rules[key2] is not None and not self.check_value(key2, rules[key2]):
2740 if rules[key2] != 'OFF':
2741 logger.debug('consistency_%s_%s returns invalid output. Assume no conflict')
2742 rules[key2] = None
2743 else:
2744 rules[key2] = None
2745
2746
2747
2748
2749
2750 self.remove_inconsistency(key)
2751
2752 for key2 in self.switch:
2753 if rules[key2]:
2754 info = {'orig_value': self.switch[key2],
2755 'changed_key': key,
2756 'new_changed_key_val': value,
2757 'replacement': rules[key2]}
2758 if key2 in self.inconsistent_details:
2759 self.inconsistent_details[key2].append(info)
2760 else:
2761 self.inconsistent_details[key2] = [info]
2762
2763 if not self.inconsistent_details:
2764 return
2765
2766
2767 for key2 in dict(self.inconsistent_details):
2768 for conflict in list(self.inconsistent_details[key2]):
2769 keep_conflict = True
2770
2771 if conflict['orig_value'] != self.switch[key2]:
2772 keep_conflict = False
2773
2774 if self.switch[conflict['changed_key']] != conflict['new_changed_key_val']:
2775 keep_conflict = False
2776 if not keep_conflict:
2777 self.inconsistent_details[key2].remove(conflict)
2778 if not self.inconsistent_details[key2]:
2779 del self.inconsistent_details[key2]
2780
2781
2782
2783
2784 tmp_switch = dict(self.switch)
2785
2786
2787 to_check = [(c['changed_key'], c['new_changed_key_val']) \
2788 for k in self.inconsistent_details.values() for c in k
2789 if c['changed_key'] != key]
2790
2791 to_check.sort(lambda x, y: -1 if self.last_changed.index(x[0])>self.last_changed.index(y[0]) else 1)
2792
2793
2794 to_check = [(key, value)] + to_check
2795
2796 i = 0
2797 while len(to_check) and i < 50:
2798
2799
2800 i +=1
2801 key2, value2 = to_check.pop(0)
2802 if hasattr(self, 'consistency_%s' % key2):
2803 rules2 = dict([(key2, None) for key2 in self.switch])
2804 rules2.update(getattr(self, 'consistency_%s' % key2)(value, tmp_switch))
2805 else:
2806 rules = {}
2807 for key3,value3 in self.switch.items():
2808 if hasattr(self, 'consistency_%s_%s' % (key2,key3)):
2809 rules[key3] = getattr(self, 'consistency_%s_%s' % (key2,key3))(value2, value3)
2810 else:
2811 rules[key3] = None
2812
2813 for key, replacement in rules.items():
2814 if replacement:
2815 tmp_switch[key] = replacement
2816 to_check.append((key, replacement))
2817
2818
2819
2820 pos = {}
2821 for i, (key,value) in enumerate(to_check):
2822 pos[key] = i
2823 to_check_new = []
2824 for i, (key,value) in enumerate(to_check):
2825 if pos[key] == i:
2826 to_check_new.append((key,value))
2827 to_check = to_check_new
2828 if i>=50:
2829 logger.critical('Failed to find a consistent set of switch values.')
2830
2831
2832
2833 self.inconsistent_keys = {}
2834 for key2, value2 in tmp_switch.items():
2835 if value2 != self.switch[key2]:
2836
2837 if value2 == 'OFF' and not self.check_value(key2, 'OFF'):
2838 continue
2839 self.inconsistent_keys[key2] = value2
2840
2841
2842
2843
2844 green = '\x1b[32m%s\x1b[0m'
2845 yellow = '\x1b[33m%s\x1b[0m'
2846 red = '\x1b[31m%s\x1b[0m'
2847 bold = '\x1b[01m%s\x1b[0m'
2849
2850 if consistency and key in self.inconsistent_keys:
2851 return self.color_for_value(key, self.inconsistent_keys[key], consistency=False) +\
2852 u' \u21d0 '+ self.yellow % switch_value
2853
2854 if self.check_value(key, switch_value):
2855 if hasattr(self, 'color_for_%s' % key):
2856 return getattr(self, 'color_for_%s' % key)(switch_value)
2857 if switch_value in ['OFF']:
2858
2859 return self.red % switch_value
2860 else:
2861 return self.green % switch_value
2862 else:
2863 if ' ' in switch_value:
2864 return self.bold % switch_value
2865 else:
2866 return self.red % switch_value
2867
2869
2870 if hasattr(self, 'print_options_%s' % key) and not keep_default:
2871 return getattr(self, 'print_options_%s' % key)()
2872
2873
2874 try:
2875 ind = self.get_allowed(key).index(self.switch[key])
2876 except Exception, err:
2877 options = self.get_allowed(key)
2878 else:
2879 options = self.get_allowed(key)[ind:]+ self.get_allowed(key)[:ind]
2880
2881 info = '|'.join([v for v in options if v != self.switch[key]])
2882 if info == '':
2883 info = 'Please install module'
2884 return info
2885
2886 - def do_help(self, line, list_command=False):
2887 """dedicated help for the control switch"""
2888
2889 if line:
2890 return self.print_help_for_switch(line)
2891
2892
2893 logger.info(" ")
2894 logger.info(" In order to change a switch you can:")
2895 logger.info(" - type 'NAME = VALUE' to set the switch NAME to a given value.")
2896 logger.info(" - type 'ID = VALUE' to set the switch correspond to the line ID to a given value.")
2897 logger.info(" - type 'ID' where ID is the value of the line to pass from one value to the next.")
2898 logger.info(" - type 'NAME' to set the switch NAME to the next value.")
2899 logger.info("")
2900 logger.info(" You can type 'help NAME' for more help on a given switch")
2901 logger.info("")
2902 logger.info(" Special keyword:", '$MG:BOLD')
2903 logger.info(" %s" % '\t'.join([p[4:] for p in dir(self) if p.startswith('ans_')]) )
2904 logger.info(" type 'help XXX' for more information")
2905 if list_command:
2906 super(ControlSwitch, self).do_help(line)
2907
2908
2910 """ """
2911
2912 arg = line.split()[0]
2913
2914 if hasattr(self, 'help_%s' % arg):
2915 return getattr(self, 'help_%s' % arg)('')
2916
2917 if hasattr(self, 'ans_%s' % arg):
2918 return getattr(self, 'help_%s' % arg).__doc__
2919
2920 if arg in self.switch:
2921 logger.info(" information for switch %s: ", arg, '$MG:BOLD')
2922 logger.info(" allowed value:")
2923 logger.info(" %s", '\t'.join(self.get_allowed(arg)))
2924 if hasattr(self, 'help_text_%s' % arg):
2925 logger.info("")
2926 for line in getattr(self, 'help_text_%s' % arg):
2927 logger.info(line)
2928
2929
2930
2931
3103
3105 """ create the question with correct formatting"""
3106
3107
3108
3109 try:
3110 nb_rows, nb_col = os.popen('stty size', 'r').read().split()
3111 nb_rows, nb_col = int(nb_rows), int(nb_col)
3112 except Exception,error:
3113 nb_rows, nb_col = 20, 80
3114
3115
3116 max_len_description = 0
3117 max_len_switch = 0
3118 max_len_name = 0
3119 max_len_add_info = 0
3120 max_len_potential_switch = 0
3121 max_nb_key = 1 + int(math.log10(len(self.to_control)))
3122
3123 for key, descrip in self.to_control:
3124 if len(descrip) > max_len_description: max_len_description = len(descrip)
3125 if len(key) > max_len_name: max_len_name = len(key)
3126 if key in self.inconsistent_keys:
3127 to_display = '%s < %s' % (self.switch[key], self.inconsistent_keys[key])
3128 else:
3129 to_display = self.switch[key]
3130 if len(to_display) > max_len_switch: max_len_switch=len(to_display)
3131
3132 info = self.print_options(key)
3133 if len(info)> max_len_add_info: max_len_add_info = len(info)
3134
3135 if self.get_allowed(key):
3136 max_k = max(len(k) for k in self.get_allowed(key))
3137 else:
3138 max_k = 0
3139 if max_k > max_len_potential_switch: max_len_potential_switch = max_k
3140
3141 upper_line, lower_line, f1, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3142 max_len_name, max_len_add_info,
3143 max_len_potential_switch, max_nb_key)
3144
3145 text = \
3146 ["The following switches determine which programs are run:",
3147 upper_line
3148 ]
3149
3150
3151
3152 for i,(key, descrip) in enumerate(self.to_control):
3153
3154
3155
3156 data_to_format = {'nb': i+1,
3157 'descrip': descrip,
3158 'name': key,
3159 'switch': self.color_for_value(key,self.switch[key]),
3160 'add_info': self.print_options(key),
3161 'switch_nc': self.switch[key],
3162 'strike_switch': u'\u0336'.join(' %s ' %self.switch[key].upper()) + u'\u0336',
3163 }
3164 if key in self.inconsistent_keys:
3165
3166 _,_,_, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3167 max_len_name, max_len_add_info,
3168 max_len_potential_switch, max_nb_key,
3169 key=key)
3170
3171 data_to_format['conflict_switch_nc'] = self.inconsistent_keys[key]
3172 data_to_format['conflict_switch'] = self.color_for_value(key,self.inconsistent_keys[key], consistency=False)
3173 text.append(f2 % data_to_format)
3174 else:
3175 text.append(f1 % data_to_format)
3176
3177
3178 text.append(lower_line)
3179
3180
3181 example = None
3182 for key in self.switch:
3183 if len(self.get_allowed(key)) > 1:
3184 for val in self.get_allowed(key):
3185 if val != self.switch[key]:
3186 example = (key, val)
3187 break
3188 else:
3189 continue
3190 break
3191
3192 if not example:
3193 example = ('KEY', 'VALUE')
3194
3195 if help_text:
3196 text += \
3197 ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
3198 "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
3199 "Type 'help' for the list of all valid option",
3200 "Type '0', 'auto', 'done' or just press enter when you are done."]
3201
3202
3203 if len(text) > nb_rows:
3204
3205 to_remove = [ -2,
3206 -5,
3207 -4,
3208 -3,
3209 -1,
3210 ]
3211 to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
3212 text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
3213
3214 self.question = "\n".join(text)
3215 return self.question
3216
3217
3218
3219
3220
3221 -class CmdFile(file):
3222 """ a class for command input file -in order to debug cmd \n problem"""
3223
3230
3232 """readline method treating correctly a line whithout \n at the end
3233 (add it)
3234 """
3235 if self.lines:
3236 line = self.lines.pop(0)
3237 else:
3238 return ''
3239
3240 if line.endswith('\n'):
3241 return line
3242 else:
3243 return line + '\n'
3244
3247
3250