Ejemplo n.º 1
0
 def check_anonymous(self):
     # If there's no API key set, ask if the run should be logged anonymously. Only launch this prompt in
     # environments with a tty.
     if not self.api.api_key and sys.stdin.isatty():
         # Require anonymous mode to be explicitly enabled for now
         if os.environ.get(env.ANONYMOUS) != "enable":
             return False
         termlog(
             'No API key found. Would you like to log runs anonymously to {}? (y/n)'
             .format(self.api.app_url))
         resp = str(input().lower().strip())
         while not (resp == 'y' or resp == 'n'):
             termlog('Invalid response. Please enter y/n.')
             resp = str(input()).lower().strip()
         if resp == 'y':
             key = self.api.create_anonymous_api_key()
             url = self.api.app_url + '/login?apiKey={}'.format(key)
             termlog(
                 'Your anonymous login link: {}. Do not share or lose this link!'
                 .format(url))
             os.environ[env.API_KEY] = key
             self.api.set_setting('anonymous', True)
             util.write_netrc(self.api.api_url, "user", key)
             util.write_settings(settings=self.api.settings())
             self.api.reauth()
             return True
     return False
Ejemplo n.º 2
0
def _init_jupyter(run, job_type):
    """Asks for user input to configure the machine if it isn't already and creates a new run.
    Log pushing and system stats don't start until `wandb.monitor()` is called.
    """
    global http_api
    # TODO: Should we log to jupyter?
    try_to_set_up_logging()
    if not http_api.api_key:
        termerror(
            "Not authenticated.  Copy a key from https://app.wandb.ai/profile?message=true"
        )
        key = getpass.getpass("API Key: ").strip()
        if len(key) == 40:
            os.environ["WANDB_API_KEY"] = key
            util.write_netrc(http_api.api_url, "user", key)
        else:
            raise ValueError("API Key must be 40 characters long")
        # Ensure our api client picks up the new key
        http_api = Api()
    if not http_api.settings('project'):
        termerror("No W&B project configured.")
        slug = six.moves.input("Enter username/project: ").strip()
        if "/" not in slug:
            raise ValueError(
                "Input must contain a slash between username and project")
        entity, project = slug.split("/")
        os.environ["WANDB_ENTITY"] = entity
        os.environ["WANDB_PROJECT"] = project
        util.write_settings(entity, project, http_api.settings()['base_url'])
        # Reset settings so they reload
        http_api._settings = None
    os.environ["WANDB_JUPYTER"] = "true"
    run.resume = "allow"
    http_api.set_current_run_id(run.id)
    print("W&B Run: %s" % run.get_url(http_api))
    print(
        "Wrap your training loop with `with wandb.monitor():` to display live results."
    )
    try:
        run.save(api=http_api, job_type=job_type)
    except (CommError, ValueError) as e:
        termerror(str(e))
    run.set_environment()
Ejemplo n.º 3
0
def init(ctx):
    from wandb import _set_stage_dir, __stage_dir__, wandb_dir
    if __stage_dir__ is None:
        _set_stage_dir('wandb')
    if os.path.isdir(wandb_dir()) and os.path.exists(
            os.path.join(wandb_dir(), "settings")):
        click.confirm(click.style(
            "This directory has been configured previously, should we re-configure it?",
            bold=True),
                      abort=True)
    else:
        click.echo(
            click.style("Let's setup this directory for W&B!",
                        fg="green",
                        bold=True))

    if api.api_key is None:
        ctx.invoke(login)

    viewer = api.viewer()

    # Viewer can be `None` in case your API information became invalid, or
    # in testing if you switch hosts.
    if not viewer:
        click.echo(
            click.style(
                "Your login information seems to be invalid: can you log in again please?",
                fg="red",
                bold=True))
        ctx.invoke(login)

    # This shouldn't happen.
    viewer = api.viewer()
    if not viewer:
        click.echo(
            click.style(
                "We're sorry, there was a problem logging you in. Please send us a note at [email protected] and tell us how this happened.",
                fg="red",
                bold=True))
        sys.exit(1)

    # At this point we should be logged in successfully.
    if len(viewer["teams"]["edges"]) > 1:
        team_names = [e["node"]["name"] for e in viewer["teams"]["edges"]]
        question = {
            'type': 'list',
            'name': 'team_name',
            'message': "Which team should we use?",
            'choices': team_names + ["Manual Entry"]
        }
        result = whaaaaat.prompt([question])
        # result can be empty on click
        if result:
            entity = result['team_name']
        else:
            entity = "Manual Entry"
        if entity == "Manual Entry":
            entity = click.prompt("Enter the name of the team you want to use")
    else:
        entity = click.prompt("What username or team should we use?",
                              default=viewer.get('entity', 'models'))

    # TODO: this error handling sucks and the output isn't pretty
    try:
        project = prompt_for_project(ctx, entity)
    except wandb.cli.ClickWandbException:
        raise ClickException('Could not find team: %s' % entity)

    util.write_settings(entity, project, api.settings())

    with open(os.path.join(wandb_dir(), '.gitignore'), "w") as file:
        file.write("*\n!settings")

    click.echo(
        click.style("This directory is configured!  Next, track a run:\n",
                    fg="green") +
        textwrap.dedent("""\
        * In your training script:
            {code1}
            {code2}
        * then `{run}`.
        """).format(
            code1=click.style("import wandb", bold=True),
            code2=click.style("wandb.init()", bold=True),
            run=click.style("python <train.py>", bold=True),
            # saving this here so I can easily put it back when we re-enable
            # push/pull
            # """
            # * Run `{push}` to manually add a file.
            # * Pull popular models into your project with: `{pull}`.
            # """
            # push=click.style("wandb push run_id weights.h5", bold=True),
            # pull=click.style("wandb pull models/inception-v4", bold=True)
        ))
