Skip to content
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into torch/log_histos_less
Browse files Browse the repository at this point in the history
  • Loading branch information
raubitsj committed Jul 24, 2020
2 parents eb77fa1 + ce9c417 commit 46b1e68
Show file tree
Hide file tree
Showing 331 changed files with 110,429 additions and 17 deletions.
8 changes: 4 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ def mocked_run(runner, test_settings):

@pytest.fixture
def runner(monkeypatch, mocker):
# whaaaaat = util.vendor_import("whaaaaat")
whaaaaat = wandb.util.vendor_import("whaaaaat")
# monkeypatch.setattr('wandb.cli.api', InternalApi(
# default_settings={'project': 'test', 'git_tag': True}, load_settings=False))
monkeypatch.setattr(click, 'launch', lambda x: 1)
# monkeypatch.setattr(whaaaaat, 'prompt', lambda x: {
# 'project_name': 'test_model', 'files': ['weights.h5'],
# 'attach': False, 'team_name': 'Manual Entry'})
monkeypatch.setattr(whaaaaat, 'prompt', lambda x: {
'project_name': 'test_model', 'files': ['weights.h5'],
'attach': False, 'team_name': 'Manual Entry'})
monkeypatch.setattr(webbrowser, 'open_new_tab', lambda x: True)
mocker.patch("wandb.lib.apikey.input", lambda x: 1)
mocker.patch("wandb.lib.apikey.getpass.getpass", lambda x: DUMMY_API_KEY)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def config_dir():
def test_init_reinit(runner, empty_netrc, local_netrc, mock_server):
with runner.isolated_filesystem():
runner.invoke(cli.login, [DUMMY_API_KEY])
result = runner.invoke(cli.init, input="y\nvanpelt\n")
result = runner.invoke(cli.init, input="y\n\n\n")
print(result.output)
print(result.exception)
print(traceback.print_tb(result.exc_info[2]))
Expand Down
8 changes: 8 additions & 0 deletions tests/utils/mock_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ def graphql():
}
}
})
if "query Models(" in body["query"]:
return json.dumps({
'data': {
'models': {
"edges": [{"node": {"id": "123", "name": "myname", "project": "myproj"}}]
}
}
})
if "query Projects(" in body["query"]:
return json.dumps({
"data": {
Expand Down
14 changes: 9 additions & 5 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
minversion=3.7
envlist = codemod,black,mypy,flake8,py27,py36,py37,py38,cover
envlist = codemod,black,mypy,flake8,py36,py27,py37,py38,cover

[testenv]
deps =
Expand Down Expand Up @@ -191,9 +191,8 @@ deps =
coverage
commands =
/usr/bin/env bash -c '{envpython} -m coverage combine {toxworkdir}/py*/.coverage'
coverage report --fail-under 70 --skip-covered --include "tests/*" --omit "wandb/vendor/*"
#coverage report --fail-under 25 --skip-covered --show-missing --include wandb/*
coverage report --fail-under 15 --skip-covered --include "wandb/*" --omit "wandb/vendor/*"
coverage report --fail-under 80 --skip-covered --include "tests/*"
coverage report --fail-under 50 --skip-covered

[testenv:coveralls]
# NOTE: Coveralls should be run with:
Expand All @@ -206,4 +205,9 @@ commands =

[coverage:run]
omit =
wandb/vendor/*
*/wandb/vendor/*

[coverage:paths]
source =
wandb/sdk/
wandb/sdk_py27/
9 changes: 9 additions & 0 deletions wandb/apis/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ def set_current_run_id(self, run_id):
def viewer(self):
return self.api.viewer()

def list_projects(self, entity=None):
return self.api.list_projects(entity=entity)

def format_project(self, project):
return self.api.format_project(project)

def upsert_project(self, project, id=None, description=None, entity=None):
return self.api.upsert_project(project, id=id, description=description, entity=entity)

def settings(self, *args, **kwargs):
return self.api.settings(*args, **kwargs)

Expand Down
88 changes: 82 additions & 6 deletions wandb/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
from wandb.sync import SyncManager
import yaml

# whaaaaat depends on prompt_toolkit < 2, ipython now uses > 2 so we vendored for now
# DANGER this changes the sys.path so we should never do this in a user script
whaaaaat = util.vendor_import("whaaaaat")


logger = logging.getLogger("wandb")

Expand Down Expand Up @@ -66,6 +70,50 @@ def wrapper(*args, **kwargs):
return wrapper


def _get_cling_api():
"""Get a reference to the internal api with cling settings."""
# TODO(jhr): make a settings object that is better for non runs.
wandb.setup(settings=wandb.Settings(_cli_only_mode=True))
api = InternalApi()
return api


def prompt_for_project(ctx, entity):
"""Ask the user for a project, creating one if necessary."""
result = ctx.invoke(projects, entity=entity, display=False)
api = _get_cling_api()

try:
if len(result) == 0:
project = click.prompt("Enter a name for your first project")
# description = editor()
project = api.upsert_project(project, entity=entity)["name"]
else:
project_names = [project["name"] for project in result]
question = {
'type': 'list',
'name': 'project_name',
'message': "Which project should we use?",
'choices': project_names + ["Create New"]
}
result = whaaaaat.prompt([question])
if result:
project = result['project_name']
else:
project = "Create New"
# TODO: check with the server if the project exists
if project == "Create New":
project = click.prompt(
"Enter a name for your new project", value_proc=api.format_project)
# description = editor()
project = api.upsert_project(project, entity=entity)["name"]

except wandb.errors.error.CommError as e:
raise ClickException(str(e))

return project


class RunGroup(click.Group):
@display_error
def get_command(self, ctx, cmd_name):
Expand All @@ -85,6 +133,27 @@ def cli(ctx):
click.echo(ctx.get_help())


@cli.command(context_settings=CONTEXT, help="List projects")
@click.option("--entity", "-e", default=None, envvar=env.ENTITY, help="The entity to scope the listing to.")
@display_error
def projects(entity, display=True):
api = _get_cling_api()
projects = api.list_projects(entity=entity)
if len(projects) == 0:
message = "No projects found for %s" % entity
else:
message = 'Latest projects for "%s"' % entity
if display:
click.echo(click.style(message, bold=True))
for project in projects:
click.echo("".join(
(click.style(project['name'], fg="blue", bold=True),
" - ",
str(project['description'] or "").split("\n")[0])
))
return projects


@cli.command(context_settings=CONTEXT, help="Login to Weights & Biases")
@click.argument("key", nargs=-1)
@click.option("--cloud", is_flag=True, help="Login to the cloud instead of local")
Expand All @@ -95,8 +164,8 @@ def cli(ctx):
def login(key, host, cloud, relogin, anonymously):
anon_mode = "must" if anonymously else "never"
wandb.setup(settings=wandb.Settings(_cli_only_mode=True, anonymous=anon_mode))
api = _get_cling_api()

api = InternalApi()
if host == "https://api.wandb.ai" or (host is None and cloud):
api.clear_setting("base_url", globally=True, persist=True)
# To avoid writing an empty local settings file, we only clear if it exists
Expand Down Expand Up @@ -171,9 +240,11 @@ def init(ctx):
'type': 'list',
'name': 'team_name',
'message': "Which team should we use?",
'choices': team_names + ["Manual Entry"]
'choices': team_names
# TODO(jhr): disabling manual entry for cling
# 'choices': team_names + ["Manual Entry"]
}
result = click.prompt(question["message"])
result = whaaaaat.prompt([question])
# result can be empty on click
if result:
entity = result['team_name']
Expand All @@ -184,7 +255,11 @@ def init(ctx):
else:
entity = viewer.get('entity') or click.prompt("What username or team should we use?")

project = click.prompt("Enter the name of the project you want to use") # prompt_for_project(ctx, entity)
# TODO: this error handling sucks and the output isn't pretty
try:
project = prompt_for_project(ctx, entity)
except ClickWandbException:
raise ClickException('Could not find team: %s' % entity)

api.set_setting('entity', entity, persist=True)
api.set_setting('project', project, persist=True)
Expand Down Expand Up @@ -413,9 +488,10 @@ def controller(verbose, sweep_id):
@cli.command(context_settings=RUN_CONTEXT, name="docker-run")
@click.pass_context
@click.argument('docker_run_args', nargs=-1)
@click.option('--help')
@click.option('--help', is_flag=True)
def docker_run(ctx, docker_run_args, help):
"""Simple docker wrapper that adds WANDB_API_KEY and WANDB_DOCKER to any docker run command.
"""Simple wrapper for `docker run` which sets W&B environment
Adds WANDB_API_KEY and WANDB_DOCKER to any docker run command.
This will also set the runtime to nvidia if the nvidia-docker executable is present on the system
and --runtime wasn't set.
"""
Expand Down
4 changes: 3 additions & 1 deletion wandb/internal/internal_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,9 @@ def upsert_project(self, project, id=None, description=None, entity=None):
''')
response = self.gql(mutation, variable_values={
'name': self.format_project(project), 'entity': entity or self.settings('entity'),
'description': description, 'repo': self.git.remote_url, 'id': id})
'description': description, 'id': id})
# TODO(jhr): Commenting out 'repo' field for cling, add back
# 'description': description, 'repo': self.git.remote_url, 'id': id})
return response['upsertModel']['model']

@normalize_exceptions
Expand Down
22 changes: 22 additions & 0 deletions wandb/vendor/prompt_toolkit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
prompt_toolkit
==============
Author: Jonathan Slenders
Description: prompt_toolkit is a Library for building powerful interactive
command lines in Python. It can be a replacement for GNU
readline, but it can be much more than that.
See the examples directory to learn about the usage.
Probably, to get started, you meight also want to have a look at
`prompt_toolkit.shortcuts.prompt`.
"""
from .interface import CommandLineInterface
from .application import AbortAction, Application
from .shortcuts import prompt, prompt_async


# Don't forget to update in `docs/conf.py`!
__version__ = '1.0.15'

0 comments on commit 46b1e68

Please sign in to comment.