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
822 "Complete the save command"
823
824 args = self.split_arg(line[0:begidx])
825
826
827 if len(args) == 1:
828 return self.list_completion(text, ['options'])
829
830
831 if args[-1].endswith(os.path.sep):
832 return self.path_completion(text,
833 pjoin('.',*[a for a in args if a.endswith(os.path.sep)]),
834 only_dirs = True)
835
836
837 if len(args) == 2:
838 return self.path_completion(text)
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
2006 """ add path for shell """
2007
2008
2009
2010 if len(self.split_arg(line[0:begidx])) > 1 and line[begidx - 1] == os.path.sep:
2011 if not text:
2012 text = ''
2013 output = self.path_completion(text,
2014 base_dir=\
2015 self.split_arg(line[0:begidx])[-1])
2016 else:
2017 output = self.path_completion(text)
2018 return output
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
2354 consistency_XX_YY(val_XX, val_YY)
2355 -> XX is the new key set by the user to a new value val_XX
2356 -> YY is another key set by the user.
2357 -> return value should be None or "replace_YY"
2358
2359 consistency_XX(val_XX):
2360 check the consistency of the other switch given the new status of this one.
2361 return a dict {key:replaced_value} or {} if nothing to do
2362
2363 user typing "NAME" will result to a call to self.ans_NAME(None)
2364 user typing "NAME=XX" will result to a call to self.ans_NAME('XX')
2365
2366 Note on case sensitivity:
2367 -------------------------
2368 the XXX is displayed with the case in self.to_control
2369 but ALL functions should use the lower case version.
2370 for key associated to get_allowed_keys(),
2371 if (user) value not in that list.
2372 -> try to find the first entry matching up to the case
2373 for ans_XXX, set the value to lower case, but if case_XXX is set to True
2374 """
2375
2376 case_sensitive = False
2377 quit_on = ['0','done', 'EOF','','auto']
2378
2379 - def __init__(self, to_control, motherinstance, *args, **opts):
2380 """to_control is a list of ('KEY': 'Choose the shower/hadronization program')
2381 """
2382
2383 self.to_control = to_control
2384 self.mother_interface = motherinstance
2385 self.inconsistent_keys = {}
2386
2387
2388 self.inconsistent_details = {}
2389 self.last_changed = []
2390
2391
2392 self.switch = {}
2393 for key, _ in to_control:
2394 self.switch[key.lower()] = 'temporary'
2395
2396 self.set_default_switch()
2397 question = self.create_question()
2398
2399
2400 allowed_args = [ `i`+';' for i in range(1, 1+len(self.to_control))]
2401 for key in self.switch:
2402 allowed_args += ['%s=%s;' % (key,s) for s in self.get_allowed(key)]
2403
2404 allowed_args += [key[4:]+';' for key in dir(self) if key.startswith('ans_')]
2405 if 'allow_arg' in opts:
2406 allowed_args += opts['allow_arg']
2407 del opts['allow_arg']
2408
2409 allowed_args +=["0", "done"]
2410 SmartQuestion.__init__(self, question, allowed_args, *args, **opts)
2411 self.options = self.mother_interface.options
2412
2439
2440
2441
2442
2443
2445
2446 for key,_ in self.to_control:
2447 key = key.lower()
2448 if hasattr(self, 'default_switch') and key in self.default_switch:
2449 self.switch[key] = self.default_switch[key]
2450 continue
2451 if hasattr(self, 'set_default_%s' % key):
2452 getattr(self, 'set_default_%s' % key)()
2453 else:
2454 self.default_switch_for(key)
2455
2457 """use this if they are no dedicated function for such key"""
2458
2459 if hasattr(self, 'get_allowed_%s' % key):
2460 return getattr(self, 'get_allowed_%s' % key)()[0]
2461 else:
2462 self.switch[key] = 'OFF'
2463
2465 """set all valid parameter to OFF --call before special keyword--
2466 """
2467
2468 for key in self.switch:
2469 if hasattr(self, 'switch_off_%s' % key):
2470 getattr(self, 'switch_off_%s' % key)()
2471 elif self.check_value(key, self.switch[key]):
2472 self.switch[key] = 'OFF'
2473 self.inconsistent_details = {}
2474 self.inconsistent_keys = {}
2475
2476
2478 """return True/False if the value is a correct value to be set by the USER.
2479 other value than those can be set by the system --like-- Not available.
2480 This does not check the full consistency of the switch
2481 """
2482
2483 if hasattr(self, 'check_value_%s' % key):
2484 return getattr(self, 'check_value_%s' % key)(value)
2485 elif value in self.get_allowed(key):
2486 return True
2487 else:
2488 return False
2489
2490
2492 """ return the list of command that need to be run to have a consistent
2493 set of cards with the switch value choosen """
2494
2495 switch = self.answer
2496 cmd= []
2497 for key in self.switch:
2498 if hasattr(self, 'get_cardcmd_for_%s' % key):
2499 cmd += getattr(self, 'get_cardcmd_for_%s' % key)(switch[key])
2500 return cmd
2501
2502
2504 """return the list of possible value for key"""
2505
2506 if hasattr(self, 'get_allowed_%s' % key):
2507 return getattr(self, 'get_allowed_%s' % key)()
2508 else:
2509 return ['ON', 'OFF']
2510
2511 - def default(self, line, raise_error=False):
2512 """Default action if line is not recognized"""
2513
2514 line=line.strip().replace('@', '__at__')
2515 if ';' in line:
2516 for l in line.split(';'):
2517 if l:
2518 out = self.default(l)
2519 return out
2520
2521 if '=' in line:
2522 base, value = line.split('=',1)
2523 base = base.strip()
2524 value = value.strip()
2525
2526 if base.isdigit() :
2527 try:
2528 base = self.to_control[int(base)-1][0]
2529 except:
2530 pass
2531 elif ' ' in line:
2532 base, value = line.split(' ', 1)
2533 elif hasattr(self, 'ans_%s' % line.lower()):
2534 base, value = line.lower(), None
2535 elif line.isdigit() and line in [`i` for i in range(1, len(self.to_control)+1)]:
2536
2537 base = self.to_control[int(line)-1][0].lower()
2538 return self.default(base)
2539 elif line.lower() in self.switch:
2540
2541 base = line.lower()
2542 try:
2543 cur = self.get_allowed(base).index(self.switch[base])
2544 except:
2545 if self.get_allowed(base):
2546 value = self.get_allowed(base)[0]
2547 else:
2548 logger.warning('Can not switch "%s" to another value via number', base)
2549 self.value='reask'
2550 return
2551 else:
2552 try:
2553 value = self.get_allowed(base)[cur+1]
2554 except IndexError:
2555 value = self.get_allowed(base)[0]
2556 elif line in ['', 'done', 'EOF', 'eof','0']:
2557 super(ControlSwitch, self).default(line)
2558 return self.answer
2559 elif line in 'auto':
2560 self.switch['dynamical'] = True
2561 return super(ControlSwitch, self).default(line)
2562 elif raise_error:
2563 raise NotValidInput('unknow command: %s' % line)
2564 else:
2565 logger.warning('unknow command: %s' % line)
2566 self.value = 'reask'
2567 return
2568
2569 self.value = 'reask'
2570 base = base.lower()
2571 if hasattr(self, 'ans_%s' % base):
2572 if value and not self.is_case_sensitive(base):
2573 value = value.lower()
2574 getattr(self, 'ans_%s' % base)(value)
2575 elif base in self.switch:
2576 self.set_switch(base, value)
2577 elif raise_error:
2578 raise NotValidInput('Not valid command: %s' % line)
2579 else:
2580 logger.warning('Not valid command: %s' % line)
2581
2583 """check if a key is case sensitive"""
2584
2585 case = self.case_sensitive
2586 if hasattr(self, 'case_%s' % key):
2587 case = getattr(self, 'case_%s' % key)
2588 return case
2589
2590 - def onecmd(self, line, **opt):
2595
2596 @property
2598
2599
2600 for key,_ in self.to_control:
2601 if not self.check_value(key, self.switch[key]):
2602 self.switch[key] = 'OFF'
2603
2604 if not self.inconsistent_keys:
2605 return self.switch
2606 else:
2607 out = dict(self.switch)
2608 out.update(self.inconsistent_keys)
2609 return out
2610
2611 - def postcmd(self, stop, line):
2612
2613 line = line.strip()
2614 if ';' in line:
2615 line= [l for l in line.split(';') if l][-1]
2616 if line in self.quit_on:
2617 return True
2618 self.create_question()
2619 return self.reask(True)
2620
2621
2623 """change a switch to a given value"""
2624
2625 assert key in self.switch
2626
2627 if hasattr(self, 'ans_%s' % key):
2628 if not self.is_case_sensitive(key):
2629 value = value.lower()
2630 return getattr(self, 'ans_%s' % key)(value)
2631
2632 if not self.is_case_sensitive(key) and value not in self.get_allowed(key):
2633 lower = [t.lower() for t in self.get_allowed(key)]
2634 try:
2635 ind = lower.index(value.lower())
2636 except ValueError:
2637 pass
2638 else:
2639 value = self.get_allowed(key)[ind]
2640
2641 check = self.check_value(key, value)
2642 if not check:
2643 logger.warning('"%s" not valid option for "%s"', value, key)
2644 return
2645 if isinstance(check, str):
2646 value = check
2647
2648 self.switch[key] = value
2649
2650 if user:
2651 self.check_consistency(key, value)
2652
2654
2655 if not keys:
2656 self.inconsistent_keys = {}
2657 self.inconsistent_details = {}
2658 elif isinstance(keys, list):
2659 for key in keys:
2660 if key in self.inconsistent_keys:
2661 del self.inconsistent_keys[keys]
2662 del self.inconsistent_details[keys]
2663 else:
2664 if keys in self.inconsistent_keys:
2665 del self.inconsistent_keys[keys]
2666 del self.inconsistent_details[keys]
2667
2669 """check the consistency of the new flag with the old ones"""
2670
2671 if key in self.last_changed:
2672 self.last_changed.remove(key)
2673 self.last_changed.append(key)
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687 if hasattr(self, 'consistency_%s' % key):
2688 rules = dict([(key2, None) for key2 in self.switch])
2689 rules.update(getattr(self, 'consistency_%s' % key)(value, self.switch))
2690 else:
2691 rules = {}
2692 for key2,value2 in self.switch.items():
2693 if hasattr(self, 'consistency_%s_%s' % (key,key2)):
2694 rules[key2] = getattr(self, 'consistency_%s_%s' % (key,key2))(value, value2)
2695
2696
2697 if rules[key2] is not None and not self.check_value(key2, rules[key2]):
2698 if rules[key2] != 'OFF':
2699 logger.debug('consistency_%s_%s returns invalid output. Assume no conflict')
2700 rules[key2] = None
2701 else:
2702 rules[key2] = None
2703
2704
2705
2706
2707
2708 self.remove_inconsistency(key)
2709
2710 for key2 in self.switch:
2711 if rules[key2]:
2712 info = {'orig_value': self.switch[key2],
2713 'changed_key': key,
2714 'new_changed_key_val': value,
2715 'replacement': rules[key2]}
2716 if key2 in self.inconsistent_details:
2717 self.inconsistent_details[key2].append(info)
2718 else:
2719 self.inconsistent_details[key2] = [info]
2720
2721 if not self.inconsistent_details:
2722 return
2723
2724
2725 for key2 in dict(self.inconsistent_details):
2726 for conflict in list(self.inconsistent_details[key2]):
2727 keep_conflict = True
2728
2729 if conflict['orig_value'] != self.switch[key2]:
2730 keep_conflict = False
2731
2732 if self.switch[conflict['changed_key']] != conflict['new_changed_key_val']:
2733 keep_conflict = False
2734 if not keep_conflict:
2735 self.inconsistent_details[key2].remove(conflict)
2736 if not self.inconsistent_details[key2]:
2737 del self.inconsistent_details[key2]
2738
2739
2740
2741
2742 tmp_switch = dict(self.switch)
2743
2744
2745 to_check = [(c['changed_key'], c['new_changed_key_val']) \
2746 for k in self.inconsistent_details.values() for c in k
2747 if c['changed_key'] != key]
2748
2749 to_check.sort(lambda x, y: -1 if self.last_changed.index(x[0])>self.last_changed.index(y[0]) else 1)
2750
2751
2752 to_check = [(key, value)] + to_check
2753
2754 i = 0
2755 while len(to_check) and i < 50:
2756
2757
2758 i +=1
2759 key2, value2 = to_check.pop(0)
2760 if hasattr(self, 'consistency_%s' % key2):
2761 rules2 = dict([(key2, None) for key2 in self.switch])
2762 rules2.update(getattr(self, 'consistency_%s' % key2)(value, tmp_switch))
2763 else:
2764 rules = {}
2765 for key3,value3 in self.switch.items():
2766 if hasattr(self, 'consistency_%s_%s' % (key2,key3)):
2767 rules[key3] = getattr(self, 'consistency_%s_%s' % (key2,key3))(value2, value3)
2768 else:
2769 rules[key3] = None
2770
2771 for key, replacement in rules.items():
2772 if replacement:
2773 tmp_switch[key] = replacement
2774 to_check.append((key, replacement))
2775
2776
2777
2778 pos = {}
2779 for i, (key,value) in enumerate(to_check):
2780 pos[key] = i
2781 to_check_new = []
2782 for i, (key,value) in enumerate(to_check):
2783 if pos[key] == i:
2784 to_check_new.append((key,value))
2785 to_check = to_check_new
2786 if i>=50:
2787 logger.critical('Failed to find a consistent set of switch values.')
2788
2789
2790
2791 self.inconsistent_keys = {}
2792 for key2, value2 in tmp_switch.items():
2793 if value2 != self.switch[key2]:
2794
2795 if value2 == 'OFF' and not self.check_value(key2, 'OFF'):
2796 continue
2797 self.inconsistent_keys[key2] = value2
2798
2799
2800
2801
2802 green = '\x1b[32m%s\x1b[0m'
2803 yellow = '\x1b[33m%s\x1b[0m'
2804 red = '\x1b[31m%s\x1b[0m'
2805 bold = '\x1b[01m%s\x1b[0m'
2807
2808 if consistency and key in self.inconsistent_keys:
2809 return self.color_for_value(key, self.inconsistent_keys[key], consistency=False) +\
2810 u' \u21d0 '+ self.yellow % switch_value
2811
2812 if self.check_value(key, switch_value):
2813 if hasattr(self, 'color_for_%s' % key):
2814 return getattr(self, 'color_for_%s' % key)(switch_value)
2815 if switch_value in ['OFF']:
2816
2817 return self.red % switch_value
2818 else:
2819 return self.green % switch_value
2820 else:
2821 if ' ' in switch_value:
2822 return self.bold % switch_value
2823 else:
2824 return self.red % switch_value
2825
2827
2828 if hasattr(self, 'print_info_%s' % key):
2829 return getattr(self, 'print_info_%s' % key)
2830
2831
2832 try:
2833 ind = self.get_allowed(key).index(self.switch[key])
2834 except Exception, err:
2835 options = self.get_allowed(key)
2836 else:
2837 options = self.get_allowed(key)[ind:]+ self.get_allowed(key)[:ind]
2838
2839 info = '|'.join([v for v in options if v != self.switch[key]])
2840 if info == '':
2841 info = 'Please install module'
2842 return info
2843
2844 - def do_help(self, line, list_command=False):
2845 """dedicated help for the control switch"""
2846
2847 if line:
2848 return self.print_help_for_switch(line)
2849
2850
2851 logger.info(" ")
2852 logger.info(" In order to change a switch you can:")
2853 logger.info(" - type 'NAME = VALUE' to set the switch NAME to a given value.")
2854 logger.info(" - type 'ID = VALUE' to set the switch correspond to the line ID to a given value.")
2855 logger.info(" - type 'ID' where ID is the value of the line to pass from one value to the next.")
2856 logger.info(" - type 'NAME' to set the switch NAME to the next value.")
2857 logger.info("")
2858 logger.info(" You can type 'help NAME' for more help on a given switch")
2859 logger.info("")
2860 logger.info(" Special keyword:", '$MG:BOLD')
2861 logger.info(" %s" % '\t'.join([p[4:] for p in dir(self) if p.startswith('ans_')]) )
2862 logger.info(" type 'help XXX' for more information")
2863 if list_command:
2864 super(ControlSwitch, self).do_help(line)
2865
2866
2868 """ """
2869
2870 arg = line.split()[0]
2871
2872 if hasattr(self, 'help_%s' % arg):
2873 return getattr(self, 'help_%s' % arg)('')
2874
2875 if hasattr(self, 'ans_%s' % arg):
2876 return getattr(self, 'help_%s' % arg).__doc__
2877
2878 if arg in self.switch:
2879 logger.info(" information for switch %s: ", arg, '$MG:BOLD')
2880 logger.info(" allowed value:")
2881 logger.info(" %s", '\t'.join(self.get_allowed(arg)))
2882 if hasattr(self, 'help_text_%s' % arg):
2883 logger.info("")
2884 for line in getattr(self, 'help_text_%s' % arg):
2885 logger.info(line)
2886
2887
2888
2889
3061
3063 """ create the question with correct formatting"""
3064
3065
3066
3067 try:
3068 nb_rows, nb_col = os.popen('stty size', 'r').read().split()
3069 nb_rows, nb_col = int(nb_rows), int(nb_col)
3070 except Exception,error:
3071 nb_rows, nb_col = 20, 80
3072
3073
3074 max_len_description = 0
3075 max_len_switch = 0
3076 max_len_name = 0
3077 max_len_add_info = 0
3078 max_len_potential_switch = 0
3079 max_nb_key = 1 + int(math.log10(len(self.to_control)))
3080
3081 for key, descrip in self.to_control:
3082 if len(descrip) > max_len_description: max_len_description = len(descrip)
3083 if len(key) > max_len_name: max_len_name = len(key)
3084 if key in self.inconsistent_keys:
3085 to_display = '%s < %s' % (self.switch[key], self.inconsistent_keys[key])
3086 else:
3087 to_display = self.switch[key]
3088 if len(to_display) > max_len_switch: max_len_switch=len(to_display)
3089
3090 info = self.print_info(key)
3091 if len(info)> max_len_add_info: max_len_add_info = len(info)
3092
3093 if self.get_allowed(key):
3094 max_k = max(len(k) for k in self.get_allowed(key))
3095 else:
3096 max_k = 0
3097 if max_k > max_len_potential_switch: max_len_potential_switch = max_k
3098
3099 upper_line, lower_line, f1, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3100 max_len_name, max_len_add_info,
3101 max_len_potential_switch, max_nb_key)
3102
3103 text = \
3104 ["The following switches determine which programs are run:",
3105 upper_line
3106 ]
3107
3108
3109
3110 for i,(key, descrip) in enumerate(self.to_control):
3111
3112
3113
3114 data_to_format = {'nb': i+1,
3115 'descrip': descrip,
3116 'name': key,
3117 'switch': self.color_for_value(key,self.switch[key]),
3118 'add_info': self.print_info(key),
3119 'switch_nc': self.switch[key],
3120 'strike_switch': u'\u0336'.join(' %s ' %self.switch[key].upper()) + u'\u0336',
3121 }
3122 if key in self.inconsistent_keys:
3123
3124 _,_,_, f2 = self.question_formatting(nb_col, max_len_description, max_len_switch,
3125 max_len_name, max_len_add_info,
3126 max_len_potential_switch, max_nb_key,
3127 key=key)
3128
3129 data_to_format['conflict_switch_nc'] = self.inconsistent_keys[key]
3130 data_to_format['conflict_switch'] = self.color_for_value(key,self.inconsistent_keys[key], consistency=False)
3131 text.append(f2 % data_to_format)
3132 else:
3133 text.append(f1 % data_to_format)
3134
3135
3136 text.append(lower_line)
3137
3138
3139 example = None
3140 for key in self.switch:
3141 if len(self.get_allowed(key)) > 1:
3142 for val in self.get_allowed(key):
3143 if val != self.switch[key]:
3144 example = (key, val)
3145 break
3146 else:
3147 continue
3148 break
3149
3150 if not example:
3151 example = ('KEY', 'VALUE')
3152
3153 if help_text:
3154 text += \
3155 ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
3156 "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
3157 "Type 'help' for the list of all valid option",
3158 "Type '0', 'auto', 'done' or just press enter when you are done."]
3159
3160
3161 if len(text) > nb_rows:
3162
3163 to_remove = [ -2,
3164 -5,
3165 -4,
3166 -3,
3167 -1,
3168 ]
3169 to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
3170 text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
3171
3172 self.question = "\n".join(text)
3173 return self.question
3174
3175
3176
3177
3178
3179 -class CmdFile(file):
3180 """ a class for command input file -in order to debug cmd \n problem"""
3181
3188
3190 """readline method treating correctly a line whithout \n at the end
3191 (add it)
3192 """
3193 if self.lines:
3194 line = self.lines.pop(0)
3195 else:
3196 return ''
3197
3198 if line.endswith('\n'):
3199 return line
3200 else:
3201 return line + '\n'
3202
3205
3208