diff --git a/README.rst b/README.rst index e35c2b8..9d8a96f 100644 --- a/README.rst +++ b/README.rst @@ -261,6 +261,25 @@ an output file:: __ http://robotframework.org/robotframework/#built-in-tools +Serving Multiple Libraries With One Server +------- + +In many cases it maybe be desirable to serve multiple libraries from a single +remote server. The libraries argument not only accepts a single class type, but +also can accept a list of classes from which to serve keywords. For example: + +.. sourcecode:: python + class KeywordLib1: + def Keyword1(self): + ... + + class KeywordLib2: + def Keyword2(self): + ... + + if __name__ == "__main__": + RobotRemoteServer([KeywordLib1(), KeywordLib2()]) + Example ------- diff --git a/example/examplelibrary.py b/example/examplelibrary.py index 8e904b0..99ba571 100755 --- a/example/examplelibrary.py +++ b/example/examplelibrary.py @@ -34,4 +34,4 @@ def strings_should_be_equal(self, str1, str2): if __name__ == '__main__': - RobotRemoteServer(ExampleLibrary(), *sys.argv[1:]) + RobotRemoteServer([ExampleLibrary()], *sys.argv[1:]) diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index cea887c..0f0ae21 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -52,11 +52,12 @@ def getfullargspec(func): class RobotRemoteServer(object): - def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, + def __init__(self, libraries, host='127.0.0.1', port=8270, port_file=None, allow_stop='DEPRECATED', serve=True, allow_remote_stop=True): """Configure and start-up remote server. - :param library: Test library instance or module to host. + :param libraries: Test library instance or module to host, can be a + list of modules to host. :param host: Address to listen. Use ``'0.0.0.0'`` to listen to all available interfaces. :param port: Port to listen. Use ``0`` to select a free port @@ -74,7 +75,11 @@ def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, ``Stop Remote Server`` keyword and ``stop_remote_server`` XML-RPC method. """ - self._library = RemoteLibraryFactory(library) + if isinstance(libraries, list): + self._libraries = [RemoteLibraryFactory(library_) + for library_ in libraries] + else: + self._libraries = [RemoteLibraryFactory(libraries)] self._server = StoppableXMLRPCServer(host, int(port)) self._register_functions(self._server) self._port_file = port_file @@ -171,28 +176,35 @@ def stop_remote_server(self, log=True): return True def get_keyword_names(self): - return self._library.get_keyword_names() + ['stop_remote_server'] + keywords = ['stop_remote_server'] + for l in self._libraries: + keywords += l.get_keyword_names() + return keywords def run_keyword(self, name, args, kwargs=None): if name == 'stop_remote_server': return KeywordRunner(self.stop_remote_server).run_keyword(args, kwargs) - return self._library.run_keyword(name, args, kwargs) + library_ = next(l for l in self._libraries if name in l._names) + return library_.run_keyword(name, args, kwargs) def get_keyword_arguments(self, name): if name == 'stop_remote_server': return [] - return self._library.get_keyword_arguments(name) + library_ = next(l for l in self._libraries if name in l._names) + return library_.get_keyword_arguments(name) def get_keyword_documentation(self, name): if name == 'stop_remote_server': return ('Stop the remote server unless stopping is disabled.\n\n' 'Return ``True/False`` depending was server stopped or not.') - return self._library.get_keyword_documentation(name) + library_ = next(l for l in self._libraries if name in l._names) + return library_.get_keyword_documentation(name) def get_keyword_tags(self, name): if name == 'stop_remote_server': return [] - return self._library.get_keyword_tags(name) + library_ = next(l for l in self._libraries if name in l._names) + return library_.get_keyword_tags(name) class StoppableXMLRPCServer(SimpleXMLRPCServer): @@ -280,7 +292,7 @@ def is_function_or_method(item): class StaticRemoteLibrary(object): def __init__(self, library): - self._library = library + self._libraries = library self._names, self._robot_name_index = self._get_keyword_names(library) def _get_keyword_names(self, library): @@ -305,7 +317,7 @@ def run_keyword(self, name, args, kwargs=None): def _get_keyword(self, name): if name in self._robot_name_index: name = self._robot_name_index[name] - return getattr(self._library, name) + return getattr(self._libraries, name) def get_keyword_arguments(self, name): if __name__ == '__init__': @@ -325,9 +337,9 @@ def get_keyword_arguments(self, name): def get_keyword_documentation(self, name): if name == '__intro__': - source = self._library + source = self._libraries elif name == '__init__': - source = self._get_init(self._library) + source = self._get_init(self._libraries) else: source = self._get_keyword(name) return inspect.getdoc(source) or '' @@ -612,4 +624,4 @@ def parse_args(script, *args): action, uri = parse_args(*sys.argv) success = action(uri) - sys.exit(0 if success else 1) + sys.exit(0 if success else 1) \ No newline at end of file