wandb 0.19.9__py3-none-win32.whl → 0.19.10__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 -1
- wandb/__init__.pyi +4 -1
- wandb/_pydantic/__init__.py +14 -7
- wandb/_pydantic/base.py +44 -9
- wandb/_pydantic/utils.py +66 -0
- wandb/_pydantic/v1_compat.py +78 -56
- wandb/apis/public/__init__.py +2 -2
- wandb/apis/public/api.py +114 -2
- wandb/apis/public/artifacts.py +365 -673
- wandb/apis/public/automations.py +69 -0
- wandb/apis/public/integrations.py +168 -0
- wandb/apis/public/projects.py +29 -0
- wandb/apis/public/utils.py +107 -1
- wandb/automations/__init__.py +81 -0
- wandb/automations/_filters/__init__.py +40 -0
- wandb/automations/_filters/expressions.py +179 -0
- wandb/automations/_filters/operators.py +267 -0
- wandb/automations/_filters/run_metrics.py +183 -0
- wandb/automations/_generated/__init__.py +184 -0
- wandb/automations/_generated/create_filter_trigger.py +21 -0
- wandb/automations/_generated/create_generic_webhook_integration.py +43 -0
- wandb/automations/_generated/delete_trigger.py +19 -0
- wandb/automations/_generated/enums.py +33 -0
- wandb/automations/_generated/fragments.py +343 -0
- wandb/automations/_generated/generic_webhook_integrations_by_entity.py +22 -0
- wandb/automations/_generated/get_triggers.py +24 -0
- wandb/automations/_generated/get_triggers_by_entity.py +24 -0
- wandb/automations/_generated/input_types.py +104 -0
- wandb/automations/_generated/integrations_by_entity.py +22 -0
- wandb/automations/_generated/operations.py +710 -0
- wandb/automations/_generated/slack_integrations_by_entity.py +22 -0
- wandb/automations/_generated/update_filter_trigger.py +21 -0
- wandb/automations/_utils.py +123 -0
- wandb/automations/_validators.py +73 -0
- wandb/automations/actions.py +205 -0
- wandb/automations/automations.py +109 -0
- wandb/automations/events.py +235 -0
- wandb/automations/integrations.py +26 -0
- wandb/automations/scopes.py +76 -0
- wandb/beta/workflows.py +9 -10
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +3 -3
- wandb/integration/keras/keras.py +2 -1
- wandb/integration/langchain/wandb_tracer.py +2 -1
- wandb/jupyter.py +137 -118
- wandb/old/summary.py +0 -2
- wandb/proto/v3/wandb_internal_pb2.py +293 -292
- 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 +292 -292
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v5/wandb_internal_pb2.py +292 -292
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v6/wandb_base_pb2.py +41 -0
- wandb/proto/v6/wandb_internal_pb2.py +393 -0
- wandb/proto/v6/wandb_server_pb2.py +78 -0
- wandb/proto/v6/wandb_settings_pb2.py +58 -0
- wandb/proto/v6/wandb_telemetry_pb2.py +52 -0
- wandb/proto/wandb_base_pb2.py +2 -0
- wandb/proto/wandb_deprecated.py +8 -0
- wandb/proto/wandb_internal_pb2.py +3 -1
- 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/_generated/__init__.py +248 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_version_files.py +36 -0
- wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +36 -0
- wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +25 -0
- wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +35 -0
- wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +35 -0
- wandb/sdk/artifacts/_generated/enums.py +17 -0
- wandb/sdk/artifacts/_generated/fragments.py +186 -0
- wandb/sdk/artifacts/_generated/input_types.py +16 -0
- wandb/sdk/artifacts/_generated/move_artifact_collection.py +35 -0
- wandb/sdk/artifacts/_generated/operations.py +510 -0
- wandb/sdk/artifacts/_generated/project_artifact_collection.py +101 -0
- wandb/sdk/artifacts/_generated/project_artifact_collections.py +33 -0
- wandb/sdk/artifacts/_generated/project_artifact_type.py +24 -0
- wandb/sdk/artifacts/_generated/project_artifact_types.py +24 -0
- wandb/sdk/artifacts/_generated/project_artifacts.py +42 -0
- wandb/sdk/artifacts/_generated/run_input_artifacts.py +51 -0
- wandb/sdk/artifacts/_generated/run_output_artifacts.py +51 -0
- wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +35 -0
- wandb/sdk/artifacts/_generated/update_artifact_sequence.py +35 -0
- wandb/sdk/artifacts/_graphql_fragments.py +56 -79
- wandb/sdk/artifacts/artifact.py +40 -13
- wandb/sdk/artifacts/artifact_manifest_entry.py +2 -1
- wandb/sdk/artifacts/storage_handlers/azure_handler.py +1 -0
- wandb/sdk/data_types/base_types/media.py +2 -3
- wandb/sdk/data_types/base_types/wb_value.py +34 -11
- wandb/sdk/data_types/html.py +36 -9
- wandb/sdk/data_types/image.py +12 -12
- wandb/sdk/data_types/table.py +5 -0
- wandb/sdk/data_types/trace_tree.py +2 -0
- wandb/sdk/data_types/utils.py +1 -1
- wandb/sdk/data_types/video.py +14 -26
- wandb/sdk/interface/interface.py +2 -0
- wandb/sdk/internal/profiler.py +6 -5
- wandb/sdk/internal/run.py +13 -6
- wandb/sdk/lib/apikey.py +25 -4
- wandb/sdk/lib/asyncio_compat.py +1 -1
- wandb/sdk/lib/deprecate.py +13 -22
- wandb/sdk/lib/disabled.py +2 -1
- wandb/sdk/lib/printer.py +37 -8
- wandb/sdk/lib/printer_asyncio.py +46 -0
- wandb/sdk/lib/redirect.py +10 -5
- wandb/sdk/service/server_sock.py +19 -14
- wandb/sdk/service/service.py +9 -7
- wandb/sdk/service/streams.py +5 -0
- wandb/sdk/verify/verify.py +6 -3
- wandb/sdk/wandb_init.py +185 -65
- wandb/sdk/wandb_login.py +13 -4
- wandb/sdk/wandb_run.py +382 -286
- wandb/sdk/wandb_settings.py +21 -3
- wandb/sdk/wandb_setup.py +49 -0
- wandb/util.py +29 -29
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/METADATA +5 -5
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/RECORD +125 -72
- wandb/_globals.py +0 -19
- wandb/sdk/internal/_generated/base.py +0 -226
- wandb/sdk/internal/_generated/typing_compat.py +0 -14
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/WHEEL +0 -0
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/entry_points.txt +0 -0
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_run.py
CHANGED
@@ -14,13 +14,26 @@ import sys
|
|
14
14
|
import threading
|
15
15
|
import time
|
16
16
|
import traceback
|
17
|
-
import warnings
|
18
17
|
from collections.abc import Mapping
|
19
18
|
from dataclasses import dataclass, field
|
20
19
|
from datetime import datetime, timedelta, timezone
|
21
20
|
from enum import IntEnum
|
22
21
|
from types import TracebackType
|
23
|
-
from typing import
|
22
|
+
from typing import (
|
23
|
+
TYPE_CHECKING,
|
24
|
+
Any,
|
25
|
+
Callable,
|
26
|
+
Literal,
|
27
|
+
NamedTuple,
|
28
|
+
Sequence,
|
29
|
+
TextIO,
|
30
|
+
TypeVar,
|
31
|
+
)
|
32
|
+
|
33
|
+
if sys.version_info < (3, 10):
|
34
|
+
from typing_extensions import Concatenate, ParamSpec
|
35
|
+
else:
|
36
|
+
from typing import Concatenate, ParamSpec
|
24
37
|
|
25
38
|
import requests
|
26
39
|
|
@@ -28,13 +41,13 @@ import wandb
|
|
28
41
|
import wandb.env
|
29
42
|
import wandb.util
|
30
43
|
from wandb import trigger
|
31
|
-
from wandb._globals import _datatypes_set_callback
|
32
44
|
from wandb.apis import internal, public
|
33
45
|
from wandb.apis.public import Api as PublicApi
|
34
46
|
from wandb.errors import CommError, UnsupportedError, UsageError
|
35
47
|
from wandb.errors.links import url_registry
|
36
48
|
from wandb.integration.torch import wandb_torch
|
37
49
|
from wandb.plot import CustomChart, Visualize
|
50
|
+
from wandb.proto.wandb_deprecated import Deprecated
|
38
51
|
from wandb.proto.wandb_internal_pb2 import (
|
39
52
|
MetadataRequest,
|
40
53
|
MetricRecord,
|
@@ -361,7 +374,13 @@ class RunStatusChecker:
|
|
361
374
|
self._internal_messages_thread.join()
|
362
375
|
|
363
376
|
|
364
|
-
|
377
|
+
_P = ParamSpec("_P")
|
378
|
+
_T = TypeVar("_T")
|
379
|
+
|
380
|
+
|
381
|
+
def _log_to_run(
|
382
|
+
func: Callable[Concatenate[Run, _P], _T],
|
383
|
+
) -> Callable[Concatenate[Run, _P], _T]:
|
365
384
|
"""Decorate a Run method to set the run ID in the logging context.
|
366
385
|
|
367
386
|
Any logs during the execution of the method go to the run's log file
|
@@ -375,7 +394,7 @@ def _log_to_run(func: Callable) -> Callable:
|
|
375
394
|
"""
|
376
395
|
|
377
396
|
@functools.wraps(func)
|
378
|
-
def wrapper(self: Run, *args, **kwargs) ->
|
397
|
+
def wrapper(self: Run, *args, **kwargs) -> _T:
|
379
398
|
# In "attach" usage, many properties of the Run are not initially
|
380
399
|
# populated.
|
381
400
|
if hasattr(self, "_settings"):
|
@@ -389,100 +408,118 @@ def _log_to_run(func: Callable) -> Callable:
|
|
389
408
|
return wrapper
|
390
409
|
|
391
410
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
@functools.wraps(func)
|
400
|
-
def wrapper(self: type[Run], *args: Any, **kwargs: Any) -> Any:
|
401
|
-
# * `_attach_id` is only assigned in service hence for all non-service cases
|
402
|
-
# it will be a passthrough.
|
403
|
-
# * `_attach_pid` is only assigned in _init (using _attach_pid guarantees single attach):
|
404
|
-
# - for non-fork case the object is shared through pickling so will be None.
|
405
|
-
# - for fork case the new process share mem space hence the value would be of parent process.
|
406
|
-
if (
|
407
|
-
getattr(self, "_attach_id", None)
|
408
|
-
and getattr(self, "_attach_pid", None) != os.getpid()
|
409
|
-
):
|
410
|
-
if cls._is_attaching:
|
411
|
-
message = (
|
412
|
-
f"Trying to attach `{func.__name__}` "
|
413
|
-
f"while in the middle of attaching `{cls._is_attaching}`"
|
414
|
-
)
|
415
|
-
raise RuntimeError(message)
|
416
|
-
cls._is_attaching = func.__name__
|
417
|
-
try:
|
418
|
-
wandb._attach(run=self) # type: ignore
|
419
|
-
except Exception as e:
|
420
|
-
# In case the attach fails we will raise the exception that caused the issue.
|
421
|
-
# This exception should be caught and fail the execution of the program.
|
422
|
-
cls._is_attaching = ""
|
423
|
-
raise e
|
424
|
-
cls._is_attaching = ""
|
425
|
-
return func(self, *args, **kwargs)
|
411
|
+
_is_attaching: str = ""
|
412
|
+
|
413
|
+
|
414
|
+
def _attach(
|
415
|
+
func: Callable[Concatenate[Run, _P], _T],
|
416
|
+
) -> Callable[Concatenate[Run, _P], _T]:
|
417
|
+
"""Decorate a Run method to auto-attach when in a new process.
|
426
418
|
|
427
|
-
|
419
|
+
When in a forked process or using a pickled Run instance, this automatically
|
420
|
+
connects to the service process to "attach" to the existing run.
|
421
|
+
"""
|
428
422
|
|
429
|
-
@
|
430
|
-
def
|
431
|
-
|
432
|
-
@functools.wraps(func)
|
433
|
-
def wrapper_fn(self: type[Run], *args: Any, **kwargs: Any) -> Any:
|
434
|
-
if not getattr(self, "_is_finished", False):
|
435
|
-
return func(self, *args, **kwargs)
|
423
|
+
@functools.wraps(func)
|
424
|
+
def wrapper(self: Run, *args, **kwargs) -> _T:
|
425
|
+
global _is_attaching
|
436
426
|
|
437
|
-
|
438
|
-
|
439
|
-
|
427
|
+
# The _attach_id attribute is only None when running in the "disable
|
428
|
+
# service" mode.
|
429
|
+
#
|
430
|
+
# Since it is set early in `__init__` and included in the run's pickled
|
431
|
+
# state, the attribute always exists.
|
432
|
+
is_using_service = self._attach_id is not None
|
433
|
+
|
434
|
+
# The _attach_pid attribute is not pickled, so it might not exist.
|
435
|
+
# It is set when the run is initialized.
|
436
|
+
attach_pid = getattr(self, "_attach_pid", None)
|
437
|
+
|
438
|
+
if is_using_service and attach_pid != os.getpid():
|
439
|
+
if _is_attaching:
|
440
|
+
raise RuntimeError(
|
441
|
+
f"Trying to attach `{func.__name__}`"
|
442
|
+
f" while in the middle of attaching `{_is_attaching}`"
|
440
443
|
)
|
441
|
-
resolved_message = message or default_message
|
442
|
-
if only_warn:
|
443
|
-
warnings.warn(resolved_message, UserWarning, stacklevel=2)
|
444
|
-
else:
|
445
|
-
raise UsageError(resolved_message)
|
446
|
-
|
447
|
-
return wrapper_fn
|
448
|
-
|
449
|
-
return decorator_fn
|
450
|
-
|
451
|
-
@classmethod
|
452
|
-
def _noop(cls, func: Callable) -> Callable:
|
453
|
-
@functools.wraps(func)
|
454
|
-
def wrapper(self: type[Run], *args: Any, **kwargs: Any) -> Any:
|
455
|
-
# `_attach_id` is only assigned in service hence for all service cases
|
456
|
-
# it will be a passthrough. We don't pickle non-service so again a way
|
457
|
-
# to see that we are in non-service case
|
458
|
-
if getattr(self, "_attach_id", None) is None:
|
459
|
-
# `_init_pid` is only assigned in __init__ (this will be constant check for mp):
|
460
|
-
# - for non-fork case the object is shared through pickling,
|
461
|
-
# and we don't pickle non-service so will be None
|
462
|
-
# - for fork case the new process share mem space hence the value would be of parent process.
|
463
|
-
_init_pid = getattr(self, "_init_pid", None)
|
464
|
-
if _init_pid != os.getpid():
|
465
|
-
message = (
|
466
|
-
f"`{func.__name__}` ignored (called from pid={os.getpid()}, "
|
467
|
-
f"`init` called from pid={_init_pid}). "
|
468
|
-
f"See: {url_registry.url('multiprocess')}"
|
469
|
-
)
|
470
|
-
# - if this process was pickled in non-service case,
|
471
|
-
# we ignore the attributes (since pickle is not supported)
|
472
|
-
# - for fork case will use the settings of the parent process
|
473
|
-
# - only point of inconsistent behavior from forked and non-forked cases
|
474
|
-
settings = getattr(self, "_settings", None)
|
475
|
-
if settings and settings.strict:
|
476
|
-
wandb.termerror(message, repeat=False)
|
477
|
-
raise UnsupportedError(
|
478
|
-
f"`{func.__name__}` does not support multiprocessing"
|
479
|
-
)
|
480
|
-
wandb.termwarn(message, repeat=False)
|
481
|
-
return cls.Dummy()
|
482
444
|
|
445
|
+
_is_attaching = func.__name__
|
446
|
+
try:
|
447
|
+
wandb._attach(run=self) # type: ignore
|
448
|
+
finally:
|
449
|
+
_is_attaching = ""
|
450
|
+
|
451
|
+
return func(self, *args, **kwargs)
|
452
|
+
|
453
|
+
return wrapper
|
454
|
+
|
455
|
+
|
456
|
+
def _raise_if_finished(
|
457
|
+
func: Callable[Concatenate[Run, _P], _T],
|
458
|
+
) -> Callable[Concatenate[Run, _P], _T]:
|
459
|
+
"""Decorate a Run method to raise an error after the run is finished."""
|
460
|
+
|
461
|
+
@functools.wraps(func)
|
462
|
+
def wrapper_fn(self: Run, *args, **kwargs) -> _T:
|
463
|
+
if not getattr(self, "_is_finished", False):
|
464
|
+
return func(self, *args, **kwargs)
|
465
|
+
|
466
|
+
message = (
|
467
|
+
f"Run ({self.id}) is finished. The call to"
|
468
|
+
f" `{func.__name__}` will be ignored."
|
469
|
+
f" Please make sure that you are using an active run."
|
470
|
+
)
|
471
|
+
|
472
|
+
raise UsageError(message)
|
473
|
+
|
474
|
+
return wrapper_fn
|
475
|
+
|
476
|
+
|
477
|
+
def _noop_if_forked_with_no_service(
|
478
|
+
func: Callable[Concatenate[Run, _P], None],
|
479
|
+
) -> Callable[Concatenate[Run, _P], None]:
|
480
|
+
"""Do nothing if called in a forked process and service is disabled.
|
481
|
+
|
482
|
+
Disabling the service is a very old and barely supported setting.
|
483
|
+
"""
|
484
|
+
|
485
|
+
@functools.wraps(func)
|
486
|
+
def wrapper(self: Run, *args, **kwargs) -> None:
|
487
|
+
# The _attach_id attribute is only None when running in the "disable
|
488
|
+
# service" mode.
|
489
|
+
#
|
490
|
+
# Since it is set early in `__init__` and included in the run's pickled
|
491
|
+
# state, the attribute always exists.
|
492
|
+
is_using_service = self._attach_id is not None
|
493
|
+
|
494
|
+
# This is the PID in which the Run object was constructed. The attribute
|
495
|
+
# always exists because it is set early in `__init__` and is included
|
496
|
+
# in the pickled state in `__getstate__` and `__setstate__`.
|
497
|
+
#
|
498
|
+
# It is not equal to the current PID if the process was forked or if
|
499
|
+
# the Run object was pickled and sent to another process.
|
500
|
+
init_pid = self._init_pid
|
501
|
+
|
502
|
+
if is_using_service or init_pid == os.getpid():
|
483
503
|
return func(self, *args, **kwargs)
|
484
504
|
|
485
|
-
|
505
|
+
message = (
|
506
|
+
f"`{func.__name__}` ignored (called from pid={os.getpid()},"
|
507
|
+
f" `init` called from pid={init_pid})."
|
508
|
+
f" See: {url_registry.url('multiprocess')}"
|
509
|
+
)
|
510
|
+
|
511
|
+
# This attribute may not exist because it is not included in the run's
|
512
|
+
# pickled state.
|
513
|
+
settings = getattr(self, "_settings", None)
|
514
|
+
if settings and settings.strict:
|
515
|
+
wandb.termerror(message, repeat=False)
|
516
|
+
raise UnsupportedError(
|
517
|
+
f"`{func.__name__}` does not support multiprocessing"
|
518
|
+
)
|
519
|
+
wandb.termwarn(message, repeat=False)
|
520
|
+
return None
|
521
|
+
|
522
|
+
return wrapper
|
486
523
|
|
487
524
|
|
488
525
|
@dataclass
|
@@ -606,6 +643,7 @@ class Run:
|
|
606
643
|
) -> None:
|
607
644
|
# pid is set, so we know if this run object was initialized by this process
|
608
645
|
self._init_pid = os.getpid()
|
646
|
+
self._attach_id = None
|
609
647
|
|
610
648
|
if settings._noop:
|
611
649
|
# TODO: properly handle setting for disabled mode
|
@@ -647,14 +685,13 @@ class Run:
|
|
647
685
|
|
648
686
|
self._step = 0
|
649
687
|
self._starting_step = 0
|
688
|
+
self._start_runtime = 0
|
650
689
|
# TODO: eventually would be nice to make this configurable using self._settings._start_time
|
651
690
|
# need to test (jhr): if you set start time to 2 days ago and run a test for 15 minutes,
|
652
691
|
# does the total time get calculated right (not as 2 days and 15 minutes)?
|
653
692
|
self._start_time = time.time()
|
654
693
|
|
655
|
-
|
656
|
-
|
657
|
-
self._printer = printer.new_printer()
|
694
|
+
self._printer = printer.new_printer(settings)
|
658
695
|
|
659
696
|
self._torch_history: wandb_torch.TorchHistory | None = None # type: ignore
|
660
697
|
|
@@ -776,8 +813,9 @@ class Run:
|
|
776
813
|
self._unique_launch_artifact_sequence_names[sequence_name] = item
|
777
814
|
|
778
815
|
def _telemetry_callback(self, telem_obj: telemetry.TelemetryRecord) -> None:
|
779
|
-
if not hasattr(self, "_telemetry_obj"):
|
816
|
+
if not hasattr(self, "_telemetry_obj") or self._is_finished:
|
780
817
|
return
|
818
|
+
|
781
819
|
self._telemetry_obj.MergeFrom(telem_obj)
|
782
820
|
self._telemetry_obj_dirty = True
|
783
821
|
self._telemetry_flush()
|
@@ -846,47 +884,45 @@ class Run:
|
|
846
884
|
|
847
885
|
@property
|
848
886
|
@_log_to_run
|
849
|
-
@
|
887
|
+
@_attach
|
850
888
|
def settings(self) -> Settings:
|
851
889
|
"""A frozen copy of run's Settings object."""
|
852
890
|
return self._settings.model_copy(deep=True)
|
853
891
|
|
854
892
|
@property
|
855
893
|
@_log_to_run
|
856
|
-
@
|
894
|
+
@_attach
|
857
895
|
def dir(self) -> str:
|
858
896
|
"""The directory where files associated with the run are saved."""
|
859
897
|
return self._settings.files_dir
|
860
898
|
|
861
899
|
@property
|
862
900
|
@_log_to_run
|
863
|
-
@
|
901
|
+
@_attach
|
864
902
|
def config(self) -> wandb_config.Config:
|
865
903
|
"""Config object associated with this run."""
|
866
904
|
return self._config
|
867
905
|
|
868
906
|
@property
|
869
907
|
@_log_to_run
|
870
|
-
@
|
908
|
+
@_attach
|
871
909
|
def config_static(self) -> wandb_config.ConfigStatic:
|
872
910
|
return wandb_config.ConfigStatic(self._config)
|
873
911
|
|
874
912
|
@property
|
875
913
|
@_log_to_run
|
876
|
-
@
|
914
|
+
@_attach
|
877
915
|
def name(self) -> str | None:
|
878
916
|
"""Display name of the run.
|
879
917
|
|
880
918
|
Display names are not guaranteed to be unique and may be descriptive.
|
881
919
|
By default, they are randomly generated.
|
882
920
|
"""
|
883
|
-
|
884
|
-
return self._settings.run_name
|
885
|
-
return None
|
921
|
+
return self._settings.run_name
|
886
922
|
|
887
923
|
@name.setter
|
888
924
|
@_log_to_run
|
889
|
-
@
|
925
|
+
@_raise_if_finished
|
890
926
|
def name(self, name: str) -> None:
|
891
927
|
with telemetry.context(run=self) as tel:
|
892
928
|
tel.feature.set_run_name = True
|
@@ -896,18 +932,18 @@ class Run:
|
|
896
932
|
|
897
933
|
@property
|
898
934
|
@_log_to_run
|
899
|
-
@
|
935
|
+
@_attach
|
900
936
|
def notes(self) -> str | None:
|
901
937
|
"""Notes associated with the run, if there are any.
|
902
938
|
|
903
|
-
Notes can be a multiline string and can also use markdown and latex
|
904
|
-
inside `$$`, like `$x + 3$`.
|
939
|
+
Notes can be a multiline string and can also use markdown and latex
|
940
|
+
equations inside `$$`, like `$x + 3$`.
|
905
941
|
"""
|
906
942
|
return self._settings.run_notes
|
907
943
|
|
908
944
|
@notes.setter
|
909
945
|
@_log_to_run
|
910
|
-
@
|
946
|
+
@_raise_if_finished
|
911
947
|
def notes(self, notes: str) -> None:
|
912
948
|
self._settings.run_notes = notes
|
913
949
|
if self._backend and self._backend.interface:
|
@@ -915,14 +951,14 @@ class Run:
|
|
915
951
|
|
916
952
|
@property
|
917
953
|
@_log_to_run
|
918
|
-
@
|
954
|
+
@_attach
|
919
955
|
def tags(self) -> tuple | None:
|
920
956
|
"""Tags associated with the run, if there are any."""
|
921
957
|
return self._settings.run_tags or ()
|
922
958
|
|
923
959
|
@tags.setter
|
924
960
|
@_log_to_run
|
925
|
-
@
|
961
|
+
@_raise_if_finished
|
926
962
|
def tags(self, tags: Sequence) -> None:
|
927
963
|
with telemetry.context(run=self) as tel:
|
928
964
|
tel.feature.set_run_tags = True
|
@@ -932,18 +968,17 @@ class Run:
|
|
932
968
|
|
933
969
|
@property
|
934
970
|
@_log_to_run
|
935
|
-
@
|
971
|
+
@_attach
|
936
972
|
def id(self) -> str:
|
937
973
|
"""Identifier for this run."""
|
938
|
-
|
939
|
-
assert self._settings.run_id is not None
|
974
|
+
assert self._settings.run_id is not None
|
940
975
|
return self._settings.run_id
|
941
976
|
|
942
977
|
@property
|
943
978
|
@_log_to_run
|
944
|
-
@
|
979
|
+
@_attach
|
945
980
|
def sweep_id(self) -> str | None:
|
946
|
-
"""
|
981
|
+
"""Identifier for the sweep associated with the run, if there is one."""
|
947
982
|
return self._settings.sweep_id
|
948
983
|
|
949
984
|
def _get_path(self) -> str:
|
@@ -959,7 +994,7 @@ class Run:
|
|
959
994
|
|
960
995
|
@property
|
961
996
|
@_log_to_run
|
962
|
-
@
|
997
|
+
@_attach
|
963
998
|
def path(self) -> str:
|
964
999
|
"""Path to the run.
|
965
1000
|
|
@@ -970,28 +1005,28 @@ class Run:
|
|
970
1005
|
|
971
1006
|
@property
|
972
1007
|
@_log_to_run
|
973
|
-
@
|
1008
|
+
@_attach
|
974
1009
|
def start_time(self) -> float:
|
975
1010
|
"""Unix timestamp (in seconds) of when the run started."""
|
976
1011
|
return self._start_time
|
977
1012
|
|
978
1013
|
@property
|
979
1014
|
@_log_to_run
|
980
|
-
@
|
1015
|
+
@_attach
|
981
1016
|
def starting_step(self) -> int:
|
982
1017
|
"""The first step of the run."""
|
983
1018
|
return self._starting_step
|
984
1019
|
|
985
1020
|
@property
|
986
1021
|
@_log_to_run
|
987
|
-
@
|
1022
|
+
@_attach
|
988
1023
|
def resumed(self) -> bool:
|
989
1024
|
"""True if the run was resumed, False otherwise."""
|
990
1025
|
return self._settings.resumed
|
991
1026
|
|
992
1027
|
@property
|
993
1028
|
@_log_to_run
|
994
|
-
@
|
1029
|
+
@_attach
|
995
1030
|
def step(self) -> int:
|
996
1031
|
"""Current value of the step.
|
997
1032
|
|
@@ -1001,34 +1036,34 @@ class Run:
|
|
1001
1036
|
|
1002
1037
|
@property
|
1003
1038
|
@_log_to_run
|
1004
|
-
@
|
1039
|
+
@_attach
|
1005
1040
|
def mode(self) -> str:
|
1006
1041
|
"""For compatibility with `0.9.x` and earlier, deprecate eventually."""
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1042
|
+
deprecate.deprecate(
|
1043
|
+
field_name=Deprecated.run__mode,
|
1044
|
+
warning_message=(
|
1045
|
+
"The mode property of wandb.run is deprecated "
|
1046
|
+
"and will be removed in a future release."
|
1047
|
+
),
|
1048
|
+
run=self,
|
1049
|
+
)
|
1015
1050
|
return "dryrun" if self._settings._offline else "run"
|
1016
1051
|
|
1017
1052
|
@property
|
1018
1053
|
@_log_to_run
|
1019
|
-
@
|
1054
|
+
@_attach
|
1020
1055
|
def offline(self) -> bool:
|
1021
1056
|
return self._settings._offline
|
1022
1057
|
|
1023
1058
|
@property
|
1024
1059
|
@_log_to_run
|
1025
|
-
@
|
1060
|
+
@_attach
|
1026
1061
|
def disabled(self) -> bool:
|
1027
1062
|
return self._settings._noop
|
1028
1063
|
|
1029
1064
|
@property
|
1030
1065
|
@_log_to_run
|
1031
|
-
@
|
1066
|
+
@_attach
|
1032
1067
|
def group(self) -> str:
|
1033
1068
|
"""Name of the group associated with the run.
|
1034
1069
|
|
@@ -1043,24 +1078,67 @@ class Run:
|
|
1043
1078
|
|
1044
1079
|
@property
|
1045
1080
|
@_log_to_run
|
1046
|
-
@
|
1081
|
+
@_attach
|
1047
1082
|
def job_type(self) -> str:
|
1048
1083
|
return self._settings.run_job_type or ""
|
1049
1084
|
|
1050
1085
|
def project_name(self) -> str:
|
1051
|
-
|
1052
|
-
|
1086
|
+
"""Name of the W&B project associated with the run.
|
1087
|
+
|
1088
|
+
Note: this method is deprecated and will be removed in a future release.
|
1089
|
+
Please use `run.project` instead.
|
1090
|
+
"""
|
1091
|
+
deprecate.deprecate(
|
1092
|
+
field_name=Deprecated.run__project_name,
|
1093
|
+
warning_message=(
|
1094
|
+
"The project_name method is deprecated and will be removed in a"
|
1095
|
+
" future release. Please use `run.project` instead."
|
1096
|
+
),
|
1097
|
+
)
|
1098
|
+
return self.project
|
1053
1099
|
|
1054
1100
|
@property
|
1055
1101
|
@_log_to_run
|
1056
|
-
@
|
1102
|
+
@_attach
|
1057
1103
|
def project(self) -> str:
|
1058
1104
|
"""Name of the W&B project associated with the run."""
|
1059
|
-
|
1105
|
+
assert self._settings.project is not None
|
1106
|
+
return self._settings.project
|
1107
|
+
|
1108
|
+
@_log_to_run
|
1109
|
+
def get_project_url(self) -> str | None:
|
1110
|
+
"""URL of the W&B project associated with the run, if there is one.
|
1111
|
+
|
1112
|
+
Offline runs do not have a project URL.
|
1060
1113
|
|
1061
|
-
|
1114
|
+
Note: this method is deprecated and will be removed in a future release.
|
1115
|
+
Please use `run.project_url` instead.
|
1116
|
+
"""
|
1117
|
+
deprecate.deprecate(
|
1118
|
+
field_name=Deprecated.run__get_project_url,
|
1119
|
+
warning_message=(
|
1120
|
+
"The get_project_url method is deprecated and will be removed in a"
|
1121
|
+
" future release. Please use `run.project_url` instead."
|
1122
|
+
),
|
1123
|
+
)
|
1124
|
+
return self.project_url
|
1125
|
+
|
1126
|
+
@property
|
1062
1127
|
@_log_to_run
|
1063
|
-
@
|
1128
|
+
@_attach
|
1129
|
+
def project_url(self) -> str | None:
|
1130
|
+
"""URL of the W&B project associated with the run, if there is one.
|
1131
|
+
|
1132
|
+
Offline runs do not have a project URL.
|
1133
|
+
"""
|
1134
|
+
if self._settings._offline:
|
1135
|
+
wandb.termwarn("URL not available in offline run")
|
1136
|
+
return None
|
1137
|
+
return self._settings.project_url
|
1138
|
+
|
1139
|
+
@_raise_if_finished
|
1140
|
+
@_log_to_run
|
1141
|
+
@_attach
|
1064
1142
|
def log_code(
|
1065
1143
|
self,
|
1066
1144
|
root: str | None = ".",
|
@@ -1147,19 +1225,30 @@ class Run:
|
|
1147
1225
|
return self._log_artifact(art)
|
1148
1226
|
|
1149
1227
|
@_log_to_run
|
1150
|
-
def
|
1151
|
-
"""
|
1228
|
+
def get_sweep_url(self) -> str | None:
|
1229
|
+
"""The URL of the sweep associated with the run, if there is one.
|
1152
1230
|
|
1153
|
-
Offline runs
|
1231
|
+
Offline runs do not have a sweep URL.
|
1232
|
+
|
1233
|
+
Note: this method is deprecated and will be removed in a future release.
|
1234
|
+
Please use `run.sweep_url` instead.
|
1154
1235
|
"""
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1236
|
+
deprecate.deprecate(
|
1237
|
+
field_name=Deprecated.run__get_sweep_url,
|
1238
|
+
warning_message=(
|
1239
|
+
"The get_sweep_url method is deprecated and will be removed in a"
|
1240
|
+
" future release. Please use `run.sweep_url` instead."
|
1241
|
+
),
|
1242
|
+
)
|
1243
|
+
return self.sweep_url
|
1159
1244
|
|
1160
|
-
@
|
1161
|
-
|
1162
|
-
|
1245
|
+
@property
|
1246
|
+
@_attach
|
1247
|
+
def sweep_url(self) -> str | None:
|
1248
|
+
"""URL of the sweep associated with the run, if there is one.
|
1249
|
+
|
1250
|
+
Offline runs do not have a sweep URL.
|
1251
|
+
"""
|
1163
1252
|
if self._settings._offline:
|
1164
1253
|
wandb.termwarn("URL not available in offline run")
|
1165
1254
|
return None
|
@@ -1167,7 +1256,27 @@ class Run:
|
|
1167
1256
|
|
1168
1257
|
@_log_to_run
|
1169
1258
|
def get_url(self) -> str | None:
|
1170
|
-
"""
|
1259
|
+
"""URL of the W&B run, if there is one.
|
1260
|
+
|
1261
|
+
Offline runs do not have a URL.
|
1262
|
+
|
1263
|
+
Note: this method is deprecated and will be removed in a future release.
|
1264
|
+
Please use `run.url` instead.
|
1265
|
+
"""
|
1266
|
+
deprecate.deprecate(
|
1267
|
+
field_name=Deprecated.run__get_url,
|
1268
|
+
warning_message=(
|
1269
|
+
"The get_url method is deprecated and will be removed in a"
|
1270
|
+
" future release. Please use `run.url` instead."
|
1271
|
+
),
|
1272
|
+
)
|
1273
|
+
return self.url
|
1274
|
+
|
1275
|
+
@property
|
1276
|
+
@_log_to_run
|
1277
|
+
@_attach
|
1278
|
+
def url(self) -> str | None:
|
1279
|
+
"""The url for the W&B run, if there is one.
|
1171
1280
|
|
1172
1281
|
Offline runs will not have a url.
|
1173
1282
|
"""
|
@@ -1178,14 +1287,7 @@ class Run:
|
|
1178
1287
|
|
1179
1288
|
@property
|
1180
1289
|
@_log_to_run
|
1181
|
-
@
|
1182
|
-
def url(self) -> str | None:
|
1183
|
-
"""The W&B url associated with the run."""
|
1184
|
-
return self.get_url()
|
1185
|
-
|
1186
|
-
@property
|
1187
|
-
@_log_to_run
|
1188
|
-
@_run_decorator._attach
|
1290
|
+
@_attach
|
1189
1291
|
def entity(self) -> str:
|
1190
1292
|
"""The name of the W&B entity associated with the run.
|
1191
1293
|
|
@@ -1280,7 +1382,7 @@ class Run:
|
|
1280
1382
|
self._label_probe_lines(lines)
|
1281
1383
|
|
1282
1384
|
@_log_to_run
|
1283
|
-
@
|
1385
|
+
@_attach
|
1284
1386
|
def display(self, height: int = 420, hidden: bool = False) -> bool:
|
1285
1387
|
"""Display this run in jupyter."""
|
1286
1388
|
if self._settings.silent:
|
@@ -1300,7 +1402,7 @@ class Run:
|
|
1300
1402
|
return False
|
1301
1403
|
|
1302
1404
|
@_log_to_run
|
1303
|
-
@
|
1405
|
+
@_attach
|
1304
1406
|
def to_html(self, height: int = 420, hidden: bool = False) -> str:
|
1305
1407
|
"""Generate HTML containing an iframe displaying the current run."""
|
1306
1408
|
url = self._settings.run_url + "?jupyter=true"
|
@@ -1317,7 +1419,7 @@ class Run:
|
|
1317
1419
|
return {"text/html": self.to_html(hidden=True)}
|
1318
1420
|
|
1319
1421
|
@_log_to_run
|
1320
|
-
@
|
1422
|
+
@_raise_if_finished
|
1321
1423
|
def _config_callback(
|
1322
1424
|
self,
|
1323
1425
|
key: tuple[str, ...] | str | None = None,
|
@@ -1339,6 +1441,8 @@ class Run:
|
|
1339
1441
|
assert isinstance(val, dict)
|
1340
1442
|
public_api = self._public_api()
|
1341
1443
|
artifact = Artifact._from_id(val["id"], public_api.client)
|
1444
|
+
|
1445
|
+
assert artifact
|
1342
1446
|
return self.use_artifact(artifact, use_as=key)
|
1343
1447
|
elif _is_artifact_string(val):
|
1344
1448
|
# this will never fail, but is required to make mypy happy
|
@@ -1357,6 +1461,7 @@ class Run:
|
|
1357
1461
|
# in the future we'll need to support using artifacts from
|
1358
1462
|
# different instances of wandb.
|
1359
1463
|
|
1464
|
+
assert artifact
|
1360
1465
|
return self.use_artifact(artifact, use_as=key)
|
1361
1466
|
elif _is_artifact_object(val):
|
1362
1467
|
return self.use_artifact(val, use_as=key)
|
@@ -1369,7 +1474,7 @@ class Run:
|
|
1369
1474
|
self._config_callback(key=("_wandb", key), val=val)
|
1370
1475
|
|
1371
1476
|
@_log_to_run
|
1372
|
-
@
|
1477
|
+
@_raise_if_finished
|
1373
1478
|
def _summary_update_callback(self, summary_record: SummaryRecord) -> None:
|
1374
1479
|
with telemetry.context(run=self) as tel:
|
1375
1480
|
tel.feature.set_summary = True
|
@@ -1400,7 +1505,16 @@ class Run:
|
|
1400
1505
|
self._backend.interface._publish_metric(metric_record)
|
1401
1506
|
|
1402
1507
|
@_log_to_run
|
1403
|
-
def
|
1508
|
+
def _publish_file(self, fname: str) -> None:
|
1509
|
+
"""Mark a run file to be uploaded with the run.
|
1510
|
+
|
1511
|
+
This is a W&B-internal function: it can be used by other internal
|
1512
|
+
wandb code.
|
1513
|
+
|
1514
|
+
Args:
|
1515
|
+
fname: The path to the file in the run's files directory, relative
|
1516
|
+
to the run's files directory.
|
1517
|
+
"""
|
1404
1518
|
if not self._backend or not self._backend.interface:
|
1405
1519
|
return
|
1406
1520
|
files: FilesDict = dict(files=[(GlobStr(fname), "now")])
|
@@ -1502,7 +1616,7 @@ class Run:
|
|
1502
1616
|
self._backend.interface.publish_output(name, data)
|
1503
1617
|
|
1504
1618
|
@_log_to_run
|
1505
|
-
@
|
1619
|
+
@_raise_if_finished
|
1506
1620
|
def _console_raw_callback(self, name: str, data: str) -> None:
|
1507
1621
|
# logger.info("console callback: %s, %s", name, data)
|
1508
1622
|
|
@@ -1548,6 +1662,9 @@ class Run:
|
|
1548
1662
|
if run_obj.start_time:
|
1549
1663
|
self._start_time = run_obj.start_time.ToMicroseconds() / 1e6
|
1550
1664
|
|
1665
|
+
if run_obj.runtime:
|
1666
|
+
self._start_runtime = run_obj.runtime
|
1667
|
+
|
1551
1668
|
# Grab the config from resuming
|
1552
1669
|
if run_obj.config:
|
1553
1670
|
c_dict = config_util.dict_no_value_from_proto_list(run_obj.config.update)
|
@@ -1683,9 +1800,9 @@ class Run:
|
|
1683
1800
|
self._step += 1
|
1684
1801
|
|
1685
1802
|
@_log_to_run
|
1686
|
-
@
|
1687
|
-
@
|
1688
|
-
@
|
1803
|
+
@_noop_if_forked_with_no_service
|
1804
|
+
@_raise_if_finished
|
1805
|
+
@_attach
|
1689
1806
|
def log(
|
1690
1807
|
self,
|
1691
1808
|
data: dict[str, Any],
|
@@ -1931,10 +2048,11 @@ class Run:
|
|
1931
2048
|
|
1932
2049
|
if sync is not None:
|
1933
2050
|
deprecate.deprecate(
|
1934
|
-
field_name=
|
2051
|
+
field_name=Deprecated.run__log_sync,
|
1935
2052
|
warning_message=(
|
1936
2053
|
"`sync` argument is deprecated and does not affect the behaviour of `wandb.log`"
|
1937
2054
|
),
|
2055
|
+
run=self,
|
1938
2056
|
)
|
1939
2057
|
if self._settings._shared and step is not None:
|
1940
2058
|
wandb.termwarn(
|
@@ -1946,8 +2064,8 @@ class Run:
|
|
1946
2064
|
self._log(data=data, step=step, commit=commit)
|
1947
2065
|
|
1948
2066
|
@_log_to_run
|
1949
|
-
@
|
1950
|
-
@
|
2067
|
+
@_raise_if_finished
|
2068
|
+
@_attach
|
1951
2069
|
def save(
|
1952
2070
|
self,
|
1953
2071
|
glob_str: str | os.PathLike | None = None,
|
@@ -2004,11 +2122,12 @@ class Run:
|
|
2004
2122
|
if glob_str is None:
|
2005
2123
|
# noop for historical reasons, run.save() may be called in legacy code
|
2006
2124
|
deprecate.deprecate(
|
2007
|
-
field_name=
|
2125
|
+
field_name=Deprecated.run__save_no_args,
|
2008
2126
|
warning_message=(
|
2009
2127
|
"Calling wandb.run.save without any arguments is deprecated."
|
2010
2128
|
"Changes to attributes are automatically persisted."
|
2011
2129
|
),
|
2130
|
+
run=self,
|
2012
2131
|
)
|
2013
2132
|
return True
|
2014
2133
|
|
@@ -2132,7 +2251,7 @@ class Run:
|
|
2132
2251
|
return [str(f) for f in globbed_files]
|
2133
2252
|
|
2134
2253
|
@_log_to_run
|
2135
|
-
@
|
2254
|
+
@_attach
|
2136
2255
|
def restore(
|
2137
2256
|
self,
|
2138
2257
|
name: str,
|
@@ -2148,8 +2267,8 @@ class Run:
|
|
2148
2267
|
)
|
2149
2268
|
|
2150
2269
|
@_log_to_run
|
2151
|
-
@
|
2152
|
-
@
|
2270
|
+
@_noop_if_forked_with_no_service
|
2271
|
+
@_attach
|
2153
2272
|
def finish(
|
2154
2273
|
self,
|
2155
2274
|
exit_code: int | None = None,
|
@@ -2173,11 +2292,12 @@ class Run:
|
|
2173
2292
|
"""
|
2174
2293
|
if quiet is not None:
|
2175
2294
|
deprecate.deprecate(
|
2176
|
-
field_name=
|
2295
|
+
field_name=Deprecated.run__finish_quiet,
|
2177
2296
|
warning_message=(
|
2178
2297
|
"The `quiet` argument to `wandb.run.finish()` is deprecated, "
|
2179
2298
|
"use `wandb.Settings(quiet=...)` to set this instead."
|
2180
2299
|
),
|
2300
|
+
run=self,
|
2181
2301
|
)
|
2182
2302
|
return self._finish(exit_code)
|
2183
2303
|
|
@@ -2186,6 +2306,11 @@ class Run:
|
|
2186
2306
|
self,
|
2187
2307
|
exit_code: int | None = None,
|
2188
2308
|
) -> None:
|
2309
|
+
if self._is_finished:
|
2310
|
+
return
|
2311
|
+
|
2312
|
+
assert self._wl
|
2313
|
+
|
2189
2314
|
logger.info(f"finishing run {self._get_path()}")
|
2190
2315
|
with telemetry.context(run=self) as tel:
|
2191
2316
|
tel.feature.finish = True
|
@@ -2199,6 +2324,7 @@ class Run:
|
|
2199
2324
|
# Early-stage hooks may use methods that require _is_finished
|
2200
2325
|
# to be False, so we set this after running those hooks.
|
2201
2326
|
self._is_finished = True
|
2327
|
+
self._wl.remove_active_run(self)
|
2202
2328
|
|
2203
2329
|
try:
|
2204
2330
|
self._atexit_cleanup(exit_code=exit_code)
|
@@ -2214,31 +2340,32 @@ class Run:
|
|
2214
2340
|
#
|
2215
2341
|
# TODO: Why not do this in _atexit_cleanup()?
|
2216
2342
|
if self._settings.run_id:
|
2217
|
-
assert self._wl
|
2218
2343
|
service = self._wl.assert_service()
|
2219
2344
|
service.inform_finish(run_id=self._settings.run_id)
|
2220
2345
|
|
2221
2346
|
finally:
|
2222
|
-
|
2347
|
+
if wandb.run is self:
|
2348
|
+
module.unset_globals()
|
2223
2349
|
wandb._sentry.end_session()
|
2224
2350
|
|
2225
2351
|
@_log_to_run
|
2226
|
-
@
|
2227
|
-
@
|
2352
|
+
@_noop_if_forked_with_no_service
|
2353
|
+
@_attach
|
2228
2354
|
def join(self, exit_code: int | None = None) -> None:
|
2229
2355
|
"""Deprecated alias for `finish()` - use finish instead."""
|
2230
2356
|
if hasattr(self, "_telemetry_obj"):
|
2231
2357
|
deprecate.deprecate(
|
2232
|
-
field_name=
|
2358
|
+
field_name=Deprecated.run__join,
|
2233
2359
|
warning_message=(
|
2234
2360
|
"wandb.run.join() is deprecated, please use wandb.run.finish()."
|
2235
2361
|
),
|
2362
|
+
run=self,
|
2236
2363
|
)
|
2237
2364
|
self._finish(exit_code=exit_code)
|
2238
2365
|
|
2239
2366
|
@_log_to_run
|
2240
|
-
@
|
2241
|
-
@
|
2367
|
+
@_raise_if_finished
|
2368
|
+
@_attach
|
2242
2369
|
def status(
|
2243
2370
|
self,
|
2244
2371
|
) -> RunStatus:
|
@@ -2270,25 +2397,6 @@ class Run:
|
|
2270
2397
|
}
|
2271
2398
|
self._config_callback(val=config, key=("_wandb", "visualize", visualize_key))
|
2272
2399
|
|
2273
|
-
def _set_globals(self) -> None:
|
2274
|
-
module.set_global(
|
2275
|
-
run=self,
|
2276
|
-
config=self.config,
|
2277
|
-
log=self.log,
|
2278
|
-
summary=self.summary,
|
2279
|
-
save=self.save,
|
2280
|
-
use_artifact=self.use_artifact,
|
2281
|
-
log_artifact=self.log_artifact,
|
2282
|
-
define_metric=self.define_metric,
|
2283
|
-
alert=self.alert,
|
2284
|
-
watch=self.watch,
|
2285
|
-
unwatch=self.unwatch,
|
2286
|
-
mark_preempting=self.mark_preempting,
|
2287
|
-
log_model=self.log_model,
|
2288
|
-
use_model=self.use_model,
|
2289
|
-
link_model=self.link_model,
|
2290
|
-
)
|
2291
|
-
|
2292
2400
|
def _redirect(
|
2293
2401
|
self,
|
2294
2402
|
stdout_slave_fd: int | None,
|
@@ -2327,6 +2435,7 @@ class Run:
|
|
2327
2435
|
lambda data: self._console_callback("stdout", data),
|
2328
2436
|
self._output_writer.write, # type: ignore
|
2329
2437
|
],
|
2438
|
+
flush_periodically=(self._settings.mode == "online"),
|
2330
2439
|
)
|
2331
2440
|
err_redir = redirect.Redirect(
|
2332
2441
|
src="stderr",
|
@@ -2334,6 +2443,7 @@ class Run:
|
|
2334
2443
|
lambda data: self._console_callback("stderr", data),
|
2335
2444
|
self._output_writer.write, # type: ignore
|
2336
2445
|
],
|
2446
|
+
flush_periodically=(self._settings.mode == "online"),
|
2337
2447
|
)
|
2338
2448
|
if os.name == "nt":
|
2339
2449
|
|
@@ -2359,6 +2469,7 @@ class Run:
|
|
2359
2469
|
lambda data: self._console_callback("stdout", data),
|
2360
2470
|
self._output_writer.write, # type: ignore
|
2361
2471
|
],
|
2472
|
+
flush_periodically=(self._settings.mode == "online"),
|
2362
2473
|
)
|
2363
2474
|
err_redir = redirect.StreamWrapper(
|
2364
2475
|
src="stderr",
|
@@ -2366,6 +2477,7 @@ class Run:
|
|
2366
2477
|
lambda data: self._console_callback("stderr", data),
|
2367
2478
|
self._output_writer.write, # type: ignore
|
2368
2479
|
],
|
2480
|
+
flush_periodically=(self._settings.mode == "online"),
|
2369
2481
|
)
|
2370
2482
|
elif console == "wrap_raw":
|
2371
2483
|
logger.info("Wrapping output streams.")
|
@@ -2468,13 +2580,7 @@ class Run:
|
|
2468
2580
|
self._output_writer = None
|
2469
2581
|
|
2470
2582
|
def _on_start(self) -> None:
|
2471
|
-
|
2472
|
-
# (we want to do the set globals after attach)
|
2473
|
-
# TODO(console) However _console_start calls Redirect that uses `wandb.run` hence breaks
|
2474
|
-
# TODO(jupyter) However _header calls _header_run_info that uses wandb.jupyter that uses
|
2475
|
-
# `wandb.run` and hence breaks
|
2476
|
-
self._set_globals()
|
2477
|
-
self._header(settings=self._settings, printer=self._printer)
|
2583
|
+
self._header()
|
2478
2584
|
|
2479
2585
|
if self._settings.save_code and self._settings.code_dir is not None:
|
2480
2586
|
self.log_code(self._settings.code_dir)
|
@@ -2504,7 +2610,6 @@ class Run:
|
|
2504
2610
|
with telemetry.context(run=self) as tel:
|
2505
2611
|
tel.feature.attach = True
|
2506
2612
|
|
2507
|
-
self._set_globals()
|
2508
2613
|
self._is_attached = True
|
2509
2614
|
self._on_ready()
|
2510
2615
|
|
@@ -2536,6 +2641,9 @@ class Run:
|
|
2536
2641
|
|
2537
2642
|
def _on_ready(self) -> None:
|
2538
2643
|
"""Event triggered when run is ready for the user."""
|
2644
|
+
assert self._wl
|
2645
|
+
self._wl.add_active_run(self)
|
2646
|
+
|
2539
2647
|
self._register_telemetry_import_hooks()
|
2540
2648
|
|
2541
2649
|
# start reporting any telemetry changes
|
@@ -2627,6 +2735,7 @@ class Run:
|
|
2627
2735
|
docker_image_name=docker_image_name,
|
2628
2736
|
)
|
2629
2737
|
|
2738
|
+
assert job_artifact
|
2630
2739
|
artifact = self.log_artifact(job_artifact)
|
2631
2740
|
|
2632
2741
|
if not artifact:
|
@@ -2739,8 +2848,8 @@ class Run:
|
|
2739
2848
|
unregister_post_import_hook(module_name, run_id)
|
2740
2849
|
|
2741
2850
|
@_log_to_run
|
2742
|
-
@
|
2743
|
-
@
|
2851
|
+
@_raise_if_finished
|
2852
|
+
@_attach
|
2744
2853
|
def define_metric(
|
2745
2854
|
self,
|
2746
2855
|
name: str,
|
@@ -2779,14 +2888,14 @@ class Run:
|
|
2779
2888
|
"""
|
2780
2889
|
if summary and "copy" in summary:
|
2781
2890
|
deprecate.deprecate(
|
2782
|
-
|
2891
|
+
Deprecated.run__define_metric_copy,
|
2783
2892
|
"define_metric(summary='copy') is deprecated and will be removed.",
|
2784
2893
|
self,
|
2785
2894
|
)
|
2786
2895
|
|
2787
2896
|
if (summary and "best" in summary) or goal is not None:
|
2788
2897
|
deprecate.deprecate(
|
2789
|
-
|
2898
|
+
Deprecated.run__define_metric_best_goal,
|
2790
2899
|
"define_metric(summary='best', goal=...) is deprecated and will be removed. "
|
2791
2900
|
"Use define_metric(summary='min') or define_metric(summary='max') instead.",
|
2792
2901
|
self,
|
@@ -2881,7 +2990,7 @@ class Run:
|
|
2881
2990
|
return m
|
2882
2991
|
|
2883
2992
|
@_log_to_run
|
2884
|
-
@
|
2993
|
+
@_attach
|
2885
2994
|
def watch(
|
2886
2995
|
self,
|
2887
2996
|
models: torch.nn.Module | Sequence[torch.nn.Module],
|
@@ -2919,7 +3028,7 @@ class Run:
|
|
2919
3028
|
wandb.sdk._watch(self, models, criterion, log, log_freq, idx, log_graph)
|
2920
3029
|
|
2921
3030
|
@_log_to_run
|
2922
|
-
@
|
3031
|
+
@_attach
|
2923
3032
|
def unwatch(
|
2924
3033
|
self, models: torch.nn.Module | Sequence[torch.nn.Module] | None = None
|
2925
3034
|
) -> None:
|
@@ -2970,8 +3079,8 @@ class Run:
|
|
2970
3079
|
pass
|
2971
3080
|
|
2972
3081
|
@_log_to_run
|
2973
|
-
@
|
2974
|
-
@
|
3082
|
+
@_raise_if_finished
|
3083
|
+
@_attach
|
2975
3084
|
def link_artifact(
|
2976
3085
|
self,
|
2977
3086
|
artifact: Artifact,
|
@@ -3036,8 +3145,8 @@ class Run:
|
|
3036
3145
|
wandb.termerror(response.error_message)
|
3037
3146
|
|
3038
3147
|
@_log_to_run
|
3039
|
-
@
|
3040
|
-
@
|
3148
|
+
@_raise_if_finished
|
3149
|
+
@_attach
|
3041
3150
|
def use_artifact(
|
3042
3151
|
self,
|
3043
3152
|
artifact_or_name: str | Artifact,
|
@@ -3156,8 +3265,8 @@ class Run:
|
|
3156
3265
|
return artifact
|
3157
3266
|
|
3158
3267
|
@_log_to_run
|
3159
|
-
@
|
3160
|
-
@
|
3268
|
+
@_raise_if_finished
|
3269
|
+
@_attach
|
3161
3270
|
def log_artifact(
|
3162
3271
|
self,
|
3163
3272
|
artifact_or_path: Artifact | StrPath,
|
@@ -3199,8 +3308,8 @@ class Run:
|
|
3199
3308
|
)
|
3200
3309
|
|
3201
3310
|
@_log_to_run
|
3202
|
-
@
|
3203
|
-
@
|
3311
|
+
@_raise_if_finished
|
3312
|
+
@_attach
|
3204
3313
|
def upsert_artifact(
|
3205
3314
|
self,
|
3206
3315
|
artifact_or_path: Artifact | str,
|
@@ -3254,8 +3363,8 @@ class Run:
|
|
3254
3363
|
)
|
3255
3364
|
|
3256
3365
|
@_log_to_run
|
3257
|
-
@
|
3258
|
-
@
|
3366
|
+
@_raise_if_finished
|
3367
|
+
@_attach
|
3259
3368
|
def finish_artifact(
|
3260
3369
|
self,
|
3261
3370
|
artifact_or_path: Artifact | str,
|
@@ -3456,8 +3565,8 @@ class Run:
|
|
3456
3565
|
return artifact, _resolve_aliases(aliases)
|
3457
3566
|
|
3458
3567
|
@_log_to_run
|
3459
|
-
@
|
3460
|
-
@
|
3568
|
+
@_raise_if_finished
|
3569
|
+
@_attach
|
3461
3570
|
def log_model(
|
3462
3571
|
self,
|
3463
3572
|
path: StrPath,
|
@@ -3508,8 +3617,8 @@ class Run:
|
|
3508
3617
|
)
|
3509
3618
|
|
3510
3619
|
@_log_to_run
|
3511
|
-
@
|
3512
|
-
@
|
3620
|
+
@_raise_if_finished
|
3621
|
+
@_attach
|
3513
3622
|
def use_model(self, name: str) -> FilePathStr:
|
3514
3623
|
"""Download the files logged in a model artifact 'name'.
|
3515
3624
|
|
@@ -3549,6 +3658,10 @@ class Run:
|
|
3549
3658
|
Returns:
|
3550
3659
|
path: (str) path to downloaded model artifact file(s).
|
3551
3660
|
"""
|
3661
|
+
if self._settings._offline:
|
3662
|
+
# Downloading artifacts is not supported when offline.
|
3663
|
+
raise RuntimeError("`use_model` not supported in offline mode.")
|
3664
|
+
|
3552
3665
|
artifact = self.use_artifact(artifact_or_name=name)
|
3553
3666
|
if "model" not in str(artifact.type.lower()):
|
3554
3667
|
raise AssertionError(
|
@@ -3566,8 +3679,8 @@ class Run:
|
|
3566
3679
|
return path
|
3567
3680
|
|
3568
3681
|
@_log_to_run
|
3569
|
-
@
|
3570
|
-
@
|
3682
|
+
@_raise_if_finished
|
3683
|
+
@_attach
|
3571
3684
|
def link_model(
|
3572
3685
|
self,
|
3573
3686
|
path: StrPath,
|
@@ -3668,8 +3781,8 @@ class Run:
|
|
3668
3781
|
self.link_artifact(artifact=artifact, target_path=target_path, aliases=aliases)
|
3669
3782
|
|
3670
3783
|
@_log_to_run
|
3671
|
-
@
|
3672
|
-
@
|
3784
|
+
@_raise_if_finished
|
3785
|
+
@_attach
|
3673
3786
|
def alert(
|
3674
3787
|
self,
|
3675
3788
|
title: str,
|
@@ -3720,8 +3833,8 @@ class Run:
|
|
3720
3833
|
return not exception_raised
|
3721
3834
|
|
3722
3835
|
@_log_to_run
|
3723
|
-
@
|
3724
|
-
@
|
3836
|
+
@_raise_if_finished
|
3837
|
+
@_attach
|
3725
3838
|
def mark_preempting(self) -> None:
|
3726
3839
|
"""Mark this run as preempting.
|
3727
3840
|
|
@@ -3732,8 +3845,8 @@ class Run:
|
|
3732
3845
|
|
3733
3846
|
@property
|
3734
3847
|
@_log_to_run
|
3735
|
-
@
|
3736
|
-
@
|
3848
|
+
@_raise_if_finished
|
3849
|
+
@_attach
|
3737
3850
|
def _system_metrics(self) -> dict[str, list[tuple[datetime, float]]]:
|
3738
3851
|
"""Returns a dictionary of system metrics.
|
3739
3852
|
|
@@ -3781,8 +3894,8 @@ class Run:
|
|
3781
3894
|
|
3782
3895
|
@property
|
3783
3896
|
@_log_to_run
|
3784
|
-
@
|
3785
|
-
@
|
3897
|
+
@_attach
|
3898
|
+
@_raise_if_finished
|
3786
3899
|
def _metadata(self) -> Metadata | None:
|
3787
3900
|
"""The metadata associated with this run.
|
3788
3901
|
|
@@ -3820,8 +3933,8 @@ class Run:
|
|
3820
3933
|
return None
|
3821
3934
|
|
3822
3935
|
@_log_to_run
|
3823
|
-
@
|
3824
|
-
@
|
3936
|
+
@_raise_if_finished
|
3937
|
+
@_attach
|
3825
3938
|
def _metadata_callback(
|
3826
3939
|
self,
|
3827
3940
|
metadata: MetadataRequest,
|
@@ -3841,59 +3954,41 @@ class Run:
|
|
3841
3954
|
# ------------------------------------------------------------------------------
|
3842
3955
|
# HEADER
|
3843
3956
|
# ------------------------------------------------------------------------------
|
3844
|
-
|
3845
|
-
|
3846
|
-
|
3847
|
-
|
3848
|
-
*,
|
3849
|
-
settings: Settings,
|
3850
|
-
printer: printer.Printer,
|
3851
|
-
) -> None:
|
3852
|
-
Run._header_wandb_version_info(settings=settings, printer=printer)
|
3853
|
-
Run._header_sync_info(settings=settings, printer=printer)
|
3854
|
-
Run._header_run_info(settings=settings, printer=printer)
|
3957
|
+
def _header(self) -> None:
|
3958
|
+
self._header_wandb_version_info()
|
3959
|
+
self._header_sync_info()
|
3960
|
+
self._header_run_info()
|
3855
3961
|
|
3856
|
-
|
3857
|
-
|
3858
|
-
*,
|
3859
|
-
settings: Settings,
|
3860
|
-
printer: printer.Printer,
|
3861
|
-
) -> None:
|
3862
|
-
if settings.quiet or settings.silent:
|
3962
|
+
def _header_wandb_version_info(self) -> None:
|
3963
|
+
if self._settings.quiet or self._settings.silent:
|
3863
3964
|
return
|
3864
3965
|
|
3865
3966
|
# TODO: add this to a higher verbosity level
|
3866
|
-
|
3967
|
+
self._printer.display(f"Tracking run with wandb version {wandb.__version__}")
|
3867
3968
|
|
3868
|
-
|
3869
|
-
|
3870
|
-
|
3871
|
-
settings: Settings,
|
3872
|
-
printer: printer.Printer,
|
3873
|
-
) -> None:
|
3874
|
-
if settings._offline:
|
3875
|
-
printer.display(
|
3969
|
+
def _header_sync_info(self) -> None:
|
3970
|
+
if self._settings._offline:
|
3971
|
+
self._printer.display(
|
3876
3972
|
[
|
3877
|
-
f"W&B syncing is set to {
|
3878
|
-
f"Run {
|
3879
|
-
"
|
3973
|
+
f"W&B syncing is set to {self._printer.code('`offline`')}"
|
3974
|
+
f" in this directory. Run {self._printer.code('`wandb online`')}"
|
3975
|
+
f" or set {self._printer.code('WANDB_MODE=online')}"
|
3976
|
+
" to enable cloud syncing.",
|
3880
3977
|
]
|
3881
3978
|
)
|
3882
3979
|
else:
|
3883
|
-
|
3884
|
-
|
3980
|
+
sync_dir = self._settings.sync_dir
|
3981
|
+
info = [f"Run data is saved locally in {self._printer.files(sync_dir)}"]
|
3982
|
+
if not self._printer.supports_html:
|
3885
3983
|
info.append(
|
3886
|
-
f"Run {
|
3984
|
+
f"Run {self._printer.code('`wandb offline`')} to turn off syncing."
|
3887
3985
|
)
|
3888
|
-
if not
|
3889
|
-
|
3986
|
+
if not self._settings.quiet and not self._settings.silent:
|
3987
|
+
self._printer.display(info)
|
3988
|
+
|
3989
|
+
def _header_run_info(self) -> None:
|
3990
|
+
settings, printer = self._settings, self._printer
|
3890
3991
|
|
3891
|
-
@staticmethod
|
3892
|
-
def _header_run_info(
|
3893
|
-
*,
|
3894
|
-
settings: Settings,
|
3895
|
-
printer: printer.Printer,
|
3896
|
-
) -> None:
|
3897
3992
|
if settings._offline or settings.silent:
|
3898
3993
|
return
|
3899
3994
|
|
@@ -3911,12 +4006,13 @@ class Run:
|
|
3911
4006
|
return
|
3912
4007
|
|
3913
4008
|
if printer.supports_html:
|
3914
|
-
|
4009
|
+
import wandb.jupyter
|
4010
|
+
|
4011
|
+
if not wandb.jupyter.display_if_magic_is_used(self):
|
3915
4012
|
run_line = f"<strong>{printer.link(run_url, run_name)}</strong>"
|
3916
4013
|
project_line, sweep_line = "", ""
|
3917
4014
|
|
3918
|
-
|
3919
|
-
if not wandb.jupyter.quiet(): # type: ignore
|
4015
|
+
if not settings.quiet:
|
3920
4016
|
doc_html = printer.link(url_registry.url("developer-guide"), "docs")
|
3921
4017
|
|
3922
4018
|
project_html = printer.link(project_url, "Weights & Biases")
|