Package madgraph :: Package interface :: Module extended_cmd
[hide private]
[frames] | no frames]

Source Code for Module madgraph.interface.extended_cmd

   1  ################################################################################ 
   2  # 
   3  # Copyright (c) 2011 The MadGraph5_aMC@NLO Development team and Contributors 
   4  # 
   5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
   6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
   7  # high-energy processes in the Standard Model and beyond. 
   8  # 
   9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
  10  # distribution. 
  11  # 
  12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
  13  # 
  14  ################################################################################ 
  15  """  A file containing different extension of the cmd basic python library""" 
  16   
  17   
  18  import cmd 
  19  import logging 
  20  import os 
  21  import pydoc 
  22  import re 
  23  import signal 
  24  import subprocess 
  25  import sys 
  26  import traceback 
  27  try: 
  28      import readline 
  29      GNU_SPLITTING = ('GNU' in readline.__doc__) 
  30  except: 
  31      readline = None 
  32      GNU_SPLITTING = True 
  33   
  34   
  35  logger = logging.getLogger('cmdprint') # for stdout 
  36  logger_stderr = logging.getLogger('fatalerror') # for stderr 
  37   
  38  try: 
  39      import madgraph.various.misc as misc 
  40      from madgraph import MG5DIR 
  41      MADEVENT = False 
  42  except ImportError, error: 
  43      try: 
  44          import internal.misc as misc 
  45      except: 
  46          raise error 
  47      MADEVENT = True 
  48   
  49   
  50  pjoin = os.path.join 
