wandb 0.17.0rc2__py3-none-any.whl → 0.17.2__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +4 -2
- wandb/apis/importers/internals/internal.py +0 -1
- wandb/apis/importers/wandb.py +12 -7
- wandb/apis/internal.py +0 -3
- wandb/apis/public/api.py +213 -79
- wandb/apis/public/artifacts.py +335 -100
- wandb/apis/public/files.py +9 -9
- wandb/apis/public/jobs.py +16 -4
- wandb/apis/public/projects.py +26 -28
- wandb/apis/public/query_generator.py +1 -1
- wandb/apis/public/runs.py +163 -65
- wandb/apis/public/sweeps.py +2 -2
- wandb/apis/reports/__init__.py +1 -7
- wandb/apis/reports/v1/__init__.py +5 -27
- wandb/apis/reports/v2/__init__.py +7 -19
- wandb/apis/workspaces/__init__.py +8 -0
- wandb/beta/workflows.py +8 -3
- wandb/cli/cli.py +151 -59
- wandb/docker/__init__.py +1 -1
- wandb/errors/term.py +10 -2
- wandb/filesync/step_checksum.py +1 -4
- wandb/filesync/step_prepare.py +4 -24
- wandb/filesync/step_upload.py +5 -107
- wandb/filesync/upload_job.py +0 -76
- wandb/integration/gym/__init__.py +35 -15
- wandb/integration/openai/fine_tuning.py +21 -3
- wandb/integration/prodigy/prodigy.py +1 -1
- wandb/jupyter.py +16 -17
- wandb/old/summary.py +5 -0
- wandb/plot/pr_curve.py +2 -1
- wandb/plot/roc_curve.py +2 -1
- wandb/{plots → plot}/utils.py +13 -25
- wandb/proto/v3/wandb_internal_pb2.py +54 -54
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v4/wandb_internal_pb2.py +54 -54
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v5/wandb_base_pb2.py +30 -0
- wandb/proto/v5/wandb_internal_pb2.py +355 -0
- wandb/proto/v5/wandb_server_pb2.py +63 -0
- wandb/proto/v5/wandb_settings_pb2.py +45 -0
- wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
- wandb/proto/wandb_base_pb2.py +2 -0
- wandb/proto/wandb_deprecated.py +9 -1
- wandb/proto/wandb_generate_deprecated.py +34 -0
- wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
- wandb/proto/wandb_internal_pb2.py +2 -0
- wandb/proto/wandb_server_pb2.py +2 -0
- wandb/proto/wandb_settings_pb2.py +2 -0
- wandb/proto/wandb_telemetry_pb2.py +2 -0
- wandb/sdk/artifacts/artifact.py +76 -23
- wandb/sdk/artifacts/artifact_manifest.py +1 -1
- wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
- wandb/sdk/artifacts/artifact_saver.py +1 -10
- wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
- wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
- wandb/sdk/artifacts/storage_policy.py +1 -12
- wandb/sdk/data_types/_dtypes.py +5 -2
- wandb/sdk/data_types/html.py +1 -1
- wandb/sdk/data_types/image.py +1 -1
- wandb/sdk/data_types/object_3d.py +1 -1
- wandb/sdk/data_types/video.py +4 -2
- wandb/sdk/interface/interface.py +13 -0
- wandb/sdk/interface/interface_shared.py +1 -1
- wandb/sdk/internal/file_pusher.py +2 -5
- wandb/sdk/internal/file_stream.py +6 -19
- wandb/sdk/internal/internal_api.py +160 -138
- wandb/sdk/internal/job_builder.py +207 -135
- wandb/sdk/internal/progress.py +0 -28
- wandb/sdk/internal/sender.py +105 -42
- wandb/sdk/internal/settings_static.py +8 -1
- wandb/sdk/internal/system/assets/gpu.py +2 -0
- wandb/sdk/internal/system/assets/trainium.py +3 -3
- wandb/sdk/internal/system/system_info.py +4 -2
- wandb/sdk/internal/update.py +1 -1
- wandb/sdk/launch/__init__.py +9 -1
- wandb/sdk/launch/_launch.py +4 -24
- wandb/sdk/launch/_launch_add.py +1 -3
- wandb/sdk/launch/_project_spec.py +184 -224
- wandb/sdk/launch/agent/agent.py +58 -18
- wandb/sdk/launch/agent/config.py +0 -3
- wandb/sdk/launch/builder/abstract.py +67 -0
- wandb/sdk/launch/builder/build.py +165 -576
- wandb/sdk/launch/builder/context_manager.py +235 -0
- wandb/sdk/launch/builder/docker_builder.py +7 -23
- wandb/sdk/launch/builder/kaniko_builder.py +10 -23
- wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
- wandb/sdk/launch/create_job.py +51 -45
- wandb/sdk/launch/environment/aws_environment.py +26 -1
- wandb/sdk/launch/inputs/files.py +148 -0
- wandb/sdk/launch/inputs/internal.py +224 -0
- wandb/sdk/launch/inputs/manage.py +95 -0
- wandb/sdk/launch/runner/abstract.py +2 -2
- wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
- wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
- wandb/sdk/launch/runner/local_container.py +2 -3
- wandb/sdk/launch/runner/local_process.py +8 -29
- wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
- wandb/sdk/launch/runner/vertex_runner.py +8 -7
- wandb/sdk/launch/sweeps/scheduler.py +2 -0
- wandb/sdk/launch/sweeps/utils.py +2 -2
- wandb/sdk/launch/utils.py +16 -138
- wandb/sdk/lib/_settings_toposort_generated.py +2 -5
- wandb/sdk/lib/apikey.py +4 -2
- wandb/sdk/lib/config_util.py +3 -3
- wandb/sdk/lib/proto_util.py +22 -1
- wandb/sdk/lib/redirect.py +1 -1
- wandb/sdk/service/service.py +2 -1
- wandb/sdk/service/streams.py +5 -5
- wandb/sdk/wandb_init.py +25 -59
- wandb/sdk/wandb_login.py +28 -25
- wandb/sdk/wandb_run.py +135 -70
- wandb/sdk/wandb_settings.py +33 -64
- wandb/sdk/wandb_watch.py +1 -1
- wandb/sklearn/plot/classifier.py +4 -6
- wandb/sync/sync.py +2 -2
- wandb/testing/relay.py +32 -17
- wandb/util.py +39 -37
- wandb/wandb_agent.py +3 -3
- wandb/wandb_controller.py +3 -2
- {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/METADATA +7 -9
- {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/RECORD +129 -151
- {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/WHEEL +1 -1
- wandb/apis/reports/v1/_blocks.py +0 -1406
- wandb/apis/reports/v1/_helpers.py +0 -70
- wandb/apis/reports/v1/_panels.py +0 -1282
- wandb/apis/reports/v1/_templates.py +0 -478
- wandb/apis/reports/v1/blocks.py +0 -27
- wandb/apis/reports/v1/helpers.py +0 -2
- wandb/apis/reports/v1/mutations.py +0 -66
- wandb/apis/reports/v1/panels.py +0 -17
- wandb/apis/reports/v1/report.py +0 -268
- wandb/apis/reports/v1/runset.py +0 -144
- wandb/apis/reports/v1/templates.py +0 -7
- wandb/apis/reports/v1/util.py +0 -406
- wandb/apis/reports/v1/validators.py +0 -131
- wandb/apis/reports/v2/blocks.py +0 -25
- wandb/apis/reports/v2/expr_parsing.py +0 -257
- wandb/apis/reports/v2/gql.py +0 -68
- wandb/apis/reports/v2/interface.py +0 -1911
- wandb/apis/reports/v2/internal.py +0 -867
- wandb/apis/reports/v2/metrics.py +0 -6
- wandb/apis/reports/v2/panels.py +0 -15
- wandb/catboost/__init__.py +0 -9
- wandb/fastai/__init__.py +0 -9
- wandb/keras/__init__.py +0 -19
- wandb/lightgbm/__init__.py +0 -9
- wandb/plots/__init__.py +0 -6
- wandb/plots/explain_text.py +0 -36
- wandb/plots/heatmap.py +0 -81
- wandb/plots/named_entity.py +0 -43
- wandb/plots/part_of_speech.py +0 -50
- wandb/plots/plot_definitions.py +0 -768
- wandb/plots/precision_recall.py +0 -121
- wandb/plots/roc.py +0 -103
- wandb/sacred/__init__.py +0 -3
- wandb/xgboost/__init__.py +0 -9
- {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/entry_points.txt +0 -0
- {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/licenses/LICENSE +0 -0
wandb/cli/cli.py
CHANGED
@@ -30,10 +30,12 @@ import wandb
|
|
30
30
|
import wandb.env
|
31
31
|
|
32
32
|
# from wandb.old.core import wandb_dir
|
33
|
+
import wandb.errors
|
33
34
|
import wandb.sdk.verify.verify as wandb_verify
|
34
35
|
from wandb import Config, Error, env, util, wandb_agent, wandb_sdk
|
35
36
|
from wandb.apis import InternalApi, PublicApi
|
36
37
|
from wandb.apis.public import RunQueue
|
38
|
+
from wandb.errors import WandbCoreNotAvailableError
|
37
39
|
from wandb.integration.magic import magic_install
|
38
40
|
from wandb.sdk.artifacts.artifact_file_cache import get_artifact_file_cache
|
39
41
|
from wandb.sdk.launch import utils as launch_utils
|
@@ -44,6 +46,7 @@ from wandb.sdk.launch.sweeps.scheduler import Scheduler
|
|
44
46
|
from wandb.sdk.lib import filesystem
|
45
47
|
from wandb.sdk.lib.wburls import wburls
|
46
48
|
from wandb.sync import SyncManager, get_run_from_path, get_runs
|
49
|
+
from wandb.util import get_core_path
|
47
50
|
|
48
51
|
# Send cli logs to wandb/debug-cli.<username>.log by default and fallback to a temp dir.
|
49
52
|
_wandb_dir = wandb.old.core.wandb_dir(env.get_dir())
|
@@ -194,9 +197,9 @@ def projects(entity, display=True):
|
|
194
197
|
api = _get_cling_api()
|
195
198
|
projects = api.list_projects(entity=entity)
|
196
199
|
if len(projects) == 0:
|
197
|
-
message = "No projects found for
|
200
|
+
message = "No projects found for {}".format(entity)
|
198
201
|
else:
|
199
|
-
message = 'Latest projects for "
|
202
|
+
message = 'Latest projects for "{}"'.format(entity)
|
200
203
|
if display:
|
201
204
|
click.echo(click.style(message, bold=True))
|
202
205
|
for project in projects:
|
@@ -420,7 +423,7 @@ def init(ctx, project, entity, reset, mode):
|
|
420
423
|
"""
|
421
424
|
).format(
|
422
425
|
code1=click.style("import wandb", bold=True),
|
423
|
-
code2=click.style('wandb.init(project="
|
426
|
+
code2=click.style('wandb.init(project="{}")'.format(project), bold=True),
|
424
427
|
run=click.style("python <train.py>", bold=True),
|
425
428
|
)
|
426
429
|
)
|
@@ -430,14 +433,15 @@ def init(ctx, project, entity, reset, mode):
|
|
430
433
|
def beta():
|
431
434
|
"""Beta versions of wandb CLI commands. Requires wandb-core."""
|
432
435
|
# this is the future that requires wandb-core!
|
433
|
-
|
436
|
+
wandb._sentry.configure_scope(process_context="wandb_beta")
|
437
|
+
wandb.require("core")
|
434
438
|
|
435
|
-
|
439
|
+
try:
|
440
|
+
get_core_path()
|
441
|
+
except WandbCoreNotAvailableError as e:
|
442
|
+
wandb._sentry.exception(f"using `wandb beta`. failed with {e}")
|
436
443
|
click.secho(
|
437
|
-
(
|
438
|
-
"wandb beta commands require wandb-core, please install with"
|
439
|
-
" `pip install wandb-core`"
|
440
|
-
),
|
444
|
+
(e),
|
441
445
|
fg="red",
|
442
446
|
err=True,
|
443
447
|
)
|
@@ -876,6 +880,14 @@ def sync(
|
|
876
880
|
default=False,
|
877
881
|
help="Resume a sweep to continue running new runs.",
|
878
882
|
)
|
883
|
+
@click.option(
|
884
|
+
"--prior_run",
|
885
|
+
"-R",
|
886
|
+
"prior_runs",
|
887
|
+
multiple=True,
|
888
|
+
default=None,
|
889
|
+
help="ID of an existing run to add to this sweep",
|
890
|
+
)
|
879
891
|
@click.argument("config_yaml_or_sweep_id")
|
880
892
|
@click.pass_context
|
881
893
|
@display_error
|
@@ -893,6 +905,7 @@ def sweep(
|
|
893
905
|
cancel,
|
894
906
|
pause,
|
895
907
|
resume,
|
908
|
+
prior_runs,
|
896
909
|
config_yaml_or_sweep_id,
|
897
910
|
):
|
898
911
|
state_args = "stop", "cancel", "pause", "resume"
|
@@ -923,7 +936,7 @@ def sweep(
|
|
923
936
|
"resume": "Resuming",
|
924
937
|
}
|
925
938
|
wandb.termlog(f"{ings[state]} sweep {entity}/{project}/{sweep_id}")
|
926
|
-
getattr(api, "
|
939
|
+
getattr(api, "{}_sweep".format(state))(sweep_id, entity=entity, project=project)
|
927
940
|
wandb.termlog("Done.")
|
928
941
|
return
|
929
942
|
else:
|
@@ -1034,6 +1047,7 @@ def sweep(
|
|
1034
1047
|
project=project,
|
1035
1048
|
entity=entity,
|
1036
1049
|
obj_id=sweep_obj_id,
|
1050
|
+
prior_runs=prior_runs,
|
1037
1051
|
)
|
1038
1052
|
sweep_utils.handle_sweep_config_violations(warnings)
|
1039
1053
|
|
@@ -1100,6 +1114,14 @@ def sweep(
|
|
1100
1114
|
default=None,
|
1101
1115
|
help="Resume a launch sweep by passing an 8-char sweep id. Queue required",
|
1102
1116
|
)
|
1117
|
+
@click.option(
|
1118
|
+
"--prior_run",
|
1119
|
+
"-R",
|
1120
|
+
"prior_runs",
|
1121
|
+
multiple=True,
|
1122
|
+
default=None,
|
1123
|
+
help="ID of an existing run to add to this sweep",
|
1124
|
+
)
|
1103
1125
|
@click.argument("config", required=False, type=click.Path(exists=True))
|
1104
1126
|
@click.pass_context
|
1105
1127
|
@display_error
|
@@ -1110,6 +1132,7 @@ def launch_sweep(
|
|
1110
1132
|
queue,
|
1111
1133
|
config,
|
1112
1134
|
resume_id,
|
1135
|
+
prior_runs,
|
1113
1136
|
):
|
1114
1137
|
api = _get_cling_api()
|
1115
1138
|
env = os.environ
|
@@ -1294,6 +1317,7 @@ def launch_sweep(
|
|
1294
1317
|
obj_id=sweep_obj_id, # if resuming
|
1295
1318
|
launch_scheduler=launch_scheduler_with_queue,
|
1296
1319
|
state="PENDING",
|
1320
|
+
prior_runs=prior_runs,
|
1297
1321
|
)
|
1298
1322
|
sweep_utils.handle_sweep_config_violations(warnings)
|
1299
1323
|
# Log nicely formatted sweep information
|
@@ -1307,7 +1331,14 @@ def launch_sweep(
|
|
1307
1331
|
|
1308
1332
|
|
1309
1333
|
@cli.command(help=f"Launch or queue a W&B Job. See {wburls.get('cli_launch')}")
|
1310
|
-
@click.option(
|
1334
|
+
@click.option(
|
1335
|
+
"--uri",
|
1336
|
+
"-u",
|
1337
|
+
metavar="(str)",
|
1338
|
+
default=None,
|
1339
|
+
help="Local path or git repo uri to launch. If provided this command will "
|
1340
|
+
"create a job from the specified uri.",
|
1341
|
+
)
|
1311
1342
|
@click.option(
|
1312
1343
|
"--job",
|
1313
1344
|
"-j",
|
@@ -1332,6 +1363,20 @@ def launch_sweep(
|
|
1332
1363
|
hidden=True,
|
1333
1364
|
help="Version of the project to run, as a Git commit reference for Git projects.",
|
1334
1365
|
)
|
1366
|
+
@click.option(
|
1367
|
+
"--build-context",
|
1368
|
+
metavar="(str)",
|
1369
|
+
help="Path to the build context within the source code. Defaults to the "
|
1370
|
+
"root of the source code. Compatible only with -u.",
|
1371
|
+
)
|
1372
|
+
@click.option(
|
1373
|
+
"--job-name",
|
1374
|
+
"-J",
|
1375
|
+
metavar="(str)",
|
1376
|
+
default=None,
|
1377
|
+
hidden=True,
|
1378
|
+
help="Name for the job created if the -u,--uri flag is passed in.",
|
1379
|
+
)
|
1335
1380
|
@click.option(
|
1336
1381
|
"--name",
|
1337
1382
|
envvar="WANDB_NAME",
|
@@ -1456,6 +1501,7 @@ def launch(
|
|
1456
1501
|
job,
|
1457
1502
|
entry_point,
|
1458
1503
|
git_version,
|
1504
|
+
build_context,
|
1459
1505
|
name,
|
1460
1506
|
resource,
|
1461
1507
|
entity,
|
@@ -1471,6 +1517,7 @@ def launch(
|
|
1471
1517
|
project_queue,
|
1472
1518
|
dockerfile,
|
1473
1519
|
priority,
|
1520
|
+
job_name,
|
1474
1521
|
):
|
1475
1522
|
"""Start a W&B run from the given URI.
|
1476
1523
|
|
@@ -1486,6 +1533,8 @@ def launch(
|
|
1486
1533
|
f"=== Launch called with kwargs {locals()} CLI Version: {wandb.__version__}==="
|
1487
1534
|
)
|
1488
1535
|
from wandb.sdk.launch._launch import _launch
|
1536
|
+
from wandb.sdk.launch.create_job import _create_job
|
1537
|
+
from wandb.sdk.launch.utils import _is_git_uri
|
1489
1538
|
|
1490
1539
|
api = _get_cling_api()
|
1491
1540
|
wandb._sentry.configure_scope(process_context="launch_cli")
|
@@ -1532,6 +1581,36 @@ def launch(
|
|
1532
1581
|
|
1533
1582
|
run_id = config.get("run_id")
|
1534
1583
|
|
1584
|
+
# If URI was provided, we need to create a job from it.
|
1585
|
+
if uri:
|
1586
|
+
if entry_point is None:
|
1587
|
+
raise LaunchError(
|
1588
|
+
"Cannot provide a uri without an entry point. Please provide an "
|
1589
|
+
"entry point with --entry-point or -E."
|
1590
|
+
)
|
1591
|
+
if job is not None:
|
1592
|
+
raise LaunchError("Cannot provide both a uri and a job name.")
|
1593
|
+
job_type = (
|
1594
|
+
"git" if _is_git_uri(uri) else "code"
|
1595
|
+
) # TODO: Add support for local URIs with git.
|
1596
|
+
if entity is None:
|
1597
|
+
entity = launch_utils.get_default_entity(api, config)
|
1598
|
+
artifact, _, _ = _create_job(
|
1599
|
+
api,
|
1600
|
+
job_type,
|
1601
|
+
uri,
|
1602
|
+
entrypoint=" ".join(entry_point),
|
1603
|
+
git_hash=git_version,
|
1604
|
+
name=job_name,
|
1605
|
+
project=project,
|
1606
|
+
build_context=build_context,
|
1607
|
+
dockerfile=dockerfile,
|
1608
|
+
entity=entity,
|
1609
|
+
)
|
1610
|
+
if artifact is None:
|
1611
|
+
raise LaunchError(f"Failed to create job from uri: {uri}")
|
1612
|
+
job = f"{entity}/{project}/{artifact.name}"
|
1613
|
+
|
1535
1614
|
if dockerfile:
|
1536
1615
|
if "overrides" in config:
|
1537
1616
|
config["overrides"]["dockerfile"] = dockerfile
|
@@ -1565,7 +1644,6 @@ def launch(
|
|
1565
1644
|
run = asyncio.run(
|
1566
1645
|
_launch(
|
1567
1646
|
api,
|
1568
|
-
uri,
|
1569
1647
|
job,
|
1570
1648
|
project=project,
|
1571
1649
|
entity=entity,
|
@@ -1602,7 +1680,6 @@ def launch(
|
|
1602
1680
|
try:
|
1603
1681
|
_launch_add(
|
1604
1682
|
api,
|
1605
|
-
uri,
|
1606
1683
|
job,
|
1607
1684
|
config,
|
1608
1685
|
template_variables,
|
@@ -1641,13 +1718,6 @@ def launch(
|
|
1641
1718
|
metavar="<queue(s)>",
|
1642
1719
|
help="The name of a queue for the agent to watch. Multiple -q flags supported.",
|
1643
1720
|
)
|
1644
|
-
@click.option(
|
1645
|
-
"--project",
|
1646
|
-
"-p",
|
1647
|
-
default=None,
|
1648
|
-
help="""Name of the project which the agent will watch.
|
1649
|
-
If passed in, will override the project value passed in using a config file.""",
|
1650
|
-
)
|
1651
1721
|
@click.option(
|
1652
1722
|
"--entity",
|
1653
1723
|
"-e",
|
@@ -1684,7 +1754,6 @@ def launch(
|
|
1684
1754
|
@display_error
|
1685
1755
|
def launch_agent(
|
1686
1756
|
ctx,
|
1687
|
-
project=None,
|
1688
1757
|
entity=None,
|
1689
1758
|
queues=None,
|
1690
1759
|
max_jobs=None,
|
@@ -1709,7 +1778,7 @@ def launch_agent(
|
|
1709
1778
|
api = _get_cling_api()
|
1710
1779
|
wandb._sentry.configure_scope(process_context="launch_agent")
|
1711
1780
|
agent_config, api = _launch.resolve_agent_config(
|
1712
|
-
entity,
|
1781
|
+
entity, max_jobs, queues, config, verbose
|
1713
1782
|
)
|
1714
1783
|
|
1715
1784
|
if len(agent_config.get("queues")) == 0:
|
@@ -1907,14 +1976,16 @@ def describe(job):
|
|
1907
1976
|
"--entry-point",
|
1908
1977
|
"-E",
|
1909
1978
|
"entrypoint",
|
1910
|
-
help="Entrypoint to the script, including an executable and an entrypoint
|
1979
|
+
help="Entrypoint to the script, including an executable and an entrypoint "
|
1980
|
+
"file. Required for code or repo jobs. If --build-context is provided, "
|
1981
|
+
"paths in the entrypoint command will be relative to the build context.",
|
1911
1982
|
)
|
1912
1983
|
@click.option(
|
1913
1984
|
"--git-hash",
|
1914
1985
|
"-g",
|
1915
1986
|
"git_hash",
|
1916
1987
|
type=str,
|
1917
|
-
help="
|
1988
|
+
help="Commit reference to use as the source for git jobs",
|
1918
1989
|
)
|
1919
1990
|
@click.option(
|
1920
1991
|
"--runtime",
|
@@ -1922,6 +1993,20 @@ def describe(job):
|
|
1922
1993
|
type=str,
|
1923
1994
|
help="Python runtime to execute the job",
|
1924
1995
|
)
|
1996
|
+
@click.option(
|
1997
|
+
"--build-context",
|
1998
|
+
"-b",
|
1999
|
+
type=str,
|
2000
|
+
help="Path to the build context from the root of the job source code. If "
|
2001
|
+
"provided, this is used as the base path for the Dockerfile and entrypoint.",
|
2002
|
+
)
|
2003
|
+
@click.option(
|
2004
|
+
"--dockerfile",
|
2005
|
+
"-D",
|
2006
|
+
type=str,
|
2007
|
+
help="Path to the Dockerfile for the job. If --build-context is provided, "
|
2008
|
+
"the Dockerfile path will be relative to the build context.",
|
2009
|
+
)
|
1925
2010
|
@click.argument(
|
1926
2011
|
"job_type",
|
1927
2012
|
type=click.Choice(("git", "code", "image")),
|
@@ -1938,6 +2023,8 @@ def create(
|
|
1938
2023
|
entrypoint,
|
1939
2024
|
git_hash,
|
1940
2025
|
runtime,
|
2026
|
+
build_context,
|
2027
|
+
dockerfile,
|
1941
2028
|
):
|
1942
2029
|
"""Create a job from a source, without a wandb run.
|
1943
2030
|
|
@@ -1980,6 +2067,8 @@ def create(
|
|
1980
2067
|
entrypoint=entrypoint,
|
1981
2068
|
git_hash=git_hash,
|
1982
2069
|
runtime=runtime,
|
2070
|
+
build_context=build_context,
|
2071
|
+
dockerfile=dockerfile,
|
1983
2072
|
)
|
1984
2073
|
if not artifact:
|
1985
2074
|
wandb.termerror("Job creation failed")
|
@@ -2038,13 +2127,13 @@ def docker_run(ctx, docker_run_args):
|
|
2038
2127
|
if image:
|
2039
2128
|
resolved_image = wandb.docker.image_id(image)
|
2040
2129
|
if resolved_image:
|
2041
|
-
args = ["-e", "WANDB_DOCKER
|
2130
|
+
args = ["-e", "WANDB_DOCKER={}".format(resolved_image)] + args
|
2042
2131
|
else:
|
2043
2132
|
wandb.termlog(
|
2044
2133
|
"Couldn't detect image argument, running command without the WANDB_DOCKER env variable"
|
2045
2134
|
)
|
2046
2135
|
if api.api_key:
|
2047
|
-
args = ["-e", "WANDB_API_KEY
|
2136
|
+
args = ["-e", "WANDB_API_KEY={}".format(api.api_key)] + args
|
2048
2137
|
else:
|
2049
2138
|
wandb.termlog(
|
2050
2139
|
"Not logged in, run `wandb login` from the host machine to enable result logging"
|
@@ -2135,14 +2224,17 @@ def docker(
|
|
2135
2224
|
resolved_image = wandb.docker.image_id(image)
|
2136
2225
|
if resolved_image is None:
|
2137
2226
|
raise ClickException(
|
2138
|
-
"Couldn't find image locally or in a registry, try running `docker pull
|
2139
|
-
|
2227
|
+
"Couldn't find image locally or in a registry, try running `docker pull {}`".format(
|
2228
|
+
image
|
2229
|
+
)
|
2140
2230
|
)
|
2141
2231
|
if digest:
|
2142
2232
|
sys.stdout.write(resolved_image)
|
2143
2233
|
exit(0)
|
2144
2234
|
|
2145
|
-
existing = wandb.docker.shell(
|
2235
|
+
existing = wandb.docker.shell(
|
2236
|
+
["ps", "-f", "ancestor={}".format(resolved_image), "-q"]
|
2237
|
+
)
|
2146
2238
|
if existing:
|
2147
2239
|
if click.confirm(
|
2148
2240
|
"Found running container with the same image, do you want to attach?"
|
@@ -2156,7 +2248,7 @@ def docker(
|
|
2156
2248
|
"-e",
|
2157
2249
|
"LANG=C.UTF-8",
|
2158
2250
|
"-e",
|
2159
|
-
"WANDB_DOCKER
|
2251
|
+
"WANDB_DOCKER={}".format(resolved_image),
|
2160
2252
|
"--ipc=host",
|
2161
2253
|
"-v",
|
2162
2254
|
wandb.docker.entrypoint + ":/wandb-entrypoint.sh",
|
@@ -2169,7 +2261,7 @@ def docker(
|
|
2169
2261
|
# TODO: We should default to the working directory if defined
|
2170
2262
|
command.extend(["-v", cwd + ":" + dir, "-w", dir])
|
2171
2263
|
if api.api_key:
|
2172
|
-
command.extend(["-e", "WANDB_API_KEY
|
2264
|
+
command.extend(["-e", "WANDB_API_KEY={}".format(api.api_key)])
|
2173
2265
|
else:
|
2174
2266
|
wandb.termlog(
|
2175
2267
|
"Couldn't find WANDB_API_KEY, run `wandb login` to enable streaming metrics"
|
@@ -2177,16 +2269,15 @@ def docker(
|
|
2177
2269
|
if jupyter:
|
2178
2270
|
command.extend(["-e", "WANDB_ENSURE_JUPYTER=1", "-p", port + ":8888"])
|
2179
2271
|
no_tty = True
|
2180
|
-
cmd = (
|
2181
|
-
|
2182
|
-
% dir
|
2272
|
+
cmd = "jupyter lab --no-browser --ip=0.0.0.0 --allow-root --NotebookApp.token= --notebook-dir {}".format(
|
2273
|
+
dir
|
2183
2274
|
)
|
2184
2275
|
command.extend(args)
|
2185
2276
|
if no_tty:
|
2186
2277
|
command.extend([image, shell, "-c", cmd])
|
2187
2278
|
else:
|
2188
2279
|
if cmd:
|
2189
|
-
command.extend(["-e", "WANDB_COMMAND
|
2280
|
+
command.extend(["-e", "WANDB_COMMAND={}".format(cmd)])
|
2190
2281
|
command.extend(["-it", image, shell])
|
2191
2282
|
wandb.termlog("Launching docker container \U0001f6a2")
|
2192
2283
|
subprocess.call(command)
|
@@ -2272,7 +2363,7 @@ def start(ctx, port, env, daemon, upgrade, edge):
|
|
2272
2363
|
exit(1)
|
2273
2364
|
image = "docker.pkg.github.com/wandb/core/local" if edge else "wandb/local"
|
2274
2365
|
username = getpass.getuser()
|
2275
|
-
env_vars = ["-e", "LOCAL_USERNAME
|
2366
|
+
env_vars = ["-e", "LOCAL_USERNAME={}".format(username)]
|
2276
2367
|
for e in env:
|
2277
2368
|
env_vars.append("-e")
|
2278
2369
|
env_vars.append(e)
|
@@ -2306,7 +2397,9 @@ def start(ctx, port, env, daemon, upgrade, edge):
|
|
2306
2397
|
)
|
2307
2398
|
exit(1)
|
2308
2399
|
else:
|
2309
|
-
wandb.termlog(
|
2400
|
+
wandb.termlog(
|
2401
|
+
"W&B server started at http://localhost:{} \U0001f680".format(port)
|
2402
|
+
)
|
2310
2403
|
wandb.termlog("You can stop the server by running `wandb server stop`")
|
2311
2404
|
if not api.api_key:
|
2312
2405
|
# Let the server start before potentially launching a browser
|
@@ -2443,7 +2536,7 @@ def get(path, root, type):
|
|
2443
2536
|
)
|
2444
2537
|
artifact = public_api.artifact(full_path, type=type)
|
2445
2538
|
path = artifact.download(root=root)
|
2446
|
-
wandb.termlog("Artifact downloaded to
|
2539
|
+
wandb.termlog("Artifact downloaded to {}".format(path))
|
2447
2540
|
except ValueError:
|
2448
2541
|
raise ClickException("Unable to download artifact")
|
2449
2542
|
|
@@ -2521,17 +2614,17 @@ def pull(run, project, entity):
|
|
2521
2614
|
|
2522
2615
|
for name in urls:
|
2523
2616
|
if api.file_current(name, urls[name]["md5"]):
|
2524
|
-
click.echo("File
|
2617
|
+
click.echo("File {} is up to date".format(name))
|
2525
2618
|
else:
|
2526
2619
|
length, response = api.download_file(urls[name]["url"])
|
2527
2620
|
# TODO: I had to add this because some versions in CI broke click.progressbar
|
2528
|
-
sys.stdout.write("File
|
2621
|
+
sys.stdout.write("File {}\r".format(name))
|
2529
2622
|
dirname = os.path.dirname(name)
|
2530
2623
|
if dirname != "":
|
2531
2624
|
filesystem.mkdir_exists_ok(dirname)
|
2532
2625
|
with click.progressbar(
|
2533
2626
|
length=length,
|
2534
|
-
label="File
|
2627
|
+
label="File {}".format(name),
|
2535
2628
|
fill_char=click.style("&", fg="green"),
|
2536
2629
|
) as bar:
|
2537
2630
|
with open(name, "wb") as f:
|
@@ -2577,11 +2670,8 @@ def restore(ctx, run, no_git, branch, project, entity):
|
|
2577
2670
|
)
|
2578
2671
|
repo = metadata.get("git", {}).get("repo")
|
2579
2672
|
image = metadata.get("docker")
|
2580
|
-
restore_message =
|
2581
|
-
|
2582
|
-
Run `git clone %s` and restore from there or pass the --no-git flag."""
|
2583
|
-
% repo
|
2584
|
-
)
|
2673
|
+
restore_message = """`wandb restore` needs to be run from the same git repository as the original run.
|
2674
|
+
Run `git clone {}` and restore from there or pass the --no-git flag.""".format(repo)
|
2585
2675
|
if no_git:
|
2586
2676
|
commit = None
|
2587
2677
|
elif not api.git.enabled:
|
@@ -2626,18 +2716,21 @@ Run `git clone %s` and restore from there or pass the --no-git flag."""
|
|
2626
2716
|
else:
|
2627
2717
|
patch_path = None
|
2628
2718
|
|
2629
|
-
branch_name = "wandb
|
2719
|
+
branch_name = "wandb/{}".format(run)
|
2630
2720
|
if branch and branch_name not in api.git.repo.branches:
|
2631
2721
|
api.git.repo.git.checkout(commit, b=branch_name)
|
2632
|
-
wandb.termlog(
|
2722
|
+
wandb.termlog(
|
2723
|
+
"Created branch {}".format(click.style(branch_name, bold=True))
|
2724
|
+
)
|
2633
2725
|
elif branch:
|
2634
2726
|
wandb.termlog(
|
2635
|
-
"Using existing branch, run `git branch -D
|
2636
|
-
|
2727
|
+
"Using existing branch, run `git branch -D {}` from master for a clean checkout".format(
|
2728
|
+
branch_name
|
2729
|
+
)
|
2637
2730
|
)
|
2638
2731
|
api.git.repo.git.checkout(branch_name)
|
2639
2732
|
else:
|
2640
|
-
wandb.termlog("Checking out
|
2733
|
+
wandb.termlog("Checking out {} in detached mode".format(commit))
|
2641
2734
|
api.git.repo.git.checkout(commit)
|
2642
2735
|
|
2643
2736
|
if patch_path:
|
@@ -2675,7 +2768,7 @@ Run `git clone %s` and restore from there or pass the --no-git flag."""
|
|
2675
2768
|
with open(config_path, "w") as f:
|
2676
2769
|
f.write(s)
|
2677
2770
|
|
2678
|
-
wandb.termlog("Restored config variables to
|
2771
|
+
wandb.termlog("Restored config variables to {}".format(config_path))
|
2679
2772
|
if image:
|
2680
2773
|
if not metadata["program"].startswith("<") and metadata.get("args") is not None:
|
2681
2774
|
# TODO: we may not want to default to python here.
|
@@ -2710,7 +2803,9 @@ def magic(ctx, program, args):
|
|
2710
2803
|
with open(program, "rb") as fp:
|
2711
2804
|
code = compile(fp.read(), program, "exec")
|
2712
2805
|
except OSError:
|
2713
|
-
click.echo(
|
2806
|
+
click.echo(
|
2807
|
+
click.style("Could not launch program: {}".format(program), fg="red")
|
2808
|
+
)
|
2714
2809
|
sys.exit(1)
|
2715
2810
|
globs = {
|
2716
2811
|
"__file__": program,
|
@@ -2718,14 +2813,11 @@ def magic(ctx, program, args):
|
|
2718
2813
|
"__package__": None,
|
2719
2814
|
"wandb_magic_install": magic_install,
|
2720
2815
|
}
|
2721
|
-
prep =
|
2722
|
-
"""
|
2816
|
+
prep = """
|
2723
2817
|
import __main__
|
2724
|
-
__main__.__file__ = "
|
2818
|
+
__main__.__file__ = "{}"
|
2725
2819
|
wandb_magic_install()
|
2726
|
-
"""
|
2727
|
-
% program
|
2728
|
-
)
|
2820
|
+
""".format(program)
|
2729
2821
|
magic_run(prep, globs, None)
|
2730
2822
|
magic_run(code, globs, None)
|
2731
2823
|
|
wandb/docker/__init__.py
CHANGED
wandb/errors/term.py
CHANGED
@@ -27,7 +27,10 @@ def termsetup(settings, logger) -> None:
|
|
27
27
|
|
28
28
|
|
29
29
|
def termlog(
|
30
|
-
string: str = "",
|
30
|
+
string: str = "",
|
31
|
+
newline: bool = True,
|
32
|
+
repeat: bool = True,
|
33
|
+
prefix: bool = True,
|
31
34
|
) -> None:
|
32
35
|
"""Log to standard error with formatting.
|
33
36
|
|
@@ -68,7 +71,12 @@ def termerror(string: str, **kwargs: Any) -> None:
|
|
68
71
|
|
69
72
|
|
70
73
|
def _log(
|
71
|
-
string="",
|
74
|
+
string="",
|
75
|
+
newline=True,
|
76
|
+
repeat=True,
|
77
|
+
prefix=True,
|
78
|
+
silent=False,
|
79
|
+
level=logging.INFO,
|
72
80
|
):
|
73
81
|
global _logger
|
74
82
|
silent = silent or _silent
|
wandb/filesync/step_checksum.py
CHANGED
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
17
17
|
|
18
18
|
from wandb.filesync import stats
|
19
19
|
from wandb.sdk.artifacts.artifact_manifest import ArtifactManifest
|
20
|
-
from wandb.sdk.artifacts.artifact_saver import SaveFn
|
20
|
+
from wandb.sdk.artifacts.artifact_saver import SaveFn
|
21
21
|
from wandb.sdk.internal import internal_api
|
22
22
|
|
23
23
|
|
@@ -31,7 +31,6 @@ class RequestStoreManifestFiles(NamedTuple):
|
|
31
31
|
manifest: "ArtifactManifest"
|
32
32
|
artifact_id: str
|
33
33
|
save_fn: "SaveFn"
|
34
|
-
save_fn_async: "SaveFnAsync"
|
35
34
|
|
36
35
|
|
37
36
|
class RequestCommitArtifact(NamedTuple):
|
@@ -96,7 +95,6 @@ class StepChecksum:
|
|
96
95
|
req.copy,
|
97
96
|
None,
|
98
97
|
None,
|
99
|
-
None,
|
100
98
|
)
|
101
99
|
)
|
102
100
|
elif isinstance(req, RequestStoreManifestFiles):
|
@@ -115,7 +113,6 @@ class StepChecksum:
|
|
115
113
|
entry.digest,
|
116
114
|
False,
|
117
115
|
functools.partial(req.save_fn, entry),
|
118
|
-
functools.partial(req.save_fn_async, entry),
|
119
116
|
entry.digest,
|
120
117
|
)
|
121
118
|
)
|
wandb/filesync/step_prepare.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
"""Batching file prepare requests to our API."""
|
2
2
|
|
3
|
-
import asyncio
|
4
|
-
import functools
|
5
3
|
import queue
|
6
4
|
import threading
|
7
5
|
import time
|
@@ -29,10 +27,7 @@ if TYPE_CHECKING:
|
|
29
27
|
# Request for a file to be prepared.
|
30
28
|
class RequestPrepare(NamedTuple):
|
31
29
|
file_spec: "CreateArtifactFileSpecInput"
|
32
|
-
response_channel:
|
33
|
-
"queue.Queue[ResponsePrepare]",
|
34
|
-
Tuple["asyncio.AbstractEventLoop", "asyncio.Future[ResponsePrepare]"],
|
35
|
-
]
|
30
|
+
response_channel: "queue.Queue[ResponsePrepare]"
|
36
31
|
|
37
32
|
|
38
33
|
class RequestFinish(NamedTuple):
|
@@ -110,7 +105,7 @@ def prepare_response(response: "CreateArtifactFilesResponseFile") -> ResponsePre
|
|
110
105
|
class StepPrepare:
|
111
106
|
"""A thread that batches requests to our file prepare API.
|
112
107
|
|
113
|
-
Any number of threads may call
|
108
|
+
Any number of threads may call prepare() in parallel. The PrepareBatcher thread
|
114
109
|
will batch requests up and send them all to the backend at once.
|
115
110
|
"""
|
116
111
|
|
@@ -145,11 +140,7 @@ class StepPrepare:
|
|
145
140
|
name = prepare_request.file_spec["name"]
|
146
141
|
response_file = batch_response[name]
|
147
142
|
response = prepare_response(response_file)
|
148
|
-
|
149
|
-
prepare_request.response_channel.put(response)
|
150
|
-
else:
|
151
|
-
loop, future = prepare_request.response_channel
|
152
|
-
loop.call_soon_threadsafe(future.set_result, response)
|
143
|
+
prepare_request.response_channel.put(response)
|
153
144
|
if finish:
|
154
145
|
break
|
155
146
|
|
@@ -167,18 +158,7 @@ class StepPrepare:
|
|
167
158
|
"""
|
168
159
|
return self._api.create_artifact_files([req.file_spec for req in batch])
|
169
160
|
|
170
|
-
def
|
171
|
-
self, file_spec: "CreateArtifactFileSpecInput"
|
172
|
-
) -> "asyncio.Future[ResponsePrepare]":
|
173
|
-
"""Request the backend to prepare a file for upload."""
|
174
|
-
response: asyncio.Future[ResponsePrepare] = asyncio.Future()
|
175
|
-
self._request_queue.put(
|
176
|
-
RequestPrepare(file_spec, (asyncio.get_event_loop(), response))
|
177
|
-
)
|
178
|
-
return response
|
179
|
-
|
180
|
-
@functools.wraps(prepare_async)
|
181
|
-
def prepare_sync(
|
161
|
+
def prepare(
|
182
162
|
self, file_spec: "CreateArtifactFileSpecInput"
|
183
163
|
) -> "queue.Queue[ResponsePrepare]":
|
184
164
|
response_queue: queue.Queue[ResponsePrepare] = queue.Queue()
|