Пример #1
0
Файл: plugin.py Проект: raiju/bs
 def index(self, ordered=False):
     """
     Get all plugins available
     @param ordered: if you want a nested json based on
     plugins paths
     """
     user = util.get_user(tg.request)
     if user.is_service:
         d = {'plugins': putil.get_plugins_path(service=user, ordered=ordered)}
     else:
         d = {'plugins': putil.get_plugins_path(ordered=ordered)}
     return d
Пример #2
0
Файл: logger.py Проект: bbcf/bs
 def wrapped(self, *args, **kw):
     user = util.get_user(request)
     conn = model.Connection()
     conn.user_id = user.id
     conn.ip = request.remote_addr
     conn.user_agent = request.user_agent
     conn.url = request.url
     conn.method = request.method
     conn.content_length = request.content_length
     conn.content_type = request.content_type
     conn.query_string = request.query_string
     conn.body = ','.join(['%s:%s' % (k, v) for k, v in request.params.iteritems()])
     model.DBSession.add(conn)
     return fn(self, *args, **kw)
Пример #3
0
 def wrapped(self, *args, **kw):
     user = util.get_user(request)
     conn = model.Connection()
     conn.user_id = user.id
     conn.ip = request.remote_addr
     conn.user_agent = request.user_agent
     conn.url = request.url
     conn.method = request.method
     conn.content_length = request.content_length
     conn.content_type = request.content_type
     conn.query_string = request.query_string
     conn.body = ','.join(
         ['%s:%s' % (k, v) for k, v in request.params.iteritems()])
     model.DBSession.add(conn)
     return fn(self, *args, **kw)
Пример #4
0
 def index(self, ordered=False):
     """
     Get all plugins available
     @param ordered: if you want a nested json based on
     plugins paths
     """
     user = util.get_user(tg.request)
     if user.is_service:
         d = {
             'plugins':
             operations.get_plugins_path(service=user, ordered=ordered)
         }
     else:
         d = {'plugins': operations.get_plugins_path(ordered=ordered)}
     return d
Пример #5
0
Файл: plugin.py Проект: raiju/bs
    def get(self, id, *args, **kw):
        """
        Display the form by it's id
        """
        # check plugin id
        plug = None
        try:
            plug = putil.get_plugin_byId(id)
        except:
            tg.abort(400, "Bad plugin identifier")

        debug('get plugin %s' % id)
        # get the plugin
        obj = plug
        info = obj.info
        form = info.get('output')()
        desc = info.get('description')
        debug('params =  %s' % kw, 1)
        # bioscript parameters
        bs_private = {}
        if 'bs_private' in kw:
            bs_private = json.loads(kw['bs_private'])
            debug("get bs private parameters %s" % bs_private, 2)

        if 'prefill' in bs_private:
            prefill_fields(info.get('in'), form, bs_private['prefill'], kw)

        # {'bs_private': {'app': pp, 'cfg': handler.job.bioscript_config, 'prefill': prefill}})

        # add some private parameters from BioScript
        pp = {'id': id}
        # if user is a serviec, add the key & the mail in the authentication
        user = util.get_user(tg.request)
        if user.is_service:
            pp['mail'] = user.email
            pp['key'] = user.key
        bs_private['pp'] = pp

        # prepare form output
        main_proxy = tg.config.get('main.proxy')
        widget = form(action=main_proxy + tg.url('/plugins/validate', {'id': id})).req()
        widget.value = {'bs_private': json.dumps(bs_private), 'key': user.key}
        debug('display plugin with bs_private : %s' % bs_private)
        debug('vaaalue : %s' % widget.value)

        debug(user)
        return {'page': 'plugin', 'desc': desc, 'title': info.get('title'), 'widget': widget}
