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)
+