wandb 0.17.0rc1__py3-none-macosx_11_0_arm64.whl → 0.17.1__py3-none-macosx_11_0_arm64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. wandb/__init__.py +1 -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/bin/apple_gpu_stats +0 -0
  19. wandb/bin/wandb-core +0 -0
  20. wandb/cli/cli.py +131 -59
  21. wandb/data_types.py +6 -3
  22. wandb/docker/__init__.py +2 -2
  23. wandb/env.py +3 -3
  24. wandb/errors/term.py +10 -2
  25. wandb/filesync/step_checksum.py +1 -4
  26. wandb/filesync/step_prepare.py +4 -24
  27. wandb/filesync/step_upload.py +5 -107
  28. wandb/filesync/upload_job.py +0 -76
  29. wandb/integration/gym/__init__.py +35 -15
  30. wandb/integration/huggingface/resolver.py +2 -2
  31. wandb/integration/keras/callbacks/metrics_logger.py +1 -1
  32. wandb/integration/keras/keras.py +1 -1
  33. wandb/integration/openai/fine_tuning.py +21 -3
  34. wandb/integration/prodigy/prodigy.py +1 -1
  35. wandb/jupyter.py +16 -17
  36. wandb/old/summary.py +1 -1
  37. wandb/plot/confusion_matrix.py +1 -1
  38. wandb/plot/pr_curve.py +2 -1
  39. wandb/plot/roc_curve.py +2 -1
  40. wandb/{plots → plot}/utils.py +13 -25
  41. wandb/proto/v3/wandb_internal_pb2.py +54 -54
  42. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  43. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  44. wandb/proto/v4/wandb_internal_pb2.py +54 -54
  45. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  46. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  47. wandb/proto/v5/wandb_base_pb2.py +30 -0
  48. wandb/proto/v5/wandb_internal_pb2.py +355 -0
  49. wandb/proto/v5/wandb_server_pb2.py +63 -0
  50. wandb/proto/v5/wandb_settings_pb2.py +45 -0
  51. wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
  52. wandb/proto/wandb_base_pb2.py +2 -0
  53. wandb/proto/wandb_deprecated.py +9 -1
  54. wandb/proto/wandb_generate_deprecated.py +34 -0
  55. wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
  56. wandb/proto/wandb_internal_pb2.py +2 -0
  57. wandb/proto/wandb_server_pb2.py +2 -0
  58. wandb/proto/wandb_settings_pb2.py +2 -0
  59. wandb/proto/wandb_telemetry_pb2.py +2 -0
  60. wandb/sdk/artifacts/artifact.py +68 -22
  61. wandb/sdk/artifacts/artifact_manifest.py +1 -1
  62. wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
  63. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
  64. wandb/sdk/artifacts/artifact_saver.py +1 -10
  65. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
  66. wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
  67. wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
  68. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
  69. wandb/sdk/artifacts/storage_policy.py +1 -12
  70. wandb/sdk/data_types/_dtypes.py +8 -8
  71. wandb/sdk/data_types/image.py +2 -2
  72. wandb/sdk/data_types/video.py +5 -3
  73. wandb/sdk/integration_utils/data_logging.py +5 -5
  74. wandb/sdk/interface/interface.py +14 -1
  75. wandb/sdk/interface/interface_shared.py +1 -1
  76. wandb/sdk/internal/file_pusher.py +2 -5
  77. wandb/sdk/internal/file_stream.py +6 -19
  78. wandb/sdk/internal/internal_api.py +148 -136
  79. wandb/sdk/internal/job_builder.py +208 -136
  80. wandb/sdk/internal/progress.py +0 -28
  81. wandb/sdk/internal/sender.py +102 -39
  82. wandb/sdk/internal/settings_static.py +8 -1
  83. wandb/sdk/internal/system/assets/trainium.py +3 -3
  84. wandb/sdk/internal/system/system_info.py +4 -2
  85. wandb/sdk/internal/update.py +1 -1
  86. wandb/sdk/launch/__init__.py +9 -1
  87. wandb/sdk/launch/_launch.py +4 -24
  88. wandb/sdk/launch/_launch_add.py +1 -3
  89. wandb/sdk/launch/_project_spec.py +187 -225
  90. wandb/sdk/launch/agent/agent.py +59 -19
  91. wandb/sdk/launch/agent/config.py +0 -3
  92. wandb/sdk/launch/builder/abstract.py +68 -1
  93. wandb/sdk/launch/builder/build.py +165 -576
  94. wandb/sdk/launch/builder/context_manager.py +235 -0
  95. wandb/sdk/launch/builder/docker_builder.py +7 -23
  96. wandb/sdk/launch/builder/kaniko_builder.py +12 -25
  97. wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
  98. wandb/sdk/launch/create_job.py +51 -45
  99. wandb/sdk/launch/environment/aws_environment.py +26 -1
  100. wandb/sdk/launch/inputs/files.py +148 -0
  101. wandb/sdk/launch/inputs/internal.py +224 -0
  102. wandb/sdk/launch/inputs/manage.py +95 -0
  103. wandb/sdk/launch/registry/google_artifact_registry.py +1 -1
  104. wandb/sdk/launch/runner/abstract.py +2 -2
  105. wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
  106. wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
  107. wandb/sdk/launch/runner/local_container.py +2 -3
  108. wandb/sdk/launch/runner/local_process.py +8 -29
  109. wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
  110. wandb/sdk/launch/runner/vertex_runner.py +8 -7
  111. wandb/sdk/launch/sweeps/scheduler.py +5 -3
  112. wandb/sdk/launch/sweeps/scheduler_sweep.py +1 -1
  113. wandb/sdk/launch/sweeps/utils.py +4 -4
  114. wandb/sdk/launch/utils.py +16 -138
  115. wandb/sdk/lib/_settings_toposort_generated.py +2 -5
  116. wandb/sdk/lib/apikey.py +4 -2
  117. wandb/sdk/lib/config_util.py +3 -3
  118. wandb/sdk/lib/import_hooks.py +1 -1
  119. wandb/sdk/lib/proto_util.py +22 -1
  120. wandb/sdk/lib/redirect.py +20 -15
  121. wandb/sdk/lib/tracelog.py +1 -1
  122. wandb/sdk/service/service.py +2 -1
  123. wandb/sdk/service/streams.py +5 -5
  124. wandb/sdk/wandb_init.py +25 -59
  125. wandb/sdk/wandb_login.py +28 -25
  126. wandb/sdk/wandb_run.py +123 -53
  127. wandb/sdk/wandb_settings.py +33 -64
  128. wandb/sdk/wandb_setup.py +1 -1
  129. wandb/sdk/wandb_watch.py +1 -1
  130. wandb/sklearn/plot/classifier.py +10 -12
  131. wandb/sklearn/plot/clusterer.py +1 -1
  132. wandb/sync/sync.py +2 -2
  133. wandb/testing/relay.py +32 -17
  134. wandb/util.py +36 -37
  135. wandb/wandb_agent.py +3 -3
  136. wandb/wandb_controller.py +5 -4
  137. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/METADATA +8 -10
  138. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/RECORD +141 -163
  139. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/WHEEL +1 -1
  140. wandb/apis/reports/v1/_blocks.py +0 -1406
  141. wandb/apis/reports/v1/_helpers.py +0 -70
  142. wandb/apis/reports/v1/_panels.py +0 -1282
  143. wandb/apis/reports/v1/_templates.py +0 -478
  144. wandb/apis/reports/v1/blocks.py +0 -27
  145. wandb/apis/reports/v1/helpers.py +0 -2
  146. wandb/apis/reports/v1/mutations.py +0 -66
  147. wandb/apis/reports/v1/panels.py +0 -17
  148. wandb/apis/reports/v1/report.py +0 -268
  149. wandb/apis/reports/v1/runset.py +0 -144
  150. wandb/apis/reports/v1/templates.py +0 -7
  151. wandb/apis/reports/v1/util.py +0 -406
  152. wandb/apis/reports/v1/validators.py +0 -131
  153. wandb/apis/reports/v2/blocks.py +0 -25
  154. wandb/apis/reports/v2/expr_parsing.py +0 -257
  155. wandb/apis/reports/v2/gql.py +0 -68
  156. wandb/apis/reports/v2/interface.py +0 -1911
  157. wandb/apis/reports/v2/internal.py +0 -867
  158. wandb/apis/reports/v2/metrics.py +0 -6
  159. wandb/apis/reports/v2/panels.py +0 -15
  160. wandb/catboost/__init__.py +0 -9
  161. wandb/fastai/__init__.py +0 -9
  162. wandb/keras/__init__.py +0 -19
  163. wandb/lightgbm/__init__.py +0 -9
  164. wandb/plots/__init__.py +0 -6
  165. wandb/plots/explain_text.py +0 -36
  166. wandb/plots/heatmap.py +0 -81
  167. wandb/plots/named_entity.py +0 -43
  168. wandb/plots/part_of_speech.py +0 -50
  169. wandb/plots/plot_definitions.py +0 -768
  170. wandb/plots/precision_recall.py +0 -121
  171. wandb/plots/roc.py +0 -103
  172. wandb/sacred/__init__.py +0 -3
  173. wandb/xgboost/__init__.py +0 -9
  174. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/entry_points.txt +0 -0
  175. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/licenses/LICENSE +0 -0
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
@@ -1853,7 +1893,7 @@ class Run:
1853
1893
  picked up automatically.
