~maddevelopers/mg5amcnlo/2.9.4

« back to all changes in this revision

Viewing changes to madgraph/interface/extended_cmd.py

pass to v2.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
################################################################################
2
2
#
3
 
# Copyright (c) 2011 The MadGraph Development team and Contributors
 
3
# Copyright (c) 2011 The MadGraph5_aMC@NLO Development team and Contributors
4
4
#
5
 
# This file is a part of the MadGraph 5 project, an application which 
 
5
# This file is a part of the MadGraph5_aMC@NLO project, an application which 
6
6
# automatically generates Feynman diagrams and matrix elements for arbitrary
7
7
# high-energy processes in the Standard Model and beyond.
8
8
#
9
 
# It is subject to the MadGraph license which should accompany this 
 
9
# It is subject to the MadGraph5_aMC@NLO license which should accompany this 
10
10
# distribution.
11
11
#
12
 
# For more information, please visit: http://madgraph.phys.ucl.ac.be
 
12
# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
13
13
#
14
14
################################################################################
15
15
"""  A file containing different extension of the cmd basic python library"""
39
39
    import madgraph.various.misc as misc
40
40
    from madgraph import MG5DIR
41
41
    MADEVENT = False
42
 
except Exception, error:
43
 
    if __debug__:
44
 
       logger.info('extended_cmd:'+str(error))
45
 
    import internal.misc as misc
 
42
except ImportError, error:
 
43
    try:
 
44
        import internal.misc as misc
 
45
    except:
 
46
        raise error
46
47
    MADEVENT = True
47
48
 
48
49
pjoin = os.path.join
161
162
                import fcntl, termios, struct
162
163
                cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
163
164
                                                     '1234'))
164
 
            except:
 
165
            except Exception:
165
166
                return None
166
167
            return cr
167
168
        cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
170
171
                fd = os.open(os.ctermid(), os.O_RDONLY)
171
172
                cr = ioctl_GWINSZ(fd)
172
173
                os.close(fd)
173
 
            except:
 
174
            except Exception:
174
175
                pass
175
176
        if not cr:
176
177
            try:
177
178
                cr = (os.environ['LINES'], os.environ['COLUMNS'])
178
 
            except:
 
179
            except Exception:
179
180
                cr = (25, 80)
180
181
        return int(cr[1])
181
182
    
184
185
         If a command has not been entered, then complete against command list.
185
186
         Otherwise try to call complete_<command> to get list of completions.
