Exemple #1
0
 def __init__(self, app):
     super().__init__(app)
     self.page_manager = PageManager(app)
     self.history_manager = HistoryManager(app)
     self.history_serializer = HistorySerializer(self.app)
     self.hda_manager = HDAManager(app)
     self.workflow_manager = WorkflowsManager(app)
Exemple #2
0
 def __init__(self, app):
     super(PageController, self).__init__(app)
     self.page_manager = PageManager(app)
     self.history_manager = HistoryManager(app)
     self.history_serializer = HistorySerializer(self.app)
     self.hda_manager = HDAManager(app)
Exemple #3
0
class PageController(BaseUIController, SharableMixin,
                     UsesStoredWorkflowMixin, UsesVisualizationMixin, UsesItemRatings):

    _page_list = PageListGrid()
    _all_published_list = PageAllPublishedGrid()
    _history_selection_grid = HistorySelectionGrid()
    _workflow_selection_grid = WorkflowSelectionGrid()
    _datasets_selection_grid = HistoryDatasetAssociationSelectionGrid()
    _page_selection_grid = PageSelectionGrid()
    _visualization_selection_grid = VisualizationSelectionGrid()

    def __init__(self, app):
        super(PageController, self).__init__(app)
        self.page_manager = PageManager(app)
        self.history_manager = HistoryManager(app)
        self.history_serializer = HistorySerializer(self.app)
        self.hda_manager = HDAManager(app)

    @web.expose
    @web.json
    @web.require_login()
    def list(self, trans, *args, **kwargs):
        """ List user's pages. """
        # Handle operation
        if 'operation' in kwargs and 'id' in kwargs:
            session = trans.sa_session
            operation = kwargs['operation'].lower()
            ids = util.listify(kwargs['id'])
            for id in ids:
                item = session.query(model.Page).get(self.decode_id(id))
                if operation == "delete":
                    item.deleted = True
            session.flush()

        # Build grid dictionary.
        grid = self._page_list(trans, *args, **kwargs)
        grid['shared_by_others'] = self._get_shared(trans)
        return grid

    @web.expose
    @web.json
    def list_published(self, trans, *args, **kwargs):
        grid = self._all_published_list(trans, *args, **kwargs)
        grid['shared_by_others'] = self._get_shared(trans)
        return grid

    def _get_shared(self, trans):
        """Identify shared pages"""
        shared_by_others = trans.sa_session \
            .query(model.PageUserShareAssociation) \
            .filter_by(user=trans.get_user()) \
            .join(model.Page.table) \
            .filter(model.Page.deleted == false()) \
            .order_by(desc(model.Page.update_time)) \
            .all()
        return [{'username' : p.page.user.username,
                 'slug'     : p.page.slug,
                 'title'    : p.page.title} for p in shared_by_others]

    @web.legacy_expose_api
    @web.require_login("create pages")
    def create(self, trans, payload=None, **kwd):
        """
        Create a new page.
        """
        if trans.request.method == 'GET':
            return {
                'title'  : 'Create a new page',
                'inputs' : [{
                    'name'      : 'title',
                    'label'     : 'Name'
                }, {
                    'name'      : 'slug',
                    'label'     : 'Identifier',
                    'help'      : 'A unique identifier that will be used for public links to this page. This field can only contain lowercase letters, numbers, and dashes (-).'
                }, {
                    'name'      : 'annotation',
                    'label'     : 'Annotation',
                    'help'      : 'A description of the page. The annotation is shown alongside published pages.'
                }, {
                    'name'      : 'content_format',
                    'label'     : 'Content Format',
                    'type'      : 'select',
                    'options'   : [('HTML', 'html'), ('Markdown', 'markdown')],
                    'help'      : 'Use the traditional rich HTML editor or the newer experimental Markdown editor to create the page content. The HTML editor has several known bugs, is unmaintained and pages created with it will be read-only in future releases of Galaxy.'
                }]
            }
        else:
            try:
                page = self.page_manager.create(trans, payload)
            except exceptions.MessageException as e:
                return self.message_exception(trans, unicodify(e))
            return {'message': 'Page \'%s\' successfully created.' % page.title, 'status': 'success'}

    @web.legacy_expose_api
    @web.require_login("edit pages")
    def edit(self, trans, payload=None, **kwd):
        """
        Edit a page's attributes.
        """
        id = kwd.get('id')
        if not id:
            return self.message_exception(trans, 'No page id received for editing.')
        decoded_id = self.decode_id(id)
        user = trans.get_user()
        p = trans.sa_session.query(model.Page).get(decoded_id)
        if trans.request.method == 'GET':
            if p.slug is None:
                self.create_item_slug(trans.sa_session, p)
            return {
                'title'  : 'Edit page attributes',
                'inputs' : [{
                    'name'      : 'title',
                    'label'     : 'Name',
                    'value'     : p.title
                }, {
                    'name'      : 'slug',
                    'label'     : 'Identifier',
                    'value'     : p.slug,
                    'help'      : 'A unique identifier that will be used for public links to this page. This field can only contain lowercase letters, numbers, and dashes (-).'
                }, {
                    'name'      : 'annotation',
                    'label'     : 'Annotation',
                    'value'     : self.get_item_annotation_str(trans.sa_session, user, p),
                    'help'      : 'A description of the page. The annotation is shown alongside published pages.'
                }]
            }
        else:
            p_title = payload.get('title')
            p_slug = payload.get('slug')
            p_annotation = payload.get('annotation')
            if not p_title:
                return self.message_exception(trans, 'Please provide a page name is required.')
            elif not p_slug:
                return self.message_exception(trans, 'Please provide a unique identifier.')
            elif not self._is_valid_slug(p_slug):
                return self.message_exception(trans, 'Page identifier can only contain lowercase letters, numbers, and dashes (-).')
            elif p_slug != p.slug and trans.sa_session.query(model.Page).filter_by(user=p.user, slug=p_slug, deleted=False).first():
                return self.message_exception(trans, 'Page id must be unique.')
            else:
                p.title = p_title
                p.slug = p_slug
                if p_annotation:
                    p_annotation = sanitize_html(p_annotation)
                    self.add_item_annotation(trans.sa_session, user, p, p_annotation)
                trans.sa_session.add(p)
                trans.sa_session.flush()
            return {'message': 'Attributes of \'%s\' successfully saved.' % p.title, 'status': 'success'}

    @web.expose
    @web.require_login("edit pages")
    def edit_content(self, trans, id):
        """
        Render the main page editor interface.
        """
        id = self.decode_id(id)
        page = trans.sa_session.query(model.Page).get(id)
        assert page.user == trans.user
        return trans.fill_template("page/editor.mako", page=page)

    @web.expose
    @web.require_login("use Galaxy pages")
    def share(self, trans, id, email="", use_panels=False):
        """ Handle sharing with an individual user. """
        msg = mtype = None
        page = trans.sa_session.query(model.Page).get(self.decode_id(id))
        if email:
            other = trans.sa_session.query(model.User) \
                                    .filter(and_(model.User.table.c.email == email,
                                                 model.User.table.c.deleted == false())) \
                                    .first()
            if not other:
                mtype = "error"
                msg = ("User '%s' does not exist" % escape(email))
            elif other == trans.get_user():
                mtype = "error"
                msg = ("You cannot share a page with yourself")
            elif trans.sa_session.query(model.PageUserShareAssociation) \
                    .filter_by(user=other, page=page).count() > 0:
                mtype = "error"
                msg = ("Page already shared with '%s'" % escape(email))
            else:
                share = model.PageUserShareAssociation()
                share.page = page
                share.user = other
                session = trans.sa_session
                session.add(share)
                self.create_item_slug(session, page)
                session.flush()
                page_title = escape(page.title)
                other_email = escape(other.email)
                trans.set_message("Page '%s' shared with user '%s'" % (page_title, other_email))
                return trans.response.send_redirect(url_for("/pages/sharing?id=%s" % id))
        return trans.fill_template("/ind_share_base.mako",
                                   message=msg,
                                   messagetype=mtype,
                                   item=page,
                                   email=email,
                                   use_panels=use_panels)

    @web.expose
    @web.require_login()
    def display(self, trans, id):
        id = self.decode_id(id)
        page = trans.sa_session.query(model.Page).get(id)
        if not page:
            raise web.httpexceptions.HTTPNotFound()
        return self.display_by_username_and_slug(trans, page.user.username, page.slug)

    @web.expose
    def display_by_username_and_slug(self, trans, username, slug):
        """ Display page based on a username and slug. """

        # Get page.
        session = trans.sa_session
        user = session.query(model.User).filter_by(username=username).first()
        page = trans.sa_session.query(model.Page).filter_by(user=user, slug=slug, deleted=False).first()
        if page is None:
            raise web.httpexceptions.HTTPNotFound()
        # Security check raises error if user cannot access page.
        self.security_check(trans, page, False, True)

        latest_revision = page.latest_revision
        if latest_revision.content_format == "html":
            # Process page content.
            processor = PageContentProcessor(trans, self._get_embed_html)
            processor.feed(page.latest_revision.content)
            # Output is string, so convert to unicode for display.
            page_content = unicodify(processor.output(), 'utf-8')
            template = "page/display.mako"
        else:
            page_content = trans.security.encode_id(page.id)
            template = "page/display_markdown.mako"

        # Get rating data.
        user_item_rating = 0
        if trans.get_user():
            user_item_rating = self.get_user_item_rating(trans.sa_session, trans.get_user(), page)
            if user_item_rating:
                user_item_rating = user_item_rating.rating
            else:
                user_item_rating = 0
        ave_item_rating, num_ratings = self.get_ave_item_rating_data(trans.sa_session, page)

        return trans.fill_template_mako(template, item=page,
                                        item_data=page_content,
                                        user_item_rating=user_item_rating,
                                        ave_item_rating=ave_item_rating,
                                        num_ratings=num_ratings,
                                        content_only=True)

    @web.expose
    @web.require_login("use Galaxy pages")
    def set_accessible_async(self, trans, id=None, accessible=False):
        """ Set page's importable attribute and slug. """
        page = self.get_page(trans, id)

        # Only set if importable value would change; this prevents a change in the update_time unless attribute really changed.
        importable = accessible in ['True', 'true', 't', 'T']
        if page.importable != importable:
            if importable:
                self._make_item_accessible(trans.sa_session, page)
            else:
                page.importable = importable
            trans.sa_session.flush()
        return

    @web.expose
    @web.require_login("rate items")
    @web.json
    def rate_async(self, trans, id, rating):
        """ Rate a page asynchronously and return updated community data. """

        page = self.get_page(trans, id, check_ownership=False, check_accessible=True)
        if not page:
            return trans.show_error_message("The specified page does not exist.")

        # Rate page.
        self.rate_item(trans.sa_session, trans.get_user(), page, rating)

        return self.get_ave_item_rating_data(trans.sa_session, page)

    @web.expose
    def get_embed_html_async(self, trans, id):
        """ Returns HTML for embedding a workflow in a page. """

        # TODO: user should be able to embed any item he has access to. see display_by_username_and_slug for security code.
        page = self.get_page(trans, id)
        if page:
            return "Embedded Page '%s'" % page.title

    @web.expose
    @web.json
    @web.require_login("use Galaxy pages")
    def get_name_and_link_async(self, trans, id=None):
        """ Returns page's name and link. """
        page = self.get_page(trans, id)

        if self.create_item_slug(trans.sa_session, page):
            trans.sa_session.flush()
        return_dict = {"name": page.title, "link": url_for(controller='page',
                                                           action="display_by_username_and_slug",
                                                           username=page.user.username,
                                                           slug=page.slug)}
        return return_dict

    @web.expose
    @web.json
    @web.require_login("select a history from saved histories")
    def list_histories_for_selection(self, trans, **kwargs):
        """ Returns HTML that enables a user to select one or more histories. """
        return self._history_selection_grid(trans, **kwargs)

    @web.expose
    @web.json
    @web.require_login("select a workflow from saved workflows")
    def list_workflows_for_selection(self, trans, **kwargs):
        """ Returns HTML that enables a user to select one or more workflows. """
        return self._workflow_selection_grid(trans, **kwargs)

    @web.expose
    @web.json
    @web.require_login("select a visualization from saved visualizations")
    def list_visualizations_for_selection(self, trans, **kwargs):
        """ Returns HTML that enables a user to select one or more visualizations. """
        return self._visualization_selection_grid(trans, **kwargs)

    @web.expose
    @web.json
    @web.require_login("select a page from saved pages")
    def list_pages_for_selection(self, trans, **kwargs):
        """ Returns HTML that enables a user to select one or more pages. """
        return self._page_selection_grid(trans, **kwargs)

    @web.expose
    @web.json
    @web.require_login("select a dataset from saved datasets")
    def list_datasets_for_selection(self, trans, **kwargs):
        """ Returns HTML that enables a user to select one or more datasets. """
        return self._datasets_selection_grid(trans, **kwargs)

    @web.expose
    def get_editor_iframe(self, trans):
        """ Returns the document for the page editor's iframe. """
        return trans.fill_template("page/wymiframe.mako")

    def get_page(self, trans, id, check_ownership=True, check_accessible=False):
        """Get a page from the database by id."""
        # Load history from database
        id = self.decode_id(id)
        page = trans.sa_session.query(model.Page).get(id)
        if not page:
            error("Page not found")
        else:
            return self.security_check(trans, page, check_ownership, check_accessible)

    def get_item(self, trans, id):
        return self.get_page(trans, id)

    def _get_embedded_history_html(self, trans, decoded_id):
        """
        Returns html suitable for embedding in another page.
        """
        # histories embedded in pages are set to importable when embedded, check for access here
        history = self.history_manager.get_accessible(decoded_id, trans.user, current_history=trans.history)

        # create ownership flag for template, dictify models
        # note: adding original annotation since this is published - get_dict returns user-based annos
        user_is_owner = trans.user == history.user
        history.annotation = self.get_item_annotation_str(trans.sa_session, history.user, history)

        # include all datasets: hidden, deleted, and purged
        history_dictionary = self.history_serializer.serialize_to_view(
            history, view='detailed', user=trans.user, trans=trans
        )
        contents = self.history_serializer.serialize_contents(history, 'contents', trans=trans, user=trans.user)
        history_dictionary['annotation'] = history.annotation

        filled = trans.fill_template("history/embed.mako",
                                     item=history,
                                     user_is_owner=user_is_owner,
                                     history_dict=history_dictionary,
                                     content_dicts=contents)
        return filled

    def _get_embedded_visualization_html(self, trans, encoded_id):
        """
        Returns html suitable for embedding visualizations in another page.
        """
        visualization = self.get_visualization(trans, encoded_id, False, True)
        visualization.annotation = self.get_item_annotation_str(trans.sa_session, visualization.user, visualization)
        if not visualization:
            return None

        # Fork to template based on visualization.type (registry or builtin).
        if((trans.app.visualizations_registry and visualization.type in trans.app.visualizations_registry.plugins) and
                (visualization.type not in trans.app.visualizations_registry.BUILT_IN_VISUALIZATIONS)):
            # if a registry visualization, load a version into an iframe :(
            # TODO: simplest path from A to B but not optimal - will be difficult to do reg visualizations any other way
            # TODO: this will load the visualization twice (once above, once when the iframe src calls 'saved')
            encoded_visualization_id = trans.security.encode_id(visualization.id)
            return trans.fill_template('visualization/embed_in_frame.mako',
                                       item=visualization,
                                       encoded_visualization_id=encoded_visualization_id,
                                       content_only=True)

        return trans.fill_template("visualization/embed.mako", item=visualization, item_data=None)

    def _get_embed_html(self, trans, item_class, item_id):
        """ Returns HTML for embedding an item in a page. """
        item_class = self.get_class(item_class)
        encoded_id, decoded_id = get_page_identifiers(item_id, trans.app)
        if item_class == model.History:
            return self._get_embedded_history_html(trans, decoded_id)

        elif item_class == model.HistoryDatasetAssociation:
            dataset = self.hda_manager.get_accessible(decoded_id, trans.user)
            dataset = self.hda_manager.error_if_uploading(dataset)

            dataset.annotation = self.get_item_annotation_str(trans.sa_session, dataset.history.user, dataset)
            if dataset:
                data = self.hda_manager.text_data(dataset)
                return trans.fill_template("dataset/embed.mako", item=dataset, item_data=data)

        elif item_class == model.StoredWorkflow:
            workflow = self.get_stored_workflow(trans, encoded_id, False, True)
            workflow.annotation = self.get_item_annotation_str(trans.sa_session, workflow.user, workflow)
            if workflow:
                self.get_stored_workflow_steps(trans, workflow)
                return trans.fill_template("workflow/embed.mako", item=workflow, item_data=workflow.latest_workflow.steps)

        elif item_class == model.Visualization:
            return self._get_embedded_visualization_html(trans, encoded_id)

        elif item_class == model.Page:
            pass
