def load_json(self, json_str): """ Load project from JSON. :param json_str: JSON-formatted string representing a project. :return: Nothing """ # project_list elements are tuples containing presentation name and file contents # The format is ["presentationname", ["file1", "file2", ...]"] project_list = json.loads(json_str) # create the real presentations by replacing file list with Presentation objects presentation_list = [] for presentation_tuple in project_list: name = presentation_tuple[0] files = presentation_tuple[1] paths = [] for file in files: path = fh.absolute_path(PathConstants.ABSOLUTE_MEDIA_FOLDER, file) paths.append(path) pres = Presentation(name) pres.presentation_filenames = paths presentation_list.append((name, pres)) self.presentations = presentation_list
def test_binding_slave(self): with patch.object(MasterGUILayout, "notify", return_value=None) as notifier: self.mock_master.add_slave_connection(SlaveConnection(None)) presentation = Presentation() presentation.presentation_filenames = ["aaaa"] self.mock_master.bind_slave_to_presentation(presentation, "localhost:8000") self.assertEqual(self.mock_master.slave_connections["localhost:8000"].presentation.presentation_filenames, ["aaaa"]) self.layout.notify.assert_called_once_with(Notification.PRESENTING_DISABLED, False)
def test_setup_project_with_nonexistent_file(self): project = Project() name1 = "test1" presentation1 = Presentation() presentation1.set_files(["abadababababababbabababbababab.jpg", "b.jpg"]) project.presentations.append((name1, presentation1)) self.mock_master.setup_project(project, PathConstants.ABSOLUTE_TEST_MEDIA_FOLDER) self.mock_master.layout.setup_project.assert_not_called() self.assertNotEqual(self.mock_master.project, project)
def __init__(self, layout=None): """ Constructor The master_connection is a RemuTCP object """ self.presentation_ended = False self.presentation = Presentation() self.layout = layout self.master_connection = None self.source = '' self.beacon = Beacon() self.beacon.start_beaconing()
def new_presentation_to_overview(self, name, given_presentation=None): """ Creates a new GUI element for a single presentation. Is used when creating a new presentation and when loading a saved presentation :param name: :return: Nothing """ master = App.get_running_app().servicemode if given_presentation is None: given_presentation = Presentation(name) self.project.presentations.append((name, given_presentation)) new_slave_presentation = SlavePresentation(given_presentation) #button = Button(text=name, size_hint=(1, 0.2)) #lf = lambda a: BindPresentationToSlavePopUp(master.slave_connections.keys(), new_presentation.get_presentation_from_widgets(), master, button).open() #button.on_press = lf self.slave_buttons[name] = SlavePresentationButton(text=name, size_hint=(1, 0.2)) self.slave_buttons[name].bind( on_press=lambda a: self.slave_button_action( new_slave_presentation.get_presentation_from_widgets(), self. slave_buttons[name])) self.slave_presentations[name] = new_slave_presentation #self.project.presentations.append((name, given_presentation)) self.ids.slave_names.add_widget(self.slave_buttons[name]) self.ids.slave_presentations.add_widget(self.slave_presentations[name]) self.max = max(self.max, len(given_presentation)) self.update_presentation_widths()
def setUp(self): self.filepath1 = "fruitful/workflow/is/nice.jpg" self.filename1 = "nice.jpg" self.filename2 = self.a_hundred_chars_long_string() self.filename3 = "somethingmorepleasantthanscreaming.mp4" self.pres = Presentation() self.layout = SlavePresentation(self.pres) self.draggable_element = SlaveVisualProperty("nice.jpg")
def create_test_presentation(self, project): name1 = "kek" presentation1 = Presentation() presentation1.set_files(["a.jpg", "b.jpg"]) name2 = "heck" presentation2 = Presentation() presentation2.set_files(["b.jpg", "a.jpg"]) project.presentations.append((name1, presentation1)) project.presentations.append((name2, presentation2))
def test_setup_project_with_valid_project(self): project = Project() name1 = "test1" presentation1 = Presentation() presentation1.set_files(["a.jpg", "b.jpg"]) name2 = "test2" presentation2 = Presentation() presentation2.set_files(["b.jpg", "a.jpg"]) project.presentations.append((name1, presentation1)) project.presentations.append((name2, presentation2)) self.mock_master.setup_project(project, PathConstants.ABSOLUTE_TEST_MEDIA_FOLDER) self.mock_master.layout.setup_project.assert_called_once_with(project) self.assertEqual(self.mock_master.project, project)
def test_set_presentation(self): slave = Slave() slave.set_presentation(Presentation()) self.assertEqual(slave.presentation.__class__.__name__, "Presentation")
def test_handle_show_next_response(self): self.sc.master = MagicMock(Master) self.sc.presentation = Presentation() self.sc.handle_show_next_response({MessageKeys.index_key: 1}) self.sc.master.notify.assert_called_once_with(Notification.PRESENTATION_STATUS_CHANGE, 1)
def setUp(self): self.slave_overview = ProjectOverview() self.slave_connection_mock = SlaveConnection(Mock(Master)) presentation = Presentation() presentation.set_files(["a.jpg", "b.jpg", "g.mp4", "test_text.txt", "test_text2.txt"]) self.slave_connection_mock.set_presentation(presentation)
def createPresentation(self): presentation = Presentation() presentation.set_source_folder(PathConstants.TEST_MEDIA_FOLDER) presentation.set_files(["mokomoko", "holoholo"]) presentation.load() return presentation
class PresentationTest(unittest.TestCase): def setUp(self): self.presentation = Presentation() self.presentation_filenames = ["a.jpg", "g.mp4", "test_text.txt"] def set_presentation_elements(self, presentation_filenames): self.presentation.set_source_folder(PathConstants.TEST_MEDIA_FOLDER) self.presentation.set_files(presentation_filenames) self.presentation.get_presentation_elements_from_path() def test_init_works_as_inteded(self): self.assertEqual(self.presentation.get_presentation_content(), []) self.assertEqual(self.presentation.presentation_elements, []) self.assertEqual(-1, self.presentation.index) self.assertEqual(self.presentation.media_path, PathConstants.MEDIA_FOLDER) def test_get_presentation_elements_from_path(self): self.set_presentation_elements(self.presentation_filenames) self.assertEqual(self.presentation_filenames, self.presentation.get_presentation_content()) self.presentation.get_presentation_elements_from_path() self.assertEqual(len(self.presentation.presentation_elements), 3) for i in range(0, len(self.presentation.presentation_elements)): self.assertEqual(self.presentation.presentation_elements[i].source_file, os.path.join(PathConstants.TEST_MEDIA_FOLDER, self.presentation_filenames[i])) def test_pic_file_is_supported(self): pic_file = os.path.join(PathConstants.TEST_MEDIA_FOLDER, "a.jpg") self.assertTrue(Presentation.filetype_is_supported(pic_file)) def test_not_pic_file_is_not_supported(self): not_pic_file = os.path.join(PathConstants.TEST_MEDIA_FOLDER, "test_text.txt") self.assertFalse(Presentation.filetype_is_supported(not_pic_file)) def test_get_function_when_presentation_elements_is_none(self): self.assertIsNone(self.presentation.get(0)) def test_get_function_lower_boundary(self): self.set_presentation_elements(self.presentation_filenames) self.assertIsNone(self.presentation.get(-1)) def test_get_function_upper_boundary(self): self.set_presentation_elements(self.presentation_filenames) self.assertIsNone(self.presentation.get(len(self.presentation_filenames))) def test_get_first_element(self): self.set_presentation_elements(self.presentation_filenames) self.assertEqual(self.presentation.get(0).source_file, os.path.join(PathConstants.TEST_MEDIA_FOLDER, self.presentation_filenames[0])) def test_get_last_element(self): self.set_presentation_elements(self.presentation_filenames) self.assertEqual(self.presentation.get(len(self.presentation.presentation_elements) - 1).source_file, os.path.join(PathConstants.TEST_MEDIA_FOLDER, self.presentation_filenames[len(self.presentation_filenames) - 1])) def test_get_message_dictionary(self): self.set_presentation_elements(self.presentation_filenames) dickie = self.presentation.get_message_dictionary() self.assertEqual(dickie[MessageKeys.index_key], -1) self.assertEqual(dickie[MessageKeys.presentation_content_key], self.presentation_filenames) self.presentation.get_next() dickie = self.presentation.get_message_dictionary() self.assertEqual(dickie[MessageKeys.index_key], 0) self.assertEqual(dickie[MessageKeys.presentation_content_key], self.presentation_filenames)
def test_not_pic_file_is_not_supported(self): not_pic_file = os.path.join(PathConstants.TEST_MEDIA_FOLDER, "test_text.txt") self.assertFalse(Presentation.filetype_is_supported(not_pic_file))
def test_pic_file_is_supported(self): pic_file = os.path.join(PathConstants.TEST_MEDIA_FOLDER, "a.jpg") self.assertTrue(Presentation.filetype_is_supported(pic_file))
def setUp(self): self.presentation = Presentation() self.presentation_filenames = ["a.jpg", "g.mp4", "test_text.txt"]
class Slave: """ CONTAINS SLAVE'S ADMINISTRATIVE AND PRESENTATIONAL DATA """ def __init__(self, layout=None): """ Constructor The master_connection is a RemuTCP object """ self.presentation_ended = False self.presentation = Presentation() self.layout = layout self.master_connection = None self.source = '' self.beacon = Beacon() self.beacon.start_beaconing() def set_master_connection(self, master_connection): """ Sets the slave's master_connection, it is a listening RemuTCP connection """ self.master_connection = master_connection self.master_connection.parent = self self.master_connection.run() def set_layout(self, new_layout): self.layout = new_layout def reset_presentation(self): self.source = '' self.presentation.reset() def notify_file_transfer_completed(self): """ Is used when the file transfer is ready to load the presentation :return: Nothing """ self.presentation.load() if len(self.presentation.presentation_elements ) == 0 else self.presentation.reload() def set_presentation(self, presentation): """ Sets the slave's presentation """ self.presentation = presentation def handle_show_next(self, msg): """ Handles requests to show the next picture in the presentation, uses a callback to tell the layout to update its view. Returns a confirmation to master """ if self.presentation_ended: return self.create_response(Command.SHOW_NEXT.value, {MessageKeys.index_key: -1}) #self.load_presentation() current = self.presentation.get_next() if self.layout: if current is not None: self.layout.set_visible_widget(current) else: Logger.debug("Slave: Presentation ended") self.presentation_ended = True self.layout.reset_presentation() return self.create_response( Command.SHOW_NEXT.value, {MessageKeys.index_key: self.presentation.index}) def handle_invalid_command(self, msg): """ Handles invalid requests made by master, simply returns acknowledgement of an invalid command without changing anything """ return self.create_response(Command.INVALID_COMMAND.value) def handle_ending_presentation(self, msg): """ Handles the ending of the presentation. """ app = App.get_running_app() self.load_presentation() self.layout.reset_presentation() if app.root is not None: #This is an ugly hack to make the tests work. Don't delete pls. Thank you. self.layout = app.root.get_current_layout() self.presentation_ended = True return self.create_response(Command.END_PRESENTATION.value) def handle_closing_connection(self, msg): """ Handles master closing its connection to the slave, doesn't close slave's listening and doesn't reply to the message because the master doesn't have a connection to the slave anymore """ if self.presentation.get_presentation_content(): self.presentation.reset() self.layout.reset_presentation() @staticmethod def create_response(command, metadata=None): """ Creates a instance of Message based on the given command """ resp = Message() resp.set_field(MessageKeys.response_key, command) if metadata is not None: for key, value in metadata.items(): resp.set_field(key, value) return resp def retrieve_files_over_ftp(self, host, port, subpath): """ Create a RemuFTPClient to retrieve files from a host :param host: the server's ip-address :param port: the server's port :param subpath: the subpath on the server to retrieve files from :return: doesn't return anything """ write_path = os.path.join(os.getcwd(), PathConstants.MEDIA_FOLDER) if not os.path.isdir(write_path): os.mkdir(write_path) client = RemuFTPClient(host, port, subpath, write_path, self) client.connect() def handle_file_retrieval(self, msg): """ Handles a command to retrieve files from a host :param msg: a Message object :return: a response to the received message """ Logger.info("Slave: Retrieving files") params = msg.get_field(MessageKeys.params_key) host = msg.get_field(MessageKeys.sender_key) port = params[MessageKeys.ftp_port_key] subpath = params[MessageKeys.ftp_subpath_key] self.presentation.set_files( params[MessageKeys.presentation_content_key]) self.presentation.reset() self.layout.init_presentation() self.retrieve_files_over_ftp(host, port, subpath) self.presentation_ended = False return self.create_response(msg.get_command()) def handle_received_presentation(self, msg): """Deprecated""" pass #print("Presentation received") #if MessageKeys.presentation_content_key in msg.fields: # print("asd") # Messagehandler """ Python's replacement for a switch-case: gives methods given by the Command-enumerator, essentially just a dictionary that has function calls """ messagehandler = { Command.SHOW_NEXT.value: handle_show_next, Command.END_PRESENTATION.value: handle_ending_presentation, Command.INVALID_COMMAND.value: handle_invalid_command, Command.DROP_CONNECTION.value: handle_closing_connection, Command.RETRIEVE_FILES.value: handle_file_retrieval, #Command.SEND_PRESENTATION.value: handle_received_presentation } def handle_message(self, msg): """ Handles the responses to master's requests """ Logger.debug("Slave: Trying to parse") if MessageKeys.command_key in msg.fields: Logger.info("Slave: Message command: %s", str(msg.get_command())) return self.messagehandler[msg.get_command()](self, msg) return self.handle_invalid_command(msg) def connection_established(self, address): pass def load_presentation(self): """ Load the presentations content """ if len(self.presentation.get_presentation_content()) == 0: self.presentation.load() def close_all_connections(self): """ Closes all networking protocols the slave uses """ self.close_TCP_connections() self.close_UDP_connection() def close_TCP_connections(self): """ Uses a RemuTCP method to close the listening connection """ if self.master_connection is not None: self.master_connection.end_connection() def close_UDP_connection(self): """ Uses a RemuUDP method to stop listening to the UDP connection """ self.beacon.stop_beaconing() def handle_exception(self, message, exception): self.layout.error(message, exception)