wandb 0.20.2rc20250616__py3-none-win32.whl → 0.21.0__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 +24 -23
- wandb/apis/internal.py +3 -0
- wandb/apis/paginator.py +17 -4
- wandb/apis/public/api.py +83 -2
- wandb/apis/public/artifacts.py +10 -8
- wandb/apis/public/files.py +5 -5
- wandb/apis/public/projects.py +44 -3
- wandb/apis/public/reports.py +64 -8
- wandb/apis/public/runs.py +16 -23
- wandb/automations/__init__.py +10 -10
- wandb/automations/_filters/run_metrics.py +0 -2
- wandb/automations/_utils.py +0 -2
- wandb/automations/actions.py +0 -2
- wandb/automations/automations.py +0 -2
- wandb/automations/events.py +0 -2
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/integration/catboost/catboost.py +6 -2
- wandb/integration/kfp/kfp_patch.py +3 -1
- wandb/integration/sb3/sb3.py +3 -3
- wandb/integration/ultralytics/callback.py +6 -2
- wandb/plot/__init__.py +2 -0
- wandb/plot/bar.py +30 -29
- wandb/plot/confusion_matrix.py +75 -71
- wandb/plot/histogram.py +26 -25
- wandb/plot/line.py +33 -32
- wandb/plot/line_series.py +100 -103
- wandb/plot/pr_curve.py +33 -32
- wandb/plot/roc_curve.py +38 -38
- wandb/plot/scatter.py +27 -27
- wandb/proto/v3/wandb_internal_pb2.py +366 -385
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_internal_pb2.py +352 -356
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_internal_pb2.py +352 -356
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/proto/v6/wandb_internal_pb2.py +352 -356
- wandb/proto/v6/wandb_settings_pb2.py +2 -2
- wandb/sdk/artifacts/_generated/__init__.py +12 -1
- wandb/sdk/artifacts/_generated/input_types.py +20 -2
- wandb/sdk/artifacts/_generated/link_artifact.py +21 -0
- wandb/sdk/artifacts/_generated/operations.py +9 -0
- wandb/sdk/artifacts/_validators.py +40 -2
- wandb/sdk/artifacts/artifact.py +163 -21
- wandb/sdk/data_types/base_types/media.py +9 -7
- wandb/sdk/data_types/base_types/wb_value.py +6 -6
- wandb/sdk/data_types/saved_model.py +3 -3
- wandb/sdk/data_types/table.py +41 -41
- wandb/sdk/data_types/trace_tree.py +12 -12
- wandb/sdk/interface/interface.py +8 -19
- wandb/sdk/interface/interface_shared.py +7 -16
- wandb/sdk/internal/datastore.py +18 -18
- wandb/sdk/internal/handler.py +3 -5
- wandb/sdk/internal/internal_api.py +54 -0
- wandb/sdk/internal/sender.py +23 -3
- wandb/sdk/internal/sender_config.py +9 -0
- wandb/sdk/launch/_project_spec.py +3 -3
- wandb/sdk/launch/agent/agent.py +3 -3
- wandb/sdk/launch/agent/job_status_tracker.py +3 -1
- wandb/sdk/launch/utils.py +3 -3
- wandb/sdk/lib/console_capture.py +66 -19
- wandb/sdk/wandb_init.py +1 -2
- wandb/sdk/wandb_require.py +0 -1
- wandb/sdk/wandb_run.py +23 -113
- wandb/sdk/wandb_settings.py +234 -72
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/METADATA +1 -1
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/RECORD +71 -71
- wandb/sdk/wandb_metadata.py +0 -623
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/WHEEL +0 -0
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/entry_points.txt +0 -0
- {wandb-0.20.2rc20250616.dist-info → wandb-0.21.0.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/lib/console_capture.py
CHANGED
@@ -25,17 +25,38 @@ In particular, it does not work with some combinations of pytest's
|
|
25
25
|
|
26
26
|
from __future__ import annotations
|
27
27
|
|
28
|
+
import logging
|
28
29
|
import sys
|
29
30
|
import threading
|
30
31
|
from typing import IO, AnyStr, Callable, Protocol
|
31
32
|
|
33
|
+
from . import wb_logging
|
34
|
+
|
35
|
+
_logger = logging.getLogger(__name__)
|
36
|
+
|
32
37
|
|
33
38
|
class CannotCaptureConsoleError(Exception):
|
34
39
|
"""The module failed to patch stdout or stderr."""
|
35
40
|
|
36
41
|
|
37
42
|
class _WriteCallback(Protocol):
|
38
|
-
"""A callback that receives intercepted bytes or string data.
|
43
|
+
"""A callback that receives intercepted bytes or string data.
|
44
|
+
|
45
|
+
This may be called from any thread, but is only called from one thread
|
46
|
+
at a time.
|
47
|
+
|
48
|
+
Note on errors: Any error raised during the callback will clear all
|
49
|
+
callbacks. This means that if a user presses Ctrl-C at an unlucky time
|
50
|
+
during a run, we will stop uploading console output---but it's not
|
51
|
+
likely to be a problem unless something catches the KeyboardInterrupt.
|
52
|
+
|
53
|
+
Regular Exceptions are caught and logged instead of bubbling up to the
|
54
|
+
user's print() statements; other exceptions like KeyboardInterrupt are
|
55
|
+
re-raised.
|
56
|
+
|
57
|
+
Callbacks should handle all exceptions---a callback that raises any
|
58
|
+
Exception is considered buggy.
|
59
|
+
"""
|
39
60
|
|
40
61
|
def __call__(
|
41
62
|
self,
|
@@ -45,6 +66,8 @@ class _WriteCallback(Protocol):
|
|
45
66
|
) -> None:
|
46
67
|
"""Intercept data passed to `write()`.
|
47
68
|
|
69
|
+
See the protocol docstring for information about exceptions.
|
70
|
+
|
48
71
|
Args:
|
49
72
|
data: The object passed to stderr's or stdout's `write()`.
|
50
73
|
written: The number of bytes or characters written.
|
@@ -52,7 +75,9 @@ class _WriteCallback(Protocol):
|
|
52
75
|
"""
|
53
76
|
|
54
77
|
|
55
|
-
|
78
|
+
# A reentrant lock is used to catch callbacks that write to stderr/stdout.
|
79
|
+
_module_rlock = threading.RLock()
|
80
|
+
_is_writing = False
|
56
81
|
|
57
82
|
_patch_exception: CannotCaptureConsoleError | None = None
|
58
83
|
|
@@ -67,9 +92,6 @@ def capture_stdout(callback: _WriteCallback) -> Callable[[], None]:
|
|
67
92
|
|
68
93
|
Args:
|
69
94
|
callback: A callback to invoke after running `sys.stdout.write`.
|
70
|
-
This may be called from any thread, so it must be thread-safe.
|
71
|
-
Exceptions are propagated to the caller of `write`.
|
72
|
-
See `_WriteCallback` for the exact protocol.
|
73
95
|
|
74
96
|
Returns:
|
75
97
|
A function to uninstall the callback.
|
@@ -77,7 +99,7 @@ def capture_stdout(callback: _WriteCallback) -> Callable[[], None]:
|
|
77
99
|
Raises:
|
78
100
|
CannotCaptureConsoleError: If patching failed on import.
|
79
101
|
"""
|
80
|
-
with
|
102
|
+
with _module_rlock:
|
81
103
|
if _patch_exception:
|
82
104
|
raise _patch_exception
|
83
105
|
|
@@ -92,9 +114,6 @@ def capture_stderr(callback: _WriteCallback) -> Callable[[], None]:
|
|
92
114
|
|
93
115
|
Args:
|
94
116
|
callback: A callback to invoke after running `sys.stderr.write`.
|
95
|
-
This may be called from any thread, so it must be thread-safe.
|
96
|
-
Exceptions are propagated to the caller of `write`.
|
97
|
-
See `_WriteCallback` for the exact protocol.
|
98
117
|
|
99
118
|
Returns:
|
100
119
|
A function to uninstall the callback.
|
@@ -102,7 +121,7 @@ def capture_stderr(callback: _WriteCallback) -> Callable[[], None]:
|
|
102
121
|
Raises:
|
103
122
|
CannotCaptureConsoleError: If patching failed on import.
|
104
123
|
"""
|
105
|
-
with
|
124
|
+
with _module_rlock:
|
106
125
|
if _patch_exception:
|
107
126
|
raise _patch_exception
|
108
127
|
|
@@ -125,11 +144,11 @@ def _insert_disposably(
|
|
125
144
|
def dispose() -> None:
|
126
145
|
nonlocal disposed
|
127
146
|
|
128
|
-
with
|
147
|
+
with _module_rlock:
|
129
148
|
if disposed:
|
130
149
|
return
|
131
150
|
|
132
|
-
|
151
|
+
callback_dict.pop(id, None)
|
133
152
|
|
134
153
|
disposed = True
|
135
154
|
|
@@ -143,16 +162,44 @@ def _patch(
|
|
143
162
|
) -> None:
|
144
163
|
orig_write: Callable[[AnyStr], int]
|
145
164
|
|
165
|
+
@wb_logging.log_to_all_runs()
|
146
166
|
def write_with_callbacks(s: AnyStr, /) -> int:
|
167
|
+
global _is_writing
|
147
168
|
n = orig_write(s)
|
148
169
|
|
149
|
-
#
|
150
|
-
#
|
151
|
-
with
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
170
|
+
# NOTE: Since _module_rlock is reentrant, this is safe. It will not
|
171
|
+
# deadlock if a callback invokes write() again.
|
172
|
+
with _module_rlock:
|
173
|
+
if _is_writing:
|
174
|
+
return n
|
175
|
+
|
176
|
+
_is_writing = True
|
177
|
+
try:
|
178
|
+
for cb in callbacks.values():
|
179
|
+
cb(s, n)
|
180
|
+
|
181
|
+
except BaseException as e:
|
182
|
+
# Clear all callbacks on any exception to avoid infinite loops:
|
183
|
+
#
|
184
|
+
# * If we re-raise, an exception handler is likely to print
|
185
|
+
# the exception to the console and trigger callbacks again
|
186
|
+
# * If we log, we can't guarantee that this doesn't print
|
187
|
+
# to console.
|
188
|
+
#
|
189
|
+
# This is especially important for KeyboardInterrupt.
|
190
|
+
_stderr_callbacks.clear()
|
191
|
+
_stdout_callbacks.clear()
|
192
|
+
|
193
|
+
if isinstance(e, Exception):
|
194
|
+
# We suppress Exceptions so that bugs in W&B code don't
|
195
|
+
# cause the user's print() statements to raise errors.
|
196
|
+
_logger.exception("Error in console callback, clearing all!")
|
197
|
+
else:
|
198
|
+
# Re-raise errors like KeyboardInterrupt.
|
199
|
+
raise
|
200
|
+
|
201
|
+
finally:
|
202
|
+
_is_writing = False
|
156
203
|
|
157
204
|
return n
|
158
205
|
|
wandb/sdk/wandb_init.py
CHANGED
@@ -740,7 +740,6 @@ class _WandbInit:
|
|
740
740
|
drun._config.update(config.sweep_no_artifacts)
|
741
741
|
drun._config.update(config.base_no_artifacts)
|
742
742
|
drun.summary = SummaryDisabled() # type: ignore
|
743
|
-
drun._Run__metadata = wandb.sdk.wandb_metadata.Metadata()
|
744
743
|
|
745
744
|
# methods
|
746
745
|
drun.log = lambda data, *_, **__: drun.summary.update(data) # type: ignore[method-assign]
|
@@ -1365,7 +1364,7 @@ def init( # noqa: C901
|
|
1365
1364
|
the UI.
|
1366
1365
|
If resuming a run, the tags provided here will replace any existing
|
1367
1366
|
tags. To add tags to a resumed run without overwriting the current
|
1368
|
-
tags, use `run.tags +=
|
1367
|
+
tags, use `run.tags += ("new_tag",)` after calling `run = wandb.init()`.
|
1369
1368
|
config: Sets `wandb.config`, a dictionary-like object for storing input
|
1370
1369
|
parameters to your run, such as model hyperparameters or data
|
1371
1370
|
preprocessing settings.
|
wandb/sdk/wandb_require.py
CHANGED
wandb/sdk/wandb_run.py
CHANGED
@@ -35,13 +35,13 @@ from wandb.integration.torch import wandb_torch
|
|
35
35
|
from wandb.plot import CustomChart, Visualize
|
36
36
|
from wandb.proto.wandb_deprecated import Deprecated
|
37
37
|
from wandb.proto.wandb_internal_pb2 import (
|
38
|
-
MetadataRequest,
|
39
38
|
MetricRecord,
|
40
39
|
PollExitResponse,
|
41
40
|
Result,
|
42
41
|
RunRecord,
|
43
42
|
)
|
44
43
|
from wandb.sdk.artifacts._internal_artifact import InternalArtifact
|
44
|
+
from wandb.sdk.artifacts._validators import is_artifact_registry_project
|
45
45
|
from wandb.sdk.artifacts.artifact import Artifact
|
46
46
|
from wandb.sdk.internal import job_builder
|
47
47
|
from wandb.sdk.lib import asyncio_compat, wb_logging
|
@@ -63,7 +63,7 @@ from wandb.util import (
|
|
63
63
|
from . import wandb_config, wandb_metric, wandb_summary
|
64
64
|
from .artifacts._validators import (
|
65
65
|
MAX_ARTIFACT_METADATA_KEYS,
|
66
|
-
|
66
|
+
ArtifactPath,
|
67
67
|
validate_aliases,
|
68
68
|
validate_tags,
|
69
69
|
)
|
@@ -92,7 +92,6 @@ from .mailbox import (
|
|
92
92
|
wait_with_progress,
|
93
93
|
)
|
94
94
|
from .wandb_alerts import AlertLevel
|
95
|
-
from .wandb_metadata import Metadata
|
96
95
|
from .wandb_settings import Settings
|
97
96
|
from .wandb_setup import _WandbSetup
|
98
97
|
|
@@ -168,6 +167,7 @@ class RunStatusChecker:
|
|
168
167
|
self,
|
169
168
|
run_id: str,
|
170
169
|
interface: InterfaceBase,
|
170
|
+
settings: Settings,
|
171
171
|
stop_polling_interval: int = 15,
|
172
172
|
retry_polling_interval: int = 5,
|
173
173
|
internal_messages_polling_interval: int = 10,
|
@@ -177,6 +177,7 @@ class RunStatusChecker:
|
|
177
177
|
self._stop_polling_interval = stop_polling_interval
|
178
178
|
self._retry_polling_interval = retry_polling_interval
|
179
179
|
self._internal_messages_polling_interval = internal_messages_polling_interval
|
180
|
+
self._settings = settings
|
180
181
|
|
181
182
|
self._join_event = threading.Event()
|
182
183
|
|
@@ -318,9 +319,15 @@ class RunStatusChecker:
|
|
318
319
|
|
319
320
|
def check_internal_messages(self) -> None:
|
320
321
|
def _process_internal_messages(result: Result) -> None:
|
322
|
+
if (
|
323
|
+
not self._settings.show_warnings
|
324
|
+
or self._settings.quiet
|
325
|
+
or self._settings.silent
|
326
|
+
):
|
327
|
+
return
|
321
328
|
internal_messages = result.response.internal_messages_response
|
322
329
|
for msg in internal_messages.messages.warning:
|
323
|
-
wandb.termwarn(msg)
|
330
|
+
wandb.termwarn(msg, repeat=False)
|
324
331
|
|
325
332
|
with wb_logging.log_to_run(self._run_id):
|
326
333
|
try:
|
@@ -620,8 +627,6 @@ class Run:
|
|
620
627
|
)
|
621
628
|
self.summary._set_update_callback(self._summary_update_callback)
|
622
629
|
|
623
|
-
self.__metadata: Metadata | None = None
|
624
|
-
|
625
630
|
self._step = 0
|
626
631
|
self._starting_step = 0
|
627
632
|
self._start_runtime = 0
|
@@ -1647,7 +1652,7 @@ class Run:
|
|
1647
1652
|
def _populate_git_info(self) -> None:
|
1648
1653
|
from .lib.gitlib import GitRepo
|
1649
1654
|
|
1650
|
-
# Use user
|
1655
|
+
# Use user-provided git info if available, otherwise resolve it from the environment
|
1651
1656
|
try:
|
1652
1657
|
repo = GitRepo(
|
1653
1658
|
root=self._settings.git_root,
|
@@ -2481,6 +2486,7 @@ class Run:
|
|
2481
2486
|
self._run_status_checker = RunStatusChecker(
|
2482
2487
|
self._settings.run_id,
|
2483
2488
|
interface=self._backend.interface,
|
2489
|
+
settings=self._settings,
|
2484
2490
|
)
|
2485
2491
|
self._run_status_checker.start()
|
2486
2492
|
|
@@ -2947,13 +2953,6 @@ class Run:
|
|
2947
2953
|
The linked artifact if linking was successful, otherwise None.
|
2948
2954
|
|
2949
2955
|
"""
|
2950
|
-
portfolio, project, entity = wandb.util._parse_entity_project_item(target_path)
|
2951
|
-
if aliases is None:
|
2952
|
-
aliases = []
|
2953
|
-
|
2954
|
-
if not self._backend or not self._backend.interface:
|
2955
|
-
return None
|
2956
|
-
|
2957
2956
|
if artifact.is_draft() and not artifact._is_draft_save_started():
|
2958
2957
|
artifact = self._log_artifact(artifact)
|
2959
2958
|
|
@@ -2961,52 +2960,17 @@ class Run:
|
|
2961
2960
|
# TODO: implement offline mode + sync
|
2962
2961
|
raise NotImplementedError
|
2963
2962
|
|
2964
|
-
#
|
2965
|
-
|
2966
|
-
|
2967
|
-
|
2968
|
-
|
2969
|
-
|
2970
|
-
|
2971
|
-
|
2972
|
-
|
2973
|
-
project = project or self.project
|
2974
|
-
entity = entity or self.entity
|
2975
|
-
handle = self._backend.interface.deliver_link_artifact(
|
2976
|
-
artifact,
|
2977
|
-
portfolio,
|
2978
|
-
aliases,
|
2979
|
-
entity,
|
2980
|
-
project,
|
2981
|
-
organization,
|
2982
|
-
)
|
2983
|
-
if artifact._ttl_duration_seconds is not None:
|
2984
|
-
wandb.termwarn(
|
2985
|
-
"Artifact TTL will be disabled for source artifacts that are linked to portfolios."
|
2986
|
-
)
|
2987
|
-
result = handle.wait_or(timeout=None)
|
2988
|
-
response = result.response.link_artifact_response
|
2989
|
-
if response.error_message:
|
2990
|
-
wandb.termerror(response.error_message)
|
2991
|
-
return None
|
2992
|
-
if response.version_index is None:
|
2993
|
-
wandb.termerror(
|
2994
|
-
"Error fetching the linked artifact's version index after linking"
|
2995
|
-
)
|
2996
|
-
return None
|
2963
|
+
# Normalize the target "entity/project/collection" with defaults
|
2964
|
+
# inferred from this run's entity and project, if needed.
|
2965
|
+
#
|
2966
|
+
# HOWEVER, if the target path is a registry collection, avoid setting
|
2967
|
+
# the target entity to the run's entity. Instead, delegate to
|
2968
|
+
# Artifact.link() to resolve the required org entity.
|
2969
|
+
target = ArtifactPath.from_str(target_path)
|
2970
|
+
if not (target.project and is_artifact_registry_project(target.project)):
|
2971
|
+
target = target.with_defaults(prefix=self.entity, project=self.project)
|
2997
2972
|
|
2998
|
-
|
2999
|
-
artifact_name = f"{entity}/{project}/{portfolio}:v{response.version_index}"
|
3000
|
-
if is_artifact_registry_project(project):
|
3001
|
-
if organization:
|
3002
|
-
artifact_name = f"{organization}/{project}/{portfolio}:v{response.version_index}"
|
3003
|
-
else:
|
3004
|
-
artifact_name = f"{project}/{portfolio}:v{response.version_index}"
|
3005
|
-
linked_artifact = self._public_api()._artifact(artifact_name)
|
3006
|
-
except Exception as e:
|
3007
|
-
wandb.termerror(f"Error fetching link artifact after linking: {e}")
|
3008
|
-
return None
|
3009
|
-
return linked_artifact
|
2973
|
+
return artifact.link(target.to_str(), aliases)
|
3010
2974
|
|
3011
2975
|
@_log_to_run
|
3012
2976
|
@_raise_if_finished
|
@@ -3734,60 +3698,6 @@ class Run:
|
|
3734
3698
|
logger.exception("Error getting system metrics.")
|
3735
3699
|
return {}
|
3736
3700
|
|
3737
|
-
@property
|
3738
|
-
@_log_to_run
|
3739
|
-
@_attach
|
3740
|
-
@_raise_if_finished
|
3741
|
-
def _metadata(self) -> Metadata | None:
|
3742
|
-
"""The metadata associated with this run.
|
3743
|
-
|
3744
|
-
NOTE: Automatically collected metadata can be overridden by the user.
|
3745
|
-
"""
|
3746
|
-
if not self._backend or not self._backend.interface:
|
3747
|
-
return self.__metadata
|
3748
|
-
|
3749
|
-
# Initialize the metadata object if it doesn't exist.
|
3750
|
-
if self.__metadata is None:
|
3751
|
-
self.__metadata = Metadata()
|
3752
|
-
self.__metadata._set_callback(self._metadata_callback)
|
3753
|
-
|
3754
|
-
handle = self._backend.interface.deliver_get_system_metadata()
|
3755
|
-
|
3756
|
-
try:
|
3757
|
-
result = handle.wait_or(timeout=1)
|
3758
|
-
except TimeoutError:
|
3759
|
-
logger.exception("Timeout getting run metadata.")
|
3760
|
-
return None
|
3761
|
-
|
3762
|
-
response = result.response.get_system_metadata_response
|
3763
|
-
|
3764
|
-
# Temporarily disable the callback to prevent triggering
|
3765
|
-
# an update call to wandb-core with the callback.
|
3766
|
-
with self.__metadata.disable_callback():
|
3767
|
-
# Values stored in the metadata object take precedence.
|
3768
|
-
self.__metadata.update_from_proto(response.metadata, skip_existing=True)
|
3769
|
-
|
3770
|
-
return self.__metadata
|
3771
|
-
|
3772
|
-
@_log_to_run
|
3773
|
-
@_raise_if_finished
|
3774
|
-
@_attach
|
3775
|
-
def _metadata_callback(
|
3776
|
-
self,
|
3777
|
-
metadata: MetadataRequest,
|
3778
|
-
) -> None:
|
3779
|
-
"""Callback to publish Metadata to wandb-core upon user updates."""
|
3780
|
-
# ignore updates if the attached to another run
|
3781
|
-
if self._is_attached:
|
3782
|
-
wandb.termwarn(
|
3783
|
-
"Metadata updates are ignored when attached to another run.",
|
3784
|
-
repeat=False,
|
3785
|
-
)
|
3786
|
-
return
|
3787
|
-
|
3788
|
-
if self._backend and self._backend.interface:
|
3789
|
-
self._backend.interface.publish_metadata(metadata)
|
3790
|
-
|
3791
3701
|
# ------------------------------------------------------------------------------
|
3792
3702
|
# HEADER
|
3793
3703
|
# ------------------------------------------------------------------------------
|