Exemple #4
0
 def set_up_managers(self):
     super(HistorySerializerTestCase, self).set_up_managers()
     self.history_manager = HistoryManager(self.app)
     self.hda_manager = hdas.HDAManager(self.app)
     self.history_serializer = HistorySerializer(self.app)
Exemple #5
0
class HistorySerializerTestCase(BaseTestCase):

    def set_up_managers(self):
        super(HistorySerializerTestCase, self).set_up_managers()
        self.history_manager = HistoryManager(self.app)
        self.hda_manager = hdas.HDAManager(self.app)
        self.history_serializer = HistorySerializer(self.app)

    def test_views(self):
        user2 = self.user_manager.create(**user2_data)
        history1 = self.history_manager.create(name='history1', user=user2)

        self.log('should have a summary view')
        summary_view = self.history_serializer.serialize_to_view(history1, view='summary')
        self.assertKeys(summary_view, self.history_serializer.views['summary'])

        self.log('should have a detailed view')
        detailed_view = self.history_serializer.serialize_to_view(history1, view='detailed')
        self.assertKeys(detailed_view, self.history_serializer.views['detailed'])

        self.log('should have the summary view as default view')
        default_view = self.history_serializer.serialize_to_view(history1, default_view='summary')
        self.assertKeys(default_view, self.history_serializer.views['summary'])

        self.log('should have a serializer for all serializable keys')
        for key in self.history_serializer.serializable_keyset:
            instantiated_attribute = getattr(history1, key, None)
            if not ((key in self.history_serializer.serializers) or
                    (isinstance(instantiated_attribute, self.TYPES_NEEDING_NO_SERIALIZERS))):
                self.fail('no serializer for: %s (%s)' % (key, instantiated_attribute))
        else:
            self.assertTrue(True, 'all serializable keys have a serializer')

    def test_views_and_keys(self):
        user2 = self.user_manager.create(**user2_data)
        history1 = self.history_manager.create(name='history1', user=user2)

        self.log('should be able to use keys with views')
        serialized = self.history_serializer.serialize_to_view(history1,
            view='summary', keys=['state_ids', 'user_id'])
        self.assertKeys(serialized,
            self.history_serializer.views['summary'] + ['state_ids', 'user_id'])

        self.log('should be able to use keys on their own')
        serialized = self.history_serializer.serialize_to_view(history1,
            keys=['state_ids', 'user_id'])
        self.assertKeys(serialized, ['state_ids', 'user_id'])

    def test_sharable(self):
        user2 = self.user_manager.create(**user2_data)
        history1 = self.history_manager.create(name='history1', user=user2)

        self.log('should have a serializer for all SharableModel keys')
        sharable_attrs = ['user_id', 'username_and_slug', 'importable', 'published', 'slug']
        serialized = self.history_serializer.serialize(history1, sharable_attrs)
        self.assertKeys(serialized, sharable_attrs)

        self.log('should return user_id for user with whom it\'s been shared if the requester is the owner')
        non_owner = self.user_manager.create(**user3_data)
        self.history_manager.share_with(history1, non_owner)
        serialized = self.history_serializer.serialize(history1, ['users_shared_with'], user=user2)
        self.assertKeys(serialized, ['users_shared_with'])
        self.assertIsInstance(serialized['users_shared_with'], list)
        self.assertEqual(serialized['users_shared_with'][0], self.app.security.encode_id(non_owner.id))

        self.log('should not return users_shared_with if the requester is not the owner')
        serialized = self.history_serializer.serialize(history1, ['users_shared_with'], user=non_owner)
        self.assertFalse(hasattr(serialized, 'users_shared_with'))

    def test_purgable(self):
        user2 = self.user_manager.create(**user2_data)
        history1 = self.history_manager.create(name='history1', user=user2)

        self.log('deleted and purged should be returned in their default states')
        keys = ['deleted', 'purged']
        serialized = self.history_serializer.serialize(history1, keys)
        self.assertEqual(serialized['deleted'], False)
        self.assertEqual(serialized['purged'], False)

        self.log('deleted and purged should return their current state')
        self.history_manager.delete(history1)
        serialized = self.history_serializer.serialize(history1, keys)
        self.assertEqual(serialized['deleted'], True)
        self.assertEqual(serialized['purged'], False)

        self.history_manager.purge(history1)
        serialized = self.history_serializer.serialize(history1, keys)
        self.assertEqual(serialized['deleted'], True)
        self.assertEqual(serialized['purged'], True)

    def test_history_serializers(self):
        user2 = self.user_manager.create(**user2_data)
        history1 = self.history_manager.create(name='history1', user=user2)
        all_keys = list(self.history_serializer.serializable_keyset)
        serialized = self.history_serializer.serialize(history1, all_keys, user=user2)

        self.log('everything serialized should be of the proper type')
        self.assertIsInstance(serialized['size'], int)
        self.assertIsInstance(serialized['nice_size'], string_types)

        self.log('serialized should jsonify well')
        self.assertIsJsonifyable(serialized)

    def _history_state_from_states_and_deleted(self, user, hda_state_and_deleted_tuples):
        history = self.history_manager.create(name='name', user=user)
        for state, deleted in hda_state_and_deleted_tuples:
            hda = self.hda_manager.create(history=history)
            hda = self.hda_manager.update(hda, dict(state=state, deleted=deleted))
        history_state = self.history_serializer.serialize(history, ['state'])['state']
        return history_state

    def test_state(self):
        dataset_states = model.Dataset.states
        user2 = self.user_manager.create(**user2_data)

        ready_states = [(state, False) for state in [dataset_states.OK, dataset_states.OK]]

        self.log('a history\'s serialized state should be running if any of its datasets are running')
        self.assertEqual('running', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.RUNNING, False)]))
        self.assertEqual('running', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.SETTING_METADATA, False)]))
        self.assertEqual('running', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.UPLOAD, False)]))

        self.log('a history\'s serialized state should be queued if any of its datasets are queued')
        self.assertEqual('queued', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.QUEUED, False)]))

        self.log('a history\'s serialized state should be error if any of its datasets are errored')
        self.assertEqual('error', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.ERROR, False)]))
        self.assertEqual('error', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.FAILED_METADATA, False)]))

        self.log('a history\'s serialized state should be ok if *all* of its datasets are ok')
        self.assertEqual('ok', self._history_state_from_states_and_deleted(user2, ready_states))

        self.log('a history\'s serialized state should be not be affected by deleted datasets')
        self.assertEqual('ok', self._history_state_from_states_and_deleted(user2,
            ready_states + [(dataset_states.RUNNING, True)]))

    def test_contents(self):
        user2 = self.user_manager.create(**user2_data)
        history1 = self.history_manager.create(name='history1', user=user2)

        self.log('a history with no contents should be properly reflected in empty, etc.')
        keys = ['empty', 'count', 'state_ids', 'state_details', 'state', 'hdas']
        serialized = self.history_serializer.serialize(history1, keys)
        self.assertEqual(serialized['state'], 'new')
        self.assertEqual(serialized['empty'], True)
        self.assertEqual(serialized['count'], 0)
        self.assertEqual(sum(serialized['state_details'].values()), 0)
        self.assertEqual(serialized['state_ids']['ok'], [])
        self.assertIsInstance(serialized['hdas'], list)

        self.log('a history with contents should be properly reflected in empty, etc.')
        hda1 = self.hda_manager.create(history=history1, hid=1)
        self.hda_manager.update(hda1, dict(state='ok'))

        serialized = self.history_serializer.serialize(history1, keys)
        self.assertEqual(serialized['state'], 'ok')
        self.assertEqual(serialized['empty'], False)
        self.assertEqual(serialized['count'], 1)
        self.assertEqual(serialized['state_details']['ok'], 1)
        self.assertIsInstance(serialized['state_ids']['ok'], list)
        self.assertIsInstance(serialized['hdas'], list)
        self.assertIsInstance(serialized['hdas'][0], string_types)

        serialized = self.history_serializer.serialize(history1, ['contents'])
        self.assertHasKeys(serialized['contents'][0], ['id', 'name', 'state', 'create_time'])

        self.log('serialized should jsonify well')
        self.assertIsJsonifyable(serialized)

    def test_ratings(self):
        user2 = self.user_manager.create(**user2_data)
        user3 = self.user_manager.create(**user3_data)
        manager = self.history_manager
        serializer = self.history_serializer
        item = manager.create(name='history1', user=user2)

        self.log('serialization should reflect no ratings')
        serialized = serializer.serialize(item, ['user_rating', 'community_rating'], user=user2)
        self.assertEqual(serialized['user_rating'], None)
        self.assertEqual(serialized['community_rating']['count'], 0)
        self.assertEqual(serialized['community_rating']['average'], 0.0)

        self.log('serialization should reflect ratings')
        manager.rate(item, user2, 1)
        manager.rate(item, user3, 4)
        serialized = serializer.serialize(item, ['user_rating', 'community_rating'], user=user2)
        self.assertEqual(serialized['user_rating'], 1)
        self.assertEqual(serialized['community_rating']['count'], 2)
        self.assertEqual(serialized['community_rating']['average'], 2.5)
        self.assertIsJsonifyable(serialized)

        self.log('serialization of user_rating without user should error')
        self.assertRaises(base.ModelSerializingError,
            serializer.serialize, item, ['user_rating'])