Пример #6
0
Файл: plugin.py Проект: raiju/bs
    def validate(self, **kw):
        """
        plugin parameters validation
        """
        user = util.get_user(tg.request)
        debug('Got request validation from user %s' % user)
        if not 'bs_private' in kw:
            tg.abort(400, "Plugin identifier not found in the request.")
        debug('params %s' % kw, 1)

        bs_private = copy.deepcopy(json.loads(kw['bs_private']))
        debug('private %s' % bs_private, 1)
        plugin_id = bs_private['pp']['id']
        if plugin_id is None:
            tg.abort(400, "Plugin identifier not found in the request.")

        # check plugin id
        plug = putil.get_plugin_byId(plugin_id)
        if plug is None:
            tg.abort(400, "Bad plugin identifier")

        # get plugin form output
        obj = plug
        info = obj.info
        form = info.get('output')()

        # callback for jsonP
        callback = kw.get('callback', 'callback')
        # get the plugin from the database
        plugin_db = DBSession.query(Plugin).filter(Plugin.generated_id == obj.unique_id()).first()
        plugin_request = _log_form_request(plugin_id=plugin_db.id, user=user, parameters=kw)

        if 'prefill' in bs_private:
            prefill_fields(info.get('in'), form, bs_private['prefill'], kw, replace_value=False)
            debug('prefill in validation', 3)
            del bs_private['prefill']

        # validation
        try:
            form = form().req()
            form.validate(kw)
        except (tw2.core.ValidationError, Invalid) as e:
            main_proxy = tg.config.get('main.proxy')
            e.widget.action = main_proxy + tg.url('plugins/index', {'id': plugin_id})
            debug('private after validation failed %s' % bs_private, 1)
            #value = {'bs_private': json.dumps(bs_private)}
            #debug('value %s' % value)
            #e.widget.value = value
            plugin_request.status = 'FAILED'
            plugin_request.error = str(e)
            DBSession.add(plugin_request)
            return jsonp_response(**{'validation': 'failed', 'desc': info.get('description'),
                    'title': info.get('title'), 'widget': e.widget.display(), 'callback': callback})
        debug('Validation pass')
        #if the validation passes, remove private parameters from the request
        del kw['bs_private']
        if 'key' in kw:
            del kw['key']
        # fetch form files
        try:
            inputs_directory = filemanager.fetch(user, obj, kw)
        except Exception as e:
            plugin_request.status = 'FAILED'
            plugin_request.error = str(e)
            DBSession.add(plugin_request)
            import sys
            import traceback
            etype, value, tb = sys.exc_info()
            traceback.print_exception(etype, value, tb)
            return jsonp_response(**{'validation': 'success', 'desc': info.get('description'),
                                    'title':  info.get('title'), 'error': 'error while fetching files : ' + str(e), 'callback': callback})
        debug('Files fetched')
        # get output directory to write results
        outputs_directory = filemanager.temporary_directory(constants.paths['data'])
        service_callback = None
        debug(user)
        if user.is_service:
            debug('is service', 1)
            # def out_path(service_name):
            o = services.service_manager.get(user.name, constants.SERVICE_RESULT_ROOT_PARAMETER)
            if o:
                outputs_directory = o
            service_callback = services.service_manager.get(user.name, constants.SERVICE_CALLBACK_URL_PARAMETER)

        debug('Output dir = %s' % outputs_directory)
        # get user parameters from the request
        user_parameters = bs_private.get('app', "{}")
        debug('get user parameters : %s' % user_parameters, 1)
        # get response config from the request
        resp_config = bs_private.get('cfg', None)

        plugin_info = {'title': info['title'],
                        'plugin_id': plugin_db.id,
                        'generated_id': plugin_db.generated_id,
                        'description': info['description'],
                        'path': info['path'],
                        'in': info['in'],
                        'out': info['out'],
                        'meta': info['meta']}

        # call plugin process
        bioscript_callback = tg.config.get('main.proxy') + '/' + tg.url('plugins/callback_results')
        async_res = tasks.plugin_job.delay(user.name, inputs_directory, outputs_directory, plugin_info,
            user_parameters, service_callback, bioscript_callback, **kw)
        task_id = async_res.task_id

        _log_job_request(plugin_request.id, task_id)

        if resp_config and resp_config.get('plugin_info', '') == 'min':
            return jsonp_response(**{'validation': 'success', 'plugin_id': plugin_id, 'task_id': task_id, 'callback': callback, 'app': user_parameters})
        return jsonp_response(**{
                'validation': 'success',
                'plugin_id': plugin_id,
                'task_id': task_id,
                'plugin_info': json.dumps(
                    {'title': info['title'],
                    'description': info['description'],
                    'path': info['path'],
                    'in': info['in'],
                    'out': info['out'],
                    'meta': info['meta']}),
                'callback': callback, 'app': user_parameters})
