Пример #1
0
def to_nexson():
    global UPLOADID_PAT
    from externalproc import get_external_proc_dir_for_upload, get_logger, invoc_status, \
            ExternalProcStatus, get_conf, write_input_files, write_ext_proc_content, do_ext_proc_launch
    import os
    import datetime
    import codecs
    import locket
    import shutil
    import uuid
    from peyotl.nexson_syntax import can_convert_nexson_forms, \
                                     get_ot_study_info_from_nexml, \
                                     add_resource_meta, \
                                     convert_nexson_format, \
                                     BADGER_FISH_NEXSON_VERSION
    from peyotl.manip import count_num_trees
    '''
    Controller for conversion of NEXUS, newick, or NeXML to NeXSON
    Required arguments:
        "file" should be a multipart-encoded file to be translated to NexSON
          OR
        "content" which is a string that contains the content of the file
            format. "content" is checked if "file" is not provided.
    Required arguments for subsequent calls:
        "uploadId" - The "uploadId" returned from the first invocation
    Optional arguments:
        "uploadId" - A unique string for this upload (optional for *first* call
            only). This is no longer encouraged, since a uuid will be provided.
        "output" one of ['ot:nexson', 'nexson', 'nexml', 'input', 'provenance']
            the default is ot:nexson. This specifies what is to be returned.
            Possible values are: 
            "ot:nexson" is the Open Tree NexSON (with character data culled).
                This should be the first call. Subsequent
                calls can retrieve intermediates. JSON.
            "nexson" is the complete NexSON version of the data. JSON.
            "nexml" is the NeXML version of the file. This is an intermediate
                for the NexSON. XML.
            "input" returns the uploaded file. text/plain.
            "provenance" returns a simple, ad-hoc JSON with initial call details.
        "dataDeposit" should be a URL that should be added to the meta element
            in the Open Tree NexSON object.
        "inputFormat" should be "nexus", "newick", or "nexml"
            default is "nexus"
        "nexml2json" should be "0.0", "1.0", or "1.2". The more
            specific forms: "0.0.0", "1.0.0", or "1.2.1" will also work.
        "idPrefix" should be an empty string (or all whitespace) if you want 
                to use the firstAvailableXXXID args:
            firstAvailableEdgeID,
            firstAvailableNodeID,
            firstAvailableOTUID,
            firstAvailableOTUsID,
            firstAvailableTreeID,
            firstAvailableTreesID
          If idPrefix is not all whitespace it will be stripped, 
            the NCLconverter default names are used
          If idPrefix is not supplied, a uuid will be the prefix for the 
            names and the names will follow the NCL converter defaults

    N.B. Further documentation is available in curator/README.md
    '''
    _LOG = get_logger(request, 'to_nexson')
    if request.env.request_method == 'OPTIONS':
        raise HTTP(200, T('Preflight approved!'))
    orig_args = {}
    is_upload = False
    # several of our NexSON use "uploadid" instead of "uploadId" so we should accept either
    if ('uploadId' in request.vars) or ('uploadid' in request.vars):
        try:
            if ('uploadId' in request.vars):
                unique_id = request.vars.uploadId
            else:
                unique_id = request.vars.uploadid
            unique_id = str(unique_id)
        except:
            raise HTTP(400, T('Illegal uploadId "{u}"'.format(u=unique_id)))
    else:
        is_upload = True
        unique_id = 'u' + str(uuid.uuid4())
    if not UPLOADID_PAT.match(unique_id):
        raise HTTP(
            400,
            T('uploadId must be series of letters, numbers, dots or dashes between 5 and 85 characters long. "{u}" does not match this pattern'
              .format(u=unique_id)))
    try:
        idPrefix = request.vars.idPrefix.strip()
    except:
        idPrefix = unique_id
    if idPrefix and (not ID_PREFIX_PAT.match(idPrefix)):
        raise HTTP(
            400,
            'idPrefix must be start with a letter. "{u}" does not match this pattern'
            .format(u=idPrefix))

    output = request.vars.output or 'ot:nexson'
    output = output.lower()
    if output == 'ot%3anexson':
        # handle unwanted encoding (happens if file submitted)
        output = 'ot:nexson'
    output_choices = ['ot:nexson', 'nexson', 'nexml', 'input', 'provenance']
    if output not in output_choices:
        raise HTTP(
            400, 'The "output" should be one of: "{c}"'.format(
                c='", "'.join(output_choices)))
    try:
        working_dir = get_external_proc_dir_for_upload(request, '2nexml',
                                                       unique_id, is_upload)
    except Exception, x:
        raise HTTP(404)
Пример #2
0
def to_nexml():
    if len(request.args) == 1:
        _LOG = get_logger(request, 'study')
        try:
            field = db['study_file']['file']
        except Error:
            sys.stderr.write('odd\n')
            raise HTTP(404)
        name = request.args[-1]
        sys.stderr.write('looking for file "' + name + '"\n')
        try:
            ext_proc_dir = get_external_proc_dir_for_upload(request, db, name)
        except ValueError:
            raise HTTP(404)
        if ext_proc_dir is None:
            raise HTTP(404)

        #@TEMPORARY could be refactored into a create_ext_proc_subdir() call
        to_nexml_dir = os.path.join(ext_proc_dir, '2nexml')
        if not os.path.exists(to_nexml_dir):
            os.makedirs(to_nexml_dir)
            _LOG.info('Created directory "%s"' % to_nexml_dir)
        block = True
        timeout_duration = 0.1  #@TEMPORARY should not be hard coded

        out_filename = 'out.xml'
        err_filename = 'err.txt'

        #@TEMPORARY could be refactored into a launch_or_get_status() call
        status = invoc_status(request, to_nexml_dir)
        launched_this_call = False
        if status == ExternalProcStatus.NOT_FOUND:
            try:
                try:
                    exe_path = get_conf(request).get("external", "2nexml")
                except:
                    _LOG.warn("Config does not have external/2nexml setting")
                    raise
                assert (os.path.exists(exe_path))
            except:
                _LOG.warn("Could not find the 2nexml executable")
                raise HTTP(
                    501,
                    T("Server is not configured to allow 2nexml conversion"))
            try:
                (filename, upload_stream) = field.retrieve(name)
            except IOError:
                sys.stderr.write('not found\n')
                raise HTTP(404)
            do_ext_proc_launch(request,
                               to_nexml_dir, [exe_path, 'in.nex'],
                               out_filename,
                               err_filename, [('in.nex', upload_stream)],
                               wait=block)
            if not block:
                time.sleep(timeout_duration)
            status = invoc_status(request, to_nexml_dir)
            assert (status != ExternalProcStatus.NOT_FOUND)
            launched_this_call = True
        if status == ExternalProcStatus.RUNNING:
            if not launched_this_call:
                time.sleep(timeout_duration)
                status = invoc_status(request, to_nexml_dir)
            if status == ExternalProcStatus.RUNNING:
                return HTTP(102, T("Process still running"))
        #@TEMPORARY /end of potential launch_or_get_status call...

        if status == ExternalProcStatus.FAILED:
            try:
                err_file = os.path.join(to_nexml_dir, err_filename)
                err_content = 'Error message:\n ' + open(err_file, 'rU').read()
            except:
                err_content = ''
            response.headers['Content-Type'] = 'text/xml'
            raise HTTP(501, T("Conversion to NeXML failed.\n" + err_content))
        output = os.path.join(to_nexml_dir, 'out.xml')
        response.headers['Content-Type'] = 'text/xml'
        return open(output, 'rU').read()

    else:
        raise HTTP(301)
    return response.download(request, db)
Пример #3
0
def to_nexml():
    if len(request.args) == 1:
        _LOG = get_logger(request, 'study')
        try:
            field = db['study_file']['file']
        except Error:
            sys.stderr.write('odd\n')
            raise HTTP(404)
        name = request.args[-1]
        sys.stderr.write('looking for file "' + name + '"\n')
        try:
            ext_proc_dir = get_external_proc_dir_for_upload(request, db, name)
        except ValueError:
            raise HTTP(404)
        if ext_proc_dir is None:
            raise HTTP(404)

        #@TEMPORARY could be refactored into a create_ext_proc_subdir() call
        to_nexml_dir = os.path.join(ext_proc_dir, '2nexml')
        if not os.path.exists(to_nexml_dir):
            os.makedirs(to_nexml_dir)
            _LOG.info('Created directory "%s"' % to_nexml_dir)
        block = True
        timeout_duration = 0.1 #@TEMPORARY should not be hard coded

        out_filename = 'out.xml'
        err_filename = 'err.txt'

        #@TEMPORARY could be refactored into a launch_or_get_status() call
        status = invoc_status(request, to_nexml_dir)
        launched_this_call = False
        if status == ExternalProcStatus.NOT_FOUND:
            try:
                try:
                    exe_path = get_conf(request).get("external", "2nexml")
                except:
                    _LOG.warn("Config does not have external/2nexml setting")
                    raise
                assert(os.path.exists(exe_path))
            except:
                _LOG.warn("Could not find the 2nexml executable")
                raise HTTP(501, T("Server is not configured to allow 2nexml conversion"))
            try:
                (filename, upload_stream) = field.retrieve(name)
            except IOError:
                sys.stderr.write('not found\n')
                raise HTTP(404)
            do_ext_proc_launch(request,
                               to_nexml_dir,
                               [exe_path, 'in.nex'],
                               out_filename,
                               err_filename,
                               [('in.nex', upload_stream)],
                               wait=block)
            if not block:
                time.sleep(timeout_duration)
            status = invoc_status(request, to_nexml_dir)
            assert(status != ExternalProcStatus.NOT_FOUND)
            launched_this_call = True
        if status == ExternalProcStatus.RUNNING:
            if not launched_this_call:
                time.sleep(timeout_duration)
                status = invoc_status(request, to_nexml_dir)
            if status == ExternalProcStatus.RUNNING:
                return HTTP(102, T("Process still running"))
        #@TEMPORARY /end of potential launch_or_get_status call...
        
        if status == ExternalProcStatus.FAILED:
            try:
                err_file = os.path.join(to_nexml_dir, err_filename)
                err_content = 'Error message:\n ' + open(err_file, 'rU').read()
            except:
                err_content = ''
            response.headers['Content-Type'] = 'text/xml'
            raise HTTP(501, T("Conversion to NeXML failed.\n" + err_content))
        output = os.path.join(to_nexml_dir, 'out.xml')
        response.headers['Content-Type'] = 'text/xml'
        return open(output, 'rU').read()
        
    else:
        raise HTTP(301)
    return response.download(request, db)
