wandb 0.19.9__py3-none-musllinux_1_2_aarch64.whl → 0.19.11__py3-none-musllinux_1_2_aarch64.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 (156) hide show
  1. wandb/__init__.py +1 -1
  2. wandb/__init__.pyi +6 -3
  3. wandb/_pydantic/__init__.py +14 -8
  4. wandb/_pydantic/base.py +51 -36
  5. wandb/_pydantic/utils.py +73 -0
  6. wandb/_pydantic/v1_compat.py +79 -57
  7. wandb/apis/public/__init__.py +2 -2
  8. wandb/apis/public/api.py +684 -4
  9. wandb/apis/public/artifacts.py +377 -677
  10. wandb/apis/public/automations.py +69 -0
  11. wandb/apis/public/integrations.py +180 -0
  12. wandb/apis/public/projects.py +29 -0
  13. wandb/apis/public/registries/__init__.py +0 -0
  14. wandb/apis/public/registries/_freezable_list.py +179 -0
  15. wandb/apis/public/{registries.py → registries/registries_search.py} +22 -129
  16. wandb/apis/public/registries/registry.py +357 -0
  17. wandb/apis/public/registries/utils.py +140 -0
  18. wandb/apis/public/runs.py +58 -56
  19. wandb/apis/public/utils.py +107 -1
  20. wandb/automations/__init__.py +73 -0
  21. wandb/automations/_filters/__init__.py +40 -0
  22. wandb/automations/_filters/expressions.py +181 -0
  23. wandb/automations/_filters/operators.py +258 -0
  24. wandb/automations/_filters/run_metrics.py +332 -0
  25. wandb/automations/_generated/__init__.py +177 -0
  26. wandb/automations/_generated/create_automation.py +17 -0
  27. wandb/automations/_generated/create_generic_webhook_integration.py +43 -0
  28. wandb/automations/_generated/delete_automation.py +17 -0
  29. wandb/automations/_generated/enums.py +33 -0
  30. wandb/automations/_generated/fragments.py +358 -0
  31. wandb/automations/_generated/generic_webhook_integrations_by_entity.py +22 -0
  32. wandb/automations/_generated/get_automations.py +24 -0
  33. wandb/automations/_generated/get_automations_by_entity.py +26 -0
  34. wandb/automations/_generated/input_types.py +104 -0
  35. wandb/automations/_generated/integrations_by_entity.py +22 -0
  36. wandb/automations/_generated/operations.py +647 -0
  37. wandb/automations/_generated/slack_integrations_by_entity.py +22 -0
  38. wandb/automations/_generated/update_automation.py +17 -0
  39. wandb/automations/_utils.py +237 -0
  40. wandb/automations/_validators.py +165 -0
  41. wandb/automations/actions.py +220 -0
  42. wandb/automations/automations.py +87 -0
  43. wandb/automations/events.py +287 -0
  44. wandb/automations/integrations.py +45 -0
  45. wandb/automations/scopes.py +78 -0
  46. wandb/beta/workflows.py +9 -10
  47. wandb/bin/gpu_stats +0 -0
  48. wandb/bin/wandb-core +0 -0
  49. wandb/cli/cli.py +3 -3
  50. wandb/env.py +11 -0
  51. wandb/integration/keras/keras.py +2 -1
  52. wandb/integration/langchain/wandb_tracer.py +2 -1
  53. wandb/jupyter.py +137 -118
  54. wandb/old/settings.py +4 -1
  55. wandb/old/summary.py +0 -2
  56. wandb/proto/v3/wandb_internal_pb2.py +297 -292
  57. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  58. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  59. wandb/proto/v4/wandb_internal_pb2.py +292 -292
  60. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  61. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  62. wandb/proto/v5/wandb_internal_pb2.py +292 -292
  63. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  64. wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
  65. wandb/proto/v6/wandb_base_pb2.py +41 -0
  66. wandb/proto/v6/wandb_internal_pb2.py +393 -0
  67. wandb/proto/v6/wandb_server_pb2.py +78 -0
  68. wandb/proto/v6/wandb_settings_pb2.py +58 -0
  69. wandb/proto/v6/wandb_telemetry_pb2.py +52 -0
  70. wandb/proto/wandb_base_pb2.py +2 -0
  71. wandb/proto/wandb_deprecated.py +8 -0
  72. wandb/proto/wandb_internal_pb2.py +3 -1
  73. wandb/proto/wandb_server_pb2.py +2 -0
  74. wandb/proto/wandb_settings_pb2.py +2 -0
  75. wandb/proto/wandb_telemetry_pb2.py +2 -0
  76. wandb/sdk/artifacts/_generated/__init__.py +289 -0
  77. wandb/sdk/artifacts/_generated/add_aliases.py +21 -0
  78. wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +43 -0
  79. wandb/sdk/artifacts/_generated/artifact_version_files.py +36 -0
  80. wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +36 -0
  81. wandb/sdk/artifacts/_generated/delete_aliases.py +21 -0
  82. wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +25 -0
  83. wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +35 -0
  84. wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +35 -0
  85. wandb/sdk/artifacts/_generated/enums.py +17 -0
  86. wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +67 -0
  87. wandb/sdk/artifacts/_generated/fragments.py +221 -0
  88. wandb/sdk/artifacts/_generated/input_types.py +28 -0
  89. wandb/sdk/artifacts/_generated/move_artifact_collection.py +35 -0
  90. wandb/sdk/artifacts/_generated/operations.py +611 -0
  91. wandb/sdk/artifacts/_generated/project_artifact_collection.py +101 -0
  92. wandb/sdk/artifacts/_generated/project_artifact_collections.py +33 -0
  93. wandb/sdk/artifacts/_generated/project_artifact_type.py +24 -0
  94. wandb/sdk/artifacts/_generated/project_artifact_types.py +24 -0
  95. wandb/sdk/artifacts/_generated/project_artifacts.py +42 -0
  96. wandb/sdk/artifacts/_generated/run_input_artifacts.py +51 -0
  97. wandb/sdk/artifacts/_generated/run_output_artifacts.py +51 -0
  98. wandb/sdk/artifacts/_generated/update_artifact.py +26 -0
  99. wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +35 -0
  100. wandb/sdk/artifacts/_generated/update_artifact_sequence.py +35 -0
  101. wandb/sdk/artifacts/_graphql_fragments.py +57 -79
  102. wandb/sdk/artifacts/_validators.py +120 -1
  103. wandb/sdk/artifacts/artifact.py +419 -215
  104. wandb/sdk/artifacts/artifact_file_cache.py +4 -6
  105. wandb/sdk/artifacts/artifact_manifest_entry.py +13 -3
  106. wandb/sdk/artifacts/storage_handlers/azure_handler.py +1 -0
  107. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +182 -1
  108. wandb/sdk/artifacts/storage_policy.py +3 -0
  109. wandb/sdk/data_types/base_types/media.py +2 -3
  110. wandb/sdk/data_types/base_types/wb_value.py +34 -11
  111. wandb/sdk/data_types/html.py +36 -9
  112. wandb/sdk/data_types/image.py +12 -12
  113. wandb/sdk/data_types/table.py +5 -0
  114. wandb/sdk/data_types/trace_tree.py +2 -0
  115. wandb/sdk/data_types/utils.py +1 -1
  116. wandb/sdk/data_types/video.py +59 -57
  117. wandb/sdk/interface/interface.py +4 -3
  118. wandb/sdk/internal/internal_api.py +21 -31
  119. wandb/sdk/internal/profiler.py +6 -5
  120. wandb/sdk/internal/run.py +13 -6
  121. wandb/sdk/internal/sender.py +5 -2
  122. wandb/sdk/launch/sweeps/utils.py +8 -0
  123. wandb/sdk/lib/apikey.py +25 -4
  124. wandb/sdk/lib/asyncio_compat.py +1 -1
  125. wandb/sdk/lib/deprecate.py +13 -22
  126. wandb/sdk/lib/disabled.py +2 -1
  127. wandb/sdk/lib/printer.py +37 -8
  128. wandb/sdk/lib/printer_asyncio.py +46 -0
  129. wandb/sdk/lib/redirect.py +10 -5
  130. wandb/sdk/projects/_generated/__init__.py +47 -0
  131. wandb/sdk/projects/_generated/delete_project.py +22 -0
  132. wandb/sdk/projects/_generated/enums.py +4 -0
  133. wandb/sdk/projects/_generated/fetch_registry.py +22 -0
  134. wandb/sdk/projects/_generated/fragments.py +41 -0
  135. wandb/sdk/projects/_generated/input_types.py +13 -0
  136. wandb/sdk/projects/_generated/operations.py +88 -0
  137. wandb/sdk/projects/_generated/rename_project.py +27 -0
  138. wandb/sdk/projects/_generated/upsert_registry_project.py +27 -0
  139. wandb/sdk/service/server_sock.py +19 -14
  140. wandb/sdk/service/service.py +18 -8
  141. wandb/sdk/service/streams.py +5 -0
  142. wandb/sdk/verify/verify.py +6 -3
  143. wandb/sdk/wandb_init.py +217 -70
  144. wandb/sdk/wandb_login.py +13 -4
  145. wandb/sdk/wandb_run.py +419 -295
  146. wandb/sdk/wandb_settings.py +27 -10
  147. wandb/sdk/wandb_setup.py +61 -0
  148. wandb/util.py +33 -29
  149. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/METADATA +5 -5
  150. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/RECORD +153 -83
  151. wandb/_globals.py +0 -19
  152. wandb/sdk/internal/_generated/base.py +0 -226
  153. wandb/sdk/internal/_generated/typing_compat.py +0 -14
  154. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/WHEEL +0 -0
  155. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/entry_points.txt +0 -0
  156. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_init.py CHANGED
