class TestFigureService(TransactionalTestCase):
    """
    Tests for the figure service
    """
    def transactional_setup_method(self):
        self.figure_service = FigureService()
        self.user = TestFactory.create_user()
        self.project = TestFactory.create_project(admin=self.user)
        self.files_helper = FilesHelper()


    def transactional_teardown_method(self):
        self.delete_project_folders()


    def assertCanReadImage(self, image_path):
        try:
            Image.open(image_path).load()
        except (IOError, ValueError):
            raise AssertionError("Could not open %s as a image" % image_path)


    def store_test_png(self):
        self.figure_service.store_result_figure(self.project, self.user, "png", IMG_DATA, image_name="test-figure")


    def retrieve_images(self):
        figures_by_session, _ = self.figure_service.retrieve_result_figures(self.project, self.user)
        # flatten image session grouping
        figures = []
        for fg in figures_by_session.itervalues():
            figures.extend(fg)
        return figures


    def test_store_image(self):
        self.store_test_png()


    def test_store_image_from_operation(self):
        # test that image can be retrieved from operation
        test_operation = TestFactory.create_operation(test_user=self.user, test_project=self.project)

        self.figure_service.store_result_figure(self.project, self.user, "png",
                                                IMG_DATA, operation_id=test_operation.id)
        figures = dao.get_figures_for_operation(test_operation.id)
        assert 1 == len(figures)
        image_path = self.files_helper.get_images_folder(self.project.name)
        image_path = os.path.join(image_path, figures[0].file_path)
        self.assertCanReadImage(image_path)


    def test_store_and_retrieve_image(self):
        self.store_test_png()
        figures = self.retrieve_images()
        assert 1 == len(figures)
        image_path = utils.url2path(figures[0].file_path)
        self.assertCanReadImage(image_path)


    def test_load_figure(self):
        self.store_test_png()
        figures = self.retrieve_images()
        self.figure_service.load_figure(figures[0].id)


    def test_edit_figure(self):
        session_name = 'the altered ones'
        name = 'altered'
        self.store_test_png()
        figures = self.retrieve_images()
        self.figure_service.edit_result_figure(figures[0].id, session_name=session_name, name=name)
        figures_by_session, _ = self.figure_service.retrieve_result_figures(self.project, self.user)
        assert [session_name] == figures_by_session.keys()
        assert name == figures_by_session.values()[0][0].name


    def test_remove_figure(self):
        self.store_test_png()
        figures = self.retrieve_images()
        assert 1 == len(figures)
        self.figure_service.remove_result_figure(figures[0].id)
        figures = self.retrieve_images()
        assert 0 == len(figures)
class FigureServiceTest(TransactionalTestCase):
    """
    Tests for the figure service
    """
    def setUp(self):
        self.figure_service = FigureService()
        self.user = TestFactory.create_user()
        self.project = TestFactory.create_project(admin=self.user)
        self.files_helper = FilesHelper()

    def tearDown(self):
        self.delete_project_folders()

    def assertCanReadImage(self, image_path):
        try:
            Image.open(image_path).load()
        except (IOError, ValueError):
            self.fail("Could not open %s as a image" % image_path)

    def store_test_png(self):
        self.figure_service.store_result_figure(self.project,
                                                self.user,
                                                "png",
                                                IMG_DATA,
                                                image_name="test-figure")

    def retrieve_images(self):
        figures_by_session, _ = self.figure_service.retrieve_result_figures(
            self.project, self.user)
        # flatten image session grouping
        figures = []
        for fg in figures_by_session.itervalues():
            figures.extend(fg)
        return figures

    def test_store_image(self):
        self.store_test_png()

    def test_store_image_from_operation(self):
        # test that image can be retrieved from operation
        test_operation = TestFactory.create_operation(
            test_user=self.user, test_project=self.project)

        self.figure_service.store_result_figure(self.project,
                                                self.user,
                                                "png",
                                                IMG_DATA,
                                                operation_id=test_operation.id)
        figures = dao.get_figures_for_operation(test_operation.id)
        self.assertEqual(1, len(figures))
        image_path = self.files_helper.get_images_folder(self.project.name)
        image_path = os.path.join(image_path, figures[0].file_path)
        self.assertCanReadImage(image_path)

    def test_store_and_retrieve_image(self):
        self.store_test_png()
        figures = self.retrieve_images()
        self.assertEqual(1, len(figures))
        image_path = utils.url2path(figures[0].file_path)
        self.assertCanReadImage(image_path)

    def test_load_figure(self):
        self.store_test_png()
        figures = self.retrieve_images()
        self.figure_service.load_figure(figures[0].id)

    def test_edit_figure(self):
        session_name = 'the altered ones'
        name = 'altered'
        self.store_test_png()
        figures = self.retrieve_images()
        self.figure_service.edit_result_figure(figures[0].id,
                                               session_name=session_name,
                                               name=name)
        figures_by_session, _ = self.figure_service.retrieve_result_figures(
            self.project, self.user)
        self.assertEqual([session_name], figures_by_session.keys())
        self.assertEqual(name, figures_by_session.values()[0][0].name)

    def test_remove_figure(self):
        self.store_test_png()
        figures = self.retrieve_images()
        self.assertEqual(1, len(figures))
        self.figure_service.remove_result_figure(figures[0].id)
        figures = self.retrieve_images()
        self.assertEqual(0, len(figures))