Пример #4
0
def to_nexson():
    global UPLOADID_PAT
    from externalproc import get_external_proc_dir_for_upload, get_logger, invoc_status, \
            ExternalProcStatus, get_conf, write_input_files, write_ext_proc_content, do_ext_proc_launch
    import os
    import datetime
    import codecs
    import locket
    import shutil
    import uuid
    from peyotl.nexson_syntax import can_convert_nexson_forms, \
                                     get_ot_study_info_from_nexml, \
                                     add_resource_meta, \
                                     convert_nexson_format, \
                                     BADGER_FISH_NEXSON_VERSION
    from peyotl.manip import count_num_trees
    '''
    Controller for conversion of NEXUS, newick, or NeXML to NeXSON
    Required arguments:
        "file" should be a multipart-encoded file to be translated to NexSON
          OR
        "content" which is a string that contains the content of the file
            format. "content" is checked if "file" is not provided.
    Required arguments for subsequent calls:
        "uploadId" - The "uploadId" returned from the first invocation
    Optional arguments:
        "uploadId" - A unique string for this upload (optional for *first* call
            only). This is no longer encouraged, since a uuid will be provided.
        "output" one of ['ot:nexson', 'nexson', 'nexml', 'input', 'provenance']
            the default is ot:nexson. This specifies what is to be returned.
            Possible values are: 
            "ot:nexson" is the Open Tree NexSON (with character data culled).
                This should be the first call. Subsequent
                calls can retrieve intermediates. JSON.
            "nexson" is the complete NexSON version of the data. JSON.
            "nexml" is the NeXML version of the file. This is an intermediate
                for the NexSON. XML.
            "input" returns the uploaded file. text/plain.
            "provenance" returns a simple, ad-hoc JSON with initial call details.
        "dataDeposit" should be a URL that should be added to the meta element
            in the Open Tree NexSON object.
        "inputFormat" should be "nexus", "newick", or "nexml"
            default is "nexus"
        "nexml2json" should be "0.0", "1.0", or "1.2". The more
            specific forms: "0.0.0", "1.0.0", or "1.2.1" will also work.
        "idPrefix" should be an empty string (or all whitespace) if you want 
                to use the firstAvailableXXXID args:
            firstAvailableEdgeID,
            firstAvailableNodeID,
            firstAvailableOTUID,
            firstAvailableOTUsID,
            firstAvailableTreeID,
            firstAvailableTreesID
          If idPrefix is not all whitespace it will be stripped, 
            the NCLconverter default names are used
          If idPrefix is not supplied, a uuid will be the prefix for the 
            names and the names will follow the NCL converter defaults

    N.B. Further documentation is available in curator/README.md
    '''
    _LOG = get_logger(request, 'to_nexson')
    ##pdb.set_trace()
    orig_args = {}
    is_upload = False
    # several of our NexSON use "uploadid" instead of "uploadId" so we should accept either
    if ('uploadId' in request.vars) or ('uploadid' in request.vars):
        try:
            if ('uploadId' in request.vars):
                unique_id = request.vars.uploadId
            else:
                unique_id = request.vars.uploadid 
            unique_id = str(unique_id)
        except:
            raise HTTP(400, T('Illegal uploadId "{u}"'.format(u=unique_id)))
    else:
        is_upload = True
        unique_id = 'u' + str(uuid.uuid4())
    if not UPLOADID_PAT.match(unique_id):
        raise HTTP(400, T('uploadId must be series of letters, numbers, dots or dashes between 5 and 85 characters long. "{u}" does not match this pattern'.format(u=unique_id)))
    try:
        idPrefix = request.vars.idPrefix.strip()
    except:
        idPrefix = unique_id
    if idPrefix and (not ID_PREFIX_PAT.match(idPrefix)):
        raise HTTP(400, 'idPrefix must be start with a letter. "{u}" does not match this pattern'.format(u=idPrefix))
    
    output = request.vars.output or 'ot:nexson'
    output = output.lower()
    if output == 'ot%3anexson':
        # handle unwanted encoding (happens if file submitted)
        output = 'ot:nexson'
    output_choices = ['ot:nexson', 'nexson', 'nexml', 'input', 'provenance']
    if output not in output_choices:
        raise HTTP(400, 'The "output" should be one of: "{c}"'.format(c='", "'.join(output_choices)))
    try:
        working_dir = get_external_proc_dir_for_upload(request, '2nexml', unique_id, is_upload)
    except Exception, x:
        raise HTTP(404)