diff --git a/zipline/lines.py b/zipline/lines.py index 9a0b49ef..9bc8b3ac 100644 --- a/zipline/lines.py +++ b/zipline/lines.py @@ -62,7 +62,7 @@ before invoking simulate. import sys import zmq import os -from signal import SIGHUP +from signal import SIGHUP, SIGINT import multiprocessing from setproctitle import setproctitle @@ -118,6 +118,9 @@ class SimulatedTrading(object): self.logger = Logger(sim_id) self.print_logger = Logger('Print') + # exit status flag + self.success = False + def simulate(self, blocking=True, send_sighup=False): @@ -155,28 +158,28 @@ class SimulatedTrading(object): self.results_socket.send(msg) self.signal_done() + self.success = True except Exception as exc: self.handle_exception(exc) finally: + # not much to do besides log our exit. self.close() def signal_done(self): # notify monitor we're done - done_frame = zp.DONE_FRAME('succes') + done_frame = zp.DONE_FRAME('success') self.results_socket.send(done_frame) def close(self): log.info("Closing Simulation: {id}".format(id=self.sim_id)) if self.proc and self.send_sighup: ppid = os.getppid() - log.warning("Sending SIGHUP") - os.kill(ppid, SIGHUP) - - def cancel(self): - if self.proc and self.proc.is_alive(): - self.proc.terminate() - else: - self.gen.throw(CancelSignal()) + if self.success: + log.warning("Sending SIGHUP") + os.kill(ppid, SIGHUP) + else: + log.warning("Sending SIGINT") + os.kill(ppid, SIGINT) def handle_exception(self, exc): if isinstance(exc, CancelSignal): diff --git a/zipline/protocol.py b/zipline/protocol.py index b5bf67ae..dd46bd60 100644 --- a/zipline/protocol.py +++ b/zipline/protocol.py @@ -527,11 +527,15 @@ def EXCEPTION_FRAME(exception_tb, name, message): rlist = [] for stack in stack_list: filename = shorten_filename(stack[0]) + # default the line to empty string rather than None + line = '' + if stack[3]: + line = stack[3] rstack = { 'filename' : filename, 'lineno' : stack[1], 'method' : stack[2], - 'line' : stack[3] + 'line' : line } rlist.append(rstack) result = { diff --git a/zipline/utils/test_utils.py b/zipline/utils/test_utils.py index 02ac4c69..13924f60 100644 --- a/zipline/utils/test_utils.py +++ b/zipline/utils/test_utils.py @@ -4,6 +4,7 @@ import time import zipline.protocol as zp from datetime import datetime import blist +from bson import ObjectId from zipline.utils.date_utils import EPOCH from itertools import izip from logbook import FileHandler @@ -31,6 +32,7 @@ def check_dict(test, a, b, label): # ignore the extra fields used by dictshield if key in ['progress']: continue + test.assertTrue(a.has_key(key), "missing key at: " + label + "." + key) test.assertTrue(b.has_key(key), "missing key at: " + label + "." + key) a_val = a[key] @@ -60,6 +62,13 @@ def check(test, a, b, label=None): else: test.assertEqual(a, b, "mismatch on path: " + label) +def check_excluded(test, a, excluded_keys=[]): + for key, value in a.iteritems(): + test.assertTrue(key not in excluded_keys) + test.assertFalse(key.endswith('_id'), 'Avoid _id fields!') + test.assertFalse(isinstance(value, ObjectId)) + if isinstance(value, dict): + check_excluded(test, value, excluded_keys) def drain_zipline(test, zipline, p_blocking=False): assert test.ctx, "method expects a valid zmq context"