> On Jun 22, 2018, at 5:20 PM, Jim Ingham <jing...@apple.com> wrote: > > This is very cool! > > Could we make a base class for lldb commands in the lldb module that provides > register_lldb_command? Then you wouldn't have to copy and paste this > boiler-plate in every command file. Now that you have a generic way to add > the commands, we could just do that automatically in "command script import" > on every class that derives from this base when we import the module, and you > wouldn't need to add the __lldb_init_module either. > > We could also provide a table driven way to specify the options, then have > the base class actually make them using opt parse. I'd like to hide this bit > as much as possible, to prepare for eventually transitioning over to having > the options be real lldb command options. > > Jim > > >> On Jun 22, 2018, at 4:34 PM, Greg Clayton via lldb-commits >> <lldb-commits@lists.llvm.org> wrote: >> >> Author: gclayton >> Date: Fri Jun 22 16:34:24 2018 >> New Revision: 335401 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=335401&view=rev >> Log: >> Update cmdtemplate.py to use best pratices. >> >> Fixes include: >> - fix all lint errors >> - add code that will automatically register and LLDB command classes by >> detecting the classes and any classes that have a "register_lldb_command" >> function >> - automatically fill in the correct module name when registering commands >> - automatically fill in the class name when registering command >> >> >> Modified: >> lldb/trunk/examples/python/cmdtemplate.py >> >> Modified: lldb/trunk/examples/python/cmdtemplate.py >> URL: >> http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/cmdtemplate.py?rev=335401&r1=335400&r2=335401&view=diff >> ============================================================================== >> --- lldb/trunk/examples/python/cmdtemplate.py (original) >> +++ lldb/trunk/examples/python/cmdtemplate.py Fri Jun 22 16:34:24 2018 >> @@ -1,69 +1,91 @@ >> #!/usr/bin/python >> >> -#---------------------------------------------------------------------- >> +# --------------------------------------------------------------------- >> # Be sure to add the python path that points to the LLDB shared library. >> # >> # # To use this in the embedded python interpreter using "lldb" just >> # import it with the full path using the "command script import" >> # command >> # (lldb) command script import /path/to/cmdtemplate.py >> -#---------------------------------------------------------------------- >> +# --------------------------------------------------------------------- >> >> +import inspect >> import lldb >> -import commands >> import optparse >> import shlex >> +import sys >> + >> >> class FrameStatCommand: >> - def create_options(self): >> + program = 'framestats' >> + >> + @classmethod >> + def register_lldb_command(cls, debugger, module_name): >> + parser = cls.create_options() >> + cls.__doc__ = parser.format_help() >> + # Add any commands contained in this module to LLDB >> + command = 'command script add -c %s.%s %s' % (module_name, >> + cls.__name__, >> + cls.program) >> + debugger.HandleCommand(command) >> + print('The "{0}" command has been installed, type "help {0}" or >> "{0} ' >> + '--help" for detailed help.'.format(cls.program)) >> + >> + @classmethod >> + def create_options(cls): >> >> usage = "usage: %prog [options]" >> - description = '''This command is meant to be an example of how to >> make an LLDB command that >> -does something useful, follows best practices, and exploits the SB API. >> -Specifically, this command computes the aggregate and average size of the >> variables in the current frame >> -and allows you to tweak exactly which variables are to be accounted in the >> computation. >> -''' >> - >> - # Pass add_help_option = False, since this keeps the command in >> line with lldb commands, >> - # and we wire up "help command" to work by providing the long & >> short help methods below. >> - self.parser = optparse.OptionParser( >> - description = description, >> - prog = 'framestats', >> - usage = usage, >> - add_help_option = False) >> + description = ('This command is meant to be an example of how to >> make ' >> + 'an LLDB command that does something useful, follows >> ' >> + 'best practices, and exploits the SB API. ' >> + 'Specifically, this command computes the aggregate ' >> + 'and average size of the variables in the current ' >> + 'frame and allows you to tweak exactly which >> variables ' >> + 'are to be accounted in the computation.') >> + >> + # Pass add_help_option = False, since this keeps the command in line >> + # with lldb commands, and we wire up "help command" to work by >> + # providing the long & short help methods below. >> + parser = optparse.OptionParser( >> + description=description, >> + prog=cls.program, >> + usage=usage, >> + add_help_option=False) >> >> - self.parser.add_option( >> + parser.add_option( >> '-i', >> '--in-scope', >> - action = 'store_true', >> - dest = 'inscope', >> - help = 'in_scope_only = True', >> - default = True) >> + action='store_true', >> + dest='inscope', >> + help='in_scope_only = True', >> + default=True) >> >> - self.parser.add_option( >> + parser.add_option( >> '-a', >> '--arguments', >> - action = 'store_true', >> - dest = 'arguments', >> - help = 'arguments = True', >> - default = True) >> + action='store_true', >> + dest='arguments', >> + help='arguments = True', >> + default=True) >> >> - self.parser.add_option( >> + parser.add_option( >> '-l', >> '--locals', >> - action = 'store_true', >> - dest = 'locals', >> - help = 'locals = True', >> - default = True) >> + action='store_true', >> + dest='locals', >> + help='locals = True', >> + default=True) >> >> - self.parser.add_option( >> + parser.add_option( >> '-s', >> '--statics', >> - action = 'store_true', >> - dest = 'statics', >> - help = 'statics = True', >> - default = True) >> - >> + action='store_true', >> + dest='statics', >> + help='statics = True', >> + default=True) >> + >> + return parser >> + >> def get_short_help(self): >> return "Example command for use in debugging" >> >> @@ -71,23 +93,25 @@ and allows you to tweak exactly which va >> return self.help_string >> >> def __init__(self, debugger, unused): >> - self.create_options() >> + self.parser = self.create_options() >> self.help_string = self.parser.format_help() >> >> def __call__(self, debugger, command, exe_ctx, result): >> # Use the Shell Lexer to properly parse up command options just like a >> # shell would >> command_args = shlex.split(command) >> - >> + >> try: >> (options, args) = self.parser.parse_args(command_args) >> except: >> - # if you don't handle exceptions, passing an incorrect argument >> to the OptionParser will cause LLDB to exit >> - # (courtesy of OptParse dealing with argument errors by >> throwing SystemExit) >> + # if you don't handle exceptions, passing an incorrect argument >> to >> + # the OptionParser will cause LLDB to exit (courtesy of OptParse >> + # dealing with argument errors by throwing SystemExit) >> result.SetError("option parsing failed") >> return >> >> - # Always get program state from the SBExecutionContext passed in as >> exe_ctx >> + # Always get program state from the lldb.SBExecutionContext passed >> + # in as exe_ctx >> frame = exe_ctx.GetFrame() >> if not frame.IsValid(): >> result.SetError("invalid frame") >> @@ -108,15 +132,16 @@ and allows you to tweak exactly which va >> variable_type = variable.GetType() >> total_size = total_size + variable_type.GetByteSize() >> average_size = float(total_size) / variables_count >> - print >>result, "Your frame has %d variables. Their total size >> is %d bytes. The average size is %f bytes" % ( >> - variables_count, total_size, average_size) >> - # not returning anything is akin to returning success >> + print >>result, ("Your frame has %d variables. Their total size >> " >> + "is %d bytes. The average size is %f bytes") % >> ( >> + variables_count, total_size, >> average_size) >> + # not returning anything is akin to returning success >> >> >> def __lldb_init_module(debugger, dict): >> - # This initializer is being run from LLDB in the embedded command >> interpreter >> - >> - # Add any commands contained in this module to LLDB >> - debugger.HandleCommand( >> - 'command script add -c cmdtemplate.FrameStatCommand framestats') >> - print 'The "framestats" command has been installed, type "help >> framestats" for detailed help.' >> + # Register all classes that have a register_lldb_command method >> + for _name, cls in inspect.getmembers(sys.modules[__name__]): >> + if inspect.isclass(cls) and callable(getattr(cls, >> + >> "register_lldb_command", >> + None)): >> + cls.register_lldb_command(debugger, __name__) >> >> >> _______________________________________________ >> lldb-commits mailing list >> lldb-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits >
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits