예제 #1
0
 def test_map_outputs_from_state_bad_spec(self):
     os.environ["KB_WORKSPACE_ID"] = self.workspace
     app_spec = {"not": "really"}
     params = {"an_input": "input_val"}
     state = {}
     with self.assertRaises(ValueError):
         map_outputs_from_state(state, params, app_spec)
예제 #2
0
 def test_map_outputs_from_state_bad_spec(self):
     os.environ['KB_WORKSPACE_ID'] = self.workspace
     app_spec = {'not': 'really'}
     params = {'an_input': 'input_val'}
     state = {}
     with self.assertRaises(ValueError):
         map_outputs_from_state(state, params, app_spec)
예제 #3
0
 def test_map_outputs_from_state_bad_spec(self):
     os.environ['KB_WORKSPACE_ID'] = self.workspace
     app_spec = {
         'not': 'really'
     }
     params = {
         'an_input': 'input_val'
     }
     state = {}
     with self.assertRaises(ValueError):
         map_outputs_from_state(state, params, app_spec)
예제 #4
0
 def test_map_outputs_from_state(self):
     os.environ["KB_WORKSPACE_ID"] = self.workspace
     app_spec = {
         "widgets": {"input": None, "output": "testOutputWidget"},
         "parameters": [],
         "behavior": {
             "kb_service_output_mapping": [
                 {"narrative_system_variable": "workspace", "target_property": "ws"},
                 {"constant_value": 5, "target_property": "a_constant"},
                 {
                     "service_method_output_path": [1],
                     "target_property": "a_path_ref",
                 },
                 {"input_parameter": "an_input", "target_property": "an_input"},
             ]
         },
     }
     params = {"an_input": "input_val"}
     state = {"job_output": {"result": ["foo", "bar"]}}
     expected = (
         "testOutputWidget",
         {
             "ws": self.workspace,
             "a_constant": 5,
             "a_path_ref": "bar",
             "an_input": "input_val",
         },
     )
     self.assertTupleEqual(map_outputs_from_state(state, params, app_spec), expected)
예제 #5
0
 def test_map_outputs_from_state(self):
     os.environ['KB_WORKSPACE_ID'] = self.workspace
     app_spec = {
         'widgets': {
             'input': None,
             'output': 'testOutputWidget'
         },
         'parameters': [],
         'behavior': {
             'kb_service_output_mapping': [{
                 'narrative_system_variable': 'workspace',
                 'target_property': 'ws'
             }, {
                 'constant_value': 5,
                 'target_property': 'a_constant'
             }, {
                 'service_method_output_path': [1],
                 'target_property': 'a_path_ref'
             }, {
                 'input_parameter': 'an_input',
                 'target_property': 'an_input'
             }]
         }
     }
     params = {'an_input': 'input_val'}
     state = {'job_output': {'result': ['foo', 'bar']}}
     expected = ('testOutputWidget', {
         'ws': self.workspace,
         'a_constant': 5,
         'a_path_ref': 'bar',
         'an_input': 'input_val'
     })
     self.assertTupleEqual(map_outputs_from_state(state, params, app_spec),
                           expected)
예제 #6
0
    def map_viewer_params(cls, job_state, job_inputs, app_id, app_tag):
        # get app spec.
        if job_state is None or job_state.get("status", "") != "completed":
            return None

        spec = SpecManager().get_spec(app_id, app_tag)
        (output_widget, widget_params) = map_outputs_from_state(
            job_state, map_inputs_from_job(job_inputs, spec), spec)
        return {"name": output_widget, "tag": app_tag, "params": widget_params}
예제 #7
0
파일: job.py 프로젝트: psdehal/narrative
    def map_viewer_params(Job, job_state, job_inputs, app_id, app_tag):
        # get app spec.
        if job_state is None or job_state['job_state'] != 'completed':
            return None

        spec = SpecManager().get_spec(app_id, app_tag)
        (output_widget, widget_params) = map_outputs_from_state(
            job_state, map_inputs_from_job(job_inputs, spec), spec)
        return {'name': output_widget, 'tag': app_tag, 'params': widget_params}
예제 #8
0
 def test_map_outputs_from_state_simple(self):
     os.environ["KB_WORKSPACE_ID"] = self.workspace
     app_spec = {
         "parameters": [],
         "behavior": {
             "output_mapping": [{"narrative_system_variable": "workspace"}]
         },
     }
     self.assertTupleEqual(
         map_outputs_from_state(None, None, app_spec),
         ("kbaseDefaultNarrativeOutput", self.workspace),
     )