@@ -21,7 +21,7 @@ import platform
21
21
  import sys
22
22
  import tempfile
23
23
  import time
24
- from typing import Any, Iterator, Literal, Sequence
24
+ from typing import TYPE_CHECKING, Any, Iterable, Iterator, Literal, Protocol, Sequence
25
25
 
26
26
  if sys.version_info >= (3, 11):
27
27
  from typing import Self
@@ -35,6 +35,7 @@ from wandb.errors import CommError, Error, UsageError
35
35
  from wandb.errors.links import url_registry
36
36
  from wandb.errors.util import ProtobufErrorHandler
37
37
  from wandb.integration import sagemaker
38
+ from wandb.proto.wandb_deprecated import Deprecated
38
39
  from wandb.sdk.lib import ipython as wb_ipython
39
40
  from wandb.sdk.lib import progress, runid, wb_logging
40
41
  from wandb.sdk.lib.paths import StrPath
@@ -43,12 +44,15 @@ from wandb.util import _is_artifact_representation
43
44
  from . import wandb_login, wandb_setup
44
45
  from .backend.backend import Backend
45
46
  from .lib import SummaryDisabled, filesystem, module, paths, printer, telemetry
46
- from .lib.deprecate import Deprecated, deprecate
47
+ from .lib.deprecate import deprecate
47
48
  from .mailbox import wait_with_progress