class HistorySerializerTestCase( BaseTestCase ):

    def set_up_managers( self ):
        super( HistorySerializerTestCase, self ).set_up_managers()
        self.history_mgr = HistoryManager( self.app )
        self.hda_mgr = hdas.HDAManager( self.app )
        self.history_serializer = HistorySerializer( self.app )

    def test_views( self ):
        user2 = self.user_mgr.create( self.trans, **user2_data )
        history1 = self.history_mgr.create( self.trans, name='history1', user=user2 )

        self.log( 'should have a summary view' )
        summary_view = self.history_serializer.serialize_to_view( self.trans, history1, view='summary' )
        self.assertKeys( summary_view, self.history_serializer.views[ 'summary' ] )

        self.log( 'should have a detailed view' )
        detailed_view = self.history_serializer.serialize_to_view( self.trans, history1, view='detailed' )
        self.assertKeys( detailed_view, self.history_serializer.views[ 'detailed' ] )

        self.log( 'should have the summary view as default view' )
        default_view = self.history_serializer.serialize_to_view( self.trans, history1, default_view='summary' )
        self.assertKeys( summary_view, self.history_serializer.views[ 'summary' ] )

        self.log( 'should have a serializer for all serializable keys' )
        need_no_serializers = ( basestring, bool, type( None ) )
        for key in self.history_serializer.serializable_keyset:
            instantiated_attribute = getattr( history1, key, None )
            if not ( ( key in self.history_serializer.serializers )
                  or ( isinstance( instantiated_attribute, need_no_serializers ) ) ):
                self.fail( 'no serializer for: %s (%s)' % ( key, instantiated_attribute ) )
        else:
            self.assertTrue( True, 'all serializable keys have a serializer' )

    def test_views_and_keys( self ):
        user2 = self.user_mgr.create( self.trans, **user2_data )
        history1 = self.history_mgr.create( self.trans, name='history1', user=user2 )

        self.log( 'should be able to use keys with views' )
        serialized = self.history_serializer.serialize_to_view( self.trans, history1,
            view='summary', keys=[ 'state_ids', 'user_id' ] )
        self.assertKeys( serialized,
            self.history_serializer.views[ 'summary' ] + [ 'state_ids', 'user_id' ] )

        self.log( 'should be able to use keys on their own' )
        serialized = self.history_serializer.serialize_to_view( self.trans, history1,
            keys=[ 'state_ids', 'user_id' ] )
        self.assertKeys( serialized, [ 'state_ids', 'user_id' ] )

    def test_sharable( self ):
        user2 = self.user_mgr.create( self.trans, **user2_data )
        history1 = self.history_mgr.create( self.trans, name='history1', user=user2 )

        self.log( 'should have a serializer for all SharableModel keys' )
        sharable_attrs = [ 'user_id', 'username_and_slug', 'importable', 'published', 'slug' ]
        serialized = self.history_serializer.serialize( self.trans, history1, sharable_attrs )
        self.assertKeys( serialized, sharable_attrs )

    def test_purgable( self ):
        user2 = self.user_mgr.create( self.trans, **user2_data )
        history1 = self.history_mgr.create( self.trans, name='history1', user=user2 )

        self.log( 'deleted and purged should be returned in their default states' )
        keys = [ 'deleted', 'purged' ]
        serialized = self.history_serializer.serialize( self.trans, history1, keys )
        self.assertEqual( serialized[ 'deleted' ], False )
        self.assertEqual( serialized[ 'purged' ], False )

        self.log( 'deleted and purged should return their current state' )
        self.history_mgr.delete( self.trans, history1 )
        serialized = self.history_serializer.serialize( self.trans, history1, keys )
        self.assertEqual( serialized[ 'deleted' ], True )
        self.assertEqual( serialized[ 'purged' ], False )

        self.history_mgr.purge( self.trans, history1 )
        serialized = self.history_serializer.serialize( self.trans, history1, keys )
        self.assertEqual( serialized[ 'deleted' ], True )
        self.assertEqual( serialized[ 'purged' ], True )

    def test_history_serializers( self ):
        user2 = self.user_mgr.create( self.trans, **user2_data )
        history1 = self.history_mgr.create( self.trans, name='history1', user=user2 )
        
        serialized = self.history_serializer.serialize( self.trans, history1, [ 'size', 'nice_size' ])
        self.assertIsInstance( serialized[ 'size' ], int )
        self.assertIsInstance( serialized[ 'nice_size' ], basestring )

    def test_contents( self ):
        user2 = self.user_mgr.create( self.trans, **user2_data )
        history1 = self.history_mgr.create( self.trans, name='history1', user=user2 )

        self.log( 'a history with no contents should be properly reflected in empty, etc.' )
        keys = [ 'empty', 'count', 'state_ids', 'state_details', 'state', 'hdas' ]
        serialized = self.history_serializer.serialize( self.trans, history1, keys )
        self.assertEqual( serialized[ 'state' ], 'new' )
        self.assertEqual( serialized[ 'empty' ], True )
        self.assertEqual( serialized[ 'count' ], 0 )
        self.assertEqual( sum( serialized[ 'state_details' ].values() ), 0 )
        self.assertEqual( serialized[ 'state_ids' ][ 'ok' ], [] )
        self.assertIsInstance( serialized[ 'hdas' ], list )

        self.log( 'a history with contents should be properly reflected in empty, etc.' )
        hda1 = self.hda_mgr.create( self.trans, history=history1, hid=1 )
        self.hda_mgr.update( self.trans, hda1, dict( state='ok' ) )

        serialized = self.history_serializer.serialize( self.trans, history1, keys )
        self.assertEqual( serialized[ 'state' ], 'ok' )
        self.assertEqual( serialized[ 'empty' ], False )
        self.assertEqual( serialized[ 'count' ], 1 )
        self.assertEqual( serialized[ 'state_details' ][ 'ok' ], 1 )
        self.assertIsInstance( serialized[ 'state_ids' ][ 'ok' ], list )
        self.assertIsInstance( serialized[ 'hdas' ], list )
        self.assertIsInstance( serialized[ 'hdas' ][0], basestring )

        serialized = self.history_serializer.serialize( self.trans, history1, [ 'contents' ] )
        self.assertHasKeys( serialized[ 'contents' ][0], [ 'id', 'name', 'peek', 'create_time' ])
