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)
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)
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)
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)