~maddevelopers/mg5amcnlo/2.6.3_rwgt

« back to all changes in this revision

Viewing changes to madgraph/interface/extended_cmd.py

  • Committer: olivier-mattelaer
  • Date: 2018-04-29 08:10:16 UTC
  • mfrom: (275.1.80 2.6.2)
  • Revision ID: olivier-mattelaer-20180429081016-9nmfvn1er0zjb23o
pass to 2.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
 
35
35
logger = logging.getLogger('cmdprint') # for stdout
36
36
logger_stderr = logging.getLogger('fatalerror') # for stderr
 
37
logger_tuto = logging.getLogger('tutorial') # for stdout
 
38
logger_plugin = logging.getLogger('tutorial_plugin') # for stdout
37
39
 
38
40
try:
39
41
    import madgraph.various.misc as misc
467
469
            out = []
468
470
            for name, opt in dico.items():
469
471
                out += opt
470
 
            return out
 
472
            return list(set(out))
471
473
 
472
474
        # check if more than one categories but only one value:
473
475
        if not forceCategory and all(len(s) <= 1 for s in dico.values() ):
767
769
 
768
770
    def help_quit(self):
769
771
        logger.info("-- terminates the application",'$MG:color:BLUE')
770
 
        logger.info("syntax: quit",'$MG:color:BLACK')
 
772
        logger.info("syntax: quit",'$MG:BOLD')
771
773
    
772
774
    help_EOF = help_quit
773
775
 
774
776
    def help_history(self):
775
777
        logger.info("-- interact with the command history.",'$MG:color:BLUE')
776
 
        logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:color:BLACK')
 
778
        logger.info("syntax: history [FILEPATH|clean|.] ",'$MG:BOLD')
777
779
        logger.info(" > If FILEPATH is \'.\' and \'output\' is done,")
778
780
        logger.info("   Cards/proc_card_mg5.dat will be used.")
779
781
        logger.info(" > If FILEPATH is omitted, the history will be output to stdout.")
781
783
        
782
784
    def help_help(self):
783
785
        logger.info("-- access to the in-line help",'$MG:color:BLUE')
784
 
        logger.info("syntax: help",'$MG:color:BLACK')
 
786
        logger.info("syntax: help",'$MG:BOLD')
785
787
 
786
788
    def help_save(self):
787
789
        """help text for save"""
788
790
        logger.info("-- save options configuration to filepath.",'$MG:color:BLUE')
789
 
        logger.info("syntax: save [options]  [FILEPATH]",'$MG:color:BLACK') 
 
791
        logger.info("syntax: save [options]  [FILEPATH]",'$MG:BOLD') 
790
792
        
791
793
    def help_display(self):
792
794
        """help for display command"""
793
795
        logger.info("-- display a the status of various internal state variables",'$MG:color:BLUE')          
794
 
        logger.info("syntax: display " + "|".join(self._display_opts),'$MG:color:BLACK')
 
796
        logger.info("syntax: display " + "|".join(self._display_opts),'$MG:BOLD')
795
797
        
796
798
class CompleteCmd(object):
797
799
    """Extension of the cmd object for only the complete command"""
1020
1022
        self.child = obj_instance
1021
1023
        self.child.mother = self
1022
1024
        
 
1025
        
1023
1026
        #ensure that notification are sync:
1024
1027
        self.child.allow_notification_center = self.allow_notification_center
1025
1028
 
1185
1188
                    self.store_line(line)
1186
1189
                    return None # print the question and use the pipe
1187
1190
                logger.info(question_instance.question)
1188
 
                logger.info('The answer to the previous question is not set in your input file', '$MG:color:BLACK')
1189
 
                logger.info('Use %s value' % default, '$MG:color:BLACK')
 
1191
                logger.info('The answer to the previous question is not set in your input file', '$MG:BOLD')
 
1192
                logger.info('Use %s value' % default, '$MG:BOLD')
1190
1193
                return str(default)
1191
1194
            
1192
1195
        line = line.replace('\n','').strip()
1211
1214
            line = os.path.expanduser(os.path.expandvars(line))
1212
1215
            if os.path.isfile(line):
1213
1216
                return line
 
1217
            if line.startswith(('http', 'www')):
 
1218
                return line
1214
1219
        elif hasattr(question_instance, 'casesensitive') and not question_instance.casesensitive:
1215
1220
            for entry in question_instance.allow_arg:
1216
1221
                if line.lower() == entry.lower():
1321
1326
                                                self.options['crash_on_error']:
1322
1327
            logger.info('stop computation due to crash_on_error=True')
1323
1328
            sys.exit(str(error))
 
1329
            
