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 if hasattr(self, 'options') and 'crash_on_error' in self.options:
1325 if self.options['crash_on_error'] is True:
1326 logger.info('stop computation due to crash_on_error=True')
1327 sys.exit(str(error))
1328 elif self.options['crash_on_error'] == 'never':
1329 return False
1330
1331
1332 if self.use_rawinput == False or self.inputfile:
1333 return True
1334 elif self.mother:
1335 if self.mother.use_rawinput is False:
1336 return True
1337
1338 elif self.mother.mother:
1339 if self.mother.mother.use_rawinput is False:
1340 return True
1341
1342 return False
1343
1344
1345
1347 if self.child:
1348 return self.child.nice_user_error(error, line)
1349
1350
1351 os.chdir(self.__initpos)
1352 if not self.history or line == self.history[-1]:
1353 error_text = 'Command \"%s\" interrupted with error:\n' % line
1354 else:
1355 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line
1356 error_text += '\"%s\" with error:\n' % self.history[-1]
1357 error_text += '%s : %s' % (error.__class__.__name__,
1358 str(error).replace('\n','\n\t'))
1359 logger_stderr.error(error_text)
1360
1361 if hasattr(self, 'options') and 'crash_on_error' in self.options:
1362 if self.options['crash_on_error'] is True:
1363 logger.info('stop computation due to crash_on_error=True')
1364 sys.exit(str(error))
1365 elif self.options['crash_on_error'] == 'never':
1366 self.history.pop()
1367 return False
1368
1369
1370 if self.use_rawinput == False or self.inputfile:
1371 return True
1372 elif self.mother:
1373 if self.mother.use_rawinput is False:
1374 return True
1375 elif self.mother.mother:
1376 if self.mother.mother.use_rawinput is False:
1377 return True
1378
1379
1380 self.history.pop()
1381 return False
1382
1384 if self.child:
1385 return self.child.nice_user_error(error, line)
1386
1387
1388 os.chdir(self.__initpos)
1389 if not self.history or line == self.history[-1]:
1390 error_text = 'Error detected in \"%s\"\n' % line
1391 else:
1392 error_text = 'Error detected in sub-command %s\n' % self.history[-1]
1393 error_text += 'write debug file %s \n' % self.debug_output
1394 self.log = False
1395 super(Cmd,self).onecmd('history %s' % self.debug_output)
1396 debug_file = open(self.debug_output, 'a')
1397 traceback.print_exc(file=debug_file)
1398 error_text += self.config_debug % {'debug' :self.debug_output}
1399 error_text += '%s : %s' % (error.__class__.__name__,
1400 str(error).replace('\n','\n\t'))
1401 logger_stderr.error(error_text)
1402
1403
1404 try:
1405 self.do_display('options', debug_file)
1406 except Exception, error:
1407 debug_file.write('Fail to write options with error %s' % error)
1408
1409 if hasattr(self, 'options') and 'crash_on_error' in self.options:
1410 if self.options['crash_on_error'] is True:
1411 logger.info('stop computation due to crash_on_error=True')
1412 sys.exit(str(error))
1413 elif self.options['crash_on_error'] == 'never':
1414 if self.history:
1415 self.history.pop()
1416 return False
1417
1418
1419
1420
1421 if self.use_rawinput == False or self.inputfile:
1422 return True
1423 elif self.mother:
1424 if self.mother.use_rawinput is False:
1425 return True
1426 elif self.mother.mother:
1427 if self.mother.mother.use_rawinput is False:
1428 return True
1429
1430
1431 if self.history:
1432 self.history.pop()
1433 return False
1434
1436 """Interpret the argument as though it had been typed in response
1437 to the prompt.
1438
1439 The return value is a flag indicating whether interpretation of
1440 commands by the interpreter should stop.
1441
1442 This allow to pass extra argument for internal call.
1443 """
1444 if '~/' in line and os.environ.has_key('HOME'):
1445 line = line.replace('~/', '%s/' % os.environ['HOME'])
1446 if '#' in line:
1447 line = line.split('#')[0]
1448
1449 line = os.path.expandvars(line)
1450 cmd, arg, line = self.parseline(line)
1451 if not line:
1452 return self.emptyline()
1453 if cmd is None:
1454 return self.default(line)
1455 self.lastcmd = line
1456 if cmd == '':
1457 return self.default(line)
1458 else:
1459 try:
1460 func = getattr(self, 'do_' + cmd)
1461 except AttributeError:
1462 return self.default(line)
1463 return func(arg, **opt)
1464
1507
1508
1509
1510 - def onecmd(self, line, **opt):
1511 """catch all error and stop properly command accordingly"""
1512
1513 try:
1514 return self.onecmd_orig(line, **opt)
1515 except BaseException, error:
1516 return self.error_handling(error, line)
1517
1518
1520 """action to perform to close nicely on a keyboard interupt"""
1521 pass
1522
1523 - def exec_cmd(self, line, errorhandling=False, printcmd=True,
1524 precmd=False, postcmd=True,
1525 child=True, **opt):
1547
1549 """for third party call, call the line with pre and postfix treatment
1550 with global error handling"""
1551
1552 return self.exec_cmd(line, errorhandling=True, precmd=True)
1553
1555 """If empty line, do nothing. Default is repeat previous command."""
1556 pass
1557
1558 - def default(self, line, log=True):
1559 """Default action if line is not recognized"""
1560
1561
1562 if log:
1563 logger.warning("Command \"%s\" not recognized, please try again" % \
1564 line.split()[0])
1565 if line.strip() in ['q', '.q', 'stop']:
1566 logger.info("If you want to quit mg5 please type \"exit\".")
1567
1568 if self.history and self.history[-1] == line:
1569 self.history.pop()
1570
1571
1572 - def do_history(self, line):
1573 """write in a file the suite of command that was used"""
1574
1575 args = self.split_arg(line)
1576
1577 self.check_history(args)
1578
1579 if len(args) == 0:
1580 logger.info('\n'.join(self.history))
1581 return
1582 elif args[0] == 'clean':
1583 self.history = []
1584 logger.info('History is cleaned')
1585 return
1586 elif args[0] == '.':
1587 output_file = os.path.join(self._export_dir, 'Cards', \
1588 'proc_card_mg5.dat')
1589 output_file = open(output_file, 'w')
1590 else:
1591 output_file = open(args[0], 'w')
1592
1593
1594 text = self.get_history_header()
1595 text += ('\n'.join(self.history) + '\n')
1596
1597
1598 output_file.write(text)
1599 output_file.close()
1600
1601 if self.log:
1602 logger.info("History written to " + output_file.name)
1603
1604 - def compile(self, *args, **opts):
1608
1609 - def avoid_history_duplicate(self, line, no_break=[]):
1610 """remove all line in history (but the last) starting with line.
1611 up to the point when a line didn't start by something in no_break.
1612 (reading in reverse order)"""
1613
1614 new_history = []
1615 for i in range(1, len(self.history)+1):
1616 cur_line = self.history[-i]
1617 if i == 1:
1618 new_history.append(cur_line)
1619 elif not any((cur_line.startswith(text) for text in no_break)):
1620 to_add = self.history[:-i+1]
1621 to_add.reverse()
1622 new_history += to_add
1623 break
1624 elif cur_line.startswith(line):
1625 continue
1626 else:
1627 new_history.append(cur_line)
1628
1629 new_history.reverse()
1630 self.history[:] = new_history
1631
1632
1634
1635 if self.history:
1636 self.history.pop()
1637
1638
1639
1640 previous_store_line = self.get_stored_line()
1641
1642
1643 if isinstance(filepath, str):
1644 commandline = open(filepath).readlines()
1645 else:
1646 commandline = filepath
1647 oldinputfile = self.inputfile
1648 oldraw = self.use_rawinput
1649 self.inputfile = (l for l in commandline)
1650 self.use_rawinput = False
1651
1652
1653
1654 for line in self.inputfile:
1655
1656
1657 line = line.replace('\n', '').strip()
1658
1659 if line:
1660 self.exec_cmd(line, precmd=True)
1661 stored = self.get_stored_line()
1662 while stored:
1663 line = stored
1664 self.exec_cmd(line, precmd=True)
1665 stored = self.get_stored_line()
1666
1667
1668 if self.child:
1669 self.child.exec_cmd('quit')
1670 self.inputfile = oldinputfile
1671 self.use_rawinput = oldraw
1672
1673
1674 cmd = self
1675 while hasattr(cmd, 'mother') and cmd.mother:
1676 cmd = cmd.mother
1677 cmd.stored_line = previous_store_line
1678 return
1679
1681 """Default history header"""
1682
1683 return self.history_header
1684
1685 - def postloop(self):
1686 """ """
1687
1688 if self.use_rawinput and self.completekey:
1689 try:
1690 import readline
1691 readline.set_completer(self.old_completer)
1692 del self.old_completer
1693 except ImportError:
1694 pass
1695 except AttributeError:
1696 pass
1697
1698 args = self.split_arg(self.lastcmd)
1699 if args and args[0] in ['quit','exit']:
1700 if 'all' in args:
1701 return True
1702 if len(args) >1 and args[1].isdigit():
1703 if args[1] not in ['0', '1']:
1704 return True
1705
1706 return False
1707
1708
1709
1710
1711 @staticmethod
1718
1719 signal.signal(signal.SIGALRM, handle_alarm)
1720
1721 if fct is None:
1722 fct = raw_input
1723
1724 if timeout:
1725 signal.alarm(timeout)
1726 question += '[%ss to answer] ' % (timeout)
1727 try:
1728 result = fct(question)
1729 except TimeOutError:
1730 if noerror:
1731 logger.info('\nuse %s' % default)
1732 if fct_timeout:
1733 fct_timeout(True)
1734 return default
1735 else:
1736 signal.alarm(0)
1737 raise
1738 finally:
1739 signal.alarm(0)
1740 if fct_timeout:
1741 fct_timeout(False)
1742 return result
1743
1744
1745
1746
1747
1748
1749
1751 """Not in help: exit the mainloop() """
1752
1753 if self.child:
1754 self.child.exec_cmd('quit ' + line, printcmd=False)
1755 return
1756 elif self.mother:
1757 self.mother.child = None
1758 if line == 'all':
1759 self.mother.do_quit('all')
1760 pass
1761 elif line:
1762 level = int(line) - 1
1763 if level:
1764 self.mother.lastcmd = 'quit %s' % level
1765 elif self.inputfile:
1766 for line in self.inputfile:
1767 logger.warning('command not executed: %s' % line.replace('\n',''))
1768
1769 return True
1770
1771
1772 do_EOF = do_quit
1773 do_exit = do_quit
1774
1776 """Not in help: propose some usefull possible action """
1777
1778
1779 if line:
1780 return super(Cmd, self).do_help(line)
1781
1782
1783 names = self.get_names()
1784 cmds = {}
1785 names.sort()
1786
1787 prevname = ''
1788 for name in names:
1789 if name[:3] == 'do_':
1790 if name == prevname:
1791 continue
1792 prevname = name
1793 cmdname=name[3:]
1794 try:
1795 doc = getattr(self.cmd, name).__doc__
1796 except Exception:
1797 doc = None
1798 if not doc:
1799 doc = getattr(self, name).__doc__
1800 if not doc:
1801 tag = "Documented commands"
1802 elif ':' in doc:
1803 tag = doc.split(':',1)[0]
1804 else:
1805 tag = "Documented commands"
1806 if tag in cmds:
1807 cmds[tag].append(cmdname)
1808 else:
1809 cmds[tag] = [cmdname]
1810
1811 self.stdout.write("%s\n"%str(self.doc_leader))
1812 for tag in self.helporder:
1813 if tag not in cmds:
1814 continue
1815 header = "%s (type help <topic>):" % tag
1816 self.print_topics(header, cmds[tag], 15,80)
1817 for name, item in cmds.items():
1818 if name in self.helporder:
1819 continue
1820 if name == "Not in help":
1821 continue
1822 header = "%s (type help <topic>):" % name
1823 self.print_topics(header, item, 15,80)
1824
1825
1826
1827 if len(self.history) == 0:
1828 last_action_2 = last_action = 'start'
1829 else:
1830 last_action_2 = last_action = 'none'
1831
1832 pos = 0
1833 authorize = self.next_possibility.keys()
1834 while last_action_2 not in authorize and last_action not in authorize:
1835 pos += 1
1836 if pos > len(self.history):
1837 last_action_2 = last_action = 'start'
1838 break
1839
1840 args = self.history[-1 * pos].split()
1841 last_action = args[0]
1842 if len(args)>1:
1843 last_action_2 = '%s %s' % (last_action, args[1])
1844 else:
1845 last_action_2 = 'none'
1846
1847 logger.info('Contextual Help')
1848 logger.info('===============')
1849 if last_action_2 in authorize:
1850 options = self.next_possibility[last_action_2]
1851 elif last_action in authorize:
1852 options = self.next_possibility[last_action]
1853 else:
1854 return
1855 text = 'The following command(s) may be useful in order to continue.\n'
1856 for option in options:
1857 text+='\t %s \n' % option
1858 logger.info(text)
1859
1861 """Advanced commands: basic display"""
1862
1863 args = self.split_arg(line)
1864
1865
1866 if len(args) == 0:
1867 self.help_display()
1868 raise self.InvalidCmd, 'display require at least one argument'
1869
1870 if args[0] == "options":
1871 outstr = "Value of current Options:\n"
1872 for key, value in self.options.items():
1873 outstr += '%25s \t:\t%s\n' %(key,value)
1874 output.write(outstr)
1875
1876 elif args[0] == "variable":
1877 outstr = "Value of Internal Variable:\n"
1878 try:
1879 var = eval(args[1])
1880 except Exception:
1881 outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1]
1882 else:
1883 outstr += 'GLOBAL:\n'
1884 outstr += misc.nice_representation(var, nb_space=4)
1885
1886 try:
1887 var = eval('self.%s' % args[1])
1888 except Exception:
1889 outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1]
1890 else:
1891 outstr += 'LOCAL:\n'
1892 outstr += misc.nice_representation(var, nb_space=4)
1893 split = args[1].split('.')
1894 for i, name in enumerate(split):
1895 try:
1896 __import__('.'.join(split[:i+1]))
1897 exec('%s=sys.modules[\'%s\']' % (split[i], '.'.join(split[:i+1])))
1898 except ImportError:
1899 try:
1900 var = eval(args[1])
1901 except Exception, error:
1902 outstr += 'EXTERNAL:\nVariable %s is not a external variable\n' % args[1]
1903 break
1904 else:
1905 outstr += 'EXTERNAL:\n'
1906 outstr += misc.nice_representation(var, nb_space=4)
1907 else:
1908 var = eval(args[1])
1909 outstr += 'EXTERNAL:\n'
1910 outstr += misc.nice_representation(var, nb_space=4)
1911
1912 pydoc.pager(outstr)
1913
1914
1915 - def do_save(self, line, check=True):
1916 """Save the configuration file"""
1917
1918 args = self.split_arg(line)
1919
1920 if check:
1921 Cmd.check_save(self, args)
1922
1923
1924 if 'HOME' in os.environ and os.environ['HOME'] and \
1925 os.path.exists(pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')):
1926 base = pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')
1927 if hasattr(self, 'me_dir'):
1928 basedir = self.me_dir
1929 elif not MADEVENT:
1930 basedir = MG5DIR
1931 else:
1932 basedir = os.getcwd()
1933 elif MADEVENT:
1934
1935 for config_file in ['me5_configuration.txt', 'amcatnlo_configuration.txt']:
1936 if os.path.exists(pjoin(self.me_dir, 'Cards', config_file)):
1937 base = pjoin(self.me_dir, 'Cards', config_file)
1938 basedir = self.me_dir
1939 else:
1940 if hasattr(self, 'me_dir'):
1941 base = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
1942 if len(args) == 0 and os.path.exists(base):
1943 self.write_configuration(base, base, self.me_dir)
1944 base = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
1945 basedir = MG5DIR
1946
1947 if len(args) == 0:
1948 args.append(base)
1949 self.write_configuration(args[0], base, basedir, self.options)
1950
1952 """Write the configuration file"""
1953
1954
1955
1956
1957 logger.info('save configuration file to %s' % filepath)
1958 to_write = to_keep.keys()
1959 text = ""
1960 has_mg5_path = False
1961
1962 for line in file(basefile):
1963 if '=' in line:
1964 data, value = line.split('=',1)
1965 else:
1966 text += line
1967 continue
1968 data = data.strip()
1969 if data.startswith('#'):
1970 key = data[1:].strip()
1971 else:
1972 key = data
1973 if '#' in value:
1974 value, comment = value.split('#',1)
1975 else:
1976 comment = ''
1977 if key in to_keep:
1978 value = str(to_keep[key])
1979 else:
1980 text += line
1981 continue
1982 if key == 'mg5_path':
1983 has_mg5_path = True
1984 try:
1985 to_write.remove(key)
1986 except Exception:
1987 pass
1988 if '_path' in key:
1989
1990
1991 if not os.path.isabs(value):
1992 value = os.path.realpath(os.path.join(basedir, value))
1993 text += '%s = %s # %s \n' % (key, value, comment)
1994 for key in to_write:
1995 if key in to_keep:
1996 text += '%s = %s \n' % (key, to_keep[key])
1997
1998 if not MADEVENT and not has_mg5_path:
1999 text += """\n# MG5 MAIN DIRECTORY\n"""
2000 text += "mg5_path = %s\n" % MG5DIR
2001
2002 writer = open(filepath,'w')
2003 writer.write(text)
2004 writer.close()
2005
2010 """CMD command with shell activate"""
2011
2012
2014 "Run a shell command"
2015
2016 if line.strip() is '':
2017 self.help_shell()
2018 else:
2019 logging.info("running shell command: " + line)
2020 subprocess.call(line, shell=True)
2021
2036
2038 """help for the shell"""
2039 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')
2040 logger.info("syntax: shell CMD (or ! CMD)",'$MG:BOLD')
2041
2045
2049 """ a class for answering a question with the path autocompletion"""
2050
2051 allowpath = False
2053 """Initializing before starting the main loop"""
2054 self.prompt = '>'
2055 self.value = None
2056 BasicCmd.preloop(self)
2057
2058 @property
2061
2062 - def __init__(self, question, allow_arg=[], default=None,
2063 mother_interface=None, *arg, **opt):
2064
2065 self.question = question
2066 self.wrong_answer = 0
2067 self.allow_arg = [str(a) for a in allow_arg]
2068 self.history_header = ''
2069 self.default_value = str(default)
2070 self.mother_interface = mother_interface
2071
2072 if 'case' in opt:
2073 self.casesensitive = opt['case']
2074 del opt['case']
2075 elif 'casesensitive' in opt:
2076 self.casesensitive = opt['casesensitive']
2077 del opt['casesensitive']
2078 else:
2079 self.casesensistive = True
2080 super(SmartQuestion, self).__init__(*arg, **opt)
2081
2082 - def __call__(self, question, reprint_opt=True, **opts):
2083
2084 self.question = question
2085 for key,value in opts:
2086 setattr(self, key, value)
2087 if reprint_opt:
2088 print question
2089 logger_tuto.info("Need help here? type 'help'", '$MG:BOLD')
2090 logger_plugin.info("Need help here? type 'help'" , '$MG:BOLD')
2091 return self.cmdloop()
2092
2093
2095 prev_timer = signal.alarm(0)
2096 if prev_timer:
2097 nb_back = len(line)
2098 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2099 self.stdout.write(line)
2100 self.stdout.flush()
2101 try:
2102 out = {}
2103 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
2104 out[' Recognized command'] = super(SmartQuestion, self).completenames(text,line, *ignored)
2105
2106 return self.deal_multiple_categories(out)
2107 except Exception, error:
2108 print error
2109
2110 completedefault = completenames
2111
2113
2114
2115 return dir(self)
2116
2117 - def onecmd(self, line, **opt):
2118 """catch all error and stop properly command accordingly
2119 Interpret the argument as though it had been typed in response
2120 to the prompt.
2121
2122 The return value is a flag indicating whether interpretation of
2123 commands by the interpreter should stop.
2124
2125 This allow to pass extra argument for internal call.
2126 """
2127 try:
2128 if '~/' in line and os.environ.has_key('HOME'):
2129 line = line.replace('~/', '%s/' % os.environ['HOME'])
2130 line = os.path.expandvars(line)
2131 cmd, arg, line = self.parseline(line)
2132 if not line:
2133 return self.emptyline()
2134 if cmd is None:
2135 return self.default(line)
2136 self.lastcmd = line
2137 if cmd == '':
2138 return self.default(line)
2139 else:
2140 try:
2141 func = getattr(self, 'do_' + cmd)
2142 except AttributeError:
2143 return self.default(line)
2144 return func(arg, **opt)
2145 except Exception as error:
2146 logger.warning(error)
2147 if __debug__:
2148 raise
2149
2150 - def reask(self, reprint_opt=True):
2151 pat = re.compile('\[(\d*)s to answer\]')
2152 prev_timer = signal.alarm(0)
2153
2154 if prev_timer:
2155 if pat.search(self.question):
2156 timeout = int(pat.search(self.question).groups()[0])
2157 signal.alarm(timeout)
2158 if reprint_opt:
2159 if not prev_timer:
2160 self.question = pat.sub('',self.question)
2161 print self.question.encode('utf8')
2162
2163 if self.mother_interface:
2164 answer = self.mother_interface.check_answer_in_input_file(self, 'EOF',
2165 path=self.allowpath)
2166 if answer:
2167 stop = self.default(answer)
2168 self.postcmd(stop, answer)
2169 return False
2170
2171 return False
2172
2174
2175 text=line
2176 out ={}
2177 out['Options'] = Cmd.list_completion(text, self.allow_arg)
2178 out['command'] = BasicCmd.completenames(self, text)
2179
2180 if not text:
2181 if out['Options']:
2182 logger.info( "Here is the list of all valid options:", '$MG:BOLD')
2183 logger.info( " "+ "\n ".join(out['Options']))
2184 if out['command']:
2185 logger.info( "Here is the list of command available:", '$MG:BOLD')
2186 logger.info( " "+ "\n ".join(out['command']))
2187 else:
2188 if out['Options']:
2189 logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:BOLD')
2190 logger.info( " "+ "\n ".join(out['Options']))
2191 if out['command']:
2192 logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:BOLD')
2193 logger.info( " "+ "\n ".join(out['command']))
2194 elif not out['Options']:
2195 logger.info( "No possibility starting with \'%s\'" % text, '$MG:BOLD')
2196 logger.info( "You can type help XXX, to see all command starting with XXX", '$MG:BOLD')
2200
2202 """Default action if line is not recognized"""
2203
2204 if line.strip() == '' and self.default_value is not None:
2205 self.value = self.default_value
2206 else:
2207 self.value = line
2208
2210 """If empty line, return default"""
2211
2212 if self.default_value is not None:
2213 self.value = self.default_value
2214
2215
2216 - def postcmd(self, stop, line):
2217
2218 try:
2219 if self.value in self.allow_arg:
2220 return True
2221 elif str(self.value) == 'EOF':
2222 self.value = self.default_value
2223 return True
2224 elif line and hasattr(self, 'do_%s' % line.split()[0]):
2225 return self.reask()
2226 elif self.value in ['repeat', 'reask']:
2227 return self.reask()
2228 elif len(self.allow_arg)==0:
2229 return True
2230 elif ' ' in line.strip() and '=' in self.value:
2231 line,n = re.subn(r'\s*=\s*', '=', line)
2232 if n:
2233 self.default(line)
2234 return self.postcmd(stop, line)
2235 if not self.casesensitive:
2236 for ans in self.allow_arg:
2237 if ans.lower() == self.value.lower():
2238 self.value = ans
2239 return True
2240 break
2241 else:
2242 raise Exception
2243
2244
2245 else:
2246 raise Exception
2247 except Exception,error:
2248 if self.wrong_answer < 100:
2249 self.wrong_answer += 1
2250 logger.warning("""%s not valid argument. Valid argument are in (%s).""" \
2251 % (self.value,','.join(self.allow_arg)))
2252 logger.warning('please retry')
2253 return False
2254 else:
2255 self.value = self.default_value
2256 return True
2257
2261
2267
2272 """ a class for answering a question with the path autocompletion"""
2273
2274 completion_prefix=''
2275 allowpath=True
2276
2277 - def completenames(self, text, line, begidx, endidx, formatting=True):
2278 prev_timer = signal.alarm(0)
2279 if prev_timer:
2280 nb_back = len(line)
2281 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2282 self.stdout.write(line)
2283 self.stdout.flush()
2284
2285 try:
2286 out = {}
2287 out[' Options'] = Cmd.list_completion(text, self.allow_arg)
2288 out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False)
2289 out[' Recognized command'] = BasicCmd.completenames(self, text, line, begidx, endidx)
2290
2291 return self.deal_multiple_categories(out, formatting)
2292 except Exception, error:
2293 print error
2294
2300
2302 prev_timer = signal.alarm(0)
2303 if prev_timer:
2304 nb_back = len(line)
2305 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
2306 self.stdout.write(line)
2307 self.stdout.flush()
2308 try:
2309 args = Cmd.split_arg(line[0:begidx])
2310 except Exception, error:
2311 print error
2312
2313
2314 if args[-1].endswith(os.path.sep):
2315
2316 return Cmd.path_completion(text,
2317 os.path.join('.',*[a for a in args \
2318 if a.endswith(os.path.sep)]),
2319 begidx, endidx)
2320 return self.completenames(text, line, begidx, endidx)
2321
2322
2323 - def postcmd(self, stop, line):
2324 try:
2325 if self.value in self.allow_arg:
2326 return True
2327 elif self.value and os.path.isfile(self.value):
2328 return os.path.relpath(self.value)
2329 elif self.value and str(self.value) == 'EOF':
2330 self.value = self.default_value
2331 return True
2332 elif line and hasattr(self, 'do_%s' % line.split()[0]):
2333
2334 reprint_opt = True
2335 elif self.value == 'repeat':
2336 reprint_opt = True
2337 else:
2338 raise Exception
2339 except Exception, error:
2340 print """not valid argument. Valid argument are file path or value in (%s).""" \
2341 % ','.join(self.allow_arg)
2342 print 'please retry'
2343 reprint_opt = False
2344
2345 if line != 'EOF':
2346 return self.reask(reprint_opt)
2347
2354
2358 """A class for asking a question on which program to run.
2359 This is the abstract class
2360
2361 Behavior for each switch can be customize via:
2362 set_default_XXXX() -> set default value
2363 This is super-seeded by self.default_switch if that attribute is defined (and has a key for XXXX)
2364 get_allowed_XXXX() -> return list of possible value
2365 check_value_XXXX(value) -> return True/False if the user can set such value
2366 switch_off_XXXXX() -> set it off (called for special mode)
2367 color_for_XXXX(value) -> return the representation on the screen for value
2368 get_cardcmd_for_XXXX(value)> return the command to run to customize the cards to
2369 match the status
2370 print_options_XXXX() -> return the text to disply below "other options"
2371 default is other possible value (ordered correctly)
2372
2373 consistency_XX_YY(val_XX, val_YY)
2374 -> XX is the new key set by the user to a new value val_XX
2375 -> YY is another key set by the user.
2376 -> return value should be None or "replace_YY"
2377
2378 consistency_XX(val_XX):
2379 check the consistency of the other switch given the new status of this one.
2380 return a dict {key:replaced_value} or {} if nothing to do
2381
2382 user typing "NAME" will result to a call to self.ans_NAME(None)
2383 user typing "NAME=XX" will result to a call to self.ans_NAME('XX')
2384
2385 Note on case sensitivity:
2386 -------------------------
2387 the XXX is displayed with the case in self.to_control
2388 but ALL functions should use the lower case version.
2389 for key associated to get_allowed_keys(),
2390 if (user) value not in that list.
2391 -> try to find the first entry matching up to the case
2392 for ans_XXX, set the value to lower case, but if case_XXX is set to True
2393 """
2394
2395 case_sensitive = False
2396 quit_on = ['0','done', 'EOF','','auto']
2397
2398 - def __init__(self, to_control, motherinstance, *args, **opts):
2399 """to_control is a list of ('KEY': 'Choose the shower/hadronization program')
2400 """
2401
2402 self.to_control = to_control
2403 self.mother_interface = motherinstance
2404 self.inconsistent_keys = {}
2405
2406
2407 self.inconsistent_details = {}
2408 self.last_changed = []
2409
2410
2411 self.switch = {}
2412 for key, _ in to_control:
2413 self.switch[key.lower()] = 'temporary'
2414
2415 self.set_default_switch()
2416 question = self.create_question()
2417
2418
2419 allowed_args = [ `i`+';' for i in range(1, 1+len(self.to_control))]
2420 for key in self.switch:
2421 allowed_args += ['%s=%s;' % (key,s) for s in self.get_allowed(key)]
2422
2423 allowed_args += [key[4:]+';' for key in dir(self) if key.startswith('ans_')]
2424 if 'allow_arg' in opts:
2425 allowed_args += opts['allow_arg']
2426 del opts['allow_arg']
2427
2428 allowed_args +=["0", "done"]
2429 SmartQuestion.__init__(self, question, allowed_args, *args, **opts)
2430 self.options = self.mother_interface.options
2431
2458
2459
2460
2461
2462
2464
2465 for key,_ in self.to_control:
2466 key = key.lower()
2467 if hasattr(self, 'default_switch') and key in self.default_switch:
2468 self.switch[key] = self.default_switch[key]
2469 continue
2470 if hasattr(self, 'set_default_%s' % key):
2471 getattr(self, 'set_default_%s' % key)()
2472 else:
2473 self.default_switch_for(key)
2474
2476 """use this if they are no dedicated function for such key"""
2477
2478 if hasattr(self, 'get_allowed_%s' % key):
2479 return getattr(self, 'get_allowed_%s' % key)()[0]
2480 else:
2481 self.switch[key] = 'OFF'
2482
2484 """set all valid parameter to OFF --call before special keyword--
2485 """
2486
2487 for key in self.switch:
2488 if hasattr(self, 'switch_off_%s' % key):
2489 getattr(self, 'switch_off_%s' % key)()
2490 elif self.check_value(key, self.switch[key]):
2491 self.switch[key] = 'OFF'
2492 self.inconsistent_details = {}
2493 self.inconsistent_keys = {}
2494
2495
2497 """return True/False if the value is a correct value to be set by the USER.
2498 other value than those can be set by the system --like-- Not available.
2499 This does not check the full consistency of the switch
2500 """
2501
2502 if hasattr(self, 'check_value_%s' % key):
2503 return getattr(self, 'check_value_%s' % key)(value)
2504 elif value in self.get_allowed(key):
2505 return True
2506 else:
2507 return False
2508
2509
2511 """ return the list of command that need to be run to have a consistent
2512 set of cards with the switch value choosen """
2513
2514 switch = self.answer
2515 cmd= []
2516 for key in self.switch:
2517 if hasattr(self, 'get_cardcmd_for_%s' % key):
2518 cmd += getattr(self, 'get_cardcmd_for_%s' % key)(switch[key])
2519 return cmd
2520
2521
2523 """return the list of possible value for key"""
2524
2525 if hasattr(self, 'get_allowed_%s' % key):
2526 return getattr(self, 'get_allowed_%s' % key)()
2527 else:
2528 return ['ON', 'OFF']
2529
2530 - def default(self, line, raise_error=False):
2531 """Default action if line is not recognized"""
2532
2533 line=line.strip().replace('@', '__at__')
2534 if ';' in line:
2535 for l in line.split(';'):
2536 if l:
2537 out = self.default(l)
2538 return out
2539
2540 if '=' in line:
2541 base, value = line.split('=',1)
2542 base = base.strip()
2543 value = value.strip()
2544
2545 if base.isdigit() :
2546 try:
2547 base = self.to_control[int(base)-1][0]
2548 except:
2549 pass
2550 elif ' ' in line:
2551 base, value = line.split(' ', 1)
2552 elif hasattr(self, 'ans_%s' % line.lower()):
2553 base, value = line.lower(), None
2554 elif line.isdigit() and line in [`i` for i in range(1, len(self.to_control)+1)]:
2555
2556 base = self.to_control[int(line)-1][0].lower()
2557 return self.default(base)
2558 elif line.lower() in self.switch:
2559
2560 base = line.lower()
2561 try:
2562 cur = self.get_allowed(base).index(self.switch[base])
2563 except:
2564 if self.get_allowed(base):
2565 value = self.get_allowed(base)[0]
2566 else:
2567 logger.warning('Can not switch "%s" to another value via number', base)
2568 self.value='reask'
2569 return
2570 else:
2571 try:
2572 value = self.get_allowed(base)[cur+1]
2573 except IndexError:
2574 value = self.get_allowed(base)[0]
2575 if value == "OFF" and cur == 0:
2576 logger.warning("Invalid action: %s" % self.print_options(base))
2577 elif cur == 0:
2578 logger.warning("Can not change value for this parameter")
2579
2580
2581 elif line in ['', 'done', 'EOF', 'eof','0']:
2582 super(ControlSwitch, self).default(line)
2583 return self.answer
2584 elif line in 'auto':
2585 self.switch['dynamical'] = True
2586 return super(ControlSwitch, self).default(line)
2587 elif raise_error:
2588 raise NotValidInput('unknow command: %s' % line)
2589 else:
2590 logger.warning('unknow command: %s' % line)
2591 self.value = 'reask'
2592 return
2593
2594 self.value = 'reask'
2595 base = base.lower()
2596 if hasattr(self, 'ans_%s' % base):
2597 if value and not self.is_case_sensitive(base):
2598 value = value.lower()
2599 getattr(self, 'ans_%s' % base)(value)
2600 elif base in self.switch:
2601 self.set_switch(base, value)
2602 elif raise_error:
2603 raise NotValidInput('Not valid command: %s' % line)
2604 else:
2605 logger.warning('Not valid command: %s' % line)
2606
2608 """check if a key is case sensitive"""
2609
2610 case = self.case_sensitive
2611 if hasattr(self, 'case_%s' % key):
2612 case = getattr(self, 'case_%s' % key)
2613 return case
2614
2615 - def onecmd(self, line, **opt):
2620
2621 @property
2623
2624
2625 for key,_ in self.to_control:
2626 if not self.check_value(key, self.switch[key]):
2627 self.switch[key] = 'OFF'
2628
2629 if not self.inconsistent_keys:
2630 return self.switch
2631 else:
2632 out = dict(self.switch)
2633 out.update(self.inconsistent_keys)
2634 return out
2635
2636 - def postcmd(self, stop, line):
2637
2638
2639
2640 try:
2641 out = super(ControlSwitch,self).postcmd(stop, line)
2642 except AttributeError:
2643 pass
2644
2645 line = line.strip()
2646 if ';' in line:
2647 line= [l for l in line.split(';') if l][-1]
2648 if line in self.quit_on:
2649 return True
2650 self.create_question()
2651 return self.reask(True)
2652
2653
2655 """change a switch to a given value"""
2656
2657 assert key in self.switch
2658
2659 if hasattr(self, 'ans_%s' % key):
2660 if not self.is_case_sensitive(key):
2661 value = value.lower()
2662 return getattr(self, 'ans_%s' % key)(value)
2663
2664 if not self.is_case_sensitive(key) and value not in self.get_allowed(key):
2665 lower = [t.lower() for t in self.get_allowed(key)]
2666 try:
2667 ind = lower.index(value.lower())
2668 except ValueError:
2669 pass
2670 else:
2671 value = self.get_allowed(key)[ind]
2672
2673 check = self.check_value(key, value)
2674 if not check:
2675 logger.warning('"%s" not valid option for "%s"', value, key)
2676 return
2677 if isinstance(check, str):
2678 value = check
2679
2680 self.switch[key] = value
2681
2682 if user:
2683 self.check_consistency(key, value)
2684
2686
2687 if not keys:
2688 self.inconsistent_keys = {}
2689 self.inconsistent_details = {}
2690 elif isinstance(keys, list):
2691 for key in keys:
2692 if key in self.inconsistent_keys:
2693 del self.inconsistent_keys[keys]
2694 del self.inconsistent_details[keys]
2695 else:
2696 if keys in self.inconsistent_keys:
2697 del self.inconsistent_keys[keys]
2698 del self.inconsistent_details[keys]
2699
2701 """check the consistency of the new flag with the old ones"""
2702
2703
2704 if key in self.last_changed:
2705 self.last_changed.remove(key)
2706 self.last_changed.append(key)
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720 if hasattr(self, 'consistency_%s' % key):
2721 rules = dict([(key2, None) for key2 in self.switch])
2722 rules.update(getattr(self, 'consistency_%s' % key)(value, self.switch))
2723 else:
2724 rules = {}
2725 for key2,value2 in self.switch.items():
2726 if hasattr(self, 'consistency_%s_%s' % (key,key2)):
2727 rules[key2] = getattr(self, 'consistency_%s_%s' % (key,key2))(value, value2)
2728
2729
2730 if rules[key2] is not None and not self.check_value(key2, rules[key2]):
2731 if rules[key2] != 'OFF':
2732 logger.debug('consistency_%s_%s returns invalid output. Assume no conflict')
2733 rules[key2] = None
2734 else:
2735 rules[key2] = None
2736
2737
2738
2739
2740
2741 self.remove_inconsistency(key)
2742
2743 for key2 in self.switch:
2744 if rules[key2]:
2745 info = {'orig_value': self.switch[key2],
2746 'changed_key': key,
2747 'new_changed_key_val': value,
2748 'replacement': rules[key2]}
2749 if key2 in self.inconsistent_details:
2750 self.inconsistent_details[key2].append(info)
2751 else:
2752 self.inconsistent_details[key2] = [info]
2753
2754 if not self.inconsistent_details:
2755 return
2756
2757
2758 for key2 in dict(self.inconsistent_details):
2759 for conflict in list(self.inconsistent_details[key2]):
2760 keep_conflict = True
2761
2762 if conflict['orig_value'] != self.switch[key2]:
2763 keep_conflict = False
2764
2765 if self.switch[conflict['changed_key']] != conflict['new_changed_key_val']:
2766 keep_conflict = False
2767 if not keep_conflict:
2768 self.inconsistent_details[key2].remove(conflict)
2769 if not self.inconsistent_details[key2]:
2770 del self.inconsistent_details[key2]
2771
2772
2773
2774
2775 tmp_switch = dict(self.switch)
2776
2777
2778 to_check = [(c['changed_key'], c['new_changed_key_val']) \
2779 for k in self.inconsistent_details.values() for c in k
2780 if c['changed_key'] != key]
2781
2782 to_check.sort(lambda x, y: -1 if self.last_changed.index(x[0])>self.last_changed.index(y[0]) else 1)
2783
2784
2785 to_check = [(key, value)] + to_check
2786
2787 i = 0
2788 while len(to_check) and i < 50:
2789
2790
2791 i +=1
2792 key2, value2 = to_check.pop(0)
2793 if hasattr(self, 'consistency_%s' % key2):
2794 rules2 = dict([(key2, None) for key2 in self.switch])
2795 rules2.update(getattr(self, 'consistency_%s' % key2)(value, tmp_switch))
2796 else:
2797 rules = {}
2798 for key3,value3 in self.switch.items():
2799 if hasattr(self, 'consistency_%s_%s' % (key2,key3)):
2800 rules[key3] = getattr(self, 'consistency_%s_%s' % (key2,key3))(value2, value3)
2801 else:
2802 rules[key3] = None
2803
2804 for key, replacement in rules.items():
2805 if replacement:
2806 tmp_switch[key] = replacement
2807 to_check.append((key, replacement))
2808
2809
2810
2811 pos = {}
2812 for i, (key,value) in enumerate(to_check):
2813 pos[key] = i
2814 to_check_new = []
2815 for i, (key,value) in enumerate(to_check):
2816 if pos[key] == i:
2817 to_check_new.append((key,value))
2818 to_check = to_check_new
2819 if i>=50:
2820 logger.critical('Failed to find a consistent set of switch values.')
2821
2822
2823
2824 self.inconsistent_keys = {}
2825 for key2, value2 in tmp_switch.items():
2826 if value2 != self.switch[key2]:
2827
2828 if value2 == 'OFF' and not self.check_value(key2, 'OFF'):
2829 continue
2830 self.inconsistent_keys[key2] = value2
2831
2832
2833
2834
2835 green = '\x1b[32m%s\x1b[0m'
2836 yellow = '\x1b[33m%s\x1b[0m'
2837 red = '\x1b[31m%s\x1b[0m'
2838 bold = '\x1b[01m%s\x1b[0m'
2840
2841 if consistency and key in self.inconsistent_keys:
2842 return self.color_for_value(key, self.inconsistent_keys[key], consistency=False) +\
2843 u' \u21d0 '+ self.yellow % switch_value
2844
2845 if self.check_value(key, switch_value):
2846 if hasattr(self, 'color_for_%s' % key):
2847 return getattr(self, 'color_for_%s' % key)(switch_value)
2848 if switch_value in ['OFF']:
2849
2850 return self.red % switch_value
2851 else:
2852 return self.green % switch_value
2853 else:
2854 if ' ' in switch_value:
2855 return self.bold % switch_value
2856 else:
2857 return self.red % switch_value
2858
2860
2861 if hasattr(self, 'print_options_%s' % key) and not keep_default:
2862 return getattr(self, 'print_options_%s' % key)()
2863
2864
2865 try:
2866 ind = self.get_allowed(key).index(self.switch[key])
2867 except Exception, err:
2868 options = self.get_allowed(key)
2869 else:
2870 options = self.get_allowed(key)[ind:]+ self.get_allowed(key)[:ind]
2871
2872 info = '|'.join([v for v in options if v != self.switch[key]])
2873 if info == '':
2874 info = 'Please install module'
2875 return info
2876
2877 - def do_help(self, line, list_command=False):
2878 """dedicated help for the control switch"""
2879
2880 if line:
2881 return self.print_help_for_switch(line)
2882
2883
2884 logger.info(" ")
2885 logger.info(" In order to change a switch you can:")
2886 logger.info(" - type 'NAME = VALUE' to set the switch NAME to a given value.")
2887 logger.info(" - type 'ID = VALUE' to set the switch correspond to the line ID to a given value.")
2888 logger.info(" - type 'ID' where ID is the value of the line to pass from one value to the next.")
2889 logger.info(" - type 'NAME' to set the switch NAME to the next value.")
2890 logger.info("")
2891 logger.info(" You can type 'help NAME' for more help on a given switch")
2892 logger.info("")
2893 logger.info(" Special keyword:", '$MG:BOLD')
2894 logger.info(" %s" % '\t'.join([p[4:] for p in dir(self) if p.startswith('ans_')]) )
2895 logger.info(" type 'help XXX' for more information")
2896 if list_command:
2897 super(ControlSwitch, self).do_help(line)
2898
2899
2901 """ """
2902
2903 arg = line.split()[0]
2904
2905 if hasattr(self, 'help_%s' % arg):
2906 return getattr(self, 'help_%s' % arg)('')
2907
2908 if hasattr(self, 'ans_%s' % arg):
2909 return getattr(self, 'help_%s' % arg).__doc__
2910
2911 if arg in self.switch:
2912 logger.info(" information for switch %s: ", arg, '$MG:BOLD')
2913 logger.info(" allowed value:")
2914 logger.info(" %s", '\t'.join(self.get_allowed(arg)))
2915 if hasattr(self, 'help_text_%s' % arg):
2916 logger.info("")
2917 for line in getattr(self, 'help_text_%s' % arg):
2918 logger.info(line)
2919
2920
2921
2922
3094
3096 """ create the question with correct formatting"""
3097
3098
3099
3100 try:
3101 nb_rows, nb_col = os.popen('stty size', 'r').read().split()
3102 nb_rows, nb_col = int(nb_rows), int(nb_col)
3103 except Exception,error:
3104 nb_rows, nb_col = 20, 80
3105
3106
3107 max_len_description = 0
3108 max_len_switch = 0
3109 max_len_name = 0
3110 max_len_add_info = 0
3111 max_len_potential_switch = 0
3112 max_nb_key = 1 + int(math.log10(len(self.to_control)))
3113
3114 for key, descrip in self.to_control:
3115 if len(descrip) > max_len_description: max_len_description = len(descrip)
3116 if len(key) > max_len_name: max_len_name = len(key)
3117 if key in self.inconsistent_keys:
3118 to_display = '%s < %s' % (self.switch[key], self.inconsistent_keys[key])
3119 else:
3120 to_display = self.switch[key]
3121 if len(to_display) > max_len_switch: max_len_switch=len(to_display)
3122
3123 info = self.print_options(key)
3124 if len(info)> max_len_add_info: max_len_add_info = len(info)
3125
3126 if self.get_allowed(key):
3127 max_k = max(len(k) for k in self.get_allowed(key))
3128 else:
3129 max_k = 0
3130 if max_k > max_len_potential_switch: max_len_potential_switch = max_k
3131
3132 upper_line, lower_line, f1, 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
3136 text = \
3137 ["The following switches determine which programs are run:",
3138 upper_line
3139 ]
3140
3141
3142
3143 for i,(key, descrip) in enumerate(self.to_control):
3144
3145
3146
3147 data_to_format = {'nb': i+1,
3148 'descrip': descrip,
3149 'name': key,
3150 'switch': self.color_for_value(key,self.switch[key]),
3151 'add_info': self.print_options(key),
3152 'switch_nc': self.switch[key],
3153 'strike_switch': u'\u0336'.join(' %s ' %self.switch[key].upper()) + u'\u0336',
3154 }
3155 if key in self.inconsistent_keys:
3156
3157 _,_,_, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3158 max_len_name, max_len_add_info,
3159 max_len_potential_switch, max_nb_key,
3160 key=key)
3161
3162 data_to_format['conflict_switch_nc'] = self.inconsistent_keys[key]
3163 data_to_format['conflict_switch'] = self.color_for_value(key,self.inconsistent_keys[key], consistency=False)
3164 text.append(f2 % data_to_format)
3165 else:
3166 text.append(f1 % data_to_format)
3167
3168
3169 text.append(lower_line)
3170
3171
3172 example = None
3173 for key in self.switch:
3174 if len(self.get_allowed(key)) > 1:
3175 for val in self.get_allowed(key):
3176 if val != self.switch[key]:
3177 example = (key, val)
3178 break
3179 else:
3180 continue
3181 break
3182
3183 if not example:
3184 example = ('KEY', 'VALUE')
3185
3186 if help_text:
3187 text += \
3188 ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
3189 "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
3190 "Type 'help' for the list of all valid option",
3191 "Type '0', 'auto', 'done' or just press enter when you are done."]
3192
3193
3194 if len(text) > nb_rows:
3195
3196 to_remove = [ -2,
3197 -5,
3198 -4,
3199 -3,
3200 -1,
3201 ]
3202 to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
3203 text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
3204
3205 self.question = "\n".join(text)
3206 return self.question
3207
3208
3209
3210
3211
3212 -class CmdFile(file):
3213 """ a class for command input file -in order to debug cmd \n problem"""
3214
3221
3223 """readline method treating correctly a line whithout \n at the end
3224 (add it)
3225 """
3226 if self.lines:
3227 line = self.lines.pop(0)
3228 else:
3229 return ''
3230
3231 if line.endswith('\n'):
3232 return line
3233 else:
3234 return line + '\n'
3235
3238
3241