Support graceful script termination
diff --git a/appurify/client.py b/appurify/client.py index 5ce6729..5c3332e 100644 --- a/appurify/client.py +++ b/appurify/client.py
@@ -16,6 +16,7 @@ import pprint import inspect +from . import signals from . import constants from .utils import log, get, post, wget @@ -99,6 +100,9 @@ def tests_check_result(access_token, test_run_id): return get('tests/check', {'access_token':access_token, 'test_run_id': test_run_id}) +def tests_abort(access_token, test_run_id): + return post('tests/abort', {'access_token':access_token, 'test_run_id': test_run_id}) + ################### ## Config file API ################### @@ -287,26 +291,36 @@ runtime = 0 while test_status != 'complete' and runtime < self.timeout: - time.sleep(self.poll_every) - r = tests_check_result(self.access_token, test_run_id) - test_status_response = r.json()['response'] - test_status = test_status_response['status'] - if test_status == 'complete': - test_response = test_status_response['results'] - log("**** COMPLETE - JSON SUMMARY FOLLOWS ****") - log(json.dumps(test_response)) - log("**** COMPLETE - JSON SUMMARY ENDS ****") - return test_status_response - else: - log("%s sec elapsed" % str(runtime)) - if 'message' in test_status_response: - log(test_status_response['message']) - log("Test progress: {}".format(test_status_response.get('detailed_status', 'status-unavailable'))) - runtime = runtime + self.poll_every + try: + time.sleep(self.poll_every) + r = tests_check_result(self.access_token, test_run_id) + test_status_response = r.json()['response'] + test_status = test_status_response['status'] + if test_status == 'complete': + test_response = test_status_response['results'] + log("**** COMPLETE - JSON SUMMARY FOLLOWS ****") + log(json.dumps(test_response)) + log("**** COMPLETE - JSON SUMMARY ENDS ****") + return test_status_response + else: + log("%s sec elapsed" % str(runtime)) + if 'message' in test_status_response: + log(test_status_response['message']) + log("Test progress: {}".format(test_status_response.get('detailed_status', 'status-unavailable'))) + runtime = runtime + self.poll_every + except signals.QuitException: + log("Quitting script") + raise + except signals.AbortException: + r = tests_abort(self.access_token, test_run_id) + log("Aborting test run...") + log(r.json()['response']) + raise + except signals.ContinueException: + pass raise AppurifyClientError("Test result poll timed out after %s seconds" % self.timeout) - def reportTestResult(self, test_status_response): test_response = test_status_response['results'] result_dir = self.args.get('result_dir', None)
diff --git a/appurify/signals.py b/appurify/signals.py new file mode 100644 index 0000000..325b0b2 --- /dev/null +++ b/appurify/signals.py
@@ -0,0 +1,42 @@ +''' +Created on Oct 15, 2013 + +@author: twang +''' +import signal + +class SigintException(Exception): + pass + +class AbortException(SigintException): + message = "Test run aborted at user request" + pass + +class ContinueException(SigintException): + message = "Continuing test execution" + pass + +class QuitException(SigintException): + message = "Script quit at user request without aborting test run" + pass + +def signal_handler(signal, frame): + response = None + while not response or response not in ['a', 'A', 'q', 'Q', 'c', 'C']: + response = read_input("Interrupted: (a)bort test run, (q)uit script without aborting or (c)ontinue script? [a/q/c]") + if response in ['a', 'A']: + raise AbortException + elif response in ['c', 'C']: + raise ContinueException + else: + raise QuitException + +def read_input(prompt): + try: + response = raw_input(prompt) + except: + response = input(prompt) + return response + +signal.signal(signal.SIGINT, signal_handler) +
diff --git a/appurify/utils.py b/appurify/utils.py index bfff5ef..bf3eab4 100644 --- a/appurify/utils.py +++ b/appurify/utils.py
@@ -203,3 +203,4 @@ """Download a file to specified path""" with open(path, 'wb') as f: f.write(requests.get(url, verify=verify).content) +