1324
1330
        #stop the execution if on a non interactive mode
1325
 
        if self.use_rawinput == False:
1326
 
            return True 
 
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
        
1327
1341
        return False
1328
1342
 
1329
1343
 
1346
1360
                                                self.options['crash_on_error']:
1347
1361
            logger.info('stop computation due to crash_on_error=True')
1348
1362
            sys.exit(str(error))
 
1363
 
1349
1364
        #stop the execution if on a non interactive mode
1350
 
        if self.use_rawinput == False:
 
1365
        if self.use_rawinput == False or self.inputfile:
1351
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
            
1352
1374
        # Remove failed command from history
1353
1375
        self.history.pop()
1354
1376
        return False
1382
1404
            logger.info('stop computation due to crash_on_error=True')
1383
1405
            sys.exit(str(error))
1384
1406
        
1385
 
        #stop the execution if on a non interactive mode                                
1386
 
        if self.use_rawinput == False:
 
1407
        #stop the execution if on a non interactive mode
 
1408
        if self.use_rawinput == False or self.inputfile:
1387
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
 
1388
1417
        # Remove failed command from history                                            
1389
1418
        if self.history:
1390
1419
            self.history.pop()
1427
1456
            me_dir = os.path.basename(me_dir) + ' '
1428
1457
        
1429
1458
        misc.EasterEgg('error')
1430
 
            
 
1459
        stop=False
1431
1460
        try:
1432
1461
            raise 
1433
 
        except self.InvalidCmd as error:            
 
1462
        except self.InvalidCmd as error:
1434
1463
            if __debug__:
1435
 
                self.nice_error_handling(error, line)
 
1464
                stop = self.nice_error_handling(error, line)
1436
1465
                self.history.pop()
1437
1466
            else:
1438
 
                self.nice_user_error(error, line)
 
1467
                stop = self.nice_user_error(error, line)
 
1468
 
1439
1469
            if self.allow_notification_center:
1440
1470
                misc.apple_notify('Run %sfailed' % me_dir,
1441
1471
                              'Invalid Command: %s' % error.__class__.__name__)
1442
1472
 
1443
1473
        except self.ConfigurationError as error:
1444
 
            self.nice_config_error(error, line)
 
1474
            stop = self.nice_config_error(error, line)
1445
1475
            if self.allow_notification_center:
1446
1476
                misc.apple_notify('Run %sfailed' % me_dir,
1447
1477
                              'Configuration error')
1448
1478
        except Exception as error:
1449
 
            self.nice_error_handling(error, line)
 
1479
            stop = self.nice_error_handling(error, line)
1450
1480
            if self.mother:
1451
1481
                self.do_quit('')
1452
1482
            if self.allow_notification_center:
1457
1487
            if __debug__:
1458
1488
                self.nice_config_error(error, line)
1459
1489
            logger.error(self.keyboard_stop_msg)
 
1490
 
 
1491
        
 
1492
        if stop:
 
1493
            self.do_quit('all')
1460
1494
        
1461
1495
 
1462
1496
 
1705
1739
        elif self.mother:
1706
1740
            self.mother.child = None
1707
1741
            if line == 'all':
 
1742
                self.mother.do_quit('all')
1708
1743
                pass
1709
1744
            elif line:
1710
1745
                level = int(line) - 1
1711
1746
                if level:
1712
1747
                    self.mother.lastcmd = 'quit %s' % level
1713
 
        logger.info(' ')
 
1748
        elif self.inputfile:
 
1749
            for line in self.inputfile:
 
1750
                logger.warning('command not executed: %s' % line.replace('\n','')) 
 
1751
 
1714
1752
        return True
1715
1753
 
1716
1754
    # Aliases
1982
2020
    def help_shell(self):
1983
2021
        """help for the shell"""
1984
2022
        logger.info("-- run the shell command CMD and catch output",'$MG:color:BLUE')        
1985
 
        logger.info("syntax: shell CMD (or ! CMD)",'$MG:color:BLACK')
1986
 
 
1987
 
 
1988
 
 
1989
 
 
 
2023
        logger.info("syntax: shell CMD (or ! CMD)",'$MG:BOLD')
 
2024
 
 
2025
 
 
2026
 
 
2027
class NotValidInput(Exception): pass
1990
2028
#===============================================================================
1991
2029
# Question with auto-completion
1992
2030
#===============================================================================
2006
2044
 
2007
2045
    def __init__(self, question, allow_arg=[], default=None, 
2008
2046
                                            mother_interface=None, *arg, **opt):
 
2047
 
2009
2048
        self.question = question
2010
2049
        self.wrong_answer = 0 # forbids infinite loop
