def prompt_api_key( settings, api=None, input_callback=None, browser_callback=None, no_offline=False, local=False, ): input_callback = input_callback or getpass.getpass api = api or InternalApi() anon_mode = _fixup_anon_mode(settings.anonymous) jupyter = settings.jupyter or False app_url = settings.base_url.replace("//api.", "//app.") choices = [choice for choice in LOGIN_CHOICES] if anon_mode == "never": # Omit LOGIN_CHOICE_ANON as a choice if the env var is set to never choices.remove(LOGIN_CHOICE_ANON) if jupyter or no_offline: choices.remove(LOGIN_CHOICE_DRYRUN) if jupyter and 'google.colab' in sys.modules: key = wandb.jupyter.attempt_colab_login(api.app_url) write_key(settings, key) return key if anon_mode == "must": result = LOGIN_CHOICE_ANON # If we're not in an interactive environment, default to dry-run. elif not isatty(sys.stdout) or not isatty(sys.stdin): result = LOGIN_CHOICE_DRYRUN elif local: result = LOGIN_CHOICE_EXISTS else: for i, choice in enumerate(choices): wandb.termlog("(%i) %s" % (i + 1, choice)) def prompt_choice(): try: return ( int( input( "%s: Enter your choice: " % LOG_STRING ) ) - 1 # noqa: W503 ) except ValueError: return -1 idx = -1 while idx < 0 or idx > len(choices) - 1: idx = prompt_choice() if idx < 0 or idx > len(choices) - 1: wandb.termwarn("Invalid choice") result = choices[idx] wandb.termlog("You chose '%s'" % result) if result == LOGIN_CHOICE_ANON: key = api.create_anonymous_api_key() write_key(settings, key) return key elif result == LOGIN_CHOICE_NEW: key = browser_callback(signup=True) if browser_callback else None if not key: wandb.termlog( "Create an account here: {}/authorize?signup=true".format(app_url) ) key = input_callback( "%s: Paste an API key from your profile and hit enter" % LOG_STRING ).strip() write_key(settings, key) return key elif result == LOGIN_CHOICE_EXISTS: key = browser_callback() if browser_callback else None if not key: wandb.termlog( "You can find your API key in your browser here: {}/authorize".format( app_url ) ) key = input_callback( "%s: Paste an API key from your profile and hit enter" % LOG_STRING ).strip() write_key(settings, key) return key else: # Jupyter environments don't have a tty, but we can still try logging in using # the browser callback if one is supplied. key, anonymous = ( browser_callback() if jupyter and browser_callback else (None, False) ) write_key(settings, key) return key
def prompt_api_key( # noqa: C901 settings, api=None, input_callback=None, browser_callback=None, no_offline=False, no_create=False, local=False, ): """Prompt for api key. Returns: str - if key is configured None - if dryrun is selected False - if unconfigured (notty) """ input_callback = input_callback or getpass.getpass log_string = term.LOG_STRING api = api or InternalApi() anon_mode = _fixup_anon_mode(settings.anonymous) jupyter = settings._jupyter or False app_url = api.app_url choices = [choice for choice in LOGIN_CHOICES] if anon_mode == "never": # Omit LOGIN_CHOICE_ANON as a choice if the env var is set to never choices.remove(LOGIN_CHOICE_ANON) if jupyter or no_offline: choices.remove(LOGIN_CHOICE_DRYRUN) if jupyter or no_create: choices.remove(LOGIN_CHOICE_NEW) if jupyter and 'google.colab' in sys.modules: log_string = term.LOG_STRING_NOCOLOR key = wandb.jupyter.attempt_colab_login(app_url) if key is not None: write_key(settings, key) return key if anon_mode == "must": result = LOGIN_CHOICE_ANON # If we're not in an interactive environment, default to dry-run. elif not jupyter and (not isatty(sys.stdout) or not isatty(sys.stdin)): result = LOGIN_CHOICE_NOTTY elif local: result = LOGIN_CHOICE_EXISTS elif len(choices) == 1: result = choices[0] else: for i, choice in enumerate(choices): wandb.termlog("(%i) %s" % (i + 1, choice)) idx = -1 while idx < 0 or idx > len(choices) - 1: idx = _prompt_choice() if idx < 0 or idx > len(choices) - 1: wandb.termwarn("Invalid choice") result = choices[idx] wandb.termlog("You chose '%s'" % result) api_ask = "%s: Paste an API key from your profile and hit enter: " % log_string if result == LOGIN_CHOICE_ANON: key = api.create_anonymous_api_key() write_key(settings, key) return key elif result == LOGIN_CHOICE_NEW: key = browser_callback(signup=True) if browser_callback else None if not key: wandb.termlog( "Create an account here: {}/authorize?signup=true".format( app_url)) key = input_callback(api_ask).strip() write_key(settings, key) return key elif result == LOGIN_CHOICE_EXISTS: key = browser_callback() if browser_callback else None if not key: wandb.termlog( "You can find your API key in your browser here: {}/authorize". format(app_url)) key = input_callback(api_ask).strip() write_key(settings, key) return key elif result == LOGIN_CHOICE_NOTTY: # TODO: Needs refactor as this needs to be handled by caller return False else: # Jupyter environments don't have a tty, but we can still try logging in using # the browser callback if one is supplied. key, anonymous = (browser_callback() if jupyter and browser_callback else (None, False)) write_key(settings, key) return key
def prompt_api_key( # noqa: C901 settings, api=None, input_callback=None, browser_callback=None, no_offline=False, no_create=False, local=False, ): """Prompt for api key. Returns: str - if key is configured None - if dryrun is selected False - if unconfigured (notty) """ input_callback = input_callback or getpass.getpass log_string = term.LOG_STRING api = api or InternalApi(settings) anon_mode = _fixup_anon_mode(settings.anonymous) jupyter = settings._jupyter or False app_url = api.app_url choices = [choice for choice in LOGIN_CHOICES] if anon_mode == "never": # Omit LOGIN_CHOICE_ANON as a choice if the env var is set to never choices.remove(LOGIN_CHOICE_ANON) if (jupyter and not settings.login_timeout) or no_offline: choices.remove(LOGIN_CHOICE_DRYRUN) if (jupyter and not settings.login_timeout) or no_create: choices.remove(LOGIN_CHOICE_NEW) if jupyter and "google.colab" in sys.modules: log_string = term.LOG_STRING_NOCOLOR key = wandb.jupyter.attempt_colab_login(app_url) if key is not None: write_key(settings, key, api=api) return key if anon_mode == "must": result = LOGIN_CHOICE_ANON # If we're not in an interactive environment, default to dry-run. elif (not jupyter and (not isatty(sys.stdout) or not isatty(sys.stdin))) or _is_databricks(): result = LOGIN_CHOICE_NOTTY elif local: result = LOGIN_CHOICE_EXISTS elif len(choices) == 1: result = choices[0] else: result = prompt_choices(choices, input_timeout=settings.login_timeout, jupyter=jupyter) api_ask = ( f"{log_string}: Paste an API key from your profile and hit enter, " "or press ctrl+c to quit: ") if result == LOGIN_CHOICE_ANON: key = api.create_anonymous_api_key() write_key(settings, key, api=api, anonymous=True) return key elif result == LOGIN_CHOICE_NEW: key = browser_callback(signup=True) if browser_callback else None if not key: wandb.termlog( f"Create an account here: {app_url}/authorize?signup=true") key = input_callback(api_ask).strip() write_key(settings, key, api=api) return key elif result == LOGIN_CHOICE_EXISTS: key = browser_callback() if browser_callback else None if not key: wandb.termlog( f"You can find your API key in your browser here: {app_url}/authorize" ) key = input_callback(api_ask).strip() write_key(settings, key, api=api) return key elif result == LOGIN_CHOICE_NOTTY: # TODO: Needs refactor as this needs to be handled by caller return False elif result == LOGIN_CHOICE_DRYRUN: return None else: # Jupyter environments don't have a tty, but we can still try logging in using # the browser callback if one is supplied. key, anonymous = (browser_callback() if jupyter and browser_callback else (None, False)) write_key(settings, key, api=api) return key