186
187
        """
187
 
                
 
188
 
188
189
        if state == 0:
189
190
            import readline
190
191
            origline = readline.get_line_buffer()
236
237
            else:
237
238
                self.completion_prefix = ''
238
239
                self.completion_matches = compfunc(text, line, begidx, endidx)
239
 
        #print self.completion_matches
240
240
 
241
 
        self.completion_matches = [ (l[-1] in [' ','@','=',os.path.sep] 
242
 
                      and l or (l+' ')) for l in self.completion_matches if l]
 
241
        self.completion_matches = [ l if l[-1] in [' ','@','=',os.path.sep]
 
242
                                    else ((l + ' ') if not l.endswith('\\$') else l[:-2])
 
243
                                  for l in self.completion_matches if l] 
243
244
        
244
245
        try:
245
246
            return self.completion_matches[state]
246
247
        except IndexError, error:
247
 
            #if __debug__:
 
248
            # if __debug__:
248
249
            #    logger.error('\n Completion ERROR:')
249
250
            #    logger.error( error)
250
251
            return None    
373
374
    """Extension of the cmd object for only the help command"""
374
375
 
375
376
    def help_quit(self):
376
 
        logger.info("syntax: quit")
377
 
        logger.info("-- terminates the application")
 
377
        logger.info("-- terminates the application",'$MG:color:BLUE')
 
378
        logger.info("syntax: quit",'$MG:color:BLACK')
378
379
    
379
380
    help_EOF = help_quit
380
381
 
381
382
    def help_history(self):
382
 
        logger.info("syntax: history [FILEPATH|clean|.] ")
383
 
        logger.info("   If FILEPATH is \'.\' and \'output\' is done,")
 
383
        logger.info("-- interact with the command history.",'$MG:color:BLUE')
 
384
        logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:color:BLACK')
 
385
        logger.info(" > If FILEPATH is \'.\' and \'output\' is done,")
384
386
        logger.info("   Cards/proc_card_mg5.dat will be used.")
385
 
        logger.info("   If FILEPATH is omitted, the history will be output to stdout.")
 
387
        logger.info(" > If FILEPATH is omitted, the history will be output to stdout.")
386
388
        logger.info("   \"clean\" will remove all entries from the history.")
387
389
        
388
390
    def help_help(self):
389
 
        logger.info("syntax: help")
390
 
        logger.info("-- access to the in-line help" )
 
391
        logger.info("-- access to the in-line help",'$MG:color:BLUE')
 
392
        logger.info("syntax: help",'$MG:color:BLACK')
391
393
 
392
394
    def help_save(self):
393
395
        """help text for save"""
394
 
        logger.info("syntax: save [options]  [FILEPATH]") 
395
 
        logger.info("-- save options configuration to filepath.")
 
396
        logger.info("-- save options configuration to filepath.",'$MG:color:BLUE')
 
397
        logger.info("syntax: save [options]  [FILEPATH]",'$MG:color:BLACK') 
396
398
        
397
399
    def help_display(self):
398
400
        """help for display command"""
399
 
        logger.info("syntax: display " + "|".join(self._display_opts))
400
 
        logger.info("-- display a the status of various internal state variables")          
 
401
        logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE')          
 
402
        logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLACK')
401
403
        
402
404
class CompleteCmd(object):
403
405
    """Extension of the cmd object for only the complete command"""
452
454
    history_header = ""
453
455
    
454
456
    _display_opts = ['options','variable']
455
 
    helporder = ['Documented commands']
456
457
    
457
458
    class InvalidCmd(Exception):
458
459
        """expected error for wrong command"""
462
463
 
463
464
    debug_output = 'debug'
464
465
    error_debug = """Please report this bug to developers\n
465
 
           More information is found in '%s'.\n
 
466
           More information is found in '%(debug)s'.\n
466
467
           Please attach this file to your report."""
467
468
    config_debug = error_debug
468
469
           
484
485
        self.haspiping = not sys.stdin.isatty() # check if mg5 is piped 
485
486
        self.stored_line = '' # for be able to treat answer to question in input file 
486
487
                              # answer which are not required.
487
 
 
 
488
        if not hasattr(self, 'helporder'):
 
489
            self.helporder = ['Documented commands']
488
490
        
489
491
        
490
492
    def precmd(self, line):
496
498
            return line
497
499
        line = line.lstrip()
498
500
 
499
 
        # Update the history of this suite of command,
500
 
        # except for useless commands (empty history and help calls)
501
 
        if ';' in line: 
502
 
            lines = line.split(';')
503
 
        else:
504
 
            lines = [line]
505
 
        for l in lines:
506
 
            l = l.strip()
507
 
            if not (l.startswith("history") or l.startswith('help') or \
508
 
                                                            l.startswith('#*')):
509
 
                self.history.append(l)
510
 
 
511
501
        # Check if we are continuing a line:
512
502
        if self.save_line:
513
503
            line = self.save_line + line 
517
507
        if line.endswith('\\'):
518
508
            self.save_line = line[:-1]
519
509
            return '' # do nothing   
520
 
        
 
510
                
521
511
        # Remove comment
522
512
        if '#' in line:
523
513
            line = line.split('#')[0]
524
514
 
525
515
        # Deal with line splitting
526
 
        if ';' in line and not (line.startswith('!') or line.startswith('shell')):
527
 
            for subline in line.split(';'):
 
516
        if ';' in line: 
 
517
            lines = line.split(';')
 
518
            for subline in lines:
 
519
                if not (subline.startswith("history") or subline.startswith('help') \
 
520
                        or subline.startswith('#*')): 
 
521
                    self.history.append(subline)           
528
522
                stop = self.onecmd(subline)
529
523
                stop = self.postcmd(stop, subline)
530
524
            return ''
531
 
        
 
525
            
532
526
        # execute the line command
 
527
        self.history.append(line) 
533
528
        return line
534
529
 
535
530
    def postcmd(self,stop, line):
569
564
    # Ask a question with nice options handling
570
565
    #===============================================================================    
571
566
    def ask(self, question, default, choices=[], path_msg=None, 
572
 
            timeout = True, fct_timeout=None, ask_class=None):
 
567
            timeout = True, fct_timeout=None, ask_class=None, alias={},**opt):
573
568
        """ ask a question with some pre-define possibility