2011
2050
        self.allow_arg = [str(a) for a in allow_arg]
2030
2069
            setattr(self, key, value)
2031
2070
        if reprint_opt:
2032
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')
2033
2074
        return self.cmdloop()
2034
2075
        
2035
2076
 
2100
2141
        if reprint_opt:
2101
2142
            if not prev_timer:
2102
2143
                self.question = pat.sub('',self.question)
2103
 
            print self.question
2104
 
            
 
2144
            print self.question.encode('utf8')
 
2145
 
2105
2146
        if self.mother_interface:
2106
2147
            answer = self.mother_interface.check_answer_in_input_file(self, 'EOF', 
2107
2148
                                                                path=self.allowpath)
2121
2162
        
2122
2163
        if not text:
2123
2164
            if out['Options']:
2124
 
                logger.info( "Here is the list of all valid options:", '$MG:color:BLACK')
 
2165
                logger.info( "Here is the list of all valid options:", '$MG:BOLD')
2125
2166
                logger.info( "  "+  "\n  ".join(out['Options']))
2126
2167
            if out['command']: 
2127
 
                logger.info( "Here is the list of command available:", '$MG:color:BLACK')
 
2168
                logger.info( "Here is the list of command available:", '$MG:BOLD')
2128
2169
                logger.info( "  "+  "\n  ".join(out['command']))
2129
2170
        else:
2130
2171
            if out['Options']:
2131
 
                logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:color:BLACK')
 
2172
                logger.info( "Here is the list of all valid options starting with \'%s\'" % text, '$MG:BOLD')
2132
2173
                logger.info( "  "+  "\n  ".join(out['Options']))
2133
2174
            if out['command']: 
2134
 
                logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:color:BLACK')
 
2175
                logger.info( "Here is the list of command available starting with \'%s\':" % text, '$MG:BOLD')
2135
2176
                logger.info( "  "+  "\n  ".join(out['command']))
2136
2177
            elif not  out['Options']:
2137
 
                logger.info( "No possibility starting with \'%s\'" % text, '$MG:color:BLACK')           
2138
 
        logger.info( "You can type help XXX, to see all command starting with XXX", '$MG:color:BLACK')
 
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')
2139
2180
    def complete_help(self, text, line, begidx, endidx):
2140
2181
        """ """
2141
2182
        return self.completenames(text, line)
2302
2343
       
2303
2344
       Behavior for each switch can be customize via:
2304
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)
2305
2347
       get_allowed_XXXX() -> return list of possible value
2306
2348
       check_value_XXXX(value) -> return True/False if the user can set such value
2307
2349
       switch_off_XXXXX()      -> set it off (called for special mode)
2364
2406
            allowed_args += opts['allow_arg']
2365
2407
            del opts['allow_arg']
2366
2408
 
2367
 
        super(ControlSwitch, self).__init__(question, allowed_args, *args, **opts)
 
2409
        allowed_args +=["0", "done"]
 
2410
        SmartQuestion.__init__(self, question, allowed_args, *args, **opts)
2368
2411
        self.options = self.mother_interface.options
2369
2412
 
2370
2413
    def special_check_answer_in_input_file(self, line, default):
2383
2426
                return str(default) 
2384
2427
            return None
2385
2428
        key, value = line.split('=',1)
2386
 
        if key in self.switch:
 
2429
        if key.lower() in self.switch:
2387
2430
            return line
2388
2431
        if key in [str(i+1) for i in range(len(self.to_control))]:
2389
2432
            self.value='reask'
2402
2445
        
2403
2446
        for key,_ in self.to_control:
2404
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
2405
2451
            if hasattr(self, 'set_default_%s' % key):
2406
2452
                getattr(self, 'set_default_%s' % key)()
2407
2453
            else:
2408
2454
                self.default_switch_for(key)
2409
 
    
 
2455
        
2410
2456
    def default_switch_for(self, key):
2411
2457
        """use this if they are no dedicated function for such key"""
2412
2458
        
2461
2507
            return getattr(self, 'get_allowed_%s' % key)()
2462
2508
        else:
2463
2509
            return ['ON', 'OFF']    
2464
 
        
2465
 
    def default(self, line):
 
2510
            
 
2511
    def default(self, line, raise_error=False):
2466
2512
        """Default action if line is not recognized"""
2467
2513
        
2468
2514
        line=line.strip().replace('@', '__at__')
2474
2520
        
2475
2521
        if '=' in line:
2476
2522
            base, value = line.split('=',1)
 
2523
            base = base.strip()
 
2524
            value = value.strip()
2477
2525
            # allow 1=OFF
2478
2526
            if base.isdigit() :
2479
2527
                try:
2484
2532
            base, value = line.split(' ', 1)