51 52 -class TimeOutError(Exception):
53 """Class for run-time error"""
54
55 -def debug(debug_only=True):
56 57 def deco_debug(f): 58 59 if debug_only and not __debug__: 60 return f 61 62 def deco_f(*args, **opt): 63 try: 64 return f(*args, **opt) 65 except Exception, error: 66 logger.error(error) 67 logger.error(traceback.print_exc(file=sys.stdout)) 68 return
69 return deco_f 70 return deco_debug 71
72 73 #=============================================================================== 74 # CmdExtended 75 #=============================================================================== 76 -class BasicCmd(cmd.Cmd):
77 """Simple extension for the readline""" 78
79 - def preloop(self):
80 if readline and not 'libedit' in readline.__doc__: 81 readline.set_completion_display_matches_hook(self.print_suggestions)
82
83 - def deal_multiple_categories(self, dico):
84 """convert the multiple category in a formatted list understand by our 85 specific readline parser""" 86 87 if 'libedit' in readline.__doc__: 88 # No parser in this case, just send all the valid options 89 out = [] 90 for name, opt in dico.items(): 91 out += opt 92 return out 93 94 # check if more than one categories but only one value: 95 if all(len(s) <= 1 for s in dico.values() ): 96 values = set((s[0] for s in dico.values() if len(s)==1)) 97 if len(values) == 1: 98 return values 99 100 # That's the real work 101 out = [] 102 valid=0 103 # if the key starts with number order the key with that number. 104 for name, opt in dico.items(): 105 if not opt: 106 continue 107 name = name.replace(' ', '_') 108 valid += 1 109 out.append(opt[0].rstrip()+'@@'+name+'@@') 110 # Remove duplicate 111 d = {} 112 for x in opt: 113 d[x] = 1 114 opt = list(d.keys()) 115 opt.sort() 116 out += opt 117 118 119 if valid == 1: 120 out = out[1:] 121 return out
122 123 @debug()
124 - def print_suggestions(self, substitution, matches, longest_match_length) :
125 """print auto-completions by category""" 126 if not hasattr(self, 'completion_prefix'): 127 self.completion_prefix = '' 128 longest_match_length += len(self.completion_prefix) 129 try: 130 if len(matches) == 1: 131 self.stdout.write(matches[0]+' ') 132 return 133 self.stdout.write('\n') 134 l2 = [a[-2:] for a in matches] 135 if '@@' in l2: 136 nb_column = self.getTerminalSize()//(longest_match_length+1) 137 pos=0 138 for val in self.completion_matches: 139 if val.endswith('@@'): 140 category = val.rsplit('@@',2)[1] 141 category = category.replace('_',' ') 142 self.stdout.write('\n %s:\n%s\n' % (category, '=' * (len(category)+2))) 143 start = 0 144 pos = 0 145 continue 146 elif pos and pos % nb_column ==0: 147 self.stdout.write('\n') 148 self.stdout.write(self.completion_prefix + val + \ 149 ' ' * (longest_match_length +1 -len(val))) 150 pos +=1 151 self.stdout.write('\n') 152 else: 153 # nb column 154 nb_column = self.getTerminalSize()//(longest_match_length+1) 155 for i,val in enumerate(matches): 156 if i and i%nb_column ==0: 157 self.stdout.write('\n') 158 self.stdout.write(self.completion_prefix + val + \ 159 ' ' * (longest_match_length +1 -len(val))) 160 self.stdout.write('\n') 161 162 self.stdout.write(self.prompt+readline.get_line_buffer()) 163 self.stdout.flush() 164 except Exception, error: 165 if __debug__: 166 logger.error(error)
167
168 - def getTerminalSize(self):
169 def ioctl_GWINSZ(fd): 170 try: 171 import fcntl, termios, struct 172 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, 173 '1234')) 174 except Exception: 175 return None 176 return cr
177 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) 178 if not cr: 179 try: 180 fd = os.open(os.ctermid(), os.O_RDONLY) 181 cr = ioctl_GWINSZ(fd) 182 os.close(fd) 183 except Exception: 184 pass 185 if not cr: 186 try: 187 cr = (os.environ['LINES'], os.environ['COLUMNS']) 188 except Exception: 189 cr = (25, 80) 190 return int(cr[1])
191
192 - def complete(self, text, state):
193 """Return the next possible completion for 'text'. 194 If a command has not been entered, then complete against command list. 195 Otherwise try to call complete_<command> to get list of completions. 196 """ 197 198 if state == 0: 199 import readline 200 origline = readline.get_line_buffer() 201 line = origline.lstrip() 202 stripped = len(origline) - len(line) 203 begidx = readline.get_begidx() - stripped 204 endidx = readline.get_endidx() - stripped 205 206 if ';' in line: 207 begin, line = line.rsplit(';',1) 208 begidx = begidx - len(begin) - 1 209 endidx = endidx - len(begin) - 1 210 if line[:begidx] == ' ' * begidx: 211 begidx=0 212 213 if begidx>0: 214 cmd, args, foo = self.parseline(line) 215 if cmd == '': 216 compfunc = self.completedefault 217 else: 218 try: 219 compfunc = getattr(self, 'complete_' + cmd) 220 except AttributeError: 221 compfunc = self.completedefault 222 else: 223 compfunc = self.completenames 224 225 # correct wrong splittion with '\ ' 226 if line and begidx > 2 and line[begidx-2:begidx] == '\ ': 227 Ntext = line.split(os.path.sep)[-1] 228 self.completion_prefix = Ntext.rsplit('\ ', 1)[0] + '\ ' 229 to_rm = len(self.completion_prefix) - 1 230 Nbegidx = len(line.rsplit(os.path.sep, 1)[0]) + 1 231 data = compfunc(Ntext.replace('\ ', ' '), line, Nbegidx, endidx) 232 self.completion_matches = [p[to_rm:] for p in data 233 if len(p)>to_rm] 234 # correct wrong splitting with '-' 235 elif line and line[begidx-1] == '-': 236 try: 237 Ntext = line.split()[-1] 238 self.completion_prefix = Ntext.rsplit('-',1)[0] +'-' 239 to_rm = len(self.completion_prefix) 240 Nbegidx = len(line.rsplit(None, 1)[0]) 241 data = compfunc(Ntext, line, Nbegidx, endidx) 242 self.completion_matches = [p[to_rm:] for p in data 243 if len(p)>to_rm] 244 except Exception, error: 245 print error 246 else: 247 self.completion_prefix = '' 248 self.completion_matches = compfunc(text, line, begidx, endidx) 249 250 self.completion_matches = [ l if l[-1] in [' ','@','=',os.path.sep] 251 else ((l + ' ') if not l.endswith('\\$') else l[:-2]) 252 for l in self.completion_matches if l] 253 254 try: 255 return self.completion_matches[state] 256 except IndexError, error: 257 # if __debug__: 258 # logger.error('\n Completion ERROR:') 259 # logger.error( error) 260 return None
261 262 @staticmethod
263 - def split_arg(line):
264 """Split a line of arguments""" 265 266 split = line.split() 267 out=[] 268 tmp='' 269 for data in split: 270 if data[-1] == '\\': 271 tmp += data[:-1]+' ' 272 elif tmp: 273 tmp += data 274 tmp = os.path.expanduser(os.path.expandvars(tmp)) 275 out.append(tmp) 276 else: 277 out.append(data) 278 return out
279 280 @staticmethod
281 - def list_completion(text, list, line=''):
282 """Propose completions of text in list""" 283 284 if not text: 285 completions = list 286 else: 287 completions = [ f 288 for f in list 289 if f.startswith(text) 290 ] 291 292 return completions
293 294 295 @staticmethod
296 - def path_completion(text, base_dir = None, only_dirs = False, 297 relative=True):
298 """Propose completions of text to compose a valid path""" 299 300 if base_dir is None: 301 base_dir = os.getcwd() 302 base_dir = os.path.expanduser(os.path.expandvars(base_dir)) 303 304 if text == '~': 305 text = '~/' 306 prefix, text = os.path.split(text) 307 prefix = os.path.expanduser(os.path.expandvars(prefix)) 308 base_dir = os.path.join(base_dir, prefix) 309 if prefix: 310 prefix += os.path.sep 311 312 if only_dirs: 313 completion = [prefix + f 314 for f in os.listdir(base_dir) 315 if f.startswith(text) and \ 316 os.path.isdir(os.path.join(base_dir, f)) and \ 317 (not f.startswith('.') or text.startswith('.')) 318 ] 319 else: 320 completion = [ prefix + f 321 for f in os.listdir(base_dir) 322 if f.startswith(text) and \ 323 os.path.isfile(os.path.join(base_dir, f)) and \ 324 (not f.startswith('.') or text.startswith('.')) 325 ] 326 327 completion = completion + \ 328 [prefix + f + os.path.sep 329 for f in os.listdir(base_dir) 330 if f.startswith(text) and \ 331 os.path.isdir(os.path.join(base_dir, f)) and \ 332 (not f.startswith('.') or text.startswith('.')) 333 ] 334 335 if relative: 336 completion += [prefix + f for f in ['.'+os.path.sep, '..'+os.path.sep] if \ 337 f.startswith(text) and not prefix.startswith('.')] 338 339 completion = [a.replace(' ','\ ') for a in completion] 340 return completion
341
342 343 344 345 -class CheckCmd(object):
346 """Extension of the cmd object for only the check command""" 347
348 - def check_history(self, args):
349 """check the validity of line""" 350 351 if len(args) > 1: 352 self.help_history() 353 raise self.InvalidCmd('\"history\" command takes at most one argument') 354 355 if not len(args): 356 return 357 358 if args[0] =='.': 359 if not self._export_dir: 360 raise self.InvalidCmd("No default directory is defined for \'.\' option") 361 elif args[0] != 'clean': 362 dirpath = os.path.dirname(args[0]) 363 if dirpath and not os.path.exists(dirpath) or \ 364 os.path.isdir(args[0]): 365 raise self.InvalidCmd("invalid path %s " % dirpath)
366
367 - def check_save(self, args):
368 """check that the line is compatible with save options""" 369 370 if len(args) > 2: 371 self.help_save() 372 raise self.InvalidCmd, 'too many arguments for save command.' 373 374 if len(args) == 2: 375 if args[0] != 'options': 376 self.help_save() 377 raise self.InvalidCmd, '\'%s\' is not recognized as first argument.' % \ 378 args[0] 379 else: 380 args.pop(0)
381
382 -class HelpCmd(object):
383 """Extension of the cmd object for only the help command""" 384
385 - def help_quit(self):
386 logger.info("-- terminates the application",'$MG:color:BLUE') 387 logger.info("syntax: quit",'$MG:color:BLACK')
388 389 help_EOF = help_quit 390
391 - def help_history(self):
392 logger.info("-- interact with the command history.",'$MG:color:BLUE') 393 logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:color:BLACK') 394 logger.info(" > If FILEPATH is \'.\' and \'output\' is done,") 395 logger.info(" Cards/proc_card_mg5.dat will be used.") 396 logger.info(" > If FILEPATH is omitted, the history will be output to stdout.") 397 logger.info(" \"clean\" will remove all entries from the history.")
398
399 - def help_help(self):
400 logger.info("-- access to the in-line help",'$MG:color:BLUE') 401 logger.info("syntax: help",'$MG:color:BLACK')
402
403 - def help_save(self):
404 """help text for save""" 405 logger.info("-- save options configuration to filepath.",'$MG:color:BLUE') 406 logger.info("syntax: save [options] [FILEPATH]",'$MG:color:BLACK')
407
408 - def help_display(self):
409 """help for display command""" 410 logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE') 411 logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLACK')
412
413 -class CompleteCmd(object):
414 """Extension of the cmd object for only the complete command""" 415
416 - def complete_display(self,text, line, begidx, endidx):
417 args = self.split_arg(line[0:begidx]) 418 # Format 419 if len(args) == 1: 420 return self.list_completion(text, self._display_opts)
421
422 - def complete_history(self, text, line, begidx, endidx):
423 "Complete the history command" 424 425 args = self.split_arg(line[0:begidx]) 426 427 # Directory continuation 428 if args[-1].endswith(os.path.sep): 429 return self.path_completion(text, 430 os.path.join('.',*[a for a in args \ 431 if a.endswith(os.path.sep)])) 432 433 if len(args) == 1: 434 return self.path_completion(text)
435
436 - def complete_save(self, text, line, begidx, endidx):
437 "Complete the save command" 438 439 args = self.split_arg(line[0:begidx]) 440 441 # Format 442 if len(args) == 1: 443 return self.list_completion(text, ['options']) 444 445 # Directory continuation 446 if args[-1].endswith(os.path.sep): 447 return self.path_completion(text, 448 pjoin('.',*[a for a in args if a.endswith(os.path.sep)]), 449 only_dirs = True) 450 451 # Filename if directory is not given 452 if len(args) == 2: 453 return self.path_completion(text)
454
455 -class Cmd(CheckCmd, HelpCmd, CompleteCmd, BasicCmd):
456 """Extension of the cmd.Cmd command line. 457 This extensions supports line breaking, history, comments, 458 internal call to cmdline, path completion,... 459 this class should be MG5 independent""" 460 461 #suggested list of command 462 next_possibility = {} # command : [list of suggested command] 463 history_header = "" 464 465 _display_opts = ['options','variable'] 466
467 - class InvalidCmd(Exception):
468 """expected error for wrong command""" 469 pass
470 471 ConfigurationError = InvalidCmd 472 473 debug_output = 'debug' 474 error_debug = """Please report this bug to developers\n 475 More information is found in '%(debug)s'.\n 476 Please attach this file to your report.""" 477 config_debug = error_debug 478 479 keyboard_stop_msg = """stopping all current operation 480 in order to quit the program please enter exit""" 481 482
483 - def __init__(self, *arg, **opt):
484 """Init history and line continuation""" 485 486 self.log = True 487 self.history = [] 488 self.save_line = '' # for line splitting 489 cmd.Cmd.__init__(self, *arg, **opt) 490 self.__initpos = os.path.abspath(os.getcwd()) 491 self.child = None # sub CMD interface call from this one 492 self.mother = None #This CMD interface was called from another one 493 self.inputfile = None # input file (in non interactive mode) 494 self.haspiping = not sys.stdin.isatty() # check if mg5 is piped 495 self.stored_line = '' # for be able to treat answer to question in input file 496 # answer which are not required. 497 if not hasattr(self, 'helporder'): 498 self.helporder = ['Documented commands']
499 500
501 - def precmd(self, line):
502 """ A suite of additional function needed for in the cmd 503 this implement history, line breaking, comment treatment,... 504 """ 505 506 if not line: 507 return line 508 line = line.lstrip() 509 510 # Check if we are continuing a line: 511 if self.save_line: 512 line = self.save_line + line 513 self.save_line = '' 514 515 # Check if the line is complete 516 if line.endswith('\\'): 517 self.save_line = line[:-1] 518 return '' # do nothing 519 520 # Remove comment 521 if '#' in line: 522 line = line.split('#')[0] 523 524 # Deal with line splitting 525 if ';' in line: 526 lines = line.split(';') 527 for subline in lines: 528 if not (subline.startswith("history") or subline.startswith('help') \ 529 or subline.startswith('#*')): 530 self.history.append(subline) 531 stop = self.onecmd(subline) 532 stop = self.postcmd(stop, subline) 533 return '' 534 535 # execute the line command 536 self.history.append(line) 537 return line
538
539 - def postcmd(self,stop, line):
540 """ finishing a command 541 This looks if the command add a special post part.""" 542 543 if line.strip(): 544 try: 545 cmd, subline = line.split(None, 1) 546 except ValueError: 547 pass 548 else: 549 if hasattr(self,'post_%s' %cmd): 550 stop = getattr(self, 'post_%s' % cmd)(stop, subline) 551 return stop
552
553 - def define_child_cmd_interface(self, obj_instance, interface=True):
554 """Define a sub cmd_interface""" 555 556 # We are in a file reading mode. So we need to redirect the cmd 557 self.child = obj_instance 558 self.child.mother = self 559 560 if self.use_rawinput and interface: 561 # We are in interactive mode -> simply call the child 562 obj_instance.cmdloop() 563 stop = obj_instance.postloop() 564 return stop 565 if self.inputfile: 566 # we are in non interactive mode -> so pass the line information 567 obj_instance.inputfile = self.inputfile 568 569 obj_instance.haspiping = self.haspiping 570 571 if not interface: 572 return self.child
573 574 #=============================================================================== 575 # Ask a question with nice options handling 576 #===============================================================================
577 - def ask(self, question, default, choices=[], path_msg=None, 578 timeout = True, fct_timeout=None, ask_class=None, alias={},**opt):
579 """ ask a question with some pre-define possibility 580 path info is 581 """ 582 if path_msg: 583 path_msg = [path_msg] 584 else: 585 path_msg = [] 586 587 if timeout: 588 try: 589 timeout = self.options['timeout'] 590 except Exception: 591 pass 592 593 # add choice info to the question 594 if choices + path_msg: 595 question += ' [' 596 question += "\033[%dm%s\033[0m, " % (4, default) 597 for data in choices[:9] + path_msg: 598 if default == data: 599 continue 600 else: 601 question += "%s, " % data 602 603 if len(choices) > 9: 604 question += '... , ' 605 question = question[:-2]+']' 606 else: 607 question += "[\033[%dm%s\033[0m] " % (4, default) 608 if ask_class: 609 obj = ask_class 610 elif path_msg: 611 obj = OneLinePathCompletion 612 else: 613 obj = SmartQuestion 614 615 if alias: 616 choices += alias.keys() 617 618 question_instance = obj(question, allow_arg=choices, default=default, 619 mother_interface=self, **opt) 620 if not self.haspiping: 621 if hasattr(obj, "haspiping"): 622 obj.haspiping = self.haspiping 623 624 625 answer = self.check_answer_in_input_file(question_instance, default, path_msg) 626 if answer is not None: 627 if answer in alias: 628 answer = alias[answer] 629 if ask_class: 630 answer = question_instance.default(answer) 631 return answer 632 633 question = question_instance.question 634 value = Cmd.timed_input(question, default, timeout=timeout, 635 fct=question_instance, fct_timeout=fct_timeout) 636 637 try: 638 if value in alias: 639 value = alias[value] 640 except TypeError: 641 pass 642 if value == default and ask_class: 643 value = question_instance.default(default) 644 return value
645
646 - def do_import(self, line):
647 """Advanced commands: Import command files""" 648 649 args = self.split_arg(line) 650 # Check argument's validity 651 self.check_import(args) 652 653 # Execute the card 654 self.import_command_file(args[1])
655
656 - def check_import(self, args):
657 """check import command""" 658 659 if '-f' in args: 660 self.force = True 661 args.remove('-f') 662 if args[0] != 'command': 663 args.set(0, 'command') 664 if len(args) != 2: 665 raise self.InvalidCmd('import command requires one filepath argument') 666 if not os.path.exists(args[1]): 667 raise 'No such file or directory %s' % args[1]
668 669
670 - def check_answer_in_input_file(self, question_instance, default, path=False):
671 """Questions can have answer in output file (or not)""" 672 673 if not self.inputfile: 674 return None# interactive mode 675 676 line = self.get_stored_line() 677 # line define if a previous answer was not answer correctly 678 if not line: 679 try: 680 line = self.inputfile.next() 681 except StopIteration: 682 if self.haspiping: 683 logger.debug('piping') 684 self.store_line(line) 685 return None # print the question and use the pipe 686 logger.info(question_instance.question) 687 logger.warning('The answer to the previous question is not set in your input file') 688 logger.warning('Use %s value' % default) 689 return str(default) 690 691 line = line.replace('\n','').strip() 692 if '#' in line: 693 line = line.split('#')[0] 694 if not line: 695 # Comment or empty line, pass to the next one 696 return self.check_answer_in_input_file(question_instance, default, path) 697 options = question_instance.allow_arg 698 if line in options: 699 return line 700 elif hasattr(question_instance, 'do_%s' % line.split()[0]): 701 #This is a command line, exec it and check next line 702 logger.info(line) 703 fct = getattr(question_instance, 'do_%s' % line.split()[0]) 704 fct(' '.join(line.split()[1:])) 705 return self.check_answer_in_input_file(question_instance, default, path) 706 elif path: 707 line = os.path.expanduser(os.path.expandvars(line)) 708 if os.path.exists(line): 709 return line 710 # No valid answer provides 711 if self.haspiping: 712 self.store_line(line) 713 return None # print the question and use the pipe 714 else: 715 logger.info(question_instance.question) 716 logger.warning('The answer to the previous question is not set in your input file') 717 logger.warning('Use %s value' % default) 718 self.store_line(line) 719 return str(default)
720
721 - def store_line(self, line):
722 """store a line of the input file which should be executed by the higher mother""" 723 724 if self.mother: 725 self.mother.store_line(line) 726 else: 727 self.stored_line = line
728
729 - def get_stored_line(self):
730 """return stored line and clean it""" 731 if self.mother: 732 value = self.mother.get_stored_line() 733 self.mother.stored_line = None 734 else: 735 value = self.stored_line 736 self.stored_line = None 737 return value
738 739 740
741 - def nice_error_handling(self, error, line):
742 """ """ 743 # Make sure that we are at the initial position 744 if self.child: 745 return self.child.nice_error_handling(error, line) 746 747 os.chdir(self.__initpos) 748 # Create the debug files 749 self.log = False 750 if os.path.exists(self.debug_output): 751 os.remove(self.debug_output) 752 try: 753 cmd.Cmd.onecmd(self, 'history %s' % self.debug_output.replace(' ', '\ ')) 754 except Exception, error: 755 logger.error(error) 756 757 debug_file = open(self.debug_output, 'a') 758 traceback.print_exc(file=debug_file) 759 # Create a nice error output 760 if self.history and line == self.history[-1]: 761 error_text = 'Command \"%s\" interrupted with error:\n' % line 762 elif self.history: 763 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line 764 error_text += '\"%s\" with error:\n' % self.history[-1] 765 else: 766 error_text = '' 767 error_text += '%s : %s\n' % (error.__class__.__name__, 768 str(error).replace('\n','\n\t')) 769 error_text += self.error_debug % {'debug':self.debug_output} 770 logger_stderr.critical(error_text) 771 772 773 # Add options status to the debug file 774 try: 775 self.do_display('options', debug_file) 776 except Exception, error: 777 debug_file.write('Fail to write options with error %s' % error) 778 779 #add the cards: 780 for card in ['proc_card_mg5.dat','param_card.dat', 'run_card.dat']: 781 try: 782 ff = open(pjoin(self.me_dir, 'Cards', card)) 783 debug_file.write(ff.read()) 784 ff.close() 785 except Exception: 786 pass 787 788 #stop the execution if on a non interactive mode 789 if self.use_rawinput == False: 790 return True 791 return False
792 793 794
795 - def nice_user_error(self, error, line):
796 if self.child: 797 return self.child.nice_user_error(error, line) 798 # Make sure that we are at the initial position 799 os.chdir(self.__initpos) 800 if line == self.history[-1]: 801 error_text = 'Command \"%s\" interrupted with error:\n' % line 802 else: 803 error_text = 'Command \"%s\" interrupted in sub-command:\n' %line 804 error_text += '\"%s\" with error:\n' % self.history[-1] 805 error_text += '%s : %s' % (error.__class__.__name__, 806 str(error).replace('\n','\n\t')) 807 logger_stderr.error(error_text) 808 #stop the execution if on a non interactive mode 809 if self.use_rawinput == False: 810 return True 811 # Remove failed command from history 812 self.history.pop() 813 return False
814
815 - def nice_config_error(self, error, line):
816 if self.child: 817 return self.child.nice_user_error(error, line) 818 # Make sure that we are at the initial position 819 os.chdir(self.__initpos) 820 if not self.history or line == self.history[-1]: 821 error_text = 'Error detected in \"%s\"\n' % line 822 else: 823 error_text = 'Error detected in sub-command %s\n' % self.history[-1] 824 error_text += 'write debug file %s \n' % self.debug_output 825 self.log = False 826 cmd.Cmd.onecmd(self, 'history %s' % self.debug_output) 827 debug_file = open(self.debug_output, 'a') 828 traceback.print_exc(file=debug_file) 829 error_text += self.config_debug % {'debug' :self.debug_output} 830 error_text += '%s : %s' % (error.__class__.__name__, 831 str(error).replace('\n','\n\t')) 832 logger_stderr.error(error_text) 833 834 # Add options status to the debug file 835 try: 836 self.do_display('options', debug_file) 837 except Exception, error: 838 debug_file.write('Fail to write options with error %s' % error) 839 #stop the execution if on a non interactive mode 840 if self.use_rawinput == False: 841 return True 842 # Remove failed command from history 843 if self.history: 844 self.history.pop() 845 return False
846
847 - def onecmd_orig(self, line, **opt):
848 """Interpret the argument as though it had been typed in response 849 to the prompt. 850 851 The return value is a flag indicating whether interpretation of 852 commands by the interpreter should stop. 853 854 This allow to pass extra argument for internal call. 855 """ 856 if '~/' in line and os.environ.has_key('HOME'): 857 line = line.replace('~/', '%s/' % os.environ['HOME']) 858 line = os.path.expandvars(line) 859 cmd, arg, line = self.parseline(line) 860 if not line: 861 return self.emptyline() 862 if cmd is None: 863 return self.default(line) 864 self.lastcmd = line 865 if cmd == '': 866 return self.default(line) 867 else: 868 try: 869 func = getattr(self, 'do_' + cmd) 870 except AttributeError: 871 return self.default(line) 872 return func(arg, **opt)
873 874
875 - def onecmd(self, line, **opt):
876 """catch all error and stop properly command accordingly""" 877 878 try: 879 return self.onecmd_orig(line, **opt) 880 except self.InvalidCmd as error: 881 if __debug__: 882 self.nice_error_handling(error, line) 883 self.history.pop() 884 else: 885 self.nice_user_error(error, line) 886 except self.ConfigurationError as error: 887 self.nice_config_error(error, line) 888 except Exception as error: 889 self.nice_error_handling(error, line) 890 if self.mother: 891 self.do_quit('') 892 except KeyboardInterrupt as error: 893 self.stop_on_keyboard_stop() 894 if __debug__: 895 self.nice_config_error(error, line) 896 logger.error(self.keyboard_stop_msg)
897
898 - def stop_on_keyboard_stop(self):
899 """action to perform to close nicely on a keyboard interupt""" 900 pass # dummy function
901
902 - def exec_cmd(self, line, errorhandling=False, printcmd=True, 903 precmd=False, postcmd=True, **opt):
904 """for third party call, call the line with pre and postfix treatment 905 without global error handling """ 906 907 if printcmd and not line.startswith('#'): 908 logger.info(line) 909 if self.child: 910 current_interface = self.child 911 else: 912 current_interface = self 913 914 if precmd: 915 line = current_interface.precmd(line) 916 if errorhandling: 917 stop = current_interface.onecmd(line, **opt) 918 else: 919 stop = Cmd.onecmd_orig(current_interface, line, **opt) 920 if postcmd: 921 stop = current_interface.postcmd(stop, line) 922 return stop
923
924 - def run_cmd(self, line):
925 """for third party call, call the line with pre and postfix treatment 926 with global error handling""" 927 928 return self.exec_cmd(line, errorhandling=True, precmd=True)
929
930 - def emptyline(self):
931 """If empty line, do nothing. Default is repeat previous command.""" 932 pass
933
934 - def default(self, line, log=True):
935 """Default action if line is not recognized""" 936 937 # Faulty command 938 if log: 939 logger.warning("Command \"%s\" not recognized, please try again" % \ 940 line.split()[0]) 941 if line.strip() in ['q', '.q', 'stop']: 942 logger.info("If you want to quit mg5 please type \"exit\".") 943 944 if self.history and self.history[-1] == line: 945 self.history.pop()
946 947 948 949 950 951 # Write the list of command line use in this session
952 - def do_history(self, line):
953 """write in a file the suite of command that was used""" 954 955 args = self.split_arg(line) 956 # Check arguments validity 957 self.check_history(args) 958 959 if len(args) == 0: 960 logger.info('\n'.join(self.history)) 961 return 962 elif args[0] == 'clean': 963 self.history = [] 964 logger.info('History is cleaned') 965 return 966 elif args[0] == '.': 967 output_file = os.path.join(self._export_dir, 'Cards', \ 968 'proc_card_mg5.dat') 969 output_file = open(output_file, 'w') 970 else: 971 output_file = open(args[0], 'w') 972 973 # Create the command file 974 text = self.get_history_header() 975 text += ('\n'.join(self.history) + '\n') 976 977 #write this information in a file 978 output_file.write(text) 979 output_file.close() 980 981 if self.log: 982 logger.info("History written to " + output_file.name)
983
984 - def compile(self, *args, **opts):
985 """ """ 986 987 return misc.compile(nb_core=self.options['nb_core'], *args, **opts)
988
989 - def avoid_history_duplicate(self, line, no_break=[]):
990 """remove all line in history (but the last) starting with line. 991 up to the point when a line didn't start by something in no_break. 992 (reading in reverse order)""" 993 994 new_history = [] 995 for i in range(1, len(self.history)+1): 996 cur_line = self.history[-i] 997 if i == 1: 998 new_history.append(cur_line) 999 elif not any((cur_line.startswith(text) for text in no_break)): 1000 to_add = self.history[:-i+1] 1001 to_add.reverse() 1002 new_history += to_add 1003 break 1004 elif cur_line.startswith(line): 1005 continue 1006 else: 1007 new_history.append(cur_line) 1008 1009 new_history.reverse() 1010 self.history[:] = new_history
1011 1012
1013 - def import_command_file(self, filepath):
1014 # remove this call from history 1015 if self.history: 1016 self.history.pop() 1017 1018 # Read the lines of the file and execute them 1019 if isinstance(filepath, str): 1020 commandline = open(filepath).readlines() 1021 else: 1022 commandline = filepath 1023 oldinputfile = self.inputfile 1024 oldraw = self.use_rawinput 1025 self.inputfile = (l for l in commandline) # make a generator 1026 self.use_rawinput = False 1027 # Note using "for line in open(filepath)" is not safe since the file 1028 # filepath can be overwritten during the run (leading to weird results) 1029 # Note also that we need a generator and not a list. 1030 for line in self.inputfile: 1031 #remove pointless spaces and \n 1032 line = line.replace('\n', '').strip() 1033 # execute the line 1034 if line: 1035 self.exec_cmd(line, precmd=True) 1036 stored = self.get_stored_line() 1037 while stored: 1038 line = stored 1039 self.exec_cmd(line, precmd=True) 1040 stored = self.get_stored_line() 1041 1042 # If a child was open close it 1043 if self.child: 1044 self.child.exec_cmd('quit') 1045 self.inputfile = oldinputfile 1046 self.use_rawinput = oldraw 1047 return
1048
1049 - def get_history_header(self):
1050 """Default history header""" 1051 1052 return self.history_header
1053
1054 - def postloop(self):
1055 """ """ 1056 1057 args = self.split_arg(self.lastcmd) 1058 if args and args[0] in ['quit','exit']: 1059 if 'all' in args: 1060 return True 1061 if len(args) >1 and args[1].isdigit(): 1062 if args[1] not in ['0', '1']: 1063 return True 1064 return False
1065 1066 #=============================================================================== 1067 # Ask a question with a maximum amount of time to answer 1068 #=============================================================================== 1069 @staticmethod
1070 - def timed_input(question, default, timeout=None, noerror=True, fct=None, 1071 fct_timeout=None):
1072 """ a question with a maximal time to answer take default otherwise""" 1073 1074 def handle_alarm(signum, frame): 1075 raise TimeOutError
1076 1077 signal.signal(signal.SIGALRM, handle_alarm) 1078 1079 if fct is None: 1080 fct = raw_input 1081 1082 if timeout: 1083 signal.alarm(timeout) 1084 question += '[%ss to answer] ' % (timeout) 1085 try: 1086 result = fct(question) 1087 except TimeOutError: 1088 if noerror: 1089 logger.info('\nuse %s' % default) 1090 if fct_timeout: 1091 fct_timeout(True) 1092 return default 1093 else: 1094 signal.alarm(0) 1095 raise 1096 finally: 1097 signal.alarm(0) 1098 if fct_timeout: 1099 fct_timeout(False) 1100 return result
1101 1102 1103 1104 1105 1106 1107 # Quit
1108 - def do_quit(self, line):
1109 """Not in help: exit the mainloop() """ 1110 1111 if self.child: 1112 self.child.exec_cmd('quit ' + line, printcmd=False) 1113 return 1114 elif self.mother: 1115 self.mother.child = None 1116 if line == 'all': 1117 pass 1118 elif line: 1119 level = int(line) - 1 1120 if level: 1121 self.mother.lastcmd = 'quit %s' % level 1122 logger.info(' ') 1123 return True
1124 1125 # Aliases 1126 do_EOF = do_quit 1127 do_exit = do_quit 1128
1129 - def do_help(self, line):
1130 """Not in help: propose some usefull possible action """ 1131 1132 # if they are an argument use the default help 1133 if line: 1134 return cmd.Cmd.do_help(self, line) 1135 1136 1137 names = self.get_names() 1138 cmds = {} 1139 names.sort() 1140 # There can be duplicates if routines overridden 1141 prevname = '' 1142 for name in names: 1143 if name[:3] == 'do_': 1144 if name == prevname: 1145 continue 1146 prevname = name 1147 cmdname=name[3:] 1148 try: 1149 doc = getattr(self.cmd, name).__doc__ 1150 except Exception: 1151 doc = None 1152 if not doc: 1153 doc = getattr(self, name).__doc__ 1154 if not doc: 1155 tag = "Documented commands" 1156 elif ':' in doc: 1157 tag = doc.split(':',1)[0] 1158 else: 1159 tag = "Documented commands" 1160 if tag in cmds: 1161 cmds[tag].append(cmdname) 1162 else: 1163 cmds[tag] = [cmdname] 1164 1165 self.stdout.write("%s\n"%str(self.doc_leader)) 1166 for tag in self.helporder: 1167 if tag not in cmds: 1168 continue 1169 header = "%s (type help <topic>):" % tag 1170 self.print_topics(header, cmds[tag], 15,80) 1171 for name, item in cmds.items(): 1172 if name in self.helporder: 1173 continue 1174 if name == "Not in help": 1175 continue 1176 header = "%s (type help <topic>):" % name 1177 self.print_topics(header, item, 15,80) 1178 1179 1180 ## Add contextual help 1181 if len(self.history) == 0: 1182 last_action_2 = last_action = 'start' 1183 else: 1184 last_action_2 = last_action = 'none' 1185 1186 pos = 0 1187 authorize = self.next_possibility.keys() 1188 while last_action_2 not in authorize and last_action not in authorize: 1189 pos += 1 1190 if pos > len(self.history): 1191 last_action_2 = last_action = 'start' 1192 break 1193 1194 args = self.history[-1 * pos].split() 1195 last_action = args[0] 1196 if len(args)>1: 1197 last_action_2 = '%s %s' % (last_action, args[1]) 1198 else: 1199 last_action_2 = 'none' 1200 1201 logger.info('Contextual Help') 1202 logger.info('===============') 1203 if last_action_2 in authorize: 1204 options = self.next_possibility[last_action_2] 1205 elif last_action in authorize: 1206 options = self.next_possibility[last_action] 1207 else: 1208 return 1209 text = 'The following command(s) may be useful in order to continue.\n' 1210 for option in options: 1211 text+='\t %s \n' % option 1212 logger.info(text)
1213
1214 - def do_display(self, line, output=sys.stdout):
1215 """Advanced commands: basic display""" 1216 1217 args = self.split_arg(line) 1218 #check the validity of the arguments 1219 1220 if len(args) == 0: 1221 self.help_display() 1222 raise self.InvalidCmd, 'display require at least one argument' 1223 1224 if args[0] == "options": 1225 outstr = "Value of current Options:\n" 1226 for key, value in self.options.items(): 1227 outstr += '%25s \t:\t%s\n' %(key,value) 1228 output.write(outstr) 1229 1230 elif args[0] == "variable": 1231 outstr = "Value of Internal Variable:\n" 1232 try: 1233 var = eval(args[1]) 1234 except Exception: 1235 outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1] 1236 else: 1237 outstr += 'GLOBAL:\n' 1238 outstr += misc.nice_representation(var, nb_space=4) 1239 1240 try: 1241 var = eval('self.%s' % args[1]) 1242 except Exception: 1243 outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1] 1244 else: 1245 outstr += 'LOCAL:\n' 1246 outstr += misc.nice_representation(var, nb_space=4) 1247 split = args[1].split('.') 1248 for i, name in enumerate(split): 1249 try: 1250 __import__('.'.join(split[:i+1])) 1251 exec('%s=sys.modules[\'%s\']' % (split[i], '.'.join(split[:i+1]))) 1252 except ImportError: 1253 try: 1254 var = eval(args[1]) 1255 except Exception, error: 1256 outstr += 'EXTERNAL:\nVariable %s is not a external variable\n' % args[1] 1257 break 1258 else: 1259 outstr += 'EXTERNAL:\n' 1260 outstr += misc.nice_representation(var, nb_space=4) 1261 else: 1262 var = eval(args[1]) 1263 outstr += 'EXTERNAL:\n' 1264 outstr += misc.nice_representation(var, nb_space=4) 1265 1266 pydoc.pager(outstr)
1267 1268
1269 - def do_save(self, line, check=True):
1270 """Save the configuration file""" 1271 1272 args = self.split_arg(line) 1273 # Check argument validity 1274 if check: 1275 Cmd.check_save(self, args) 1276 1277 # find base file for the configuration 1278 if'HOME' in os.environ and os.environ['HOME'] and \ 1279 os.path.exists(pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt')): 1280 base = pjoin(os.environ['HOME'], '.mg5', 'mg5_configuration.txt') 1281 if hasattr(self, 'me_dir'): 1282 basedir = self.me_dir 1283 elif not MADEVENT: 1284 basedir = MG5DIR 1285 else: 1286 basedir = os.getcwd() 1287 elif MADEVENT: 1288 # launch via ./bin/madevent 1289 for config_file in ['me5_configuration.txt', 'amcatnlo_configuration.txt']: 1290 if os.path.exists(pjoin(self.me_dir, 'Cards', config_file)): 1291 base = pjoin(self.me_dir, 'Cards', config_file) 1292 basedir = self.me_dir 1293 else: 1294 if hasattr(self, 'me_dir'): 1295 base = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt') 1296 if len(args) == 0 and os.path.exists(base): 1297 self.write_configuration(base, base, self.me_dir) 1298 base = pjoin(MG5DIR, 'input', 'mg5_configuration.txt') 1299 basedir = MG5DIR 1300 1301 if len(args) == 0: 1302 args.append(base) 1303 self.write_configuration(args[0], base, basedir, self.options)
1304
1305 - def write_configuration(self, filepath, basefile, basedir, to_keep):
1306 """Write the configuration file""" 1307 # We use the default configuration file as a template. 1308 # to ensure that all configuration information are written we 1309 # keep track of all key that we need to write. 1310 1311 logger.info('save configuration file to %s' % filepath) 1312 to_write = to_keep.keys() 1313 text = "" 1314 # Use local configuration => Need to update the path 1315 for line in file(basefile): 1316 if '=' in line: 1317 data, value = line.split('=',1) 1318 else: 1319 text += line 1320 continue 1321 data = data.strip() 1322 if data.startswith('#'): 1323 key = data[1:].strip() 1324 else: 1325 key = data 1326 if '#' in value: 1327 value, comment = value.split('#',1) 1328 else: 1329 comment = '' 1330 if key in to_keep: 1331 value = str(to_keep[key]) 1332 else: 1333 text += line 1334 continue 1335 try: 1336 to_write.remove(key) 1337 except Exception: 1338 pass 1339 if '_path' in key: 1340 # special case need to update path 1341 # check if absolute path 1342 if not os.path.isabs(value): 1343 value = os.path.realpath(os.path.join(basedir, value)) 1344 text += '%s = %s # %s \n' % (key, value, comment) 1345 for key in to_write: 1346 if key in to_keep: 1347 text += '%s = %s \n' % (key, to_keep[key]) 1348 1349 if not MADEVENT: 1350 text += """\n# MG5 MAIN DIRECTORY\n""" 1351 text += "mg5_path = %s\n" % MG5DIR 1352 1353 writer = open(filepath,'w') 1354 writer.write(text) 1355 writer.close()
1356
1357 1358 1359 1360 -class CmdShell(Cmd):
1361 """CMD command with shell activate""" 1362 1363 # Access to shell
1364 - def do_shell(self, line):
1365 "Run a shell command" 1366 1367 if line.strip() is '': 1368 self.help_shell() 1369 else: 1370 logging.info("running shell command: " + line) 1371 subprocess.call(line, shell=True)
1372
1373 - def complete_shell(self, text, line, begidx, endidx):
1374 """ add path for shell """ 1375 1376 # Filename if directory is given 1377 # 1378 if len(self.split_arg(line[0:begidx])) > 1 and line[begidx - 1] == os.path.sep: 1379 if not text: 1380 text = '' 1381 output = self.path_completion(text, 1382 base_dir=\ 1383 self.split_arg(line[0:begidx])[-1]) 1384 else: 1385 output = self.path_completion(text) 1386 return output
1387
1388 - def help_shell(self):
1389 """help for the shell""" 1390 logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE') 1391 logger.info("syntax: shell CMD (or ! CMD)",'$MG:color:BLACK')
1392
1393 1394 1395 1396 #=============================================================================== 1397 # Question with auto-completion 1398 #=============================================================================== 1399 -class SmartQuestion(BasicCmd):
1400 """ a class for answering a question with the path autocompletion""" 1401
1402 - def preloop(self):
1403 """Initializing before starting the main loop""" 1404 self.prompt = '>' 1405 self.value = None 1406 BasicCmd.preloop(self)
1407 1408
1409 - def __init__(self, question, allow_arg=[], default=None, 1410 mother_interface=None, *arg, **opt):
1411 self.question = question 1412 self.wrong_answer = 0 # forbids infinite loop 1413 self.allow_arg = [str(a) for a in allow_arg] 1414 self.history_header = '' 1415 self.default_value = str(default) 1416 self.mother_interface = mother_interface 1417 cmd.Cmd.__init__(self, *arg, **opt)
1418
1419 - def __call__(self, question, reprint_opt=True, **opts):
1420 1421 self.question = question 1422 for key,value in opts: 1423 setattr(self, key, value) 1424 if reprint_opt: 1425 print question 1426 return self.cmdloop()
1427 1428
1429 - def completenames(self, text, line, *ignored):
1430 prev_timer = signal.alarm(0) # avoid timer if any 1431 if prev_timer: 1432 nb_back = len(line) 1433 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 1434 self.stdout.write(line) 1435 self.stdout.flush() 1436 try: 1437 out = {} 1438 out[' Options'] = Cmd.list_completion(text, self.allow_arg) 1439 out[' Recognized command'] = BasicCmd.completenames(self, text) 1440 1441 return self.deal_multiple_categories(out) 1442 except Exception, error: 1443 print error
1444
1445 - def get_names(self):
1446 # This method used to pull in base class attributes 1447 # at a time dir() didn't do it yet. 1448 return dir(self)
1449
1450 - def onecmd(self, line, **opt):
1451 """catch all error and stop properly command accordingly 1452 Interpret the argument as though it had been typed in response 1453 to the prompt. 1454 1455 The return value is a flag indicating whether interpretation of 1456 commands by the interpreter should stop. 1457 1458 This allow to pass extra argument for internal call. 1459 """ 1460 try: 1461 if '~/' in line and os.environ.has_key('HOME'): 1462 line = line.replace('~/', '%s/' % os.environ['HOME']) 1463 line = os.path.expandvars(line) 1464 cmd, arg, line = self.parseline(line) 1465 if not line: 1466 return self.emptyline() 1467 if cmd is None: 1468 return self.default(line) 1469 self.lastcmd = line 1470 if cmd == '': 1471 return self.default(line) 1472 else: 1473 try: 1474 func = getattr(self, 'do_' + cmd) 1475 except AttributeError: 1476 return self.default(line) 1477 return func(arg, **opt) 1478 except Exception as error: 1479 logger.warning(error)
1480
1481 - def reask(self, reprint_opt=True):
1482 pat = re.compile('\[(\d*)s to answer\]') 1483 prev_timer = signal.alarm(0) # avoid timer if any 1484 1485 if prev_timer: 1486 if pat.search(self.question): 1487 timeout = int(pat.search(self.question).groups()[0]) 1488 else: 1489 timeout=20 1490 print 1491 signal.alarm(timeout) 1492 if reprint_opt: 1493 if not prev_timer: 1494 self.question = pat.sub('',self.question) 1495 print self.question 1496 return False
1497
1498 - def default(self, line):
1499 """Default action if line is not recognized""" 1500 1501 if line.strip() == '' and self.default_value is not None: 1502 self.value = self.default_value 1503 else: 1504 self.value = line
1505
1506 - def emptyline(self):
1507 """If empty line, return default""" 1508 1509 if self.default_value is not None: 1510 self.value = self.default_value
1511 1512
1513 - def postcmd(self, stop, line):
1514 1515 try: 1516 if self.value in self.allow_arg: 1517 return True 1518 elif str(self.value) == 'EOF': 1519 self.value = self.default_value 1520 return True 1521 elif line and hasattr(self, 'do_%s' % line.split()[0]): 1522 return self.reask() 1523 elif self.value == 'repeat': 1524 return self.reask() 1525 elif len(self.allow_arg)==0: 1526 return True 1527 else: 1528 raise Exception 1529 except Exception,error: 1530 if self.wrong_answer < 100: 1531 self.wrong_answer += 1 1532 logger.warning("""%s not valid argument. Valid argument are in (%s).""" \ 1533 % (self.value,','.join(self.allow_arg))) 1534 logger.warning('please retry') 1535 return False 1536 else: 1537 self.value = self.default_value 1538 return True
1539
1540 - def cmdloop(self, intro=None):
1541 cmd.Cmd.cmdloop(self, intro) 1542 return self.value
1543
1544 # a function helper 1545 -def smart_input(input_text, allow_arg=[], default=None):
1546 print input_text 1547 obj = SmartQuestion(allow_arg=allow_arg, default=default) 1548 return obj.cmdloop()
1549
1550 #=============================================================================== 1551 # Question in order to return a path with auto-completion 1552 #=============================================================================== 1553 -class OneLinePathCompletion(SmartQuestion):
1554 """ a class for answering a question with the path autocompletion""" 1555 1556 completion_prefix='' 1557
1558 - def completenames(self, text, line, begidx, endidx):
1559 prev_timer = signal.alarm(0) # avoid timer if any 1560 if prev_timer: 1561 nb_back = len(line) 1562 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 1563 self.stdout.write(line) 1564 self.stdout.flush() 1565 1566 try: 1567 out = {} 1568 out[' Options'] = Cmd.list_completion(text, self.allow_arg) 1569 out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False) 1570 out[' Recognized command'] = BasicCmd.completenames(self, text) 1571 1572 return self.deal_multiple_categories(out) 1573 except Exception, error: 1574 print error
1575
1576 - def precmd(self, *args):
1577 """ """ 1578 1579 signal.alarm(0) 1580 return SmartQuestion.precmd(self, *args)
1581
1582 - def completedefault(self,text, line, begidx, endidx):
1583 prev_timer = signal.alarm(0) # avoid timer if any 1584 if prev_timer: 1585 nb_back = len(line) 1586 self.stdout.write('\b'*nb_back + '[timer stopped]\n') 1587 self.stdout.write(line) 1588 self.stdout.flush() 1589 try: 1590 args = Cmd.split_arg(line[0:begidx]) 1591 except Exception, error: 1592 print error 1593 1594 # Directory continuation 1595 if args[-1].endswith(os.path.sep): 1596 1597 return Cmd.path_completion(text, 1598 os.path.join('.',*[a for a in args \ 1599 if a.endswith(os.path.sep)])) 1600 self.completenames(line+text)
1601 1602
1603 - def postcmd(self, stop, line):
1604 try: 1605 if self.value in self.allow_arg: 1606 return True 1607 elif self.value and os.path.isfile(self.value): 1608 return os.path.relpath(self.value) 1609 elif self.value and str(self.value) == 'EOF': 1610 self.value = self.default_value 1611 return True 1612 elif line and hasattr(self, 'do_%s' % line.split()[0]): 1613 # go to retry 1614 reprint_opt = True 1615 elif self.value == 'repeat': 1616 reprint_opt = True 1617 else: 1618 raise Exception 1619 except Exception, error: 1620 print """not valid argument. Valid argument are file path or value in (%s).""" \ 1621 % ','.join(self.allow_arg) 1622 print 'please retry' 1623 reprint_opt = False 1624 1625 return self.reask(reprint_opt)
1626
1627 1628 # a function helper 1629 -def raw_path_input(input_text, allow_arg=[], default=None):
1630 print input_text 1631 obj = OneLinePathCompletion(allow_arg=allow_arg, default=default ) 1632 return obj.cmdloop()
1633
1634 #=============================================================================== 1635 # 1636 #=============================================================================== 1637 -class CmdFile(file):
1638 """ a class for command input file -in order to debug cmd \n problem""" 1639
1640 - def __init__(self, name, opt='rU'):
1641 1642 file.__init__(self, name, opt) 1643 self.text = file.read(self) 1644 self.close() 1645 self.lines = self.text.split('\n')
1646
1647 - def readline(self, *arg, **opt):
1648 """readline method treating correctly a line whithout \n at the end 1649 (add it) 1650 """ 1651 if self.lines: 1652 line = self.lines.pop(0) 1653 else: 1654 return '' 1655 1656 if line.endswith('\n'): 1657 return line 1658 else: 1659 return line + '\n'
1660
1661 - def __next__(self):
1662 return self.lines.__next__()
1663
1664 - def __iter__(self):
1665 return self.lines.__iter__()
1666