1854
1894
 
1855
1895
  A `base_path` may be provided to control the directory structure of
1856
- uploaded files. It should be a prefix of `glob_str`, and the direcotry
1896
+ uploaded files. It should be a prefix of `glob_str`, and the directory
1857
1897
  structure beneath it is preserved. It's best understood through
1858
1898
  examples:
1859
1899
 
@@ -1911,7 +1951,11 @@ class Run:
1911
1951
  # Provide a better error message for a common misuse.
1912
1952
  wandb.termlog(f"{glob_str} is a cloud storage url, can't save file to W&B.")
1913
1953
  return []
1914
- glob_path = pathlib.Path(glob_str)
1954
+ # NOTE: We use PurePath instead of Path because WindowsPath doesn't
1955
+ # like asterisks and errors out in resolve(). It also makes logical
1956
+ # sense: globs aren't real paths, they're just path-like strings.
1957
+ glob_path = pathlib.PurePath(glob_str)
1958
+ resolved_glob_path = pathlib.PurePath(os.path.abspath(glob_path))
1915
1959
 
1916
1960
  if base_path is not None:
1917
1961
  base_path = pathlib.Path(base_path)
@@ -1925,15 +1969,14 @@ class Run:
1925
1969
  'wandb.save("/mnt/folder/file.h5", base_path="/mnt")',