2485
2533
        elif hasattr(self, 'ans_%s' % line.lower()):
2486
2534
            base, value = line.lower(), None
2487
 
        elif line.isdigit() and line in [`i` for i in range(1, len(self.switch)+1)]:
 
2535
        elif line.isdigit() and line in [`i` for i in range(1, len(self.to_control)+1)]:
2488
2536
            # go from one valid option to the next in the get_allowed for that option
2489
2537
            base = self.to_control[int(line)-1][0].lower()
2490
2538
            return self.default(base) # just recall this function with the associate name
2496
2544
            except:
2497
2545
                if self.get_allowed(base):
2498
2546
                    value = self.get_allowed(base)[0]
2499
 
                else:                                            
 
2547
                else:                      
2500
2548
                    logger.warning('Can not switch "%s" to another value via number', base)
2501
2549
                    self.value='reask'
2502
2550
                    return
2511
2559
        elif line in 'auto':
2512
2560
            self.switch['dynamical'] = True
2513
2561
            return super(ControlSwitch, self).default(line)
 
2562
        elif raise_error:
 
2563
            raise NotValidInput('unknow command: %s' % line)
2514
2564
        else:
2515
2565
            logger.warning('unknow command: %s' % line)
2516
2566
            self.value = 'reask'
2523
2573
                value = value.lower()
2524
2574
            getattr(self, 'ans_%s' % base)(value)
2525
2575
        elif base in self.switch:
2526
 
            self.set_switch(base, value)        
 
2576
            self.set_switch(base, value)
 
2577
        elif raise_error:
 
2578
            raise NotValidInput('Not valid command: %s' % line)                
2527
2579
        else:
2528
2580
            logger.warning('Not valid command: %s' % line)
2529
2581
   
2571
2623
        """change a switch to a given value"""
2572
2624
 
2573
2625
        assert key in self.switch
2574
 
 
2575
 
        
2576
2626
        
2577
2627
        if hasattr(self, 'ans_%s' % key):
2578
2628
            if not self.is_case_sensitive(key):
2790
2840
        if info == '':
2791
2841
            info = 'Please install module'
2792
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
        # here for simple "help"
 
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
        
 
2867
    def print_help_for_switch(self, line):
 
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
    
2793
2889
 
2794
2890
    def question_formatting(self, nb_col = 80,
2795
2891
                                  ldescription=0,
2963
3059
        
2964
3060
        return upper, lower, f1, f2
2965
3061
                
2966
 
    def create_question(self):
 
3062
    def create_question(self, help_text=True):
2967
3063
        """ create the question  with correct formatting"""
2968
3064
        
2969
3065
        # geth the number of line and column of the shell to adapt the printing
3053
3149
                
3054
3150
        if not example:
3055
3151
            example = ('KEY', 'VALUE')
3056
 
            
3057
 
        text += \
3058
 
          ["Either type the switch number (1 to %s) to change its setting," % len(self.to_control),
3059
 
           "Set any switch explicitly (e.g. type '%s=%s' at the prompt)" % example,
3060
 
           "Type 'help' for the list of all valid option",
3061
 
           "Type '0', 'auto', 'done' or just press enter when you are done."]
3062
 
        
3063
 
        # check on the number of row:
3064
 
        if len(text) > nb_rows:
3065
 
            # too many lines. Remove some
3066
 
            to_remove = [ -2, #Type 'help' for the list of all valid option
3067
 
                          -5,  # \====/
3068
 
                          -4, #Either type the switch number (1 to %s) to change its setting,
3069
 
                          -3, # Set any switch explicitly
3070
 
                          -1, # Type '0', 'auto', 'done' or just press enter when you are done.
3071
 
                         ] 
3072
 
            to_remove = to_remove[:min(len(to_remove), len(text)-nb_rows)]
3073
 
            text = [t for i,t in enumerate(text) if i-len(text) not in to_remove]
3074
 
        
 
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
            # check on the number of row:
 
3161
            if len(text) > nb_rows:
 
3162
                # too many lines. Remove some
 
3163
                to_remove = [ -2, #Type 'help' for the list of all valid option
 
3164
                              -5,  # \====/
 
3165
                              -4, #Either type the switch number (1 to %s) to change its setting,
 
3166
                              -3, # Set any switch explicitly
 
3167
                              -1, # Type '0', 'auto', 'done' or just press enter when you are done.
 
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
            
3075
3172
        self.question =    "\n".join(text)                                                              
3076
3173
        return self.question
3077
3174
    
3078
3175
 
3079
 
 
3080
 
 
3081
3176
#===============================================================================
3082
3177
3083
3178
#===============================================================================