コード例 #1
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(
         Message(
             'vault_request', 'add_stock',
             ManagedStock(data['acronym'],
                          last_price=float(data['price']),
                          shares=int(data['shares']))))
コード例 #2
0
class SQLTestCase(unittest.TestCase):
    def setUp(self) -> None:
        StockVault.setup_instance(db_directory='/tmp/robin_test_db')
        self.client = MessageHandler('client_handler')

    def tearDown(self) -> None:
        StockVault.sjoin()
        self.client.join()
        with os.scandir('/tmp/robin_test_db/') as it:
            for entry in it:
                os.remove(entry.path)
        os.rmdir('/tmp/robin_test_db')

    def test_file_creation(self):
        sql.setup_db('/tmp/robin_test_db')
        self.assertTrue(path.exists(path.join('/tmp/robin_test_db', db_name)),
                        'Can create test files without error')

    def test_add_stock(self):
        self.client.send(Message('vault_request', 'add_monitor',
                                 Stock('AAPL')))
        time.sleep(0.5)
        names = StockVault.get_stock_names()
        print(names)
        self.assertTrue('AAPL' in names,
                        'An inserted stock should appear in the database')

    def test_remove_stock(self):
        self.client.send(Message('vault_request', 'add_monitor',
                                 Stock('AAPL')))
        self.client.send(
            Message('vault_request', 'remove_monitor', Stock('AAPL')))
        time.sleep(0.5)
        names = StockVault.get_stock_names()
        self.assertTrue('AAPL' not in names,
                        'A removed stock should not appear in the database')

    def test_get_info(self):
        self.client.send(Message('vault_request', 'add_monitor',
                                 Stock('AAPL')))
        time.sleep(0.1)
        info = StockVault.get_info('AAPL')
        self.assertTrue(
            info.acronym == 'AAPL',
            'Inserted database element should be able to be found by info grab'
        )
コード例 #3
0
class StateTestCase(unittest.TestCase):
    def setUp(self) -> None:
        self.uut = TestQSM('test')
        self.uut.start()

        self.jcontr = JSONController('test_json', output_directory, 1)
        self.jcontr.start()

        self.client = MessageHandler('client')

    def tearDown(self) -> None:
        self.uut.join()
        self.jcontr.join()
        self.client.join()

    def test_save(self):
        self.client.send(Message('json_request', 'save'))
        time.sleep(1)
        self.assertTrue(
            path.exists(path.join(output_directory, state_save_file)),
            'Saving generates a state file')
        self.assertTrue(
            path.getsize(path.join(output_directory, state_save_file)) > 0,
            'Saving should populate file')

    def test_load(self):
        self.client.send(Message('json_request', 'save'))
        time.sleep(1)
        data = JSONController.load(output_directory)
        self.assertTrue(
            len(data) == 2, "Loading should've created two controllers")

        found = False
        for d in data:
            if d.name == 'test':
                found = True

        self.assertTrue(found,
                        "TestQSM should've been loaded by the controller")

    def test_config_filename(self):
        self.client.send(
            Message('json_config', 'filename', '/tmp/robin_test_2/'))
        self.client.send(Message('json_request', 'save'))
        time.sleep(1)
        self.assertTrue(
            path.exists(path.join('/tmp/robin_test_2/', state_save_file)),
            'Modifying filename, configures to save in new location')

    def test_config_count(self):
        self.client.send(Message('json_config', 'count', 2))
        second_uut = TestQSM('test2')
        second_uut.start()
        self.client.send(Message('json_request', 'save'))
        time.sleep(1)
        data = JSONController.load(output_directory)
        self.assertTrue(
            len(data) == 3,
            "Modifying the count value should've generated three controllers, not {}"
            .format(len(data)))
コード例 #4
0
        second_uut.start()
        self.client.send(Message('json_request', 'save'))
        time.sleep(1)
        data = JSONController.load(output_directory)
        self.assertTrue(
            len(data) == 3,
            "Modifying the count value should've generated three controllers, not {}"
            .format(len(data)))


if __name__ == '__main__':
    # unittest.main()
    uut = TestQSM()
    uut.start()

    jcontr = JSONController('test_json', output_directory, 1)
    jcontr.start()

    client = MessageHandler('client')

    client.send(Message('json_request', 'save'))
    time.sleep(1)
    data = JSONController.load(output_directory)
    assert len(data) == 2

    found = False
    for d in data:
        if isinstance(d, TestQSM):
            found = True
    assert found
コード例 #5
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(Message('monitor_config', 'limit', data['limit']))
コード例 #6
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     trans = StockTransaction(data['id'], '', True, data['price'],
                              data['shares'])
     trans.date = dt.datetime.strptime(data['date'], date_format)
     handler.send(Message('vault_request', 'add_transaction', trans))