1926
1970
  repeat=False,
1927
1971
  )
1928
- base_path = glob_path.resolve().parent.parent
1972
+ base_path = resolved_glob_path.parent.parent
1929
1973
 
1930
1974
  if policy not in ("live", "end", "now"):
1931
1975
  raise ValueError(
1932
1976
  'Only "live", "end" and "now" policies are currently supported.'
1933
1977
  )
1934
1978
 
1935
- resolved_glob_path = glob_path.resolve()
1936
- resolved_base_path = base_path.resolve()
1979
+ resolved_base_path = pathlib.PurePath(os.path.abspath(base_path))
1937
1980
 
1938
1981
  return self._save(
1939
1982
  resolved_glob_path,
@@ -1943,8 +1986,8 @@ class Run:
1943
1986
 
1944
1987
  def _save(
1945
1988
  self,
1946
- glob_path: pathlib.Path,
1947
- base_path: pathlib.Path,
1989
+ glob_path: pathlib.PurePath,
1990
+ base_path: pathlib.PurePath,
1948
1991
  policy: "PolicyName",
1949
1992
  ) -> List[str]:
1950
1993
  # Can't use is_relative_to() because that's added in Python 3.9,
@@ -2440,6 +2483,8 @@ class Run:
2440
2483
  self._telemetry_obj_active = True
2441
2484
  self._telemetry_flush()
2442
2485
 
2486
+ self._detect_and_apply_job_inputs()
2487
+
2443
2488
  # object is about to be returned to the user, don't let them modify it
2444
2489
  self._freeze()
2445
2490
 
@@ -2447,6 +2492,12 @@ class Run:
2447
2492
  if os.path.exists(self._settings.resume_fname):
2448
2493
  os.remove(self._settings.resume_fname)
2449
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
+
2450
2501
  def _make_job_source_reqs(self) -> Tuple[List[str], Dict[str, Any], Dict[str, Any]]:
2451
2502
  from wandb.util import working_set
2452
2503
 
@@ -2552,6 +2603,14 @@ class Run:
2552
2603
  self._console_stop() # TODO: there's a race here with jupyter console logging
2553
2604
 
2554
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
+
2555
2614
  exit_handle = self._backend.interface.deliver_exit(self._exit_code)
2556
2615
  exit_handle.add_probe(on_probe=self._on_probe_exit)
2557
2616
 
@@ -2560,6 +2619,7 @@ class Run:
2560
2619
  # self._exit_code, settings=self._settings, printer=self._printer
2561
2620
  # )
2562
2621
 
2622
+ # wait for the exit to complete
2563
2623
  _ = exit_handle.wait(timeout=-1, on_progress=self._on_progress_exit)
2564
2624
 
2565
2625
  poll_exit_handle = self._backend.interface.deliver_poll_exit()
@@ -2577,16 +2637,11 @@ class Run:
2577
2637
 
2578
2638
  # dispatch all our final requests
2579
2639
 
2580
- server_info_handle = self._backend.interface.deliver_request_server_info()
2581
2640
  final_summary_handle = self._backend.interface.deliver_get_summary()
2582
2641
  sampled_history_handle = (
2583
2642
  self._backend.interface.deliver_request_sampled_history()
2584
2643
  )
2585
2644
 
2586
- result = server_info_handle.wait(timeout=-1)
2587
- assert result
2588
- self._server_info_response = result.response.server_info_response
2589
-
2590
2645
  result = sampled_history_handle.wait(timeout=-1)
2591
2646
  assert result
2592
2647
  self._sampled_history = result.response.sampled_history_response
@@ -2705,12 +2760,23 @@ class Run:
2705
2760
  if i not in valid:
2706
2761
  raise wandb.Error(f"Unhandled define_metric() arg: summary op: {i}")
2707
2762
  summary_ops.append(i)
2763
+ with telemetry.context(run=self) as tel:
2764
+ tel.feature.metric_summary = True
2708
2765
  goal_cleaned: Optional[str] = None
2709
2766
  if goal is not None:
2710
2767
  goal_cleaned = goal[:3].lower()
2711
2768
  valid_goal = {"min", "max"}
2712
2769
  if goal_cleaned not in valid_goal:
2713
2770
  raise wandb.Error(f"Unhandled define_metric() arg: goal: {goal}")
2771
+ with telemetry.context(run=self) as tel:
2772
+ tel.feature.metric_goal = True
2773
+ if hidden:
2774
+ with telemetry.context(run=self) as tel:
2775
+ tel.feature.metric_hidden = True
2776
+ if step_sync:
2777
+ with telemetry.context(run=self) as tel:
2778
+ tel.feature.metric_step_sync = True
2779
+
2714
2780
  m = wandb_metric.Metric(
2715
2781
  name=name,
2716
2782
  step_metric=step_metric,
@@ -2895,6 +2961,7 @@ class Run:
2895
2961
  api.use_artifact(
2896
2962
  artifact.id,
2897
2963
  entity_name=r.entity,
2964
+ project_name=r.project,
2898
2965
  use_as=use_as or artifact_or_name,
2899
2966
  )
2900
2967
  else:
@@ -2957,8 +3024,7 @@ class Run:
2957
3024
  - `s3://bucket/path`
2958
3025
  You can also pass an Artifact object created by calling
2959
3026
  `wandb.Artifact`.
2960
- name: (str, optional) An artifact name. May be prefixed with entity/project.
2961
- Valid names can be in the following forms:
3027
+ name: (str, optional) An artifact name. Valid names can be in the following forms:
2962
3028
  - name:version
2963
3029
  - name:alias
2964
3030
  - digest
@@ -3604,7 +3670,11 @@ class Run:
3604
3670
  project_url = settings.project_url
3605
3671
  sweep_url = settings.sweep_url
3606
3672
 
3607
- run_state_str = "Resuming run" if settings.resumed else "Syncing run"
3673
+ run_state_str = (
3674
+ "Resuming run"
3675
+ if settings.resumed or settings.resume_from
3676
+ else "Syncing run"
3677
+ )
3608
3678
  run_name = settings.run_name
3609
3679
  if not run_name:
3610
3680
  return
@@ -3658,7 +3728,7 @@ class Run:
3658
3728
  # FOOTER
3659
3729
  # ------------------------------------------------------------------------------
3660
3730
  # Note: All the footer methods are static methods since we want to share the printing logic
3661
- # with the service execution path that doesn't have acess to the run instance
3731
+ # with the service execution path that doesn't have access to the run instance
3662
3732
  @staticmethod
3663
3733
  def _footer(
3664
3734
  sampled_history: Optional["SampledHistoryResponse"] = None,
@@ -3961,11 +4031,11 @@ class Run:
3961
4031
 
3962
4032
  # Render summary if available
3963
4033
  if summary:
3964
- final_summary = {
3965
- item.key: json.loads(item.value_json)
3966
- for item in summary.item
3967
- if not item.key.startswith("_")
3968
- }
4034
+ final_summary = {}
4035
+ for item in summary.item:
4036
+ if item.key.startswith("_") or len(item.nested_key) > 0:
4037
+ continue
4038
+ final_summary[item.key] = json.loads(item.value_json)
3969
4039
 
3970
4040
  logger.info("rendering summary")
3971
4041
  summary_rows = []