Example #1
0
    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
Example #2
0
 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)
Example #3
0
    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)
Example #4
0
 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()
Example #5
0
 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()
Example #6
0
 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")
Example #7
0
    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))
Example #8
0
    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)
Example #9
0
 def test_set_presentation(self):
     slave = Slave()
     slave.set_presentation(Presentation())
     self.assertEqual(slave.presentation.__class__.__name__, "Presentation")
Example #10
0
 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)
Example #11
0
 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)
Example #12
0
 def createPresentation(self):
     presentation = Presentation()
     presentation.set_source_folder(PathConstants.TEST_MEDIA_FOLDER)
     presentation.set_files(["mokomoko", "holoholo"])
     presentation.load()
     return presentation
Example #13
0
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)
Example #14
0
 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))
Example #15
0
 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))
Example #16
0
 def setUp(self):
     self.presentation = Presentation()
     self.presentation_filenames = ["a.jpg", "g.mp4", "test_text.txt"]
Example #17
0
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)