574
569
            path info is
575
570
        """
581
576
        if timeout:
582
577
            try:
583
578
                timeout = self.options['timeout']
584
 
            except:
 
579
            except Exception:
585
580
                pass
586
581
                    
587
582
        # add choice info to the question
597
592
            if len(choices) > 9:
598
593
                question += '... , ' 
599
594
            question = question[:-2]+']'
 
595
        else:
 
596
            question += "[\033[%dm%s\033[0m] " % (4, default)    
600
597
        if ask_class:
601
598
            obj = ask_class  
602
599
        elif path_msg:
604
601
        else:
605
602
            obj = SmartQuestion
606
603
 
607
 
        question_instance = obj(allow_arg=choices, default=default, 
608
 
                                                          mother_interface=self)
609
 
        question_instance.question = question
 
604
        if alias:
 
605
            choices += alias.keys()
 
606
        
 
607
        question_instance = obj(question, allow_arg=choices, default=default, 
 
608
                                                   mother_interface=self, **opt)
610
609
 
611
610
        answer = self.check_answer_in_input_file(question_instance, default, path_msg)
612
611
        if answer is not None:
 
612
            if answer in alias:
 
613
                answer = alias[answer]
 
614
            if ask_class:
 
615
                answer = question_instance.default(answer)
613
616
            return answer
614
617
        
 
618
        question = question_instance.question
615
619
        value =   Cmd.timed_input(question, default, timeout=timeout,
616
620
                                 fct=question_instance, fct_timeout=fct_timeout)
617
 
 
 
621
        
 
622
        try:
 
623
            if value in alias:
 
624
                value = alias[value]
 
625
        except TypeError:
 
626
            pass
 
627
        if value == default and ask_class:
 
628
            value = question_instance.default(default)
618
629
        return value
619
630
 
620
631
    
704
715
            cmd.Cmd.onecmd(self, 'history %s' % self.debug_output.replace(' ', '\ '))
705
716
        except Exception, error:
706
717
           logger.error(error)
707
 
            
 
718
 
708
719
        debug_file = open(self.debug_output, 'a')
709
720
        traceback.print_exc(file=debug_file)
710
721
        # Create a nice error output
717
728
            error_text = ''
718
729
        error_text += '%s : %s\n' % (error.__class__.__name__, 
719
730
                                            str(error).replace('\n','\n\t'))
720
 
        error_text += self.error_debug % {'debug': self.debug_output}
 
731
        error_text += self.error_debug % {'debug':self.debug_output}
721
732
        logger_stderr.critical(error_text)
 
733
        
722
734
                
723
735
        # Add options status to the debug file
724
736
        try:
726
738
        except Exception, error:
727
739
            debug_file.write('Fail to write options with error %s' % error)
728
740
        
729
 
 
 
741
        #add the cards:
 
742
        for card in ['proc_card_mg5.dat','param_card.dat', 'run_card.dat']:
 
743
            try:
 
744
                ff = open(pjoin(self.me_dir, 'Cards', card))
 
745
                debug_file.write(ff.read())
 
746
                ff.close()
 
747
            except Exception:
 
748
                pass
 
749
            
730
750
        #stop the execution if on a non interactive mode
731
751
        if self.use_rawinput == False:
732
752
            return True 
733
753
        return False
734
754
 
 
755
 
 
756
 
735
757
    def nice_user_error(self, error, line):
736
758
        if self.child:
737
759
            return self.child.nice_user_error(error, line)
844
866
        """for third party call, call the line with pre and postfix treatment