示例#3
0
class TestFigureService(TransactionalTestCase):
    """
    Tests for the figure service
    """
    def transactional_setup_method(self):
        self.figure_service = FigureService()
        self.user = TestFactory.create_user()
        self.project = TestFactory.create_project(admin=self.user)
        self.files_helper = FilesHelper()

    def transactional_teardown_method(self):
        self.delete_project_folders()

    def assertCanReadImage(self, image_path):
        try:
            Image.open(image_path).load()
        except (IOError, ValueError):
            raise AssertionError("Could not open %s as a image" % image_path)

    def store_test_png(self):
        self.figure_service.store_result_figure(self.project, self.user, "png",
                                                IMG_DATA, "test-figure")

    def retrieve_images(self):
        figures_by_session, _ = self.figure_service.retrieve_result_figures(
            self.project, self.user)
        # flatten image session grouping
        figures = []
        for fg in figures_by_session.values():
            figures.extend(fg)
        return figures

    def test_store_image(self):
        self.store_test_png()

    def test_store_and_retrieve_image(self):
        self.store_test_png()
        figures = self.retrieve_images()
        assert 1 == len(figures)
        image_path = utils.url2path(figures[0].file_path)
        self.assertCanReadImage(image_path)

    def test_load_figure(self):
        self.store_test_png()
        figures = self.retrieve_images()
        self.figure_service.load_figure(figures[0].id)

    def test_edit_figure(self):
        session_name = 'the altered ones'
        name = 'altered'
        self.store_test_png()
        figures = self.retrieve_images()
        self.figure_service.edit_result_figure(figures[0].id,
                                               session_name=session_name,
                                               name=name)
        figures_by_session, _ = self.figure_service.retrieve_result_figures(
            self.project, self.user)
        assert [session_name] == list(figures_by_session)
        assert name == list(figures_by_session.values())[0][0].name

    def test_remove_figure(self):
        self.store_test_png()
        figures = self.retrieve_images()
        assert 1 == len(figures)
        self.figure_service.remove_result_figure(figures[0].id)
        figures = self.retrieve_images()
        assert 0 == len(figures)
