wandb 0.19.7__py3-none-macosx_11_0_arm64.whl → 0.19.9__py3-none-macosx_11_0_arm64.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 (91) hide show
  1. wandb/__init__.py +5 -1
  2. wandb/__init__.pyi +43 -9
  3. wandb/_pydantic/__init__.py +23 -0
  4. wandb/_pydantic/base.py +113 -0
  5. wandb/_pydantic/v1_compat.py +262 -0
  6. wandb/apis/paginator.py +82 -38
  7. wandb/apis/public/api.py +10 -64
  8. wandb/apis/public/artifacts.py +73 -17
  9. wandb/apis/public/files.py +2 -2
  10. wandb/apis/public/projects.py +3 -2
  11. wandb/apis/public/reports.py +2 -2
  12. wandb/apis/public/runs.py +19 -11
  13. wandb/bin/gpu_stats +0 -0
  14. wandb/bin/wandb-core +0 -0
  15. wandb/data_types.py +1 -1
  16. wandb/filesync/dir_watcher.py +2 -1
  17. wandb/integration/metaflow/metaflow.py +19 -17
  18. wandb/integration/sacred/__init__.py +1 -1
  19. wandb/jupyter.py +18 -15
  20. wandb/proto/v3/wandb_internal_pb2.py +7 -3
  21. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  22. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  23. wandb/proto/v4/wandb_internal_pb2.py +3 -3
  24. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  25. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  26. wandb/proto/v5/wandb_internal_pb2.py +3 -3
  27. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  28. wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
  29. wandb/proto/wandb_deprecated.py +2 -0
  30. wandb/sdk/artifacts/_graphql_fragments.py +18 -20
  31. wandb/sdk/artifacts/_validators.py +1 -0
  32. wandb/sdk/artifacts/artifact.py +81 -46
  33. wandb/sdk/artifacts/artifact_saver.py +16 -2
  34. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +23 -2
  35. wandb/sdk/backend/backend.py +16 -5
  36. wandb/sdk/data_types/audio.py +1 -3
  37. wandb/sdk/data_types/base_types/media.py +11 -4
  38. wandb/sdk/data_types/image.py +44 -25
  39. wandb/sdk/data_types/molecule.py +1 -5
  40. wandb/sdk/data_types/object_3d.py +2 -1
  41. wandb/sdk/data_types/saved_model.py +7 -9
  42. wandb/sdk/data_types/video.py +1 -4
  43. wandb/sdk/interface/interface.py +65 -43
  44. wandb/sdk/interface/interface_queue.py +0 -7
  45. wandb/sdk/interface/interface_relay.py +6 -16
  46. wandb/sdk/interface/interface_shared.py +47 -40
  47. wandb/sdk/interface/interface_sock.py +1 -8
  48. wandb/sdk/interface/router.py +22 -54
  49. wandb/sdk/interface/router_queue.py +11 -10
  50. wandb/sdk/interface/router_relay.py +24 -12
  51. wandb/sdk/interface/router_sock.py +6 -11
  52. wandb/{apis/public → sdk/internal}/_generated/__init__.py +0 -6
  53. wandb/sdk/internal/_generated/base.py +226 -0
  54. wandb/{apis/public → sdk/internal}/_generated/server_features_query.py +3 -3
  55. wandb/{apis/public → sdk/internal}/_generated/typing_compat.py +1 -1
  56. wandb/sdk/internal/internal_api.py +138 -47
  57. wandb/sdk/internal/sender.py +5 -1
  58. wandb/sdk/internal/sender_config.py +8 -11
  59. wandb/sdk/internal/settings_static.py +24 -2
  60. wandb/sdk/lib/apikey.py +15 -16
  61. wandb/sdk/lib/console_capture.py +172 -0
  62. wandb/sdk/lib/redirect.py +102 -76
  63. wandb/sdk/lib/run_moment.py +4 -6
  64. wandb/sdk/lib/service_connection.py +37 -17
  65. wandb/sdk/lib/sock_client.py +2 -52
  66. wandb/sdk/lib/wb_logging.py +161 -0
  67. wandb/sdk/mailbox/__init__.py +3 -3
  68. wandb/sdk/mailbox/mailbox.py +31 -17
  69. wandb/sdk/mailbox/mailbox_handle.py +127 -0
  70. wandb/sdk/mailbox/{handles.py → response_handle.py} +34 -66
  71. wandb/sdk/mailbox/wait_with_progress.py +16 -15
  72. wandb/sdk/service/server_sock.py +4 -2
  73. wandb/sdk/service/streams.py +10 -5
  74. wandb/sdk/wandb_config.py +44 -43
  75. wandb/sdk/wandb_init.py +151 -92
  76. wandb/sdk/wandb_metadata.py +107 -91
  77. wandb/sdk/wandb_run.py +160 -54
  78. wandb/sdk/wandb_settings.py +410 -202
  79. wandb/sdk/wandb_setup.py +3 -1
  80. wandb/sdk/wandb_sync.py +1 -7
  81. {wandb-0.19.7.dist-info → wandb-0.19.9.dist-info}/METADATA +3 -3
  82. {wandb-0.19.7.dist-info → wandb-0.19.9.dist-info}/RECORD +88 -84
  83. wandb/apis/public/_generated/base.py +0 -128
  84. wandb/sdk/interface/message_future.py +0 -27
  85. wandb/sdk/interface/message_future_poll.py +0 -50
  86. /wandb/{apis/public → sdk/internal}/_generated/enums.py +0 -0
  87. /wandb/{apis/public → sdk/internal}/_generated/input_types.py +0 -0
  88. /wandb/{apis/public → sdk/internal}/_generated/operations.py +0 -0
  89. {wandb-0.19.7.dist-info → wandb-0.19.9.dist-info}/WHEEL +0 -0
  90. {wandb-0.19.7.dist-info → wandb-0.19.9.dist-info}/entry_points.txt +0 -0
  91. {wandb-0.19.7.dist-info → wandb-0.19.9.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_init.py CHANGED
@@ -10,6 +10,7 @@ For more on using `wandb.init()`, including code snippets, check out our
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ import contextlib
13
14
  import copy
14
15
  import dataclasses
15
16
  import json
@@ -20,7 +21,7 @@ import platform
20
21
  import sys
21
22
  import tempfile
22
23
  import time
23
- from typing import Any, Literal, Sequence
24
+ from typing import Any, Iterator, Literal, Sequence
24
25
 
25
26
  if sys.version_info >= (3, 11):
26
27
  from typing import Self
@@ -29,12 +30,13 @@ else:
29
30
 
30
31
  import wandb
31
32
  import wandb.env
32
- from wandb import trigger
33
+ from wandb import env, trigger
33
34
  from wandb.errors import CommError, Error, UsageError
34
35
  from wandb.errors.links import url_registry
35
36
  from wandb.errors.util import ProtobufErrorHandler
36
37
  from wandb.integration import sagemaker
37
- from wandb.sdk.lib import progress, runid
38
+ from wandb.sdk.lib import ipython as wb_ipython
39
+ from wandb.sdk.lib import progress, runid, wb_logging
38
40
  from wandb.sdk.lib.paths import StrPath
39
41
  from wandb.util import _is_artifact_representation
40
42
 
@@ -42,7 +44,7 @@ from . import wandb_login, wandb_setup
42
44
  from .backend.backend import Backend
43
45
  from .lib import SummaryDisabled, filesystem, module, paths, printer, telemetry
44
46
  from .lib.deprecate import Deprecated, deprecate
45
- from .mailbox import Mailbox, wait_with_progress
47
+ from .mailbox import wait_with_progress
46
48
  from .wandb_helper import parse_config
47
49
  from .wandb_run import Run, TeardownHook, TeardownStage
48
50
  from .wandb_settings import Settings
@@ -349,6 +351,9 @@ class _WandbInit:
349
351
 
350
352
  After this, `settings.run_id` is guaranteed to be set.
351
353
 
354
+ If a `resume_from` is provided and `run_id` is not set, initialize
355
+ `run_id` with the `resume_from` run's `run_id`.
356
+
352
357
  Args:
353
358
  settings: The run's settings derived from the environment
354
359
  and explicit values passed to `wandb.init()`.
@@ -375,7 +380,12 @@ class _WandbInit:
375
380
  # If no run ID was inferred, explicitly set, or loaded from an
376
381
  # auto-resume file, then we generate a new ID.
377
382
  if settings.run_id is None:
378
- settings.run_id = runid.generate_id()
383
+ # If resume_from is provided and run_id is not already set,
384
+ # initialize run_id with the value from resume_from.
385
+ if settings.resume_from:
386
+ settings.run_id = settings.resume_from.run
387
+ else:
388
+ settings.run_id = runid.generate_id()
379
389
 
380
390
  if resume_path:
381
391
  self._save_autoresume_run_id(
@@ -401,14 +411,17 @@ class _WandbInit:
401
411
  Returns:
402
412
  Initial values for the run's config.
403
413
  """
404
- # TODO: remove this once officially deprecated
405
414
  if config_exclude_keys:
406
- self.deprecated_features_used["config_exclude_keys"] = (
407
- "Use `config=wandb.helper.parse_config(config_object, exclude=('key',))` instead."
415
+ self.deprecated_features_used["init__config_exclude_keys"] = (
416
+ "config_exclude_keys is deprecated. Use"
417
+ " `config=wandb.helper.parse_config(config_object,"
418
+ " exclude=('key',))` instead."
408
419
  )
409
420
  if config_include_keys:
410
- self.deprecated_features_used["config_include_keys"] = (
411
- "Use `config=wandb.helper.parse_config(config_object, include=('key',))` instead."
421
+ self.deprecated_features_used["init__config_include_keys"] = (
422
+ "config_include_keys is deprecated. Use"
423
+ " `config=wandb.helper.parse_config(config_object,"
424
+ " include=('key',))` instead."
412
425
  )
413
426
  config = parse_config(
414
427
  config or dict(),
@@ -498,37 +511,6 @@ class _WandbInit:
498
511
  else:
499
512
  config_target.setdefault(k, v)
500
513
 
501
- def _create_logger(self, log_fname: str) -> logging.Logger:
502
- """Returns a logger configured to write to a file.
503
-
504
- This adds a run_id to the log, in case of multiple processes on the same
505
- machine. Currently, there is no way to disable logging after it's
506
- enabled.
507
- """
508
- handler = logging.FileHandler(log_fname)
509
- handler.setLevel(logging.INFO)
510
-
511
- formatter = logging.Formatter(
512
- "%(asctime)s %(levelname)-7s %(threadName)-10s:%(process)d "
513
- "[%(filename)s:%(funcName)s():%(lineno)s] %(message)s"
514
- )
515
-
516
- handler.setFormatter(formatter)
517
-
518
- logger = logging.getLogger("wandb")
519
- logger.propagate = False
520
- logger.addHandler(handler)
521
- # TODO: make me configurable
522
- logger.setLevel(logging.DEBUG)
523
- self._teardown_hooks.append(
524
- TeardownHook(
525
- lambda: (handler.close(), logger.removeHandler(handler)), # type: ignore
526
- TeardownStage.LATE,
527
- )
528
- )
529
-
530
- return logger
531
-
532
514
  def _safe_symlink(
533
515
  self, base: str, target: str, name: str, delete: bool = False
534
516
  ) -> None:
@@ -615,8 +597,14 @@ class _WandbInit:
615
597
 
616
598
  ipython.display_pub.publish = publish
617
599
 
618
- def setup_run_log_directory(self, settings: Settings) -> None:
619
- """Set up logging from settings."""
600
+ @contextlib.contextmanager
601
+ def setup_run_log_directory(self, settings: Settings) -> Iterator[None]:
602
+ """Set up the run's log directory.
603
+
604
+ This is a context manager that closes and unregisters the log handler
605
+ in case of an uncaught exception, so that future logged messages do not
606
+ modify this run's log file.
607
+ """
620
608
  filesystem.mkdir_exists_ok(os.path.dirname(settings.log_user))
621
609
  filesystem.mkdir_exists_ok(os.path.dirname(settings.log_internal))
622
610
  filesystem.mkdir_exists_ok(os.path.dirname(settings.sync_file))
@@ -643,9 +631,41 @@ class _WandbInit:
643
631
  delete=True,
644
632
  )
645
633
 
646
- self._wl._early_logger_flush(self._create_logger(settings.log_user))
647
- self._logger.info(f"Logging user logs to {settings.log_user}")
648
- self._logger.info(f"Logging internal logs to {settings.log_internal}")
634
+ assert settings.run_id
635
+ handler = wb_logging.add_file_handler(
636
+ settings.run_id,
637
+ pathlib.Path(settings.log_user),
638
+ )
639
+
640
+ if env.is_debug():
641
+ handler.setLevel(logging.DEBUG)
642
+
643
+ disposed = False
644
+
645
+ def dispose_handler() -> None:
646
+ nonlocal disposed
647
+
648
+ if not disposed:
649
+ disposed = True
650
+ logging.getLogger("wandb").removeHandler(handler)
651
+ handler.close()
652
+
653
+ try:
654
+ self._teardown_hooks.append(
655
+ TeardownHook(
656
+ call=dispose_handler,
657
+ stage=TeardownStage.LATE,
658
+ )
659
+ )
660
+
661
+ self._wl._early_logger_flush(logging.getLogger("wandb"))
662
+ self._logger.info(f"Logging user logs to {settings.log_user}")
663
+ self._logger.info(f"Logging internal logs to {settings.log_internal}")
664
+
665
+ yield
666
+ except Exception:
667
+ dispose_handler()
668
+ raise
649
669
 
650
670
  def make_disabled_run(self, config: _ConfigParts) -> Run:
651
671
  """Returns a Run-like object where all methods are no-ops.
@@ -682,11 +702,11 @@ class _WandbInit:
682
702
  drun._Run__metadata = wandb.sdk.wandb_metadata.Metadata()
683
703
 
684
704
  # methods
685
- drun.log = lambda data, *_, **__: drun.summary.update(data) # type: ignore
686
- drun.finish = lambda *_, **__: module.unset_globals() # type: ignore
687
- drun.join = drun.finish # type: ignore
688
- drun.define_metric = lambda *_, **__: wandb.sdk.wandb_metric.Metric("dummy") # type: ignore
689
- drun.save = lambda *_, **__: False # type: ignore
705
+ drun.log = lambda data, *_, **__: drun.summary.update(data) # type: ignore[method-assign]
706
+ drun.finish = lambda *_, **__: module.unset_globals() # type: ignore[method-assign]
707
+ drun.join = drun.finish # type: ignore[method-assign]
708
+ drun.define_metric = lambda *_, **__: wandb.sdk.wandb_metric.Metric("dummy") # type: ignore[method-assign]
709
+ drun.save = lambda *_, **__: False # type: ignore[method-assign]
690
710
  for symbol in (
691
711
  "alert",
692
712
  "finish_artifact",
@@ -733,7 +753,7 @@ class _WandbInit:
733
753
  def __call__(self, *args: Any, **kwargs: Any) -> _ChainableNoOp:
734
754
  return _ChainableNoOp()
735
755
 
736
- drun.log_artifact = _ChainableNoOpField()
756
+ drun.log_artifact = _ChainableNoOpField() # type: ignore[method-assign]
737
757
  # attributes
738
758
  drun._start_time = time.time()
739
759
  drun._starting_step = 0
@@ -769,8 +789,13 @@ class _WandbInit:
769
789
  )
770
790
 
771
791
  if wandb.run is not None and os.getpid() == wandb.run._init_pid:
772
- if settings.reinit:
773
- self._logger.info(f"finishing previous run: {wandb.run.id}")
792
+ if (
793
+ settings.reinit in (True, "finish_previous")
794
+ # calling wandb.init() in notebooks finishes previous runs
795
+ # by default for user convenience.
796
+ or (settings.reinit == "default" and wb_ipython.in_notebook())
797
+ ):
798
+ self._logger.info("finishing previous run: %s", wandb.run.id)
774
799
  wandb.run.finish()
775
800
  else:
776
801
  self._logger.info("wandb.init() called while a run is active")
@@ -793,12 +818,7 @@ class _WandbInit:
793
818
  else:
794
819
  service = None
795
820
 
796
- mailbox = Mailbox()
797
- backend = Backend(
798
- settings=settings,
799
- service=service,
800
- mailbox=mailbox,
801
- )
821
+ backend = Backend(settings=settings, service=service)
802
822
  backend.ensure_launched()
803
823
  self._logger.info("backend started and connected")
804
824
 
@@ -886,10 +906,9 @@ class _WandbInit:
886
906
  run._label_probe_main()
887
907
 
888
908
  for deprecated_feature, msg in self.deprecated_features_used.items():
889
- warning_message = f"`{deprecated_feature}` is deprecated. {msg}"
890
909
  deprecate(
891
- field_name=getattr(Deprecated, "init__" + deprecated_feature),
892
- warning_message=warning_message,
910
+ field_name=getattr(Deprecated, deprecated_feature),
911
+ warning_message=msg,
893
912
  run=run,
894
913
  )
895
914
 
@@ -1085,8 +1104,7 @@ def _attach(
1085
1104
  )
1086
1105
 
1087
1106
  # TODO: consolidate this codepath with wandb.init()
1088
- mailbox = Mailbox()
1089
- backend = Backend(settings=settings, service=service, mailbox=mailbox)
1107
+ backend = Backend(settings=settings, service=service)
1090
1108
  backend.ensure_launched()
1091
1109
  logger.info("attach backend started and connected")
1092
1110
 
@@ -1134,6 +1152,29 @@ def _monkeypatch_tensorboard() -> None:
1134
1152
  tb_module.patch()
1135
1153
 
1136
1154
 
1155
+ def try_create_root_dir(settings: Settings) -> None:
1156
+ """Try to create the root directory specified in settings.
1157
+
1158
+ If creation fails due to permissions or other errors,
1159
+ falls back to using the system temp directory.
1160
+
1161
+ Args:
1162
+ settings: The runs settings containing root_dir configuration.
1163
+ This function may update the root_dir to a temporary directory
1164
+ if the parent directory is not writable.
1165
+ """
1166
+ try:
1167
+ if not os.path.exists(settings.root_dir):
1168
+ os.makedirs(settings.root_dir, exist_ok=True)
1169
+ except OSError:
1170
+ temp_dir = tempfile.gettempdir()
1171
+ wandb.termwarn(
1172
+ f"Path {settings.root_dir} wasn't writable, using system temp directory {temp_dir}.",
1173
+ repeat=False,
1174
+ )
1175
+ settings.root_dir = temp_dir
1176
+
1177
+
1137
1178
  def init( # noqa: C901
1138
1179
  entity: str | None = None,
1139
1180
  project: str | None = None,
@@ -1151,7 +1192,15 @@ def init( # noqa: C901
1151
1192
  mode: Literal["online", "offline", "disabled"] | None = None,
1152
1193
  force: bool | None = None,
1153
1194
  anonymous: Literal["never", "allow", "must"] | None = None,
1154
- reinit: bool | None = None,
1195
+ reinit: (
1196
+ bool
1197
+ | Literal[
1198
+ None,
1199
+ "default",
1200
+ "return_previous",
1201
+ "finish_previous",
1202
+ ]
1203
+ ) = None,
1155
1204
  resume: bool | Literal["allow", "never", "must", "auto"] | None = None,
1156
1205
  resume_from: str | None = None,
1157
1206
  fork_from: str | None = None,
@@ -1299,12 +1348,8 @@ def init( # noqa: C901
1299
1348
  to view the charts and data in the UI.
1300
1349
  - `"must"`: Forces the run to be logged to an anonymous account, even
1301
1350
  if the user is logged in.
1302
- reinit: Determines if multiple `wandb.init()` calls can start new runs
1303
- within the same process. By default (`False`), if an active run
1304
- exists, calling `wandb.init()` returns the existing run instead of
1305
- creating a new one. When `reinit=True`, the active run is finished
1306
- before a new run is initialized. In notebook environments, runs are
1307
- reinitialized by default unless `reinit` is explicitly set to `False`.
1351
+ reinit: Shorthand for the "reinit" setting. Determines the behavior of
1352
+ `wandb.init()` when a run is active.
1308
1353
  resume: Controls the behavior when resuming a run with the specified `id`.
1309
1354
  Available options are:
1310
1355
  - `"allow"`: If a run with the specified `id` exists, it will resume
@@ -1433,6 +1478,12 @@ def init( # noqa: C901
1433
1478
  wi.maybe_login(init_settings)
1434
1479
  run_settings = wi.make_run_settings(init_settings)
1435
1480
 
1481
+ if isinstance(run_settings.reinit, bool):
1482
+ wi.deprecated_features_used["run__reinit_bool"] = (
1483
+ "Using a boolean value for 'reinit' is deprecated."
1484
+ " Use 'return_previous' or 'finish_previous' instead."
1485
+ )
1486
+
1436
1487
  if run_settings.run_id is not None:
1437
1488
  init_telemetry.feature.set_init_id = True
1438
1489
  if run_settings.run_name is not None:
@@ -1444,31 +1495,39 @@ def init( # noqa: C901
1444
1495
 
1445
1496
  wi.set_run_id(run_settings)
1446
1497
 
1447
- run_config = wi.make_run_config(
1448
- settings=run_settings,
1449
- config=config,
1450
- config_exclude_keys=config_exclude_keys,
1451
- config_include_keys=config_include_keys,
1452
- )
1498
+ with contextlib.ExitStack() as exit_stack:
1499
+ exit_stack.enter_context(wb_logging.log_to_run(run_settings.run_id))
1500
+
1501
+ run_config = wi.make_run_config(
1502
+ settings=run_settings,
1503
+ config=config,
1504
+ config_exclude_keys=config_exclude_keys,
1505
+ config_include_keys=config_include_keys,
1506
+ )
1507
+
1508
+ if run_settings._noop:
1509
+ return wi.make_disabled_run(run_config)
1510
+
1511
+ try_create_root_dir(run_settings)
1512
+ exit_stack.enter_context(wi.setup_run_log_directory(run_settings))
1453
1513
 
1454
- if run_settings._noop:
1455
- return wi.make_disabled_run(run_config)
1514
+ if run_settings._jupyter:
1515
+ wi.monkeypatch_ipython(run_settings)
1456
1516
 
1457
- wi.setup_run_log_directory(run_settings)
1458
- if run_settings._jupyter:
1459
- wi.monkeypatch_ipython(run_settings)
1517
+ if monitor_gym:
1518
+ _monkeypatch_openai_gym()
1460
1519
 
1461
- if monitor_gym:
1462
- _monkeypatch_openai_gym()
1520
+ if wandb.patched["tensorboard"]:
1521
+ # NOTE: The user may have called the patch function directly.
1522
+ init_telemetry.feature.tensorboard_patch = True
1523
+ if run_settings.sync_tensorboard:
1524
+ _monkeypatch_tensorboard()
1525
+ init_telemetry.feature.tensorboard_sync = True
1463
1526
 
1464
- if wandb.patched["tensorboard"]:
1465
- # NOTE: The user may have called the patch function directly.
1466
- init_telemetry.feature.tensorboard_patch = True
1467
- if run_settings.sync_tensorboard:
1468
- _monkeypatch_tensorboard()
1469
- init_telemetry.feature.tensorboard_sync = True
1527
+ if run_settings.x_server_side_derived_summary:
1528
+ init_telemetry.feature.server_side_derived_summary = True
1470
1529
 
1471
- return wi.init(run_settings, run_config)
1530
+ return wi.init(run_settings, run_config)
1472
1531
 
1473
1532
  except KeyboardInterrupt as e:
1474
1533
  if wl: