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
                }))
示例#3
0
    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
            }))
示例#4
0
    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
示例#5
0
    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}))
示例#6
0
    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")
示例#7
0
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)
示例#10
0
    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
示例#11
0
    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
            }))
示例#12
0
 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
示例#15
0
    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
            }))
示例#16
0
    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)