コード例 #7
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(Message('monitor_config', 'add', Stock(data['acronym'])))
コード例 #8
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     up = BalanceUpdate(data['amount'])
     up.date = dt.datetime.strptime(data['date'], date_format)
     handler.send(Message('vault_request', 'add_balance_update', up))
コード例 #9
0
class QSM(Process, Dictable):
    def __init__(self, name: str, msg_list: list = None):
        super().__init__()
        self.is_exitting = False
        self.name = name

        self.mappings = {}
        self.setup_states()

        self.msg_list = msg_list if msg_list is not None else []
        if 'all' not in self.msg_list:
            self.msg_list.append('all')

        self.setup_msg_mappings(self.msg_list)

        self.handler = MessageHandler(self.name, self.msg_list)  # Because otherwise we can't join from 'final'
        self.states = Queue()
        self.append_state('init')

    @property
    def dict(self) -> dict:
        print('Converting qsm to dict')
        d = {'name': self.name,
             'msg_list': self.msg_list,
             'handler': self.handler.dict}
        return d

    @staticmethod
    def from_dict(d: dict) -> object:
        sm = QSM(d['name'], d['msg_list'])
        sm.handler = MessageHandler.from_dict(d['handler'])
        sm.append_state('init')
        return sm

    def join(self, timeout: Optional[float] = -1) -> None:
        self.append_state('exit')
        super().join(timeout=timeout)
        self.handler.join()

    def run(self) -> None:
        # sys.stdin = self.cclient
        while not self.is_exitting:
            try:
                s = self.states.get_nowait()
                # print('Going to {}'.format(s['state']))
                if s['payload'] is not None:
                    self.mappings[s['state']](s['payload'])
                else:
                    self.mappings[s['state']]()
            except Empty as _:
                self.mappings['idle']()

    def setup_msg_mappings(self, msg_list: list):
        """Sets up the self.msg_map dictionary, mapping message titles to state names,
        by default, appends '_msg' to msg_list entries"""
        for m in msg_list:
            # print('Setting up message state for {} to {}'.format(m, eval('self.' + m + '_msg')))
            self.mappings[m] = eval('self.' + m + '_msg')

    def all_msg(self, msg: Message):
        if msg.msg == 'save':
            self.handler.send(Message('json_update', self.name, {'dtype': str(type(self).__name__),
                                                                 'package': inspect.getmodulename(
                                                                     inspect.getfile(self.__class__)),
                                                                 'path': str(inspect.getfile(self.__class__)),
                                                                 'data': self.dict}))

    def setup_states(self):
        """Sets up the self.mappings dictionary, mapping state names to state methods,
        by default 'init', 'idle', 'exit', and 'final' states are set up."""
        self.mappings['init'] = self.initial_state
        self.mappings['idle'] = self.idle_state
        self.mappings['exit'] = self.exit_state
        self.mappings['final'] = self.final_state

    def append_state(self, state: str, payload: object = None):
        try:
            # print('Appending {}'.format(state))
            self.states.put_nowait({'state': state, 'payload': payload})
        except Full as _:
            print('{} state queue is full, skipping {}'.format(self.name, state))

    def append_states(self, states: list, payloads: list = None):
        for i, s in enumerate(states):
            p = payloads[i] if payloads is not None else None
            self.append_state(s, p)

    def initial_state(self):
        """This is the first state to execute, always"""
        pass

    def idle_state(self):
        """This is the state the is triggered when the state machine has nowhere to go to."""
        m = self.handler.receive(block=False)
        if m is not None:
            print('Received message {}'.format(m))
            self.append_state(m.title, m)

    def exit_state(self):
        """This stateis triggered when the qsm should exit, enqueues the 'final' state"""
        # print('Exitting')
        self.append_state('final')

    def final_state(self):
        """This is the final state to execute, always"""
        self.is_exitting = True
コード例 #10
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(Message('vault_request', 'remove_stock', ManagedStock('None', data['id'], data['shares'])))
コード例 #11
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     if data['title'] == 'force':
         handler.send(Message('monitor_config', 'update'))
     else:
         super().handle(handler, data)
コード例 #12
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(Message('all', 'load'))
コード例 #13
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(Message('trade_request', 'sell', data))
コード例 #14
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(
         Message(
             'vault_request', 'update_monitor',
             Stock(data['acronym'], data['ask_price'], data['bid_price'],
                   data['ask_size'], data['bid_size'])))
コード例 #15
0
 def handle(self, handler: MessageHandler, data: dict) -> None:
     handler.send(
         Message(
             'vault_request', 'update_stock',
             ManagedStock(data['acronym'], data['id'], data['shares'],
                          data['price'])))