Skip to content

Commit

Permalink
Fix and simplify lldb.command decorator
Browse files Browse the repository at this point in the history
Summary:
This change fixes one issue with `lldb.command`, and also reduces the implementation.

The fix: a command function's docstring was not shown when running `help <command_name>`. This is because the docstring attached the source function is not propagated to the decorated function (`f.__call__`). By returning the original function, the docstring will be properly displayed by `help`.

Also with this change, the command name is assumed to be the function's name, but can still be explicitly defined as previously.

Additionally, the implementation was updated to:

* Remove inner class
* Remove use of `inspect` module
* Remove `*args` and `**kwargs`

Reviewers: clayborg

Reviewed By: clayborg

Subscribers: keith, xiaobai, lldb-commits

Differential Revision: https://reviews.llvm.org/D48658

llvm-svn: 336287
  • Loading branch information
kastiglione committed Jul 4, 2018
1 parent 17c0c4e commit 8ab5c2d
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 21 deletions.
Expand Up @@ -49,6 +49,7 @@ def cleanup():
self.runCmd('command script delete tell_curr', check=False)
self.runCmd('command script delete bug11569', check=False)
self.runCmd('command script delete takes_exe_ctx', check=False)
self.runCmd('command script delete decorated', check=False)

# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
Expand All @@ -67,13 +68,19 @@ def cleanup():
substrs=['Just a docstring for welcome_impl',
'A command that says hello to LLDB users'])

decorated_commands = ["decorated" + str(n) for n in range(1, 5)]
for name in decorated_commands:
self.expect(name, substrs=["hello from " + name])
self.expect("help " + name,
substrs=["Python command defined by @lldb.command"])

self.expect("help",
substrs=['For more information run',
'welcome'])
'welcome'] + decorated_commands)

self.expect("help -a",
substrs=['For more information run',
'welcome'])
'welcome'] + decorated_commands)

self.expect("help -u", matching=False,
substrs=['For more information run'])
Expand Down
@@ -0,0 +1,35 @@
from __future__ import print_function

import lldb


@lldb.command()
def decorated1(debugger, args, exe_ctx, result, dict):
"""
Python command defined by @lldb.command
"""
print("hello from decorated1", file=result)


@lldb.command(doc="Python command defined by @lldb.command")
def decorated2(debugger, args, exe_ctx, result, dict):
"""
This docstring is overridden.
"""
print("hello from decorated2", file=result)


@lldb.command()
def decorated3(debugger, args, result, dict):
"""
Python command defined by @lldb.command
"""
print("hello from decorated3", file=result)


@lldb.command("decorated4")
def _decorated4(debugger, args, exe_ctx, result, dict):
"""
Python command defined by @lldb.command
"""
print("hello from decorated4", file=result)
Expand Up @@ -10,3 +10,4 @@ command script add tell_sync --function welcome.check_for_synchro --synchronicit
command script add tell_async --function welcome.check_for_synchro --synchronicity async
command script add tell_curr --function welcome.check_for_synchro --synchronicity curr
command script add takes_exe_ctx --function welcome.takes_exe_ctx
command script import decorated.py
27 changes: 8 additions & 19 deletions lldb/scripts/Python/python-extensions.swig
Expand Up @@ -839,29 +839,18 @@

%pythoncode %{

def command(*args, **kwargs):
def command(command_name=None, doc=None):
import lldb
import inspect
"""A decorator function that registers an LLDB command line
command that is bound to the function it is attached to."""
class obj(object):
"""The object that tracks adding the command to LLDB one time and handles
calling the function on subsequent calls."""
def __init__(self, function, command_name, doc = None):
if doc:
function.__doc__ = doc
command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name)
lldb.debugger.HandleCommand(command)
self.function = function
def __call__(self, debugger, command, exe_ctx, result, dict):
if len(inspect.getargspec(self.function).args) == 5:
self.function(debugger, command, exe_ctx, result, dict)
else:
self.function(debugger, command, result, dict)
def callable(function):
"""Creates a callable object that gets used."""
f = obj(function, *args, **kwargs)
return f.__call__
"""Registers an lldb command for the decorated function."""
command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name or function.__name__)
lldb.debugger.HandleCommand(command)
if doc:
function.__doc__ = doc
return function

return callable

class declaration(object):
Expand Down

0 comments on commit 8ab5c2d

Please sign in to comment.