48
49
  from .wandb_helper import parse_config
49
50
  from .wandb_run import Run, TeardownHook, TeardownStage
50
51
  from .wandb_settings import Settings
51
52
 
53
+ if TYPE_CHECKING:
54
+ import wandb.jupyter
55
+
52
56
 
53
57
  def _huggingface_version() -> str | None:
54
58
  if "transformers" in sys.modules:
@@ -124,6 +128,34 @@ class _ConfigParts:
124
128
  """
125
129
 
126
130
 
131
+ class _PrinterCallback(Protocol):
132
+ """A callback for displaying messages after a printer is configured.
133
+
134
+ This is used for a few messages that may be generated before run settings
135
+ are computed, which are necessary for creating a printer.
136
+ """
137
+
138
+ def __call__(self, run_printer: printer.Printer) -> None:
139
+ """Display information through the given printer."""
140
+
141
+
142
+ def _noop_printer_callback() -> _PrinterCallback:
143
+ """A printer callback that does not print anything."""
144
+ return lambda _: None
145
+
146
+
147
+ def _concat_printer_callbacks(
148
+ cbs: Iterable[_PrinterCallback],
149
+ ) -> _PrinterCallback:
150
+ """Returns a printer callback that runs the given callbacks in order."""
151
+
152
+ def do_callbacks(run_printer: printer.Printer) -> None:
153
+ for cb in cbs:
154
+ cb(run_printer)
155
+
156
+ return do_callbacks
157
+
158
+
127
159
  class _WandbInit:
128
160
  def __init__(
129
161
  self,
@@ -143,8 +175,7 @@ class _WandbInit:
143
175
  self.backend: Backend | None = None
144
176
 
145
177
  self._teardown_hooks: list[TeardownHook] = []
146
- self.notebook: wandb.jupyter.Notebook | None = None # type: ignore
147
- self.printer = printer.new_printer()
178
+ self.notebook: wandb.jupyter.Notebook | None = None
148
179
 
149
180
  self.deprecated_features_used: dict[str, str] = dict()
150
181
 
@@ -176,20 +207,21 @@ class _WandbInit:
176
207
 
177
208
  wandb_login._login(
178
209
  anonymous=run_settings.anonymous,
210
+ host=run_settings.base_url,
179
211
  force=run_settings.force,
180
212
  _disable_warning=True,
181
213
  _silent=run_settings.quiet or run_settings.silent,
182
214
  )
183
215
 
184
- def warn_env_vars_change_after_setup(self) -> None:
185
- """Warn if environment variables change after wandb singleton is initialized.
216
+ def warn_env_vars_change_after_setup(self) -> _PrinterCallback:
217
+ """Warn if environment variables changed after `wandb.setup()`.
186
218
 
187
- Any settings from environment variables set after the singleton is initialized
188
- (via login/setup/etc.) will be ignored.
219
+ Returns:
220
+ A callback to print any generated warnings.
189
221
  """
190
222
  singleton = wandb_setup.singleton()
191
223
  if singleton is None:
192
- return
224
+ return _noop_printer_callback()
193
225
 
194
226
  exclude_env_vars = {"WANDB_SERVICE", "WANDB_KUBEFLOW_URL"}
195
227
  # check if environment variables have changed
@@ -203,26 +235,36 @@ class _WandbInit:
203
235
  for k, v in os.environ.items()
204
236
  if k.startswith("WANDB_") and k not in exclude_env_vars
205
237
  }
206
- if set(singleton_env.keys()) != set(os_env.keys()) or set(
207
- singleton_env.values()
208
- ) != set(os_env.values()):
238
+
239
+ if (
240
+ set(singleton_env.keys()) == set(os_env.keys()) #
241
+ and set(singleton_env.values()) == set(os_env.values())
242
+ ):
243
+ return _noop_printer_callback()
244
+
245
+ def print_warning(run_printer: printer.Printer) -> None:
209
246
  line = (
210
247
  "Changes to your `wandb` environment variables will be ignored "
211
248
  "because your `wandb` session has already started. "
212
249
  "For more information on how to modify your settings with "
213
250
  "`wandb.init()` arguments, please refer to "
214
- f"{self.printer.link(url_registry.url('wandb-init'), 'the W&B docs')}."
251
+ f"{run_printer.link(url_registry.url('wandb-init'), 'the W&B docs')}."
215
252
  )
216
- self.printer.display(line, level="warn")
253
+ run_printer.display(line, level="warn")
254
+
255
+ return print_warning
217
256
 
218
257
  def clear_run_path_if_sweep_or_launch(
219
258
  self,
220
259
  init_settings: Settings,
221
- ) -> None:
260
+ ) -> _PrinterCallback:
222
261
  """Clear project/entity/run_id keys if in a Sweep or a Launch context.
223
262
 
224
263
  Args:
225
264
  init_settings: Settings specified in the call to `wandb.init()`.
265
+
266
+ Returns:
267
+ A callback to print any generated warnings.
226
268
  """
227
269
  when_doing_thing = ""
228
270
 
@@ -232,13 +274,12 @@ class _WandbInit:
232
274
  when_doing_thing = "when running from a wandb launch context"
233
275
 
234
276
  if not when_doing_thing:
235
- return
277
+ return _noop_printer_callback()
278
+
279
+ warnings = []
236
280
 
237
281
  def warn(key: str, value: str) -> None:
238
- self.printer.display(
239
- f"Ignoring {key} {value!r} {when_doing_thing}.",
240
- level="warn",
241
- )
282
+ warnings.append(f"Ignoring {key} {value!r} {when_doing_thing}.")
242
283
 
243
284
  if init_settings.project is not None:
244
285
  warn("project", init_settings.project)
@@ -250,16 +291,26 @@ class _WandbInit:
250
291
  warn("run_id", init_settings.run_id)
251
292
  init_settings.run_id = None
252
293
 
253
- def make_run_settings(self, init_settings: Settings) -> Settings:
254
- """Returns the run's settings.
294
+ def print_warnings(run_printer: printer.Printer) -> None:
295
+ for warning in warnings:
296
+ run_printer.display(warning, level="warn")
297
+
298
+ return print_warnings
299
+
300
+ def make_run_settings(
301
+ self,
302
+ init_settings: Settings,
303
+ ) -> tuple[Settings, _PrinterCallback]:
304
+ """Returns the run's settings and any warnings.
255
305
 
256
306
  Args:
257
307
  init_settings: Settings passed to `wandb.init()` or set via
258
308
  keyword arguments.
259
309
  """
260
- self.warn_env_vars_change_after_setup()
261
-
262
- self.clear_run_path_if_sweep_or_launch(init_settings)
310
+ warning_callbacks: list[_PrinterCallback] = [
311
+ self.warn_env_vars_change_after_setup(),
312
+ self.clear_run_path_if_sweep_or_launch(init_settings),
313
+ ]
263
314
 
264
315
  # Inherit global settings.
265
316
  settings = self._wl.settings.model_copy()
@@ -305,7 +356,7 @@ class _WandbInit:
305
356
  label = runid.generate_id()
306
357
  settings.x_label = f"{prefix}-{label}" if prefix else label
307
358
 
308
- return settings
359
+ return settings, _concat_printer_callbacks(warning_callbacks)
309
360
 
310
361
  def _load_autoresume_run_id(self, resume_file: pathlib.Path) -> str | None:
311
362
  """Returns the run_id stored in the auto-resume file, if any.
@@ -533,62 +584,73 @@ class _WandbInit:
533
584
  except OSError:
534
585
  pass
535
586
 
536
- def _pause_backend(self, *args: Any, **kwargs: Any) -> None: # noqa
537
- if self.backend is None:
538
- return None
587
+ def _pre_run_cell_hook(self, *args, **kwargs) -> None:
588
+ """Hook for the IPython pre_run_cell event.
539
589
 
540
- # Attempt to save the code on every execution
541
- if self.notebook.save_ipynb(): # type: ignore
590
+ This pauses a run, preventing system metrics from being collected
591
+ the run's runtime from increasing. It also uploads the notebook's code.
592
+ """
593
+ if not self.backend:
594
+ return
595
+
596
+ if self.notebook and self.notebook.save_ipynb():
542
597
  assert self.run is not None
543
598
  res = self.run.log_code(root=None)
544
- self._logger.info("saved code: %s", res) # type: ignore
599
+ self._logger.info("saved code: %s", res)
600
+
545
601
  if self.backend.interface is not None:
546
- self._logger.info("pausing backend") # type: ignore
602
+ self._logger.info("pausing backend")
547
603
  self.backend.interface.publish_pause()
548
604
 
549
- def _resume_backend(self, *args: Any, **kwargs: Any) -> None: # noqa
550
- if self.backend is not None and self.backend.interface is not None:
551
- self._logger.info("resuming backend") # type: ignore
552
- self.backend.interface.publish_resume()
605
+ def _post_run_cell_hook(self, *args, **kwargs) -> None:
606
+ """Hook for the IPython post_run_cell event.
607
+
608
+ Resumes collection of system metrics and the run's timer.
609
+ """
610
+ if self.backend is None or self.backend.interface is None:
611
+ return
612
+
613
+ self._logger.info("resuming backend")
614
+ self.backend.interface.publish_resume()
553
615
 
554
616
  def _jupyter_teardown(self) -> None:
555
617
  """Teardown hooks and display saving, called with wandb.finish."""
556
618
  assert self.notebook
557
619
  ipython = self.notebook.shell
558
- self.notebook.save_history()
620
+
621
+ if self.run:
622
+ self.notebook.save_history(self.run)
623
+
559
624
  if self.notebook.save_ipynb():
560
625
  assert self.run is not None
561
626
  res = self.run.log_code(root=None)
562
- self._logger.info("saved code and history: %s", res) # type: ignore
563
- self._logger.info("cleaning up jupyter logic") # type: ignore
564
- # because of how we bind our methods we manually find them to unregister
565
- for hook in ipython.events.callbacks["pre_run_cell"]:
566
- if "_resume_backend" in hook.__name__:
567
- ipython.events.unregister("pre_run_cell", hook)
568
- for hook in ipython.events.callbacks["post_run_cell"]:
569
- if "_pause_backend" in hook.__name__:
570
- ipython.events.unregister("post_run_cell", hook)
627
+ self._logger.info("saved code and history: %s", res)
628
+ self._logger.info("cleaning up jupyter logic")
629
+
630
+ ipython.events.unregister("pre_run_cell", self._pre_run_cell_hook)
631
+ ipython.events.unregister("post_run_cell", self._post_run_cell_hook)
632
+
571
633
  ipython.display_pub.publish = ipython.display_pub._orig_publish
572
634
  del ipython.display_pub._orig_publish
573
635
 
574
636
  def monkeypatch_ipython(self, settings: Settings) -> None:
575
637
  """Add hooks, and session history saving."""
576
- self.notebook = wandb.jupyter.Notebook(settings) # type: ignore
638
+ self.notebook = wandb.jupyter.Notebook(settings)
577
639
  ipython = self.notebook.shell
578
640
 
579
641
  # Monkey patch ipython publish to capture displayed outputs
580
642
  if not hasattr(ipython.display_pub, "_orig_publish"):
581
- self._logger.info("configuring jupyter hooks %s", self) # type: ignore
643
+ self._logger.info("configuring jupyter hooks %s", self)
582
644
  ipython.display_pub._orig_publish = ipython.display_pub.publish
583
- # Registering resume and pause hooks
584
645
 