Пример #7
0
Файл: plugin.py Проект: bbcf/bs
    def fetch(self, oid, *args, **kw):
        """
        Display the form by it's id
        """
        debug('\n[plugin controller]FETCH')
        # check plugin id
        plug = None
        try:
            plug = operations.get_plugin_byId(oid)
        except:
            tg.abort(400, "Bad plugin identifier")

        debug('[x] get plugin %s' % oid,)
        # get the plugin
        obj = plug
        info = obj.info
        form = info.get('output')()
        desc = plug.description_as_html

        debug('[x] params =  %s' % kw,)
        # bioscript parameters
        bs_private = {}
        if 'bs_private' in kw:
            bs_private = json.loads(kw['bs_private'])
            debug("[x] get bs private parameters %s" % bs_private,)

        if 'prefill' in bs_private:
            prefill_fields(info.get('in'), form, bs_private['prefill'], kw)

        # add some private parameters from BioScript
        pp = {'id': oid}
        # if user is a service, add the key & the mail in the authentication
        user = util.get_user(tg.request)
        if user.is_service:
            pp['mail'] = user.email
            pp['key'] = user.key
        bs_private['pp'] = pp

        # prepare form output
        main_proxy = tg.config.get('main.proxy')
        widget = form(action=main_proxy + tg.url('/plugins/validate', {'id': oid})).req()
        widget.value = {'bs_private': json.dumps(bs_private), 'key': user.key}
        debug('display plugin with bs_private : %s' % bs_private)
        debug('vaaalue : %s' % widget.value)

        debug(user)
        debug('END FETCH')
        html_doc = ''
        html_src_code = ''
        try:
            html_doc = obj.html_doc_link()
            html_src_code = obj.html_source_code_link()
        except Exception as e:
            print '"html_doc" and "src_code" seems to be missing for your plugin, please update bsplugins to the last version'
            print e

        meta = info.get('meta', {})
        return {'page': 'plugin',
        'desc': desc,
        'title': info.get('title'),
        'widget': widget,
        'html_doc': html_doc,
        'html_src_code': html_src_code,
        'author': meta.get('author'),
        'contact': meta.get('contact')}
