wandb 0.19.0__py3-none-win32.whl → 0.19.1__py3-none-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wandb/__init__.py +1 -7
- wandb/__init__.pyi +211 -209
- wandb/apis/attrs.py +15 -4
- wandb/apis/public/api.py +8 -4
- wandb/apis/public/files.py +65 -12
- wandb/apis/public/runs.py +52 -7
- wandb/apis/public/sweeps.py +1 -1
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +2 -1
- wandb/env.py +1 -1
- wandb/errors/term.py +60 -1
- wandb/integration/keras/callbacks/tables_builder.py +3 -1
- wandb/integration/kfp/kfp_patch.py +25 -15
- wandb/integration/lightning/fabric/logger.py +3 -1
- wandb/integration/tensorboard/monkeypatch.py +3 -2
- wandb/jupyter.py +4 -5
- wandb/plot/bar.py +5 -6
- wandb/plot/histogram.py +1 -1
- wandb/plot/line_series.py +3 -3
- wandb/plot/pr_curve.py +7 -3
- wandb/plot/scatter.py +2 -1
- wandb/proto/v3/wandb_settings_pb2.py +25 -15
- wandb/proto/v4/wandb_settings_pb2.py +17 -15
- wandb/proto/v5/wandb_settings_pb2.py +17 -15
- wandb/sdk/artifacts/_validators.py +1 -3
- wandb/sdk/artifacts/artifact_manifest_entry.py +1 -1
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +12 -2
- wandb/sdk/data_types/helper_types/image_mask.py +8 -2
- wandb/sdk/data_types/histogram.py +3 -3
- wandb/sdk/data_types/image.py +3 -1
- wandb/sdk/interface/interface.py +34 -5
- wandb/sdk/interface/interface_sock.py +2 -2
- wandb/sdk/internal/file_stream.py +4 -1
- wandb/sdk/internal/sender.py +4 -1
- wandb/sdk/internal/settings_static.py +17 -4
- wandb/sdk/launch/utils.py +1 -0
- wandb/sdk/lib/ipython.py +5 -27
- wandb/sdk/lib/printer.py +33 -20
- wandb/sdk/lib/progress.py +7 -1
- wandb/sdk/lib/sparkline.py +1 -2
- wandb/sdk/wandb_config.py +2 -2
- wandb/sdk/wandb_init.py +236 -243
- wandb/sdk/wandb_run.py +172 -231
- wandb/sdk/wandb_settings.py +104 -15
- {wandb-0.19.0.dist-info → wandb-0.19.1.dist-info}/METADATA +1 -1
- {wandb-0.19.0.dist-info → wandb-0.19.1.dist-info}/RECORD +50 -50
- {wandb-0.19.0.dist-info → wandb-0.19.1.dist-info}/WHEEL +0 -0
- {wandb-0.19.0.dist-info → wandb-0.19.1.dist-info}/entry_points.txt +0 -0
- {wandb-0.19.0.dist-info → wandb-0.19.1.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_run.py
CHANGED
@@ -19,7 +19,6 @@ from collections.abc import Mapping
|
|
19
19
|
from dataclasses import dataclass, field
|
20
20
|
from datetime import datetime, timedelta, timezone
|
21
21
|
from enum import IntEnum
|
22
|
-
from functools import reduce
|
23
22
|
from types import TracebackType
|
24
23
|
from typing import TYPE_CHECKING, Any, Callable, Literal, NamedTuple, Sequence, TextIO
|
25
24
|
|
@@ -83,9 +82,7 @@ from .lib import (
|
|
83
82
|
telemetry,
|
84
83
|
)
|
85
84
|
from .lib.exit_hooks import ExitHooks
|
86
|
-
from .lib.gitlib import GitRepo
|
87
85
|
from .lib.mailbox import MailboxError, MailboxHandle, MailboxProbe, MailboxProgress
|
88
|
-
from .lib.proto_util import message_to_dict
|
89
86
|
from .wandb_alerts import AlertLevel
|
90
87
|
from .wandb_settings import Settings
|
91
88
|
from .wandb_setup import _WandbSetup
|
@@ -520,17 +517,7 @@ class Run:
|
|
520
517
|
_telemetry_obj_flushed: bytes
|
521
518
|
|
522
519
|
_teardown_hooks: list[TeardownHook]
|
523
|
-
_tags: tuple[Any, ...] | None
|
524
520
|
|
525
|
-
_entity: str | None
|
526
|
-
_project: str | None
|
527
|
-
_group: str | None
|
528
|
-
_job_type: str | None
|
529
|
-
_name: str | None
|
530
|
-
_notes: str | None
|
531
|
-
_sweep_id: str | None
|
532
|
-
|
533
|
-
_run_obj: RunRecord | None
|
534
521
|
_backend: wandb.sdk.backend.backend.Backend | None
|
535
522
|
_internal_run_interface: wandb.sdk.interface.interface_queue.InterfaceQueue | None
|
536
523
|
_wl: _WandbSetup | None
|
@@ -567,6 +554,8 @@ class Run:
|
|
567
554
|
_is_finished: bool
|
568
555
|
_settings: Settings
|
569
556
|
|
557
|
+
_forked: bool
|
558
|
+
|
570
559
|
_launch_artifacts: dict[str, Any] | None
|
571
560
|
_printer: printer.Printer
|
572
561
|
|
@@ -605,16 +594,15 @@ class Run:
|
|
605
594
|
self._config._set_callback(self._config_callback)
|
606
595
|
self._config._set_artifact_callback(self._config_artifact_callback)
|
607
596
|
self._config._set_settings(self._settings)
|
608
|
-
|
609
|
-
self._internal_run_interface = None
|
597
|
+
|
610
598
|
# todo: perhaps this should be a property that is a noop on a finished run
|
611
599
|
self.summary = wandb_summary.Summary(
|
612
600
|
self._summary_get_current_summary_callback,
|
613
601
|
)
|
614
602
|
self.summary._set_update_callback(self._summary_update_callback)
|
615
|
-
self._step = 0
|
616
|
-
self._torch_history: wandb_torch.TorchHistory | None = None # type: ignore
|
617
603
|
|
604
|
+
self._step = 0
|
605
|
+
self._starting_step = 0
|
618
606
|
# todo: eventually would be nice to make this configurable using self._settings._start_time
|
619
607
|
# need to test (jhr): if you set start time to 2 days ago and run a test for 15 minutes,
|
620
608
|
# does the total time get calculated right (not as 2 days and 15 minutes)?
|
@@ -623,36 +611,27 @@ class Run:
|
|
623
611
|
_datatypes_set_callback(self._datatypes_callback)
|
624
612
|
|
625
613
|
self._printer = printer.new_printer()
|
626
|
-
self._wl = None
|
627
614
|
|
628
|
-
self.
|
629
|
-
|
630
|
-
self.
|
631
|
-
self.
|
632
|
-
self.
|
633
|
-
self._starting_step = 0
|
634
|
-
self._name = None
|
635
|
-
self._notes = None
|
636
|
-
self._tags = None
|
637
|
-
self._remote_url = None
|
638
|
-
self._commit = None
|
639
|
-
self._sweep_id = None
|
615
|
+
self._torch_history: wandb_torch.TorchHistory | None = None # type: ignore
|
616
|
+
|
617
|
+
self._backend = None
|
618
|
+
self._internal_run_interface = None
|
619
|
+
self._wl = None
|
640
620
|
|
641
621
|
self._hooks = None
|
642
622
|
self._teardown_hooks = []
|
623
|
+
|
624
|
+
self._output_writer = None
|
643
625
|
self._out_redir = None
|
644
626
|
self._err_redir = None
|
645
627
|
self._stdout_slave_fd = None
|
646
628
|
self._stderr_slave_fd = None
|
629
|
+
|
647
630
|
self._exit_code = None
|
648
631
|
self._exit_result = None
|
649
632
|
|
650
|
-
self._output_writer = None
|
651
633
|
self._used_artifact_slots: dict[str, str] = {}
|
652
634
|
|
653
|
-
# Returned from backend request_run(), set from wandb_init?
|
654
|
-
self._run_obj = None
|
655
|
-
|
656
635
|
# Created when the run "starts".
|
657
636
|
self._run_status_checker = None
|
658
637
|
|
@@ -670,9 +649,6 @@ class Run:
|
|
670
649
|
|
671
650
|
self._atexit_cleanup_called = False
|
672
651
|
|
673
|
-
# Pull info from settings
|
674
|
-
self._init_from_settings(self._settings)
|
675
|
-
|
676
652
|
# Initial scope setup for sentry.
|
677
653
|
# This might get updated when the actual run comes back.
|
678
654
|
wandb._sentry.configure_scope(
|
@@ -737,7 +713,7 @@ class Run:
|
|
737
713
|
self._is_finished = False
|
738
714
|
|
739
715
|
self._attach_pid = os.getpid()
|
740
|
-
|
716
|
+
self._forked = False
|
741
717
|
# for now, use runid as attach id, this could/should be versioned in the future
|
742
718
|
if not self._settings.x_disable_service:
|
743
719
|
self._attach_id = self._settings.run_id
|
@@ -813,71 +789,6 @@ class Run:
|
|
813
789
|
raise Exception(f"Attribute {attr} is not supported on Run object.")
|
814
790
|
super().__setattr__(attr, value)
|
815
791
|
|
816
|
-
def _update_settings(self, settings: Settings) -> None:
|
817
|
-
self._settings = settings
|
818
|
-
self._init_from_settings(settings)
|
819
|
-
|
820
|
-
def _init_from_settings(self, settings: Settings) -> None:
|
821
|
-
if settings.entity is not None:
|
822
|
-
self._entity = settings.entity
|
823
|
-
if settings.project is not None:
|
824
|
-
self._project = settings.project
|
825
|
-
if settings.run_group is not None:
|
826
|
-
self._group = settings.run_group
|
827
|
-
if settings.run_job_type is not None:
|
828
|
-
self._job_type = settings.run_job_type
|
829
|
-
if settings.run_name is not None:
|
830
|
-
self._name = settings.run_name
|
831
|
-
if settings.run_notes is not None:
|
832
|
-
self._notes = settings.run_notes
|
833
|
-
if settings.run_tags is not None:
|
834
|
-
self._tags = settings.run_tags
|
835
|
-
if settings.sweep_id is not None:
|
836
|
-
self._sweep_id = settings.sweep_id
|
837
|
-
|
838
|
-
def _make_proto_run(self, run: RunRecord) -> None:
|
839
|
-
"""Populate protocol buffer RunData for interface/interface."""
|
840
|
-
if self._entity is not None:
|
841
|
-
run.entity = self._entity
|
842
|
-
if self._project is not None:
|
843
|
-
run.project = self._project
|
844
|
-
if self._group is not None:
|
845
|
-
run.run_group = self._group
|
846
|
-
if self._job_type is not None:
|
847
|
-
run.job_type = self._job_type
|
848
|
-
if self._run_id is not None:
|
849
|
-
run.run_id = self._run_id
|
850
|
-
if self._name is not None:
|
851
|
-
run.display_name = self._name
|
852
|
-
if self._notes is not None:
|
853
|
-
run.notes = self._notes
|
854
|
-
if self._tags is not None:
|
855
|
-
for tag in self._tags:
|
856
|
-
run.tags.append(tag)
|
857
|
-
if self._start_time is not None:
|
858
|
-
run.start_time.FromMicroseconds(int(self._start_time * 1e6))
|
859
|
-
if self._remote_url is not None:
|
860
|
-
run.git.remote_url = self._remote_url
|
861
|
-
if self._commit is not None:
|
862
|
-
run.git.commit = self._commit
|
863
|
-
if self._sweep_id is not None:
|
864
|
-
run.sweep_id = self._sweep_id
|
865
|
-
# Note: run.config is set in interface/interface:_make_run()
|
866
|
-
|
867
|
-
def _populate_git_info(self) -> None:
|
868
|
-
# Use user provided git info if available otherwise resolve it from the environment
|
869
|
-
try:
|
870
|
-
repo = GitRepo(
|
871
|
-
root=self._settings.git_root,
|
872
|
-
remote=self._settings.git_remote,
|
873
|
-
remote_url=self._settings.git_remote_url,
|
874
|
-
commit=self._settings.git_commit,
|
875
|
-
lazy=False,
|
876
|
-
)
|
877
|
-
self._remote_url, self._commit = repo.remote_url, repo.last_commit
|
878
|
-
except Exception:
|
879
|
-
wandb.termwarn("Cannot find valid git repo associated with this directory.")
|
880
|
-
|
881
792
|
def __deepcopy__(self, memo: dict[int, Any]) -> Run:
|
882
793
|
return self
|
883
794
|
|
@@ -948,18 +859,16 @@ class Run:
|
|
948
859
|
Display names are not guaranteed to be unique and may be descriptive.
|
949
860
|
By default, they are randomly generated.
|
950
861
|
"""
|
951
|
-
if self.
|
952
|
-
return self.
|
953
|
-
|
954
|
-
return None
|
955
|
-
return self._run_obj.display_name
|
862
|
+
if self._settings.run_name:
|
863
|
+
return self._settings.run_name
|
864
|
+
return None
|
956
865
|
|
957
866
|
@name.setter
|
958
867
|
@_run_decorator._noop_on_finish()
|
959
868
|
def name(self, name: str) -> None:
|
960
869
|
with telemetry.context(run=self) as tel:
|
961
870
|
tel.feature.set_run_name = True
|
962
|
-
self.
|
871
|
+
self._settings.run_name = name
|
963
872
|
if self._backend and self._backend.interface:
|
964
873
|
self._backend.interface.publish_run(self)
|
965
874
|
|
@@ -971,16 +880,12 @@ class Run:
|
|
971
880
|
Notes can be a multiline string and can also use markdown and latex equations
|
972
881
|
inside `$$`, like `$x + 3$`.
|
973
882
|
"""
|
974
|
-
|
975
|
-
return self._notes
|
976
|
-
if not self._run_obj:
|
977
|
-
return None
|
978
|
-
return self._run_obj.notes
|
883
|
+
return self._settings.run_notes
|
979
884
|
|
980
885
|
@notes.setter
|
981
886
|
@_run_decorator._noop_on_finish()
|
982
887
|
def notes(self, notes: str) -> None:
|
983
|
-
self.
|
888
|
+
self._settings.run_notes = notes
|
984
889
|
if self._backend and self._backend.interface:
|
985
890
|
self._backend.interface.publish_run(self)
|
986
891
|
|
@@ -988,18 +893,14 @@ class Run:
|
|
988
893
|
@_run_decorator._attach
|
989
894
|
def tags(self) -> tuple | None:
|
990
895
|
"""Tags associated with the run, if there are any."""
|
991
|
-
|
992
|
-
return self._tags
|
993
|
-
if self._run_obj:
|
994
|
-
return tuple(self._run_obj.tags)
|
995
|
-
return None
|
896
|
+
return self._settings.run_tags or ()
|
996
897
|
|
997
898
|
@tags.setter
|
998
899
|
@_run_decorator._noop_on_finish()
|
999
900
|
def tags(self, tags: Sequence) -> None:
|
1000
901
|
with telemetry.context(run=self) as tel:
|
1001
902
|
tel.feature.set_run_tags = True
|
1002
|
-
self.
|
903
|
+
self._settings.run_tags = tuple(tags)
|
1003
904
|
if self._backend and self._backend.interface:
|
1004
905
|
self._backend.interface.publish_run(self)
|
1005
906
|
|
@@ -1008,22 +909,25 @@ class Run:
|
|
1008
909
|
def id(self) -> str:
|
1009
910
|
"""Identifier for this run."""
|
1010
911
|
if TYPE_CHECKING:
|
1011
|
-
assert self.
|
1012
|
-
return self.
|
912
|
+
assert self._settings.run_id is not None
|
913
|
+
return self._settings.run_id
|
1013
914
|
|
1014
915
|
@property
|
1015
916
|
@_run_decorator._attach
|
1016
917
|
def sweep_id(self) -> str | None:
|
1017
918
|
"""ID of the sweep associated with the run, if there is one."""
|
1018
|
-
|
1019
|
-
return None
|
1020
|
-
return self._run_obj.sweep_id or None
|
919
|
+
return self._settings.sweep_id
|
1021
920
|
|
1022
921
|
def _get_path(self) -> str:
|
1023
|
-
|
1024
|
-
e
|
1025
|
-
|
1026
|
-
|
922
|
+
return "/".join(
|
923
|
+
e
|
924
|
+
for e in [
|
925
|
+
self._settings.entity,
|
926
|
+
self._settings.project,
|
927
|
+
self._settings.run_id,
|
928
|
+
]
|
929
|
+
if e is not None
|
930
|
+
)
|
1027
931
|
|
1028
932
|
@property
|
1029
933
|
@_run_decorator._attach
|
@@ -1035,33 +939,23 @@ class Run:
|
|
1035
939
|
"""
|
1036
940
|
return self._get_path()
|
1037
941
|
|
1038
|
-
def _get_start_time(self) -> float:
|
1039
|
-
return (
|
1040
|
-
self._start_time
|
1041
|
-
if not self._run_obj
|
1042
|
-
else (self._run_obj.start_time.ToMicroseconds() / 1e6)
|
1043
|
-
)
|
1044
|
-
|
1045
942
|
@property
|
1046
943
|
@_run_decorator._attach
|
1047
944
|
def start_time(self) -> float:
|
1048
945
|
"""Unix timestamp (in seconds) of when the run started."""
|
1049
|
-
return self.
|
1050
|
-
|
1051
|
-
def _get_starting_step(self) -> int:
|
1052
|
-
return self._starting_step if not self._run_obj else self._run_obj.starting_step
|
946
|
+
return self._start_time
|
1053
947
|
|
1054
948
|
@property
|
1055
949
|
@_run_decorator._attach
|
1056
950
|
def starting_step(self) -> int:
|
1057
951
|
"""The first step of the run."""
|
1058
|
-
return self.
|
952
|
+
return self._starting_step
|
1059
953
|
|
1060
954
|
@property
|
1061
955
|
@_run_decorator._attach
|
1062
956
|
def resumed(self) -> bool:
|
1063
957
|
"""True if the run was resumed, False otherwise."""
|
1064
|
-
return self.
|
958
|
+
return self._settings.resumed
|
1065
959
|
|
1066
960
|
@property
|
1067
961
|
@_run_decorator._attach
|
@@ -1072,10 +966,6 @@ class Run:
|
|
1072
966
|
"""
|
1073
967
|
return self._step
|
1074
968
|
|
1075
|
-
def project_name(self) -> str:
|
1076
|
-
# TODO: deprecate this in favor of project
|
1077
|
-
return self._run_obj.project if self._run_obj else ""
|
1078
|
-
|
1079
969
|
@property
|
1080
970
|
@_run_decorator._attach
|
1081
971
|
def mode(self) -> str:
|
@@ -1100,9 +990,6 @@ class Run:
|
|
1100
990
|
def disabled(self) -> bool:
|
1101
991
|
return self._settings._noop
|
1102
992
|
|
1103
|
-
def _get_group(self) -> str:
|
1104
|
-
return self._run_obj.run_group if self._run_obj else ""
|
1105
|
-
|
1106
993
|
@property
|
1107
994
|
@_run_decorator._attach
|
1108
995
|
def group(self) -> str:
|
@@ -1115,12 +1002,16 @@ class Run:
|
|
1115
1002
|
If you are doing cross-validation you should give all the cross-validation
|
1116
1003
|
folds the same group.
|
1117
1004
|
"""
|
1118
|
-
return self.
|
1005
|
+
return self._settings.run_group or ""
|
1119
1006
|
|
1120
1007
|
@property
|
1121
1008
|
@_run_decorator._attach
|
1122
1009
|
def job_type(self) -> str:
|
1123
|
-
return self.
|
1010
|
+
return self._settings.run_job_type or ""
|
1011
|
+
|
1012
|
+
def project_name(self) -> str:
|
1013
|
+
# TODO: deprecate this in favor of project
|
1014
|
+
return self._settings.project or ""
|
1124
1015
|
|
1125
1016
|
@property
|
1126
1017
|
@_run_decorator._attach
|
@@ -1167,7 +1058,9 @@ class Run:
|
|
1167
1058
|
run.log_code(
|
1168
1059
|
"../",
|
1169
1060
|
include_fn=lambda path: path.endswith(".py") or path.endswith(".ipynb"),
|
1170
|
-
exclude_fn=lambda path, root: os.path.relpath(path, root).startswith(
|
1061
|
+
exclude_fn=lambda path, root: os.path.relpath(path, root).startswith(
|
1062
|
+
"cache/"
|
1063
|
+
),
|
1171
1064
|
)
|
1172
1065
|
```
|
1173
1066
|
|
@@ -1184,9 +1077,11 @@ class Run:
|
|
1184
1077
|
notebook_name = self.settings.x_jupyter_name
|
1185
1078
|
else:
|
1186
1079
|
notebook_name = self.settings.x_jupyter_path
|
1187
|
-
name_string = f"{self.
|
1080
|
+
name_string = f"{self._settings.project}-{notebook_name}"
|
1188
1081
|
else:
|
1189
|
-
name_string =
|
1082
|
+
name_string = (
|
1083
|
+
f"{self._settings.project}-{self._settings.program_relpath}"
|
1084
|
+
)
|
1190
1085
|
name = wandb.util.make_artifact_name_safe(f"source-{name_string}")
|
1191
1086
|
art = wandb.Artifact(name, "code")
|
1192
1087
|
files_added = False
|
@@ -1211,16 +1106,6 @@ class Run:
|
|
1211
1106
|
|
1212
1107
|
return self._log_artifact(art)
|
1213
1108
|
|
1214
|
-
def get_url(self) -> str | None:
|
1215
|
-
"""Return the url for the W&B run, if there is one.
|
1216
|
-
|
1217
|
-
Offline runs will not have a url.
|
1218
|
-
"""
|
1219
|
-
if self._settings._offline:
|
1220
|
-
wandb.termwarn("URL not available in offline run")
|
1221
|
-
return None
|
1222
|
-
return self._settings.run_url
|
1223
|
-
|
1224
1109
|
def get_project_url(self) -> str | None:
|
1225
1110
|
"""Return the url for the W&B project associated with the run, if there is one.
|
1226
1111
|
|
@@ -1238,6 +1123,16 @@ class Run:
|
|
1238
1123
|
return None
|
1239
1124
|
return self._settings.sweep_url
|
1240
1125
|
|
1126
|
+
def get_url(self) -> str | None:
|
1127
|
+
"""Return the url for the W&B run, if there is one.
|
1128
|
+
|
1129
|
+
Offline runs will not have a url.
|
1130
|
+
"""
|
1131
|
+
if self._settings._offline:
|
1132
|
+
wandb.termwarn("URL not available in offline run")
|
1133
|
+
return None
|
1134
|
+
return self._settings.run_url
|
1135
|
+
|
1241
1136
|
@property
|
1242
1137
|
@_run_decorator._attach
|
1243
1138
|
def url(self) -> str | None:
|
@@ -1251,7 +1146,7 @@ class Run:
|
|
1251
1146
|
|
1252
1147
|
Entity can be a username or the name of a team or organization.
|
1253
1148
|
"""
|
1254
|
-
return self.
|
1149
|
+
return self._settings.entity or ""
|
1255
1150
|
|
1256
1151
|
def _label_internal(
|
1257
1152
|
self,
|
@@ -1342,10 +1237,19 @@ class Run:
|
|
1342
1237
|
@_run_decorator._attach
|
1343
1238
|
def display(self, height: int = 420, hidden: bool = False) -> bool:
|
1344
1239
|
"""Display this run in jupyter."""
|
1345
|
-
if self._settings.
|
1346
|
-
|
1240
|
+
if self._settings.silent:
|
1241
|
+
return False
|
1242
|
+
|
1243
|
+
if not ipython.in_jupyter():
|
1244
|
+
return False
|
1245
|
+
|
1246
|
+
try:
|
1247
|
+
from IPython import display
|
1248
|
+
|
1249
|
+
display.display(display.HTML(self.to_html(height, hidden)))
|
1347
1250
|
return True
|
1348
|
-
|
1251
|
+
|
1252
|
+
except ImportError:
|
1349
1253
|
wandb.termwarn(".display() only works in jupyter environments")
|
1350
1254
|
return False
|
1351
1255
|
|
@@ -1548,13 +1452,13 @@ class Run:
|
|
1548
1452
|
def _set_teardown_hooks(self, hooks: list[TeardownHook]) -> None:
|
1549
1453
|
self._teardown_hooks = hooks
|
1550
1454
|
|
1551
|
-
def _set_run_obj(self, run_obj: RunRecord) -> None:
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1455
|
+
def _set_run_obj(self, run_obj: RunRecord) -> None: # noqa: C901
|
1456
|
+
if run_obj.starting_step:
|
1457
|
+
self._starting_step = run_obj.starting_step
|
1458
|
+
self._step = run_obj.starting_step
|
1555
1459
|
|
1556
|
-
|
1557
|
-
|
1460
|
+
if run_obj.start_time:
|
1461
|
+
self._start_time = run_obj.start_time.ToMicroseconds() / 1e6
|
1558
1462
|
|
1559
1463
|
# Grab the config from resuming
|
1560
1464
|
if run_obj.config:
|
@@ -1571,40 +1475,61 @@ class Run:
|
|
1571
1475
|
summary_dict[orig.key] = json.loads(orig.value_json)
|
1572
1476
|
if summary_dict:
|
1573
1477
|
self.summary.update(summary_dict)
|
1574
|
-
self._step = self._get_starting_step()
|
1575
1478
|
|
1576
1479
|
# update settings from run_obj
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
if
|
1600
|
-
|
1601
|
-
|
1480
|
+
if run_obj.run_id:
|
1481
|
+
self._settings.run_id = run_obj.run_id
|
1482
|
+
if run_obj.entity:
|
1483
|
+
self._settings.entity = run_obj.entity
|
1484
|
+
if run_obj.project:
|
1485
|
+
self._settings.project = run_obj.project
|
1486
|
+
if run_obj.run_group:
|
1487
|
+
self._settings.run_group = run_obj.run_group
|
1488
|
+
if run_obj.job_type:
|
1489
|
+
self._settings.run_job_type = run_obj.job_type
|
1490
|
+
if run_obj.display_name:
|
1491
|
+
self._settings.run_name = run_obj.display_name
|
1492
|
+
if run_obj.notes:
|
1493
|
+
self._settings.run_notes = run_obj.notes
|
1494
|
+
if run_obj.tags:
|
1495
|
+
self._settings.run_tags = run_obj.tags
|
1496
|
+
if run_obj.sweep_id:
|
1497
|
+
self._settings.sweep_id = run_obj.sweep_id
|
1498
|
+
if run_obj.host:
|
1499
|
+
self._settings.host = run_obj.host
|
1500
|
+
if run_obj.resumed:
|
1501
|
+
self._settings.resumed = run_obj.resumed
|
1502
|
+
if run_obj.git:
|
1503
|
+
if run_obj.git.remote_url:
|
1504
|
+
self._settings.git_remote_url = run_obj.git.remote_url
|
1505
|
+
if run_obj.git.commit:
|
1506
|
+
self._settings.git_commit = run_obj.git.commit
|
1507
|
+
|
1508
|
+
if run_obj.forked:
|
1509
|
+
self._forked = run_obj.forked
|
1602
1510
|
|
1603
1511
|
wandb._sentry.configure_scope(
|
1604
1512
|
process_context="user",
|
1605
1513
|
tags=dict(self._settings),
|
1606
1514
|
)
|
1607
1515
|
|
1516
|
+
def _populate_git_info(self) -> None:
|
1517
|
+
from .lib.gitlib import GitRepo
|
1518
|
+
|
1519
|
+
# Use user provided git info if available otherwise resolve it from the environment
|
1520
|
+
try:
|
1521
|
+
repo = GitRepo(
|
1522
|
+
root=self._settings.git_root,
|
1523
|
+
remote=self._settings.git_remote,
|
1524
|
+
remote_url=self._settings.git_remote_url,
|
1525
|
+
commit=self._settings.git_commit,
|
1526
|
+
lazy=False,
|
1527
|
+
)
|
1528
|
+
self._settings.git_remote_url = repo.remote_url
|
1529
|
+
self._settings.git_commit = repo.last_commit
|
1530
|
+
except Exception:
|
1531
|
+
wandb.termwarn("Cannot find valid git repo associated with this directory.")
|
1532
|
+
|
1608
1533
|
def _add_singleton(
|
1609
1534
|
self, data_type: str, key: str, value: dict[int | str, str]
|
1610
1535
|
) -> None:
|
@@ -1715,12 +1640,14 @@ class Run:
|
|
1715
1640
|
the following results in two sections named "train" and "validate":
|
1716
1641
|
|
1717
1642
|
```
|
1718
|
-
run.log(
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1643
|
+
run.log(
|
1644
|
+
{
|
1645
|
+
"train/accuracy": 0.9,
|
1646
|
+
"train/loss": 30,
|
1647
|
+
"validate/accuracy": 0.8,
|
1648
|
+
"validate/loss": 20,
|
1649
|
+
}
|
1650
|
+
)
|
1724
1651
|
```
|
1725
1652
|
|
1726
1653
|
Only one level of nesting is supported; `run.log({"a/b/c": 1})`
|
@@ -1846,7 +1773,9 @@ class Run:
|
|
1846
1773
|
run = wandb.init()
|
1847
1774
|
examples = []
|
1848
1775
|
for i in range(3):
|
1849
|
-
pixels = np.random.randint(
|
1776
|
+
pixels = np.random.randint(
|
1777
|
+
low=0, high=256, size=(100, 100, 3), dtype=np.uint8
|
1778
|
+
)
|
1850
1779
|
pil_image = PILImage.fromarray(pixels, mode="RGB")
|
1851
1780
|
image = wandb.Image(pil_image, caption=f"random field {i}")
|
1852
1781
|
examples.append(image)
|
@@ -1861,7 +1790,9 @@ class Run:
|
|
1861
1790
|
|
1862
1791
|
run = wandb.init()
|
1863
1792
|
# axes are (time, channel, height, width)
|
1864
|
-
frames = np.random.randint(
|
1793
|
+
frames = np.random.randint(
|
1794
|
+
low=0, high=256, size=(10, 3, 100, 100), dtype=np.uint8
|
1795
|
+
)
|
1865
1796
|
run.log({"video": wandb.Video(frames, fps=4)})
|
1866
1797
|
```
|
1867
1798
|
|
@@ -2203,8 +2134,8 @@ class Run:
|
|
2203
2134
|
#
|
2204
2135
|
# TODO: Why not do this in _atexit_cleanup()?
|
2205
2136
|
service = self._wl and self._wl.service
|
2206
|
-
if service and self.
|
2207
|
-
service.inform_finish(run_id=self.
|
2137
|
+
if service and self._settings.run_id:
|
2138
|
+
service.inform_finish(run_id=self._settings.run_id)
|
2208
2139
|
|
2209
2140
|
finally:
|
2210
2141
|
module.unset_globals()
|
@@ -2517,12 +2448,12 @@ class Run:
|
|
2517
2448
|
|
2518
2449
|
import_telemetry_set = telemetry.list_telemetry_imports()
|
2519
2450
|
import_hook_fn = functools.partial(_telemetry_import_hook, self)
|
2520
|
-
if not self.
|
2451
|
+
if not self._settings.run_id:
|
2521
2452
|
return
|
2522
2453
|
for module_name in import_telemetry_set:
|
2523
2454
|
register_post_import_hook(
|
2524
2455
|
import_hook_fn,
|
2525
|
-
self.
|
2456
|
+
self._settings.run_id,
|
2526
2457
|
module_name,
|
2527
2458
|
)
|
2528
2459
|
|
@@ -2534,7 +2465,10 @@ class Run:
|
|
2534
2465
|
self._telemetry_obj_active = True
|
2535
2466
|
self._telemetry_flush()
|
2536
2467
|
|
2537
|
-
|
2468
|
+
try:
|
2469
|
+
self._detect_and_apply_job_inputs()
|
2470
|
+
except Exception as e:
|
2471
|
+
logger.error("Problem applying launch job inputs", exc_info=e)
|
2538
2472
|
|
2539
2473
|
# object is about to be returned to the user, don't let them modify it
|
2540
2474
|
self._freeze()
|
@@ -2715,8 +2649,8 @@ class Run:
|
|
2715
2649
|
if self._run_status_checker:
|
2716
2650
|
self._run_status_checker.join()
|
2717
2651
|
|
2718
|
-
if self.
|
2719
|
-
self._unregister_telemetry_import_hooks(self.
|
2652
|
+
if self._settings.run_id:
|
2653
|
+
self._unregister_telemetry_import_hooks(self._settings.run_id)
|
2720
2654
|
|
2721
2655
|
@staticmethod
|
2722
2656
|
def _unregister_telemetry_import_hooks(run_id: str) -> None:
|
@@ -3051,10 +2985,14 @@ class Run:
|
|
3051
2985
|
"""
|
3052
2986
|
if self._settings._offline:
|
3053
2987
|
raise TypeError("Cannot use artifact when in offline mode.")
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
2988
|
+
|
2989
|
+
api = internal.Api(
|
2990
|
+
default_settings={
|
2991
|
+
"entity": self._settings.entity,
|
2992
|
+
"project": self._settings.project,
|
2993
|
+
}
|
2994
|
+
)
|
2995
|
+
api.set_current_run_id(self._settings.run_id)
|
3058
2996
|
|
3059
2997
|
if isinstance(artifact_or_name, str):
|
3060
2998
|
if self._launch_artifact_mapping:
|
@@ -3085,8 +3023,8 @@ class Run:
|
|
3085
3023
|
self._used_artifact_slots[use_as] = artifact.id
|
3086
3024
|
api.use_artifact(
|
3087
3025
|
artifact.id,
|
3088
|
-
entity_name=
|
3089
|
-
project_name=
|
3026
|
+
entity_name=self._settings.entity,
|
3027
|
+
project_name=self._settings.project,
|
3090
3028
|
use_as=use_as or artifact_or_name,
|
3091
3029
|
)
|
3092
3030
|
else:
|
@@ -3211,12 +3149,12 @@ class Run:
|
|
3211
3149
|
Returns:
|
3212
3150
|
An `Artifact` object.
|
3213
3151
|
"""
|
3214
|
-
if self.
|
3152
|
+
if self._settings.run_group is None and distributed_id is None:
|
3215
3153
|
raise TypeError(
|
3216
3154
|
"Cannot upsert artifact unless run is in a group or distributed_id is provided"
|
3217
3155
|
)
|
3218
3156
|
if distributed_id is None:
|
3219
|
-
distributed_id = self.
|
3157
|
+
distributed_id = self._settings.run_group or ""
|
3220
3158
|
return self._log_artifact(
|
3221
3159
|
artifact_or_path,
|
3222
3160
|
name=name,
|
@@ -3264,12 +3202,12 @@ class Run:
|
|
3264
3202
|
Returns:
|
3265
3203
|
An `Artifact` object.
|
3266
3204
|
"""
|
3267
|
-
if self.
|
3205
|
+
if self._settings.run_group is None and distributed_id is None:
|
3268
3206
|
raise TypeError(
|
3269
3207
|
"Cannot finish artifact unless run is in a group or distributed_id is provided"
|
3270
3208
|
)
|
3271
3209
|
if distributed_id is None:
|
3272
|
-
distributed_id = self.
|
3210
|
+
distributed_id = self._settings.run_group or ""
|
3273
3211
|
|
3274
3212
|
return self._log_artifact(
|
3275
3213
|
artifact_or_path,
|
@@ -3349,10 +3287,10 @@ class Run:
|
|
3349
3287
|
return artifact
|
3350
3288
|
|
3351
3289
|
def _public_api(self, overrides: dict[str, str] | None = None) -> PublicApi:
|
3352
|
-
overrides = {"run": self.
|
3353
|
-
if not
|
3354
|
-
overrides["entity"] = self.
|
3355
|
-
overrides["project"] = self.
|
3290
|
+
overrides = {"run": self._settings.run_id} # type: ignore
|
3291
|
+
if not self._settings._offline:
|
3292
|
+
overrides["entity"] = self._settings.entity or ""
|
3293
|
+
overrides["project"] = self._settings.project or ""
|
3356
3294
|
return public.Api(overrides)
|
3357
3295
|
|
3358
3296
|
# TODO(jhr): annotate this
|
@@ -3395,7 +3333,10 @@ class Run:
|
|
3395
3333
|
aliases: list[str] | None = None,
|
3396
3334
|
) -> tuple[Artifact, list[str]]:
|
3397
3335
|
if isinstance(artifact_or_path, (str, os.PathLike)):
|
3398
|
-
name =
|
3336
|
+
name = (
|
3337
|
+
name
|
3338
|
+
or f"run-{self._settings.run_id}-{os.path.basename(artifact_or_path)}"
|
3339
|
+
)
|
3399
3340
|
artifact = wandb.Artifact(name, type or "unspecified")
|
3400
3341
|
if os.path.isfile(artifact_or_path):
|
3401
3342
|
artifact.add_file(str(artifact_or_path))
|