585
- ipython.events.register("pre_run_cell", self._resume_backend)
586
- ipython.events.register("post_run_cell", self._pause_backend)
646
+ ipython.events.register("pre_run_cell", self._pre_run_cell_hook)
647
+ ipython.events.register("post_run_cell", self._post_run_cell_hook)
648
+
587
649
  self._teardown_hooks.append(
588
650
  TeardownHook(self._jupyter_teardown, TeardownStage.EARLY)
589
651
  )
590
652
 
591
- def publish(data, metadata=None, **kwargs) -> None: # type: ignore
653
+ def publish(data, metadata=None, **kwargs) -> None:
592
654
  ipython.display_pub._orig_publish(data, metadata=metadata, **kwargs)
593
655
  assert self.notebook is not None
594
656
  self.notebook.save_display(
@@ -729,6 +791,10 @@ class _WandbInit:
729
791
  ):
730
792
  setattr(drun, symbol, lambda *_, **__: None) # type: ignore
731
793
 
794
+ # set properties to None
795
+ for attr in ("url", "project_url", "sweep_url"):
796
+ setattr(type(drun), attr, property(lambda _: None))
797
+
732
798
  class _ChainableNoOp:
733
799
  """An object that allows chaining arbitrary attributes and method calls."""
734
800
 
@@ -753,7 +819,7 @@ class _WandbInit:
753
819
  def __call__(self, *args: Any, **kwargs: Any) -> _ChainableNoOp:
754
820
  return _ChainableNoOp()
755
821
 
756
- drun.log_artifact = _ChainableNoOpField() # type: ignore[method-assign]
822
+ drun.log_artifact = _ChainableNoOpField() # type: ignore
757
823
  # attributes
758
824
  drun._start_time = time.time()
759
825
  drun._starting_step = 0
@@ -777,7 +843,12 @@ class _WandbInit:
777
843
  )
778
844
  return drun
779
845
 
780
- def init(self, settings: Settings, config: _ConfigParts) -> Run: # noqa: C901
846
+ def init( # noqa: C901
847
+ self,
848
+ settings: Settings,
849
+ config: _ConfigParts,
850
+ run_printer: printer.Printer,
851
+ ) -> Run:
781
852
  self._logger.info("calling init triggers")
782
853
  trigger.call("on_init")
783
854
 
@@ -788,23 +859,36 @@ class _WandbInit:
788
859
  f"\nconfig: {config.base_no_artifacts}"
789
860
  )
790
861
 
791
- if wandb.run is not None and os.getpid() == wandb.run._init_pid:
862
+ if previous_run := self._wl.most_recent_active_run:
792
863
  if (
793
864
  settings.reinit in (True, "finish_previous")
794
865
  # calling wandb.init() in notebooks finishes previous runs
795
866
  # by default for user convenience.
796
867
  or (settings.reinit == "default" and wb_ipython.in_notebook())
797
868
  ):
798
- self._logger.info("finishing previous run: %s", wandb.run.id)
799
- wandb.run.finish()
869
+ run_printer.display(
870
+ "Finishing previous runs because reinit is set"
871
+ f" to {settings.reinit!r}."
872
+ )
873
+ self._wl.finish_all_active_runs()
874
+
875
+ elif settings.reinit == "create_new":
876
+ self._logger.info(
877
+ "wandb.init() called while a run is active,"
878
+ " and reinit is set to 'create_new', so continuing"
879
+ )
880
+
800
881
  else:
801
- self._logger.info("wandb.init() called while a run is active")
882
+ run_printer.display(
883
+ "wandb.init() called while a run is active and reinit is"
884
+ f" set to {settings.reinit!r}, so returning the previous"
885
+ " run."
886
+ )
802
887
 
803
- # NOTE: Updates telemetry on the pre-existing run.
804
- with telemetry.context() as tel:
888
+ with telemetry.context(run=previous_run) as tel:
805
889
  tel.feature.init_return_run = True
806
890
 
807
- return wandb.run
891
+ return previous_run
808
892
 
809
893
  self._logger.info("starting backend")
810
894
 
@@ -897,6 +981,12 @@ class _WandbInit:
897
981
  )
898
982
  tel.feature.shared_mode = True
899
983
 
984
+ if settings.x_label:
985
+ tel.feature.user_provided_label = True
986
+
987
+ if wandb.env.dcgm_profiling_enabled():
988
+ tel.feature.dcgm_profiling_enabled = True
989
+
900
990
  tel.env.maybe_mp = _maybe_mp_process(backend)
901
991
 
902
992
  if not settings.label_disable:
@@ -946,7 +1036,7 @@ class _WandbInit:
946
1036
  assert backend.interface
947
1037
 
948
1038
  with progress.progress_printer(
949
- self.printer,
1039
+ run_printer,
950
1040
  default_text="Waiting for wandb.init()...",
951
1041
  ) as progress_printer:
952
1042
  await progress.loop_printing_operation_stats(
@@ -1052,6 +1142,10 @@ class _WandbInit:
1052
1142
  run.use_artifact(job_artifact)
1053
1143
 
1054
1144
  self.backend = backend
1145
+
1146
+ if settings.reinit != "create_new":
1147
+ _set_global_run(run)
1148
+
1055
1149
  run._on_start()
1056
1150
  self._logger.info("run started, returning control to user process")
1057
1151
  return run
@@ -1128,10 +1222,36 @@ def _attach(
1128
1222
  raise UsageError(f"Failed to attach to run: {attach_response.error.message}")
1129
1223
 
1130
1224
  run._set_run_obj(attach_response.run)
1225
+ _set_global_run(run)
1131
1226
  run._on_attach()
1132
1227
  return run
1133
1228
 
1134
1229
 
1230
+ def _set_global_run(run: Run) -> None:
1231
+ """Set `wandb.run` and point some top-level functions to its methods.
1232
+
1233
+ Args:
1234
+ run: The run to make global.
1235
+ """
1236
+ module.set_global(
1237
+ run=run,
1238
+ config=run.config,
1239
+ log=run.log,
1240
+ summary=run.summary,
1241
+ save=run.save,
1242
+ use_artifact=run.use_artifact,
1243
+ log_artifact=run.log_artifact,
1244
+ define_metric=run.define_metric,
1245
+ alert=run.alert,
1246
+ watch=run.watch,
1247
+ unwatch=run.unwatch,
1248
+ mark_preempting=run.mark_preempting,
1249
+ log_model=run.log_model,
1250
+ use_model=run.use_model,
1251
+ link_model=run.link_model,
1252
+ )
1253
+
1254
+
1135
1255
  def _monkeypatch_openai_gym() -> None:
1136
1256
  """Patch OpenAI gym to log to the global `wandb.run`."""
1137
1257
  if len(wandb.patched["gym"]) > 0:
@@ -1163,16 +1283,40 @@ def try_create_root_dir(settings: Settings) -> None:
1163
1283
  This function may update the root_dir to a temporary directory
1164
1284
  if the parent directory is not writable.
1165
1285
  """
1286
+ fallback_to_temp_dir = False
1287
+
1166
1288
  try:
1167
- if not os.path.exists(settings.root_dir):
1168
- os.makedirs(settings.root_dir, exist_ok=True)
1289
+ os.makedirs(settings.root_dir, exist_ok=True)
1169
1290
  except OSError:
1170
- temp_dir = tempfile.gettempdir()
1171
1291
  wandb.termwarn(
1172
- f"Path {settings.root_dir} wasn't writable, using system temp directory {temp_dir}.",
1292
+ f"Unable to create root directory {settings.root_dir}",
1173
1293
  repeat=False,
1174
1294
  )
1175
- settings.root_dir = temp_dir
1295
+ fallback_to_temp_dir = True
1296
+ else:
1297
+ if not os.access(settings.root_dir, os.W_OK | os.R_OK):
1298
+ wandb.termwarn(
1299
+ f"Path {settings.root_dir} wasn't read/writable",
1300
+ repeat=False,
1301
+ )
1302
+ fallback_to_temp_dir = True
1303
+
1304
+ if not fallback_to_temp_dir:
1305
+ return
1306
+
1307
+ tmp_dir = tempfile.gettempdir()
1308
+ if not os.access(tmp_dir, os.W_OK | os.R_OK):
1309
+ raise ValueError(
1310
+ f"System temp directory ({tmp_dir}) is not writable/readable, "
1311
+ "please set the `dir` argument in `wandb.init()` to a writable/readable directory."
1312
+ )
1313
+
1314
+ settings.root_dir = tmp_dir
1315
+ wandb.termwarn(
1316
+ f"Falling back to temporary directory {tmp_dir}.",
1317
+ repeat=False,
1318
+ )
1319
+ os.makedirs(settings.root_dir, exist_ok=True)
1176
1320
 
1177
1321
 
1178
1322
  def init( # noqa: C901
@@ -1199,6 +1343,7 @@ def init( # noqa: C901
1199
1343
  "default",
1200
1344
  "return_previous",
1201
1345
  "finish_previous",
1346
+ "create_new",
1202
1347
  ]
1203
1348
  ) = None,
1204
1349
  resume: bool | Literal["allow", "never", "must", "auto"] | None = None,
@@ -1476,7 +1621,7 @@ def init( # noqa: C901
1476
1621
  wi = _WandbInit(wl, init_telemetry)
1477
1622
 
1478
1623
  wi.maybe_login(init_settings)
1479
- run_settings = wi.make_run_settings(init_settings)
1624
+ run_settings, show_warnings = wi.make_run_settings(init_settings)
1480
1625
 
1481
1626
  if isinstance(run_settings.reinit, bool):
1482
1627
  wi.deprecated_features_used["run__reinit_bool"] = (
@@ -1494,6 +1639,8 @@ def init( # noqa: C901
1494
1639
  init_telemetry.feature.offline = True
1495
1640
 
1496
1641
  wi.set_run_id(run_settings)
1642
+ run_printer = printer.new_printer(run_settings)
1643
+ show_warnings(run_printer)
1497
1644
 
1498
1645
  with contextlib.ExitStack() as exit_stack:
1499
1646
  exit_stack.enter_context(wb_logging.log_to_run(run_settings.run_id))
@@ -1527,7 +1674,7 @@ def init( # noqa: C901
1527
1674
  if run_settings.x_server_side_derived_summary:
1528
1675
  init_telemetry.feature.server_side_derived_summary = True
1529
1676
 
1530
- return wi.init(run_settings, run_config)
1677
+ return wi.init(run_settings, run_config, run_printer)
1531
1678
 
1532
1679
  except KeyboardInterrupt as e:
1533
1680
  if wl:
wandb/sdk/wandb_login.py CHANGED
@@ -45,6 +45,7 @@ def login(
45
45
  force: Optional[bool] = None,
46
46
  timeout: Optional[int] = None,
47
47
  verify: bool = False,
48
+ referrer: Optional[str] = None,
48
49
  ) -> bool:
49
50
  """Set up W&B login credentials.
50
51
 
@@ -64,6 +65,7 @@ def login(
64
65
  force: (bool, optional) If true, will force a relogin.
65
66
  timeout: (int, optional) Number of seconds to wait for user input.
66
67
  verify: (bool) Verify the credentials with the W&B server.
68
+ referrer: (string, optional) The referrer to use in the URL login request.
67
69
 
68
70
  Returns:
69
71
  bool: if key is configured
@@ -81,6 +83,7 @@ def login(
81
83
  force=force,
82
84
  timeout=timeout,
83
85
  verify=verify,
86
+ referrer=referrer,
84
87
  )
85
88
 
86
89
 
@@ -199,7 +202,9 @@ class _WandbLogin:
199
202
  if not self._wandb_setup.settings._offline:
200
203
  self._wandb_setup._update_user_settings()
201
204
 
202
- def _prompt_api_key(self) -> Tuple[Optional[str], ApiKeyStatus]:
205
+ def _prompt_api_key(
206
+ self, referrer: Optional[str] = None
207
+ ) -> Tuple[Optional[str], ApiKeyStatus]:
203
208
  api = Api(self._settings)
204
209
  while True:
205
210
  try:
@@ -208,6 +213,7 @@ class _WandbLogin:
208
213
  api=api,
209
214
  no_offline=self._settings.force if self._settings else None,
210
215
  no_create=self._settings.force if self._settings else None,
216
+ referrer=referrer,
211
217
  )
212
218
  except ValueError as e:
213
219
  # invalid key provided, try again
@@ -222,9 +228,11 @@ class _WandbLogin:
222
228
  return None, ApiKeyStatus.OFFLINE
223
229
  return key, ApiKeyStatus.VALID
224
230
 
225
- def prompt_api_key(self) -> Tuple[Optional[str], ApiKeyStatus]:
231
+ def prompt_api_key(
232
+ self, referrer: Optional[str] = None
233
+ ) -> Tuple[Optional[str], ApiKeyStatus]:
226
234
  """Updates the global API key by prompting the user."""
227
- key, status = self._prompt_api_key()
235
+ key, status = self._prompt_api_key(referrer)
228
236
  if status == ApiKeyStatus.NOTTY:
229
237
  directive = (
230
238
  "wandb login [your_api_key]"
@@ -262,6 +270,7 @@ def _login(
262
270
  force: Optional[bool] = None,
263
271
  timeout: Optional[int] = None,
264
272
  verify: bool = False,
273
+ referrer: str = "models",
265
274
  _silent: Optional[bool] = None,
266
275
  _disable_warning: Optional[bool] = None,
267
276
  ) -> bool:
@@ -302,7 +311,7 @@ def _login(
302
311
  if key and not relogin:
303
312
  key_is_pre_configured = True
304
313
  else:
305
- key, key_status = wlogin.prompt_api_key()
314
+ key, key_status = wlogin.prompt_api_key(referrer=referrer)
306
315
 
307
316
  if verify:
308
317
  wlogin._verify_login(key)