111 lines
3.7 KiB
Python
111 lines
3.7 KiB
Python
|
from threading import Thread
|
||
|
from typing import Dict, List
|
||
|
|
||
|
from ...StreamResponseHandler import StreamResponseHandler
|
||
|
from ...utils import http_request, generic_handle_stream_response
|
||
|
from .Controller import Controller
|
||
|
|
||
|
|
||
|
class TransactionController(Controller, StreamResponseHandler):
|
||
|
def __init__(self, model, app):
|
||
|
super().__init__(model, app)
|
||
|
self.op_idx = 0
|
||
|
self.error_messages = []
|
||
|
|
||
|
def start(self):
|
||
|
Thread(target=self._start_txn).start()
|
||
|
|
||
|
def _start_txn(self):
|
||
|
resp = http_request(
|
||
|
self.model.http_verb,
|
||
|
self.model.req_path,
|
||
|
**self.model.req_kwargs
|
||
|
)
|
||
|
data = generic_handle_stream_response(resp, self.model.operations, self)
|
||
|
self.write_extra_txn_info(data)
|
||
|
|
||
|
# to be overridden in child classes if desired
|
||
|
def write_extra_txn_info(self, data: List[Dict]):
|
||
|
pass
|
||
|
|
||
|
def _show_lines(self, lines):
|
||
|
num_lines = len(lines)
|
||
|
# Since the message_text is at the bottom of the window,
|
||
|
# we want to add sufficient padding to the bottom of the text
|
||
|
lines += [''] * max(4 - num_lines, 0)
|
||
|
for i, line in enumerate(lines):
|
||
|
if type(line) is str:
|
||
|
lines[i] = line + '\n'
|
||
|
else: # tuple (attr, text)
|
||
|
lines[i] = (line[0], line[1] + '\n')
|
||
|
self.view.message_text.set_text(lines)
|
||
|
|
||
|
def _abort(self):
|
||
|
for elem in self.view.right_col_elems[self.op_idx:]:
|
||
|
elem.set_text(('red', 'ABORTED'))
|
||
|
self.view.enable_next_button()
|
||
|
|
||
|
def begin(self):
|
||
|
pass
|
||
|
|
||
|
def handle_non_200(self, resp):
|
||
|
def target():
|
||
|
self._abort()
|
||
|
lines = ['An error occurred:']
|
||
|
if resp.headers.get('content-type') == 'application/json':
|
||
|
err_msg = resp.json()['error']
|
||
|
else:
|
||
|
err_msg = resp.text
|
||
|
lines.extend(err_msg.split('\n'))
|
||
|
self._show_lines(lines)
|
||
|
self.app.run_in_main_loop(target)
|
||
|
|
||
|
def handle_aborted(self, err_msg):
|
||
|
def target():
|
||
|
self._abort()
|
||
|
lines = [
|
||
|
'The transaction was rolled back.',
|
||
|
'The error was:',
|
||
|
'',
|
||
|
*err_msg.split('\n'),
|
||
|
]
|
||
|
self._show_lines(lines)
|
||
|
self.app.run_in_main_loop(target)
|
||
|
|
||
|
def handle_completed(self):
|
||
|
def target():
|
||
|
lines = ['Transaction successfully completed.']
|
||
|
if len(self.error_messages) > 0:
|
||
|
lines.append('There were some errors:')
|
||
|
for msg in self.error_messages:
|
||
|
lines.extend(msg.split('\n'))
|
||
|
self._show_lines(lines)
|
||
|
self.view.enable_next_button()
|
||
|
self.app.run_in_main_loop(target)
|
||
|
|
||
|
def handle_successful_operation(self):
|
||
|
def target():
|
||
|
self.view.right_col_elems[self.op_idx].set_text(('green', 'Done'))
|
||
|
self.op_idx += 1
|
||
|
self.app.run_in_main_loop(target)
|
||
|
|
||
|
def handle_failed_operation(self, err_msg):
|
||
|
def target():
|
||
|
self.view.right_col_elems[self.op_idx].set_text(('red', 'Failed'))
|
||
|
self.op_idx += 1
|
||
|
if err_msg is not None:
|
||
|
self.error_messages.append(err_msg)
|
||
|
self.app.run_in_main_loop(target)
|
||
|
|
||
|
def handle_skipped_operation(self):
|
||
|
def target():
|
||
|
self.view.right_col_elems[self.op_idx].set_text('Skipped')
|
||
|
self.op_idx += 1
|
||
|
self.app.run_in_main_loop(target)
|
||
|
|
||
|
def handle_unrecognized_operation(self, operation):
|
||
|
def target():
|
||
|
self.error_messages.append('Unrecognized operation: ' + operation)
|
||
|
self.op_idx += 1
|
||
|
self.app.run_in_main_loop(target)
|