def PUT(resource, resource_id, **kwargs): "Open Tree API methods relating to updating existing resources" # global TIMING # support JSONP request from another domain if kwargs.get('jsoncallback', None) or kwargs.get('callback', None): response.view = 'generic.jsonp' if not resource == 'study': _LOG.debug('resource must be "study"') raise HTTP(400, 'resource != study') # TIMING = api_utils.log_time_diff(_LOG) gh, author_name, author_email = api_utils.authenticate(**kwargs) # TIMING = api_utils.log_time_diff(_LOG, 'github authentication', TIMING) nexson, annotation, validation_log, rich_nexson = validate_and_normalize_nexson( **kwargs) # TIMING = api_utils.log_time_diff(_LOG, 'validation and normalization', TIMING) gd = GitData(repo=repo_path) # We compare sha1's instead of the actual data to reduce memory use # when comparing large studies posted_nexson_sha1 = hashlib.sha1(nexson).hexdigest() nexson_sha1 = hashlib.sha1(gd.fetch_study(resource_id)).hexdigest() # TIMING = api_utils.log_time_diff(_LOG, 'GitData creation and sha', TIMING) # the POSTed data is the same as what we currently have, do nothing and return successfully if posted_nexson_sha1 == nexson_sha1: return { "error": 0, "description": "success, nothing to update" } blob = __finish_write_verb(gd, gh, nexson, author_name, author_email, resource_id, rich_nexson, annotation) # TIMING = api_utils.log_time_diff(_LOG, 'blob creation', TIMING) return blob
def DELETE(resource, resource_id=None, **kwargs): "Open Tree API methods relating to deleting existing resources" # support JSONP request from another domain if kwargs.get('jsoncallback', None) or kwargs.get('callback', None): response.view = 'generic.jsonp' if not resource == 'study': raise HTTP(400, 'resource != study') (gh, author_name, author_email) = api_utils.authenticate(**kwargs) author = "%s <%s>" % (author_name, author_email) branch_name = "%s_study_%s" % (gh.get_user().login, resource_id) gd = GitData(repo=repo_path) try: gd.acquire_lock() except LockError, e: raise HTTP( 400, json.dumps({ "error": 1, "description": "Could not acquire lock to delete the study #%s" % resource_id }))
def POST(branch="master",jsoncallback=None,callback=None,_=None,**kwargs): """OpenTree API methods relating to updating branches This controller implements the updating of a branch (pulling it from our remote) via the API. For example, to update the branch leto_study_12 via curl: curl -X POST http://localhost:8000/api/pull/v1/leto_study_12?auth_token=$GITHUB_OAUTH_TOKEN The default branch is master, so to pull in changes from our remote master: curl -X POST http://localhost:8000/api/pull/v1?auth_token=$GITHUB_OAUTH_TOKEN If the request is successful, a JSON response similar to this will be returned: { "error": 0, "branch_name": "master", "description": "Updated branch", "sha": "dcab222749c9185797645378d0bda08d598f81e7" } If there is an error, an HTTP 400 error will be returned with a JSON response similar to this: { "error": 1, "description": "Could not pull from remote origin! Details: ..." } """ # support JSONP request from another domain if jsoncallback or callback: response.view = 'generic.jsonp' (gh, author_name, author_email) = api_utils.authenticate(**kwargs) repo_path, repo_remote, git_ssh, pkey = api_utils.read_config(request) git_env = {"GIT_SSH": git_ssh, "PKEY": pkey} gd = GitData(repo=repo_path) try: gd.acquire_lock() except LockError, e: raise HTTP(400, json.dumps({ "error": 1, "description": "Could not acquire lock to pull branch %s" % branch }))
def POST(resource, resource_id=None, _method='POST', **kwargs): "OTOL API methods relating to creating (and importing) resources" # support JSONP request from another domain if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' # check for HTTP method override (passed on query string) if _method == 'PUT': PUT(resource, resource_id, kwargs) elif _method == 'DELETE': DELETE(resource, resource_id, kwargs) # elif _method == 'PATCH': ... if not resource=='study': raise HTTP(400, json.dumps({"error":1, "description": "Only the creation of new studies is currently supported"})) # we're creating a new study (possibly with import instructions in the payload) cc0_agreement = kwargs.get('cc0_agreement', '') import_option = kwargs.get('import_option', '') treebase_id = kwargs.get('treebase_id', '') dryad_DOI = kwargs.get('dryad_DOI', '') import_option = kwargs.get('import_option', '') #TODO, need to make this spawn a thread to do the second commit rather than block block_until_annotation_commit = True (gh, author_name, author_email) = api_utils.authenticate(**kwargs) nexson, annotation, validation_log, rich_nexson = validate_and_normalize_nexson(**kwargs) gd = GitData(repo=repo_path) # studies created by the OpenTree API start with o, # so they don't conflict with new study id's from other sources new_resource_id = "o%d" % (gd.newest_study_id() + 1) unadulterated_content_commit = do_commit(gd, gh, nexson, author_name, author_email, new_resource_id) if unadulterated_content_commit['error'] != 0: raise HTTP(400, json.dumps(unadulterated_content_commit)) if block_until_annotation_commit: # add the annotation and commit the resulting blob... add_or_replace_annotation(rich_nexson._raw, annotation) nexson = json.dumps(rich_nexson._raw, sort_keys=True, indent=0) annotated_commit = do_commit(gd, gh, nexson, author_name, author_email, new_resource_id) if annotated_commit['error'] != 0: raise HTTP(400, json.dumps(annotated_commit)) return annotated_commit else: return unadulterated_content_commit
def PUT(resource_id, starting_commit_SHA, jsoncallback=None, callback=None, _=None, **kwargs): """OpenTree API methods relating to updating branches curl -X POST http://localhost:8000/api/merge/v1?resource_id=9&starting_commit_SHA=152316261261342&auth_token=$GITHUB_OAUTH_TOKEN If the request is successful, a JSON response similar to this will be returned: { "error": 0, "branch_name": "my_user_9_2", "description": "Updated branch", "sha": "dcab222749c9185797645378d0bda08d598f81e7", "merged_SHA": "16463623459987070600ab2757540c06ddepa608", } 'merged_SHA' must be included in the next PUT for this study (unless you are happy with your work languishing on a WIP branch instead of master). If there is an error, an HTTP 400 error will be returned with a JSON response similar to this: { "error": 1, "description": "Could not merge master into WIP! Details: ..." } """ if not check_not_read_only(): raise HTTP(500, "should raise from check_not_read_only") # support JSONP request from another domain if jsoncallback or callback: response.view = 'generic.jsonp' auth_info = api_utils.authenticate(**kwargs) phylesystem = api_utils.get_phylesystem(request) gd = phylesystem.create_git_action(resource_id) try: return merge_from_master(gd, resource_id, auth_info, starting_commit_SHA) except GitWorkflowError, err: raise HTTP(400, json.dumps({"error": 1, "description": err.msg}))
def PUT(resource, resource_id=None, **kwargs): "Open Tree API methods relating to updating existing resources" #global TIMING _LOG = api_utils.get_logger(request, 'ot_api.default.v1.PUT') delegate = _route_tag2func.get(resource) if delegate: _LOG.debug('PUT call to {} bouncing to delegate'.format(resource)) return delegate() # support JSONP request from another domain if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' if not resource=='study': _LOG.debug('resource must be "study"') raise HTTP(400, 'resource != study') if resource_id is None: _LOG.debug('resource id not provided') raise HTTP(400, json.dumps({"error": 1, "description": 'study ID expected after "study/"'})) parent_sha = kwargs.get('starting_commit_SHA') if parent_sha is None: raise HTTP(400, 'Expecting a "starting_commit_SHA" argument with the SHA of the parent') commit_msg = kwargs.get('commit_msg') master_file_blob_included = kwargs.get('merged_SHA') _LOG.debug('PUT to study {} for starting_commit_SHA = {} and merged_SHA = {}'.format(resource_id, parent_sha, str(master_file_blob_included))) #TIMING = api_utils.log_time_diff(_LOG) auth_info = api_utils.authenticate(**kwargs) #TIMING = api_utils.log_time_diff(_LOG, 'github authentication', TIMING) bundle = __extract_and_validate_nexson(request, repo_nexml2json, kwargs) nexson, annotation, nexson_adaptor = bundle #TIMING = api_utils.log_time_diff(_LOG, 'validation and normalization', TIMING) phylesystem = api_utils.get_phylesystem(request) try: gd = phylesystem.create_git_action(resource_id) except KeyError, err: _LOG.debug('PUT failed in create_git_action (probably a bad study ID)') _raise_HTTP_from_msg("invalid study ID, please check the URL")
def run_all(email, password, expired): s, headers = authenticate(email, password) if s == None: logger.critical('Aborting search, check your credentials.') quit() df_alerts = get_alerts(s, headers) df_apparts, expired_index = get_all_apparts(df_alerts, s, headers) df_apparts = cleaner(df_apparts) df_apparts = features_engineering(df_apparts) df_history = append_history_df(df_apparts, HISTORY_PATH) df_apparts = df_apparts.loc[~df_apparts.index.duplicated()] df_apparts = get_all_links(s, df_apparts, expired, APPARTS_DB_PATH) if expired: df_history = update_history_df(df_apparts, df_history, expired_index) df_apparts = remove_expired(s, df_apparts, LAST_DELETED_PATH) df_apparts.to_csv(APPARTS_CSV_PATH, sep=';', encoding='utf-8') with warnings.catch_warnings(): warnings.simplefilter("ignore") try: df_apparts.to_excel(APPARTS_XLSX_PATH, encoding='utf-8') except IllegalCharacterError as e: logger.warn( "Some illegal characters were replaced in the dataframe.") ILLEGAL_CHARACTERS_RE = re.compile( r'[\000-\010]|[\013-\014]|[\016-\037]') df_apparts.applymap(lambda x: ILLEGAL_CHARACTERS_RE.sub(r'', x) if isinstance(x, str) else x).to_excel( APPARTS_XLSX_PATH, encoding='utf-8') df_history.to_csv(HISTORY_PATH, sep=';', encoding='utf-8') if upload: uploader = Uploader(credentials_path=CREDS_PATH, token_file_path=TOKEN_FILE_PATH, secret_client_path=SECRET_CLIENT_PATH) uploader.push_table( df_apparts, spreadsheet_id='131UoWqQwZfydMJ3yqVe-L6TY6NKtJx8zVNppo034dT4', worksheet_name='apparts', index=True)
def POST(resource, resource_id=None, _method='POST', **kwargs): "Open Tree API methods relating to creating (and importing) resources" # support JSONP request from another domain if kwargs.get('jsoncallback', None) or kwargs.get('callback', None): response.view = 'generic.jsonp' # check for HTTP method override (passed on query string) if _method == 'PUT': PUT(resource, resource_id, kwargs) elif _method == 'DELETE': DELETE(resource, resource_id, kwargs) # elif _method == 'PATCH': ... if not resource == 'study': raise HTTP( 400, json.dumps({ "error": 1, "description": "Only the creation of new studies is currently supported" })) # we're creating a new study (possibly with import instructions in the payload) cc0_agreement = kwargs.get('cc0_agreement', '') import_option = kwargs.get('import_option', '') treebase_id = kwargs.get('treebase_id', '') dryad_DOI = kwargs.get('dryad_DOI', '') import_option = kwargs.get('import_option', '') (gh, author_name, author_email) = api_utils.authenticate(**kwargs) nexson, annotation, validation_log, rich_nexson = validate_and_normalize_nexson( **kwargs) gd = GitData(repo=repo_path) # studies created by the OpenTree API start with o, # so they don't conflict with new study id's from other sources new_resource_id = "o%d" % (gd.newest_study_id() + 1) return __finish_write_verb(gd, gh, nexson, author_name, author_email, new_resource_id, rich_nexson, annotation)
def POST(resource, resource_id=None, _method='POST', **kwargs): "Open Tree API methods relating to creating (and importing) resources" # support JSONP request from another domain if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' # check for HTTP method override (passed on query string) if _method == 'PUT': PUT(resource, resource_id, kwargs) elif _method == 'DELETE': DELETE(resource, resource_id, kwargs) # elif _method == 'PATCH': ... if not resource=='study': raise HTTP(400, json.dumps({"error":1, "description": "Only the creation of new studies is currently supported"})) # we're creating a new study (possibly with import instructions in the payload) cc0_agreement = kwargs.get('cc0_agreement', '') import_option = kwargs.get('import_option', '') treebase_id = kwargs.get('treebase_id', '') dryad_DOI = kwargs.get('dryad_DOI', '') import_option = kwargs.get('import_option', '') (gh, author_name, author_email) = api_utils.authenticate(**kwargs) nexson, annotation, validation_log, rich_nexson = validate_and_normalize_nexson(**kwargs) gd = GitData(repo=repo_path) # studies created by the OpenTree API start with o, # so they don't conflict with new study id's from other sources new_resource_id = "o%d" % (gd.newest_study_id() + 1) return __finish_write_verb(gd, gh, nexson, author_name, author_email, new_resource_id, rich_nexson, annotation)
def PUT(resource, resource_id, **kwargs): "OTOL API methods relating to updating existing resources" #TODO, need to make this spawn a thread to do the second commit rather than block block_until_annotation_commit = True # support JSONP request from another domain if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' if not resource=='study': raise HTTP(400, 'resource != study') gh, author_name, author_email = api_utils.authenticate(**kwargs) nexson, annotation, validation_log, rich_nexson = validate_and_normalize_nexson(**kwargs) gd = GitData(repo=repo_path) # We compare sha1's instead of the actual data to reduce memory use # when comparing large studies posted_nexson_sha1 = hashlib.sha1(nexson).hexdigest() nexson_sha1 = hashlib.sha1( gd.fetch_study(resource_id) ).hexdigest() # the POSTed data is the same as what we currently have, do nothing and return successfully if posted_nexson_sha1 == nexson_sha1: return { "error": 0, "description": "success, nothing to update" }; else: unadulterated_content_commit = do_commit(gd, gh, nexson, author_name, author_email, resource_id) if unadulterated_content_commit['error'] != 0: raise HTTP(400, json.dumps(unadulterated_content_commit)) if block_until_annotation_commit: # add the annotation and commit the resulting blob... add_or_replace_annotation(rich_nexson._raw, annotation) nexson = json.dumps(rich_nexson._raw, sort_keys=True, indent=0) annotated_commit = do_commit(gd, gh, nexson, author_name, author_email, resource_id) if annotated_commit['error'] != 0: raise HTTP(400, json.dumps(annotated_commit)) return annotated_commit else: return unadulterated_content_commit
def DELETE(resource, resource_id=None, **kwargs): "OTOL API methods relating to deleting existing resources" # support JSONP request from another domain if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' if not resource=='study': raise HTTP(400, 'resource != study') (gh, author_name, author_email) = api_utils.authenticate(**kwargs) author = "%s <%s>" % (author_name, author_email) branch_name = "%s_study_%s" % (gh.get_user().login, resource_id) gd = GitData(repo=repo_path) try: gd.acquire_lock() except LockError, e: raise HTTP(400, json.dumps({ "error": 1, "description": "Could not acquire lock to delete the study #%s" % resource_id }))
def DELETE(resource, resource_id=None, **kwargs): "Open Tree API methods relating to deleting existing resources" # support JSONP request from another domain _LOG = api_utils.get_logger(request, 'ot_api.default.v1.DELETE') if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' if not resource=='study': raise HTTP(400, 'resource != study') if resource_id is None: _LOG.debug('resource id not provided') raise HTTP(400, json.dumps({"error": 1, "description": 'study ID expected after "study/"'})) parent_sha = kwargs.get('starting_commit_SHA') if parent_sha is None: raise HTTP(400, 'Expecting a "starting_commit_SHA" argument with the SHA of the parent') auth_info = api_utils.authenticate(**kwargs) phylesystem = api_utils.get_phylesystem(request) try: x = phylesystem.delete_study(resource_id, auth_info, parent_sha) if x.get('error') == 0: __deferred_push_to_gh_call(request, None, **kwargs) return x except GitWorkflowError, err: _raise_HTTP_from_msg(err.msg)
def PUT(resource_id, starting_commit_SHA, jsoncallback=None,callback=None,_=None,**kwargs): """OpenTree API methods relating to updating branches curl -X POST http://localhost:8000/api/merge/v1?resource_id=9&starting_commit_SHA=152316261261342&auth_token=$GITHUB_OAUTH_TOKEN If the request is successful, a JSON response similar to this will be returned: { "error": 0, "branch_name": "my_user_9_2", "description": "Updated branch", "sha": "dcab222749c9185797645378d0bda08d598f81e7", "merged_SHA": "16463623459987070600ab2757540c06ddepa608", } 'merged_SHA' must be included in the next PUT for this study (unless you are happy with your work languishing on a WIP branch instead of master). If there is an error, an HTTP 400 error will be returned with a JSON response similar to this: { "error": 1, "description": "Could not merge master into WIP! Details: ..." } """ # support JSONP request from another domain if jsoncallback or callback: response.view = 'generic.jsonp' auth_info = api_utils.authenticate(**kwargs) phylesystem = api_utils.get_phylesystem(request) gd = phylesystem.create_git_action(resource_id) try: return merge_from_master(gd, resource_id, auth_info, starting_commit_SHA) except GitWorkflowError, err: raise HTTP(400, json.dumps({"error": 1, "description": err.msg}))
def PUT(resource, resource_id, **kwargs): "Open Tree API methods relating to updating existing resources" # global TIMING # support JSONP request from another domain if kwargs.get('jsoncallback',None) or kwargs.get('callback',None): response.view = 'generic.jsonp' if not resource=='study': _LOG.debug('resource must be "study"') raise HTTP(400, 'resource != study') # TIMING = api_utils.log_time_diff(_LOG) gh, author_name, author_email = api_utils.authenticate(**kwargs) # TIMING = api_utils.log_time_diff(_LOG, 'github authentication', TIMING) nexson, annotation, validation_log, rich_nexson = validate_and_normalize_nexson(**kwargs) # TIMING = api_utils.log_time_diff(_LOG, 'validation and normalization', TIMING) gd = GitData(repo=repo_path) # We compare sha1's instead of the actual data to reduce memory use # when comparing large studies posted_nexson_sha1 = hashlib.sha1(nexson).hexdigest() nexson_sha1 = hashlib.sha1( gd.fetch_study(resource_id) ).hexdigest() # TIMING = api_utils.log_time_diff(_LOG, 'GitData creation and sha', TIMING) # the POSTed data is the same as what we currently have, do nothing and return successfully if posted_nexson_sha1 == nexson_sha1: return { "error": 0, "description": "success, nothing to update" }; blob = __finish_write_verb(gd, gh, nexson, author_name, author_email, resource_id, rich_nexson, annotation) # TIMING = api_utils.log_time_diff(_LOG, 'blob creation', TIMING) return blob
def POST(branch,base_branch="master",jsoncallback=None,callback=None,_=None,**kwargs): """OpenTree API methods relating to merging branches This controller implements the merging of branches via the API. For example, to merge the branch leto_study_12 to master via curl: curl -X POST http://localhost:8000/api/merge/v1/leto_study_12/master?auth_token=$GITHUB_OAUTH_TOKEN where the first branch is the branch to merge *in* and the second is the branch to merge *into*. The second branch defaults to "master", so this request is equivalent to the above: curl -X POST http://localhost:8000/api/merge/v1/leto_study_12?auth_token=$GITHUB_OAUTH_TOKEN If the request is successful, a JSON response similar to this will be returned: { "error": 0, "branch_name": "master", "description": "Merged branch leto_study_12", "sha": "dcab222749c9185797645378d0bda08d598f81e7" } If there is an error, an HTTP 400 error will be returned with a JSON response similar to this: { "error": 1, "description": "Could not push foo branch" } """ # support JSONP request from another domain if jsoncallback or callback: response.view = 'generic.jsonp' (gh, author_name, author_email) = api_utils.authenticate(**kwargs) repo_path, repo_remote, git_ssh, pkey = api_utils.read_config(request) git_env = {"GIT_SSH": git_ssh, "PKEY": pkey} gd = GitData(repo=repo_path) if branch == base_branch: raise HTTP(400, json.dumps({ "error": 1, "description": "Cannot merge %s branch to itself" % branch })) for b in [ branch, base_branch ]: if not gd.branch_exists(b): raise HTTP(400, json.dumps({ "error": 1, "description": "Cannot merge non-existent branch %s" % b })) try: gd.acquire_lock() except LockError, e: raise HTTP(400, json.dumps({ "error": 1, "description": "Could not acquire lock to merge branch %s" % branch }))
def POST(resource, resource_id=None, _method='POST', **kwargs): "Open Tree API methods relating to creating (and importing) resources" delegate = _route_tag2func.get(resource) if delegate: return delegate() _LOG = api_utils.get_logger(request, 'ot_api.default.v1.POST') # support JSONP request from another domain if kwargs.get('jsoncallback', None) or kwargs.get('callback', None): response.view = 'generic.jsonp' # check for HTTP method override (passed on query string) if _method == 'PUT': PUT(resource, resource_id, kwargs) elif _method == 'DELETE': DELETE(resource, resource_id, kwargs) if not resource == 'study': raise HTTP(400, json.dumps({"error":1, "description": "Only the creation of new studies is currently supported"})) auth_info = api_utils.authenticate(**kwargs) # Studies that were created in phylografter, can be added by # POSTing the content with resource_id new_study_id = resource_id if new_study_id is not None: try: int(new_study_id) except: new_study_id = 'pg_' + new_study_id else: try: new_study_id.startswith('pg_') except: raise HTTP(400, 'Use of the resource_id to specify a study ID is limited to phylografter studies') bundle = __extract_and_validate_nexson(request, repo_nexml2json, kwargs) new_study_nexson = bundle[0] else: # we're creating a new study (possibly with import instructions in the payload) import_from_location = kwargs.get('import_from_location', '') treebase_id = kwargs.get('treebase_id', '') nexml_fetch_url = kwargs.get('nexml_fetch_url', '') nexml_pasted_string = kwargs.get('nexml_pasted_string', '') publication_doi = kwargs.get('publication_DOI', '') # if a URL or something other than a valid DOI was entered, don't submit it to crossref API publication_doi_for_crossref = __make_valid_DOI(publication_doi) or None publication_ref = kwargs.get('publication_reference', '') # is the submitter explicity applying the CC0 waiver to a new study # (i.e., this study is not currently in an online repository)? if import_from_location == 'IMPORT_FROM_UPLOAD': cc0_agreement = (kwargs.get('chosen_license', '') == 'apply-new-CC0-waiver' and kwargs.get('cc0_agreement', '') == 'true') else: cc0_agreement = False # look for the chosen import method, e.g, # 'import-method-PUBLICATION_DOI' or 'import-method-MANUAL_ENTRY' import_method = kwargs.get('import_method', '') ##dryad_DOI = kwargs.get('dryad_DOI', '') app_name = request.application # add known values for its metatags meta_publication_reference = None # Create initial study NexSON using the chosen import method. # # N.B. We're currently using a streamlined creation path with just # two methods (TreeBASE ID and publication DOI). But let's keep the # logic for others, just in case we revert based on user feedback. importing_from_treebase_id = (import_method == 'import-method-TREEBASE_ID' and treebase_id) importing_from_nexml_fetch = (import_method == 'import-method-NEXML' and nexml_fetch_url) importing_from_nexml_string = (import_method == 'import-method-NEXML' and nexml_pasted_string) importing_from_crossref_API = (import_method == 'import-method-PUBLICATION_DOI' and publication_doi_for_crossref) or \ (import_method == 'import-method-PUBLICATION_REFERENCE' and publication_ref) # Are they using an existing license or waiver (CC0, CC-BY, something else?) using_existing_license = (kwargs.get('chosen_license', '') == 'study-data-has-existing-license') # any of these methods should returna parsed NexSON dict (vs. string) if importing_from_treebase_id: # make sure the treebase ID is an integer treebase_id = "".join(treebase_id.split()) # remove all whitespace treebase_id = treebase_id.lstrip('S').lstrip('s') # allow for possible leading 'S'? try: treebase_id = int(treebase_id) except ValueError, e: raise HTTP(400, json.dumps({ "error": 1, "description": "TreeBASE ID should be a simple integer, not '%s'! Details:\n%s" % (treebase_id, e.message) })) new_study_nexson = import_nexson_from_treebase(treebase_id, nexson_syntax_version=BY_ID_HONEY_BADGERFISH) # elif importing_from_nexml_fetch: # if not (nexml_fetch_url.startswith('http://') or nexml_fetch_url.startswith('https://')): # raise HTTP(400, json.dumps({ # "error": 1, # "description": 'Expecting: "nexml_fetch_url" to startwith http:// or https://', # })) # new_study_nexson = get_ot_study_info_from_treebase_nexml(src=nexml_fetch_url, # nexson_syntax_version=BY_ID_HONEY_BADGERFISH) # elif importing_from_nexml_string: # new_study_nexson = get_ot_study_info_from_treebase_nexml(nexml_content=nexml_pasted_string, # nexson_syntax_version=BY_ID_HONEY_BADGERFISH) elif importing_from_crossref_API: new_study_nexson = _new_nexson_with_crossref_metadata(doi=publication_doi_for_crossref, ref_string=publication_ref, include_cc0=cc0_agreement)