wandb 0.17.0rc2__py3-none-any.whl → 0.17.2__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. wandb/__init__.py +4 -2
  2. wandb/apis/importers/internals/internal.py +0 -1
  3. wandb/apis/importers/wandb.py +12 -7
  4. wandb/apis/internal.py +0 -3
  5. wandb/apis/public/api.py +213 -79
  6. wandb/apis/public/artifacts.py +335 -100
  7. wandb/apis/public/files.py +9 -9
  8. wandb/apis/public/jobs.py +16 -4
  9. wandb/apis/public/projects.py +26 -28
  10. wandb/apis/public/query_generator.py +1 -1
  11. wandb/apis/public/runs.py +163 -65
  12. wandb/apis/public/sweeps.py +2 -2
  13. wandb/apis/reports/__init__.py +1 -7
  14. wandb/apis/reports/v1/__init__.py +5 -27
  15. wandb/apis/reports/v2/__init__.py +7 -19
  16. wandb/apis/workspaces/__init__.py +8 -0
  17. wandb/beta/workflows.py +8 -3
  18. wandb/cli/cli.py +151 -59
  19. wandb/docker/__init__.py +1 -1
  20. wandb/errors/term.py +10 -2
  21. wandb/filesync/step_checksum.py +1 -4
  22. wandb/filesync/step_prepare.py +4 -24
  23. wandb/filesync/step_upload.py +5 -107
  24. wandb/filesync/upload_job.py +0 -76
  25. wandb/integration/gym/__init__.py +35 -15
  26. wandb/integration/openai/fine_tuning.py +21 -3
  27. wandb/integration/prodigy/prodigy.py +1 -1
  28. wandb/jupyter.py +16 -17
  29. wandb/old/summary.py +5 -0
  30. wandb/plot/pr_curve.py +2 -1
  31. wandb/plot/roc_curve.py +2 -1
  32. wandb/{plots → plot}/utils.py +13 -25
  33. wandb/proto/v3/wandb_internal_pb2.py +54 -54
  34. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  35. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  36. wandb/proto/v4/wandb_internal_pb2.py +54 -54
  37. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  38. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  39. wandb/proto/v5/wandb_base_pb2.py +30 -0
  40. wandb/proto/v5/wandb_internal_pb2.py +355 -0
  41. wandb/proto/v5/wandb_server_pb2.py +63 -0
  42. wandb/proto/v5/wandb_settings_pb2.py +45 -0
  43. wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
  44. wandb/proto/wandb_base_pb2.py +2 -0
  45. wandb/proto/wandb_deprecated.py +9 -1
  46. wandb/proto/wandb_generate_deprecated.py +34 -0
  47. wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
  48. wandb/proto/wandb_internal_pb2.py +2 -0
  49. wandb/proto/wandb_server_pb2.py +2 -0
  50. wandb/proto/wandb_settings_pb2.py +2 -0
  51. wandb/proto/wandb_telemetry_pb2.py +2 -0
  52. wandb/sdk/artifacts/artifact.py +76 -23
  53. wandb/sdk/artifacts/artifact_manifest.py +1 -1
  54. wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
  55. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
  56. wandb/sdk/artifacts/artifact_saver.py +1 -10
  57. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
  58. wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
  59. wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
  60. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
  61. wandb/sdk/artifacts/storage_policy.py +1 -12
  62. wandb/sdk/data_types/_dtypes.py +5 -2
  63. wandb/sdk/data_types/html.py +1 -1
  64. wandb/sdk/data_types/image.py +1 -1
  65. wandb/sdk/data_types/object_3d.py +1 -1
  66. wandb/sdk/data_types/video.py +4 -2
  67. wandb/sdk/interface/interface.py +13 -0
  68. wandb/sdk/interface/interface_shared.py +1 -1
  69. wandb/sdk/internal/file_pusher.py +2 -5
  70. wandb/sdk/internal/file_stream.py +6 -19
  71. wandb/sdk/internal/internal_api.py +160 -138
  72. wandb/sdk/internal/job_builder.py +207 -135
  73. wandb/sdk/internal/progress.py +0 -28
  74. wandb/sdk/internal/sender.py +105 -42
  75. wandb/sdk/internal/settings_static.py +8 -1
  76. wandb/sdk/internal/system/assets/gpu.py +2 -0
  77. wandb/sdk/internal/system/assets/trainium.py +3 -3
  78. wandb/sdk/internal/system/system_info.py +4 -2
  79. wandb/sdk/internal/update.py +1 -1
  80. wandb/sdk/launch/__init__.py +9 -1
  81. wandb/sdk/launch/_launch.py +4 -24
  82. wandb/sdk/launch/_launch_add.py +1 -3
  83. wandb/sdk/launch/_project_spec.py +184 -224
  84. wandb/sdk/launch/agent/agent.py +58 -18
  85. wandb/sdk/launch/agent/config.py +0 -3
  86. wandb/sdk/launch/builder/abstract.py +67 -0
  87. wandb/sdk/launch/builder/build.py +165 -576
  88. wandb/sdk/launch/builder/context_manager.py +235 -0
  89. wandb/sdk/launch/builder/docker_builder.py +7 -23
  90. wandb/sdk/launch/builder/kaniko_builder.py +10 -23
  91. wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
  92. wandb/sdk/launch/create_job.py +51 -45
  93. wandb/sdk/launch/environment/aws_environment.py +26 -1
  94. wandb/sdk/launch/inputs/files.py +148 -0
  95. wandb/sdk/launch/inputs/internal.py +224 -0
  96. wandb/sdk/launch/inputs/manage.py +95 -0
  97. wandb/sdk/launch/runner/abstract.py +2 -2
  98. wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
  99. wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
  100. wandb/sdk/launch/runner/local_container.py +2 -3
  101. wandb/sdk/launch/runner/local_process.py +8 -29
  102. wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
  103. wandb/sdk/launch/runner/vertex_runner.py +8 -7
  104. wandb/sdk/launch/sweeps/scheduler.py +2 -0
  105. wandb/sdk/launch/sweeps/utils.py +2 -2
  106. wandb/sdk/launch/utils.py +16 -138
  107. wandb/sdk/lib/_settings_toposort_generated.py +2 -5
  108. wandb/sdk/lib/apikey.py +4 -2
  109. wandb/sdk/lib/config_util.py +3 -3
  110. wandb/sdk/lib/proto_util.py +22 -1
  111. wandb/sdk/lib/redirect.py +1 -1
  112. wandb/sdk/service/service.py +2 -1
  113. wandb/sdk/service/streams.py +5 -5
  114. wandb/sdk/wandb_init.py +25 -59
  115. wandb/sdk/wandb_login.py +28 -25
  116. wandb/sdk/wandb_run.py +135 -70
  117. wandb/sdk/wandb_settings.py +33 -64
  118. wandb/sdk/wandb_watch.py +1 -1
  119. wandb/sklearn/plot/classifier.py +4 -6
  120. wandb/sync/sync.py +2 -2
  121. wandb/testing/relay.py +32 -17
  122. wandb/util.py +39 -37
  123. wandb/wandb_agent.py +3 -3
  124. wandb/wandb_controller.py +3 -2
  125. {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/METADATA +7 -9
  126. {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/RECORD +129 -151
  127. {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/WHEEL +1 -1
  128. wandb/apis/reports/v1/_blocks.py +0 -1406
  129. wandb/apis/reports/v1/_helpers.py +0 -70
  130. wandb/apis/reports/v1/_panels.py +0 -1282
  131. wandb/apis/reports/v1/_templates.py +0 -478
  132. wandb/apis/reports/v1/blocks.py +0 -27
  133. wandb/apis/reports/v1/helpers.py +0 -2
  134. wandb/apis/reports/v1/mutations.py +0 -66
  135. wandb/apis/reports/v1/panels.py +0 -17
  136. wandb/apis/reports/v1/report.py +0 -268
  137. wandb/apis/reports/v1/runset.py +0 -144
  138. wandb/apis/reports/v1/templates.py +0 -7
  139. wandb/apis/reports/v1/util.py +0 -406
  140. wandb/apis/reports/v1/validators.py +0 -131
  141. wandb/apis/reports/v2/blocks.py +0 -25
  142. wandb/apis/reports/v2/expr_parsing.py +0 -257
  143. wandb/apis/reports/v2/gql.py +0 -68
  144. wandb/apis/reports/v2/interface.py +0 -1911
  145. wandb/apis/reports/v2/internal.py +0 -867
  146. wandb/apis/reports/v2/metrics.py +0 -6
  147. wandb/apis/reports/v2/panels.py +0 -15
  148. wandb/catboost/__init__.py +0 -9
  149. wandb/fastai/__init__.py +0 -9
  150. wandb/keras/__init__.py +0 -19
  151. wandb/lightgbm/__init__.py +0 -9
  152. wandb/plots/__init__.py +0 -6
  153. wandb/plots/explain_text.py +0 -36
  154. wandb/plots/heatmap.py +0 -81
  155. wandb/plots/named_entity.py +0 -43
  156. wandb/plots/part_of_speech.py +0 -50
  157. wandb/plots/plot_definitions.py +0 -768
  158. wandb/plots/precision_recall.py +0 -121
  159. wandb/plots/roc.py +0 -103
  160. wandb/sacred/__init__.py +0 -3
  161. wandb/xgboost/__init__.py +0 -9
  162. {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/entry_points.txt +0 -0
  163. {wandb-0.17.0rc2.dist-info → wandb-0.17.2.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_init.py CHANGED
@@ -15,7 +15,6 @@ import os
15
15
  import platform
16
16
  import sys
17
17
  import tempfile
18
- import traceback
19
18
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union
20
19
 
21
20
  import wandb
@@ -555,7 +554,7 @@ class _WandbInit:
555
554
  percent_done = handle.percent_done
556
555
  self.printer.progress_update(line, percent_done=percent_done)
557
556
 
558
- def init(self) -> Union[Run, RunDisabled, None]: # noqa: C901
557
+ def init(self) -> Union[Run, RunDisabled]: # noqa: C901
559
558
  if logger is None:
560
559
  raise RuntimeError("Logger not initialized")
561
560
  logger.info("calling init triggers")
@@ -654,9 +653,6 @@ class _WandbInit:
654
653
  if self.settings.launch:
655
654
  tel.feature.launch = True
656
655
 
657
- if self.settings._async_upload_concurrency_limit:
658
- tel.feature.async_uploads = True
659
-
660
656
  for module_name in telemetry.list_telemetry_imports(only_imported=True):
661
657
  setattr(tel.imports_init, module_name, True)
662
658
 
@@ -843,13 +839,6 @@ class _WandbInit:
843
839
  return run
844
840
 
845
841
 
846
- def getcaller() -> None:
847
- if not logger:
848
- return None
849
- src, line, func, stack = logger.findCaller(stack_info=True)
850
- print("Problem at:", src, line, func)
851
-
852
-
853
842
  def _attach(
854
843
  attach_id: Optional[str] = None,
855
844
  run_id: Optional[str] = None,
@@ -957,8 +946,9 @@ def init(
957
946
  save_code: Optional[bool] = None,
958
947
  id: Optional[str] = None,
959
948
  fork_from: Optional[str] = None,
949
+ resume_from: Optional[str] = None,
960
950
  settings: Union[Settings, Dict[str, Any], None] = None,
961
- ) -> Union[Run, RunDisabled, None]:
951
+ ) -> Union[Run, RunDisabled]:
962
952
  r"""Start a new run to track and log to W&B.
963
953
 
964
954
  In an ML training pipeline, you could add `wandb.init()`
@@ -1006,7 +996,7 @@ def init(
1006
996
  there, so make sure to create your account or team in the UI before
1007
997
  starting to log runs.
1008
998
  If you don't specify an entity, the run will be sent to your default
1009
- entity, which is usually your username. Change your default entity
999
+ entity. Change your default entity
1010
1000
  in [your settings](https://wandb.ai/settings) under "default location
1011
1001
  to create new projects".
1012
1002
  config: (dict, argparse, absl.flags, str, optional)
@@ -1164,57 +1154,33 @@ def init(
1164
1154
  wandb._assert_is_user_process()
1165
1155
 
1166
1156
  kwargs = dict(locals())
1167
- error_seen = None
1168
- except_exit = None
1169
- run: Optional[Union[Run, RunDisabled]] = None
1170
1157
 
1171
- # convert fork_from into a version that can be passed to settings
1172
- if fork_from is not None and resume is not None:
1173
- raise ValueError("Cannot specify both `fork_from` and `resume`")
1158
+ num_resume_options_set = (
1159
+ (fork_from is not None) # wrap
1160
+ + (resume is not None)
1161
+ + (resume_from is not None)
1162
+ )
1163
+ if num_resume_options_set > 1:
1164
+ raise ValueError(
1165
+ "You cannot specify more than one of `fork_from`, `resume`, or `resume_from`"
1166
+ )
1174
1167
 
1175
1168
  try:
1176
1169
  wi = _WandbInit()
1177
1170
  wi.setup(kwargs)
1178
- assert wi.settings
1179
- except_exit = wi.settings._except_exit
1180
- try:
1181
- run = wi.init()
1182
- except_exit = wi.settings._except_exit
1183
- except (KeyboardInterrupt, Exception) as e:
1184
- if not isinstance(e, KeyboardInterrupt):
1185
- wandb._sentry.exception(e)
1186
- if not (
1187
- wandb.wandb_agent._is_running() and isinstance(e, KeyboardInterrupt)
1188
- ):
1189
- getcaller()
1190
- assert logger
1191
- if wi.settings.problem == "fatal":
1192
- raise
1193
- if wi.settings.problem == "warn":
1194
- pass
1195
- # TODO(jhr): figure out how to make this RunDummy
1196
- run = None
1197
- except Error as e:
1198
- if logger is not None:
1199
- logger.exception(str(e))
1200
- raise e
1171
+ return wi.init()
1172
+
1201
1173
  except KeyboardInterrupt as e:
1202
- assert logger
1203
- logger.warning("interrupted", exc_info=e)
1204
- raise e
1174
+ if logger is not None:
1175
+ logger.warning("interrupted", exc_info=e)
1176
+
1177
+ raise
1178
+
1205
1179
  except Exception as e:
1206
- error_seen = e
1207
- traceback.print_exc()
1208
- assert logger
1209
- logger.error("error", exc_info=e)
1180
+ if logger is not None:
1181
+ logger.exception("error in wandb.init()", exc_info=e)
1182
+
1210
1183
  # Need to build delay into this sentry capture because our exit hooks
1211
1184
  # mess with sentry's ability to send out errors before the program ends.
1212
- wandb._sentry.exception(e)
1213
- # reraise(*sys.exc_info())
1214
- finally:
1215
- if error_seen:
1216
- if except_exit:
1217
- wandb.termerror("Abnormal program exit")
1218
- os._exit(1)
1219
- raise Error("An unexpected error occurred") from error_seen
1220
- return run
1185
+ wandb._sentry.reraise(e)
1186
+ raise AssertionError() # unreachable
wandb/sdk/wandb_login.py CHANGED
@@ -6,7 +6,7 @@ This authenticates your machine to log data to your account.
6
6
  import enum
7
7
  import os
8
8
  import sys
9
- from typing import Dict, Optional, Tuple
9
+ from typing import Optional, Tuple
10
10
 
11
11
  if sys.version_info >= (3, 8):
12
12
  from typing import Literal
@@ -112,11 +112,10 @@ class ApiKeyStatus(enum.Enum):
112
112
 
113
113
  class _WandbLogin:
114
114
  def __init__(self):
115
- self.kwargs: Optional[Dict] = None
116
115
  self._settings: Optional[Settings] = None
117
116
  self._backend = None
118
- self._silent = None
119
- self._entity = None
117
+ self._silent: Optional[bool] = None
118
+ self._entity: Optional[str] = None
120
119
  self._wl = None
121
120
  self._key = None
122
121
  self._relogin = None
@@ -130,7 +129,8 @@ class _WandbLogin:
130
129
  host: Optional[str] = None,
131
130
  force: Optional[bool] = None,
132
131
  timeout: Optional[int] = None,
133
- ):
132
+ ) -> None:
133
+ """Updates login-related settings on the global setup object."""
134
134
  self._relogin = relogin
135
135
 
136
136
  # built up login settings
@@ -152,19 +152,24 @@ class _WandbLogin:
152
152
  self._wl = wandb.setup(settings=login_settings)
153
153
  self._settings = self._wl.settings
154
154
 
155
- def is_apikey_configured(self):
155
+ def is_apikey_configured(self) -> bool:
156
+ """Returns whether an API key is set or can be inferred."""
156
157
  return apikey.api_key(settings=self._settings) is not None
157
158
 
158
159
  def set_backend(self, backend):
159
160
  self._backend = backend
160
161
 
161
- def set_silent(self, silent: bool):
162
+ def set_silent(self, silent: bool) -> None:
162
163
  self._silent = silent
163
164
 
164
- def set_entity(self, entity: str):
165
+ def set_entity(self, entity: str) -> None:
165
166
  self._entity = entity
166
167
 
167
- def login(self):
168
+ def login(self) -> bool:
169
+ """Returns whether the user is logged in (i.e. an API key exists).
170
+
171
+ If the user is logged in, this also prints an informational message.
172
+ """
168
173
  apikey_configured = self.is_apikey_configured()
169
174
  if self._settings.relogin or self._relogin:
170
175
  apikey_configured = False
@@ -172,11 +177,12 @@ class _WandbLogin:
172
177
  return False
173
178
 
174
179
  if not self._silent:
175
- self.login_display()
180
+ self._print_logged_in_message()
176
181
 
177
182
  return apikey_configured
178
183
 
179
- def login_display(self):
184
+ def _print_logged_in_message(self) -> None:
185
+ """Prints a message telling the user they are logged in."""
180
186
  username = self._wl._get_username()
181
187
 
182
188
  if username:
@@ -200,7 +206,8 @@ class _WandbLogin:
200
206
  repeat=False,
201
207
  )
202
208
 
203
- def configure_api_key(self, key):
209
+ def configure_api_key(self, key: str) -> None:
210
+ """Saves the API key and updates the the global setup object."""
204
211
  if self._settings._notebook and not self._settings.silent:
205
212
  wandb.termwarn(
206
213
  "If you're specifying your api key in code, ensure this "
@@ -213,8 +220,14 @@ class _WandbLogin:
213
220
  self._key = key
214
221
 
215
222
  def update_session(
216
- self, key: Optional[str], status: ApiKeyStatus = ApiKeyStatus.VALID
223
+ self,
224
+ key: Optional[str],
225
+ status: ApiKeyStatus = ApiKeyStatus.VALID,
217
226
  ) -> None:
227
+ """Updates mode and API key settings on the global setup object.
228
+
229
+ If we're online, this also pulls in user settings from the server.
230
+ """
218
231
  _logger = wandb.setup()._get_logger()
219
232
  login_settings = dict()
220
233
  if status == ApiKeyStatus.OFFLINE:
@@ -252,7 +265,8 @@ class _WandbLogin:
252
265
  return None, ApiKeyStatus.OFFLINE
253
266
  return key, ApiKeyStatus.VALID
254
267
 
255
- def prompt_api_key(self):
268
+ def prompt_api_key(self) -> None:
269
+ """Updates the global API key by prompting the user."""
256
270
  key, status = self._prompt_api_key()
257
271
  if status == ApiKeyStatus.NOTTY:
258
272
  directive = (
@@ -265,14 +279,6 @@ class _WandbLogin:
265
279
  self.update_session(key, status=status)
266
280
  self._key = key
267
281
 
268
- def propogate_login(self):
269
- # TODO(jhr): figure out if this is really necessary
270
- if self._backend:
271
- # TODO: calling this twice is gross, this deserves a refactor
272
- # Make sure our backend picks up the new creds
273
- # _ = self._backend.interface.communicate_login(key, anonymous)
274
- pass
275
-
276
282
 
277
283
  def _login(
278
284
  *,
@@ -333,7 +339,4 @@ def _login(
333
339
  if not key:
334
340
  wlogin.prompt_api_key()
335
341
 
336
- # make sure login credentials get to the backend
337
- wlogin.propogate_login()
338
-
339
342
  return wlogin._key or False
wandb/sdk/wandb_run.py CHANGED
@@ -207,6 +207,15 @@ class RunStatusChecker:
207
207
  self._network_status_thread.start()
208
208
  self._internal_messages_thread.start()
209
209
 
210
+ @staticmethod
211
+ def _abandon_status_check(
212
+ lock: threading.Lock,
213
+ handle: Optional[MailboxHandle],
214
+ ):
215
+ with lock:
216
+ if handle:
217
+ handle.abandon()
218
+
210
219
  def _loop_check_status(
211
220
  self,
212
221
  *,
@@ -247,7 +256,7 @@ class RunStatusChecker:
247
256
  local_handle = None
248
257
 
249
258
  time_elapsed = time.monotonic() - time_probe
250
- wait_time = max(self._stop_polling_interval - time_elapsed, 0)
259
+ wait_time = max(timeout - time_elapsed, 0)
251
260
  join_requested = self._join_event.wait(timeout=wait_time)
252
261
 
253
262
  def check_network_status(self) -> None:
@@ -265,13 +274,19 @@ class RunStatusChecker:
265
274
  )
266
275
  )
267
276
 
268
- self._loop_check_status(
269
- lock=self._network_status_lock,
270
- set_handle=lambda x: setattr(self, "_network_status_handle", x),
271
- timeout=self._retry_polling_interval,
272
- request=self._interface.deliver_network_status,
273
- process=_process_network_status,
274
- )
277
+ try:
278
+ self._loop_check_status(
279
+ lock=self._network_status_lock,
280
+ set_handle=lambda x: setattr(self, "_network_status_handle", x),
281
+ timeout=self._retry_polling_interval,
282
+ request=self._interface.deliver_network_status,
283
+ process=_process_network_status,
284
+ )
285
+ except BrokenPipeError:
286
+ self._abandon_status_check(
287
+ self._network_status_lock,
288
+ self._network_status_handle,
289
+ )
275
290
 
276
291
  def check_stop_status(self) -> None:
277
292
  def _process_stop_status(result: Result) -> None:
@@ -283,13 +298,19 @@ class RunStatusChecker:
283
298
  thread.interrupt_main()
284
299
  return
285
300
 
286
- self._loop_check_status(
287
- lock=self._stop_status_lock,
288
- set_handle=lambda x: setattr(self, "_stop_status_handle", x),
289
- timeout=self._stop_polling_interval,
290
- request=self._interface.deliver_stop_status,
291
- process=_process_stop_status,
292
- )
301
+ try:
302
+ self._loop_check_status(
303
+ lock=self._stop_status_lock,
304
+ set_handle=lambda x: setattr(self, "_stop_status_handle", x),
305
+ timeout=self._stop_polling_interval,
306
+ request=self._interface.deliver_stop_status,
307
+ process=_process_stop_status,
308
+ )
309
+ except BrokenPipeError:
310
+ self._abandon_status_check(
311
+ self._stop_status_lock,
312
+ self._stop_status_handle,
313
+ )
293
314
 
294
315
  def check_internal_messages(self) -> None:
295
316
  def _process_internal_messages(result: Result) -> None:
@@ -297,25 +318,34 @@ class RunStatusChecker:
297
318
  for msg in internal_messages.messages.warning:
298
319
  wandb.termwarn(msg)
299
320
 
300
- self._loop_check_status(
301
- lock=self._internal_messages_lock,
302
- set_handle=lambda x: setattr(self, "_internal_messages_handle", x),
303
- timeout=1,
304
- request=self._interface.deliver_internal_messages,
305
- process=_process_internal_messages,
306
- )
321
+ try:
322
+ self._loop_check_status(
323
+ lock=self._internal_messages_lock,
324
+ set_handle=lambda x: setattr(self, "_internal_messages_handle", x),
325
+ timeout=1,
326
+ request=self._interface.deliver_internal_messages,
327
+ process=_process_internal_messages,
328
+ )
329
+ except BrokenPipeError:
330
+ self._abandon_status_check(
331
+ self._internal_messages_lock,
332
+ self._internal_messages_handle,
333
+ )
307
334
 
308
335
  def stop(self) -> None:
309
336
  self._join_event.set()
310
- with self._stop_status_lock:
311
- if self._stop_status_handle:
312
- self._stop_status_handle.abandon()
313
- with self._network_status_lock:
314
- if self._network_status_handle:
315
- self._network_status_handle.abandon()
316
- with self._internal_messages_lock:
317
- if self._internal_messages_handle:
318
- self._internal_messages_handle.abandon()
337
+ self._abandon_status_check(
338
+ self._stop_status_lock,
339
+ self._stop_status_handle,
340
+ )
341
+ self._abandon_status_check(
342
+ self._network_status_lock,
343
+ self._network_status_handle,
344
+ )
345
+ self._abandon_status_check(
346
+ self._internal_messages_lock,
347
+ self._internal_messages_handle,
348
+ )
319
349
 
320
350
  def join(self) -> None:
321
351
  self.stop()
@@ -676,6 +706,12 @@ class Run:
676
706
  "step": self._settings.fork_from.value,
677
707
  }
678
708
 
709
+ if self._settings.resume_from is not None:
710
+ config[wandb_key]["branch_point"] = {
711
+ "run_id": self._settings.resume_from.run,
712
+ "step": self._settings.resume_from.value,
713
+ }
714
+
679
715
  self._config._update(config, ignore_locked=True)
680
716
 
681
717
  if sweep_config:
@@ -1400,6 +1436,10 @@ class Run:
1400
1436
  # self._printer.display(line)
1401
1437
 
1402
1438
  def _summary_get_current_summary_callback(self) -> Dict[str, Any]:
1439
+ if self._is_finished:
1440
+ # TODO: WB-18420: fetch summary from backend and stage it before run is finished
1441
+ wandb.termwarn("Summary data not available in finished run")
1442
+ return {}
1403
1443
  if not self._backend or not self._backend.interface:
1404
1444
  return {}
1405
1445
  handle = self._backend.interface.deliver_get_summary()
@@ -1792,7 +1832,7 @@ class Run:
1792
1832
  import wandb
1793
1833
 
1794
1834
  run = wandb.init()
1795
- run.log({"pr": wandb.plots.precision_recall(y_test, y_probas, labels)})
1835
+ run.log({"pr": wandb.plot.pr_curve(y_test, y_probas, labels)})
1796
1836
  ```
1797
1837
 
1798
1838
  ### 3D Object
@@ -2443,6 +2483,8 @@ class Run:
2443
2483
  self._telemetry_obj_active = True
2444
2484
  self._telemetry_flush()
2445
2485
 
2486
+ self._detect_and_apply_job_inputs()
2487
+
2446
2488
  # object is about to be returned to the user, don't let them modify it
2447
2489
  self._freeze()
2448
2490
 
@@ -2450,6 +2492,12 @@ class Run:
2450
2492
  if os.path.exists(self._settings.resume_fname):
2451
2493
  os.remove(self._settings.resume_fname)
2452
2494
 
2495
+ def _detect_and_apply_job_inputs(self) -> None:
2496
+ """If the user has staged launch inputs, apply them to the run."""
2497
+ from wandb.sdk.launch.inputs.internal import StagedLaunchInputs
2498
+
2499
+ StagedLaunchInputs().apply(self)
2500
+
2453
2501
  def _make_job_source_reqs(self) -> Tuple[List[str], Dict[str, Any], Dict[str, Any]]:
2454
2502
  from wandb.util import working_set
2455
2503
 
@@ -2555,14 +2603,18 @@ class Run:
2555
2603
  self._console_stop() # TODO: there's a race here with jupyter console logging
2556
2604
 
2557
2605
  assert self._backend and self._backend.interface
2606
+
2607
+ # get the server info before starting the defer state machine as
2608
+ # it will stop communication with the server
2609
+ server_info_handle = self._backend.interface.deliver_request_server_info()
2610
+ result = server_info_handle.wait(timeout=-1)
2611
+ assert result
2612
+ self._server_info_response = result.response.server_info_response
2613
+
2558
2614
  exit_handle = self._backend.interface.deliver_exit(self._exit_code)
2559
2615
  exit_handle.add_probe(on_probe=self._on_probe_exit)
2560
2616
 
2561
- # this message is confusing, we should remove it
2562
- # self._footer_exit_status_info(
2563
- # self._exit_code, settings=self._settings, printer=self._printer
2564
- # )
2565
-
2617
+ # wait for the exit to complete
2566
2618
  _ = exit_handle.wait(timeout=-1, on_progress=self._on_progress_exit)
2567
2619
 
2568
2620
  poll_exit_handle = self._backend.interface.deliver_poll_exit()
@@ -2580,16 +2632,11 @@ class Run:
2580
2632
 
2581
2633
  # dispatch all our final requests
2582
2634
 
2583
- server_info_handle = self._backend.interface.deliver_request_server_info()
2584
2635
  final_summary_handle = self._backend.interface.deliver_get_summary()
2585
2636
  sampled_history_handle = (
2586
2637
  self._backend.interface.deliver_request_sampled_history()
2587
2638
  )
2588
2639
 
2589
- result = server_info_handle.wait(timeout=-1)
2590
- assert result
2591
- self._server_info_response = result.response.server_info_response
2592
-
2593
2640
  result = sampled_history_handle.wait(timeout=-1)
2594
2641
  assert result
2595
2642
  self._sampled_history = result.response.sampled_history_response
@@ -2708,12 +2755,23 @@ class Run:
2708
2755
  if i not in valid:
2709
2756
  raise wandb.Error(f"Unhandled define_metric() arg: summary op: {i}")
2710
2757
  summary_ops.append(i)
2758
+ with telemetry.context(run=self) as tel:
2759
+ tel.feature.metric_summary = True
2711
2760
  goal_cleaned: Optional[str] = None
2712
2761
  if goal is not None:
2713
2762
  goal_cleaned = goal[:3].lower()
2714
2763
  valid_goal = {"min", "max"}
2715
2764
  if goal_cleaned not in valid_goal:
2716
2765
  raise wandb.Error(f"Unhandled define_metric() arg: goal: {goal}")
2766
+ with telemetry.context(run=self) as tel:
2767
+ tel.feature.metric_goal = True
2768
+ if hidden:
2769
+ with telemetry.context(run=self) as tel:
2770
+ tel.feature.metric_hidden = True
2771
+ if step_sync:
2772
+ with telemetry.context(run=self) as tel:
2773
+ tel.feature.metric_step_sync = True
2774
+
2717
2775
  m = wandb_metric.Metric(
2718
2776
  name=name,
2719
2777
  step_metric=step_metric,
@@ -2898,6 +2956,7 @@ class Run:
2898
2956
  api.use_artifact(
2899
2957
  artifact.id,
2900
2958
  entity_name=r.entity,
2959
+ project_name=r.project,
2901
2960
  use_as=use_as or artifact_or_name,
2902
2961
  )
2903
2962
  else:
@@ -2960,8 +3019,7 @@ class Run:
2960
3019
  - `s3://bucket/path`
2961
3020
  You can also pass an Artifact object created by calling
2962
3021
  `wandb.Artifact`.
2963
- name: (str, optional) An artifact name. May be prefixed with entity/project.
2964
- Valid names can be in the following forms:
3022
+ name: (str, optional) An artifact name. Valid names can be in the following forms:
2965
3023
  - name:version
2966
3024
  - name:alias
2967
3025
  - digest
@@ -3607,7 +3665,11 @@ class Run:
3607
3665
  project_url = settings.project_url
3608
3666
  sweep_url = settings.sweep_url
3609
3667
 
3610
- run_state_str = "Resuming run" if settings.resumed else "Syncing run"
3668
+ run_state_str = (
3669
+ "Resuming run"
3670
+ if settings.resumed or settings.resume_from
3671
+ else "Syncing run"
3672
+ )
3611
3673
  run_name = settings.run_name
3612
3674
  if not run_name:
3613
3675
  return
@@ -3697,6 +3759,11 @@ class Run:
3697
3759
  settings=settings,
3698
3760
  printer=printer,
3699
3761
  )
3762
+ Run._footer_notify_wandb_core(
3763
+ quiet=quiet,
3764
+ settings=settings,
3765
+ printer=printer,
3766
+ )
3700
3767
  Run._footer_local_warn(
3701
3768
  server_info_response=server_info_response,
3702
3769
  quiet=quiet,
@@ -3719,26 +3786,6 @@ class Run:
3719
3786
  printer=printer,
3720
3787
  )
3721
3788
 
3722
- @staticmethod
3723
- def _footer_exit_status_info(
3724
- exit_code: Optional[int],
3725
- *,
3726
- settings: "Settings",
3727
- printer: Union["PrinterTerm", "PrinterJupyter"],
3728
- ) -> None:
3729
- if settings.silent:
3730
- return
3731
-
3732
- status = "(success)." if not exit_code else f"(failed {exit_code})."
3733
- info = [
3734
- f"Waiting for W&B process to finish... {printer.status(status, bool(exit_code))}"
3735
- ]
3736
-
3737
- if not settings._offline and exit_code:
3738
- info.append(f"Press {printer.abort()} to abort syncing.")
3739
-
3740
- printer.display(f'{" ".join(info)}')
3741
-
3742
3789
  # fixme: Temporary hack until we move to rich which allows multiple spinners
3743
3790
  @staticmethod
3744
3791
  def _footer_file_pusher_status_info(
@@ -3964,11 +4011,11 @@ class Run:
3964
4011
 
3965
4012
  # Render summary if available
3966
4013
  if summary:
3967
- final_summary = {
3968
- item.key: json.loads(item.value_json)
3969
- for item in summary.item
3970
- if not item.key.startswith("_")
3971
- }
4014
+ final_summary = {}
4015
+ for item in summary.item:
4016
+ if item.key.startswith("_") or len(item.nested_key) > 0:
4017
+ continue
4018
+ final_summary[item.key] = json.loads(item.value_json)
3972
4019
 
3973
4020
  logger.info("rendering summary")
3974
4021
  summary_rows = []
@@ -4087,6 +4134,24 @@ class Run:
4087
4134
  if package_problem and check_version.upgrade_message:
4088
4135
  printer.display(check_version.upgrade_message)
4089
4136
 
4137
+ @staticmethod
4138
+ def _footer_notify_wandb_core(
4139
+ *,
4140
+ quiet: Optional[bool] = None,
4141
+ settings: "Settings",
4142
+ printer: Union["PrinterTerm", "PrinterJupyter"],
4143
+ ) -> None:
4144
+ """Prints a message advertising the upcoming core release."""
4145
+ if quiet or settings._require_core:
4146
+ return
4147
+
4148
+ printer.display(
4149
+ "The new W&B backend becomes opt-out in version 0.18.0;"
4150
+ ' try it out with `wandb.require("core")`!'
4151
+ " See https://wandb.me/wandb-core for more information.",
4152
+ level="warn",
4153
+ )
4154
+
4090
4155
  @staticmethod
4091
4156
  def _footer_reporter_warn_err(
4092
4157
  reporter: Optional[Reporter] = None,