예제 #9
0
파일: job.py 프로젝트: briehl/narrative
    def map_viewer_params(Job, job_state, job_inputs, app_id, app_tag):
        # get app spec.
        if job_state is None or job_state['job_state'] != 'completed':
            return None

        spec = SpecManager().get_spec(app_id, app_tag)
        (output_widget, widget_params) = map_outputs_from_state(job_state, map_inputs_from_job(job_inputs, spec), spec)
        return {
            'name': output_widget,
            'tag': app_tag,
            'params': widget_params
        }
예제 #10
0
    def _run_local_app_internal(self, app_id, params, widget_state, tag, version, cell_id, run_id):
        self._send_comm_message('run_status', {
            'event': 'validating_app',
            'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
            'cell_id': cell_id,
            'run_id': run_id
        })

        spec = self._get_validated_app_spec(app_id, tag, False, version=version)

        # Here, we just deal with two behaviors:
        # 1. None of the above - it's a viewer.
        # 2. ***TODO*** python_class / python_function.
        #    Import and exec the python code.

        # for now, just map the inputs to outputs.
        # First, validate.
        # Preflight check the params - all required ones are present, all
        # values are the right type, all numerical values are in given ranges
        spec_params = self.spec_manager.app_params(spec)
        (params, ws_refs) = validate_parameters(app_id, tag, spec_params, params)

        # Log that we're trying to run a job...
        log_info = {
            'app_id': app_id,
            'tag': tag,
            'username': system_variable('user_id'),
            'ws': system_variable('workspace')
        }
        kblogging.log_event(self._log, "run_local_app", log_info)

        self._send_comm_message('run_status', {
            'event': 'success',
            'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
            'cell_id': cell_id,
            'run_id': run_id
        })

        (output_widget, widget_params) = map_outputs_from_state([],
                                                                params,
                                                                spec)

        # All a local app does is route the inputs to outputs through the
        # spec's mapping, and then feed that into the specified output widget.
        wm = WidgetManager()
        if widget_state is not None:
            return wm.show_advanced_viewer_widget(
                output_widget, widget_params, widget_state, cell_id=cell_id, tag=tag
            )
        else:
            return wm.show_output_widget(
                output_widget, widget_params, cell_id=cell_id, tag=tag
            )
예제 #11
0
 def test_map_outputs_from_state_simple(self):
     os.environ['KB_WORKSPACE_ID'] = self.workspace
     app_spec = {
         'parameters': [],
         'behavior': {
             'output_mapping': [{
                 'narrative_system_variable': 'workspace'
             }]
         }
     }
     self.assertTupleEqual(map_outputs_from_state(None, None, app_spec),
                           ('kbaseDefaultNarrativeOutput', self.workspace))
예제 #12
0
 def test_map_outputs_from_state_simple(self):
     os.environ['KB_WORKSPACE_ID'] = self.workspace
     app_spec = {
         'parameters': [],
         'behavior': {
             'output_mapping': [
                 {
                     'narrative_system_variable': 'workspace'
                 }
             ]
         }
     }
     self.assertTupleEqual(map_outputs_from_state(None, None, app_spec), ('kbaseDefaultNarrativeOutput', self.workspace))
예제 #13
0
 def test_map_outputs_from_state(self):
     os.environ['KB_WORKSPACE_ID'] = self.workspace
     app_spec = {
         'widgets': {
             'input': None,
             'output': 'testOutputWidget'
         },
         'parameters': [],
         'behavior': {
             'kb_service_output_mapping': [
                 {
                     'narrative_system_variable': 'workspace',
                     'target_property': 'ws'
                 },
                 {
                     'constant_value': 5,
                     'target_property': 'a_constant'
                 },
                 {
                     'service_method_output_path': [1],
                     'target_property': 'a_path_ref'
                 },
                 {
                     'input_parameter': 'an_input',
                     'target_property': 'an_input'
                 }
             ]
         }
     }
     params = {
         'an_input': 'input_val'
     }
     state = {
         'result': ['foo', 'bar']
     }
     expected = (
         'testOutputWidget',
         {
             'ws': self.workspace,
             'a_constant': 5,
             'a_path_ref': 'bar',
             'an_input': 'input_val'
         }
     )
     self.assertTupleEqual(map_outputs_from_state(state, params, app_spec), expected)
