From b430137f0d51a69118ee896152a19ab532d66d54 Mon Sep 17 00:00:00 2001 From: Eddy Pronk Date: Thu, 12 Jan 2017 09:09:41 +1100 Subject: [PATCH] Implemented support for @keyword decorator get_keyword_names populates the mapping from an 'embedded argument name' to a 'function name'. Assumed is that get_keyword_names is always called before run_keyword. Tags passed to the decorator are added at the end of the keyword documentation using Tags: tag1, tag2 syntax. The test does not check if tag1 and tag2 have been added to the keyword yet. issue: #35 --- src/robotremoteserver.py | 21 ++++++++++++++++++--- test/atest/keyword_decorator.robot | 14 ++++++++++++++ test/libs/keyword_decorator.py | 22 ++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 test/atest/keyword_decorator.robot create mode 100644 test/libs/keyword_decorator.py diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index 403388f..bc08736 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -190,16 +190,27 @@ class StaticRemoteLibrary(object): def __init__(self, library): self._library = library + self._robot_name_index = {} def get_keyword_names(self): - return [name for name, value in inspect.getmembers(self._library) - if name[0] != '_' and is_function_or_method(value)] + names = [] + for name, value in inspect.getmembers(self._library): + if is_function_or_method(value): + if getattr(value, 'robot_name', None) not in (None, ''): + names.append(value.robot_name) + self._robot_name_index[value.robot_name] = name + else: + if name[0] != '_': + names.append(name) + return names def run_keyword(self, name, args, kwargs=None): kw = self._get_keyword(name) return KeywordRunner(kw).run_keyword(args, kwargs) def _get_keyword(self, name): + if name in self._robot_name_index: + name = self._robot_name_index[name] kw = getattr(self._library, name, None) return kw if is_function_or_method(kw) else None @@ -227,7 +238,11 @@ def get_keyword_documentation(self, name): return inspect.getdoc(self._library) or '' if name == '__init__' and inspect.ismodule(self._library): return '' - return inspect.getdoc(self._get_keyword(name)) or '' + keyword = self._get_keyword(name) + doc = inspect.getdoc(keyword) or '' + if len(getattr(keyword, 'robot_tags')): + doc += "\nTags: %s\n" % ', '.join(keyword.robot_tags) + return doc class HybridRemoteLibrary(StaticRemoteLibrary): diff --git a/test/atest/keyword_decorator.robot b/test/atest/keyword_decorator.robot new file mode 100644 index 0000000..fc95d8f --- /dev/null +++ b/test/atest/keyword_decorator.robot @@ -0,0 +1,14 @@ +*** Settings *** +Resource resource.robot +Suite Setup Start And Import Remote Library keyword_decorator.py +Suite Teardown Stop Remote Library + +*** Test Cases *** +Keyword with 2 arguments + Add 7 Copies Of Coffee To Cart + +When embedded name is empty keyword is still callable + Embedded name empty + +Tags added with keyword decorator + login admin diff --git a/test/libs/keyword_decorator.py b/test/libs/keyword_decorator.py new file mode 100644 index 0000000..bb7fdea --- /dev/null +++ b/test/libs/keyword_decorator.py @@ -0,0 +1,22 @@ +from robot.api.deco import keyword + +class Arguments(object): + + @keyword('Add ${quantity:\d+} Copies Of ${item} To Cart') + def add_copies_to_cart(self, quantity, item): + pass + + @keyword('') + def embedded_name_empty(self): + pass + + @keyword(tags=['tag1', 'tag2']) + def login(username, password): + ''' + This is keyword documentation''' + +if __name__ == '__main__': + import sys + from robotremoteserver import RobotRemoteServer + + RobotRemoteServer(Arguments(), '127.0.0.1', *sys.argv[1:])