Ejemplo n.º 4
0
def login(key, server=LocalServer(), browser=True, anonymous=False):
    global api

    key = key[0] if len(key) > 0 else None

    # Import in here for performance reasons
    import webbrowser
    browser = util.launch_browser(browser)

    # Go through the regular user login flow first, unless --anonymous is specified.
    if not key and not anonymous:
        # TODO: use Oauth?: https://community.auth0.com/questions/6501/authenticating-an-installed-cli-with-oidc-and-a-th
        url = api.app_url + '/authorize'
        if key or not browser:
            launched = False
        else:
            launched = webbrowser.open_new_tab(url + "?{}".format(server.qs()))
        if launched:
            click.echo('Opening [{}] in your default browser'.format(url))
            server.start(blocking=False)
        elif not key:
            click.echo(
                "You can find your API keys in your browser here: {}".format(
                    url))

        def cancel_prompt(*args):
            raise KeyboardInterrupt()

        # Hijacking this signal broke tests in py2...
        # if not os.getenv("WANDB_TEST"):
        signal.signal(signal.SIGINT, cancel_prompt)
        try:
            key = key or click.prompt("Paste an API key from your profile",
                                      value_proc=lambda x: x.strip())
        except Abort:
            if server.result.get("key"):
                key = server.result["key"][0]

        # If we still don't have a key, go through the anonymous user flow if we're running interactively.
        if not key:
            try:
                click.confirm(
                    'No API key found. Would you like to log runs anonymously?',
                    abort=True)
                anonymous = True
            except Abort:
                anonymous = False

    # Go through the anonymous login flow.
    if not key and anonymous:
        if api.api_key:
            click.confirm(
                'You are already logged in. Are you sure you want to create a new anonymous login?',
                abort=True)

        # Generate a new anonymous user and use its API key.
        key = api.create_anonymous_api_key()

        url = api.app_url + '/login?apiKey={}'.format(key)
        if browser:
            webbrowser.open_new_tab(url)

        click.echo(
            "Your anonymous login link: {}. Do not share or lose this link!".
            format(url))

    if key:
        # TODO: get the username here...
        # username = api.viewer().get('entity', 'models')
        if util.write_netrc(api.api_url, "user", key):
            api.set_setting('anonymous', anonymous)
            util.write_settings(settings=api.settings())
            click.secho("Successfully logged in to Weights & Biases!",
                        fg="green")
    else:
        click.echo("No key provided, please try again")

    # reinitialize API to create the new client
    api = InternalApi()

    return key
Ejemplo n.º 5
0
def init(ctx):
    from wandb import _set_stage_dir, __stage_dir__, wandb_dir
    if __stage_dir__ is None:
        _set_stage_dir('wandb')
    if os.path.isdir(wandb_dir()):
        click.confirm(click.style(
            "This directory has been configured previously, should we re-configure it?", bold=True), abort=True)
    else:
        click.echo(click.style(
            "Let's setup this directory for W&B!", fg="green", bold=True))

    global IS_INIT

    if api.api_key is None:
        ctx.invoke(login)

    IS_INIT = True

    viewer = api.viewer()
    if len(viewer["teams"]["edges"]) > 1:
        team_names = [e["node"]["name"] for e in viewer["teams"]["edges"]]
        question = {
            'type': 'list',
            'name': 'team_name',
            'message': "Which team should we use?",
            'choices': team_names + ["Manual Entry"]
        }
        result = whaaaaat.prompt([question])
        # result can be empty on click
        if result:
            entity = result['team_name']
        else:
            entity = "Manual Entry"
        if entity == "Manual Entry":
            entity = click.prompt("Enter the name of the team you want to use")
    else:
        entity = click.prompt("What username or team should we use?",
                              default=viewer.get('entity', 'models'))

    # TODO: this error handling sucks and the output isn't pretty
    try:
        project = prompt_for_project(ctx, entity)
    except wandb.cli.ClickWandbException:
        raise ClickException('Could not find team: %s' % entity)

    util.write_settings(entity, project, api.settings()['base_url'])

    with open(os.path.join(wandb_dir(), '.gitignore'), "w") as file:
        file.write("*\n!settings")

    click.echo(click.style("This directory is configured!  Next, track a run:\n", fg="green") +
               textwrap.dedent("""\
        * In your training script:
            {code1}
            {code2}
        * then `{run}`.
        """).format(
        code1=click.style("import wandb", bold=True),
        code2=click.style("wandb.init()", bold=True),
        run=click.style("python <train.py>", bold=True),
        # saving this here so I can easily put it back when we re-enable
        # push/pull
        #"""
        #* Run `{push}` to manually add a file.
        #* Pull popular models into your project with: `{pull}`.
        #"""
        # push=click.style("wandb push run_id weights.h5", bold=True),
        # pull=click.style("wandb pull models/inception-v4", bold=True)
    ))