예제 #14
0
파일: test_job.py 프로젝트: kbase/narrative
def get_widget_info(job_id):
    state = get_test_job(job_id)
    if state.get("status") != COMPLETED_STATUS:
        return None
    job_input = state.get("job_input", {})
    app_id = job_input.get("app_id", JOB_ATTR_DEFAULTS["app_id"])
    params = job_input.get("params", JOB_ATTR_DEFAULTS["params"])
    tag = job_input.get("narrative_cell_info", {}).get("tag", JOB_ATTR_DEFAULTS["tag"])
    spec = get_test_spec(tag, app_id)
    with mock.patch("biokbase.narrative.app_util.clients.get", get_mock_client):
        output_widget, widget_params = map_outputs_from_state(
            state,
            map_inputs_from_job(params, spec),
            spec,
        )
    return {
        "name": output_widget,
        "tag": tag,
        "params": widget_params,
    }
예제 #15
0
    def _run_local_app_internal(self, app_id, params, widget_state, tag,
                                version, cell_id, run_id):
        self._send_comm_message(
            'run_status', {
                'event': 'validating_app',
                'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
                'cell_id': cell_id,
                'run_id': run_id
            })

        spec = self._get_validated_app_spec(app_id,
                                            tag,
                                            False,
                                            version=version)

        # Here, we just deal with two behaviors:
        # 1. None of the above - it's a viewer.
        # 2. ***TODO*** python_class / python_function.
        #    Import and exec the python code.

        # for now, just map the inputs to outputs.
        # First, validate.
        # Preflight check the params - all required ones are present, all
        # values are the right type, all numerical values are in given ranges
        spec_params = self.spec_manager.app_params(spec)
        (params, ws_refs) = validate_parameters(app_id, tag, spec_params,
                                                params)

        # Log that we're trying to run a job...
        log_info = {
            'app_id': app_id,
            'tag': tag,
            'username': system_variable('user_id'),
            'ws': system_variable('workspace')
        }
        kblogging.log_event(self._log, "run_local_app", log_info)

        self._send_comm_message(
            'run_status', {
                'event': 'success',
                'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
                'cell_id': cell_id,
                'run_id': run_id
            })

        (output_widget, widget_params) = map_outputs_from_state([], params,
                                                                spec)

        # All a local app does is route the inputs to outputs through the
        # spec's mapping, and then feed that into the specified output widget.
        wm = WidgetManager()
        if widget_state is not None:
            return wm.show_advanced_viewer_widget(output_widget,
                                                  widget_params,
                                                  widget_state,
                                                  cell_id=cell_id,
                                                  tag=tag)
        else:
            return wm.show_output_widget(output_widget,
                                         widget_params,
                                         cell_id=cell_id,
                                         tag=tag)
예제 #16
0
    def _run_local_app_internal(self, app_id, params, tag, version, cell_id, run_id, **kwargs):
        self._send_comm_message('run_status', {
            'event': 'validating_app',
            'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
            'cell_id': cell_id,
            'run_id': run_id
        })

        ### TODO: this needs restructuring so that we can send back validation failure
        ### messages. Perhaps a separate function and catch the errors, or return an
        ### error structure.

        # Intro tests:
        self.spec_manager.check_app(app_id, tag, raise_exception=True)

        if version is not None and tag != "release":
            raise ValueError("App versions only apply to released app modules!")

        # Get the spec & params
        spec = self.spec_manager.get_spec(app_id, tag)

        if 'behavior' not in spec:
            raise ValueError("This app appears invalid - it has no defined behavior")

        behavior = spec['behavior']

        if 'kb_service_input_mapping' in behavior:
            # it's a service! Should run this with run_app!
            raise ValueError('This app appears to be a long-running job! Please start it using the run_app function instead.')

        if 'script_module' in behavior or 'script_name' in behavior:
            # It's an old NJS script. These don't work anymore.
            raise ValueError('This app relies on a service that is now obsolete. Please contact the administrator.')

        # Here, we just deal with two behaviors:
        # 1. None of the above - it's a viewer.
        # 2. ***TODO*** python_class / python_function. Import and exec the python code.

        # for now, just map the inputs to outputs.
        # First, validate.
        # Preflight check the params - all required ones are present, all values are the right type, all numerical values are in given ranges
        spec_params = self.spec_manager.app_params(spec)
        (params, ws_refs) = self._validate_parameters(app_id, tag, spec_params, params)

        # Log that we're trying to run a job...
        log_info = {
            'app_id': app_id,
            'tag': tag,
            'username': system_variable('user_id'),
            'ws': system_variable('workspace')
        }
        kblogging.log_event(self._log, "run_local_app", log_info)

        self._send_comm_message('run_status', {
            'event': 'success',
            'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
            'cell_id': cell_id,
            'run_id': run_id
        })

        # now just map onto outputs.
        (output_widget, widget_params) = map_outputs_from_state([], params, spec)
        return WidgetManager().show_output_widget(output_widget, widget_params, cell_id=cell_id, tag=tag)
