From 8ab5c2db8a7345143fc994718303fda2a63f90c3 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 4 Jul 2018 16:11:43 +0000 Subject: [PATCH] Fix and simplify lldb.command decorator 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 `. 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 --- .../command_script/TestCommandScript.py | 11 ++++-- .../command_script/decorated.py | 35 +++++++++++++++++++ .../functionalities/command_script/py_import | 1 + lldb/scripts/Python/python-extensions.swig | 27 +++++--------- 4 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/command_script/decorated.py diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py b/lldb/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py index 103189e9dd5a..1698c0d0c35f 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py @@ -49,6 +49,7 @@ class CmdPythonTestCase(TestBase): 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) @@ -67,13 +68,19 @@ class CmdPythonTestCase(TestBase): 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']) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/command_script/decorated.py b/lldb/packages/Python/lldbsuite/test/functionalities/command_script/decorated.py new file mode 100644 index 000000000000..f9707a5706ac --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/command_script/decorated.py @@ -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) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/command_script/py_import b/lldb/packages/Python/lldbsuite/test/functionalities/command_script/py_import index 169daacc1a83..6c1f7b8185f6 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/command_script/py_import +++ b/lldb/packages/Python/lldbsuite/test/functionalities/command_script/py_import @@ -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 diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig index d79917b92158..5543bee95d47 100644 --- a/lldb/scripts/Python/python-extensions.swig +++ b/lldb/scripts/Python/python-extensions.swig @@ -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):