示例#4
0
class FigureController(ProjectController):
    """
    Resulting Figures are user-saved figures with specific visualizers or TVB pages which are considered important.
    """
    def __init__(self):
        ProjectController.__init__(self)
        self.storage_interface = StorageInterface()
        self.figure_service = FigureService()

    @cherrypy.expose
    @handle_error(redirect=False)
    @check_user
    @context_selected
    def storeresultfigure(self, img_type, **kwargs):
        """Create preview for current displayed canvas and 
        store image in current session, for future comparison."""
        project = common.get_current_project()
        user = common.get_logged_user()
        suggested_name = kwargs.get("suggestedName")
        self.figure_service.store_result_figure(project, user, img_type,
                                                kwargs['export_data'],
                                                suggested_name)

    @expose_page
    @context_selected
    def displayresultfigures(self, selected_session='all_sessions'):
        """ Collect and display saved previews, grouped by session."""
        project = common.get_current_project()
        user = common.get_logged_user()
        data, all_sessions_info = self.figure_service.retrieve_result_figures(
            project, user, selected_session)
        manage_figure_title = "Figures for " + str(
            selected_session) + " category"
        if selected_session == 'all_sessions':
            manage_figure_title = "Figures for all categories"
        template_specification = dict(mainContent="project/figures_display",
                                      title="Stored Visualizer Previews",
                                      controlPage=None,
                                      displayControl=False,
                                      selected_sessions_data=data,
                                      all_sessions_info=all_sessions_info,
                                      selected_session=selected_session,
                                      manageFigureTitle=manage_figure_title)
        template_specification = self.fill_default_attributes(
            template_specification, subsection='figures')
        return template_specification

    @cherrypy.expose
    @handle_error(redirect=True)
    @check_user
    @context_selected
    def editresultfigures(self,
                          remove_figure=False,
                          rename_session=False,
                          remove_session=False,
                          **data):
        """
        This method knows how to handle the following actions:
        remove figure, update figure, remove session and update session.
        """
        project = common.get_current_project()
        user = common.get_logged_user()

        redirect_url = '/project/figure/displayresultfigures'
        if "selected_session" in data and data[
                "selected_session"] is not None and len(
                    data["selected_session"]):
            redirect_url += '/' + data["selected_session"]
            del data["selected_session"]
        figure_id = None
        if "figure_id" in data:
            figure_id = data["figure_id"]
            del data["figure_id"]

        if cherrypy.request.method == 'POST' and rename_session:
            successfully_updated = True
            if "old_session_name" in data and "new_session_name" in data:
                figures_dict, _ = self.figure_service.retrieve_result_figures(
                    project, user, data["old_session_name"])
                for _key, value in figures_dict.items():
                    for figure in value:
                        new_data = {
                            "name": figure.name,
                            "session_name": data["new_session_name"]
                        }
                        success = self._update_figure(figure.id, **new_data)
                        if not success:
                            successfully_updated = False
                if successfully_updated:
                    common.set_info_message(
                        "The session was successfully updated!")
                else:
                    common.set_error_message(
                        "The session was not successfully updated! "
                        "There could be some figures that still refer to the old session."
                    )
        elif cherrypy.request.method == 'POST' and remove_session:
            successfully_removed = True
            if "old_session_name" in data:
                figures_dict, _ = self.figure_service.retrieve_result_figures(
                    project, user, data["old_session_name"])
                for _key, value in figures_dict.items():
                    for figure in value:
                        success = self.figure_service.remove_result_figure(
                            figure.id)
                        if not success:
                            successfully_removed = False
                if successfully_removed:
                    common.set_info_message(
                        "The session was removed successfully!")
                else:
                    common.set_error_message(
                        "The session was not entirely removed!")
        elif cherrypy.request.method == 'POST' and remove_figure and figure_id is not None:
            success = self.figure_service.remove_result_figure(figure_id)
            if success:
                common.set_info_message("Figure removed successfully!")
            else:
                common.set_error_message("Figure could not be removed!")
        elif figure_id is not None:
            self._update_figure(figure_id, **data)
        raise cherrypy.HTTPRedirect(redirect_url)

    def _update_figure(self, figure_id, **data):
        """
        Updates the figure details to the given data.
        """
        try:
            data = EditPreview().to_python(data)
            self.figure_service.edit_result_figure(figure_id, **data)
            common.set_info_message('Figure details updated successfully.')
            return True
        except formencode.Invalid as excep:
            self.logger.debug(excep)
            common.set_error_message(excep.message)
            return False

    @cherrypy.expose
    @handle_error(redirect=False)
    @check_user
    def downloadimage(self, figure_id):
        """
        Allow a user to download a figure.
        """
        figure = self.figure_service.load_figure(figure_id)
        image_folder = self.storage_interface.get_images_folder(
            figure.project.name)
        figure_path = os.path.join(image_folder, figure.file_path)
        return serve_file(figure_path, "image/" + figure.file_format,
                          "attachment",
                          "%s.%s" % (figure.name, figure.file_format))

    @cherrypy.expose
    @handle_error(redirect=False)
    @using_template("overlay")
    @check_user
    def displayzoomedimage(self, figure_id):
        """
        Displays the image with the specified id in an overlay dialog.
        """
        figure = self.figure_service.load_figure(figure_id)
        figures_folder = self.storage_interface.get_images_folder(
            figure.project.name)
        figure_full_path = os.path.join(figures_folder, figure.file_path)
        figure_file_path = utils.path2url_part(figure_full_path)
        description = figure.session_name + " - " + figure.name
        template_dictionary = dict(figure_file_path=figure_file_path)
        return self.fill_overlay_attributes(template_dictionary, "Detail",
                                            description,
                                            "project/figure_zoom_overlay",
                                            "lightbox")