예제 #17
0
    def _run_local_app_advanced_internal(self, app_id, params, widget_state,
                                         tag, version, cell_id, run_id,
                                         **kwargs):
        self._send_comm_message(
            'run_status', {
                'event': 'validating_app',
                'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
                'cell_id': cell_id,
                'run_id': run_id
            })

        # Intro tests:
        self.spec_manager.check_app(app_id, tag, raise_exception=True)

        if version is not None and tag != "release":
            raise ValueError("App versions only apply to released modules!")

        # Get the spec & params
        spec = self.spec_manager.get_spec(app_id, tag)

        if 'behavior' not in spec:
            raise ValueError("This app appears invalid - " +
                             "it has no defined behavior")

        behavior = spec['behavior']

        if 'script_module' in behavior or 'script_name' in behavior:
            # It's an old NJS script. These don't work anymore.
            raise ValueError('This app relies on a service that is now ' +
                             'obsolete. Please contact the administrator.')

        # Here, we just deal with two behaviors:
        # 1. None of the above - it's a viewer.
        # 2. ***TODO*** python_class / python_function.
        #    Import and exec the python code.

        # for now, just map the inputs to outputs.
        # First, validate.
        # Preflight check the params - all required ones are present, all
        # values are the right type, all numerical values are in given ranges
        spec_params = self.spec_manager.app_params(spec)
        (params, ws_refs) = self._validate_parameters(app_id, tag, spec_params,
                                                      params)

        # Log that we're trying to run a job...
        log_info = {
            'app_id': app_id,
            'tag': tag,
            'username': system_variable('user_id'),
            'ws': system_variable('workspace')
        }
        kblogging.log_event(self._log, "run_local_app", log_info)

        self._send_comm_message(
            'run_status', {
                'event': 'success',
                'event_at': datetime.datetime.utcnow().isoformat() + 'Z',
                'cell_id': cell_id,
                'run_id': run_id
            })

        (output_widget, widget_params) = map_outputs_from_state([], params,
                                                                spec)

        # All a local app does is route the inputs to outputs through the
        # spec's mapping, and then feed that into the specified output widget.
        return WidgetManager().show_advanced_viewer_widget(output_widget,
                                                           widget_params,
                                                           widget_state,
                                                           cell_id=cell_id,
                                                           tag=tag)
