wandb 0.18.3__py3-none-win32.whl → 0.18.4__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 +16 -7
- wandb/__init__.pyi +96 -63
- wandb/analytics/sentry.py +91 -88
- wandb/apis/public/api.py +18 -4
- wandb/apis/public/runs.py +53 -2
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/beta.py +178 -0
- wandb/cli/cli.py +5 -171
- wandb/data_types.py +3 -0
- wandb/env.py +74 -73
- wandb/errors/term.py +300 -43
- wandb/proto/v3/wandb_internal_pb2.py +263 -223
- wandb/proto/v3/wandb_server_pb2.py +57 -37
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_internal_pb2.py +226 -218
- wandb/proto/v4/wandb_server_pb2.py +41 -37
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_internal_pb2.py +226 -218
- wandb/proto/v5/wandb_server_pb2.py +41 -37
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/sdk/__init__.py +3 -3
- wandb/sdk/artifacts/_validators.py +41 -8
- wandb/sdk/artifacts/artifact.py +32 -1
- wandb/sdk/artifacts/artifact_file_cache.py +1 -2
- wandb/sdk/data_types/_dtypes.py +7 -3
- wandb/sdk/data_types/video.py +15 -6
- wandb/sdk/interface/interface.py +2 -0
- wandb/sdk/internal/internal_api.py +122 -5
- wandb/sdk/internal/sender.py +16 -3
- wandb/sdk/launch/inputs/internal.py +1 -1
- wandb/sdk/lib/module.py +12 -0
- wandb/sdk/lib/printer.py +291 -105
- wandb/sdk/lib/progress.py +274 -0
- wandb/sdk/service/streams.py +21 -11
- wandb/sdk/wandb_init.py +58 -54
- wandb/sdk/wandb_run.py +380 -454
- wandb/sdk/wandb_settings.py +2 -0
- wandb/sdk/wandb_watch.py +17 -11
- wandb/util.py +6 -2
- {wandb-0.18.3.dist-info → wandb-0.18.4.dist-info}/METADATA +4 -3
- {wandb-0.18.3.dist-info → wandb-0.18.4.dist-info}/RECORD +45 -43
- wandb/bin/nvidia_gpu_stats.exe +0 -0
- {wandb-0.18.3.dist-info → wandb-0.18.4.dist-info}/WHEEL +0 -0
- {wandb-0.18.3.dist-info → wandb-0.18.4.dist-info}/entry_points.txt +0 -0
- {wandb-0.18.3.dist-info → wandb-0.18.4.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_run.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import _thread as thread
|
2
4
|
import atexit
|
3
5
|
import functools
|
@@ -18,20 +20,12 @@ from dataclasses import dataclass, field
|
|
18
20
|
from datetime import datetime, timedelta, timezone
|
19
21
|
from enum import IntEnum
|
20
22
|
from types import TracebackType
|
21
|
-
from typing import
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
NamedTuple,
|
28
|
-
Optional,
|
29
|
-
Sequence,
|
30
|
-
TextIO,
|
31
|
-
Tuple,
|
32
|
-
Type,
|
33
|
-
Union,
|
34
|
-
)
|
23
|
+
from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Sequence, TextIO
|
24
|
+
|
25
|
+
if sys.version_info < (3, 8):
|
26
|
+
from typing_extensions import Literal
|
27
|
+
else:
|
28
|
+
from typing import Literal
|
35
29
|
|
36
30
|
import requests
|
37
31
|
|
@@ -69,7 +63,11 @@ from wandb.util import (
|
|
69
63
|
)
|
70
64
|
|
71
65
|
from . import wandb_config, wandb_metric, wandb_summary
|
72
|
-
from .artifacts._validators import
|
66
|
+
from .artifacts._validators import (
|
67
|
+
is_artifact_registry_project,
|
68
|
+
validate_aliases,
|
69
|
+
validate_tags,
|
70
|
+
)
|
73
71
|
from .data_types._dtypes import TypeRegistry
|
74
72
|
from .interface.interface import FilesDict, GlobStr, InterfaceBase, PolicyName
|
75
73
|
from .interface.summary_record import SummaryRecord
|
@@ -80,6 +78,8 @@ from .lib import (
|
|
80
78
|
filesystem,
|
81
79
|
ipython,
|
82
80
|
module,
|
81
|
+
printer,
|
82
|
+
progress,
|
83
83
|
proto_util,
|
84
84
|
redirect,
|
85
85
|
telemetry,
|
@@ -87,7 +87,6 @@ from .lib import (
|
|
87
87
|
from .lib.exit_hooks import ExitHooks
|
88
88
|
from .lib.gitlib import GitRepo
|
89
89
|
from .lib.mailbox import MailboxError, MailboxHandle, MailboxProbe, MailboxProgress
|
90
|
-
from .lib.printer import get_printer
|
91
90
|
from .lib.proto_util import message_to_dict
|
92
91
|
from .lib.reporting import Reporter
|
93
92
|
from .lib.wburls import wburls
|
@@ -101,26 +100,27 @@ if TYPE_CHECKING:
|
|
101
100
|
else:
|
102
101
|
from typing_extensions import TypedDict
|
103
102
|
|
103
|
+
import torch # type: ignore [import-not-found]
|
104
|
+
|
104
105
|
import wandb.apis.public
|
105
106
|
import wandb.sdk.backend.backend
|
106
107
|
import wandb.sdk.interface.interface_queue
|
108
|
+
from wandb.data_types import Table
|
107
109
|
from wandb.proto.wandb_internal_pb2 import (
|
108
110
|
GetSummaryResponse,
|
109
111
|
InternalMessagesResponse,
|
110
112
|
SampledHistoryResponse,
|
111
113
|
)
|
112
114
|
|
113
|
-
from .lib.printer import PrinterJupyter, PrinterTerm
|
114
|
-
|
115
115
|
class GitSourceDict(TypedDict):
|
116
116
|
remote: str
|
117
117
|
commit: str
|
118
|
-
entrypoint:
|
118
|
+
entrypoint: list[str]
|
119
119
|
args: Sequence[str]
|
120
120
|
|
121
121
|
class ArtifactSourceDict(TypedDict):
|
122
122
|
artifact: str
|
123
|
-
entrypoint:
|
123
|
+
entrypoint: list[str]
|
124
124
|
args: Sequence[str]
|
125
125
|
|
126
126
|
class ImageSourceDict(TypedDict):
|
@@ -130,10 +130,10 @@ if TYPE_CHECKING:
|
|
130
130
|
class JobSourceDict(TypedDict, total=False):
|
131
131
|
_version: str
|
132
132
|
source_type: str
|
133
|
-
source:
|
134
|
-
input_types:
|
135
|
-
output_types:
|
136
|
-
runtime:
|
133
|
+
source: GitSourceDict | ArtifactSourceDict | ImageSourceDict
|
134
|
+
input_types: dict[str, Any]
|
135
|
+
output_types: dict[str, Any]
|
136
|
+
runtime: str | None
|
137
137
|
|
138
138
|
|
139
139
|
logger = logging.getLogger("wandb")
|
@@ -160,11 +160,11 @@ class RunStatusChecker:
|
|
160
160
|
"""
|
161
161
|
|
162
162
|
_stop_status_lock: threading.Lock
|
163
|
-
_stop_status_handle:
|
163
|
+
_stop_status_handle: MailboxHandle | None
|
164
164
|
_network_status_lock: threading.Lock
|
165
|
-
_network_status_handle:
|
165
|
+
_network_status_handle: MailboxHandle | None
|
166
166
|
_internal_messages_lock: threading.Lock
|
167
|
-
_internal_messages_handle:
|
167
|
+
_internal_messages_handle: MailboxHandle | None
|
168
168
|
|
169
169
|
def __init__(
|
170
170
|
self,
|
@@ -212,7 +212,7 @@ class RunStatusChecker:
|
|
212
212
|
@staticmethod
|
213
213
|
def _abandon_status_check(
|
214
214
|
lock: threading.Lock,
|
215
|
-
handle:
|
215
|
+
handle: MailboxHandle | None,
|
216
216
|
):
|
217
217
|
with lock:
|
218
218
|
if handle:
|
@@ -227,7 +227,7 @@ class RunStatusChecker:
|
|
227
227
|
request: Any,
|
228
228
|
process: Any,
|
229
229
|
) -> None:
|
230
|
-
local_handle:
|
230
|
+
local_handle: MailboxHandle | None = None
|
231
231
|
join_requested = False
|
232
232
|
while not join_requested:
|
233
233
|
time_probe = time.monotonic()
|
@@ -365,7 +365,7 @@ class _run_decorator: # noqa: N801
|
|
365
365
|
@classmethod
|
366
366
|
def _attach(cls, func: Callable) -> Callable:
|
367
367
|
@functools.wraps(func)
|
368
|
-
def wrapper(self:
|
368
|
+
def wrapper(self: type[Run], *args: Any, **kwargs: Any) -> Any:
|
369
369
|
# * `_attach_id` is only assigned in service hence for all non-service cases
|
370
370
|
# it will be a passthrough.
|
371
371
|
# * `_attach_pid` is only assigned in _init (using _attach_pid guarantees single attach):
|
@@ -398,7 +398,7 @@ class _run_decorator: # noqa: N801
|
|
398
398
|
def _noop_on_finish(cls, message: str = "", only_warn: bool = False) -> Callable:
|
399
399
|
def decorator_fn(func: Callable) -> Callable:
|
400
400
|
@functools.wraps(func)
|
401
|
-
def wrapper_fn(self:
|
401
|
+
def wrapper_fn(self: type[Run], *args: Any, **kwargs: Any) -> Any:
|
402
402
|
if not getattr(self, "_is_finished", False):
|
403
403
|
return func(self, *args, **kwargs)
|
404
404
|
|
@@ -419,7 +419,7 @@ class _run_decorator: # noqa: N801
|
|
419
419
|
@classmethod
|
420
420
|
def _noop(cls, func: Callable) -> Callable:
|
421
421
|
@functools.wraps(func)
|
422
|
-
def wrapper(self:
|
422
|
+
def wrapper(self: type[Run], *args: Any, **kwargs: Any) -> Any:
|
423
423
|
# `_attach_id` is only assigned in service hence for all service cases
|
424
424
|
# it will be a passthrough. We don't pickle non-service so again a way
|
425
425
|
# to see that we are in non-service case
|
@@ -458,7 +458,7 @@ class _run_decorator: # noqa: N801
|
|
458
458
|
class RunStatus:
|
459
459
|
sync_items_total: int = field(default=0)
|
460
460
|
sync_items_pending: int = field(default=0)
|
461
|
-
sync_time:
|
461
|
+
sync_time: datetime | None = field(default=None)
|
462
462
|
|
463
463
|
|
464
464
|
class Run:
|
@@ -528,67 +528,65 @@ class Run:
|
|
528
528
|
_telemetry_obj_dirty: bool
|
529
529
|
_telemetry_obj_flushed: bytes
|
530
530
|
|
531
|
-
_teardown_hooks:
|
532
|
-
_tags:
|
531
|
+
_teardown_hooks: list[TeardownHook]
|
532
|
+
_tags: tuple[Any, ...] | None
|
533
533
|
|
534
|
-
_entity:
|
535
|
-
_project:
|
536
|
-
_group:
|
537
|
-
_job_type:
|
538
|
-
_name:
|
539
|
-
_notes:
|
540
|
-
_sweep_id:
|
534
|
+
_entity: str | None
|
535
|
+
_project: str | None
|
536
|
+
_group: str | None
|
537
|
+
_job_type: str | None
|
538
|
+
_name: str | None
|
539
|
+
_notes: str | None
|
540
|
+
_sweep_id: str | None
|
541
541
|
|
542
|
-
_run_obj:
|
542
|
+
_run_obj: RunRecord | None
|
543
543
|
# Use string literal annotation because of type reference loop
|
544
|
-
_backend:
|
545
|
-
_internal_run_interface:
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
_output_writer: Optional["filesystem.CRDedupedFile"]
|
555
|
-
_quiet: Optional[bool]
|
544
|
+
_backend: wandb.sdk.backend.backend.Backend | None
|
545
|
+
_internal_run_interface: wandb.sdk.interface.interface_queue.InterfaceQueue | None
|
546
|
+
_wl: _WandbSetup | None
|
547
|
+
|
548
|
+
_out_redir: redirect.RedirectBase | None
|
549
|
+
_err_redir: redirect.RedirectBase | None
|
550
|
+
_redirect_cb: Callable[[str, str], None] | None
|
551
|
+
_redirect_raw_cb: Callable[[str, str], None] | None
|
552
|
+
_output_writer: filesystem.CRDedupedFile | None
|
553
|
+
_quiet: bool | None
|
556
554
|
|
557
555
|
_atexit_cleanup_called: bool
|
558
|
-
_hooks:
|
559
|
-
_exit_code:
|
556
|
+
_hooks: ExitHooks | None
|
557
|
+
_exit_code: int | None
|
560
558
|
|
561
|
-
_run_status_checker:
|
559
|
+
_run_status_checker: RunStatusChecker | None
|
562
560
|
|
563
|
-
_sampled_history:
|
564
|
-
_final_summary:
|
565
|
-
_poll_exit_handle:
|
566
|
-
_poll_exit_response:
|
567
|
-
_internal_messages_response:
|
561
|
+
_sampled_history: SampledHistoryResponse | None
|
562
|
+
_final_summary: GetSummaryResponse | None
|
563
|
+
_poll_exit_handle: MailboxHandle | None
|
564
|
+
_poll_exit_response: PollExitResponse | None
|
565
|
+
_internal_messages_response: InternalMessagesResponse | None
|
568
566
|
|
569
|
-
_stdout_slave_fd:
|
570
|
-
_stderr_slave_fd:
|
571
|
-
_artifact_slots:
|
567
|
+
_stdout_slave_fd: int | None
|
568
|
+
_stderr_slave_fd: int | None
|
569
|
+
_artifact_slots: list[str]
|
572
570
|
|
573
571
|
_init_pid: int
|
574
572
|
_attach_pid: int
|
575
|
-
_iface_pid:
|
576
|
-
_iface_port:
|
573
|
+
_iface_pid: int | None
|
574
|
+
_iface_port: int | None
|
577
575
|
|
578
|
-
_attach_id:
|
576
|
+
_attach_id: str | None
|
579
577
|
_is_attached: bool
|
580
578
|
_is_finished: bool
|
581
579
|
_settings: Settings
|
582
580
|
|
583
|
-
_launch_artifacts:
|
584
|
-
_printer:
|
581
|
+
_launch_artifacts: dict[str, Any] | None
|
582
|
+
_printer: printer.Printer
|
585
583
|
|
586
584
|
def __init__(
|
587
585
|
self,
|
588
586
|
settings: Settings,
|
589
|
-
config:
|
590
|
-
sweep_config:
|
591
|
-
launch_config:
|
587
|
+
config: dict[str, Any] | None = None,
|
588
|
+
sweep_config: dict[str, Any] | None = None,
|
589
|
+
launch_config: dict[str, Any] | None = None,
|
592
590
|
) -> None:
|
593
591
|
# pid is set, so we know if this run object was initialized by this process
|
594
592
|
self._init_pid = os.getpid()
|
@@ -608,9 +606,9 @@ class Run:
|
|
608
606
|
def _init(
|
609
607
|
self,
|
610
608
|
settings: Settings,
|
611
|
-
config:
|
612
|
-
sweep_config:
|
613
|
-
launch_config:
|
609
|
+
config: dict[str, Any] | None = None,
|
610
|
+
sweep_config: dict[str, Any] | None = None,
|
611
|
+
launch_config: dict[str, Any] | None = None,
|
614
612
|
) -> None:
|
615
613
|
self._settings = settings
|
616
614
|
|
@@ -626,7 +624,7 @@ class Run:
|
|
626
624
|
)
|
627
625
|
self.summary._set_update_callback(self._summary_update_callback)
|
628
626
|
self._step = 0
|
629
|
-
self._torch_history:
|
627
|
+
self._torch_history: wandb_torch.TorchHistory | None = None # type: ignore
|
630
628
|
|
631
629
|
# todo: eventually would be nice to make this configurable using self._settings._start_time
|
632
630
|
# need to test (jhr): if you set start time to 2 days ago and run a test for 15 minutes,
|
@@ -635,9 +633,9 @@ class Run:
|
|
635
633
|
|
636
634
|
_datatypes_set_callback(self._datatypes_callback)
|
637
635
|
|
638
|
-
self._printer = get_printer(self._settings._jupyter)
|
636
|
+
self._printer = printer.get_printer(self._settings._jupyter)
|
639
637
|
self._wl = None
|
640
|
-
self._reporter:
|
638
|
+
self._reporter: Reporter | None = None
|
641
639
|
|
642
640
|
self._entity = None
|
643
641
|
self._project = None
|
@@ -663,7 +661,7 @@ class Run:
|
|
663
661
|
self._quiet = self._settings.quiet
|
664
662
|
|
665
663
|
self._output_writer = None
|
666
|
-
self._used_artifact_slots:
|
664
|
+
self._used_artifact_slots: dict[str, str] = {}
|
667
665
|
|
668
666
|
# Returned from backend request_run(), set from wandb_init?
|
669
667
|
self._run_obj = None
|
@@ -699,8 +697,8 @@ class Run:
|
|
699
697
|
config = config or dict()
|
700
698
|
wandb_key = "_wandb"
|
701
699
|
config.setdefault(wandb_key, dict())
|
702
|
-
self._launch_artifact_mapping:
|
703
|
-
self._unique_launch_artifact_sequence_names:
|
700
|
+
self._launch_artifact_mapping: dict[str, Any] = {}
|
701
|
+
self._unique_launch_artifact_sequence_names: dict[str, Any] = {}
|
704
702
|
if self._settings.save_code and self._settings.program_relpath:
|
705
703
|
config[wandb_key]["code_path"] = LogicalPath(
|
706
704
|
os.path.join("code", self._settings.program_relpath)
|
@@ -766,7 +764,7 @@ class Run:
|
|
766
764
|
def _handle_launch_artifact_overrides(self) -> None:
|
767
765
|
if self._settings.launch and (os.environ.get("WANDB_ARTIFACTS") is not None):
|
768
766
|
try:
|
769
|
-
artifacts:
|
767
|
+
artifacts: dict[str, Any] = json.loads(
|
770
768
|
os.environ.get("WANDB_ARTIFACTS", "{}")
|
771
769
|
)
|
772
770
|
except (ValueError, SyntaxError):
|
@@ -786,7 +784,7 @@ class Run:
|
|
786
784
|
artifacts = launch_config.get("overrides").get("artifacts")
|
787
785
|
self._initialize_launch_artifact_maps(artifacts)
|
788
786
|
|
789
|
-
def _initialize_launch_artifact_maps(self, artifacts:
|
787
|
+
def _initialize_launch_artifact_maps(self, artifacts: dict[str, Any]) -> None:
|
790
788
|
for key, item in artifacts.items():
|
791
789
|
self._launch_artifact_mapping[key] = item
|
792
790
|
artifact_sequence_tuple_or_slot = key.split(":")
|
@@ -893,7 +891,7 @@ class Run:
|
|
893
891
|
except Exception:
|
894
892
|
wandb.termwarn("Cannot find valid git repo associated with this directory.")
|
895
893
|
|
896
|
-
def __deepcopy__(self, memo:
|
894
|
+
def __deepcopy__(self, memo: dict[int, Any]) -> Run:
|
897
895
|
return self
|
898
896
|
|
899
897
|
def __getstate__(self) -> Any:
|
@@ -927,7 +925,7 @@ class Run:
|
|
927
925
|
self.__dict__.update(state)
|
928
926
|
|
929
927
|
@property
|
930
|
-
def _torch(self) ->
|
928
|
+
def _torch(self) -> wandb_torch.TorchHistory: # type: ignore
|
931
929
|
if self._torch_history is None:
|
932
930
|
self._torch_history = wandb_torch.TorchHistory() # type: ignore
|
933
931
|
return self._torch_history
|
@@ -959,7 +957,7 @@ class Run:
|
|
959
957
|
|
960
958
|
@property
|
961
959
|
@_run_decorator._attach
|
962
|
-
def name(self) ->
|
960
|
+
def name(self) -> str | None:
|
963
961
|
"""Display name of the run.
|
964
962
|
|
965
963
|
Display names are not guaranteed to be unique and may be descriptive.
|
@@ -982,7 +980,7 @@ class Run:
|
|
982
980
|
|
983
981
|
@property
|
984
982
|
@_run_decorator._attach
|
985
|
-
def notes(self) ->
|
983
|
+
def notes(self) -> str | None:
|
986
984
|
"""Notes associated with the run, if there are any.
|
987
985
|
|
988
986
|
Notes can be a multiline string and can also use markdown and latex equations
|
@@ -1003,7 +1001,7 @@ class Run:
|
|
1003
1001
|
|
1004
1002
|
@property
|
1005
1003
|
@_run_decorator._attach
|
1006
|
-
def tags(self) ->
|
1004
|
+
def tags(self) -> tuple | None:
|
1007
1005
|
"""Tags associated with the run, if there are any."""
|
1008
1006
|
if self._tags:
|
1009
1007
|
return self._tags
|
@@ -1030,7 +1028,7 @@ class Run:
|
|
1030
1028
|
|
1031
1029
|
@property
|
1032
1030
|
@_run_decorator._attach
|
1033
|
-
def sweep_id(self) ->
|
1031
|
+
def sweep_id(self) -> str | None:
|
1034
1032
|
"""ID of the sweep associated with the run, if there is one."""
|
1035
1033
|
if not self._run_obj:
|
1036
1034
|
return None
|
@@ -1149,15 +1147,13 @@ class Run:
|
|
1149
1147
|
@_run_decorator._attach
|
1150
1148
|
def log_code(
|
1151
1149
|
self,
|
1152
|
-
root:
|
1153
|
-
name:
|
1154
|
-
include_fn:
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
] = filenames.exclude_wandb_fn,
|
1160
|
-
) -> Optional[Artifact]:
|
1150
|
+
root: str | None = ".",
|
1151
|
+
name: str | None = None,
|
1152
|
+
include_fn: Callable[[str, str], bool]
|
1153
|
+
| Callable[[str], bool] = _is_py_requirements_or_dockerfile,
|
1154
|
+
exclude_fn: Callable[[str, str], bool]
|
1155
|
+
| Callable[[str], bool] = filenames.exclude_wandb_fn,
|
1156
|
+
) -> Artifact | None:
|
1161
1157
|
"""Save the current state of your code to a W&B Artifact.
|
1162
1158
|
|
1163
1159
|
By default, it walks the current directory and logs all files that end with `.py`.
|
@@ -1230,7 +1226,7 @@ class Run:
|
|
1230
1226
|
|
1231
1227
|
return self._log_artifact(art)
|
1232
1228
|
|
1233
|
-
def get_url(self) ->
|
1229
|
+
def get_url(self) -> str | None:
|
1234
1230
|
"""Return the url for the W&B run, if there is one.
|
1235
1231
|
|
1236
1232
|
Offline runs will not have a url.
|
@@ -1240,7 +1236,7 @@ class Run:
|
|
1240
1236
|
return None
|
1241
1237
|
return self._settings.run_url
|
1242
1238
|
|
1243
|
-
def get_project_url(self) ->
|
1239
|
+
def get_project_url(self) -> str | None:
|
1244
1240
|
"""Return the url for the W&B project associated with the run, if there is one.
|
1245
1241
|
|
1246
1242
|
Offline runs will not have a project url.
|
@@ -1250,7 +1246,7 @@ class Run:
|
|
1250
1246
|
return None
|
1251
1247
|
return self._settings.project_url
|
1252
1248
|
|
1253
|
-
def get_sweep_url(self) ->
|
1249
|
+
def get_sweep_url(self) -> str | None:
|
1254
1250
|
"""Return the url for the sweep associated with the run, if there is one."""
|
1255
1251
|
if self._settings._offline:
|
1256
1252
|
wandb.termwarn("URL not available in offline run")
|
@@ -1259,7 +1255,7 @@ class Run:
|
|
1259
1255
|
|
1260
1256
|
@property
|
1261
1257
|
@_run_decorator._attach
|
1262
|
-
def url(self) ->
|
1258
|
+
def url(self) -> str | None:
|
1263
1259
|
"""The W&B url associated with the run."""
|
1264
1260
|
return self.get_url()
|
1265
1261
|
|
@@ -1274,9 +1270,9 @@ class Run:
|
|
1274
1270
|
|
1275
1271
|
def _label_internal(
|
1276
1272
|
self,
|
1277
|
-
code:
|
1278
|
-
repo:
|
1279
|
-
code_version:
|
1273
|
+
code: str | None = None,
|
1274
|
+
repo: str | None = None,
|
1275
|
+
code_version: str | None = None,
|
1280
1276
|
) -> None:
|
1281
1277
|
with telemetry.context(run=self) as tel:
|
1282
1278
|
if code and RE_LABEL.match(code):
|
@@ -1288,9 +1284,9 @@ class Run:
|
|
1288
1284
|
|
1289
1285
|
def _label(
|
1290
1286
|
self,
|
1291
|
-
code:
|
1292
|
-
repo:
|
1293
|
-
code_version:
|
1287
|
+
code: str | None = None,
|
1288
|
+
repo: str | None = None,
|
1289
|
+
code_version: str | None = None,
|
1294
1290
|
**kwargs: str,
|
1295
1291
|
) -> None:
|
1296
1292
|
if self._settings.label_disable:
|
@@ -1312,7 +1308,7 @@ class Run:
|
|
1312
1308
|
# update telemetry in the backend immediately for _label() callers
|
1313
1309
|
self._telemetry_flush()
|
1314
1310
|
|
1315
|
-
def _label_probe_lines(self, lines:
|
1311
|
+
def _label_probe_lines(self, lines: list[str]) -> None:
|
1316
1312
|
if not lines:
|
1317
1313
|
return
|
1318
1314
|
parsed = telemetry._parse_label_lines(lines)
|
@@ -1380,23 +1376,23 @@ class Run:
|
|
1380
1376
|
return prefix + f"<iframe src={url!r} style={style!r}></iframe>"
|
1381
1377
|
|
1382
1378
|
def _repr_mimebundle_(
|
1383
|
-
self, include:
|
1384
|
-
) ->
|
1379
|
+
self, include: Any | None = None, exclude: Any | None = None
|
1380
|
+
) -> dict[str, str]:
|
1385
1381
|
return {"text/html": self.to_html(hidden=True)}
|
1386
1382
|
|
1387
1383
|
@_run_decorator._noop_on_finish()
|
1388
1384
|
def _config_callback(
|
1389
1385
|
self,
|
1390
|
-
key:
|
1391
|
-
val:
|
1392
|
-
data:
|
1386
|
+
key: tuple[str, ...] | str | None = None,
|
1387
|
+
val: Any | None = None,
|
1388
|
+
data: dict[str, object] | None = None,
|
1393
1389
|
) -> None:
|
1394
1390
|
logger.info(f"config_cb {key} {val} {data}")
|
1395
1391
|
if self._backend and self._backend.interface:
|
1396
1392
|
self._backend.interface.publish_config(key=key, val=val, data=data)
|
1397
1393
|
|
1398
1394
|
def _config_artifact_callback(
|
1399
|
-
self, key: str, val:
|
1395
|
+
self, key: str, val: str | Artifact | dict
|
1400
1396
|
) -> Artifact:
|
1401
1397
|
# artifacts can look like dicts as they are passed into the run config
|
1402
1398
|
# since the run config stores them on the backend as a dict with fields shown
|
@@ -1447,7 +1443,7 @@ class Run:
|
|
1447
1443
|
# line = "Waiting for run.summary data..."
|
1448
1444
|
# self._printer.display(line)
|
1449
1445
|
|
1450
|
-
def _summary_get_current_summary_callback(self) ->
|
1446
|
+
def _summary_get_current_summary_callback(self) -> dict[str, Any]:
|
1451
1447
|
if self._is_finished:
|
1452
1448
|
# TODO: WB-18420: fetch summary from backend and stage it before run is finished
|
1453
1449
|
wandb.termwarn("Summary data not available in finished run")
|
@@ -1474,7 +1470,7 @@ class Run:
|
|
1474
1470
|
files: FilesDict = dict(files=[(GlobStr(glob.escape(fname)), "now")])
|
1475
1471
|
self._backend.interface.publish_files(files)
|
1476
1472
|
|
1477
|
-
def _visualization_hack(self, row:
|
1473
|
+
def _visualization_hack(self, row: dict[str, Any]) -> dict[str, Any]:
|
1478
1474
|
# TODO(jhr): move visualize hack somewhere else
|
1479
1475
|
chart_keys = set()
|
1480
1476
|
split_table_set = set()
|
@@ -1511,9 +1507,9 @@ class Run:
|
|
1511
1507
|
|
1512
1508
|
def _partial_history_callback(
|
1513
1509
|
self,
|
1514
|
-
row:
|
1515
|
-
step:
|
1516
|
-
commit:
|
1510
|
+
row: dict[str, Any],
|
1511
|
+
step: int | None = None,
|
1512
|
+
commit: bool | None = None,
|
1517
1513
|
) -> None:
|
1518
1514
|
row = row.copy()
|
1519
1515
|
if row:
|
@@ -1560,19 +1556,19 @@ class Run:
|
|
1560
1556
|
def _set_library(self, library: _WandbSetup) -> None:
|
1561
1557
|
self._wl = library
|
1562
1558
|
|
1563
|
-
def _set_backend(self, backend:
|
1559
|
+
def _set_backend(self, backend: wandb.sdk.backend.backend.Backend) -> None:
|
1564
1560
|
self._backend = backend
|
1565
1561
|
|
1566
1562
|
def _set_internal_run_interface(
|
1567
1563
|
self,
|
1568
|
-
interface:
|
1564
|
+
interface: wandb.sdk.interface.interface_queue.InterfaceQueue,
|
1569
1565
|
) -> None:
|
1570
1566
|
self._internal_run_interface = interface
|
1571
1567
|
|
1572
1568
|
def _set_reporter(self, reporter: Reporter) -> None:
|
1573
1569
|
self._reporter = reporter
|
1574
1570
|
|
1575
|
-
def _set_teardown_hooks(self, hooks:
|
1571
|
+
def _set_teardown_hooks(self, hooks: list[TeardownHook]) -> None:
|
1576
1572
|
self._teardown_hooks = hooks
|
1577
1573
|
|
1578
1574
|
def _set_run_obj(self, run_obj: RunRecord) -> None:
|
@@ -1610,7 +1606,7 @@ class Run:
|
|
1610
1606
|
)
|
1611
1607
|
|
1612
1608
|
def _add_singleton(
|
1613
|
-
self, data_type: str, key: str, value:
|
1609
|
+
self, data_type: str, key: str, value: dict[int | str, str]
|
1614
1610
|
) -> None:
|
1615
1611
|
"""Store a singleton item to wandb config.
|
1616
1612
|
|
@@ -1640,9 +1636,9 @@ class Run:
|
|
1640
1636
|
|
1641
1637
|
def _log(
|
1642
1638
|
self,
|
1643
|
-
data:
|
1644
|
-
step:
|
1645
|
-
commit:
|
1639
|
+
data: dict[str, Any],
|
1640
|
+
step: int | None = None,
|
1641
|
+
commit: bool | None = None,
|
1646
1642
|
) -> None:
|
1647
1643
|
if not isinstance(data, Mapping):
|
1648
1644
|
raise ValueError("wandb.log must be passed a dictionary")
|
@@ -1681,10 +1677,10 @@ class Run:
|
|
1681
1677
|
@_run_decorator._attach
|
1682
1678
|
def log(
|
1683
1679
|
self,
|
1684
|
-
data:
|
1685
|
-
step:
|
1686
|
-
commit:
|
1687
|
-
sync:
|
1680
|
+
data: dict[str, Any],
|
1681
|
+
step: int | None = None,
|
1682
|
+
commit: bool | None = None,
|
1683
|
+
sync: bool | None = None,
|
1688
1684
|
) -> None:
|
1689
1685
|
"""Upload run data.
|
1690
1686
|
|
@@ -1937,10 +1933,10 @@ class Run:
|
|
1937
1933
|
@_run_decorator._attach
|
1938
1934
|
def save(
|
1939
1935
|
self,
|
1940
|
-
glob_str:
|
1941
|
-
base_path:
|
1936
|
+
glob_str: str | os.PathLike | None = None,
|
1937
|
+
base_path: str | os.PathLike | None = None,
|
1942
1938
|
policy: PolicyName = "live",
|
1943
|
-
) ->
|
1939
|
+
) -> bool | list[str]:
|
1944
1940
|
"""Sync one or more files to W&B.
|
1945
1941
|
|
1946
1942
|
Relative paths are relative to the current working directory.
|
@@ -2045,8 +2041,8 @@ class Run:
|
|
2045
2041
|
self,
|
2046
2042
|
glob_path: pathlib.PurePath,
|
2047
2043
|
base_path: pathlib.PurePath,
|
2048
|
-
policy:
|
2049
|
-
) ->
|
2044
|
+
policy: PolicyName,
|
2045
|
+
) -> list[str]:
|
2050
2046
|
# Can't use is_relative_to() because that's added in Python 3.9,
|
2051
2047
|
# but we support down to Python 3.7.
|
2052
2048
|
if not str(glob_path).startswith(str(base_path)):
|
@@ -2129,10 +2125,10 @@ class Run:
|
|
2129
2125
|
def restore(
|
2130
2126
|
self,
|
2131
2127
|
name: str,
|
2132
|
-
run_path:
|
2128
|
+
run_path: str | None = None,
|
2133
2129
|
replace: bool = False,
|
2134
|
-
root:
|
2135
|
-
) ->
|
2130
|
+
root: str | None = None,
|
2131
|
+
) -> None | TextIO:
|
2136
2132
|
return restore(
|
2137
2133
|
name,
|
2138
2134
|
run_path or self._get_path(),
|
@@ -2142,9 +2138,7 @@ class Run:
|
|
2142
2138
|
|
2143
2139
|
@_run_decorator._noop
|
2144
2140
|
@_run_decorator._attach
|
2145
|
-
def finish(
|
2146
|
-
self, exit_code: Optional[int] = None, quiet: Optional[bool] = None
|
2147
|
-
) -> None:
|
2141
|
+
def finish(self, exit_code: int | None = None, quiet: bool | None = None) -> None:
|
2148
2142
|
"""Mark a run as finished, and finish uploading all data.
|
2149
2143
|
|
2150
2144
|
This is used when creating multiple runs in the same process. We automatically
|
@@ -2158,8 +2152,8 @@ class Run:
|
|
2158
2152
|
|
2159
2153
|
def _finish(
|
2160
2154
|
self,
|
2161
|
-
exit_code:
|
2162
|
-
quiet:
|
2155
|
+
exit_code: int | None = None,
|
2156
|
+
quiet: bool | None = None,
|
2163
2157
|
) -> None:
|
2164
2158
|
logger.info(f"finishing run {self._get_path()}")
|
2165
2159
|
with telemetry.context(run=self) as tel:
|
@@ -2210,7 +2204,7 @@ class Run:
|
|
2210
2204
|
|
2211
2205
|
@_run_decorator._noop
|
2212
2206
|
@_run_decorator._attach
|
2213
|
-
def join(self, exit_code:
|
2207
|
+
def join(self, exit_code: int | None = None) -> None:
|
2214
2208
|
"""Deprecated alias for `finish()` - use finish instead."""
|
2215
2209
|
if hasattr(self, "_telemetry_obj"):
|
2216
2210
|
deprecate.deprecate(
|
@@ -2249,10 +2243,10 @@ class Run:
|
|
2249
2243
|
@staticmethod
|
2250
2244
|
def plot_table(
|
2251
2245
|
vega_spec_name: str,
|
2252
|
-
data_table:
|
2253
|
-
fields:
|
2254
|
-
string_fields:
|
2255
|
-
split_table:
|
2246
|
+
data_table: Table,
|
2247
|
+
fields: dict[str, Any],
|
2248
|
+
string_fields: dict[str, Any] | None = None,
|
2249
|
+
split_table: bool | None = False,
|
2256
2250
|
) -> CustomChart:
|
2257
2251
|
"""Create a custom plot on a table.
|
2258
2252
|
|
@@ -2264,6 +2258,8 @@ class Run:
|
|
2264
2258
|
visualization needs
|
2265
2259
|
string_fields: a dict that provides values for any string constants
|
2266
2260
|
the custom visualization needs
|
2261
|
+
split_table: a boolean that indicates whether the table should be in
|
2262
|
+
a separate section in the UI
|
2267
2263
|
"""
|
2268
2264
|
return custom_chart(
|
2269
2265
|
vega_spec_name, data_table, fields, string_fields or {}, split_table
|
@@ -2290,6 +2286,8 @@ class Run:
|
|
2290
2286
|
define_metric=self.define_metric,
|
2291
2287
|
plot_table=self.plot_table,
|
2292
2288
|
alert=self.alert,
|
2289
|
+
watch=self.watch,
|
2290
|
+
unwatch=self.unwatch,
|
2293
2291
|
mark_preempting=self.mark_preempting,
|
2294
2292
|
log_model=self.log_model,
|
2295
2293
|
use_model=self.use_model,
|
@@ -2298,9 +2296,9 @@ class Run:
|
|
2298
2296
|
|
2299
2297
|
def _redirect(
|
2300
2298
|
self,
|
2301
|
-
stdout_slave_fd:
|
2302
|
-
stderr_slave_fd:
|
2303
|
-
console:
|
2299
|
+
stdout_slave_fd: int | None,
|
2300
|
+
stderr_slave_fd: int | None,
|
2301
|
+
console: str | None = None,
|
2304
2302
|
) -> None:
|
2305
2303
|
if console is None:
|
2306
2304
|
console = self._settings.console
|
@@ -2415,7 +2413,7 @@ class Run:
|
|
2415
2413
|
self._err_redir.uninstall()
|
2416
2414
|
logger.info("restore done")
|
2417
2415
|
|
2418
|
-
def _atexit_cleanup(self, exit_code:
|
2416
|
+
def _atexit_cleanup(self, exit_code: int | None = None) -> None:
|
2419
2417
|
if self._backend is None:
|
2420
2418
|
logger.warning("process exited without backend configured")
|
2421
2419
|
return
|
@@ -2526,7 +2524,7 @@ class Run:
|
|
2526
2524
|
self,
|
2527
2525
|
) -> None:
|
2528
2526
|
def _telemetry_import_hook(
|
2529
|
-
run:
|
2527
|
+
run: Run,
|
2530
2528
|
module: Any,
|
2531
2529
|
) -> None:
|
2532
2530
|
with telemetry.context(run=run) as tel:
|
@@ -2569,7 +2567,7 @@ class Run:
|
|
2569
2567
|
|
2570
2568
|
StagedLaunchInputs().apply(self)
|
2571
2569
|
|
2572
|
-
def _make_job_source_reqs(self) ->
|
2570
|
+
def _make_job_source_reqs(self) -> tuple[list[str], dict[str, Any], dict[str, Any]]:
|
2573
2571
|
from wandb.util import working_set
|
2574
2572
|
|
2575
2573
|
installed_packages_list = sorted(f"{d.key}=={d.version}" for d in working_set())
|
@@ -2581,10 +2579,10 @@ class Run:
|
|
2581
2579
|
def _construct_job_artifact(
|
2582
2580
|
self,
|
2583
2581
|
name: str,
|
2584
|
-
source_dict:
|
2585
|
-
installed_packages_list:
|
2586
|
-
patch_path:
|
2587
|
-
) ->
|
2582
|
+
source_dict: JobSourceDict,
|
2583
|
+
installed_packages_list: list[str],
|
2584
|
+
patch_path: os.PathLike | None = None,
|
2585
|
+
) -> Artifact:
|
2588
2586
|
job_artifact = job_builder.JobArtifact(name)
|
2589
2587
|
if patch_path and os.path.exists(patch_path):
|
2590
2588
|
job_artifact.add_file(FilePathStr(str(patch_path)), "diff.patch")
|
@@ -2597,12 +2595,12 @@ class Run:
|
|
2597
2595
|
|
2598
2596
|
def _create_image_job(
|
2599
2597
|
self,
|
2600
|
-
input_types:
|
2601
|
-
output_types:
|
2602
|
-
installed_packages_list:
|
2603
|
-
docker_image_name:
|
2604
|
-
args:
|
2605
|
-
) ->
|
2598
|
+
input_types: dict[str, Any],
|
2599
|
+
output_types: dict[str, Any],
|
2600
|
+
installed_packages_list: list[str],
|
2601
|
+
docker_image_name: str | None = None,
|
2602
|
+
args: list[str] | None = None,
|
2603
|
+
) -> Artifact | None:
|
2606
2604
|
docker_image_name = docker_image_name or os.getenv("WANDB_DOCKER")
|
2607
2605
|
|
2608
2606
|
if not docker_image_name:
|
@@ -2625,7 +2623,7 @@ class Run:
|
|
2625
2623
|
return job_artifact
|
2626
2624
|
|
2627
2625
|
def _log_job_artifact_with_image(
|
2628
|
-
self, docker_image_name: str, args:
|
2626
|
+
self, docker_image_name: str, args: list[str] | None = None
|
2629
2627
|
) -> Artifact:
|
2630
2628
|
packages, in_types, out_types = self._make_job_source_reqs()
|
2631
2629
|
job_artifact = self._create_image_job(
|
@@ -2654,16 +2652,20 @@ class Run:
|
|
2654
2652
|
handle = self._backend.interface.deliver_poll_exit()
|
2655
2653
|
probe_handle.set_mailbox_handle(handle)
|
2656
2654
|
|
2657
|
-
def _on_progress_exit(
|
2655
|
+
def _on_progress_exit(
|
2656
|
+
self,
|
2657
|
+
progress_printer: progress.ProgressPrinter,
|
2658
|
+
progress_handle: MailboxProgress,
|
2659
|
+
) -> None:
|
2658
2660
|
probe_handles = progress_handle.get_probe_handles()
|
2659
|
-
|
2661
|
+
if not probe_handles or len(probe_handles) != 1:
|
2662
|
+
return
|
2660
2663
|
|
2661
2664
|
result = probe_handles[0].get_probe_result()
|
2662
2665
|
if not result:
|
2663
2666
|
return
|
2664
|
-
|
2665
|
-
|
2666
|
-
)
|
2667
|
+
|
2668
|
+
progress_printer.update([result.response.poll_exit_response])
|
2667
2669
|
|
2668
2670
|
def _on_finish(self) -> None:
|
2669
2671
|
trigger.call("on_finished")
|
@@ -2678,16 +2680,28 @@ class Run:
|
|
2678
2680
|
exit_handle = self._backend.interface.deliver_exit(self._exit_code)
|
2679
2681
|
exit_handle.add_probe(on_probe=self._on_probe_exit)
|
2680
2682
|
|
2681
|
-
|
2682
|
-
|
2683
|
+
with progress.progress_printer(
|
2684
|
+
self._printer,
|
2685
|
+
self._settings,
|
2686
|
+
) as progress_printer:
|
2687
|
+
# Wait for the run to complete.
|
2688
|
+
_ = exit_handle.wait(
|
2689
|
+
timeout=-1,
|
2690
|
+
on_progress=functools.partial(
|
2691
|
+
self._on_progress_exit,
|
2692
|
+
progress_printer,
|
2693
|
+
),
|
2694
|
+
)
|
2683
2695
|
|
2696
|
+
# Print some final statistics.
|
2684
2697
|
poll_exit_handle = self._backend.interface.deliver_poll_exit()
|
2685
|
-
# wait for them, it's ok to do this serially but this can be improved
|
2686
2698
|
result = poll_exit_handle.wait(timeout=-1)
|
2687
2699
|
assert result
|
2688
|
-
|
2689
|
-
|
2700
|
+
progress.print_sync_dedupe_stats(
|
2701
|
+
self._printer,
|
2702
|
+
result.response.poll_exit_response,
|
2690
2703
|
)
|
2704
|
+
|
2691
2705
|
self._poll_exit_response = result.response.poll_exit_response
|
2692
2706
|
internal_messages_handle = self._backend.interface.deliver_internal_messages()
|
2693
2707
|
result = internal_messages_handle.wait(timeout=-1)
|
@@ -2728,12 +2742,12 @@ class Run:
|
|
2728
2742
|
def define_metric(
|
2729
2743
|
self,
|
2730
2744
|
name: str,
|
2731
|
-
step_metric:
|
2732
|
-
step_sync:
|
2733
|
-
hidden:
|
2734
|
-
summary:
|
2735
|
-
goal:
|
2736
|
-
overwrite:
|
2745
|
+
step_metric: str | wandb_metric.Metric | None = None,
|
2746
|
+
step_sync: bool | None = None,
|
2747
|
+
hidden: bool | None = None,
|
2748
|
+
summary: str | None = None,
|
2749
|
+
goal: str | None = None,
|
2750
|
+
overwrite: bool | None = None,
|
2737
2751
|
) -> wandb_metric.Metric:
|
2738
2752
|
"""Customize metrics logged with `wandb.log()`.
|
2739
2753
|
|
@@ -2789,12 +2803,12 @@ class Run:
|
|
2789
2803
|
def _define_metric(
|
2790
2804
|
self,
|
2791
2805
|
name: str,
|
2792
|
-
step_metric:
|
2793
|
-
step_sync:
|
2794
|
-
hidden:
|
2795
|
-
summary:
|
2796
|
-
goal:
|
2797
|
-
overwrite:
|
2806
|
+
step_metric: str | wandb_metric.Metric | None = None,
|
2807
|
+
step_sync: bool | None = None,
|
2808
|
+
hidden: bool | None = None,
|
2809
|
+
summary: str | None = None,
|
2810
|
+
goal: str | None = None,
|
2811
|
+
overwrite: bool | None = None,
|
2798
2812
|
) -> wandb_metric.Metric:
|
2799
2813
|
if not name:
|
2800
2814
|
raise wandb.Error("define_metric() requires non-empty name argument")
|
@@ -2820,7 +2834,7 @@ class Run:
|
|
2820
2834
|
raise wandb.Error(
|
2821
2835
|
f"Unhandled define_metric() arg: name (glob suffixes only): {name}"
|
2822
2836
|
)
|
2823
|
-
summary_ops:
|
2837
|
+
summary_ops: Sequence[str] | None = None
|
2824
2838
|
if summary:
|
2825
2839
|
summary_items = [s.lower() for s in summary.split(",")]
|
2826
2840
|
summary_ops = []
|
@@ -2833,7 +2847,7 @@ class Run:
|
|
2833
2847
|
with telemetry.context(run=self) as tel:
|
2834
2848
|
tel.feature.metric_summary = True
|
2835
2849
|
# TODO: deprecate goal
|
2836
|
-
goal_cleaned:
|
2850
|
+
goal_cleaned: str | None = None
|
2837
2851
|
if goal is not None:
|
2838
2852
|
goal_cleaned = goal[:3].lower()
|
2839
2853
|
valid_goal = {"min", "max"}
|
@@ -2864,26 +2878,57 @@ class Run:
|
|
2864
2878
|
m._commit()
|
2865
2879
|
return m
|
2866
2880
|
|
2867
|
-
# TODO(jhr): annotate this
|
2868
2881
|
@_run_decorator._attach
|
2869
|
-
def watch(
|
2882
|
+
def watch(
|
2870
2883
|
self,
|
2871
|
-
models,
|
2872
|
-
criterion=None,
|
2873
|
-
log="gradients",
|
2874
|
-
log_freq=
|
2875
|
-
idx=None,
|
2876
|
-
log_graph=False,
|
2884
|
+
models: torch.nn.Module | Sequence[torch.nn.Module],
|
2885
|
+
criterion: torch.F | None = None,
|
2886
|
+
log: Literal["gradients", "parameters", "all"] | None = "gradients",
|
2887
|
+
log_freq: int = 1000,
|
2888
|
+
idx: int | None = None,
|
2889
|
+
log_graph: bool = False,
|
2877
2890
|
) -> None:
|
2878
|
-
|
2891
|
+
"""Hooks into the given PyTorch model(s) to monitor gradients and the model's computational graph.
|
2892
|
+
|
2893
|
+
This function can track parameters, gradients, or both during training. It should be
|
2894
|
+
extended to support arbitrary machine learning models in the future.
|
2895
|
+
|
2896
|
+
Args:
|
2897
|
+
models (Union[torch.nn.Module, Sequence[torch.nn.Module]]):
|
2898
|
+
A single model or a sequence of models to be monitored.
|
2899
|
+
criterion (Optional[torch.F]):
|
2900
|
+
The loss function being optimized (optional).
|
2901
|
+
log (Optional[Literal["gradients", "parameters", "all"]]):
|
2902
|
+
Specifies whether to log "gradients", "parameters", or "all".
|
2903
|
+
Set to None to disable logging. (default="gradients")
|
2904
|
+
log_freq (int):
|
2905
|
+
Frequency (in batches) to log gradients and parameters. (default=1000)
|
2906
|
+
idx (Optional[int]):
|
2907
|
+
Index used when tracking multiple models with `wandb.watch`. (default=None)
|
2908
|
+
log_graph (bool):
|
2909
|
+
Whether to log the model's computational graph. (default=False)
|
2910
|
+
|
2911
|
+
Raises:
|
2912
|
+
ValueError:
|
2913
|
+
If `wandb.init` has not been called or if any of the models are not instances
|
2914
|
+
of `torch.nn.Module`.
|
2915
|
+
"""
|
2916
|
+
wandb.sdk._watch(self, models, criterion, log, log_freq, idx, log_graph)
|
2879
2917
|
|
2880
|
-
# TODO(jhr): annotate this
|
2881
2918
|
@_run_decorator._attach
|
2882
|
-
def unwatch(
|
2883
|
-
|
2919
|
+
def unwatch(
|
2920
|
+
self, models: torch.nn.Module | Sequence[torch.nn.Module] | None = None
|
2921
|
+
) -> None:
|
2922
|
+
"""Remove pytorch model topology, gradient and parameter hooks.
|
2923
|
+
|
2924
|
+
Args:
|
2925
|
+
models (torch.nn.Module | Sequence[torch.nn.Module]):
|
2926
|
+
Optional list of pytorch models that have had watch called on them
|
2927
|
+
"""
|
2928
|
+
wandb.sdk._unwatch(self, models=models)
|
2884
2929
|
|
2885
2930
|
# TODO(kdg): remove all artifact swapping logic
|
2886
|
-
def _swap_artifact_name(self, artifact_name: str, use_as:
|
2931
|
+
def _swap_artifact_name(self, artifact_name: str, use_as: str | None) -> str:
|
2887
2932
|
artifact_key_string = use_as or artifact_name
|
2888
2933
|
replacement_artifact_info = self._launch_artifact_mapping.get(
|
2889
2934
|
artifact_key_string
|
@@ -2926,7 +2971,7 @@ class Run:
|
|
2926
2971
|
self,
|
2927
2972
|
artifact: Artifact,
|
2928
2973
|
target_path: str,
|
2929
|
-
aliases:
|
2974
|
+
aliases: list[str] | None = None,
|
2930
2975
|
) -> None:
|
2931
2976
|
"""Link the given artifact to a portfolio (a promoted collection of artifacts).
|
2932
2977
|
|
@@ -2961,6 +3006,12 @@ class Run:
|
|
2961
3006
|
# Wait until the artifact is committed before trying to link it.
|
2962
3007
|
artifact.wait()
|
2963
3008
|
|
3009
|
+
organization = ""
|
3010
|
+
if is_artifact_registry_project(project):
|
3011
|
+
organization = entity
|
3012
|
+
# In a Registry linking, the entity is used to fetch the organization of the artifact
|
3013
|
+
# therefore the source artifact's entity is passed to the backend
|
3014
|
+
entity = artifact._source_entity
|
2964
3015
|
handle = self._backend.interface.deliver_link_artifact(
|
2965
3016
|
self,
|
2966
3017
|
artifact,
|
@@ -2968,6 +3019,7 @@ class Run:
|
|
2968
3019
|
aliases,
|
2969
3020
|
entity,
|
2970
3021
|
project,
|
3022
|
+
organization,
|
2971
3023
|
)
|
2972
3024
|
if artifact._ttl_duration_seconds is not None:
|
2973
3025
|
wandb.termwarn(
|
@@ -2985,10 +3037,10 @@ class Run:
|
|
2985
3037
|
@_run_decorator._attach
|
2986
3038
|
def use_artifact(
|
2987
3039
|
self,
|
2988
|
-
artifact_or_name:
|
2989
|
-
type:
|
2990
|
-
aliases:
|
2991
|
-
use_as:
|
3040
|
+
artifact_or_name: str | Artifact,
|
3041
|
+
type: str | None = None,
|
3042
|
+
aliases: list[str] | None = None,
|
3043
|
+
use_as: str | None = None,
|
2992
3044
|
) -> Artifact:
|
2993
3045
|
"""Declare an artifact as an input to a run.
|
2994
3046
|
|
@@ -2996,8 +3048,9 @@ class Run:
|
|
2996
3048
|
|
2997
3049
|
Arguments:
|
2998
3050
|
artifact_or_name: (str or Artifact) An artifact name.
|
2999
|
-
May be prefixed with entity/project/.
|
3000
|
-
|
3051
|
+
May be prefixed with project/ or entity/project/.
|
3052
|
+
If no entity is specified in the name, the Run or API setting's entity is used.
|
3053
|
+
Valid names can be in the following forms:
|
3001
3054
|
- name:version
|
3002
3055
|
- name:alias
|
3003
3056
|
You can also pass an Artifact object created by calling `wandb.Artifact`
|
@@ -3094,11 +3147,11 @@ class Run:
|
|
3094
3147
|
@_run_decorator._attach
|
3095
3148
|
def log_artifact(
|
3096
3149
|
self,
|
3097
|
-
artifact_or_path:
|
3098
|
-
name:
|
3099
|
-
type:
|
3100
|
-
aliases:
|
3101
|
-
tags:
|
3150
|
+
artifact_or_path: Artifact | StrPath,
|
3151
|
+
name: str | None = None,
|
3152
|
+
type: str | None = None,
|
3153
|
+
aliases: list[str] | None = None,
|
3154
|
+
tags: list[str] | None = None,
|
3102
3155
|
) -> Artifact:
|
3103
3156
|
"""Declare an artifact as an output of a run.
|
3104
3157
|
|
@@ -3136,11 +3189,11 @@ class Run:
|
|
3136
3189
|
@_run_decorator._attach
|
3137
3190
|
def upsert_artifact(
|
3138
3191
|
self,
|
3139
|
-
artifact_or_path:
|
3140
|
-
name:
|
3141
|
-
type:
|
3142
|
-
aliases:
|
3143
|
-
distributed_id:
|
3192
|
+
artifact_or_path: Artifact | str,
|
3193
|
+
name: str | None = None,
|
3194
|
+
type: str | None = None,
|
3195
|
+
aliases: list[str] | None = None,
|
3196
|
+
distributed_id: str | None = None,
|
3144
3197
|
) -> Artifact:
|
3145
3198
|
"""Declare (or append to) a non-finalized artifact as output of a run.
|
3146
3199
|
|
@@ -3190,11 +3243,11 @@ class Run:
|
|
3190
3243
|
@_run_decorator._attach
|
3191
3244
|
def finish_artifact(
|
3192
3245
|
self,
|
3193
|
-
artifact_or_path:
|
3194
|
-
name:
|
3195
|
-
type:
|
3196
|
-
aliases:
|
3197
|
-
distributed_id:
|
3246
|
+
artifact_or_path: Artifact | str,
|
3247
|
+
name: str | None = None,
|
3248
|
+
type: str | None = None,
|
3249
|
+
aliases: list[str] | None = None,
|
3250
|
+
distributed_id: str | None = None,
|
3198
3251
|
) -> Artifact:
|
3199
3252
|
"""Finishes a non-finalized artifact as output of a run.
|
3200
3253
|
|
@@ -3242,12 +3295,12 @@ class Run:
|
|
3242
3295
|
|
3243
3296
|
def _log_artifact(
|
3244
3297
|
self,
|
3245
|
-
artifact_or_path:
|
3246
|
-
name:
|
3247
|
-
type:
|
3248
|
-
aliases:
|
3249
|
-
tags:
|
3250
|
-
distributed_id:
|
3298
|
+
artifact_or_path: Artifact | StrPath,
|
3299
|
+
name: str | None = None,
|
3300
|
+
type: str | None = None,
|
3301
|
+
aliases: list[str] | None = None,
|
3302
|
+
tags: list[str] | None = None,
|
3303
|
+
distributed_id: str | None = None,
|
3251
3304
|
finalize: bool = True,
|
3252
3305
|
is_user_created: bool = False,
|
3253
3306
|
use_after_commit: bool = False,
|
@@ -3308,7 +3361,7 @@ class Run:
|
|
3308
3361
|
)
|
3309
3362
|
return artifact
|
3310
3363
|
|
3311
|
-
def _public_api(self, overrides:
|
3364
|
+
def _public_api(self, overrides: dict[str, str] | None = None) -> PublicApi:
|
3312
3365
|
overrides = {"run": self._run_id}
|
3313
3366
|
if not (self._settings._offline or self._run_obj is None):
|
3314
3367
|
overrides["entity"] = self._run_obj.entity
|
@@ -3349,11 +3402,11 @@ class Run:
|
|
3349
3402
|
|
3350
3403
|
def _prepare_artifact(
|
3351
3404
|
self,
|
3352
|
-
artifact_or_path:
|
3353
|
-
name:
|
3354
|
-
type:
|
3355
|
-
aliases:
|
3356
|
-
) ->
|
3405
|
+
artifact_or_path: Artifact | StrPath,
|
3406
|
+
name: str | None = None,
|
3407
|
+
type: str | None = None,
|
3408
|
+
aliases: list[str] | None = None,
|
3409
|
+
) -> tuple[Artifact, list[str]]:
|
3357
3410
|
if isinstance(artifact_or_path, (str, os.PathLike)):
|
3358
3411
|
name = name or f"run-{self._run_id}-{os.path.basename(artifact_or_path)}"
|
3359
3412
|
artifact = wandb.Artifact(name, type or "unspecified")
|
@@ -3384,8 +3437,8 @@ class Run:
|
|
3384
3437
|
def log_model(
|
3385
3438
|
self,
|
3386
3439
|
path: StrPath,
|
3387
|
-
name:
|
3388
|
-
aliases:
|
3440
|
+
name: str | None = None,
|
3441
|
+
aliases: list[str] | None = None,
|
3389
3442
|
) -> None:
|
3390
3443
|
"""Logs a model artifact containing the contents inside the 'path' to a run and marks it as an output to this run.
|
3391
3444
|
|
@@ -3489,8 +3542,8 @@ class Run:
|
|
3489
3542
|
self,
|
3490
3543
|
path: StrPath,
|
3491
3544
|
registered_model_name: str,
|
3492
|
-
name:
|
3493
|
-
aliases:
|
3545
|
+
name: str | None = None,
|
3546
|
+
aliases: list[str] | None = None,
|
3494
3547
|
) -> None:
|
3495
3548
|
"""Log a model artifact version and link it to a registered model in the model registry.
|
3496
3549
|
|
@@ -3583,8 +3636,8 @@ class Run:
|
|
3583
3636
|
self,
|
3584
3637
|
title: str,
|
3585
3638
|
text: str,
|
3586
|
-
level:
|
3587
|
-
wait_duration:
|
3639
|
+
level: str | AlertLevel | None = None,
|
3640
|
+
wait_duration: int | float | timedelta | None = None,
|
3588
3641
|
) -> None:
|
3589
3642
|
"""Launch an alert with the given title and text.
|
3590
3643
|
|
@@ -3612,12 +3665,12 @@ class Run:
|
|
3612
3665
|
if self._backend and self._backend.interface:
|
3613
3666
|
self._backend.interface.publish_alert(title, text, level_str, wait_duration)
|
3614
3667
|
|
3615
|
-
def __enter__(self) ->
|
3668
|
+
def __enter__(self) -> Run:
|
3616
3669
|
return self
|
3617
3670
|
|
3618
3671
|
def __exit__(
|
3619
3672
|
self,
|
3620
|
-
exc_type:
|
3673
|
+
exc_type: type[BaseException],
|
3621
3674
|
exc_val: BaseException,
|
3622
3675
|
exc_tb: TracebackType,
|
3623
3676
|
) -> bool:
|
@@ -3641,7 +3694,7 @@ class Run:
|
|
3641
3694
|
@property
|
3642
3695
|
@_run_decorator._noop_on_finish()
|
3643
3696
|
@_run_decorator._attach
|
3644
|
-
def _system_metrics(self) ->
|
3697
|
+
def _system_metrics(self) -> dict[str, list[tuple[datetime, float]]]:
|
3645
3698
|
"""Returns a dictionary of system metrics.
|
3646
3699
|
|
3647
3700
|
Returns:
|
@@ -3650,7 +3703,7 @@ class Run:
|
|
3650
3703
|
|
3651
3704
|
def pb_to_dict(
|
3652
3705
|
system_metrics_pb: wandb.proto.wandb_internal_pb2.GetSystemMetricsResponse,
|
3653
|
-
) ->
|
3706
|
+
) -> dict[str, list[tuple[datetime, float]]]:
|
3654
3707
|
res = {}
|
3655
3708
|
|
3656
3709
|
for metric, records in system_metrics_pb.system_metrics.items():
|
@@ -3691,8 +3744,8 @@ class Run:
|
|
3691
3744
|
@staticmethod
|
3692
3745
|
def _header(
|
3693
3746
|
*,
|
3694
|
-
settings:
|
3695
|
-
printer:
|
3747
|
+
settings: Settings,
|
3748
|
+
printer: printer.Printer,
|
3696
3749
|
) -> None:
|
3697
3750
|
Run._header_wandb_version_info(settings=settings, printer=printer)
|
3698
3751
|
Run._header_sync_info(settings=settings, printer=printer)
|
@@ -3701,22 +3754,20 @@ class Run:
|
|
3701
3754
|
@staticmethod
|
3702
3755
|
def _header_wandb_version_info(
|
3703
3756
|
*,
|
3704
|
-
settings:
|
3705
|
-
printer:
|
3757
|
+
settings: Settings,
|
3758
|
+
printer: printer.Printer,
|
3706
3759
|
) -> None:
|
3707
3760
|
if settings.quiet or settings.silent:
|
3708
3761
|
return
|
3709
3762
|
|
3710
3763
|
# TODO: add this to a higher verbosity level
|
3711
|
-
printer.display(
|
3712
|
-
f"Tracking run with wandb version {wandb.__version__}", off=False
|
3713
|
-
)
|
3764
|
+
printer.display(f"Tracking run with wandb version {wandb.__version__}")
|
3714
3765
|
|
3715
3766
|
@staticmethod
|
3716
3767
|
def _header_sync_info(
|
3717
3768
|
*,
|
3718
|
-
settings:
|
3719
|
-
printer:
|
3769
|
+
settings: Settings,
|
3770
|
+
printer: printer.Printer,
|
3720
3771
|
) -> None:
|
3721
3772
|
if settings._offline:
|
3722
3773
|
printer.display(
|
@@ -3728,17 +3779,18 @@ class Run:
|
|
3728
3779
|
)
|
3729
3780
|
else:
|
3730
3781
|
info = [f"Run data is saved locally in {printer.files(settings.sync_dir)}"]
|
3731
|
-
if not printer.
|
3782
|
+
if not printer.supports_html:
|
3732
3783
|
info.append(
|
3733
3784
|
f"Run {printer.code('`wandb offline`')} to turn off syncing."
|
3734
3785
|
)
|
3735
|
-
|
3786
|
+
if not settings.quiet and not settings.silent:
|
3787
|
+
printer.display(info)
|
3736
3788
|
|
3737
3789
|
@staticmethod
|
3738
3790
|
def _header_run_info(
|
3739
3791
|
*,
|
3740
|
-
settings:
|
3741
|
-
printer:
|
3792
|
+
settings: Settings,
|
3793
|
+
printer: printer.Printer,
|
3742
3794
|
) -> None:
|
3743
3795
|
if settings._offline or settings.silent:
|
3744
3796
|
return
|
@@ -3756,7 +3808,7 @@ class Run:
|
|
3756
3808
|
if not run_name:
|
3757
3809
|
return
|
3758
3810
|
|
3759
|
-
if printer.
|
3811
|
+
if printer.supports_html:
|
3760
3812
|
if not wandb.jupyter.maybe_display(): # type: ignore
|
3761
3813
|
run_line = f"<strong>{printer.link(run_url, run_name)}</strong>"
|
3762
3814
|
project_line, sweep_line = "", ""
|
@@ -3775,10 +3827,8 @@ class Run:
|
|
3775
3827
|
[f"{run_state_str} {run_line} {project_line}", sweep_line],
|
3776
3828
|
)
|
3777
3829
|
|
3778
|
-
|
3779
|
-
printer.display(
|
3780
|
-
f"{run_state_str} {printer.name(run_name)}", off=not run_name
|
3781
|
-
)
|
3830
|
+
elif run_name:
|
3831
|
+
printer.display(f"{run_state_str} {printer.name(run_name)}")
|
3782
3832
|
|
3783
3833
|
if not settings.quiet:
|
3784
3834
|
# TODO: add verbosity levels and add this to higher levels
|
@@ -3794,11 +3844,13 @@ class Run:
|
|
3794
3844
|
)
|
3795
3845
|
|
3796
3846
|
# TODO(settings) use `wandb_settings` (if self.settings.anonymous == "true":)
|
3797
|
-
if Api().api.settings().get("anonymous") == "true":
|
3847
|
+
if run_name and Api().api.settings().get("anonymous") == "true":
|
3798
3848
|
printer.display(
|
3799
|
-
|
3849
|
+
(
|
3850
|
+
"Do NOT share these links with anyone."
|
3851
|
+
" They can be used to claim your runs."
|
3852
|
+
),
|
3800
3853
|
level="warn",
|
3801
|
-
off=not run_name,
|
3802
3854
|
)
|
3803
3855
|
|
3804
3856
|
# ------------------------------------------------------------------------------
|
@@ -3808,15 +3860,15 @@ class Run:
|
|
3808
3860
|
# with the service execution path that doesn't have access to the run instance
|
3809
3861
|
@staticmethod
|
3810
3862
|
def _footer(
|
3811
|
-
sampled_history:
|
3812
|
-
final_summary:
|
3813
|
-
poll_exit_response:
|
3814
|
-
internal_messages_response:
|
3815
|
-
reporter:
|
3816
|
-
quiet:
|
3863
|
+
sampled_history: SampledHistoryResponse | None = None,
|
3864
|
+
final_summary: GetSummaryResponse | None = None,
|
3865
|
+
poll_exit_response: PollExitResponse | None = None,
|
3866
|
+
internal_messages_response: InternalMessagesResponse | None = None,
|
3867
|
+
reporter: Reporter | None = None,
|
3868
|
+
quiet: bool | None = None,
|
3817
3869
|
*,
|
3818
|
-
settings:
|
3819
|
-
printer:
|
3870
|
+
settings: Settings,
|
3871
|
+
printer: printer.Printer,
|
3820
3872
|
) -> None:
|
3821
3873
|
Run._footer_history_summary_info(
|
3822
3874
|
history=sampled_history,
|
@@ -3848,177 +3900,51 @@ class Run:
|
|
3848
3900
|
reporter=reporter, quiet=quiet, settings=settings, printer=printer
|
3849
3901
|
)
|
3850
3902
|
|
3851
|
-
# fixme: Temporary hack until we move to rich which allows multiple spinners
|
3852
3903
|
@staticmethod
|
3853
|
-
def
|
3854
|
-
|
3855
|
-
|
3856
|
-
] = None,
|
3857
|
-
*,
|
3858
|
-
printer: Union["PrinterTerm", "PrinterJupyter"],
|
3859
|
-
) -> None:
|
3860
|
-
if not poll_exit_responses:
|
3861
|
-
return
|
3862
|
-
if isinstance(poll_exit_responses, PollExitResponse):
|
3863
|
-
Run._footer_single_run_file_pusher_status_info(
|
3864
|
-
poll_exit_responses, printer=printer
|
3865
|
-
)
|
3866
|
-
elif isinstance(poll_exit_responses, list):
|
3867
|
-
poll_exit_responses_list = poll_exit_responses
|
3868
|
-
assert all(
|
3869
|
-
response is None or isinstance(response, PollExitResponse)
|
3870
|
-
for response in poll_exit_responses_list
|
3871
|
-
)
|
3872
|
-
if len(poll_exit_responses_list) == 0:
|
3873
|
-
return
|
3874
|
-
elif len(poll_exit_responses_list) == 1:
|
3875
|
-
Run._footer_single_run_file_pusher_status_info(
|
3876
|
-
poll_exit_responses_list[0], printer=printer
|
3877
|
-
)
|
3878
|
-
else:
|
3879
|
-
Run._footer_multiple_runs_file_pusher_status_info(
|
3880
|
-
poll_exit_responses_list, printer=printer
|
3881
|
-
)
|
3882
|
-
else:
|
3883
|
-
logger.error(
|
3884
|
-
f"Got the type `{type(poll_exit_responses)}` for `poll_exit_responses`. "
|
3885
|
-
"Expected either None, PollExitResponse or a List[Union[PollExitResponse, None]]"
|
3886
|
-
)
|
3887
|
-
|
3888
|
-
@staticmethod
|
3889
|
-
def _footer_single_run_file_pusher_status_info(
|
3890
|
-
poll_exit_response: Optional[PollExitResponse] = None,
|
3904
|
+
def _footer_sync_info(
|
3905
|
+
poll_exit_response: PollExitResponse | None = None,
|
3906
|
+
quiet: bool | None = None,
|
3891
3907
|
*,
|
3892
|
-
|
3908
|
+
settings: Settings,
|
3909
|
+
printer: printer.Printer,
|
3893
3910
|
) -> None:
|
3894
|
-
|
3895
|
-
if not poll_exit_response:
|
3911
|
+
if settings.silent:
|
3896
3912
|
return
|
3897
3913
|
|
3898
|
-
|
3899
|
-
|
3900
|
-
megabyte = wandb.util.POW_2_BYTES[2][1]
|
3901
|
-
line = (
|
3902
|
-
f"{stats.uploaded_bytes / megabyte:.3f} MB"
|
3903
|
-
f" of {stats.total_bytes / megabyte:.3f} MB uploaded"
|
3904
|
-
)
|
3905
|
-
if stats.deduped_bytes > 0:
|
3906
|
-
line += f" ({stats.deduped_bytes / megabyte:.3f} MB deduped)"
|
3907
|
-
line += "\r"
|
3908
|
-
|
3909
|
-
if stats.total_bytes > 0:
|
3910
|
-
printer.progress_update(line, stats.uploaded_bytes / stats.total_bytes)
|
3911
|
-
else:
|
3912
|
-
printer.progress_update(line, 1.0)
|
3913
|
-
|
3914
|
-
if poll_exit_response.done:
|
3915
|
-
printer.progress_close()
|
3916
|
-
|
3917
|
-
if stats.total_bytes > 0:
|
3918
|
-
dedupe_fraction = stats.deduped_bytes / float(stats.total_bytes)
|
3919
|
-
else:
|
3920
|
-
dedupe_fraction = 0
|
3921
|
-
|
3922
|
-
if stats.deduped_bytes > 0.01:
|
3914
|
+
if settings._offline:
|
3915
|
+
if not quiet and not settings.quiet:
|
3923
3916
|
printer.display(
|
3924
|
-
|
3917
|
+
[
|
3918
|
+
"You can sync this run to the cloud by running:",
|
3919
|
+
printer.code(f"wandb sync {settings.sync_dir}"),
|
3920
|
+
],
|
3925
3921
|
)
|
3926
|
-
|
3927
|
-
@staticmethod
|
3928
|
-
def _footer_multiple_runs_file_pusher_status_info(
|
3929
|
-
poll_exit_responses: List[Optional[PollExitResponse]],
|
3930
|
-
*,
|
3931
|
-
printer: Union["PrinterTerm", "PrinterJupyter"],
|
3932
|
-
) -> None:
|
3933
|
-
# todo: is this same as settings._offline?
|
3934
|
-
if not all(poll_exit_responses):
|
3935
3922
|
return
|
3936
3923
|
|
3937
|
-
|
3938
|
-
|
3939
|
-
|
3940
|
-
|
3941
|
-
response.file_counts.wandb_count,
|
3942
|
-
response.file_counts.media_count,
|
3943
|
-
response.file_counts.artifact_count,
|
3944
|
-
response.file_counts.other_count,
|
3945
|
-
]
|
3924
|
+
info = []
|
3925
|
+
if settings.run_name and settings.run_url:
|
3926
|
+
info.append(
|
3927
|
+
f"{printer.emoji('rocket')} View run {printer.name(settings.run_name)} at: {printer.link(settings.run_url)}"
|
3946
3928
|
)
|
3947
|
-
|
3948
|
-
|
3949
|
-
|
3950
|
-
uploaded = sum(
|
3951
|
-
response.pusher_stats.uploaded_bytes
|
3952
|
-
for response in poll_exit_responses
|
3953
|
-
if response is not None and response.pusher_stats is not None
|
3954
|
-
)
|
3955
|
-
total = sum(
|
3956
|
-
response.pusher_stats.total_bytes
|
3957
|
-
for response in poll_exit_responses
|
3958
|
-
if response is not None and response.pusher_stats is not None
|
3959
|
-
)
|
3960
|
-
|
3961
|
-
line = (
|
3962
|
-
f"Processing {len(poll_exit_responses)} runs with {total_files} files "
|
3963
|
-
f"({uploaded/megabyte :.2f} MB/{total/megabyte :.2f} MB)\r"
|
3964
|
-
)
|
3965
|
-
# line = "{}{:<{max_len}}\r".format(line, " ", max_len=(80 - len(line)))
|
3966
|
-
printer.progress_update(line) # type:ignore[call-arg]
|
3967
|
-
|
3968
|
-
done = all(
|
3969
|
-
[
|
3970
|
-
poll_exit_response.done
|
3971
|
-
for poll_exit_response in poll_exit_responses
|
3972
|
-
if poll_exit_response
|
3973
|
-
]
|
3974
|
-
)
|
3975
|
-
if done:
|
3976
|
-
printer.progress_close()
|
3977
|
-
|
3978
|
-
@staticmethod
|
3979
|
-
def _footer_sync_info(
|
3980
|
-
poll_exit_response: Optional[PollExitResponse] = None,
|
3981
|
-
quiet: Optional[bool] = None,
|
3982
|
-
*,
|
3983
|
-
settings: "Settings",
|
3984
|
-
printer: Union["PrinterTerm", "PrinterJupyter"],
|
3985
|
-
) -> None:
|
3986
|
-
if settings.silent:
|
3987
|
-
return
|
3988
|
-
|
3989
|
-
if settings._offline:
|
3990
|
-
printer.display(
|
3991
|
-
[
|
3992
|
-
"You can sync this run to the cloud by running:",
|
3993
|
-
printer.code(f"wandb sync {settings.sync_dir}"),
|
3994
|
-
],
|
3995
|
-
off=(quiet or settings.quiet),
|
3929
|
+
if settings.project_url:
|
3930
|
+
info.append(
|
3931
|
+
f"{printer.emoji('star')} View project at: {printer.link(settings.project_url)}"
|
3996
3932
|
)
|
3997
|
-
|
3998
|
-
info
|
3999
|
-
|
4000
|
-
|
4001
|
-
|
4002
|
-
)
|
4003
|
-
|
4004
|
-
|
4005
|
-
f"{printer.emoji('star')} View project at: {printer.link(settings.project_url)}"
|
4006
|
-
)
|
4007
|
-
if poll_exit_response and poll_exit_response.file_counts:
|
4008
|
-
logger.info("logging synced files")
|
4009
|
-
file_counts = poll_exit_response.file_counts
|
4010
|
-
info.append(
|
4011
|
-
f"Synced {file_counts.wandb_count} W&B file(s), {file_counts.media_count} media file(s), "
|
4012
|
-
f"{file_counts.artifact_count} artifact file(s) and {file_counts.other_count} other file(s)",
|
4013
|
-
)
|
4014
|
-
printer.display(info)
|
3933
|
+
if poll_exit_response and poll_exit_response.file_counts:
|
3934
|
+
logger.info("logging synced files")
|
3935
|
+
file_counts = poll_exit_response.file_counts
|
3936
|
+
info.append(
|
3937
|
+
f"Synced {file_counts.wandb_count} W&B file(s), {file_counts.media_count} media file(s), "
|
3938
|
+
f"{file_counts.artifact_count} artifact file(s) and {file_counts.other_count} other file(s)",
|
3939
|
+
)
|
3940
|
+
printer.display(info)
|
4015
3941
|
|
4016
3942
|
@staticmethod
|
4017
3943
|
def _footer_log_dir_info(
|
4018
|
-
quiet:
|
3944
|
+
quiet: bool | None = None,
|
4019
3945
|
*,
|
4020
|
-
settings:
|
4021
|
-
printer:
|
3946
|
+
settings: Settings,
|
3947
|
+
printer: printer.Printer,
|
4022
3948
|
) -> None:
|
4023
3949
|
if (quiet or settings.quiet) or settings.silent:
|
4024
3950
|
return
|
@@ -4032,12 +3958,12 @@ class Run:
|
|
4032
3958
|
|
4033
3959
|
@staticmethod
|
4034
3960
|
def _footer_history_summary_info(
|
4035
|
-
history:
|
4036
|
-
summary:
|
4037
|
-
quiet:
|
3961
|
+
history: SampledHistoryResponse | None = None,
|
3962
|
+
summary: GetSummaryResponse | None = None,
|
3963
|
+
quiet: bool | None = None,
|
4038
3964
|
*,
|
4039
|
-
settings:
|
4040
|
-
printer:
|
3965
|
+
settings: Settings,
|
3966
|
+
printer: printer.Printer,
|
4041
3967
|
) -> None:
|
4042
3968
|
if (quiet or settings.quiet) or settings.silent:
|
4043
3969
|
return
|
@@ -4103,11 +4029,11 @@ class Run:
|
|
4103
4029
|
|
4104
4030
|
@staticmethod
|
4105
4031
|
def _footer_internal_messages(
|
4106
|
-
internal_messages_response:
|
4107
|
-
quiet:
|
4032
|
+
internal_messages_response: InternalMessagesResponse | None = None,
|
4033
|
+
quiet: bool | None = None,
|
4108
4034
|
*,
|
4109
|
-
settings:
|
4110
|
-
printer:
|
4035
|
+
settings: Settings,
|
4036
|
+
printer: printer.Printer,
|
4111
4037
|
) -> None:
|
4112
4038
|
if (quiet or settings.quiet) or settings.silent:
|
4113
4039
|
return
|
@@ -4121,9 +4047,9 @@ class Run:
|
|
4121
4047
|
@staticmethod
|
4122
4048
|
def _footer_notify_wandb_core(
|
4123
4049
|
*,
|
4124
|
-
quiet:
|
4125
|
-
settings:
|
4126
|
-
printer:
|
4050
|
+
quiet: bool | None = None,
|
4051
|
+
settings: Settings,
|
4052
|
+
printer: printer.Printer,
|
4127
4053
|
) -> None:
|
4128
4054
|
"""Prints a message advertising the upcoming core release."""
|
4129
4055
|
if quiet or not settings._require_legacy_service:
|
@@ -4138,11 +4064,11 @@ class Run:
|
|
4138
4064
|
|
4139
4065
|
@staticmethod
|
4140
4066
|
def _footer_reporter_warn_err(
|
4141
|
-
reporter:
|
4142
|
-
quiet:
|
4067
|
+
reporter: Reporter | None = None,
|
4068
|
+
quiet: bool | None = None,
|
4143
4069
|
*,
|
4144
|
-
settings:
|
4145
|
-
printer:
|
4070
|
+
settings: Settings,
|
4071
|
+
printer: printer.Printer,
|
4146
4072
|
) -> None:
|
4147
4073
|
if (quiet or settings.quiet) or settings.silent:
|
4148
4074
|
return
|
@@ -4168,10 +4094,10 @@ class Run:
|
|
4168
4094
|
# We define this outside of the run context to support restoring before init
|
4169
4095
|
def restore(
|
4170
4096
|
name: str,
|
4171
|
-
run_path:
|
4097
|
+
run_path: str | None = None,
|
4172
4098
|
replace: bool = False,
|
4173
|
-
root:
|
4174
|
-
) ->
|
4099
|
+
root: str | None = None,
|
4100
|
+
) -> None | TextIO:
|
4175
4101
|
"""Download the specified file from cloud storage.
|
4176
4102
|
|
4177
4103
|
File is placed into the current directory or run directory.
|
@@ -4229,7 +4155,7 @@ except AttributeError:
|
|
4229
4155
|
pass
|
4230
4156
|
|
4231
4157
|
|
4232
|
-
def finish(exit_code:
|
4158
|
+
def finish(exit_code: int | None = None, quiet: bool | None = None) -> None:
|
4233
4159
|
"""Mark a run as finished, and finish uploading all data.
|
4234
4160
|
|
4235
4161
|
This is used when creating multiple runs in the same process.
|