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 = line.split()
649 out=[]
650 tmp=''
651 for data in split:
652 if data[-1] == '\\':
653 tmp += data[:-1]+' '
654 elif tmp:
655 tmp += data
656 tmp = os.path.expanduser(os.path.expandvars(tmp))
657 out.append(tmp)
658
659
660 tmp = ''
661 else:
662 out.append(data)
663 return out
664
665 @staticmethod
667 """Propose completions of text in list"""
668
669 if not text:
670 completions = list
671 else:
672 completions = [ f
673 for f in list
674 if f.startswith(text)
675 ]
676
677 return completions
678
679
680 @staticmethod
681 - def path_completion(text, base_dir = None, only_dirs = False,
682 relative=True):
683 """Propose completions of text to compose a valid path"""
684
685 if base_dir is None:
686 base_dir = os.getcwd()
687 base_dir = os.path.expanduser(os.path.expandvars(base_dir))
688
689 if text == '~':
690 text = '~/'
691 prefix, text = os.path.split(text)
692 prefix = os.path.expanduser(os.path.expandvars(prefix))
693 base_dir = os.path.join(base_dir, prefix)
694 if prefix:
695 prefix += os.path.sep
696
697 if only_dirs:
698 completion = [prefix + f + os.path.sep
699 for f in os.listdir(base_dir)
700 if f.startswith(text) and \
701 os.path.isdir(os.path.join(base_dir, f)) and \
702 (not f.startswith('.') or text.startswith('.'))
703 ]
704 else:
705 completion = [ prefix + f
706 for f in os.listdir(base_dir)
707 if f.startswith(text) and \
708 os.path.isfile(os.path.join(base_dir, f)) and \
709 (not f.startswith('.') or text.startswith('.'))
710 ]
711
712 completion = completion + \
713 [prefix + f + os.path.sep
714 for f in os.listdir(base_dir)
715 if f.startswith(text) and \
716 os.path.isdir(os.path.join(base_dir, f)) and \
717 (not f.startswith('.') or text.startswith('.'))
718 ]
719
720 if relative:
721 completion += [prefix + f for f in ['.'+os.path.sep, '..'+os.path.sep] if \
722 f.startswith(text) and not prefix.startswith('.')]
723
724 completion = [a.replace(' ','\ ') for a in completion]
725 return completion
726
731 """Extension of the cmd object for only the check command"""
732
733 - def check_history(self, args):
734 """check the validity of line"""
735
736 if len(args) > 1:
737 self.help_history()
738 raise self.InvalidCmd('\"history\" command takes at most one argument')
739
740 if not len(args):
741 return
742
743 if args[0] =='.':
744 if not self._export_dir:
745 raise self.InvalidCmd("No default directory is defined for \'.\' option")
746 elif args[0] != 'clean':
747 dirpath = os.path.dirname(args[0])
748 if dirpath and not os.path.exists(dirpath) or \
749 os.path.isdir(args[0]):
750 raise self.InvalidCmd("invalid path %s " % dirpath)
751
753 """check that the line is compatible with save options"""
754
755 if len(args) > 2:
756 self.help_save()
757 raise self.InvalidCmd, 'too many arguments for save command.'
758
759 if len(args) == 2:
760 if args[0] != 'options':
761 self.help_save()
762 raise self.InvalidCmd, '\'%s\' is not recognized as first argument.' % \
763 args[0]
764 else:
765 args.pop(0)
766
768 """Extension of the cmd object for only the help command"""
769
771 logger.info("-- terminates the application",'$MG:color:BLUE')
772 logger.info("syntax: quit",'$MG:BOLD')
773
774 help_EOF = help_quit
775
776 - def help_history(self):
777 logger.info("-- interact with the command history.",'$MG:color:BLUE')
778 logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:BOLD')
779 logger.info(" > If FILEPATH is \'.\' and \'output\' is done,")
780 logger.info(" Cards/proc_card_mg5.dat will be used.")
781 logger.info(" > If FILEPATH is omitted, the history will be output to stdout.")
782 logger.info(" \"clean\" will remove all entries from the history.")
783
785 logger.info("-- access to the in-line help",'$MG:color:BLUE')
786 logger.info("syntax: help",'$MG:BOLD')
787
789 """help text for save"""
790 logger.info("-- save options configuration to filepath.",'$MG:color:BLUE')
791 logger.info("syntax: save [options] [FILEPATH]",'$MG:BOLD')
792
794 """help for display command"""
795 logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE')
796 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:BOLD')
797
806
807 - def complete_history(self, text, line, begidx, endidx):
808 "Complete the history command"
809
810 args = self.split_arg(line[0:begidx])
811
812
813 if args[-1].endswith(os.path.sep):
814 return self.path_completion(text,
815 os.path.join('.',*[a for a in args \
816 if a.endswith(os.path.sep)]))
817
818 if len(args) == 1:
819 return self.path_completion(text)
820
839
840 -class Cmd(CheckCmd, HelpCmd, CompleteCmd, BasicCmd):
841 """Extension of the cmd.Cmd command line.
842 This extensions supports line breaking, history, comments,
843 internal call to cmdline, path completion,...
844 this class should be MG5 independent"""
845
846
847 next_possibility = {}
848 history_header = ""
849
850 _display_opts = ['options','variable']
851 allow_notification_center = True
852
854 """expected error for wrong command"""
855 pass
856
857 ConfigurationError = InvalidCmd
858
859 debug_output = 'debug'
860 error_debug = """Please report this bug to developers\n
861 More information is found in '%(debug)s'.\n
862 Please attach this file to your report."""
863 config_debug = error_debug
864
865 keyboard_stop_msg = """stopping all current operation
866 in order to quit the program please enter exit"""
867
868 if MADEVENT:
869 plugin_path = []
870 else:
871 plugin_path = [pjoin(MG5DIR, 'PLUGIN')]
872 if 'PYTHONPATH' in os.environ:
873 for PluginCandidate in os.environ['PYTHONPATH'].split(':'):
874 try:
875 dirlist = os.listdir(PluginCandidate)
876 except OSError:
877 continue
878 for onedir in dirlist:
879 if onedir == 'MG5aMC_PLUGIN':
880 plugin_path.append(pjoin(PluginCandidate, 'MG5aMC_PLUGIN'))
881 break
882 else:
883 continue
884 break
885
887 """Init history and line continuation"""
888
889 self.log = True
890 self.history = []
891 self.save_line = ''
892 super(Cmd, self).__init__(*arg, **opt)
893 self.__initpos = os.path.abspath(os.getcwd())
894 self.child = None
895 self.mother = None
896 self.inputfile = None
897 self.haspiping = not sys.stdin.isatty()
898 self.stored_line = ''
899
900 if not hasattr(self, 'helporder'):
901 self.helporder = ['Documented commands']
902
904 """Hook method executed once when the cmdloop() method is called."""
905 if self.completekey:
906 try:
907 import readline
908 self.old_completer = readline.get_completer()
909 readline.set_completer(self.complete)
910 readline.parse_and_bind(self.completekey+": complete")
911 except ImportError:
912 readline = None
913 pass
914 if readline and not 'libedit' in readline.__doc__:
915 readline.set_completion_display_matches_hook(self.print_suggestions)
916
917
919
920 self.preloop()
921 if intro is not None:
922 self.intro = intro
923 if self.intro:
924 print self.intro
925 stop = None
926 while not stop:
927 if self.cmdqueue:
928 line = self.cmdqueue[0]
929 del self.cmdqueue[0]
930 else:
931 if self.use_rawinput:
932 try:
933 line = raw_input(self.prompt)
934 except EOFError:
935 line = 'EOF'
936 else:
937 sys.stdout.write(self.prompt)
938 sys.stdout.flush()
939 line = sys.stdin.readline()
940 if not len(line):
941 line = 'EOF'
942 else:
943 line = line[:-1]
944 try:
945 line = self.precmd(line)
946 stop = self.onecmd(line)
947 except BaseException, error:
948 self.error_handling(error, line)
949 if isinstance(error, KeyboardInterrupt):
950 stop = True
951 finally:
952 stop = self.postcmd(stop, line)
953 self.postloop()
954
956 """avoid to have html opening / notification"""
957 self.allow_notification_center = False
958 try:
959 self.options['automatic_html_opening'] = False
960 self.options['notification_center'] = False
961
962 except:
963 pass
964
965
967 """ A suite of additional function needed for in the cmd
968 this implement history, line breaking, comment treatment,...
969 """
970
971 if not line:
972 return line
973
974
975 if self.save_line:
976 line = self.save_line + line
977 self.save_line = ''
978
979 line = line.lstrip()
980
981 if line.endswith('\\'):
982 self.save_line = line[:-1]
983 return ''
984
985
986 if '#' in line:
987 line = line.split('#')[0]
988
989
990 if ';' in line:
991 lines = line.split(';')
992 for subline in lines:
993 if not (subline.startswith("history") or subline.startswith('help') \
994 or subline.startswith('#*')):
995 self.history.append(subline)
996 stop = self.onecmd_orig(subline)
997 stop = self.postcmd(stop, subline)
998 return ''
999
1000
1001 self.history.append(line)
1002 return line
1003
1004 - def postcmd(self,stop, line):
1005 """ finishing a command
1006 This looks if the command add a special post part."""
1007
1008 if line.strip():
1009 try:
1010 cmd, subline = line.split(None, 1)
1011 except ValueError:
1012 pass
1013 else:
1014 if hasattr(self,'post_%s' %cmd):
1015 stop = getattr(self, 'post_%s' % cmd)(stop, subline)
1016 return stop
1017
1042
1043
1044
1045
1046 - def ask(self, question, default, choices=[], path_msg=None,
1047 timeout = True, fct_timeout=None, ask_class=None, alias={},
1048 first_cmd=None, text_format='4', force=False,
1049 return_instance=False, **opt):
1050 """ ask a question with some pre-define possibility
1051 path info is
1052 """
1053
1054 if path_msg:
1055 path_msg = [path_msg]
1056 else:
1057 path_msg = []
1058
1059 if timeout is True:
1060 try:
1061 timeout = self.options['timeout']
1062 except Exception:
1063 pass
1064
1065
1066 if choices + path_msg:
1067 question += ' ['
1068 question += "\033[%sm%s\033[0m, " % (text_format, default)
1069 for data in choices[:9] + path_msg:
1070 if default == data:
1071 continue
1072 else:
1073 question += "%s, " % data
1074
1075 if len(choices) > 9:
1076 question += '... , '
1077 question = question[:-2]+']'
1078 else:
1079 question += "[\033[%sm%s\033[0m] " % (text_format, default)
1080 if ask_class:
1081 obj = ask_class
1082 elif path_msg:
1083 obj = OneLinePathCompletion
1084 else:
1085 obj = SmartQuestion
1086
1087 if alias:
1088 choices += alias.keys()
1089
1090 question_instance = obj(question, allow_arg=choices, default=default,
1091 mother_interface=self, **opt)
1092
1093 if first_cmd:
1094 if isinstance(first_cmd, str):
1095 question_instance.onecmd(first_cmd)
1096 else:
1097 for line in first_cmd:
1098 question_instance.onecmd(line)
1099 if not self.haspiping:
1100 if hasattr(obj, "haspiping"):
1101 obj.haspiping = self.haspiping
1102
1103 if force:
1104 answer = default
1105 else:
1106 answer = self.check_answer_in_input_file(question_instance, default, path_msg)
1107 if answer is not None:
1108 if answer in alias:
1109 answer = alias[answer]
1110 if ask_class:
1111 line=answer
1112 answer = question_instance.default(line)
1113 question_instance.postcmd(answer, line)
1114 if not return_instance:
1115 return question_instance.answer
1116 else:
1117 return question_instance.answer , question_instance
1118 if hasattr(question_instance, 'check_answer_consistency'):
1119 question_instance.check_answer_consistency()
1120 if not return_instance:
1121 return answer
1122 else:
1123 return answer, question_instance
1124
1125 question = question_instance.question
1126 if not force:
1127 value = Cmd.timed_input(question, default, timeout=timeout,
1128 fct=question_instance, fct_timeout=fct_timeout)
1129 else:
1130 value = default
1131
1132 try:
1133 if value in alias:
1134 value = alias[value]
1135 except TypeError:
1136 pass
1137
1138 if value == default and ask_class:
1139 value = question_instance.default(default)
1140
1141 if not return_instance:
1142 return value
1143 else:
1144 return value, question_instance
1145
1155
1156
1158 """check import command"""
1159
1160 if '-f' in args:
1161 self.force = True
1162 args.remove('-f')
1163 if args[0] != 'command':
1164 args.set(0, 'command')
1165 if len(args) != 2:
1166 raise self.InvalidCmd('import command requires one filepath argument')
1167 if not os.path.exists(args[1]):
1168 raise 'No such file or directory %s' % args[1]
1169
1170
1254
1256 """store a line of the input file which should be executed by the higher mother"""
1257
1258 if self.mother:
1259 self.mother.store_line(line)
1260 else:
1261 self.stored_line = line
1262
1264 """return stored line and clean it"""
1265 if self.mother:
1266 value = self.mother.get_stored_line()
1267 self.mother.stored_line = None
1268 else:
1269 value = self.stored_line
1270 self.stored_line = None
1271 return value
1272
1273
1274
1276 """ """
1277
1278 if self.child:
1279 return self.child.nice_error_handling(error, line)
1280
1281 os.chdir(self.__initpos)
1282
1283 self.log = False
1284 if os.path.exists(self.debug_output):
1285 os.remove(self.debug_output)
1286 try:
1287 super(Cmd,self).onecmd('history %s' % self.debug_output.replace(' ', '\ '))
1288 except Exception, error:
1289 logger.error(error)
1290
1291 debug_file = open(self.debug_output, 'a')
1292 traceback.print_exc(file=debug_file)
1293 if hasattr(error, 'filename'):
1294 debug_file.write("Related File: %s\n" % error.filename)
1295
1296 if self.history and line == self.history[-1]:
1297 error_text = 'Command \"%s\" interrupted with error:\n' % line
1298 elif self.history:
1299 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
1300 error_text += '\"%s\" with error:\n' % self.history[-1]
1301 else:
1302 error_text = ''
1303 error_text += '%s : %s\n' % (error.__class__.__name__,
1304 str(error).replace('\n','\n\t'))
1305 error_text += self.error_debug % {'debug':self.debug_output}
1306 logger_stderr.critical(error_text)
1307
1308
1309
1310 try:
1311 self.do_display('options', debug_file)
1312 except Exception, error:
1313 debug_file.write('Fail to write options with error %s' % error)
1314
1315
1316 for card in ['proc_card_mg5.dat','param_card.dat', 'run_card.dat']:
1317 try:
1318 ff = open(pjoin(self.me_dir, 'Cards', card))
1319 debug_file.write(ff.read())
1320 ff.close()
1321 except Exception:
1322 pass
1323
1324
1325 if hasattr(self, 'options') and 'crash_on_error' in self.options and \
1326 self.options['crash_on_error']:
1327 logger.info('stop computation due to crash_on_error=True')
1328 sys.exit(str(error))
1329
1330
1331 if self.use_rawinput == False or self.inputfile:
1332 return True
1333 elif self.mother:
1334 if self.mother.use_rawinput is False:
1335 return True
1336
1337 elif self.mother.mother:
1338 if self.mother.mother.use_rawinput is False:
1339 return True
1340
1341 return False
1342
1343
1344
1346 if self.child:
1347 return self.child.nice_user_error(error, line)
1348
1349 os.chdir(self.__initpos)
1350 if not self.history or line == self.history[-1]:
1351 error_text = 'Command \"%s\" interrupted with error:\n' % line
1352 else:
1353 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
1354 error_text += '\"%s\" with error:\n' % self.history[-1]
1355 error_text += '%s : %s' % (error.__class__.__name__,
1356 str(error).replace('\n','\n\t'))
1357 logger_stderr.error(error_text)
1358
1359 if hasattr(self, 'options') and 'crash_on_error' in self.options and \
1360 self.options['crash_on_error']:
1361 logger.info('stop computation due to crash_on_error=True')
1362 sys.exit(str(error))
1363
1364
1365 if self.use_rawinput == False or self.inputfile:
1366 return True
1367 elif self.mother:
1368 if self.mother.use_rawinput is False:
1369 return True
1370 elif self.mother.mother:
1371 if self.mother.mother.use_rawinput is False:
1372 return True
1373
1374
1375 self.history.pop()
1376 return False
1377
1379 if self.child:
1380 return self.child.nice_user_error(error, line)
1381
1382 os.chdir(self.__initpos)
1383 if not self.history or line == self.history[-1]:
1384 error_text = 'Error detected in \"%s\"\n' % line
1385 else:
1386 error_text = 'Error detected in sub-command %s\n' % self.history[-1]
1387 error_text += 'write debug file %s \n' % self.debug_output
1388 self.log = False
1389 super(Cmd,self).onecmd('history %s' % self.debug_output)
1390 debug_file = open(self.debug_output, 'a')
1391 traceback.print_exc(file=debug_file)
1392 error_text += self.config_debug % {'debug' :self.debug_output}
1393 error_text += '%s : %s' % (error.__class__.__name__,
1394 str(error).replace('\n','\n\t'))
1395 logger_stderr.error(error_text)
1396
1397
1398 try:
1399 self.do_display('options', debug_file)
1400 except Exception, error:
1401 debug_file.write('Fail to write options with error %s' % error)
1402 if hasattr(self, 'options') and 'crash_on_error' in self.options and \
1403 self.options['crash_on_error']:
1404 logger.info('stop computation due to crash_on_error=True')
1405 sys.exit(str(error))
1406
1407
1408 if self.use_rawinput == False or self.inputfile:
1409 return True
1410 elif self.mother:
1411 if self.mother.use_rawinput is False:
1412 return True
1413 elif self.mother.mother:
1414 if self.mother.mother.use_rawinput is False:
1415 return True
1416
1417
1418 if self.history:
1419 self.history.pop()
1420 return False
1421
1423 """Interpret the argument as though it had been typed in response
1424 to the prompt.
1425
1426 The return value is a flag indicating whether interpretation of
1427 commands by the interpreter should stop.
1428
1429 This allow to pass extra argument for internal call.
1430 """
1431 if '~/' in line and os.environ.has_key('HOME'):
1432 line = line.replace('~/', '%s/' % os.environ['HOME'])
1433 if '#' in line:
1434 line = line.split('#')[0]
1435
1436 line = os.path.expandvars(line)
1437 cmd, arg, line = self.parseline(line)
1438 if not line:
1439 return self.emptyline()
1440 if cmd is None:
1441 return self.default(line)
1442 self.lastcmd = line
1443 if cmd == '':
1444 return self.default(line)
1445 else:
1446 try:
1447 func = getattr(self, 'do_' + cmd)
1448 except AttributeError:
1449 return self.default(line)
1450 return func(arg, **opt)
1451
1494
1495
1496
1497 - def onecmd(self, line, **opt):
1498 """catch all error and stop properly command accordingly"""
1499
1500 try:
1501 return self.onecmd_orig(line, **opt)
1502 except BaseException, error:
1503 self.error_handling(error, line)
1504
1505
1507 """action to perform to close nicely on a keyboard interupt"""
1508 pass
1509
1510 - def exec_cmd(self, line, errorhandling=False, printcmd=True,
1511 precmd=False, postcmd=True,
1512 child=True, **opt):
1532
1534 """for third party call, call the line with pre and postfix treatment
1535 with global error handling"""
1536
1537 return self.exec_cmd(line, errorhandling=True, precmd=True)
1538
1540 """If empty line, do nothing. Default is repeat previous command."""
1541 pass
1542
1543 - def default(self, line, log=True):
1544 """Default action if line is not recognized"""
1545
1546
1547 if log:
1548 logger.warning("Command \"%s\" not recognized, please try again" % \
1549 line.split()[0])
1550 if line.strip() in ['q', '.q', 'stop']:
1551 logger.info("If you want to quit mg5 please type \"exit\".")
1552
1553 if self.history and self.history[-1] == line:
1554 self.history.pop()
1555
1556
1557 - def do_history(self, line):
1558 """write in a file the suite of command that was used"""
1559
1560 args = self.split_arg(line)
1561
1562 self.check_history(args)
1563
1564 if len(args) == 0:
1565 logger.info('\n'.join(self.history))
1566 return
1567 elif args[0] == 'clean':
1568 self.history = []
1569 logger.info('History is cleaned')
1570 return
1571 elif args[0] == '.':
1572 output_file = os.path.join(self._export_dir, 'Cards', \
1573 'proc_card_mg5.dat')
1574 output_file = open(output_file, 'w')
1575 else:
1576 output_file = open(args[0], 'w')
1577
1578
1579 text = self.get_history_header()
1580 text += ('\n'.join(self.history) + '\n')
1581
1582
1583 output_file.write(text)
1584 output_file.close()
1585
1586 if self.log:
1587 logger.info("History written to " + output_file.name)
1588
1589 - def compile(self, *args, **opts):
1593
1594 - def avoid_history_duplicate(self, line, no_break=[]):
1595 """remove all line in history (but the last) starting with line.
1596 up to the point when a line didn't start by something in no_break.
1597 (reading in reverse order)"""
1598
1599 new_history = []
1600 for i in range(1, len(self.history)+1):
1601 cur_line = self.history[-i]
1602 if i == 1:
1603 new_history.append(cur_line)
1604 elif not any((cur_line.startswith(text) for text in no_break)):
1605 to_add = self.history[:-i+1]
1606 to_add.reverse()
1607 new_history += to_add
1608 break
1609 elif cur_line.startswith(line):
1610 continue
1611 else:
1612 new_history.append(cur_line)
1613
1614 new_history.reverse()
1615 self.history[:] = new_history
1616
1617
1619
1620 if self.history:
1621 self.history.pop()
1622
1623
1624 previous_store_line = self.get_stored_line()
1625
1626
1627 if isinstance(filepath, str):
1628 commandline = open(filepath).readlines()
1629 else:
1630 commandline = filepath
1631 oldinputfile = self.inputfile
1632 oldraw = self.use_rawinput
1633 self.inputfile = (l for l in commandline)
1634 self.use_rawinput = False
1635
1636
1637
1638 for line in self.inputfile:
1639
1640 line = line.replace('\n', '').strip()
1641
1642 if line:
1643 self.exec_cmd(line, precmd=True)
1644 stored = self.get_stored_line()
1645 while stored:
1646 line = stored
1647 self.exec_cmd(line, precmd=True)
1648 stored = self.get_stored_line()
1649
1650
1651 if self.child:
1652 self.child.exec_cmd('quit')
1653 self.inputfile = oldinputfile
1654 self.use_rawinput = oldraw
1655
1656
1657 cmd = self
1658 while hasattr(cmd, 'mother') and cmd.mother:
1659 cmd = cmd.mother
1660 cmd.stored_line = previous_store_line
1661 return
1662
1664 """Default history header"""
1665
1666 return self.history_header
1667
1668 - def postloop(self):
1669 """ """
1670
1671 if self.use_rawinput and self.completekey:
1672 try:
1673 import readline
1674 readline.set_completer(self.old_completer)
1675 del self.old_completer
1676 except ImportError:
1677 pass
1678 except AttributeError:
1679 pass
1680
1681 args = self.split_arg(self.lastcmd)
1682 if args and args[0] in ['quit','exit']:
1683 if 'all' in args:
1684 return True
1685 if len(args) >1 and args[1].isdigit():
1686 if args[1] not in ['0', '1']:
1687 return True
1688
1689 return False
1690
1691
1692
1693
1694 @staticmethod
1701
1702 signal.signal(signal.SIGALRM, handle_alarm)
1703
1704 if fct is None:
1705 fct = raw_input
1706
1707 if timeout:
1708 signal.alarm(timeout)
1709 question += '[%ss to answer] ' % (timeout)
1710 try:
1711 result = fct(question)
1712 except TimeOutError:
1713 if noerror:
1714 logger.info('\nuse %s' % default)
1715 if fct_timeout:
1716 fct_timeout(True)
1717 return default
1718 else:
1719 signal.alarm(0)
1720 raise
1721 finally:
1722 signal.alarm(0)
1723 if fct_timeout:
1724 fct_timeout(False)
1725 return result
1726
1727
1728
1729
1730
1731
1732
1734 """Not in help: exit the mainloop() """
1735
1736 if self.child:
1737 self.child.exec_cmd('quit ' + line, printcmd=False)
1738 return
1739 elif self.mother:
1740 self.mother.child = None
1741 if line == 'all':
1742 self.mother.do_quit('all')
1743 pass
1744 elif line:
1745 level = int(line) - 1
1746 if level:
1747 self.mother.lastcmd = 'quit %s' % level
1748 elif self.inputfile:
1749 for line in self.inputfile:
1750 logger.warning('command not executed: %s' % line.replace('\n',''))
1751
1752 return True
1753
1754
1755 do_EOF = do_quit
1756 do_exit = do_quit
1757
1759 """Not in help: propose some usefull possible action """
1760
1761
1762 if line:
1763 return super(Cmd, self).do_help(line)
1764
1765
1766 names = self.get_names()
1767 cmds = {}
1768 names.sort()
1769
1770 prevname = ''
1771 for name in names:
1772 if name[:3] == 'do_':
1773 if name == prevname:
1774 continue
1775 prevname = name
1776 cmdname=name[3:]
1777 try:
1778 doc = getattr(self.cmd, name).__doc__
1779 except Exception:
1780 doc = None
1781 if not doc:
1782 doc = getattr(self, name).__doc__
1783 if not doc:
1784 tag = "Documented commands"
1785 elif ':' in doc:
1786 tag = doc.split(':',1)[0]
1787 else:
1788 tag = "Documented commands"
1789 if tag in cmds:
1790 cmds[tag].append(cmdname)
1791 else:
1792 cmds[tag] = [cmdname]
1793
1794 self.stdout.write("%s\n"%str(self.doc_leader))
1795 for tag in self.helporder:
1796 if tag not in cmds:
1797 continue
1798 header = "%s (type help <topic>):" % tag
1799 self.print_topics(header, cmds[tag], 15,80)
1800 for name, item in cmds.items():
1801 if name in self.helporder:
1802 continue
1803 if name == "Not in help":
1804 continue
1805 header = "%s (type help <topic>):" % name
1806 self.print_topics(header, item, 15,80)
1807
1808
1809
1810 if len(self.history) == 0:
1811 last_action_2 = last_action = 'start'
1812 else:
1813 last_action_2 = last_action = 'none'
1814
1815 pos = 0
1816 authorize = self.next_possibility.keys()
1817 while last_action_2 not in authorize and last_action not in authorize:
1818 pos += 1
1819 if pos > len(self.history):
1820 last_action_2 = last_action = 'start'
1821 break
1822
1823 args = self.history[-1 * pos].split()
1824 last_action = args[0]
1825 if len(args)>1:
1826 last_action_2 = '%s %s' % (last_action, args[1])
1827 else:
1828 last_action_2 = 'none'
1829
1830 logger.info('Contextual Help')
1831 logger.info('===============')
1832 if last_action_2 in authorize:
1833 options = self.next_possibility[last_action_2]
1834 elif last_action in authorize:
1835 options = self.next_possibility[last_action]
1836 else:
1837 return
1838 text = 'The following command(s) may be useful in order to continue.\n'
1839 for option in options:
1840 text+='\t %s \n' % option
1841 logger.info(text)
1842
1844 """Advanced commands: basic display"""
1845
1846 args = self.split_arg(line)
1847
1848
1849 if len(args) == 0:
1850 self.help_display()
1851 raise self.InvalidCmd, 'display require at least one argument'
1852
1853 if args[0] == "options":
1854 outstr = "Value of current Options:\n"
1855 for key, value in self.options.items():
1856 outstr += '%25s \t:\t%s\n' %(key,value)
1857 output.write(outstr)
1858
1859 elif args[0] == "variable":
1860 outstr = "Value of Internal Variable:\n"
1861 try:
1862 var = eval(args[1])
1863 except Exception:
1864 outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1]
1865 else:
1866 outstr += 'GLOBAL:\n'
1867 outstr += misc.nice_representation(var, nb_space=4)
1868
1869 try:
1870 var = eval('self.%s' % args[1])
1871 except Exception:
1872 outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1]
1873 else:
1874 outstr += 'LOCAL:\n'
1875 outstr += misc.nice_representation(var, nb_space=4)
1876 split = args[1].split('.')
1877 for i, name in enumerate(split):
1878 try:
1879 __import__('.'.join(split[:i+1]))
1880 exec('%s=sys.modules[\'%s\']' % (split[i], '.'.join(split[:i+1])))
1881 except ImportError:
1882 try:
1883 var = eval(args[1])
1884 except Exception, error:
1885 outstr += 'EXTERNAL:\nVariable %s is not a external variable\n' % args[1]
1886 break
1887 else:
1888 outstr += 'EXTERNAL:\n'
1889 outstr += misc.nice_representation(var, nb_space=4)
1890 else:
1891 var = eval(args[1])
1892 outstr += 'EXTERNAL:\n'
1893 outstr += misc.nice_representation(var, nb_space=4)
1894
1895 pydoc.pager(outstr)
1896
1897
1898 - def do_save(self, line, check=True):
1899 """Save the configuration file"""
1900
1901 args = self.split_arg(line)
1902
1903 if check:
1904 Cmd.check_save(self, args)
1905
1906
1907 if 'HOME' in os.environ and os.environ['HOME'] and \
1908 os.path.exists(pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')):
1909 base = pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')
1910 if hasattr(self, 'me_dir'):
1911 basedir = self.me_dir
1912 elif not MADEVENT:
1913 basedir = MG5DIR
1914 else:
1915 basedir = os.getcwd()
1916 elif MADEVENT:
1917
1918 for config_file in ['me5_configuration.txt', 'amcatnlo_configuration.txt']:
1919 if os.path.exists(pjoin(self.me_dir, 'Cards', config_file)):
1920 base = pjoin(self.me_dir, 'Cards', config_file)
1921 basedir = self.me_dir
1922 else:
1923 if hasattr(self, 'me_dir'):
1924 base = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1925 if len(args) == 0 and os.path.exists(base):
1926 self.write_configuration(base, base, self.me_dir)
1927 base = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
1928 basedir = MG5DIR
1929
1930 if len(args) == 0:
1931 args.append(base)
1932 self.write_configuration(args[0], base, basedir, self.options)
1933
1935 """Write the configuration file"""
1936
1937
1938
1939
1940 logger.info('save configuration file to %s' % filepath)
1941 to_write = to_keep.keys()
1942 text = ""
1943 has_mg5_path = False
1944
1945 for line in file(basefile):
1946 if '=' in line:
1947 data, value = line.split('=',1)
1948 else:
1949 text += line
1950 continue
1951 data = data.strip()
1952 if data.startswith('#'):
1953 key = data[1:].strip()
1954 else:
1955 key = data
1956 if '#' in value:
1957 value, comment = value.split('#',1)
1958 else:
1959 comment = ''
1960 if key in to_keep:
1961 value = str(to_keep[key])
1962 else:
1963 text += line
1964 continue
1965 if key == 'mg5_path':
1966 has_mg5_path = True
1967 try:
1968 to_write.remove(key)
1969 except Exception:
1970 pass
1971 if '_path' in key:
1972
1973
1974 if not os.path.isabs(value):
1975 value = os.path.realpath(os.path.join(basedir, value))
1976 text += '%s = %s # %s \n' % (key, value, comment)
1977 for key in to_write:
1978 if key in to_keep:
1979 text += '%s = %s \n' % (key, to_keep[key])
1980
1981 if not MADEVENT and not has_mg5_path:
1982 text += """\n# MG5 MAIN DIRECTORY\n"""
1983 text += "mg5_path = %s\n" % MG5DIR
1984
1985 writer = open(filepath,'w')
1986 writer.write(text)
1987 writer.close()
1988
1993 """CMD command with shell activate"""
1994
1995
1997 "Run a shell command"
1998
1999 if line.strip() is '':
2000 self.help_shell()
2001 else:
2002 logging.info("running shell command: " + line)
2003 subprocess.call(line, shell=True)
2004
2019
2021 """help for the shell"""
2022 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')
2023 logger.info("syntax: shell CMD (or ! CMD)",'$MG:BOLD')
2024
2028
2032 """ a class for answering a question with the path autocompletion"""
2033
2034 allowpath = False
2036 """Initializing before starting the main loop"""
2037 self.prompt = '>'
2038 self.value = None
2039 BasicCmd.preloop(self)
2040
2041 @property
2044
2045 - def __init__(self, question, allow_arg=[], default=None,
2046 mother_interface=None, *arg, **opt):
2047
2048 self.question = question
2049 self.wrong_answer = 0
2050 self.allow_arg = [str(a) for a in allow_arg]
2051 self.history_header = ''
2052 self.default_value = str(default)
2053 self.mother_interface = mother_interface
2054
2055 if 'case' in opt:
2056 self.casesensitive = opt['case']
2057 del opt['case']
2058 elif 'casesensitive' in opt:
2059 self.casesensitive = opt['casesensitive']
2060 del opt['casesensitive']
2061 else:
2062 self.casesensistive = True
2063 super(SmartQuestion, self).__init__(*arg, **opt)
2064
2065 - def __call__(self, question, reprint_opt=True, **opts):
2066
2067 self.question = question
2068 for key,value in opts:
2069 setattr(self, key, value)
2070 if reprint_opt:
2071 print question
2072 logger_tuto.info("Need help here? type 'help'", '$MG:BOLD')
2073 logger_plugin.info("Need help here? type 'help'" , '$MG:BOLD')
2074 return self.cmdloop()
2075
2076
2078 prev_timer = signal.alarm(0)
2079 if prev_timer:
2080 nb_back = len(line)
2081 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2082 self.stdout.write(line)
2083 self.stdout.flush()
2084 try:
2085 out = {}
2086 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
2087 out[' Recognized command'] = super(SmartQuestion, self).completenames(text,line, *ignored)
2088
2089 return self.deal_multiple_categories(out)
2090 except Exception, error:
2091 print error
2092
2093 completedefault = completenames
2094
2096
2097
2098 return dir(self)
2099
2100 - def onecmd(self, line, **opt):
2101 """catch all error and stop properly command accordingly
2102 Interpret the argument as though it had been typed in response
2103 to the prompt.
2104
2105 The return value is a flag indicating whether interpretation of
2106 commands by the interpreter should stop.
2107
2108 This allow to pass extra argument for internal call.
2109 """
2110 try:
2111 if '~/' in line and os.environ.has_key('HOME'):
2112 line = line.replace('~/', '%s/' % os.environ['HOME'])
2113 line = os.path.expandvars(line)
2114 cmd, arg, line = self.parseline(line)
2115 if not line:
2116 return self.emptyline()
2117 if cmd is None:
2118 return self.default(line)
2119 self.lastcmd = line
2120 if cmd == '':
2121 return self.default(line)
2122 else:
2123 try:
2124 func = getattr(self, 'do_' + cmd)
2125 except AttributeError:
2126 return self.default(line)
2127 return func(arg, **opt)
2128 except Exception as error:
2129 logger.warning(error)
2130 if __debug__:
2131 raise
2132
2133 - def reask(self, reprint_opt=True):
2134 pat = re.compile('\[(\d*)s to answer\]')
2135 prev_timer = signal.alarm(0)
2136
2137 if prev_timer:
2138 if pat.search(self.question):
2139 timeout = int(pat.search(self.question).groups()[0])
2140 signal.alarm(timeout)
2141 if reprint_opt:
2142 if not prev_timer:
2143 self.question = pat.sub('',self.question)
2144 print self.question.encode('utf8')
2145
2146 if self.mother_interface:
2147 answer = self.mother_interface.check_answer_in_input_file(self, 'EOF',
2148 path=self.allowpath)
2149 if answer:
2150 stop = self.default(answer)
2151 self.postcmd(stop, answer)
2152 return False
2153
2154 return False
2155
2157
2158 text=line
2159 out ={}
2160 out['Options'] = Cmd.list_completion(text, self.allow_arg)
2161 out['command'] = BasicCmd.completenames(self, text)
2162
2163 if not text:
2164 if out['Options']:
2165 logger.info( "Here is the list of all valid options:", '$MG:BOLD')
2166 logger.info( " "+ "\n ".join(out['Options']))
2167 if out['command']:
2168 logger.info( "Here is the list of command available:", '$MG:BOLD')
2169 logger.info( " "+ "\n ".join(out['command']))
2170 else:
2171 if out['Options']:
2172 logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:BOLD')
2173 logger.info( " "+ "\n ".join(out['Options']))
2174 if out['command']:
2175 logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:BOLD')
2176 logger.info( " "+ "\n ".join(out['command']))
2177 elif not out['Options']:
2178 logger.info( "No possibility starting with \'%s\'" % text, '$MG:BOLD')
2179 logger.info( "You can type help XXX, to see all command starting with XXX", '$MG:BOLD')
2183
2185 """Default action if line is not recognized"""
2186
2187 if line.strip() == '' and self.default_value is not None:
2188 self.value = self.default_value
2189 else:
2190 self.value = line
2191
2193 """If empty line, return default"""
2194
2195 if self.default_value is not None:
2196 self.value = self.default_value
2197
2198
2199 - def postcmd(self, stop, line):
2200
2201 try:
2202 if self.value in self.allow_arg:
2203 return True
2204 elif str(self.value) == 'EOF':
2205 self.value = self.default_value
2206 return True
2207 elif line and hasattr(self, 'do_%s' % line.split()[0]):
2208 return self.reask()
2209 elif self.value in ['repeat', 'reask']:
2210 return self.reask()
2211 elif len(self.allow_arg)==0:
2212 return True
2213 elif ' ' in line.strip() and '=' in self.value:
2214 line,n = re.subn(r'\s*=\s*', '=', line)
2215 if n:
2216 self.default(line)
2217 return self.postcmd(stop, line)
2218 if not self.casesensitive:
2219 for ans in self.allow_arg:
2220 if ans.lower() == self.value.lower():
2221 self.value = ans
2222 return True
2223 break
2224 else:
2225 raise Exception
2226
2227
2228 else:
2229 raise Exception
2230 except Exception,error:
2231 if self.wrong_answer < 100:
2232 self.wrong_answer += 1
2233 logger.warning("""%s not valid argument. Valid argument are in (%s).""" \
2234 % (self.value,','.join(self.allow_arg)))
2235 logger.warning('please retry')
2236 return False
2237 else:
2238 self.value = self.default_value
2239 return True
2240
2244
2250
2255 """ a class for answering a question with the path autocompletion"""
2256
2257 completion_prefix=''
2258 allowpath=True
2259
2260 - def completenames(self, text, line, begidx, endidx, formatting=True):
2261 prev_timer = signal.alarm(0)
2262 if prev_timer:
2263 nb_back = len(line)
2264 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2265 self.stdout.write(line)
2266 self.stdout.flush()
2267
2268 try:
2269 out = {}
2270 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
2271 out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False)
2272 out[' Recognized command'] = BasicCmd.completenames(self, text, line, begidx, endidx)
2273
2274 return self.deal_multiple_categories(out, formatting)
2275 except Exception, error:
2276 print error
2277
2283
2285 prev_timer = signal.alarm(0)
2286 if prev_timer:
2287 nb_back = len(line)
2288 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2289 self.stdout.write(line)
2290 self.stdout.flush()
2291 try:
2292 args = Cmd.split_arg(line[0:begidx])
2293 except Exception, error:
2294 print error
2295
2296
2297 if args[-1].endswith(os.path.sep):
2298
2299 return Cmd.path_completion(text,
2300 os.path.join('.',*[a for a in args \
2301 if a.endswith(os.path.sep)]),
2302 begidx, endidx)
2303 return self.completenames(text, line, begidx, endidx)
2304
2305
2306 - def postcmd(self, stop, line):
2307 try:
2308 if self.value in self.allow_arg:
2309 return True
2310 elif self.value and os.path.isfile(self.value):
2311 return os.path.relpath(self.value)
2312 elif self.value and str(self.value) == 'EOF':
2313 self.value = self.default_value
2314 return True
2315 elif line and hasattr(self, 'do_%s' % line.split()[0]):
2316
2317 reprint_opt = True
2318 elif self.value == 'repeat':
2319 reprint_opt = True
2320 else:
2321 raise Exception
2322 except Exception, error:
2323 print """not valid argument. Valid argument are file path or value in (%s).""" \
2324 % ','.join(self.allow_arg)
2325 print 'please retry'
2326 reprint_opt = False
2327
2328 if line != 'EOF':
2329 return self.reask(reprint_opt)
2330
2337
2341 """A class for asking a question on which program to run.
2342 This is the abstract class
2343
2344 Behavior for each switch can be customize via:
2345 set_default_XXXX() -> set default value
2346 This is super-seeded by self.default_switch if that attribute is defined (and has a key for XXXX)
2347 get_allowed_XXXX() -> return list of possible value
2348 check_value_XXXX(value) -> return True/False if the user can set such value
2349 switch_off_XXXXX() -> set it off (called for special mode)
2350 color_for_XXXX(value) -> return the representation on the screen for value
2351 get_cardcmd_for_XXXX(value)> return the command to run to customize the cards to
2352 match the status
2353 print_options_XXXX() -> return the text to disply below "other options"
2354 default is other possible value (ordered correctly)
2355
2356 consistency_XX_YY(val_XX, val_YY)
2357 -> XX is the new key set by the user to a new value val_XX
2358 -> YY is another key set by the user.
2359 -> return value should be None or "replace_YY"
2360
2361 consistency_XX(val_XX):
2362 check the consistency of the other switch given the new status of this one.
2363 return a dict {key:replaced_value} or {} if nothing to do
2364
2365 user typing "NAME" will result to a call to self.ans_NAME(None)
2366 user typing "NAME=XX" will result to a call to self.ans_NAME('XX')
2367
2368 Note on case sensitivity:
2369 -------------------------
2370 the XXX is displayed with the case in self.to_control
2371 but ALL functions should use the lower case version.
2372 for key associated to get_allowed_keys(),
2373 if (user) value not in that list.
2374 -> try to find the first entry matching up to the case
2375 for ans_XXX, set the value to lower case, but if case_XXX is set to True
2376 """
2377
2378 case_sensitive = False
2379 quit_on = ['0','done', 'EOF','','auto']
2380
2381 - def __init__(self, to_control, motherinstance, *args, **opts):
2382 """to_control is a list of ('KEY': 'Choose the shower/hadronization program')
2383 """
2384
2385 self.to_control = to_control
2386 self.mother_interface = motherinstance
2387 self.inconsistent_keys = {}
2388
2389
2390 self.inconsistent_details = {}
2391 self.last_changed = []
2392
2393
2394 self.switch = {}
2395 for key, _ in to_control:
2396 self.switch[key.lower()] = 'temporary'
2397
2398 self.set_default_switch()
2399 question = self.create_question()
2400
2401
2402 allowed_args = [ `i`+';' for i in range(1, 1+len(self.to_control))]
2403 for key in self.switch:
2404 allowed_args += ['%s=%s;' % (key,s) for s in self.get_allowed(key)]
2405
2406 allowed_args += [key[4:]+';' for key in dir(self) if key.startswith('ans_')]
2407 if 'allow_arg' in opts:
2408 allowed_args += opts['allow_arg']
2409 del opts['allow_arg']
2410
2411 allowed_args +=["0", "done"]
2412 SmartQuestion.__init__(self, question, allowed_args, *args, **opts)
2413 self.options = self.mother_interface.options
2414
2441
2442
2443
2444
2445
2447
2448 for key,_ in self.to_control:
2449 key = key.lower()
2450 if hasattr(self, 'default_switch') and key in self.default_switch:
2451 self.switch[key] = self.default_switch[key]
2452 continue
2453 if hasattr(self, 'set_default_%s' % key):
2454 getattr(self, 'set_default_%s' % key)()
2455 else:
2456 self.default_switch_for(key)
2457
2459 """use this if they are no dedicated function for such key"""
2460
2461 if hasattr(self, 'get_allowed_%s' % key):
2462 return getattr(self, 'get_allowed_%s' % key)()[0]
2463 else:
2464 self.switch[key] = 'OFF'
2465
2467 """set all valid parameter to OFF --call before special keyword--
2468 """
2469
2470 for key in self.switch:
2471 if hasattr(self, 'switch_off_%s' % key):
2472 getattr(self, 'switch_off_%s' % key)()
2473 elif self.check_value(key, self.switch[key]):
2474 self.switch[key] = 'OFF'
2475 self.inconsistent_details = {}
2476 self.inconsistent_keys = {}
2477
2478
2480 """return True/False if the value is a correct value to be set by the USER.
2481 other value than those can be set by the system --like-- Not available.
2482 This does not check the full consistency of the switch
2483 """
2484
2485 if hasattr(self, 'check_value_%s' % key):
2486 return getattr(self, 'check_value_%s' % key)(value)
2487 elif value in self.get_allowed(key):
2488 return True
2489 else:
2490 return False
2491
2492
2494 """ return the list of command that need to be run to have a consistent
2495 set of cards with the switch value choosen """
2496
2497 switch = self.answer
2498 cmd= []
2499 for key in self.switch:
2500 if hasattr(self, 'get_cardcmd_for_%s' % key):
2501 cmd += getattr(self, 'get_cardcmd_for_%s' % key)(switch[key])
2502 return cmd
2503
2504
2506 """return the list of possible value for key"""
2507
2508 if hasattr(self, 'get_allowed_%s' % key):
2509 return getattr(self, 'get_allowed_%s' % key)()
2510 else:
2511 return ['ON', 'OFF']
2512
2513 - def default(self, line, raise_error=False):
2514 """Default action if line is not recognized"""
2515
2516 line=line.strip().replace('@', '__at__')
2517 if ';' in line:
2518 for l in line.split(';'):
2519 if l:
2520 out = self.default(l)
2521 return out
2522
2523 if '=' in line:
2524 base, value = line.split('=',1)
2525 base = base.strip()
2526 value = value.strip()
2527
2528 if base.isdigit() :
2529 try:
2530 base = self.to_control[int(base)-1][0]
2531 except:
2532 pass
2533 elif ' ' in line:
2534 base, value = line.split(' ', 1)
2535 elif hasattr(self, 'ans_%s' % line.lower()):
2536 base, value = line.lower(), None
2537 elif line.isdigit() and line in [`i` for i in range(1, len(self.to_control)+1)]:
2538
2539 base = self.to_control[int(line)-1][0].lower()
2540 return self.default(base)
2541 elif line.lower() in self.switch:
2542
2543 base = line.lower()
2544 try:
2545 cur = self.get_allowed(base).index(self.switch[base])
2546 except:
2547 if self.get_allowed(base):
2548 value = self.get_allowed(base)[0]
2549 else:
2550 logger.warning('Can not switch "%s" to another value via number', base)
2551 self.value='reask'
2552 return
2553 else:
2554 try:
2555 value = self.get_allowed(base)[cur+1]
2556 except IndexError:
2557 value = self.get_allowed(base)[0]
2558 if value == "OFF" and cur == 0:
2559 logger.warning("Invalid action: %s" % self.print_options(base))
2560 elif cur == 0:
2561 logger.warning("Can not change value for this parameter")
2562
2563
2564 elif line in ['', 'done', 'EOF', 'eof','0']:
2565 super(ControlSwitch, self).default(line)
2566 return self.answer
2567 elif line in 'auto':
2568 self.switch['dynamical'] = True
2569 return super(ControlSwitch, self).default(line)
2570 elif raise_error:
2571 raise NotValidInput('unknow command: %s' % line)
2572 else:
2573 logger.warning('unknow command: %s' % line)
2574 self.value = 'reask'
2575 return
2576
2577 self.value = 'reask'
2578 base = base.lower()
2579 if hasattr(self, 'ans_%s' % base):
2580 if value and not self.is_case_sensitive(base):
2581 value = value.lower()
2582 getattr(self, 'ans_%s' % base)(value)
2583 elif base in self.switch:
2584 self.set_switch(base, value)
2585 elif raise_error:
2586 raise NotValidInput('Not valid command: %s' % line)
2587 else:
2588 logger.warning('Not valid command: %s' % line)
2589
2591 """check if a key is case sensitive"""
2592
2593 case = self.case_sensitive
2594 if hasattr(self, 'case_%s' % key):
2595 case = getattr(self, 'case_%s' % key)
2596 return case
2597
2598 - def onecmd(self, line, **opt):
2603
2604 @property
2606
2607
2608 for key,_ in self.to_control:
2609 if not self.check_value(key, self.switch[key]):
2610 self.switch[key] = 'OFF'
2611
2612 if not self.inconsistent_keys:
2613 return self.switch
2614 else:
2615 out = dict(self.switch)
2616 out.update(self.inconsistent_keys)
2617 return out
2618
2619 - def postcmd(self, stop, line):
2620
2621 line = line.strip()
2622 if ';' in line:
2623 line= [l for l in line.split(';') if l][-1]
2624 if line in self.quit_on:
2625 return True
2626 self.create_question()
2627 return self.reask(True)
2628
2629
2631 """change a switch to a given value"""
2632
2633 assert key in self.switch
2634
2635 if hasattr(self, 'ans_%s' % key):
2636 if not self.is_case_sensitive(key):
2637 value = value.lower()
2638 return getattr(self, 'ans_%s' % key)(value)
2639
2640 if not self.is_case_sensitive(key) and value not in self.get_allowed(key):
2641 lower = [t.lower() for t in self.get_allowed(key)]
2642 try:
2643 ind = lower.index(value.lower())
2644 except ValueError:
2645 pass
2646 else:
2647 value = self.get_allowed(key)[ind]
2648
2649 check = self.check_value(key, value)
2650 if not check:
2651 logger.warning('"%s" not valid option for "%s"', value, key)
2652 return
2653 if isinstance(check, str):
2654 value = check
2655
2656 self.switch[key] = value
2657
2658 if user:
2659 self.check_consistency(key, value)
2660
2662
2663 if not keys:
2664 self.inconsistent_keys = {}
2665 self.inconsistent_details = {}
2666 elif isinstance(keys, list):
2667 for key in keys:
2668 if key in self.inconsistent_keys:
2669 del self.inconsistent_keys[keys]
2670 del self.inconsistent_details[keys]
2671 else:
2672 if keys in self.inconsistent_keys:
2673 del self.inconsistent_keys[keys]
2674 del self.inconsistent_details[keys]
2675
2677 """check the consistency of the new flag with the old ones"""
2678
2679 if key in self.last_changed:
2680 self.last_changed.remove(key)
2681 self.last_changed.append(key)
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695 if hasattr(self, 'consistency_%s' % key):
2696 rules = dict([(key2, None) for key2 in self.switch])
2697 rules.update(getattr(self, 'consistency_%s' % key)(value, self.switch))
2698 else:
2699 rules = {}
2700 for key2,value2 in self.switch.items():
2701 if hasattr(self, 'consistency_%s_%s' % (key,key2)):
2702 rules[key2] = getattr(self, 'consistency_%s_%s' % (key,key2))(value, value2)
2703
2704
2705 if rules[key2] is not None and not self.check_value(key2, rules[key2]):
2706 if rules[key2] != 'OFF':
2707 logger.debug('consistency_%s_%s returns invalid output. Assume no conflict')
2708 rules[key2] = None
2709 else:
2710 rules[key2] = None
2711
2712
2713
2714
2715
2716 self.remove_inconsistency(key)
2717
2718 for key2 in self.switch:
2719 if rules[key2]:
2720 info = {'orig_value': self.switch[key2],
2721 'changed_key': key,
2722 'new_changed_key_val': value,
2723 'replacement': rules[key2]}
2724 if key2 in self.inconsistent_details:
2725 self.inconsistent_details[key2].append(info)
2726 else:
2727 self.inconsistent_details[key2] = [info]
2728
2729 if not self.inconsistent_details:
2730 return
2731
2732
2733 for key2 in dict(self.inconsistent_details):
2734 for conflict in list(self.inconsistent_details[key2]):
2735 keep_conflict = True
2736
2737 if conflict['orig_value'] != self.switch[key2]:
2738 keep_conflict = False
2739
2740 if self.switch[conflict['changed_key']] != conflict['new_changed_key_val']:
2741 keep_conflict = False
2742 if not keep_conflict:
2743 self.inconsistent_details[key2].remove(conflict)
2744 if not self.inconsistent_details[key2]:
2745 del self.inconsistent_details[key2]
2746
2747
2748
2749
2750 tmp_switch = dict(self.switch)
2751
2752
2753 to_check = [(c['changed_key'], c['new_changed_key_val']) \
2754 for k in self.inconsistent_details.values() for c in k
2755 if c['changed_key'] != key]
2756
2757 to_check.sort(lambda x, y: -1 if self.last_changed.index(x[0])>self.last_changed.index(y[0]) else 1)
2758
2759
2760 to_check = [(key, value)] + to_check
2761
2762 i = 0
2763 while len(to_check) and i < 50:
2764
2765
2766 i +=1
2767 key2, value2 = to_check.pop(0)
2768 if hasattr(self, 'consistency_%s' % key2):
2769 rules2 = dict([(key2, None) for key2 in self.switch])
2770 rules2.update(getattr(self, 'consistency_%s' % key2)(value, tmp_switch))
2771 else:
2772 rules = {}
2773 for key3,value3 in self.switch.items():
2774 if hasattr(self, 'consistency_%s_%s' % (key2,key3)):
2775 rules[key3] = getattr(self, 'consistency_%s_%s' % (key2,key3))(value2, value3)
2776 else:
2777 rules[key3] = None
2778
2779 for key, replacement in rules.items():
2780 if replacement:
2781 tmp_switch[key] = replacement
2782 to_check.append((key, replacement))
2783
2784
2785
2786 pos = {}
2787 for i, (key,value) in enumerate(to_check):
2788 pos[key] = i
2789 to_check_new = []
2790 for i, (key,value) in enumerate(to_check):
2791 if pos[key] == i:
2792 to_check_new.append((key,value))
2793 to_check = to_check_new
2794 if i>=50:
2795 logger.critical('Failed to find a consistent set of switch values.')
2796
2797
2798
2799 self.inconsistent_keys = {}
2800 for key2, value2 in tmp_switch.items():
2801 if value2 != self.switch[key2]:
2802
2803 if value2 == 'OFF' and not self.check_value(key2, 'OFF'):
2804 continue
2805 self.inconsistent_keys[key2] = value2
2806
2807
2808
2809
2810 green = '\x1b[32m%s\x1b[0m'
2811 yellow = '\x1b[33m%s\x1b[0m'
2812 red = '\x1b[31m%s\x1b[0m'
2813 bold = '\x1b[01m%s\x1b[0m'
2815
2816 if consistency and key in self.inconsistent_keys:
2817 return self.color_for_value(key, self.inconsistent_keys[key], consistency=False) +\
2818 u' \u21d0 '+ self.yellow % switch_value
2819
2820 if self.check_value(key, switch_value):
2821 if hasattr(self, 'color_for_%s' % key):
2822 return getattr(self, 'color_for_%s' % key)(switch_value)
2823 if switch_value in ['OFF']:
2824
2825 return self.red % switch_value
2826 else:
2827 return self.green % switch_value
2828 else:
2829 if ' ' in switch_value:
2830 return self.bold % switch_value
2831 else:
2832 return self.red % switch_value
2833
2835
2836 if hasattr(self, 'print_options_%s' % key) and not keep_default:
2837 return getattr(self, 'print_options_%s' % key)()
2838
2839
2840 try:
2841 ind = self.get_allowed(key).index(self.switch[key])
2842 except Exception, err:
2843 options = self.get_allowed(key)
2844 else:
2845 options = self.get_allowed(key)[ind:]+ self.get_allowed(key)[:ind]
2846
2847 info = '|'.join([v for v in options if v != self.switch[key]])
2848 if info == '':
2849 info = 'Please install module'
2850 return info
2851
2852 - def do_help(self, line, list_command=False):
2853 """dedicated help for the control switch"""
2854
2855 if line:
2856 return self.print_help_for_switch(line)
2857
2858
2859 logger.info(" ")
2860 logger.info(" In order to change a switch you can:")
2861 logger.info(" - type 'NAME = VALUE' to set the switch NAME to a given value.")
2862 logger.info(" - type 'ID = VALUE' to set the switch correspond to the line ID to a given value.")
2863 logger.info(" - type 'ID' where ID is the value of the line to pass from one value to the next.")
2864 logger.info(" - type 'NAME' to set the switch NAME to the next value.")
2865 logger.info("")
2866 logger.info(" You can type 'help NAME' for more help on a given switch")
2867 logger.info("")
2868 logger.info(" Special keyword:", '$MG:BOLD')
2869 logger.info(" %s" % '\t'.join([p[4:] for p in dir(self) if p.startswith('ans_')]) )
2870 logger.info(" type 'help XXX' for more information")
2871 if list_command:
2872 super(ControlSwitch, self).do_help(line)
2873
2874
2876 """ """
2877
2878 arg = line.split()[0]
2879
2880 if hasattr(self, 'help_%s' % arg):
2881 return getattr(self, 'help_%s' % arg)('')
2882
2883 if hasattr(self, 'ans_%s' % arg):
2884 return getattr(self, 'help_%s' % arg).__doc__
2885
2886 if arg in self.switch:
2887 logger.info(" information for switch %s: ", arg, '$MG:BOLD')
2888 logger.info(" allowed value:")
2889 logger.info(" %s", '\t'.join(self.get_allowed(arg)))
2890 if hasattr(self, 'help_text_%s' % arg):
2891 logger.info("")
2892 for line in getattr(self, 'help_text_%s' % arg):
2893 logger.info(line)
2894
2895
2896
2897
3069
3071 """ create the question with correct formatting"""
3072
3073
3074
3075 try:
3076 nb_rows, nb_col = os.popen('stty size', 'r').read().split()
3077 nb_rows, nb_col = int(nb_rows), int(nb_col)
3078 except Exception,error:
3079 nb_rows, nb_col = 20, 80
3080
3081
3082 max_len_description = 0
3083 max_len_switch = 0
3084 max_len_name = 0
3085 max_len_add_info = 0
3086 max_len_potential_switch = 0
3087 max_nb_key = 1 + int(math.log10(len(self.to_control)))
3088
3089 for key, descrip in self.to_control:
3090 if len(descrip) > max_len_description: max_len_description = len(descrip)
3091 if len(key) > max_len_name: max_len_name = len(key)
3092 if key in self.inconsistent_keys:
3093 to_display = '%s < %s' % (self.switch[key], self.inconsistent_keys[key])
3094 else:
3095 to_display = self.switch[key]
3096 if len(to_display) > max_len_switch: max_len_switch=len(to_display)
3097
3098 info = self.print_options(key)
3099 if len(info)> max_len_add_info: max_len_add_info = len(info)
3100
3101 if self.get_allowed(key):
3102 max_k = max(len(k) for k in self.get_allowed(key))
3103 else:
3104 max_k = 0
3105 if max_k > max_len_potential_switch: max_len_potential_switch = max_k
3106
3107 upper_line, lower_line, f1, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3108 max_len_name, max_len_add_info,
3109 max_len_potential_switch, max_nb_key)
3110
3111 text = \
3112 ["The following switches determine which programs are run:",
3113 upper_line
3114 ]
3115
3116
3117
3118 for i,(key, descrip) in enumerate(self.to_control):
3119
3120
3121
3122 data_to_format = {'nb': i+1,
3123 'descrip': descrip,
3124 'name': key,
3125 'switch': self.color_for_value(key,self.switch[key]),
3126 'add_info': self.print_options(key),
3127 'switch_nc': self.switch[key],
3128 'strike_switch': u'\u0336'.join(' %s ' %self.switch[key].upper()) + u'\u0336',
3129 }
3130 if key in self.inconsistent_keys:
3131
3132 _,_,_, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3133 max_len_name, max_len_add_info,
3134 max_len_potential_switch, max_nb_key,
3135 key=key)
3136
3137 data_to_format['conflict_switch_nc'] = self.inconsistent_keys[key]
3138 data_to_format['conflict_switch'] = self.color_for_value(key,self.inconsistent_keys[key], consistency=False)
3139 text.append(f2 % data_to_format)
3140 else:
3141 text.append(f1 % data_to_format)
3142
3143
3144 text.append(lower_line)
3145
3146
3147 example = None
3148 for key in self.switch:
3149 if len(self.get_allowed(key)) > 1:
3150 for val in self.get_allowed(key):
3151 if val != self.switch[key]:
3152 example = (key, val)
3153 break
3154 else:
3155 continue
3156 break
3157
3158 if not example:
3159 example = ('KEY', 'VALUE')
3160
3161 if help_text:
3162 text += \
3163 ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
3164 "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
3165 "Type 'help' for the list of all valid option",
3166 "Type '0', 'auto', 'done' or just press enter when you are done."]
3167
3168
3169 if len(text) > nb_rows:
3170
3171 to_remove = [ -2,
3172 -5,
3173 -4,
3174 -3,
3175 -1,
3176 ]
3177 to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
3178 text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
3179
3180 self.question = "\n".join(text)
3181 return self.question
3182
3183
3184
3185
3186
3187 -class CmdFile(file):
3188 """ a class for command input file -in order to debug cmd \n problem"""
3189
3196
3198 """readline method treating correctly a line whithout \n at the end
3199 (add it)
3200 """
3201 if self.lines:
3202 line = self.lines.pop(0)
3203 else:
3204 return ''
3205
3206 if line.endswith('\n'):
3207 return line
3208 else:
3209 return line + '\n'
3210
3213
3216