wandb 0.19.12rc1__py3-none-win32.whl → 0.20.1__py3-none-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. wandb/__init__.py +1 -2
  2. wandb/__init__.pyi +3 -6
  3. wandb/_iterutils.py +26 -7
  4. wandb/_pydantic/__init__.py +2 -1
  5. wandb/_pydantic/utils.py +7 -0
  6. wandb/agents/pyagent.py +9 -15
  7. wandb/analytics/sentry.py +1 -2
  8. wandb/apis/attrs.py +3 -4
  9. wandb/apis/importers/internals/util.py +1 -1
  10. wandb/apis/importers/validation.py +2 -2
  11. wandb/apis/importers/wandb.py +30 -25
  12. wandb/apis/normalize.py +2 -2
  13. wandb/apis/public/__init__.py +1 -0
  14. wandb/apis/public/api.py +37 -33
  15. wandb/apis/public/artifacts.py +103 -72
  16. wandb/apis/public/jobs.py +3 -2
  17. wandb/apis/public/registries/registries_search.py +4 -2
  18. wandb/apis/public/registries/registry.py +1 -1
  19. wandb/apis/public/registries/utils.py +9 -9
  20. wandb/apis/public/runs.py +18 -6
  21. wandb/automations/_filters/expressions.py +1 -1
  22. wandb/automations/_filters/operators.py +1 -1
  23. wandb/automations/_filters/run_metrics.py +1 -1
  24. wandb/beta/workflows.py +6 -5
  25. wandb/bin/gpu_stats.exe +0 -0
  26. wandb/bin/wandb-core +0 -0
  27. wandb/cli/cli.py +54 -73
  28. wandb/docker/__init__.py +21 -74
  29. wandb/docker/names.py +40 -0
  30. wandb/env.py +0 -1
  31. wandb/errors/util.py +1 -1
  32. wandb/filesync/step_checksum.py +1 -1
  33. wandb/filesync/step_upload.py +1 -1
  34. wandb/integration/diffusers/resolvers/multimodal.py +1 -2
  35. wandb/integration/gym/__init__.py +5 -6
  36. wandb/integration/keras/callbacks/model_checkpoint.py +2 -2
  37. wandb/integration/keras/keras.py +13 -19
  38. wandb/integration/kfp/kfp_patch.py +2 -3
  39. wandb/integration/langchain/wandb_tracer.py +1 -1
  40. wandb/integration/metaflow/metaflow.py +13 -13
  41. wandb/integration/openai/fine_tuning.py +3 -2
  42. wandb/integration/sagemaker/auth.py +2 -1
  43. wandb/integration/sklearn/utils.py +2 -1
  44. wandb/integration/tensorboard/__init__.py +1 -1
  45. wandb/integration/tensorboard/log.py +2 -5
  46. wandb/integration/tensorflow/__init__.py +2 -2
  47. wandb/jupyter.py +20 -17
  48. wandb/plot/confusion_matrix.py +1 -1
  49. wandb/plot/utils.py +8 -7
  50. wandb/proto/v3/wandb_internal_pb2.py +355 -335
  51. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  52. wandb/proto/v3/wandb_telemetry_pb2.py +12 -12
  53. wandb/proto/v4/wandb_internal_pb2.py +339 -335
  54. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  55. wandb/proto/v4/wandb_telemetry_pb2.py +12 -12
  56. wandb/proto/v5/wandb_internal_pb2.py +339 -335
  57. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  58. wandb/proto/v5/wandb_telemetry_pb2.py +12 -12
  59. wandb/proto/v6/wandb_internal_pb2.py +339 -335
  60. wandb/proto/v6/wandb_settings_pb2.py +2 -2
  61. wandb/proto/v6/wandb_telemetry_pb2.py +12 -12
  62. wandb/proto/wandb_deprecated.py +6 -8
  63. wandb/sdk/artifacts/_internal_artifact.py +43 -0
  64. wandb/sdk/artifacts/_validators.py +55 -35
  65. wandb/sdk/artifacts/artifact.py +117 -115
  66. wandb/sdk/artifacts/artifact_download_logger.py +2 -0
  67. wandb/sdk/artifacts/artifact_saver.py +1 -3
  68. wandb/sdk/artifacts/artifact_state.py +2 -0
  69. wandb/sdk/artifacts/artifact_ttl.py +2 -0
  70. wandb/sdk/artifacts/exceptions.py +14 -0
  71. wandb/sdk/artifacts/staging.py +2 -0
  72. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +2 -6
  73. wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
  74. wandb/sdk/artifacts/storage_handlers/tracking_handler.py +2 -6
  75. wandb/sdk/artifacts/storage_handlers/wb_artifact_handler.py +1 -5
  76. wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +1 -1
  77. wandb/sdk/artifacts/storage_layout.py +2 -0
  78. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +3 -3
  79. wandb/sdk/backend/backend.py +11 -182
  80. wandb/sdk/data_types/_dtypes.py +2 -6
  81. wandb/sdk/data_types/audio.py +20 -3
  82. wandb/sdk/data_types/base_types/media.py +12 -7
  83. wandb/sdk/data_types/base_types/wb_value.py +8 -18
  84. wandb/sdk/data_types/bokeh.py +19 -2
  85. wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +17 -1
  86. wandb/sdk/data_types/helper_types/image_mask.py +7 -1
  87. wandb/sdk/data_types/html.py +4 -4
  88. wandb/sdk/data_types/image.py +178 -103
  89. wandb/sdk/data_types/molecule.py +6 -6
  90. wandb/sdk/data_types/object_3d.py +10 -5
  91. wandb/sdk/data_types/saved_model.py +11 -6
  92. wandb/sdk/data_types/table.py +313 -83
  93. wandb/sdk/data_types/table_decorators.py +108 -0
  94. wandb/sdk/data_types/utils.py +43 -7
  95. wandb/sdk/data_types/video.py +21 -3
  96. wandb/sdk/interface/interface.py +10 -0
  97. wandb/sdk/internal/datastore.py +2 -6
  98. wandb/sdk/internal/file_pusher.py +1 -5
  99. wandb/sdk/internal/file_stream.py +8 -17
  100. wandb/sdk/internal/handler.py +2 -2
  101. wandb/sdk/internal/incremental_table_util.py +53 -0
  102. wandb/sdk/internal/internal.py +3 -5
  103. wandb/sdk/internal/internal_api.py +66 -89
  104. wandb/sdk/internal/job_builder.py +2 -7
  105. wandb/sdk/internal/profiler.py +2 -2
  106. wandb/sdk/internal/progress.py +1 -3
  107. wandb/sdk/internal/run.py +1 -6
  108. wandb/sdk/internal/sender.py +24 -36
  109. wandb/sdk/internal/system/assets/aggregators.py +1 -7
  110. wandb/sdk/internal/system/assets/disk.py +3 -3
  111. wandb/sdk/internal/system/assets/gpu.py +4 -4
  112. wandb/sdk/internal/system/assets/gpu_amd.py +4 -4
  113. wandb/sdk/internal/system/assets/interfaces.py +6 -6
  114. wandb/sdk/internal/system/assets/tpu.py +1 -1
  115. wandb/sdk/internal/system/assets/trainium.py +6 -6
  116. wandb/sdk/internal/system/system_info.py +5 -7
  117. wandb/sdk/internal/system/system_monitor.py +4 -4
  118. wandb/sdk/internal/tb_watcher.py +5 -7
  119. wandb/sdk/launch/_launch.py +1 -1
  120. wandb/sdk/launch/_project_spec.py +19 -20
  121. wandb/sdk/launch/agent/agent.py +3 -3
  122. wandb/sdk/launch/agent/config.py +1 -1
  123. wandb/sdk/launch/agent/job_status_tracker.py +2 -2
  124. wandb/sdk/launch/builder/build.py +2 -3
  125. wandb/sdk/launch/builder/kaniko_builder.py +5 -4
  126. wandb/sdk/launch/environment/gcp_environment.py +1 -2
  127. wandb/sdk/launch/registry/azure_container_registry.py +2 -2
  128. wandb/sdk/launch/registry/elastic_container_registry.py +2 -2
  129. wandb/sdk/launch/registry/google_artifact_registry.py +3 -3
  130. wandb/sdk/launch/runner/abstract.py +5 -5
  131. wandb/sdk/launch/runner/kubernetes_monitor.py +2 -2
  132. wandb/sdk/launch/runner/kubernetes_runner.py +1 -1
  133. wandb/sdk/launch/runner/sagemaker_runner.py +2 -4
  134. wandb/sdk/launch/runner/vertex_runner.py +2 -7
  135. wandb/sdk/launch/sweeps/__init__.py +1 -1
  136. wandb/sdk/launch/sweeps/scheduler.py +2 -2
  137. wandb/sdk/launch/sweeps/utils.py +3 -3
  138. wandb/sdk/launch/utils.py +3 -4
  139. wandb/sdk/lib/apikey.py +5 -8
  140. wandb/sdk/lib/config_util.py +3 -3
  141. wandb/sdk/lib/fsm.py +3 -18
  142. wandb/sdk/lib/gitlib.py +6 -5
  143. wandb/sdk/lib/ipython.py +2 -2
  144. wandb/sdk/lib/json_util.py +9 -14
  145. wandb/sdk/lib/printer.py +3 -8
  146. wandb/sdk/lib/redirect.py +1 -1
  147. wandb/sdk/lib/retry.py +3 -7
  148. wandb/sdk/lib/run_moment.py +2 -2
  149. wandb/sdk/lib/service_connection.py +3 -1
  150. wandb/sdk/lib/service_token.py +1 -2
  151. wandb/sdk/mailbox/mailbox_handle.py +3 -7
  152. wandb/sdk/mailbox/response_handle.py +2 -6
  153. wandb/sdk/service/streams.py +3 -7
  154. wandb/sdk/verify/verify.py +5 -6
  155. wandb/sdk/wandb_config.py +1 -1
  156. wandb/sdk/wandb_init.py +38 -106
  157. wandb/sdk/wandb_login.py +7 -6
  158. wandb/sdk/wandb_run.py +52 -240
  159. wandb/sdk/wandb_settings.py +71 -60
  160. wandb/sdk/wandb_setup.py +40 -14
  161. wandb/sdk/wandb_watch.py +5 -7
  162. wandb/sync/__init__.py +1 -1
  163. wandb/sync/sync.py +13 -13
  164. wandb/util.py +17 -35
  165. wandb/wandb_agent.py +8 -11
  166. {wandb-0.19.12rc1.dist-info → wandb-0.20.1.dist-info}/METADATA +5 -5
  167. {wandb-0.19.12rc1.dist-info → wandb-0.20.1.dist-info}/RECORD +170 -168
  168. wandb/docker/auth.py +0 -435
  169. wandb/docker/www_authenticate.py +0 -94
  170. {wandb-0.19.12rc1.dist-info → wandb-0.20.1.dist-info}/WHEEL +0 -0
  171. {wandb-0.19.12rc1.dist-info → wandb-0.20.1.dist-info}/entry_points.txt +0 -0
  172. {wandb-0.19.12rc1.dist-info → wandb-0.20.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,108 @@
1
+ """Decorators for W&B Table operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from functools import wraps
6
+ from typing import Any, Callable, TypeVar
7
+
8
+ from typing_extensions import Concatenate, ParamSpec
9
+
10
+ import wandb
11
+
12
+ _P = ParamSpec("_P")
13
+ _T = TypeVar("_T")
14
+
15
+
16
+ def allow_relogging_after_mutation(
17
+ method: Callable[Concatenate[wandb.Table, _P], _T],
18
+ ) -> Callable[Concatenate[wandb.Table, _P], _T]:
19
+ """Decorator that handles table state after mutations based on log_mode.
20
+
21
+ For MUTABLE tables, resets the run and artifact target to allow re-logging.
22
+ For IMMUTABLE tables, warns if attempting to mutate after logging.
23
+ """
24
+
25
+ @wraps(method)
26
+ def wrapper(self: wandb.Table, *args: Any, **kwargs: Any) -> _T:
27
+ has_been_logged = self._run is not None or self._artifact_target is not None
28
+
29
+ if self.log_mode == "MUTABLE":
30
+ self._run = None
31
+ self._artifact_target = None
32
+ self._path = None
33
+ self._sha256 = None
34
+ elif self.log_mode == "IMMUTABLE" and has_been_logged:
35
+ wandb.termwarn(
36
+ "You are mutating a Table with log_mode='IMMUTABLE' that has been "
37
+ "logged already. Subsequent log() calls will have no effect. "
38
+ "Set log_mode='MUTABLE' to enable re-logging after mutations",
39
+ repeat=False,
40
+ )
41
+
42
+ return method(self, *args, **kwargs)
43
+
44
+ return wrapper
45
+
46
+
47
+ def allow_incremental_logging_after_append(
48
+ method: Callable[Concatenate[wandb.Table, _P], _T],
49
+ ) -> Callable[Concatenate[wandb.Table, _P], _T]:
50
+ """Decorator that handles incremental logging state after append operations.
51
+
52
+ For INCREMENTAL tables, manages artifact references and increments counters
53
+ to support partial data logging.
54
+ """
55
+
56
+ @wraps(method)
57
+ def wrapper(self: wandb.Table, *args: Any, **kwargs: Any) -> _T:
58
+ res = method(self, *args, **kwargs)
59
+
60
+ if self.log_mode != "INCREMENTAL" or self._artifact_target is None:
61
+ return res
62
+
63
+ art_entry_url = self._get_artifact_entry_ref_url()
64
+ if art_entry_url is not None:
65
+ if self._previous_increments_paths is None:
66
+ raise ValueError(
67
+ "_previous_increments_paths must be set if incremental"
68
+ " table has been logged already"
69
+ )
70
+ self._previous_increments_paths.append(art_entry_url)
71
+ self._run = None
72
+ self._artifact_target = None
73
+ self._path = None
74
+ self._sha256 = None
75
+
76
+ if self._increment_num is None:
77
+ raise ValueError(
78
+ "_increment_num must be set if incremental table has been"
79
+ " logged already"
80
+ )
81
+
82
+ self._increment_num += 1
83
+ if self._increment_num > 99:
84
+ wandb.termwarn(
85
+ "You have exceeded 100 increments for this table. "
86
+ "Only the latest 100 increments will be visualized in the run workspace.",
87
+ repeat=False,
88
+ )
89
+ return res
90
+
91
+ return wrapper
92
+
93
+
94
+ def ensure_not_incremental(
95
+ method: Callable[Concatenate[wandb.Table, _P], _T],
96
+ ) -> Callable[Concatenate[wandb.Table, _P], _T]:
97
+ """Decorator that checks if log mode is incremental to disallow methods from being called."""
98
+
99
+ @wraps(method)
100
+ def wrapper(self: wandb.Table, *args: Any, **kwargs: Any) -> _T:
101
+ if self.log_mode == "INCREMENTAL":
102
+ raise wandb.Error(
103
+ f"Operation '{method.__name__}' is not supported for tables with "
104
+ "log_mode='INCREMENTAL'. Use a different log mode like 'MUTABLE' or 'IMMUTABLE'."
105
+ )
106
+ return method(self, *args, **kwargs)
107
+
108
+ return wrapper
@@ -1,13 +1,13 @@
1
1
  import datetime
2
2
  import logging
3
3
  import os
4
- import re
5
4
  from decimal import Decimal
6
5
  from typing import TYPE_CHECKING, Optional, Sequence, Union, cast
7
6
 
8
7
  import wandb
9
8
  from wandb import util
10
9
 
10
+ from ..internal import incremental_table_util
11
11
  from .base_types.media import BatchableMedia, Media
12
12
  from .base_types.wb_value import WBValue
13
13
  from .image import _server_accepts_image_filenames
@@ -148,11 +148,7 @@ def val_to_json(
148
148
  "partitioned-table",
149
149
  "joined-table",
150
150
  ]:
151
- # Sanitize the key to meet the constraints of artifact names.
152
- sanitized_key = re.sub(r"[^a-zA-Z0-9_\-.]+", "", key)
153
- art = wandb.Artifact(f"run-{run.id}-{sanitized_key}", "run_table")
154
- art.add(val, key)
155
- run.log_artifact(art)
151
+ _log_table_artifact(val, key, run)
156
152
 
157
153
  # Partitioned tables and joined tables do not support being bound to runs.
158
154
  if not (
@@ -161,11 +157,51 @@ def val_to_json(
161
157
  ):
162
158
  val.bind_to_run(run, key, namespace)
163
159
 
164
- return val.to_json(run)
160
+ res = val.to_json(run)
161
+
162
+ if isinstance(val, wandb.Table) and val.log_mode == "INCREMENTAL":
163
+ # Set the _last_logged_idx AFTER the Table has been logged and
164
+ # bound to the run.
165
+ val._last_logged_idx = len(val.data) - 1
166
+ return res
165
167
 
166
168
  return converted # type: ignore
167
169
 
168
170
 
171
+ def _log_table_artifact(val: "Media", key: str, run: "LocalRun") -> None:
172
+ """Log a table to the run based on the table type and logging mode.
173
+
174
+ Creates and logs a `run_table` type for Table, PartitionedTable, and
175
+ JoinedTable values. For tables with log_mode="INCREMENTAL", creates and
176
+ logs an incremental artifact of type `wandb-run-incremental-table.`
177
+
178
+ Args:
179
+ val: A wbvalue with log_type "table", "partitioned-table",
180
+ or "joined-table."
181
+ key: The key used to log val.
182
+ run: The LocalRun used to log val.
183
+ """
184
+ from wandb.sdk.artifacts._internal_artifact import InternalArtifact
185
+
186
+ if isinstance(val, wandb.Table) and val.log_mode == "INCREMENTAL":
187
+ if (
188
+ run.resumed
189
+ and val._previous_increments_paths is None
190
+ and val._increment_num is None
191
+ ):
192
+ val._load_incremental_table_state_from_resumed_run(run, key)
193
+ else:
194
+ val._set_incremental_table_run_target(run)
195
+ art = incremental_table_util.init_artifact(run, key)
196
+ entry_name = incremental_table_util.get_entry_name(val, key)
197
+ else:
198
+ art = InternalArtifact(f"run-{run.id}-{key}", "run_table")
199
+ entry_name = key
200
+
201
+ art.add(val, entry_name)
202
+ run.log_artifact(art)
203
+
204
+
169
205
  def _prune_max_seq(seq: Sequence["BatchableMedia"]) -> Sequence["BatchableMedia"]:
170
206
  # If media type has a max respect it
171
207
  items = seq
@@ -1,6 +1,7 @@
1
1
  import functools
2
2
  import logging
3
3
  import os
4
+ import pathlib
4
5
  from io import BytesIO
5
6
  from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type, Union
6
7
 
@@ -34,12 +35,26 @@ if TYPE_CHECKING: # pragma: no cover
34
35
  def write_gif_with_image_io(
35
36
  clip: Any, filename: str, fps: Optional[int] = None
36
37
  ) -> None:
38
+ from packaging.version import parse
39
+
37
40
  imageio = util.get_module(
38
41
  "imageio",
39
42
  required='wandb.Video requires imageio when passing raw data. Install with "pip install wandb[media]"',
40
43
  )
41
44
 
42
- writer = imageio.save(filename, fps=clip.fps, quantizer=0, palettesize=256, loop=0)
45
+ if parse(imageio.__version__) < parse("2.28.1"):
46
+ raise ValueError(
47
+ "imageio version 2.28.1 or higher is required to encode gifs. "
48
+ "Please upgrade imageio with `pip install imageio>=2.28.1`"
49
+ )
50
+
51
+ writer = imageio.save(
52
+ filename,
53
+ quantizer=0,
54
+ palettesize=256,
55
+ loop=0,
56
+ duration=1000 / clip.fps,
57
+ )
43
58
 
44
59
  for frame in clip.iter_frames(fps=fps, dtype="uint8"):
45
60
  writer.append_data(frame)
@@ -57,7 +72,7 @@ class Video(BatchableMedia):
57
72
 
58
73
  def __init__(
59
74
  self,
60
- data_or_path: Union["np.ndarray", str, "TextIO", "BytesIO"],
75
+ data_or_path: Union[str, pathlib.Path, "np.ndarray", "TextIO", "BytesIO"],
61
76
  caption: Optional[str] = None,
62
77
  fps: Optional[int] = None,
63
78
  format: Optional[Literal["gif", "mp4", "webm", "ogg"]] = None,
@@ -84,6 +99,7 @@ class Video(BatchableMedia):
84
99
  or io object. This parameter will be used to determine the format
85
100
  to use when encoding the video data. Accepted values are "gif",
86
101
  "mp4", "webm", or "ogg".
102
+ If no value is provided, the default format will be "gif".
87
103
 
88
104
  Examples:
89
105
  ### Log a numpy array as a video
@@ -130,7 +146,9 @@ class Video(BatchableMedia):
130
146
  with open(filename, "wb") as f:
131
147
  f.write(data_or_path.read())
132
148
  self._set_file(filename, is_tmp=True)
133
- elif isinstance(data_or_path, str):
149
+ elif isinstance(data_or_path, (str, pathlib.Path)):
150
+ data_or_path = str(data_or_path)
151
+
134
152
  _, ext = os.path.splitext(data_or_path)
135
153
  ext = ext[1:].lower()
136
154
  if ext not in Video.EXTS:
@@ -166,6 +166,16 @@ class InterfaceBase:
166
166
  proto_run.host = run._settings.host
167
167
  if run._settings.resumed:
168
168
  proto_run.resumed = run._settings.resumed
169
+ if run._settings.fork_from:
170
+ run_moment = run._settings.fork_from
171
+ proto_run.branch_point.run = run_moment.run
172
+ proto_run.branch_point.metric = run_moment.metric
173
+ proto_run.branch_point.value = run_moment.value
174
+ if run._settings.resume_from:
175
+ run_moment = run._settings.resume_from
176
+ proto_run.branch_point.run = run_moment.run
177
+ proto_run.branch_point.metric = run_moment.metric
178
+ proto_run.branch_point.value = run_moment.value
169
179
  if run._forked:
170
180
  proto_run.forked = run._forked
171
181
  if run._config is not None:
@@ -126,9 +126,7 @@ class DataStore:
126
126
  return None
127
127
  assert (
128
128
  len(header) == LEVELDBLOG_HEADER_LEN
129
- ), "record header is {} bytes instead of the expected {}".format(
130
- len(header), LEVELDBLOG_HEADER_LEN
131
- )
129
+ ), f"record header is {len(header)} bytes instead of the expected {LEVELDBLOG_HEADER_LEN}"
132
130
  fields = struct.unpack("<IHB", header)
133
131
  checksum, dlength, dtype = fields
134
132
  # check len, better fit in the block
@@ -195,9 +193,7 @@ class DataStore:
195
193
  header = self._fp.read(LEVELDBLOG_HEADER_LEN)
196
194
  assert (
197
195
  len(header) == LEVELDBLOG_HEADER_LEN
198
- ), "header is {} bytes instead of the expected {}".format(
199
- len(header), LEVELDBLOG_HEADER_LEN
200
- )
196
+ ), f"header is {len(header)} bytes instead of the expected {LEVELDBLOG_HEADER_LEN}"
201
197
  ident, magic, version = struct.unpack("<4sHB", header)
202
198
  if ident != strtobytes(LEVELDBLOG_HEADER_IDENT):
203
199
  raise Exception("Invalid header")
@@ -98,11 +98,7 @@ class FilePusher:
98
98
  if not self.is_alive():
99
99
  stop = True
100
100
  summary = self._stats.summary()
101
- line = " {:.2f}MB of {:.2f}MB uploaded ({:.2f}MB deduped)\r".format(
102
- summary.uploaded_bytes / 1048576.0,
103
- summary.total_bytes / 1048576.0,
104
- summary.deduped_bytes / 1048576.0,
105
- )
101
+ line = f" {summary.uploaded_bytes / 1048576.0:.2f}MB of {summary.total_bytes / 1048576.0:.2f}MB uploaded ({summary.deduped_bytes / 1048576.0:.2f}MB deduped)\r"
106
102
  line = spinner_states[step % 4] + line
107
103
  step += 1
108
104
  wandb.termlog(line, newline=False, prefix=prefix)
@@ -75,7 +75,7 @@ class DefaultFilePolicy:
75
75
 
76
76
  # get key size and convert to MB
77
77
  key_sizes = [(k, len(json.dumps(v))) for k, v in loaded.items()]
78
- key_msg = [f"{k}: {v/1048576:.5f} MB" for k, v in key_sizes]
78
+ key_msg = [f"{k}: {v / 1048576:.5f} MB" for k, v in key_sizes]
79
79
  wandb.termerror(f"Step: {loaded['_step']} | {key_msg}", repeat=False)
80
80
  self.has_debug_log = True
81
81
 
@@ -88,10 +88,7 @@ class JsonlFilePolicy(DefaultFilePolicy):
88
88
  chunk_data = []
89
89
  for chunk in chunks:
90
90
  if len(chunk.data) > util.MAX_LINE_BYTES:
91
- msg = "Metric data exceeds maximum size of {} ({})".format(
92
- util.to_human_size(util.MAX_LINE_BYTES),
93
- util.to_human_size(len(chunk.data)),
94
- )
91
+ msg = f"Metric data exceeds maximum size of {util.to_human_size(util.MAX_LINE_BYTES)} ({util.to_human_size(len(chunk.data))})"
95
92
  wandb.termerror(msg, repeat=False)
96
93
  wandb._sentry.message(msg, repeat=False)
97
94
  self._debug_log(chunk.data)
@@ -108,9 +105,7 @@ class SummaryFilePolicy(DefaultFilePolicy):
108
105
  def process_chunks(self, chunks: List[Chunk]) -> Union[bool, "ProcessedChunk"]:
109
106
  data = chunks[-1].data
110
107
  if len(data) > util.MAX_LINE_BYTES:
111
- msg = "Summary data exceeds maximum size of {}. Dropping it.".format(
112
- util.to_human_size(util.MAX_LINE_BYTES)
113
- )
108
+ msg = f"Summary data exceeds maximum size of {util.to_human_size(util.MAX_LINE_BYTES)}. Dropping it."
114
109
  wandb.termerror(msg, repeat=False)
115
110
  wandb._sentry.message(msg, repeat=False)
116
111
  self._debug_log(data)
@@ -494,12 +489,12 @@ class FileStreamApi:
494
489
  # TODO: Consolidate with internal_util.ExceptionThread
495
490
  try:
496
491
  self._thread_body()
497
- except Exception as e:
492
+ except Exception:
498
493
  exc_info = sys.exc_info()
499
494
  self._exc_info = exc_info
500
495
  logger.exception("generic exception in filestream thread")
501
496
  wandb._sentry.exception(exc_info)
502
- raise e
497
+ raise
503
498
 
504
499
  def _handle_response(self, response: Union[Exception, "requests.Response"]) -> None:
505
500
  """Log dropped chunks and updates dynamic settings."""
@@ -507,7 +502,7 @@ class FileStreamApi:
507
502
  wandb.termerror(
508
503
  "Dropped streaming file chunk (see wandb/debug-internal.log)"
509
504
  )
510
- logger.exception("dropped chunk {}".format(response))
505
+ logger.exception(f"dropped chunk {response}")
511
506
  self._dropped_chunks += 1
512
507
  else:
513
508
  parsed: Optional[dict] = None
@@ -664,8 +659,7 @@ def request_with_retry(
664
659
  e.response is not None and e.response.status_code == 429
665
660
  ):
666
661
  err_str = (
667
- "Filestream rate limit exceeded, "
668
- f"retrying in {delay:.1f} seconds. "
662
+ f"Filestream rate limit exceeded, retrying in {delay:.1f} seconds. "
669
663
  )
670
664
  if retry_callback:
671
665
  retry_callback(e.response.status_code, err_str)
@@ -688,8 +682,5 @@ def request_with_retry(
688
682
  error_message = response.json()["error"] # todo: clean this up
689
683
  except Exception:
690
684
  pass
691
- logger.error(f"requests_with_retry error: {error_message}")
692
- logger.exception(
693
- "requests_with_retry encountered unretryable exception: %s", e
694
- )
685
+ logger.exception(f"requests_with_retry error: {error_message}")
695
686
  return e
@@ -704,8 +704,8 @@ class HandleManager:
704
704
  ):
705
705
  try:
706
706
  self._metadata = Metadata(**self._system_monitor.probe(publish=True))
707
- except Exception as e:
708
- logger.error("Error probing system metadata: %s", e)
707
+ except Exception:
708
+ logger.exception("Error probing system metadata.")
709
709
 
710
710
  self._tb_watcher = tb_watcher.TBWatcher(
711
711
  self._settings, interface=self._interface, run_proto=run_start.run
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from wandb import Table
8
+ from wandb.sdk.artifacts.artifact import Artifact
9
+
10
+ from ..wandb_run import Run as LocalRun
11
+
12
+ ART_TYPE = "wandb-run-incremental-table"
13
+
14
+
15
+ def _get_artifact_name(run: LocalRun, key: str) -> str:
16
+ from wandb.sdk.artifacts._internal_artifact import sanitize_artifact_name
17
+
18
+ return sanitize_artifact_name(f"run-{run.id}-incr-{key}")
19
+
20
+
21
+ def init_artifact(run: LocalRun, sanitized_key: str) -> Artifact:
22
+ """Initialize a new artifact for an incremental table.
23
+
24
+ Args:
25
+ run: The wandb run associated with this artifact
26
+ sanitized_key: Sanitized string key to identify the table
27
+
28
+ Returns:
29
+ A wandb Artifact configured for incremental table storage
30
+ """
31
+ from wandb.sdk.artifacts._internal_artifact import InternalArtifact
32
+
33
+ artifact = InternalArtifact(
34
+ _get_artifact_name(run, sanitized_key),
35
+ ART_TYPE,
36
+ incremental=True,
37
+ )
38
+ return artifact
39
+
40
+
41
+ def get_entry_name(incr_table: Table, key: str) -> str:
42
+ """Generate a unique entry name for a table increment.
43
+
44
+ Args:
45
+ run: The wandb run associated with this table
46
+ incr_table: The incremental table being updated
47
+ key: String key for the table entry
48
+
49
+ Returns:
50
+ A unique string name for the table entry
51
+ """
52
+ epoch = time.time_ns() // 1_000_000
53
+ return f"{incr_table._increment_num}-{epoch}.{key}"
@@ -169,11 +169,9 @@ def wandb_internal(
169
169
  traceback.print_exception(*exc_info)
170
170
  wandb._sentry.exception(exc_info)
171
171
  wandb.termerror("Internal wandb error: file data was not synced")
172
- if not settings.x_disable_service:
173
- # TODO: We can make this more graceful by returning an error to streams.py
174
- # and potentially just fail the one stream.
175
- os._exit(-1)
176
- sys.exit(-1)
172
+ # TODO: We can make this more graceful by returning an error to streams.py
173
+ # and potentially just fail the one stream.
174
+ os._exit(-1)
177
175
 
178
176
  close_internal_log()
179
177