├── LICENSE.txt ├── README.rst ├── runKeywordAsync ├── __init__.py └── runKeywordAsync.py └── setup.py /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fredrik Reveny 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | **Description** 2 | Generic Robot Framework library for asynchronous keyword or method execution 3 | This module takes keyword as input and runs it as an independent thread. This module also provide a mechanism to wait for all the spawned thread with a timeout and returns a list containing result. 4 | 5 | **Installation** 6 | 7 | If you have pip installed: 8 | pip3 install robotframework-run-keyword-async 9 | 10 | Alternatively download directly from the Python Package Index: 11 | https://pypi.python.org/pypi/robotframework-run-keyword-async 12 | 13 | **Usage** 14 | 15 | **1. Import into a test suite with:** 16 | Library runKeywordAsync 17 | 18 | **2. To run a keyword asynchronously:** 19 | ${handle}= Run Keyword Async 20 | (Note: It takes only args as arguments, kwargs is not supported) 21 | 22 | **3. To wait for all keywords and retrieve the return value:** 23 | ${return_value}= Wait Async All timeout=3 24 | (Note: timeout is an optional parameter, default timeout is 60 seconds) 25 | -------------------------------------------------------------------------------- /runKeywordAsync/__init__.py: -------------------------------------------------------------------------------- 1 | from .runKeywordAsync import runKeywordAsync 2 | -------------------------------------------------------------------------------- /runKeywordAsync/runKeywordAsync.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import time 4 | from robot.libraries.BuiltIn import BuiltIn 5 | from robot.output.logger import LOGGER 6 | 7 | class runKeywordAsync: 8 | def __init__(self): 9 | self._thread_pool = {} 10 | self._last_thread_handle = 1 11 | #self._robot_log_level = BuiltIn().get_variable_value("${LOG_LEVEL}") 12 | 13 | def run_method_async(self, keyword, *args, **kwargs): 14 | #BuiltIn().set_log_level("NONE") 15 | handle = self._last_thread_handle 16 | thread = self._threaded_method(keyword, *args, **kwargs) 17 | thread.start() 18 | self._thread_pool[handle] = thread 19 | self._last_thread_handle += 1 20 | return handle 21 | 22 | def run_keyword_async(self, keyword, *args): 23 | #BuiltIn().set_log_level("NONE") 24 | handle = self._last_thread_handle 25 | thread = self._threaded(keyword, *args) 26 | thread.start() 27 | self._thread_pool[handle] = thread 28 | self._last_thread_handle += 1 29 | return handle 30 | 31 | def wait_async_all(self, timeout=60): 32 | timeout = int(timeout) 33 | results = [] 34 | for thread in self._thread_pool: 35 | try: 36 | result = self._thread_pool[thread].result_queue.get(True, timeout) 37 | results.append(result) 38 | except: 39 | #BuiltIn().set_log_level(self._robot_log_level) 40 | for thread in self._thread_pool: 41 | self._thread_pool[thread].terminate() 42 | raise Exception("Process " + str(thread) + " Failed") 43 | #BuiltIn().set_log_level(self._robot_log_level) 44 | self._thread_pool = {} 45 | self._last_thread_handle = 1 46 | return results 47 | 48 | def get_async_return(self, handle, timeout=60): 49 | timeout = int(timeout) 50 | if handle in self._thread_pool: 51 | try: 52 | result = self._thread_pool[handle].result_queue.get(True, timeout) 53 | del self._thread_pool[handle] 54 | # BuiltIn().set_log_level(self._robot_log_level) 55 | return result 56 | except: 57 | raise Exception("Process " + str(handle) + " Failed") 58 | else: 59 | raise Exception("Passed Process id " + str(handle) + " is not a valid id") 60 | 61 | def _threaded_method(self, keyword, *args, **kwargs): 62 | from multiprocessing import Queue 63 | from multiprocessing import Process 64 | 65 | def wrapped_f(q, *args, **kwargs): 66 | ''' Calls the decorated function and puts the result in a queue ''' 67 | ret = BuiltIn().call_method(keyword, *args, **kwargs) 68 | q.put(ret) 69 | 70 | q = Queue() 71 | th = Process(target=wrapped_f, args=(q,)+args, kwargs=kwargs) 72 | th.result_queue = q 73 | return th 74 | 75 | def _threaded(self, keyword, *args): 76 | from multiprocessing import Queue 77 | from multiprocessing import Process 78 | 79 | def wrapped_f(q, *args): 80 | ''' Calls the decorated function and puts the result in a queue ''' 81 | LOGGER.unregister_xml_logger() 82 | ret = BuiltIn().run_keyword(keyword, *args) 83 | q.put(ret) 84 | 85 | q = Queue() 86 | th = Process(target=wrapped_f, args=(q,)+args) 87 | th.result_queue = q 88 | return th 89 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name = "robotframework-run-keyword-async", 5 | version = "1.0.9", 6 | description = "Generic Robot Framework library for asynchronous keyword or method execution", 7 | author = "Awadh Shukla", 8 | author_email = "shukla.awadh@gmail.com", 9 | license = "MIT", 10 | url = "https://github.com/awadhn/robotframework-run-keyword-async", 11 | download_url = "https://github.com/awadhn/robotframework-run-keyword-async", 12 | keywords = ["run-keyword-async", "async", "robotframework"], 13 | install_requires = ["robotframework >= 2.8.6"], 14 | packages = ["runKeywordAsync"], 15 | classifiers = [ 16 | "Programming Language :: Python", 17 | "Programming Language :: Python :: 3", 18 | "Development Status :: 4 - Beta", 19 | "Environment :: Other Environment", 20 | "Intended Audience :: Developers", 21 | "Operating System :: OS Independent", 22 | "Topic :: Software Development :: Libraries :: Python Modules", 23 | ] 24 | ) 25 | --------------------------------------------------------------------------------