Пример #8
0
Файл: plugin.py Проект: bbcf/bs
    def validate(self, **kw):
        """
        plugin parameters validation
        """
        user = util.get_user(tg.request)
        # get private bioscript parameters
        if not 'bs_private' in kw:
            debug('bs_private not found')
            tg.abort(400, "Plugin identifier not found in the request.")
        bs_private = copy.deepcopy(json.loads(kw['bs_private']))

        debug('\n[plugin controller]\nVALIDATE %s' % kw,)


        # get the plugin from the private parameters
        plugin_id = 0
        try:
            plugin_id = bs_private['pp']['id']
        except KeyError:
            tg.abort(400, "Plugin identifier not found in the request.")
        if plugin_id == 0:
            tg.abort(400, "Plugin identifier not found in the request.")
        plug = operations.get_plugin_byId(plugin_id)
        if plug is None:
            tg.abort(400, "Bad plugin identifier.")

        # get the plugin from database
        plugin_db = DBSession.query(Plugin).filter(Plugin.generated_id == plug.unique_id()).first()

        


        # validate the form
        # we must do an HTTP call because I don't find a way
        # to call the 'render' method on 'plugin_validate' template
        request_url = tg.config.get('main.proxy') + '/plugins/_validate'
        validated = True
        info = plug.info
        # get the callback if any
        callback = kw.get('callback', 'callback')
        try:
            form = urllib2.urlopen(request_url, urllib.urlencode(kw)).read()

            # add some header because the request can come from another domain
            response.headers['Access-Control-Allow-Headers'] = 'X-CSRF-Token'
            response.headers['Access-Control-Allow-Origin'] = '*'

            
            try:
                form = json.loads(form)
            except:
                pass
           
            validated = isinstance(form, dict)


        except Exception as e:
            util.print_traceback()
            validated = False
            form = 'Problem with Bioscript server.'

        if not validated:
            debug('Validation failed',)
            return json.dumps({'validation': 'failed',
                               'desc': info.get('description'),
                               'title': info.get('title'),
                               'widget': form,
                               'callback': callback})

        # validation passes
        new_params = form['params']
        new_params = kw
        debug('Validation passes with params : %s' % new_params,)

        # we regoup all multi stuff in a single list:
        # for instance a multi field will give parameters like:
        # {SigMulti:1:signals: val1, SigMulti:2:signals: val2, ...}
        # and we will transform it to
        # {SigMulti: { signals : [val1, val2], ...}
        
        grouped_params = {}
        todel = []
        for k, v in new_params.iteritems():
            m = multipattern.match(k)
            if m is not None:
                todel.append(k)
                if v or isinstance(v, cgi.FieldStorage):
                    key1, n, key2 = m.groups()
                    if key1 not in grouped_params:
                        grouped_params[key1] = {}
                    if key2 in grouped_params[key1]:
                        grouped_params[key1][key2][int(n) - 1] = v
                    elif not key2.endswith('bs_group'):
                        sl = SparseList()
                        sl[int(n) - 1] = v
                        grouped_params[key1][key2] = sl


        debug('group "multi" params: %s' % grouped_params)
        # debug('check fieldstorages',)
        # # must keep fieldstorages because they were converted to str
        # fs_bk = []
        # import cgi
        # for k, v in kw.iteritems():
        #     if isinstance(v, cgi.FieldStorage):
        #         fs_bk.append((k, v))
        # debug(fs_bk)

        # for fsk, fsv in fs_bk:
        #     m = multipattern.match(fsk)
        #     if m:
        #         key1, n, key2 = m.groups()
        #         grouped_params[key1][key2][int(n) - 1] = fsv
        #     else:
        #         grouped_params[fsk] = fsv
        new_params.update(grouped_params)
        
        # delete multi parameters
        for td in todel:
            del new_params[td]

        # but we need to keep all params that are multi and urls
        kw = new_params
       
        #remove private parameters from the request
        if 'bs_private' in kw:
            del kw['bs_private']
        if 'key' in kw:
            del kw['key']

        debug('New params are : %s' % new_params,)

        # update plugin arameters
        # log the request, it's a valid one
        plugin_request = _log_form_request(plugin_id=plugin_db.id, user=user, parameters=dict(kw))
        DBSession.add(plugin_request)
    
        debug('get output directory',)
        # get output directory to write results
        outputs_directory = filemanager.temporary_directory(constants.paths['data'])
        service_callback = None
        # if the user is a service, get parameters from configuration
        if user.is_service:
            debug('is service',)
            o = services.service_manager.get(user.name, constants.SERVICE_RESULT_ROOT_PARAMETER)
            if o:
                outputs_directory = o
            service_callback = services.service_manager.get(user.name, constants.SERVICE_CALLBACK_URL_PARAMETER)
        debug('Write result in %s' % outputs_directory,)
        

        # get prvate parameters from the request
        private_parameters = bs_private.get('app', "{}")

        # get response configuration from the request
        resp_config = bs_private.get('cfg', None)
        plugin_info = {'title': info['title'],
                       'plugin_id': plugin_db.id,
                       'generated_id': plugin_db.generated_id,
                       'description': info['description'],
                       'path': info['path'],
                       'in': info['in'],
                       'out': info['out'],
                       'meta': info['meta']}

        # define the bioscript callback
        bioscript_callback = tg.config.get('main.proxy') + '/' + tg.url('plugins/callback_results')
        debug("callback on bs : %s " % bioscript_callback,)

        # if some files come from a file field, we must download them directly
        inputs_directory, dwdfiles = filemanager.fetchfilefields(user, plug, kw)

        # chain jobs : fetch files then plugin process
        async_res = tasks.plugin_job.delay(user,
                                   plug,
                                   inputs_directory,
                                   outputs_directory,
                                   dwdfiles,
                                   plugin_info,
                                   private_parameters,
                                   service_callback,
                                   bioscript_callback,
                                   **kw)

        task_id = async_res.task_id
        debug('Launch task %s' % task_id,)

        # log the job request
        _log_job_request(plugin_request.id, task_id)

        #prepare the response
        resp = {'validation': 'success',
                'plugin_id': plugin_id,
                'task_id': task_id,
                'callback': callback,
                'app': private_parameters}
        if resp_config and resp_config.get('plugin_info', '') == 'min':
            resp.update({'plugin_info': json.dumps({'title': info['title'],
                                                    'description': info['description'],
                                                    'path': info['path'],
                                                    'in': info['in'],
                                                    'out': info['out'],
                                                    'meta': info['meta']})})
        return json.dumps(resp)