예제 #18
0
    def show_data_widget(self, upa, title=None, cell_id=None, tag="release"):
        """
        Renders a widget using the generic kbaseNarrativeOutputCell container.
        First, it looks up the UPA to get its object type. It then uses that type to look up
        what the viewer app should be. This contains the widget and the parameter mapping to view
        that widget. It then maps all of these together to run show_output_widget against a widget
        with a set of parameters for it.

        If there's an error here at any step, it still renders a widget, but it makes a
        kbaseNarrativeError widget instead, that'll hopefully be informative.

        Parameters
        ----------
        upa : string
            UPA defining a workspace object. Used to translate that object into parameters
            for the mapping to the data object used in the output cell.
            This may also be a Workspace reference path.
        title=None : string
            A title for the cell. If None, this just gets replaced with an empty string.
        cell_id=None : string
            if not None, this should be the id of the cell where the widget will live. Generated by
            the Narrative frontend.
        tag="release" : string
            All objects are related to their viewers by an app. This is the tag for that app's
            release state (should be one of release, beta, or dev)
        """
        widget_name = 'widgets/function_output/kbaseDefaultObjectView'  # set as default, overridden below
        widget_data = dict()
        upas = dict()
        info_tuple = clients.get('workspace').get_object_info_new({
            'objects': [{
                'ref': upa
            }],
            'includeMetadata':
            1
        })[0]
        bare_type = info_tuple[2].split('-')[0]
        type_module = bare_type.split(".")[0]

        type_spec = self._sm.get_type_spec(bare_type, raise_exception=False)

        if type_spec is None:
            widget_data = {
                "error": {
                    "msg":
                    f"Unable to find viewer specification for objects of type {bare_type}.",
                    "method_name": "WidgetManager.show_data_widget",
                    "traceback":
                    f"Can't find type spec info for type {bare_type}"
                }
            }
            upas['upas'] = [upa]  # doompety-doo
        else:
            if not type_spec.get('view_method_ids'):
                return f"No viewer found for objects of type {bare_type}"
            app_id = type_spec['view_method_ids'][0]
            app_spec = None
            try:
                app_spec = self._sm.get_spec(app_id, tag=tag)
            except Exception as e:
                widget_data = {
                    "error": {
                        "msg":
                        f"Unable to find specification for viewer app {app_id}",
                        "method_name": "WidgetManager.show_data_widget",
                        "traceback": e.message
                    }
                }
            if app_spec is not None:
                spec_params = self._sm.app_params(app_spec)
                input_params = {}
                is_ref_path = ';' in upa
                is_external = info_tuple[7] != os.environ['KB_WORKSPACE_ID']
                # it's not safe to use reference yet (until we switch to them all over the Apps)
                # But in case we deal with ref-path we have to do it anyway:
                obj_param_value = upa if (is_ref_path
                                          or is_external) else info_tuple[1]
                upa_params = list()
                for param in spec_params:
                    if param.get('allowed_types') is None or any(
                        (t == bare_type or t == type_module)
                            for t in param.get('allowed_types', [])):
                        input_params[param['id']] = obj_param_value
                        upa_params.append(param['id'])

                (input_params,
                 ws_refs) = validate_parameters(app_id, tag, spec_params,
                                                input_params)
                (widget_name,
                 widget_data) = map_outputs_from_state([], input_params,
                                                       app_spec)

                # Figure out params for upas.
                for mapping in app_spec.get('behavior',
                                            {}).get('output_mapping', []):
                    if mapping.get(
                            'input_parameter',
                            '') in upa_params and 'target_property' in mapping:
                        upas[mapping['target_property']] = upa

        return self.show_output_widget(widget_name,
                                       widget_data,
                                       upas=upas,
                                       title=title,
                                       type="viewer",
                                       cell_id=cell_id)
예제 #19
0
    def run_local_app(
        self,
        app_id,
        params,
        tag="release",
        version=None,
        cell_id=None,
        run_id=None,
        widget_state=None,
    ):
        """
        Attempts to run a local app. These do not return a Job object, but just
        the result of the app. In most cases, this will be a Javascript display
        of the result, but could be anything.

        If the app_spec looks like it makes a service call, then this raises a
        ValueError. Otherwise, it validates each parameter in **kwargs against
        the app spec, executes it, and returns the result.

        Parameters:
        -----------
        app_id - should be from the app spec, e.g. 'view_expression_profile'
        params - the dictionary of parameters for the app. Should be key-value
                 pairs where they keys are strings. If any non-optional
                 parameters are missing, an informative string will be printed.
        tag - optional, one of [release|beta|dev] (default=release)
        version - optional, a semantic version string. Only released modules
                  have versions, so if the tag is not 'release', and a version
                  is given, a ValueError will be raised.

        Example:
        run_local_app('NarrativeViewers/view_expression_profile',
                      {
                          "input_expression_matrix": "MyMatrix",
                          "input_gene_ids": "1234"
                      },
                      version='0.0.1',
                      input_expression_matrix="MyMatrix")
        """
        spec = self._get_validated_app_spec(app_id, tag, False, version=version)

        # Here, we just deal with two behaviors:
        # 1. None of the above - it's a viewer.
        # 2. ***TODO*** python_class / python_function.
        #    Import and exec the python code.

        # for now, just map the inputs to outputs.
        # First, validate.
        # Preflight check the params - all required ones are present, all
        # values are the right type, all numerical values are in given ranges
        spec_params = self.spec_manager.app_params(spec)
        (params, ws_refs) = validate_parameters(app_id, tag, spec_params, params)

        # Log that we're trying to run a job...
        log_info = {
            "app_id": app_id,
            "tag": tag,
            "username": system_variable("user_id"),
            "ws": system_variable("workspace"),
        }
        kblogging.log_event(self._log, "run_local_app", log_info)

        self._send_comm_message(
            MESSAGE_TYPE["RUN_STATUS"],
            {
                "event": "success",
                "event_at": timestamp(),
                "cell_id": cell_id,
                "run_id": run_id,
            },
        )

        (output_widget, widget_params) = map_outputs_from_state([], params, spec)

        # All a local app does is route the inputs to outputs through the
        # spec's mapping, and then feed that into the specified output widget.
        wm = WidgetManager()
        if widget_state is not None:
            return wm.show_advanced_viewer_widget(
                output_widget, widget_params, widget_state, cell_id=cell_id, tag=tag
            )
        else:
            return wm.show_output_widget(
                output_widget, widget_params, cell_id=cell_id, tag=tag
            )
예제 #20
0
파일: job.py 프로젝트: briehl/narrative
 def _get_output_info(self, state):
     spec = self.app_spec()
     return map_outputs_from_state(state, map_inputs_from_job(self.parameters(), spec), spec)
예제 #21
0
파일: job.py 프로젝트: psdehal/narrative
 def _get_output_info(self, state):
     spec = self.app_spec()
     return map_outputs_from_state(
         state, map_inputs_from_job(self.parameters(), spec), spec)
예제 #22
0
    def show_data_widget(self, widget_name, params, title="", cell_id=None, tag="release"):
        """
        Renders a widget using the generic kbaseNarrativeOutputWidget container.

        Parameters
        ----------
        widget_name : string
            The name of the widget to print the widgets for.
        params : dict
            The dictionary of parameters that gets fed into the widget.
        """

        input_data = dict(params)
        obj_ref = None
        info = None
        if 'info' in params:
            info = params['info']
            obj_ref = str(info['ws_id']) + '/' + str(info['id']) + '/' + str(info['version'])
        elif 'ref' in params:
            obj_ref = params['ref']  # may include ref-path (or chain, not sure which one is text)
        else:
            raise ValueError("Neither 'info' nor 'ref' field is set in input parameters")
        info_tuple = clients.get('workspace').get_object_info_new({'objects': [{'ref': obj_ref}],
                                                                   'includeMetadata': 1})[0]
        input_data['info'] = info
        input_data['info_tuple'] = info_tuple

        bare_type = info_tuple[2].split('-')[0]
        
        type_spec = self._sm.get_type_spec(bare_type, raise_exception=False)
        if type_spec is None:
            input_data['error_message'] = "Type-spec wasn't found for '" + bare_type + "'"
        elif 'view_method_ids' not in type_spec or len(type_spec['view_method_ids']) != 1:
            input_data['error_message'] = ("Type-spec for '" + bare_type + "' should " +
                                           "have exactly one ID in 'view_method_ids' field")
        else:
            input_data['type_spec'] = type_spec
            method_id = type_spec['view_method_ids'][0]
            spec = self._sm.get_spec(method_id, tag=tag)
            input_data['app_spec'] = spec
            
            # Let's build output according to mappings in method-spec
            spec_params = self._sm.app_params(spec)
            input_params = {}
            is_ref_path = ';' in obj_ref
            is_external = info_tuple[7] != os.environ['KB_WORKSPACE_ID']
            # it's not safe to use reference yet (until we switch to them all over the Apps)
            # But in case we deal with ref-path we have to do it anyway:
            obj_param_value = obj_ref if (is_ref_path or is_external) else info_tuple[1]
            for param in spec_params:
                if any(t == bare_type for t in param['allowed_types']):
                    input_params[param['id']] = obj_param_value
    
            (input_params, ws_refs) = validate_parameters(method_id, tag,
                                                          spec_params, input_params)
            (output_widget, output) = map_outputs_from_state([], input_params, spec)
            input_data['output'] = output
        
        input_template = """
        element.html("<div id='{{input_id}}' class='kb-vis-area'></div>");

        require(['kbaseNarrativeOutputCell'], function(KBaseNarrativeOutputCell) {
            var w = new KBaseNarrativeOutputCell($('#{{input_id}}'), {
                "data": {{input_data}},
                "type":"viewer",
                "widget":"{{widget_name}}",
                "cellId":"{{cell_id}}",
                "title":"{{cell_title}}",
                "time":{{timestamp}}
            });
        });
        """

        js = Template(input_template).render(input_id=self._cell_id_prefix + str(uuid.uuid4()),
                                             widget_name=widget_name,
                                             input_data=json.dumps(input_data),
                                             cell_title=title,
                                             cell_id=cell_id,
                                             timestamp=int(round(time.time()*1000)))
        return Javascript(data=js, lib=None, css=None)