Exemple #7
0
class HistorySerializerTestCase(BaseTestCase):
    def assertHasKeys(self, obj, key_list):
        self.assertEqual(sorted(obj.keys()), sorted(key_list))

    def set_up_managers(self):
        super(HistorySerializerTestCase, self).set_up_managers()
        self.history_mgr = HistoryManager(self.app)
        self.hda_mgr = hdas.HDAManager(self.app)
        self.history_serializer = HistorySerializer(self.app)

    def test_views(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log('should have a summary view')
        summary_view = self.history_serializer.serialize_to_view(
            self.trans, history1, view='summary')
        self.assertHasKeys(summary_view,
                           self.history_serializer.views['summary'])

        self.log('should have a detailed view')
        detailed_view = self.history_serializer.serialize_to_view(
            self.trans, history1, view='detailed')
        self.assertHasKeys(detailed_view,
                           self.history_serializer.views['detailed'])

        self.log('should have a extended view')
        extended_view = self.history_serializer.serialize_to_view(
            self.trans, history1, view='extended')
        self.assertHasKeys(extended_view,
                           self.history_serializer.views['extended'])

        self.log('should have the summary view as default view')
        default_view = self.history_serializer.serialize_to_view(
            self.trans, history1, default_view='summary')
        self.assertHasKeys(summary_view,
                           self.history_serializer.views['summary'])

        self.log('should have a serializer for all serializable keys')
        need_no_serializers = (basestring, bool, type(None))
        for key in self.history_serializer.serializable_keys:
            instantiated_attribute = getattr(history1, key, None)
            if not ((key in self.history_serializer.serializers) or
                    (isinstance(instantiated_attribute, need_no_serializers))):
                self.fail('no serializer for: %s (%s)' %
                          (key, instantiated_attribute))
        else:
            self.assertTrue(True, 'all serializable keys have a serializer')

    def test_views_and_keys(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log('should be able to use keys with views')
        serialized = self.history_serializer.serialize_to_view(
            self.trans,
            history1,
            view='summary',
            keys=['state_ids', 'user_id'])
        self.assertHasKeys(
            serialized, self.history_serializer.views['summary'] +
            ['state_ids', 'user_id'])

        self.log('should be able to use keys on their own')
        serialized = self.history_serializer.serialize_to_view(
            self.trans, history1, keys=['state_ids', 'user_id'])
        self.assertHasKeys(serialized, ['state_ids', 'user_id'])

    def test_serializers(self):
        # size
        # nice size
        pass

    def test_contents(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log(
            'a history with no contents should be properly reflected in empty, etc.'
        )
        keys = ['empty', 'count', 'state_ids', 'state_details', 'state']
        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['state'], 'new')
        self.assertEqual(serialized['empty'], True)
        self.assertEqual(serialized['count'], 0)
        self.assertEqual(sum(serialized['state_details'].values()), 0)
        self.assertEqual(serialized['state_ids']['ok'], [])

        hda1 = self.hda_mgr.create(self.trans, history=history1, hid=1)
        self.hda_mgr.update(self.trans, hda1, dict(state='ok'))

        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['state'], 'ok')
        self.assertEqual(serialized['empty'], False)
        self.assertEqual(serialized['count'], 1)
        self.assertEqual(serialized['state_details']['ok'], 1)
        self.assertIsInstance(serialized['state_ids']['ok'], list)
class HistorySerializerTestCase(BaseTestCase):
    def set_up_managers(self):
        super(HistorySerializerTestCase, self).set_up_managers()
        self.history_mgr = HistoryManager(self.app)
        self.hda_mgr = hdas.HDAManager(self.app)
        self.history_serializer = HistorySerializer(self.app)

    def test_views(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log('should have a summary view')
        summary_view = self.history_serializer.serialize_to_view(
            self.trans, history1, view='summary')
        self.assertKeys(summary_view, self.history_serializer.views['summary'])

        self.log('should have a detailed view')
        detailed_view = self.history_serializer.serialize_to_view(
            self.trans, history1, view='detailed')
        self.assertKeys(detailed_view,
                        self.history_serializer.views['detailed'])

        self.log('should have the summary view as default view')
        default_view = self.history_serializer.serialize_to_view(
            self.trans, history1, default_view='summary')
        self.assertKeys(summary_view, self.history_serializer.views['summary'])

        self.log('should have a serializer for all serializable keys')
        need_no_serializers = (basestring, bool, type(None))
        for key in self.history_serializer.serializable_keyset:
            instantiated_attribute = getattr(history1, key, None)
            if not ((key in self.history_serializer.serializers) or
                    (isinstance(instantiated_attribute, need_no_serializers))):
                self.fail('no serializer for: %s (%s)' %
                          (key, instantiated_attribute))
        else:
            self.assertTrue(True, 'all serializable keys have a serializer')

    def test_views_and_keys(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log('should be able to use keys with views')
        serialized = self.history_serializer.serialize_to_view(
            self.trans,
            history1,
            view='summary',
            keys=['state_ids', 'user_id'])
        self.assertKeys(
            serialized, self.history_serializer.views['summary'] +
            ['state_ids', 'user_id'])

        self.log('should be able to use keys on their own')
        serialized = self.history_serializer.serialize_to_view(
            self.trans, history1, keys=['state_ids', 'user_id'])
        self.assertKeys(serialized, ['state_ids', 'user_id'])

    def test_sharable(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log('should have a serializer for all SharableModel keys')
        sharable_attrs = [
            'user_id', 'username_and_slug', 'importable', 'published', 'slug'
        ]
        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       sharable_attrs)
        self.assertKeys(serialized, sharable_attrs)

    def test_purgable(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log(
            'deleted and purged should be returned in their default states')
        keys = ['deleted', 'purged']
        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['deleted'], False)
        self.assertEqual(serialized['purged'], False)

        self.log('deleted and purged should return their current state')
        self.history_mgr.delete(self.trans, history1)
        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['deleted'], True)
        self.assertEqual(serialized['purged'], False)

        self.history_mgr.purge(self.trans, history1)
        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['deleted'], True)
        self.assertEqual(serialized['purged'], True)

    def test_history_serializers(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       ['size', 'nice_size'])
        self.assertIsInstance(serialized['size'], int)
        self.assertIsInstance(serialized['nice_size'], basestring)

    def test_contents(self):
        user2 = self.user_mgr.create(self.trans, **user2_data)
        history1 = self.history_mgr.create(self.trans,
                                           name='history1',
                                           user=user2)

        self.log(
            'a history with no contents should be properly reflected in empty, etc.'
        )
        keys = [
            'empty', 'count', 'state_ids', 'state_details', 'state', 'hdas'
        ]
        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['state'], 'new')
        self.assertEqual(serialized['empty'], True)
        self.assertEqual(serialized['count'], 0)
        self.assertEqual(sum(serialized['state_details'].values()), 0)
        self.assertEqual(serialized['state_ids']['ok'], [])
        self.assertIsInstance(serialized['hdas'], list)

        self.log(
            'a history with contents should be properly reflected in empty, etc.'
        )
        hda1 = self.hda_mgr.create(self.trans, history=history1, hid=1)
        self.hda_mgr.update(self.trans, hda1, dict(state='ok'))

        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       keys)
        self.assertEqual(serialized['state'], 'ok')
        self.assertEqual(serialized['empty'], False)
        self.assertEqual(serialized['count'], 1)
        self.assertEqual(serialized['state_details']['ok'], 1)
        self.assertIsInstance(serialized['state_ids']['ok'], list)
        self.assertIsInstance(serialized['hdas'], list)
        self.assertIsInstance(serialized['hdas'][0], basestring)

        serialized = self.history_serializer.serialize(self.trans, history1,
                                                       ['contents'])
        self.assertHasKeys(serialized['contents'][0],
                           ['id', 'name', 'peek', 'create_time'])