845
867
        without global error handling """
846
868
 
847
 
        if printcmd:
 
869
        if printcmd and not line.startswith('#'):
848
870
            logger.info(line)
849
871
        if self.child:
850
872
            current_interface = self.child
877
899
        # Faulty command
878
900
        logger.warning("Command \"%s\" not recognized, please try again" % \
879
901
                                                                line.split()[0])
880
 
        self.history.pop()
 
902
        if line.strip() in ['q', '.q', 'stop']:
 
903
            logger.info("If you want to quit mg5 please type \"exit\".")
 
904
 
 
905
        if self.history and self.history[-1] == line:        
 
906
            self.history.pop()
881
907
        
882
908
 
883
909
 
942
968
                new_history.append(cur_line)
943
969
            
944
970
        new_history.reverse()
945
 
        self.history = new_history
946
 
        
947
 
        
948
 
    def clean_history(self, to_keep=['set','add','load'],
949
 
                            remove_bef_last=None,
950
 
                            to_remove=['open','display','launch', 'check'],
951
 
                            allow_for_removal=None,
952
 
                            keep_switch=False):
953
 
        """Remove command in arguments from history.
954
 
        All command before the last occurrence of  'remove_bef_last'
955
 
        (including it) will be removed (but if another options tells the opposite).                
956
 
        'to_keep' is a set of line to always keep.
957
 
        'to_remove' is a set of line to always remove (don't care about remove_bef_ 
958
 
        status but keep_switch acts.).
959
 
        if 'allow_for_removal' is define only the command in that list can be 
960
 
        remove of the history for older command that remove_bef_lb1. all parameter
961
 
        present in to_remove are always remove even if they are not part of this 
962
 
        list.
963
 
        keep_switch force to keep the statement remove_bef_??? which changes starts
964
 
        the removal mode.
