wandb 0.17.0rc1__py3-none-win_amd64.whl → 0.17.1__py3-none-win_amd64.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +1 -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/bin/wandb-core +0 -0
- wandb/cli/cli.py +131 -59
- wandb/data_types.py +6 -3
- wandb/docker/__init__.py +2 -2
- wandb/env.py +3 -3
- 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/huggingface/resolver.py +2 -2
- wandb/integration/keras/callbacks/metrics_logger.py +1 -1
- wandb/integration/keras/keras.py +1 -1
- wandb/integration/openai/fine_tuning.py +21 -3
- wandb/integration/prodigy/prodigy.py +1 -1
- wandb/jupyter.py +16 -17
- wandb/old/summary.py +1 -1
- wandb/plot/confusion_matrix.py +1 -1
- 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 +68 -22
- 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 +8 -8
- wandb/sdk/data_types/image.py +2 -2
- wandb/sdk/data_types/video.py +5 -3
- wandb/sdk/integration_utils/data_logging.py +5 -5
- wandb/sdk/interface/interface.py +14 -1
- 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 +148 -136
- wandb/sdk/internal/job_builder.py +208 -136
- wandb/sdk/internal/progress.py +0 -28
- wandb/sdk/internal/sender.py +102 -39
- wandb/sdk/internal/settings_static.py +8 -1
- 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 +187 -225
- wandb/sdk/launch/agent/agent.py +59 -19
- wandb/sdk/launch/agent/config.py +0 -3
- wandb/sdk/launch/builder/abstract.py +68 -1
- 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 +12 -25
- 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/registry/google_artifact_registry.py +1 -1
- 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 +5 -3
- wandb/sdk/launch/sweeps/scheduler_sweep.py +1 -1
- wandb/sdk/launch/sweeps/utils.py +4 -4
- 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/import_hooks.py +1 -1
- wandb/sdk/lib/proto_util.py +22 -1
- wandb/sdk/lib/redirect.py +20 -15
- wandb/sdk/lib/tracelog.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 +123 -53
- wandb/sdk/wandb_settings.py +33 -64
- wandb/sdk/wandb_setup.py +1 -1
- wandb/sdk/wandb_watch.py +1 -1
- wandb/sklearn/plot/classifier.py +10 -12
- wandb/sklearn/plot/clusterer.py +1 -1
- wandb/sync/sync.py +2 -2
- wandb/testing/relay.py +32 -17
- wandb/util.py +36 -37
- wandb/wandb_agent.py +3 -3
- wandb/wandb_controller.py +5 -4
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/METADATA +8 -10
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/RECORD +140 -162
- 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.0rc1.dist-info → wandb-0.17.1.dist-info}/WHEEL +0 -0
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/entry_points.txt +0 -0
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/launch/utils.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# heavily inspired by https://github.com/mlflow/mlflow/blob/master/mlflow/projects/utils.py
|
2
1
|
import asyncio
|
3
2
|
import json
|
4
3
|
import logging
|
@@ -16,7 +15,6 @@ import wandb
|
|
16
15
|
import wandb.docker as docker
|
17
16
|
from wandb import util
|
18
17
|
from wandb.apis.internal import Api
|
19
|
-
from wandb.errors import CommError
|
20
18
|
from wandb.sdk.launch.errors import LaunchError
|
21
19
|
from wandb.sdk.launch.git_reference import GitReference
|
22
20
|
from wandb.sdk.launch.wandb_reference import WandbReference
|
@@ -32,12 +30,13 @@ FAILED_PACKAGES_REGEX = re.compile(
|
|
32
30
|
)
|
33
31
|
|
34
32
|
if TYPE_CHECKING: # pragma: no cover
|
35
|
-
from wandb.sdk.artifacts.artifact import Artifact
|
36
33
|
from wandb.sdk.launch.agent.job_status_tracker import JobAndRunStatusTracker
|
37
34
|
|
38
35
|
|
39
36
|
# TODO: this should be restricted to just Git repos and not S3 and stuff like that
|
40
|
-
_GIT_URI_REGEX = re.compile(
|
37
|
+
_GIT_URI_REGEX = re.compile(
|
38
|
+
r"^[^/|^~|^\.].*(git|bitbucket|dev\.azure\.com|\.visualstudio\.com)"
|
39
|
+
)
|
41
40
|
_VALID_IP_REGEX = r"^https?://[0-9]+(?:\.[0-9]+){3}(:[0-9]+)?"
|
42
41
|
_VALID_PIP_PACKAGE_REGEX = r"^[a-zA-Z0-9_.-]+$"
|
43
42
|
_VALID_WANDB_REGEX = r"^https?://(api.)?wandb"
|
@@ -75,6 +74,7 @@ AZURE_BLOB_REGEX = re.compile(
|
|
75
74
|
r"^https://([^\.]+)\.blob\.core\.windows\.net/([^/]+)/?(.*)$"
|
76
75
|
)
|
77
76
|
|
77
|
+
ARN_PARTITION_RE = re.compile(r"^arn:([^:]+):[^:]*:[^:]*:[^:]*:[^:]*$")
|
78
78
|
|
79
79
|
PROJECT_SYNCHRONOUS = "SYNCHRONOUS"
|
80
80
|
|
@@ -316,16 +316,13 @@ def construct_launch_spec(
|
|
316
316
|
|
317
317
|
|
318
318
|
def validate_launch_spec_source(launch_spec: Dict[str, Any]) -> None:
|
319
|
-
uri = launch_spec.get("uri")
|
320
319
|
job = launch_spec.get("job")
|
321
320
|
docker_image = launch_spec.get("docker", {}).get("docker_image")
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
elif sum(map(bool, [uri, job, docker_image])) > 1:
|
328
|
-
raise LaunchError("Must specify exactly one of uri, job or image")
|
321
|
+
if bool(job) == bool(docker_image):
|
322
|
+
raise LaunchError(
|
323
|
+
"Exactly one of job or docker_image must be specified in the launch "
|
324
|
+
"spec."
|
325
|
+
)
|
329
326
|
|
330
327
|
|
331
328
|
def parse_wandb_uri(uri: str) -> Tuple[str, str, str]:
|
@@ -336,77 +333,6 @@ def parse_wandb_uri(uri: str) -> Tuple[str, str, str]:
|
|
336
333
|
return (ref.entity, ref.project, ref.run_id)
|
337
334
|
|
338
335
|
|
339
|
-
def is_bare_wandb_uri(uri: str) -> bool:
|
340
|
-
"""Check that a wandb uri is valid.
|
341
|
-
|
342
|
-
URI must be in the format
|
343
|
-
`/<entity>/<project>/runs/<run_name>[other stuff]`
|
344
|
-
or
|
345
|
-
`/<entity>/<project>/artifacts/job/<job_name>[other stuff]`.
|
346
|
-
"""
|
347
|
-
_logger.info(f"Checking if uri {uri} is bare...")
|
348
|
-
return uri.startswith("/") and WandbReference.is_uri_job_or_run(uri)
|
349
|
-
|
350
|
-
|
351
|
-
def fetch_wandb_project_run_info(
|
352
|
-
entity: str, project: str, run_name: str, api: Api
|
353
|
-
) -> Any:
|
354
|
-
_logger.info("Fetching run info...")
|
355
|
-
try:
|
356
|
-
result = api.get_run_info(entity, project, run_name)
|
357
|
-
except CommError:
|
358
|
-
result = None
|
359
|
-
if result is None:
|
360
|
-
raise LaunchError(
|
361
|
-
f"Run info is invalid or doesn't exist for {api.settings('base_url')}/{entity}/{project}/runs/{run_name}"
|
362
|
-
)
|
363
|
-
if result.get("codePath") is None:
|
364
|
-
# TODO: we don't currently expose codePath in the runInfo endpoint, this downloads
|
365
|
-
# it from wandb-metadata.json if we can.
|
366
|
-
metadata = api.download_url(
|
367
|
-
project, "wandb-metadata.json", run=run_name, entity=entity
|
368
|
-
)
|
369
|
-
if metadata is not None:
|
370
|
-
_, response = api.download_file(metadata["url"])
|
371
|
-
data = response.json()
|
372
|
-
result["codePath"] = data.get("codePath")
|
373
|
-
result["cudaVersion"] = data.get("cuda", None)
|
374
|
-
|
375
|
-
return result
|
376
|
-
|
377
|
-
|
378
|
-
def download_entry_point(
|
379
|
-
entity: str, project: str, run_name: str, api: Api, entry_point: str, dir: str
|
380
|
-
) -> bool:
|
381
|
-
metadata = api.download_url(
|
382
|
-
project, f"code/{entry_point}", run=run_name, entity=entity
|
383
|
-
)
|
384
|
-
if metadata is not None:
|
385
|
-
_, response = api.download_file(metadata["url"])
|
386
|
-
with util.fsync_open(os.path.join(dir, entry_point), "wb") as file:
|
387
|
-
for data in response.iter_content(chunk_size=1024):
|
388
|
-
file.write(data)
|
389
|
-
return True
|
390
|
-
return False
|
391
|
-
|
392
|
-
|
393
|
-
def download_wandb_python_deps(
|
394
|
-
entity: str, project: str, run_name: str, api: Api, dir: str
|
395
|
-
) -> Optional[str]:
|
396
|
-
reqs = api.download_url(project, "requirements.txt", run=run_name, entity=entity)
|
397
|
-
if reqs is not None:
|
398
|
-
_logger.info("Downloading python dependencies")
|
399
|
-
_, response = api.download_file(reqs["url"])
|
400
|
-
|
401
|
-
with util.fsync_open(
|
402
|
-
os.path.join(dir, "requirements.frozen.txt"), "wb"
|
403
|
-
) as file:
|
404
|
-
for data in response.iter_content(chunk_size=1024):
|
405
|
-
file.write(data)
|
406
|
-
return "requirements.frozen.txt"
|
407
|
-
return None
|
408
|
-
|
409
|
-
|
410
336
|
def get_local_python_deps(
|
411
337
|
dir: str, filename: str = "requirements.local.txt"
|
412
338
|
) -> Optional[str]:
|
@@ -498,19 +424,6 @@ def validate_wandb_python_deps(
|
|
498
424
|
_logger.warning("Unable to validate local python dependencies")
|
499
425
|
|
500
426
|
|
501
|
-
def fetch_project_diff(
|
502
|
-
entity: str, project: str, run_name: str, api: Api
|
503
|
-
) -> Optional[str]:
|
504
|
-
"""Fetches project diff from wandb servers."""
|
505
|
-
_logger.info("Searching for diff.patch")
|
506
|
-
patch = None
|
507
|
-
try:
|
508
|
-
(_, _, patch, _) = api.run_config(project, run_name, entity)
|
509
|
-
except CommError:
|
510
|
-
pass
|
511
|
-
return patch
|
512
|
-
|
513
|
-
|
514
427
|
def apply_patch(patch_string: str, dst_dir: str) -> None:
|
515
428
|
"""Applies a patch file to a directory."""
|
516
429
|
_logger.info("Applying diff.patch")
|
@@ -531,17 +444,6 @@ def apply_patch(patch_string: str, dst_dir: str) -> None:
|
|
531
444
|
raise wandb.Error("Failed to apply diff.patch associated with run.")
|
532
445
|
|
533
446
|
|
534
|
-
def _make_refspec_from_version(version: Optional[str]) -> List[str]:
|
535
|
-
"""Create a refspec that checks for the existence of origin/main and the version."""
|
536
|
-
if version:
|
537
|
-
return [f"+{version}"]
|
538
|
-
|
539
|
-
return [
|
540
|
-
"+refs/heads/main*:refs/remotes/origin/main*",
|
541
|
-
"+refs/heads/master*:refs/remotes/origin/master*",
|
542
|
-
]
|
543
|
-
|
544
|
-
|
545
447
|
def _fetch_git_repo(dst_dir: str, uri: str, version: Optional[str]) -> Optional[str]:
|
546
448
|
"""Clones the git repo at ``uri`` into ``dst_dir``.
|
547
449
|
|
@@ -561,13 +463,6 @@ def _fetch_git_repo(dst_dir: str, uri: str, version: Optional[str]) -> Optional[
|
|
561
463
|
return version
|
562
464
|
|
563
465
|
|
564
|
-
def merge_parameters(
|
565
|
-
higher_priority_params: Dict[str, Any], lower_priority_params: Dict[str, Any]
|
566
|
-
) -> Dict[str, Any]:
|
567
|
-
"""Merge the contents of two dicts, keeping values from higher_priority_params if there are conflicts."""
|
568
|
-
return {**lower_priority_params, **higher_priority_params}
|
569
|
-
|
570
|
-
|
571
466
|
def convert_jupyter_notebook_to_script(fname: str, project_dir: str) -> str:
|
572
467
|
nbconvert = wandb.util.get_module(
|
573
468
|
"nbconvert", "nbformat and nbconvert are required to use launch with notebooks"
|
@@ -597,25 +492,6 @@ def convert_jupyter_notebook_to_script(fname: str, project_dir: str) -> str:
|
|
597
492
|
return new_name
|
598
493
|
|
599
494
|
|
600
|
-
def check_and_download_code_artifacts(
|
601
|
-
entity: str, project: str, run_name: str, internal_api: Api, project_dir: str
|
602
|
-
) -> Optional["Artifact"]:
|
603
|
-
_logger.info("Checking for code artifacts")
|
604
|
-
public_api = wandb.PublicApi(
|
605
|
-
overrides={"base_url": internal_api.settings("base_url")}
|
606
|
-
)
|
607
|
-
|
608
|
-
run = public_api.run(f"{entity}/{project}/{run_name}")
|
609
|
-
run_artifacts = run.logged_artifacts()
|
610
|
-
|
611
|
-
for artifact in run_artifacts:
|
612
|
-
if hasattr(artifact, "type") and artifact.type == "code":
|
613
|
-
artifact.download(project_dir)
|
614
|
-
return artifact # type: ignore
|
615
|
-
|
616
|
-
return None
|
617
|
-
|
618
|
-
|
619
495
|
def to_camel_case(maybe_snake_str: str) -> str:
|
620
496
|
if "_" not in maybe_snake_str:
|
621
497
|
return maybe_snake_str
|
@@ -623,11 +499,6 @@ def to_camel_case(maybe_snake_str: str) -> str:
|
|
623
499
|
return "".join(x.title() if x else "_" for x in components)
|
624
500
|
|
625
501
|
|
626
|
-
def run_shell(args: List[str]) -> Tuple[str, str]:
|
627
|
-
out = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
628
|
-
return out.stdout.decode("utf-8").strip(), out.stderr.decode("utf-8").strip()
|
629
|
-
|
630
|
-
|
631
502
|
def validate_build_and_registry_configs(
|
632
503
|
build_config: Dict[str, Any], registry_config: Dict[str, Any]
|
633
504
|
) -> None:
|
@@ -864,3 +735,10 @@ def get_entrypoint_file(entrypoint: List[str]) -> Optional[str]:
|
|
864
735
|
if len(entrypoint) < 2:
|
865
736
|
return None
|
866
737
|
return entrypoint[1]
|
738
|
+
|
739
|
+
|
740
|
+
def get_current_python_version() -> Tuple[str, str]:
|
741
|
+
full_version = sys.version.split()[0].split(".")
|
742
|
+
major = full_version[0]
|
743
|
+
version = ".".join(full_version[:2]) if len(full_version) >= 2 else major + ".0"
|
744
|
+
return version, major
|
@@ -13,7 +13,6 @@ else:
|
|
13
13
|
_Setting = Literal[
|
14
14
|
"_args",
|
15
15
|
"_aws_lambda",
|
16
|
-
"_async_upload_concurrency_limit",
|
17
16
|
"_cli_only_mode",
|
18
17
|
"_code_path_local",
|
19
18
|
"_colab",
|
@@ -25,7 +24,6 @@ _Setting = Literal[
|
|
25
24
|
"_disable_update_check",
|
26
25
|
"_disable_viewer",
|
27
26
|
"_disable_machine_info",
|
28
|
-
"_except_exit",
|
29
27
|
"_executable",
|
30
28
|
"_extra_http_headers",
|
31
29
|
"_file_stream_retry_max",
|
@@ -92,6 +90,7 @@ _Setting = Literal[
|
|
92
90
|
"colab_url",
|
93
91
|
"config_paths",
|
94
92
|
"console",
|
93
|
+
"console_multipart",
|
95
94
|
"deployment",
|
96
95
|
"disable_code",
|
97
96
|
"disable_git",
|
@@ -104,6 +103,7 @@ _Setting = Literal[
|
|
104
103
|
"files_dir",
|
105
104
|
"force",
|
106
105
|
"fork_from",
|
106
|
+
"resume_from",
|
107
107
|
"git_commit",
|
108
108
|
"git_remote",
|
109
109
|
"git_remote_url",
|
@@ -126,7 +126,6 @@ _Setting = Literal[
|
|
126
126
|
"login_timeout",
|
127
127
|
"mode",
|
128
128
|
"notebook_name",
|
129
|
-
"problem",
|
130
129
|
"program",
|
131
130
|
"program_abspath",
|
132
131
|
"program_relpath",
|
@@ -179,7 +178,6 @@ _Setting = Literal[
|
|
179
178
|
]
|
180
179
|
|
181
180
|
SETTINGS_TOPOLOGICALLY_SORTED: Final[Tuple[_Setting, ...]] = (
|
182
|
-
"_async_upload_concurrency_limit",
|
183
181
|
"_service_wait",
|
184
182
|
"_stats_sample_rate_seconds",
|
185
183
|
"_stats_samples_to_average",
|
@@ -189,7 +187,6 @@ SETTINGS_TOPOLOGICALLY_SORTED: Final[Tuple[_Setting, ...]] = (
|
|
189
187
|
"console",
|
190
188
|
"job_source",
|
191
189
|
"mode",
|
192
|
-
"problem",
|
193
190
|
"project",
|
194
191
|
"run_id",
|
195
192
|
"start_method",
|
wandb/sdk/lib/apikey.py
CHANGED
@@ -202,7 +202,7 @@ def write_netrc(host: str, entity: str, key: str) -> Optional[bool]:
|
|
202
202
|
elif skip:
|
203
203
|
skip -= 1
|
204
204
|
else:
|
205
|
-
f.write("
|
205
|
+
f.write("{}\n".format(line))
|
206
206
|
f.write(
|
207
207
|
textwrap.dedent(
|
208
208
|
"""\
|
@@ -236,7 +236,9 @@ def write_key(
|
|
236
236
|
_, suffix = key.split("-", 1) if "-" in key else ("", key)
|
237
237
|
|
238
238
|
if len(suffix) != 40:
|
239
|
-
raise ValueError(
|
239
|
+
raise ValueError(
|
240
|
+
"API key must be 40 characters long, yours was {}".format(len(key))
|
241
|
+
)
|
240
242
|
|
241
243
|
if anonymous:
|
242
244
|
api.set_setting("anonymous", "true", globally=True, persist=True)
|
wandb/sdk/lib/config_util.py
CHANGED
@@ -66,13 +66,13 @@ def dict_from_config_file(
|
|
66
66
|
) -> Optional[Dict[str, Any]]:
|
67
67
|
if not os.path.exists(filename):
|
68
68
|
if must_exist:
|
69
|
-
raise ConfigError("config file
|
70
|
-
logger.debug("no default config file found in
|
69
|
+
raise ConfigError("config file {} doesn't exist".format(filename))
|
70
|
+
logger.debug("no default config file found in {}".format(filename))
|
71
71
|
return None
|
72
72
|
try:
|
73
73
|
conf_file = open(filename)
|
74
74
|
except OSError:
|
75
|
-
raise ConfigError("Couldn't read config file:
|
75
|
+
raise ConfigError("Couldn't read config file: {}".format(filename))
|
76
76
|
try:
|
77
77
|
loaded = load_yaml(conf_file)
|
78
78
|
except yaml.parser.ParserError:
|
wandb/sdk/lib/import_hooks.py
CHANGED
@@ -143,7 +143,7 @@ class _ImportHookChainedLoader:
|
|
143
143
|
# None, so handle None as well. The module may not support attribute
|
144
144
|
# assignment, in which case we simply skip it. Note that we also deal
|
145
145
|
# with __loader__ not existing at all. This is to future proof things
|
146
|
-
# due to proposal to remove the
|
146
|
+
# due to proposal to remove the attribute as described in the GitHub
|
147
147
|
# issue at https://github.com/python/cpython/issues/77458. Also prior
|
148
148
|
# to Python 3.3, the __loader__ attribute was only set if a custom
|
149
149
|
# module loader was used. It isn't clear whether the attribute still
|
wandb/sdk/lib/proto_util.py
CHANGED
@@ -12,7 +12,28 @@ if TYPE_CHECKING: # pragma: no cover
|
|
12
12
|
|
13
13
|
|
14
14
|
def dict_from_proto_list(obj_list: "RepeatedCompositeFieldContainer") -> Dict[str, Any]:
|
15
|
-
|
15
|
+
result: Dict[str, Any] = {}
|
16
|
+
|
17
|
+
for item in obj_list:
|
18
|
+
# Start from the root of the result dict
|
19
|
+
current_level = result
|
20
|
+
|
21
|
+
if len(item.nested_key) > 0:
|
22
|
+
keys = list(item.nested_key)
|
23
|
+
else:
|
24
|
+
keys = [item.key]
|
25
|
+
|
26
|
+
for key in keys[:-1]:
|
27
|
+
if key not in current_level:
|
28
|
+
current_level[key] = {}
|
29
|
+
# Move the reference deeper into the nested dictionary
|
30
|
+
current_level = current_level[key]
|
31
|
+
|
32
|
+
# Set the value at the final key location, parsing JSON from the value_json field
|
33
|
+
final_key = keys[-1]
|
34
|
+
current_level[final_key] = json.loads(item.value_json)
|
35
|
+
|
36
|
+
return result
|
16
37
|
|
17
38
|
|
18
39
|
def _result_from_record(record: "pb.Record") -> "pb.Result":
|
wandb/sdk/lib/redirect.py
CHANGED
@@ -224,7 +224,7 @@ class TerminalEmulator:
|
|
224
224
|
def carriage_return(self):
|
225
225
|
self.cursor.x = 0
|
226
226
|
|
227
|
-
def
|
227
|
+
def cursor_position(self, line, column):
|
228
228
|
self.cursor.x = min(column, 1) - 1
|
229
229
|
self.cursor.y = min(line, 1) - 1
|
230
230
|
|
@@ -393,25 +393,30 @@ class TerminalEmulator:
|
|
393
393
|
p = (int(p[0]), 1)
|
394
394
|
else:
|
395
395
|
p = (1, 1)
|
396
|
-
self.
|
396
|
+
self.cursor_position(*p)
|
397
397
|
except Exception:
|
398
398
|
pass
|
399
399
|
|
400
400
|
def _get_line(self, n):
|
401
401
|
line = self.buffer[n]
|
402
402
|
line_len = self._get_line_len(n)
|
403
|
-
# We have to loop through each character in the line and check if foreground,
|
404
|
-
# other attributes (italics, bold, underline, etc) of the ith
|
405
|
-
# (i-1)th character. If different, the
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
|
410
|
-
#
|
411
|
-
#
|
412
|
-
|
413
|
-
#
|
414
|
-
#
|
403
|
+
# We have to loop through each character in the line and check if foreground,
|
404
|
+
# background and other attributes (italics, bold, underline, etc) of the ith
|
405
|
+
# character are different from those of the (i-1)th character. If different, the
|
406
|
+
# appropriate ascii character for switching the color/attribute should be
|
407
|
+
# appended to the output string before appending the actual character. This loop
|
408
|
+
# and subsequent checks can be expensive, especially because 99% of terminal
|
409
|
+
# output use default colors and formatting. Even in outputs that do contain
|
410
|
+
# colors and styles, its unlikely that they will change on a per character
|
411
|
+
# basis.
|
412
|
+
|
413
|
+
# So instead we create a character list without any ascii codes (`out`), and a
|
414
|
+
# list of all the foregrounds in the line (`fgs`) on which we call np.diff() and
|
415
|
+
# np.where() to find the indices where the foreground change, and insert the
|
416
|
+
# ascii characters in the output list (`out`) on those indices. All of this is
|
417
|
+
# the done only if there are more than 1 foreground color in the line in the
|
418
|
+
# first place (`if len(set(fgs)) > 1 else None`). Same logic is repeated for
|
419
|
+
# background colors and other attributes.
|
415
420
|
|
416
421
|
out = [line[i].data for i in range(line_len)]
|
417
422
|
|
@@ -499,7 +504,7 @@ class RedirectBase:
|
|
499
504
|
|
500
505
|
@property
|
501
506
|
def src_stream(self):
|
502
|
-
return getattr(sys, "__
|
507
|
+
return getattr(sys, "__{}__".format(self.src))
|
503
508
|
|
504
509
|
@property
|
505
510
|
def src_fd(self):
|
wandb/sdk/lib/tracelog.py
CHANGED
@@ -6,7 +6,7 @@ Functions:
|
|
6
6
|
log_message_send - message sent to socket
|
7
7
|
log_message_recv - message received from socket
|
8
8
|
log_message_process - message processed by thread
|
9
|
-
log_message_link - message linked to another
|
9
|
+
log_message_link - message linked to another message
|
10
10
|
log_message_assert - message encountered problem
|
11
11
|
|
12
12
|
"""
|
wandb/sdk/service/service.py
CHANGED
@@ -110,7 +110,8 @@ class _Service:
|
|
110
110
|
f"The wandb service process exited with {proc.returncode}. "
|
111
111
|
"Ensure that `sys.executable` is a valid python interpreter. "
|
112
112
|
"You can override it with the `_executable` setting "
|
113
|
-
"or with the `WANDB__EXECUTABLE` environment variable."
|
113
|
+
"or with the `WANDB__EXECUTABLE` environment variable."
|
114
|
+
f"\n{context}",
|
114
115
|
context=context,
|
115
116
|
)
|
116
117
|
if not os.path.isfile(fname):
|
wandb/sdk/service/streams.py
CHANGED
@@ -319,8 +319,8 @@ class StreamMux:
|
|
319
319
|
# These could be done in parallel in the future
|
320
320
|
for _sid, stream in started_streams.items():
|
321
321
|
# dispatch all our final requests
|
322
|
-
poll_exit_handle = stream.interface.deliver_poll_exit()
|
323
322
|
server_info_handle = stream.interface.deliver_request_server_info()
|
323
|
+
poll_exit_handle = stream.interface.deliver_poll_exit()
|
324
324
|
final_summary_handle = stream.interface.deliver_get_summary()
|
325
325
|
sampled_history_handle = stream.interface.deliver_request_sampled_history()
|
326
326
|
internal_messages_handle = stream.interface.deliver_internal_messages()
|
@@ -330,14 +330,14 @@ class StreamMux:
|
|
330
330
|
internal_messages_response = result.response.internal_messages_response
|
331
331
|
|
332
332
|
# wait for them, it's ok to do this serially but this can be improved
|
333
|
-
result = poll_exit_handle.wait(timeout=-1)
|
334
|
-
assert result
|
335
|
-
poll_exit_response = result.response.poll_exit_response
|
336
|
-
|
337
333
|
result = server_info_handle.wait(timeout=-1)
|
338
334
|
assert result
|
339
335
|
server_info_response = result.response.server_info_response
|
340
336
|
|
337
|
+
result = poll_exit_handle.wait(timeout=-1)
|
338
|
+
assert result
|
339
|
+
poll_exit_response = result.response.poll_exit_response
|
340
|
+
|
341
341
|
result = sampled_history_handle.wait(timeout=-1)
|
342
342
|
assert result
|
343
343
|
sampled_history = result.response.sampled_history_response
|
wandb/sdk/wandb_init.py
CHANGED
@@ -15,7 +15,6 @@ import os
|
|
15
15
|
import platform
|
16
16
|
import sys
|
17
17
|
import tempfile
|
18
|
-
import traceback
|
19
18
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union
|
20
19
|
|
21
20
|
import wandb
|
@@ -555,7 +554,7 @@ class _WandbInit:
|
|
555
554
|
percent_done = handle.percent_done
|
556
555
|
self.printer.progress_update(line, percent_done=percent_done)
|
557
556
|
|
558
|
-
def init(self) -> Union[Run, RunDisabled
|
557
|
+
def init(self) -> Union[Run, RunDisabled]: # noqa: C901
|
559
558
|
if logger is None:
|
560
559
|
raise RuntimeError("Logger not initialized")
|
561
560
|
logger.info("calling init triggers")
|
@@ -654,9 +653,6 @@ class _WandbInit:
|
|
654
653
|
if self.settings.launch:
|
655
654
|
tel.feature.launch = True
|
656
655
|
|
657
|
-
if self.settings._async_upload_concurrency_limit:
|
658
|
-
tel.feature.async_uploads = True
|
659
|
-
|
660
656
|
for module_name in telemetry.list_telemetry_imports(only_imported=True):
|
661
657
|
setattr(tel.imports_init, module_name, True)
|
662
658
|
|
@@ -843,13 +839,6 @@ class _WandbInit:
|
|
843
839
|
return run
|
844
840
|
|
845
841
|
|
846
|
-
def getcaller() -> None:
|
847
|
-
if not logger:
|
848
|
-
return None
|
849
|
-
src, line, func, stack = logger.findCaller(stack_info=True)
|
850
|
-
print("Problem at:", src, line, func)
|
851
|
-
|
852
|
-
|
853
842
|
def _attach(
|
854
843
|
attach_id: Optional[str] = None,
|
855
844
|
run_id: Optional[str] = None,
|
@@ -957,8 +946,9 @@ def init(
|
|
957
946
|
save_code: Optional[bool] = None,
|
958
947
|
id: Optional[str] = None,
|
959
948
|
fork_from: Optional[str] = None,
|
949
|
+
resume_from: Optional[str] = None,
|
960
950
|
settings: Union[Settings, Dict[str, Any], None] = None,
|
961
|
-
) -> Union[Run, RunDisabled
|
951
|
+
) -> Union[Run, RunDisabled]:
|
962
952
|
r"""Start a new run to track and log to W&B.
|
963
953
|
|
964
954
|
In an ML training pipeline, you could add `wandb.init()`
|
@@ -1006,7 +996,7 @@ def init(
|
|
1006
996
|
there, so make sure to create your account or team in the UI before
|
1007
997
|
starting to log runs.
|
1008
998
|
If you don't specify an entity, the run will be sent to your default
|
1009
|
-
entity
|
999
|
+
entity. Change your default entity
|
1010
1000
|
in [your settings](https://wandb.ai/settings) under "default location
|
1011
1001
|
to create new projects".
|
1012
1002
|
config: (dict, argparse, absl.flags, str, optional)
|
@@ -1164,57 +1154,33 @@ def init(
|
|
1164
1154
|
wandb._assert_is_user_process()
|
1165
1155
|
|
1166
1156
|
kwargs = dict(locals())
|
1167
|
-
error_seen = None
|
1168
|
-
except_exit = None
|
1169
|
-
run: Optional[Union[Run, RunDisabled]] = None
|
1170
1157
|
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1158
|
+
num_resume_options_set = (
|
1159
|
+
(fork_from is not None) # wrap
|
1160
|
+
+ (resume is not None)
|
1161
|
+
+ (resume_from is not None)
|
1162
|
+
)
|
1163
|
+
if num_resume_options_set > 1:
|
1164
|
+
raise ValueError(
|
1165
|
+
"You cannot specify more than one of `fork_from`, `resume`, or `resume_from`"
|
1166
|
+
)
|
1174
1167
|
|
1175
1168
|
try:
|
1176
1169
|
wi = _WandbInit()
|
1177
1170
|
wi.setup(kwargs)
|
1178
|
-
|
1179
|
-
|
1180
|
-
try:
|
1181
|
-
run = wi.init()
|
1182
|
-
except_exit = wi.settings._except_exit
|
1183
|
-
except (KeyboardInterrupt, Exception) as e:
|
1184
|
-
if not isinstance(e, KeyboardInterrupt):
|
1185
|
-
wandb._sentry.exception(e)
|
1186
|
-
if not (
|
1187
|
-
wandb.wandb_agent._is_running() and isinstance(e, KeyboardInterrupt)
|
1188
|
-
):
|
1189
|
-
getcaller()
|
1190
|
-
assert logger
|
1191
|
-
if wi.settings.problem == "fatal":
|
1192
|
-
raise
|
1193
|
-
if wi.settings.problem == "warn":
|
1194
|
-
pass
|
1195
|
-
# TODO(jhr): figure out how to make this RunDummy
|
1196
|
-
run = None
|
1197
|
-
except Error as e:
|
1198
|
-
if logger is not None:
|
1199
|
-
logger.exception(str(e))
|
1200
|
-
raise e
|
1171
|
+
return wi.init()
|
1172
|
+
|
1201
1173
|
except KeyboardInterrupt as e:
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1174
|
+
if logger is not None:
|
1175
|
+
logger.warning("interrupted", exc_info=e)
|
1176
|
+
|
1177
|
+
raise
|
1178
|
+
|
1205
1179
|
except Exception as e:
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
logger.error("error", exc_info=e)
|
1180
|
+
if logger is not None:
|
1181
|
+
logger.exception("error in wandb.init()", exc_info=e)
|
1182
|
+
|
1210
1183
|
# Need to build delay into this sentry capture because our exit hooks
|
1211
1184
|
# mess with sentry's ability to send out errors before the program ends.
|
1212
|
-
wandb._sentry.
|
1213
|
-
|
1214
|
-
finally:
|
1215
|
-
if error_seen:
|
1216
|
-
if except_exit:
|
1217
|
-
wandb.termerror("Abnormal program exit")
|
1218
|
-
os._exit(1)
|
1219
|
-
raise Error("An unexpected error occurred") from error_seen
|
1220
|
-
return run
|
1185
|
+
wandb._sentry.reraise(e)
|
1186
|
+
raise AssertionError() # unreachable
|