Пример #9
0
    def fetch(self, oid, *args, **kw):
        """
        Display the form by it's id
        """
        debug('\n[plugin controller]FETCH')
        # check plugin id
        plug = None
        try:
            plug = operations.get_plugin_byId(oid)
        except:
            tg.abort(400, "Bad plugin identifier")

        debug('[x] get plugin %s' % oid, )
        # get the plugin
        obj = plug
        info = obj.info
        form = info.get('output')()
        desc = plug.description_as_html

        debug('[x] params =  %s' % kw, )
        # bioscript parameters
        bs_private = {}
        if 'bs_private' in kw:
            bs_private = json.loads(kw['bs_private'])
            debug("[x] get bs private parameters %s" % bs_private, )

        if 'prefill' in bs_private:
            prefill_fields(info.get('in'), form, bs_private['prefill'], kw)

        # add some private parameters from BioScript
        pp = {'id': oid}
        # if user is a service, add the key & the mail in the authentication
        user = util.get_user(tg.request)
        if user.is_service:
            pp['mail'] = user.email
            pp['key'] = user.key
        bs_private['pp'] = pp

        # prepare form output
        main_proxy = tg.config.get('main.proxy')
        widget = form(action=main_proxy +
                      tg.url('/plugins/validate', {'id': oid})).req()
        widget.value = {'bs_private': json.dumps(bs_private), 'key': user.key}
        debug('display plugin with bs_private : %s' % bs_private)
        debug('vaaalue : %s' % widget.value)

        debug(user)
        debug('END FETCH')
        html_doc = ''
        html_src_code = ''
        try:
            html_doc = obj.html_doc_link()
            html_src_code = obj.html_source_code_link()
        except Exception as e:
            print '"html_doc" and "src_code" seems to be missing for your plugin, please update bsplugins to the last version'
            print e

        meta = info.get('meta', {})
        return {
            'page': 'plugin',
            'desc': desc,
            'title': info.get('title'),
            'widget': widget,
            'html_doc': html_doc,
            'html_src_code': html_src_code,
            'author': meta.get('author'),
            'contact': meta.get('contact')
        }