965
 
        """
966
 
        
967
 
        #check consistency
968
 
        if __debug__ and allow_for_removal:
969
 
            for arg in to_keep:
970
 
                assert arg not in allow_for_removal
971
 
            
972
 
    
973
 
        nline = -1
974
 
        removal = False
975
 
        #looping backward
976
 
        while nline > -len(self.history):
977
 
            switch  = False # set in True when removal pass in True
978
 
 
979
 
            #check if we need to pass in removal mode
980
 
            if not removal and remove_bef_last:
981
 
                    if self.history[nline].startswith(remove_bef_last):
982
 
                        removal = True
983
 
                        switch = True  
984
 
 
985
 
            # if this is the switch and is protected pass to the next element
986
 
            if switch and keep_switch:
987
 
                nline -= 1
988
 
                continue
989
 
 
990
 
            # remove command in to_remove (whatever the status of removal)
991
 
            if any([self.history[nline].startswith(arg) for arg in to_remove]):
992
 
                self.history.pop(nline)
993
 
                continue
994
 
            
995
 
            # Only if removal mode is active!
996
 
            if removal:
997
 
                if allow_for_removal:
998
 
                    # Only a subset of command can be removed
999
 
                    if any([self.history[nline].startswith(arg) 
1000
 
                                                 for arg in allow_for_removal]):
1001
 
                        self.history.pop(nline)
1002
 
                        continue
1003
 
                elif not any([self.history[nline].startswith(arg) for arg in to_keep]):
1004
 
                    # All command have to be remove but protected
1005
 
                    self.history.pop(nline)
1006
 
                    continue
1007
 
            
1008
 
            # update the counter to pass to the next element
1009
 
            nline -= 1
1010
 
                
 
971
        self.history[:] = new_history
 
972
        
 
973
                        
1011
974
    def import_command_file(self, filepath):
1012
975
        # remove this call from history
1013
976
        if self.history:
1014
977
            self.history.pop()
1015
978
        
1016
979
        # Read the lines of the file and execute them
1017
 
        commandline = open(filepath).readlines()
 
980
        if isinstance(filepath, str):
 
981
            commandline = open(filepath).readlines()
 
982
        else:
 
983
            commandline = filepath
1018
984
        oldinputfile = self.inputfile
1019
985
        oldraw = self.use_rawinput
1020
986
        self.inputfile = (l for l in commandline) # make a generator
1101
1067
 
1102
1068
    # Quit
1103
1069
    def do_quit(self, line):
1104
 
        """ exit the mainloop() """
 
1070
        """Not in help: exit the mainloop() """
1105
1071
        
1106
1072
        if self.child:
1107
1073
            self.child.exec_cmd('quit ' + line, printcmd=False)
1114
1080
                level = int(line) - 1
1115
1081
                if level:
1116
1082
                    self.mother.lastcmd = 'quit %s' % level
1117
 
 
 
1083
        logger.info(' ')
1118
1084
        return True
1119
1085
 
1120
1086
    # Aliases
1142
1108
                cmdname=name[3:]
1143
1109
                try:
1144
1110
                    doc = getattr(self.cmd, name).__doc__
1145
 
                except:
 
1111
                except Exception:
1146
1112
                    doc = None
1147
1113
                if not doc:
1148
1114
                    doc = getattr(self, name).__doc__
1155
1121
                if tag in cmds:
1156
1122
                    cmds[tag].append(cmdname)
1157
1123
                else:
1158
 
                    cmds[tag] = [cmdname]
1159
 
                
1160
 
 
 
1124
                    cmds[tag] = [cmdname] 
 
1125
                    
1161
1126
        self.stdout.write("%s\n"%str(self.doc_leader))
1162
1127
        for tag in self.helporder:
 
1128
            if tag not in cmds:
 
1129
                continue
1163
1130
            header = "%s (type help <topic>):" % tag
1164
1131
            self.print_topics(header, cmds[tag],   15,80)
1165
1132
        for name, item in cmds.items():
1198
1165
            options = self.next_possibility[last_action_2]
1199
1166
        elif last_action in authorize:
1200
1167
            options = self.next_possibility[last_action]
1201
 
        
 
1168
        else:
 
1169
            return
1202
1170
        text = 'The following command(s) may be useful in order to continue.\n'
1203
1171
        for option in options:
1204
1172
            text+='\t %s \n' % option      
1224
1192
            outstr = "Value of Internal Variable:\n"
1225
1193
            try:
1226
1194
                var = eval(args[1])
1227
 
            except:
 
1195
            except Exception:
1228
1196
                outstr += 'GLOBAL:\nVariable %s is not a global variable\n' % args[1]
1229
1197
            else:
1230
1198
                outstr += 'GLOBAL:\n' 
1232
1200
               
1233
1201
            try:
1234
1202
                var = eval('self.%s' % args[1])
1235
 
            except:
 
1203
            except Exception:
1236
1204
                outstr += 'LOCAL:\nVariable %s is not a local variable\n' % args[1]
1237
1205
            else:
1238
1206
                outstr += 'LOCAL:\n'
1291
1259
            
1292
1260
        if len(args) == 0:
1293
1261
            args.append(base)
1294
 
        self.write_configuration(args[0], base, basedir)
 
1262
        self.write_configuration(args[0], base, basedir, self.options)
1295
1263
        
1296
1264
    def write_configuration(self, filepath, basefile, basedir, to_keep):
1297
1265
        """Write the configuration file"""
1318
1286
                value, comment = value.split('#',1)
1319
1287
            else:
1320
1288
                comment = ''    
1321
 
            
1322
1289
            if key in to_keep:
1323
1290
                value = str(to_keep[key])
1324
1291
            else:
1326
1293
                continue
1327
1294
            try:
1328
1295
                to_write.remove(key)
1329
 
            except:
 
1296
            except Exception:
1330
1297
                pass
1331
1298
            if '_path' in key:       
1332
1299
                # special case need to update path
1379
1346
 
1380
1347
    def help_shell(self):
1381
1348
        """help for the shell"""
1382
 
        
1383
 
        logger.info("syntax: shell CMD (or ! CMD)")
1384
 
        logger.info("-- run the shell command CMD and catch output")
 
1349
        logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')        
 
1350
        logger.info("syntax: shell CMD (or ! CMD)",'$MG:color:BLACK')
1385
1351
 
1386
1352
 
1387
1353
 
1399
1365
        BasicCmd.preloop(self)
1400
1366
        
1401
1367
 
1402
 
    def __init__(self,  allow_arg=[], default=None, mother_interface=None, 
1403
 
                                                                   *arg, **opt):
 
1368
    def __init__(self, question, allow_arg=[], default=None, 
 
1369
                                            mother_interface=None, *arg, **opt):
 
1370
        self.question = question
1404
1371
        self.wrong_answer = 0 # forbids infinite loop
1405
1372
        self.allow_arg = [str(a) for a in allow_arg]
1406
1373
        self.history_header = ''
1426
1393
            self.stdout.write(line)
1427
1394
            self.stdout.flush()
1428
1395
        try:
1429
 
            return Cmd.list_completion(text, self.allow_arg)
 
1396
            out = {}
 
1397
            out[' Options'] = Cmd.list_completion(text, self.allow_arg)
 
1398
            out[' Recognized command'] = BasicCmd.completenames(self, text)
 
1399
            
 
1400
            return self.deal_multiple_categories(out)
1430
1401
        except Exception, error:
1431
1402
            print error
1432
1403
            
 
1404
            
1433
1405
    def reask(self, reprint_opt=True):
1434
1406
        pat = re.compile('\[(\d*)s to answer\]')
1435
1407
        prev_timer = signal.alarm(0) # avoid timer if any
1461
1433
        if self.default_value is not None:
1462
1434
            self.value = self.default_value
1463
1435
 
 
1436
 
1464
1437
    def postcmd(self, stop, line):
1465
1438
        
1466
1439
        try:    
1471
1444
                return True
1472
1445
            elif line and hasattr(self, 'do_%s' % line.split()[0]):
1473
1446
                return self.reask()
 
1447
            elif self.value == 'repeat':
 
1448
                return self.reask()
 
1449
            elif len(self.allow_arg)==0:
 
1450
                return True
1474
1451
            else: 
1475
1452
                raise Exception
1476
 
        except Exception:
 
1453
        except Exception,error:
1477
1454
            if self.wrong_answer < 100:
1478
1455
                self.wrong_answer += 1
1479
 
                print """%s not valid argument. Valid argument are in (%s).""" \
1480
 
                          % (self.value,','.join(self.allow_arg))
1481
 
                print 'please retry'
 
1456
                logger.warning("""%s not valid argument. Valid argument are in (%s).""" \
 
1457
                          % (self.value,','.join(self.allow_arg)))
 
1458
                logger.warning('please retry')
1482
1459
                return False
1483
1460
            else:
1484
1461
                self.value = self.default_value
1500
1477
class OneLinePathCompletion(SmartQuestion):
1501
1478
    """ a class for answering a question with the path autocompletion"""
1502
1479
    
 
1480
    completion_prefix=''
1503
1481
 
1504
1482
    def completenames(self, text, line, begidx, endidx):
1505
1483
        prev_timer = signal.alarm(0) # avoid timer if any
1510
1488
            self.stdout.flush()
1511
1489
        try:
1512
1490
            out = {}
1513
 
            out[' Options'] = SmartQuestion.completenames(self, text, line)
 
1491
            out[' Options'] = Cmd.list_completion(text, self.allow_arg)
1514
1492
            out[' Path from ./'] = Cmd.path_completion(text, only_dirs = False)
1515
1493
            out[' Recognized command'] = BasicCmd.completenames(self, text)
1516
1494
            
1517
1495
            return self.deal_multiple_categories(out)
1518
1496
        except Exception, error:
1519
1497
            print error
1520
 
 
 
1498
            
 
1499
    def precmd(self, *args):
 
1500
        """ """
 
1501
        
 
1502
        signal.alarm(0)
 
1503
        return SmartQuestion.precmd(self, *args)
 
1504
        
1521
1505
    def completedefault(self,text, line, begidx, endidx):
1522
1506
        prev_timer = signal.alarm(0) # avoid timer if any
1523
1507
        if prev_timer:
1550
1534
                return True
1551
1535
            elif line and hasattr(self, 'do_%s' % line.split()[0]):
1552
1536
                # go to retry
1553
 
                reprint_opt = True          
 
1537
                reprint_opt = True 
 
1538
            elif self.value == 'repeat':
 
1539
                reprint_opt = True         
1554
1540
            else:
1555
1541
                raise Exception
1556
1542
        except Exception, error: