Exemple #1
0
    def list_narratives(self, ws_id=None):
        # self.log.debug("Listing Narratives")
        # self.log.debug("kbase_session = %s" % str(self.kbase_session))
        """
        By default, this searches for Narrative types in any workspace that the
        current token has read access to. Works anonymously as well.

        If the ws_id field is not None, it will only look up Narratives in that
        particular workspace (by its numerical id).

        Returns a list of dictionaries of object descriptions, one for each Narrative.
        The keys in each dictionary are those from the list_objects_fields list above.

        This is just a wrapper around the Workspace list_objects command.

        Raises: WorkspaceError, if access is denied; ValueError is ws_id is not
        numeric.
        """
        log_event(g_log, 'list_narratives start', {'ws_id': ws_id})
        list_obj_params = {'type': self.nar_type, 'includeMetadata': 1}
        if ws_id:
            try:
                int(ws_id)  # will throw an exception if ws_id isn't an int
                list_obj_params['ids'] = [ws_id]
            except ValueError:
                raise

        try:
            ws = self.ws_client()
            res = ws.list_objects(list_obj_params)
        except ServerError as err:
            raise WorkspaceError(err, ws_id)
        my_narratives = [dict(zip(list_objects_fields, obj)) for obj in res]
        for nar in my_narratives:
            # Look first for the name in the object metadata. if it's not there, use
            # the object's name. If THAT'S not there, use Untitled.
            # This gives support for some rather old narratives that don't
            # have their name stashed in the metadata.
            nar['name'] = nar['meta'].get('name', nar.get('name', 'Untitled'))

        return my_narratives
 def _ws_id_to_name(self, wsid):
     try:
         ws_info = self.ws_client().get_workspace_info({'id': wsid})
         return ws_info[1]
     except ServerError as err:
         raise WorkspaceError(err, wsid)
    def write_narrative(self, ref, nb, cur_user):
        """
        :param ref: a NarrativeRef
        :param nb: a notebook model
        :cur_user: the current user id
        Given a notebook, break this down into a couple parts:
        1. Figure out what ws and obj to save to
        2. Build metadata object
        3. Save the narrative object (write_narrative)
        4. Return any notebook changes as a list-
           (narrative, ws_id, obj_id, ver)
        """

        assert isinstance(
            ref,
            NarrativeRef), "write_narrative must use a NarrativeRef as input!"
        if 'worksheets' in nb:
            # it's an old version. update it by replacing the 'worksheets' key with
            # the 'cells' subkey
            # the old version only uses the first 'worksheet', so if it's there,
            # copy it out
            if (isinstance(nb['worksheets'], list)
                    and len(nb['worksheets']) > 0
                    and 'cells' in nb['worksheets'][0]):
                nb['cells'] = nb['worksheets'][0]['cells']
            else:
                nb['cells'] = list()
            del (nb['worksheets'])
            nb['nbformat'] = 4

        ws_id = ref.wsid
        obj_id = ref.objid

        # make sure the metadata's up to date.
        try:
            meta = nb['metadata']
            if 'name' not in meta:
                meta['name'] = 'Untitled'
            if 'ws_name' not in meta:
                meta[
                    'ws_name'] = util.kbase_env.workspace or self._ws_id_to_name(
                        ws_id)
            if 'creator' not in meta:
                meta['creator'] = cur_user
            if 'type' not in meta:
                meta['type'] = self.nar_type
            if 'description' not in meta:
                meta['description'] = ''
            if 'data_dependencies' not in meta:
                meta['data_dependencies'] = list()
            if 'job_ids' not in meta:
                meta['job_ids'] = {
                    'methods': [],
                    'apps': [],
                    'job_usage': {
                        'queue_time': 0,
                        'run_time': 0
                    }
                }
            if 'methods' not in meta['job_ids']:
                meta['job_ids']['methods'] = list()
            if 'apps' not in meta['job_ids']:
                meta['job_ids']['apps'] = list()
            if 'job_usage' not in meta['job_ids']:
                meta['job_ids']['job_usage'] = {'queue_time': 0, 'run_time': 0}
            meta['is_temporary'] = 'false'
            meta['format'] = 'ipynb'

            if len(meta['name']) > MAX_METADATA_STRING_BYTES - len('name'):
                meta['name'] = meta['name'][0:MAX_METADATA_STRING_BYTES -
                                            len('name')]

            nb['metadata'] = meta
        except Exception as e:
            raise HTTPError(
                400, 'Unexpected error setting Narrative attributes: %s' % e)

        # With that set, update the workspace metadata with the new info.
        perms = self.narrative_permissions(ref, user=cur_user)
        if perms[cur_user] == 'a':
            try:
                updated_metadata = {
                    u'is_temporary': u'false',
                    u'narrative_nice_name': nb[u'metadata'][u'name']
                }
                self.ws_client().alter_workspace_metadata({
                    u'wsi': {
                        u'id': ws_id
                    },
                    u'new':
                    updated_metadata
                })
            except ServerError as err:
                raise WorkspaceError(
                    err,
                    ws_id,
                    message="Error adjusting Narrative metadata",
                    http_code=500)

        # Now we can save the Narrative object.
        try:
            ws_save_obj = {
                'type':
                self.nar_type,
                'data':
                nb,
                'objid':
                obj_id,
                'meta':
                nb['metadata'].copy(),
                'provenance': [{
                    'service': 'narrative',
                    'description': 'Saved by KBase Narrative Interface',
                    'service_ver': str(biokbase.narrative.version())
                }]
            }
            # no non-strings allowed in metadata!
            ws_save_obj['meta']['data_dependencies'] = json.dumps(
                ws_save_obj['meta']['data_dependencies'])

            # Sort out job info we want to keep
            # Gonna look like this, so init it that way
            nb_job_usage = nb['metadata']['job_ids'].get(
                'job_usage', {
                    'queue_time': 0,
                    'run_time': 0
                })
            job_info = {
                'queue_time': nb_job_usage.get('queue_time', 0),
                'run_time': nb_job_usage.get('run_time', 0),
                'running': 0,
                'completed': 0,
                'error': 0
            }
            for job in nb['metadata']['job_ids']['methods'] + nb['metadata'][
                    'job_ids']['apps']:
                status = job.get('status', 'running')
                if status.startswith('complete'):
                    job_info['completed'] += 1
                elif 'error' in status:
                    job_info['error'] += 1
                else:
                    job_info['running'] += 1
            ws_save_obj['meta']['job_info'] = json.dumps(job_info)
            if 'job_ids' in ws_save_obj['meta']:
                ws_save_obj['meta'].pop('job_ids')
            # clear out anything from metadata that doesn't have a string value
            # This flushes things from IPython that we don't need as KBase object metadata
            ws_save_obj['meta'] = {
                k: v
                for k, v in ws_save_obj['meta'].items() if isinstance(v, str)
            }
            ws_save_obj['meta'] = self._process_cell_usage(
                nb, ws_save_obj['meta'])

            # Actually do the save now!
            obj_info = self.ws_client().save_objects({
                'id': ws_id,
                'objects': [ws_save_obj]
            })[0]

            return (nb, obj_info[6], obj_info[0], obj_info[4])

        except ServerError as err:
            raise WorkspaceError(err, ws_id)
        except Exception as e:
            raise HTTPError(500, '%s saving Narrative: %s' % (type(e), e))