예제 #23
0
    def show_data_widget(self, upa, title=None, cell_id=None, tag="release"):
        """
        Renders a widget using the generic kbaseNarrativeOutputCell container.
        First, it looks up the UPA to get its object type. It then uses that type to look up
        what the viewer app should be. This contains the widget and the parameter mapping to view
        that widget. It then maps all of these together to run show_output_widget against a widget
        with a set of parameters for it.

        If there's an error here at any step, it still renders a widget, but it makes a
        kbaseNarrativeError widget instead, that'll hopefully be informative.

        Parameters
        ----------
        upa : string
            UPA defining a workspace object. Used to translate that object into parameters
            for the mapping to the data object used in the output cell.
            This may also be a Workspace reference path.
        title=None : string
            A title for the cell. If None, this just gets replaced with an empty string.
        cell_id=None : string
            if not None, this should be the id of the cell where the widget will live. Generated by
            the Narrative frontend.
        tag="release" : string
            All objects are related to their viewers by an app. This is the tag for that app's
            release state (should be one of release, beta, or dev)
        """
        widget_name = 'widgets/function_output/kbaseDefaultObjectView'   # set as default, overridden below
        widget_data = dict()
        upas = dict()
        info_tuple = clients.get('workspace').get_object_info_new({'objects': [{'ref': upa}],
                                                                   'includeMetadata': 1})[0]
        bare_type = info_tuple[2].split('-')[0]
        type_module = bare_type.split(".")[0]

        type_spec = self._sm.get_type_spec(bare_type, raise_exception=False)

        if type_spec is None:
            widget_data = {
                "error": {
                    "msg": "Unable to find viewer specification for objects of type {}.".format(bare_type),
                    "method_name": "WidgetManager.show_data_widget",
                    "traceback": "Can't find type spec info for type {}".format(bare_type)
                }
            }
            upas['upas'] = [upa]  # doompety-doo
        else:
            if not type_spec.get('view_method_ids'):
                return "No viewer found for objects of type {}".format(bare_type)
            app_id = type_spec['view_method_ids'][0]
            app_spec = None
            try:
                app_spec = self._sm.get_spec(app_id, tag=tag)
            except Exception as e:
                widget_data = {
                    "error": {
                        "msg": "Unable to find specification for viewer app {}".format(app_id),
                        "method_name": "WidgetManager.show_data_widget",
                        "traceback": e.message
                    }
                }
            if app_spec is not None:
                spec_params = self._sm.app_params(app_spec)
                input_params = {}
                is_ref_path = ';' in upa
                is_external = info_tuple[7] != os.environ['KB_WORKSPACE_ID']
                # it's not safe to use reference yet (until we switch to them all over the Apps)
                # But in case we deal with ref-path we have to do it anyway:
                obj_param_value = upa if (is_ref_path or is_external) else info_tuple[1]
                upa_params = list()
                for param in spec_params:
                    if param.get('allowed_types') is None or any((t == bare_type or t == type_module) for t in param.get('allowed_types', [])):
                        input_params[param['id']] = obj_param_value
                        upa_params.append(param['id'])

                (input_params, ws_refs) = validate_parameters(app_id, tag,
                                                              spec_params, input_params)
                (widget_name, widget_data) = map_outputs_from_state([], input_params, app_spec)

                # Figure out params for upas.
                for mapping in app_spec.get('behavior', {}).get('output_mapping', []):
                    if mapping.get('input_parameter', '') in upa_params and 'target_property' in mapping:
                        upas[mapping['target_property']] = upa

        return self.show_output_widget(
            widget_name,
            widget_data,
            upas=upas,
            title=title,
            type="viewer",
            cell_id=cell_id
        )