Пример #10
0
    def validate(self, **kw):
        """
        plugin parameters validation
        """
        user = util.get_user(tg.request)
        # get private bioscript parameters
        if not 'bs_private' in kw:
            debug('bs_private not found')
            tg.abort(400, "Plugin identifier not found in the request.")
        bs_private = copy.deepcopy(json.loads(kw['bs_private']))

        debug('\n[plugin controller]\nVALIDATE %s' % kw, )

        # get the plugin from the private parameters
        plugin_id = 0
        try:
            plugin_id = bs_private['pp']['id']
        except KeyError:
            tg.abort(400, "Plugin identifier not found in the request.")
        if plugin_id == 0:
            tg.abort(400, "Plugin identifier not found in the request.")
        plug = operations.get_plugin_byId(plugin_id)
        if plug is None:
            tg.abort(400, "Bad plugin identifier.")

        # get the plugin from database
        plugin_db = DBSession.query(Plugin).filter(
            Plugin.generated_id == plug.unique_id()).first()

        # validate the form
        # we must do an HTTP call because I don't find a way
        # to call the 'render' method on 'plugin_validate' template
        request_url = tg.config.get('main.proxy') + '/plugins/_validate'
        validated = True
        info = plug.info
        # get the callback if any
        callback = kw.get('callback', 'callback')
        try:
            form = urllib2.urlopen(request_url, urllib.urlencode(kw)).read()

            # add some header because the request can come from another domain
            response.headers['Access-Control-Allow-Headers'] = 'X-CSRF-Token'
            response.headers['Access-Control-Allow-Origin'] = '*'

            try:
                form = json.loads(form)
            except:
                pass

            validated = isinstance(form, dict)

        except Exception as e:
            util.print_traceback()
            validated = False
            form = 'Problem with Bioscript server.'

        if not validated:
            debug('Validation failed', )
            return json.dumps({
                'validation': 'failed',
                'desc': info.get('description'),
                'title': info.get('title'),
                'widget': form,
                'callback': callback
            })

        # validation passes
        new_params = form['params']
        new_params = kw
        debug('Validation passes with params : %s' % new_params, )

        # we regoup all multi stuff in a single list:
        # for instance a multi field will give parameters like:
        # {SigMulti:1:signals: val1, SigMulti:2:signals: val2, ...}
        # and we will transform it to
        # {SigMulti: { signals : [val1, val2], ...}

        grouped_params = {}
        todel = []
        for k, v in new_params.iteritems():
            m = multipattern.match(k)
            if m is not None:
                todel.append(k)
                if v or isinstance(v, cgi.FieldStorage):
                    key1, n, key2 = m.groups()
                    if key1 not in grouped_params:
                        grouped_params[key1] = {}
                    if key2 in grouped_params[key1]:
                        grouped_params[key1][key2][int(n) - 1] = v
                    elif not key2.endswith('bs_group'):
                        sl = SparseList()
                        sl[int(n) - 1] = v
                        grouped_params[key1][key2] = sl

        debug('group "multi" params: %s' % grouped_params)
        # debug('check fieldstorages',)
        # # must keep fieldstorages because they were converted to str
        # fs_bk = []
        # import cgi
        # for k, v in kw.iteritems():
        #     if isinstance(v, cgi.FieldStorage):
        #         fs_bk.append((k, v))
        # debug(fs_bk)

        # for fsk, fsv in fs_bk:
        #     m = multipattern.match(fsk)
        #     if m:
        #         key1, n, key2 = m.groups()
        #         grouped_params[key1][key2][int(n) - 1] = fsv
        #     else:
        #         grouped_params[fsk] = fsv
        new_params.update(grouped_params)

        # delete multi parameters
        for td in todel:
            del new_params[td]

        # but we need to keep all params that are multi and urls
        kw = new_params

        #remove private parameters from the request
        if 'bs_private' in kw:
            del kw['bs_private']
        if 'key' in kw:
            del kw['key']

        debug('New params are : %s' % new_params, )

        # update plugin arameters
        # log the request, it's a valid one
        plugin_request = _log_form_request(plugin_id=plugin_db.id,
                                           user=user,
                                           parameters=dict(kw))
        DBSession.add(plugin_request)

        debug('get output directory', )
        # get output directory to write results
        outputs_directory = filemanager.temporary_directory(
            constants.paths['data'])
        service_callback = None
        # if the user is a service, get parameters from configuration
        if user.is_service:
            debug('is service', )
            o = services.service_manager.get(
                user.name, constants.SERVICE_RESULT_ROOT_PARAMETER)
            if o:
                outputs_directory = o
            service_callback = services.service_manager.get(
                user.name, constants.SERVICE_CALLBACK_URL_PARAMETER)
        debug('Write result in %s' % outputs_directory, )

        # get prvate parameters from the request
        private_parameters = bs_private.get('app', "{}")

        # get response configuration from the request
        resp_config = bs_private.get('cfg', None)
        plugin_info = {
            'title': info['title'],
            'plugin_id': plugin_db.id,
            'generated_id': plugin_db.generated_id,
            'description': info['description'],
            'path': info['path'],
            'in': info['in'],
            'out': info['out'],
            'meta': info['meta']
        }

        # define the bioscript callback
        bioscript_callback = tg.config.get('main.proxy') + '/' + tg.url(
            'plugins/callback_results')
        debug("callback on bs : %s " % bioscript_callback, )

        # if some files come from a file field, we must download them directly
        inputs_directory, dwdfiles = filemanager.fetchfilefields(
            user, plug, kw)

        # chain jobs : fetch files then plugin process
        async_res = tasks.plugin_job.delay(user, plug, inputs_directory,
                                           outputs_directory, dwdfiles,
                                           plugin_info, private_parameters,
                                           service_callback,
                                           bioscript_callback, **kw)

        task_id = async_res.task_id
        debug('Launch task %s' % task_id, )

        # log the job request
        _log_job_request(plugin_request.id, task_id)

        #prepare the response
        resp = {
            'validation': 'success',
            'plugin_id': plugin_id,
            'task_id': task_id,
            'callback': callback,
            'app': private_parameters
        }
        if resp_config and resp_config.get('plugin_info', '') == 'min':
            resp.update({
                'plugin_info':
                json.dumps({
                    'title': info['title'],
                    'description': info['description'],
                    'path': info['path'],
                    'in': info['in'],
                    'out': info['out'],
                    'meta': info['meta']
                })
            })
        return json.dumps(resp)