Exemple #4
0
    def write_narrative(self, ref, nb, cur_user):
        """
        :param ref: a NarrativeRef
        :param nb: a notebook model
        :cur_user: the current user id
        Given a notebook, break this down into a couple parts:
        1. Figure out what ws and obj to save to
        2. Build metadata object
        3. Save the narrative object (write_narrative)
        4. Return any notebook changes as a list-
           (narrative, ws_id, obj_id, ver)
        """

        assert isinstance(
            ref, NarrativeRef
        ), "write_narrative must use a NarrativeRef as input!"
        if "worksheets" in nb:
            # it's an old version. update it by replacing the 'worksheets' key with
            # the 'cells' subkey
            # the old version only uses the first 'worksheet', so if it's there,
            # copy it out
            if (
                isinstance(nb["worksheets"], list)
                and len(nb["worksheets"]) > 0
                and "cells" in nb["worksheets"][0]
            ):
                nb["cells"] = nb["worksheets"][0]["cells"]
            else:
                nb["cells"] = list()
            del nb["worksheets"]
            nb["nbformat"] = 4

        ws_id = ref.wsid
        obj_id = ref.objid

        # make sure the metadata's up to date.
        try:
            meta = nb["metadata"]
            if "name" not in meta:
                meta["name"] = "Untitled"
            if "ws_name" not in meta:
                meta["ws_name"] = util.kbase_env.workspace or self._ws_id_to_name(ws_id)
            if "creator" not in meta:
                meta["creator"] = cur_user
            if "type" not in meta:
                meta["type"] = self.nar_type
            if "description" not in meta:
                meta["description"] = ""
            if "data_dependencies" not in meta:
                meta["data_dependencies"] = list()
            if "job_ids" not in meta:
                meta["job_ids"] = {
                    "methods": [],
                    "apps": [],
                    "job_usage": {"queue_time": 0, "run_time": 0},
                }
            if "methods" not in meta["job_ids"]:
                meta["job_ids"]["methods"] = list()
            if "apps" not in meta["job_ids"]:
                meta["job_ids"]["apps"] = list()
            if "job_usage" not in meta["job_ids"]:
                meta["job_ids"]["job_usage"] = {"queue_time": 0, "run_time": 0}
            meta["is_temporary"] = "false"
            meta["format"] = "ipynb"

            if len(meta["name"]) > MAX_METADATA_STRING_BYTES - len("name"):
                meta["name"] = meta["name"][0 : MAX_METADATA_STRING_BYTES - len("name")]

            nb["metadata"] = meta
        except Exception as e:
            raise HTTPError(
                400, "Unexpected error setting Narrative attributes: %s" % e
            )

        # With that set, update the workspace metadata with the new info.
        perms = self.narrative_permissions(ref, user=cur_user)
        if perms[cur_user] == "a":
            try:
                updated_metadata = {
                    "is_temporary": "false",
                    "narrative_nice_name": nb["metadata"]["name"],
                    "searchtags": "narrative",
                }
                self.ws_client().alter_workspace_metadata(
                    {"wsi": {"id": ws_id}, "new": updated_metadata}
                )
            except ServerError as err:
                raise WorkspaceError(
                    err,
                    ws_id,
                    message="Error adjusting Narrative metadata",
                    http_code=500,
                )

        # Now we can save the Narrative object.
        try:
            ws_save_obj = {
                "type": self.nar_type,
                "data": nb,
                "objid": obj_id,
                "meta": nb["metadata"].copy(),
                "provenance": [
                    {
                        "service": "narrative",
                        "description": "Saved by KBase Narrative Interface",
                        "service_ver": str(biokbase.narrative.version()),
                    }
                ],
            }
            # no non-strings allowed in metadata!
            ws_save_obj["meta"]["data_dependencies"] = json.dumps(
                ws_save_obj["meta"]["data_dependencies"]
            )

            # Sort out job info we want to keep
            # Gonna look like this, so init it that way
            nb_job_usage = nb["metadata"]["job_ids"].get(
                "job_usage", {"queue_time": 0, "run_time": 0}
            )
            job_info = {
                "queue_time": nb_job_usage.get("queue_time", 0),
                "run_time": nb_job_usage.get("run_time", 0),
                "running": 0,
                "completed": 0,
                "error": 0,
            }
            for job in (
                nb["metadata"]["job_ids"]["methods"] + nb["metadata"]["job_ids"]["apps"]
            ):
                status = job.get("status", "running")
                if status.startswith("complete"):
                    job_info["completed"] += 1
                elif "error" in status:
                    job_info["error"] += 1
                else:
                    job_info["running"] += 1
            ws_save_obj["meta"]["job_info"] = json.dumps(job_info)
            if "job_ids" in ws_save_obj["meta"]:
                ws_save_obj["meta"].pop("job_ids")
            # clear out anything from metadata that doesn't have a string value
            # This flushes things from IPython that we don't need as KBase object metadata
            ws_save_obj["meta"] = {
                k: v for k, v in ws_save_obj["meta"].items() if isinstance(v, str)
            }
            ws_save_obj["meta"] = self._process_cell_usage(nb, ws_save_obj["meta"])

            # Actually do the save now!
            obj_info = self.ws_client().save_objects(
                {"id": ws_id, "objects": [ws_save_obj]}
            )[0]

            return (nb, obj_info[6], obj_info[0], obj_info[4])

        except ServerError as err:
            raise WorkspaceError(err, ws_id)
        except Exception as e:
            raise HTTPError(500, "%s saving Narrative: %s" % (type(e), e))