class FigureController(ProjectController):
    """
    Resulting Figures are user-saved figures with specific visualizers or TVB pages which are considered important.
    """

    def __init__(self):
        ProjectController.__init__(self)
        self.files_helper = FilesHelper()
        self.figure_service = FigureService()


    @cherrypy.expose
    @handle_error(redirect=False)
    @check_user
    @context_selected
    def storeresultfigure(self, img_type, **kwargs):
        """Create preview for current displayed canvas and 
        store image in current session, for future comparison."""
        project = common.get_current_project()
        user = common.get_logged_user()
        operation_id = kwargs.get("operationId")
        suggested_name = kwargs.get("suggestedName")
        self.figure_service.store_result_figure(project, user, img_type, kwargs['export_data'],
                                                image_name=suggested_name, operation_id=operation_id)


    @expose_page
    @context_selected
    def displayresultfigures(self, selected_session='all_sessions'):
        """ Collect and display saved previews, grouped by session."""
        project = common.get_current_project()
        user = common.get_logged_user()
        data, all_sessions_info = self.figure_service.retrieve_result_figures(project, user, selected_session)
        manage_figure_title = "Figures for " + str(selected_session) + " category"
        if selected_session == 'all_sessions':
            manage_figure_title = "Figures for all categories"
        template_specification = dict(mainContent="project/figures_display", title="Stored Visualizer Previews",
                                      controlPage=None, displayControl=False, selected_sessions_data=data,
                                      all_sessions_info=all_sessions_info, selected_session=selected_session,
                                      manageFigureTitle=manage_figure_title)
        template_specification = self.fill_default_attributes(template_specification, subsection='figures')
        return template_specification


    @cherrypy.expose
    @handle_error(redirect=True)
    @check_user
    @context_selected
    def editresultfigures(self, remove_figure=False, rename_session=False, remove_session=False, **data):
        """
        This method knows how to handle the following actions:
        remove figure, update figure, remove session and update session.
        """
        project = common.get_current_project()
        user = common.get_logged_user()

        redirect_url = '/project/figure/displayresultfigures'
        if "selected_session" in data and data["selected_session"] is not None and len(data["selected_session"]):
            redirect_url += '/' + data["selected_session"]
            del data["selected_session"]
        figure_id = None
        if "figure_id" in data:
            figure_id = data["figure_id"]
            del data["figure_id"]

        if cherrypy.request.method == 'POST' and rename_session:
            successfully_updated = True
            if "old_session_name" in data and "new_session_name" in data:
                figures_dict, _ = self.figure_service.retrieve_result_figures(project, user, data["old_session_name"])
                for _key, value in figures_dict.iteritems():
                    for figure in value:
                        new_data = {"name": figure.name, "session_name": data["new_session_name"]}
                        success = self._update_figure(figure.id, **new_data)
                        if not success:
                            successfully_updated = False
                if successfully_updated:
                    common.set_info_message("The session was successfully updated!")
                else:
                    common.set_error_message("The session was not successfully updated! "
                                             "There could be some figures that still refer to the old session.")
        elif cherrypy.request.method == 'POST' and remove_session:
            successfully_removed = True
            if "old_session_name" in data:
                figures_dict, _ = self.figure_service.retrieve_result_figures(project, user, data["old_session_name"])
                for _key, value in figures_dict.iteritems():
                    for figure in value:
                        success = self.figure_service.remove_result_figure(figure.id)
                        if not success:
                            successfully_removed = False
                if successfully_removed:
                    common.set_info_message("The session was removed successfully!")
                else:
                    common.set_error_message("The session was not entirely removed!")
        elif cherrypy.request.method == 'POST' and remove_figure and figure_id is not None:
            success = self.figure_service.remove_result_figure(figure_id)
            if success:
                common.set_info_message("Figure removed successfully!")
            else:
                common.set_error_message("Figure could not be removed!")
        elif figure_id is not None:
            self._update_figure(figure_id, **data)
        raise cherrypy.HTTPRedirect(redirect_url)


    def _update_figure(self, figure_id, **data):
        """
        Updates the figure details to the given data.
        """
        try:
            data = EditPreview().to_python(data)
            self.figure_service.edit_result_figure(figure_id, **data)
            common.set_info_message('Figure details updated successfully.')
            return True
        except formencode.Invalid, excep:
            self.logger.debug(excep)
            common.set_error_message(excep.message)
            return False