wandb 0.19.2__py3-none-any.whl → 0.19.3__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
wandb/__init__.py CHANGED
@@ -10,7 +10,7 @@ For reference documentation, see https://docs.wandb.com/ref/python.
10
10
  """
11
11
  from __future__ import annotations
12
12
 
13
- __version__ = "0.19.2"
13
+ __version__ = "0.19.3"
14
14
 
15
15
 
16
16
  from wandb.errors import Error
wandb/__init__.pyi CHANGED
@@ -103,7 +103,7 @@ if TYPE_CHECKING:
103
103
  import wandb
104
104
  from wandb.plot import CustomChart
105
105
 
106
- __version__: str = "0.19.2"
106
+ __version__: str = "0.19.3"
107
107
 
108
108
  run: Run | None
109
109
  config: wandb_config.Config
@@ -651,7 +651,12 @@ def log(
651
651
  run = wandb.init()
652
652
  examples = []
653
653
  for i in range(3):
654
- pixels = np.random.randint(low=0, high=256, size=(100, 100, 3), dtype=np.uint8)
654
+ pixels = np.random.randint(
655
+ low=0,
656
+ high=256,
657
+ size=(100, 100, 3),
658
+ dtype=np.uint8,
659
+ )
655
660
  pil_image = PILImage.fromarray(pixels, mode="RGB")
656
661
  image = wandb.Image(pil_image, caption=f"random field {i}")
657
662
  examples.append(image)
@@ -666,7 +671,12 @@ def log(
666
671
 
667
672
  run = wandb.init()
668
673
  # axes are (time, channel, height, width)
669
- frames = np.random.randint(low=0, high=256, size=(10, 3, 100, 100), dtype=np.uint8)
674
+ frames = np.random.randint(
675
+ low=0,
676
+ high=256,
677
+ size=(10, 3, 100, 100),
678
+ dtype=np.uint8,
679
+ )
670
680
  run.log({"video": wandb.Video(frames, fps=4)})
671
681
  ```
672
682
 
@@ -328,15 +328,13 @@ def wandb_log(
328
328
  if not isinstance(settings, wandb.sdk.wandb_settings.Settings):
329
329
  settings = wandb.Settings()
330
330
 
331
- settings.update(
332
- run_group=coalesce(
333
- settings.run_group, f"{current.flow_name}/{current.run_id}"
334
- ),
335
- source=wandb.sdk.wandb_settings.Source.INIT,
336
- )
337
- settings.update(
338
- run_job_type=coalesce(settings.run_job_type, current.step_name),
339
- source=wandb.sdk.wandb_settings.Source.INIT,
331
+ settings.update_from_dict(
332
+ {
333
+ "run_group": coalesce(
334
+ settings.run_group, f"{current.flow_name}/{current.run_id}"
335
+ ),
336
+ "run_job_type": coalesce(settings.run_job_type, current.step_name),
337
+ }
340
338
  )
341
339
 
342
340
  with wandb.init(settings=settings) as run:
wandb/sdk/wandb_init.py CHANGED
@@ -14,6 +14,7 @@ import copy
14
14
  import json
15
15
  import logging
16
16
  import os
17
+ import pathlib
17
18
  import platform
18
19
  import sys
19
20
  import tempfile
@@ -48,14 +49,6 @@ from .wandb_settings import Settings
48
49
  if TYPE_CHECKING:
49
50
  from wandb.proto import wandb_internal_pb2 as pb
50
51
 
51
- logger: wandb_setup.Logger | None = None # logger configured during wandb.init()
52
-
53
-
54
- def _set_logger(log_object: wandb_setup.Logger | None) -> None:
55
- """Configure module logger."""
56
- global logger
57
- logger = log_object
58
-
59
52
 
60
53
  def _huggingface_version() -> str | None:
61
54
  if "transformers" in sys.modules:
@@ -115,9 +108,10 @@ def _handle_launch_config(settings: Settings) -> dict[str, Any]:
115
108
  class _WandbInit:
116
109
  _init_telemetry_obj: telemetry.TelemetryRecord
117
110
 
118
- def __init__(self) -> None:
111
+ def __init__(self, wl: wandb_setup._WandbSetup) -> None:
112
+ self._wl = wl
113
+
119
114
  self.kwargs = None
120
- self.settings: Settings | None = None
121
115
  self.sweep_config: dict[str, Any] = {}
122
116
  self.launch_config: dict[str, Any] = {}
123
117
  self.config: dict[str, Any] = {}
@@ -125,7 +119,6 @@ class _WandbInit:
125
119
  self.backend: Backend | None = None
126
120
 
127
121
  self._teardown_hooks: list[TeardownHook] = []
128
- self._wl = wandb.setup()
129
122
  self.notebook: wandb.jupyter.Notebook | None = None # type: ignore
130
123
  self.printer = printer.new_printer()
131
124
 
@@ -133,6 +126,40 @@ class _WandbInit:
133
126
 
134
127
  self.deprecated_features_used: dict[str, str] = dict()
135
128
 
129
+ @property
130
+ def _logger(self) -> wandb_setup.Logger:
131
+ return self._wl._get_logger()
132
+
133
+ def maybe_login(self, init_settings: Settings) -> None:
134
+ """Log in if we are not creating an offline or disabled run.
135
+
136
+ This may change the W&B singleton settings.
137
+
138
+ Args:
139
+ init_settings: Settings passed to `wandb.init()` or set via
140
+ keyword arguments.
141
+ """
142
+ # Allow settings passed to init() to override inferred values.
143
+ #
144
+ # Calling login() may change settings on the singleton,
145
+ # so these may not be the final run settings.
146
+ run_settings = self._wl.settings.model_copy()
147
+ run_settings.update_from_settings(init_settings)
148
+
149
+ # NOTE: _noop or _offline can become true after _login().
150
+ # _noop happens if _login hits a timeout.
151
+ # _offline can be selected by the user at the login prompt.
152
+ if run_settings._noop or run_settings._offline:
153
+ return
154
+
155
+ wandb_login._login(
156
+ anonymous=run_settings.anonymous,
157
+ force=run_settings.force,
158
+ _disable_warning=True,
159
+ _silent=run_settings.quiet or run_settings.silent,
160
+ _entity=run_settings.entity,
161
+ )
162
+
136
163
  def warn_env_vars_change_after_setup(self) -> None:
137
164
  """Warn if environment variables change after wandb singleton is initialized.
138
165
 
@@ -202,24 +229,15 @@ class _WandbInit:
202
229
  warn("run_id", init_settings.run_id)
203
230
  init_settings.run_id = None
204
231
 
205
- def setup( # noqa: C901
206
- self,
207
- init_settings: Settings,
208
- config: dict | str | None = None,
209
- config_exclude_keys: list[str] | None = None,
210
- config_include_keys: list[str] | None = None,
211
- allow_val_change: bool | None = None,
212
- monitor_gym: bool | None = None,
213
- ) -> None:
214
- """Complete setup for `wandb.init()`.
232
+ def compute_run_settings(self, init_settings: Settings) -> Settings:
233
+ """Returns the run's settings.
215
234
 
216
- This includes parsing all arguments, applying them with settings and enabling logging.
235
+ Args:
236
+ init_settings: Settings passed to `wandb.init()` or set via
237
+ keyword arguments.
217
238
  """
218
239
  self.warn_env_vars_change_after_setup()
219
240
 
220
- _set_logger(self._wl._get_logger())
221
- assert logger
222
-
223
241
  self.clear_run_path_if_sweep_or_launch(init_settings)
224
242
 
225
243
  # Inherit global settings.
@@ -231,10 +249,121 @@ class _WandbInit:
231
249
  # Infer the run ID from SageMaker.
232
250
  if not settings.sagemaker_disable and sagemaker.is_using_sagemaker():
233
251
  if sagemaker.set_run_id(settings):
234
- logger.info("set run ID and group based on SageMaker")
252
+ self._logger.info("set run ID and group based on SageMaker")
235
253
  with telemetry.context(obj=self._init_telemetry_obj) as tel:
236
254
  tel.feature.sagemaker = True
237
255
 
256
+ # get status of code saving before applying user settings
257
+ save_code_pre_user_settings = settings.save_code
258
+ if not settings._offline and not settings._noop:
259
+ user_settings = self._wl._load_user_settings()
260
+ if user_settings is not None:
261
+ settings.update_from_dict(user_settings)
262
+
263
+ # ensure that user settings don't set saving to true
264
+ # if user explicitly set these to false in UI
265
+ if save_code_pre_user_settings is False:
266
+ settings.save_code = False
267
+
268
+ # TODO: remove this once we refactor the client. This is a temporary
269
+ # fix to make sure that we use the same project name for wandb-core.
270
+ # The reason this is not going through the settings object is to
271
+ # avoid failure cases in other parts of the code that will be
272
+ # removed with the switch to wandb-core.
273
+ if settings.project is None:
274
+ settings.project = wandb.util.auto_project_name(settings.program)
275
+
276
+ settings.x_start_time = time.time()
277
+
278
+ return settings
279
+
280
+ def _load_autoresume_run_id(self, resume_file: pathlib.Path) -> str | None:
281
+ """Returns the run_id stored in the auto-resume file, if any.
282
+
283
+ Returns None if the file does not exist or is not in a valid format.
284
+
285
+ Args:
286
+ resume_file: The file path to use for resume='auto' mode.
287
+ """
288
+ if not resume_file.exists():
289
+ return None
290
+
291
+ with resume_file.open() as f:
292
+ try:
293
+ return json.load(f)["run_id"]
294
+
295
+ except json.JSONDecodeError as e:
296
+ self._logger.exception(
297
+ f"could not decode {resume_file}, ignoring",
298
+ exc_info=e,
299
+ )
300
+ return None
301
+
302
+ except KeyError:
303
+ self._logger.error(
304
+ f"resume file at {resume_file} did not store a run_id"
305
+ )
306
+ return None
307
+
308
+ def _save_autoresume_run_id(
309
+ self,
310
+ *,
311
+ resume_file: pathlib.Path,
312
+ run_id: str,
313
+ ) -> None:
314
+ """Write the run ID to the auto-resume file."""
315
+ resume_file.parent.mkdir(exist_ok=True)
316
+ with resume_file.open("w") as f:
317
+ json.dump({"run_id": run_id}, f)
318
+
319
+ def set_run_id(self, settings: Settings) -> None:
320
+ """Set the run ID and possibly save it to the auto-resume file.
321
+
322
+ After this, `settings.run_id` is guaranteed to be set.
323
+
324
+ Args:
325
+ settings: The run's settings derived from the environment
326
+ and explicit values passed to `wandb.init()`.
327
+ """
328
+ if settings.resume == "auto" and settings.resume_fname:
329
+ resume_path = pathlib.Path(settings.resume_fname)
330
+ else:
331
+ resume_path = None
332
+
333
+ if resume_path:
334
+ previous_id = self._load_autoresume_run_id(resume_path)
335
+
336
+ if not previous_id:
337
+ pass
338
+ elif settings.run_id is None:
339
+ self._logger.info(f"loaded run ID from {resume_path}")
340
+ settings.run_id = previous_id
341
+ elif settings.run_id != previous_id:
342
+ wandb.termwarn(
343
+ f"Ignoring ID {previous_id} loaded due to resume='auto'"
344
+ f" because the run ID is set to {settings.run_id}.",
345
+ )
346
+
347
+ # If no run ID was inferred, explicitly set, or loaded from an
348
+ # auto-resume file, then we generate a new ID.
349
+ if settings.run_id is None:
350
+ settings.run_id = runid.generate_id()
351
+
352
+ if resume_path:
353
+ self._save_autoresume_run_id(
354
+ resume_file=resume_path,
355
+ run_id=settings.run_id,
356
+ )
357
+
358
+ def setup(
359
+ self,
360
+ settings: Settings,
361
+ config: dict | str | None = None,
362
+ config_exclude_keys: list[str] | None = None,
363
+ config_include_keys: list[str] | None = None,
364
+ monitor_gym: bool | None = None,
365
+ ) -> None:
366
+ """Compute the run's config and some telemetry."""
238
367
  with telemetry.context(obj=self._init_telemetry_obj) as tel:
239
368
  if config is not None:
240
369
  tel.feature.set_init_config = True
@@ -295,55 +424,6 @@ class _WandbInit:
295
424
  with telemetry.context(obj=self._init_telemetry_obj) as tel:
296
425
  tel.feature.tensorboard_sync = True
297
426
 
298
- if not settings._offline and not settings._noop:
299
- wandb_login._login(
300
- anonymous=settings.anonymous,
301
- force=settings.force,
302
- _disable_warning=True,
303
- _silent=settings.quiet or settings.silent,
304
- _entity=settings.entity,
305
- )
306
-
307
- # apply updated global state after login was handled
308
- login_settings = {
309
- k: v
310
- for k, v in {
311
- "anonymous": self._wl.settings.anonymous,
312
- "api_key": self._wl.settings.api_key,
313
- "base_url": self._wl.settings.base_url,
314
- "force": self._wl.settings.force,
315
- "login_timeout": self._wl.settings.login_timeout,
316
- }.items()
317
- if v is not None
318
- }
319
- if login_settings:
320
- settings.update_from_dict(login_settings)
321
-
322
- # handle custom resume logic
323
- settings.handle_resume_logic()
324
-
325
- # get status of code saving before applying user settings
326
- save_code_pre_user_settings = settings.save_code
327
- if not settings._offline and not settings._noop:
328
- user_settings = self._wl._load_user_settings()
329
- if user_settings is not None:
330
- settings.update_from_dict(user_settings)
331
-
332
- # ensure that user settings don't set saving to true
333
- # if user explicitly set these to false in UI
334
- if save_code_pre_user_settings is False:
335
- settings.save_code = False
336
-
337
- # TODO: remove this once we refactor the client. This is a temporary
338
- # fix to make sure that we use the same project name for wandb-core.
339
- # The reason this is not going through the settings object is to
340
- # avoid failure cases in other parts of the code that will be
341
- # removed with the switch to wandb-core.
342
- if settings.project is None:
343
- settings.project = wandb.util.auto_project_name(settings.program)
344
-
345
- settings.x_start_time = time.time()
346
-
347
427
  if not settings._noop:
348
428
  self._log_setup(settings)
349
429
 
@@ -353,13 +433,10 @@ class _WandbInit:
353
433
  if launch_config:
354
434
  self._split_artifacts_from_config(launch_config, self.launch_config)
355
435
 
356
- self.settings = settings
357
-
358
436
  def teardown(self) -> None:
359
437
  # TODO: currently this is only called on failed wandb.init attempts
360
438
  # normally this happens on the run object
361
- assert logger
362
- logger.info("tearing down wandb.init")
439
+ self._logger.info("tearing down wandb.init")
363
440
  for hook in self._teardown_hooks:
364
441
  hook.call()
365
442
 
@@ -372,11 +449,12 @@ class _WandbInit:
372
449
  else:
373
450
  config_target.setdefault(k, v)
374
451
 
375
- def _enable_logging(self, log_fname: str) -> None:
376
- """Enable logging to the global debug log.
452
+ def _create_logger(self, log_fname: str) -> logging.Logger:
453
+ """Returns a logger configured to write to a file.
377
454
 
378
- This adds a run_id to the log, in case of multiple processes on the same machine.
379
- Currently, there is no way to disable logging after it's enabled.
455
+ This adds a run_id to the log, in case of multiple processes on the same
456
+ machine. Currently, there is no way to disable logging after it's
457
+ enabled.
380
458
  """
381
459
  handler = logging.FileHandler(log_fname)
382
460
  handler.setLevel(logging.INFO)
@@ -387,7 +465,8 @@ class _WandbInit:
387
465
  )
388
466
 
389
467
  handler.setFormatter(formatter)
390
- assert isinstance(logger, logging.Logger)
468
+
469
+ logger = logging.getLogger("wandb")
391
470
  logger.propagate = False
392
471
  logger.addHandler(handler)
393
472
  # TODO: make me configurable
@@ -399,6 +478,8 @@ class _WandbInit:
399
478
  )
400
479
  )
401
480
 
481
+ return logger
482
+
402
483
  def _safe_symlink(
403
484
  self, base: str, target: str, name: str, delete: bool = False
404
485
  ) -> None:
@@ -429,14 +510,14 @@ class _WandbInit:
429
510
  if self.notebook.save_ipynb(): # type: ignore
430
511
  assert self.run is not None
431
512
  res = self.run.log_code(root=None)
432
- logger.info("saved code: %s", res) # type: ignore
513
+ self._logger.info("saved code: %s", res) # type: ignore
433
514
  if self.backend.interface is not None:
434
- logger.info("pausing backend") # type: ignore
515
+ self._logger.info("pausing backend") # type: ignore
435
516
  self.backend.interface.publish_pause()
436
517
 
437
518
  def _resume_backend(self, *args: Any, **kwargs: Any) -> None: # noqa
438
519
  if self.backend is not None and self.backend.interface is not None:
439
- logger.info("resuming backend") # type: ignore
520
+ self._logger.info("resuming backend") # type: ignore
440
521
  self.backend.interface.publish_resume()
441
522
 
442
523
  def _jupyter_teardown(self) -> None:
@@ -447,8 +528,8 @@ class _WandbInit:
447
528
  if self.notebook.save_ipynb():
448
529
  assert self.run is not None
449
530
  res = self.run.log_code(root=None)
450
- logger.info("saved code and history: %s", res) # type: ignore
451
- logger.info("cleaning up jupyter logic") # type: ignore
531
+ self._logger.info("saved code and history: %s", res) # type: ignore
532
+ self._logger.info("cleaning up jupyter logic") # type: ignore
452
533
  # because of how we bind our methods we manually find them to unregister
453
534
  for hook in ipython.events.callbacks["pre_run_cell"]:
454
535
  if "_resume_backend" in hook.__name__:
@@ -466,7 +547,7 @@ class _WandbInit:
466
547
 
467
548
  # Monkey patch ipython publish to capture displayed outputs
468
549
  if not hasattr(ipython.display_pub, "_orig_publish"):
469
- logger.info("configuring jupyter hooks %s", self) # type: ignore
550
+ self._logger.info("configuring jupyter hooks %s", self) # type: ignore
470
551
  ipython.display_pub._orig_publish = ipython.display_pub.publish
471
552
  # Registering resume and pause hooks
472
553
 
@@ -513,15 +594,9 @@ class _WandbInit:
513
594
  delete=True,
514
595
  )
515
596
 
516
- _set_logger(logging.getLogger("wandb"))
517
- self._enable_logging(settings.log_user)
518
-
519
- assert self._wl
520
- assert logger
521
-
522
- self._wl._early_logger_flush(logger)
523
- logger.info(f"Logging user logs to {settings.log_user}")
524
- logger.info(f"Logging internal logs to {settings.log_internal}")
597
+ self._wl._early_logger_flush(self._create_logger(settings.log_user))
598
+ self._logger.info(f"Logging user logs to {settings.log_user}")
599
+ self._logger.info(f"Logging internal logs to {settings.log_internal}")
525
600
 
526
601
  def _make_run_disabled(self) -> Run:
527
602
  """Returns a Run-like object where all methods are no-ops.
@@ -635,24 +710,20 @@ class _WandbInit:
635
710
  percent_done = handle.percent_done
636
711
  self.printer.progress_update(line, percent_done=percent_done)
637
712
 
638
- def init(self) -> Run: # noqa: C901
639
- if logger is None:
640
- raise RuntimeError("Logger not initialized")
641
- logger.info("calling init triggers")
713
+ def init(self, settings: Settings) -> Run: # noqa: C901
714
+ self._logger.info("calling init triggers")
642
715
  trigger.call("on_init")
643
716
 
644
- assert self.settings is not None
645
717
  assert self._wl is not None
646
718
 
647
- logger.info(
719
+ self._logger.info(
648
720
  f"wandb.init called with sweep_config: {self.sweep_config}\nconfig: {self.config}"
649
721
  )
650
722
 
651
- if self.settings._noop:
723
+ if settings._noop:
652
724
  return self._make_run_disabled()
653
725
  if (
654
- self.settings.reinit
655
- or (self.settings._jupyter and self.settings.reinit is not False)
726
+ settings.reinit or (settings._jupyter and settings.reinit is not False)
656
727
  ) and len(self._wl._global_run_stack) > 0:
657
728
  if len(self._wl._global_run_stack) > 1:
658
729
  wandb.termwarn(
@@ -663,39 +734,39 @@ class _WandbInit:
663
734
  )
664
735
 
665
736
  latest_run = self._wl._global_run_stack[-1]
666
- logger.info(f"found existing run on stack: {latest_run.id}")
737
+ self._logger.info(f"found existing run on stack: {latest_run.id}")
667
738
  latest_run.finish()
668
739
  elif wandb.run is not None and os.getpid() == wandb.run._init_pid:
669
- logger.info("wandb.init() called when a run is still active")
740
+ self._logger.info("wandb.init() called when a run is still active")
670
741
  with telemetry.context() as tel:
671
742
  tel.feature.init_return_run = True
672
743
  return wandb.run
673
744
 
674
- logger.info("starting backend")
745
+ self._logger.info("starting backend")
675
746
 
676
- if not self.settings.x_disable_service:
747
+ if not settings.x_disable_service:
677
748
  service = self._wl.ensure_service()
678
- logger.info("sending inform_init request")
749
+ self._logger.info("sending inform_init request")
679
750
  service.inform_init(
680
- settings=self.settings.to_proto(),
681
- run_id=self.settings.run_id, # type: ignore
751
+ settings=settings.to_proto(),
752
+ run_id=settings.run_id, # type: ignore
682
753
  )
683
754
  else:
684
755
  service = None
685
756
 
686
757
  mailbox = Mailbox()
687
758
  backend = Backend(
688
- settings=self.settings,
759
+ settings=settings,
689
760
  service=service,
690
761
  mailbox=mailbox,
691
762
  )
692
763
  backend.ensure_launched()
693
- logger.info("backend started and connected")
764
+ self._logger.info("backend started and connected")
694
765
 
695
766
  # resuming needs access to the server, check server_status()?
696
767
  run = Run(
697
768
  config=self.config,
698
- settings=self.settings,
769
+ settings=settings,
699
770
  sweep_config=self.sweep_config,
700
771
  launch_config=self.launch_config,
701
772
  )
@@ -708,18 +779,18 @@ class _WandbInit:
708
779
  hf_version = _huggingface_version()
709
780
  if hf_version:
710
781
  tel.huggingface_version = hf_version
711
- if self.settings._jupyter:
782
+ if settings._jupyter:
712
783
  tel.env.jupyter = True
713
- if self.settings._ipython:
784
+ if settings._ipython:
714
785
  tel.env.ipython = True
715
- if self.settings._colab:
786
+ if settings._colab:
716
787
  tel.env.colab = True
717
- if self.settings._kaggle:
788
+ if settings._kaggle:
718
789
  tel.env.kaggle = True
719
- if self.settings._windows:
790
+ if settings._windows:
720
791
  tel.env.windows = True
721
792
 
722
- if self.settings.launch:
793
+ if settings.launch:
723
794
  tel.feature.launch = True
724
795
 
725
796
  for module_name in telemetry.list_telemetry_imports(only_imported=True):
@@ -727,8 +798,8 @@ class _WandbInit:
727
798
 
728
799
  # probe the active start method
729
800
  active_start_method: str | None = None
730
- if self.settings.start_method == "thread":
731
- active_start_method = self.settings.start_method
801
+ if settings.start_method == "thread":
802
+ active_start_method = settings.start_method
732
803
  else:
733
804
  active_start_method = getattr(
734
805
  backend._multiprocessing, "get_start_method", lambda: None
@@ -746,7 +817,7 @@ class _WandbInit:
746
817
  if os.environ.get("PEX"):
747
818
  tel.env.pex = True
748
819
 
749
- if self.settings._aws_lambda:
820
+ if settings._aws_lambda:
750
821
  tel.env.aws_lambda = True
751
822
 
752
823
  if os.environ.get(wandb.env._DISABLE_SERVICE):
@@ -754,13 +825,13 @@ class _WandbInit:
754
825
 
755
826
  if service:
756
827
  tel.feature.service = True
757
- if self.settings.x_flow_control_disabled:
828
+ if settings.x_flow_control_disabled:
758
829
  tel.feature.flow_control_disabled = True
759
- if self.settings.x_flow_control_custom:
830
+ if settings.x_flow_control_custom:
760
831
  tel.feature.flow_control_custom = True
761
- if not self.settings.x_require_legacy_service:
832
+ if not settings.x_require_legacy_service:
762
833
  tel.feature.core = True
763
- if self.settings._shared:
834
+ if settings._shared:
764
835
  wandb.termwarn(
765
836
  "The `_shared` feature is experimental and may change. "
766
837
  "Please contact support@wandb.com for guidance and to report any issues."
@@ -769,7 +840,7 @@ class _WandbInit:
769
840
 
770
841
  tel.env.maybe_mp = _maybe_mp_process(backend)
771
842
 
772
- if not self.settings.label_disable:
843
+ if not settings.label_disable:
773
844
  if self.notebook:
774
845
  run._label_probe_notebook(self.notebook)
775
846
  else:
@@ -783,7 +854,7 @@ class _WandbInit:
783
854
  run=run,
784
855
  )
785
856
 
786
- logger.info("updated telemetry")
857
+ self._logger.info("updated telemetry")
787
858
 
788
859
  run._set_library(self._wl)
789
860
  run._set_backend(backend)
@@ -797,25 +868,27 @@ class _WandbInit:
797
868
  # Using GitRepo() blocks & can be slow, depending on user's current git setup.
798
869
  # We don't want to block run initialization/start request, so populate run's git
799
870
  # info beforehand.
800
- if not (self.settings.disable_git or self.settings.x_disable_machine_info):
871
+ if not (settings.disable_git or settings.x_disable_machine_info):
801
872
  run._populate_git_info()
802
873
 
803
874
  run_result: pb.RunUpdateResult | None = None
804
875
 
805
- if self.settings._offline:
876
+ if settings._offline:
806
877
  with telemetry.context(run=run) as tel:
807
878
  tel.feature.offline = True
808
879
 
809
- if self.settings.resume:
880
+ if settings.resume:
810
881
  wandb.termwarn(
811
882
  "`resume` will be ignored since W&B syncing is set to `offline`. "
812
883
  f"Starting a new run with run id {run.id}."
813
884
  )
814
885
  error: wandb.Error | None = None
815
886
 
816
- timeout = self.settings.init_timeout
887
+ timeout = settings.init_timeout
817
888
 
818
- logger.info(f"communicating run to backend with {timeout} second timeout")
889
+ self._logger.info(
890
+ f"communicating run to backend with {timeout} second timeout",
891
+ )
819
892
 
820
893
  run_init_handle = backend.interface.deliver_run(run)
821
894
  result = run_init_handle.wait(
@@ -842,7 +915,7 @@ class _WandbInit:
842
915
  error = ProtobufErrorHandler.to_exception(run_result.error)
843
916
 
844
917
  if error is not None:
845
- logger.error(f"encountered error: {error}")
918
+ self._logger.error(f"encountered error: {error}")
846
919
  if not service:
847
920
  # Shutdown the backend and get rid of the logger
848
921
  # we don't need to do console cleanup at this point
@@ -860,19 +933,19 @@ class _WandbInit:
860
933
  )
861
934
 
862
935
  if run_result.run.resumed:
863
- logger.info("run resumed")
936
+ self._logger.info("run resumed")
864
937
  with telemetry.context(run=run) as tel:
865
938
  tel.feature.resumed = run_result.run.resumed
866
939
  run._set_run_obj(run_result.run)
867
940
 
868
- logger.info("starting run threads in backend")
941
+ self._logger.info("starting run threads in backend")
869
942
  # initiate run (stats and metadata probing)
870
943
 
871
944
  if service:
872
- assert self.settings.run_id
945
+ assert settings.run_id
873
946
  service.inform_start(
874
- settings=self.settings.to_proto(),
875
- run_id=self.settings.run_id,
947
+ settings=settings.to_proto(),
948
+ run_id=settings.run_id,
876
949
  )
877
950
 
878
951
  assert backend.interface
@@ -889,11 +962,11 @@ class _WandbInit:
889
962
 
890
963
  run._handle_launch_artifact_overrides()
891
964
  if (
892
- self.settings.launch
893
- and self.settings.launch_config_path
894
- and os.path.exists(self.settings.launch_config_path)
965
+ settings.launch
966
+ and settings.launch_config_path
967
+ and os.path.exists(settings.launch_config_path)
895
968
  ):
896
- run.save(self.settings.launch_config_path)
969
+ run.save(settings.launch_config_path)
897
970
  # put artifacts in run config here
898
971
  # since doing so earlier will cause an error
899
972
  # as the run is not upserted
@@ -907,7 +980,7 @@ class _WandbInit:
907
980
 
908
981
  self.backend = backend
909
982
  run._on_start()
910
- logger.info("run started, returning control to user process")
983
+ self._logger.info("run started, returning control to user process")
911
984
  return run
912
985
 
913
986
 
@@ -938,10 +1011,7 @@ def _attach(
938
1011
  wandb._assert_is_user_process() # type: ignore
939
1012
 
940
1013
  _wl = wandb.setup()
941
-
942
- _set_logger(_wl._get_logger())
943
- if logger is None:
944
- raise UsageError("logger is not initialized")
1014
+ logger = _wl._get_logger()
945
1015
 
946
1016
  service = _wl.ensure_service()
947
1017
 
@@ -1276,27 +1346,36 @@ def init( # noqa: C901
1276
1346
  if resume_from is not None:
1277
1347
  init_settings.resume_from = resume_from # type: ignore
1278
1348
 
1349
+ wl: wandb_setup._WandbSetup | None = None
1350
+
1279
1351
  try:
1280
- wi = _WandbInit()
1352
+ wl = wandb.setup()
1353
+
1354
+ wi = _WandbInit(wl)
1355
+
1356
+ wi.maybe_login(init_settings)
1357
+ run_settings = wi.compute_run_settings(init_settings)
1358
+ wi.set_run_id(run_settings)
1359
+
1281
1360
  wi.setup(
1282
- init_settings=init_settings,
1361
+ settings=run_settings,
1283
1362
  config=config,
1284
1363
  config_exclude_keys=config_exclude_keys,
1285
1364
  config_include_keys=config_include_keys,
1286
- allow_val_change=allow_val_change,
1287
1365
  monitor_gym=monitor_gym,
1288
1366
  )
1289
- return wi.init()
1367
+
1368
+ return wi.init(run_settings)
1290
1369
 
1291
1370
  except KeyboardInterrupt as e:
1292
- if logger is not None:
1293
- logger.warning("interrupted", exc_info=e)
1371
+ if wl:
1372
+ wl._get_logger().warning("interrupted", exc_info=e)
1294
1373
 
1295
1374
  raise
1296
1375
 
1297
1376
  except Exception as e:
1298
- if logger is not None:
1299
- logger.exception("error in wandb.init()", exc_info=e)
1377
+ if wl:
1378
+ wl._get_logger().exception("error in wandb.init()", exc_info=e)
1300
1379
 
1301
1380
  # Need to build delay into this sentry capture because our exit hooks
1302
1381
  # mess with sentry's ability to send out errors before the program ends.
wandb/sdk/wandb_run.py CHANGED
@@ -29,7 +29,6 @@ import wandb.util
29
29
  from wandb import trigger
30
30
  from wandb._globals import _datatypes_set_callback
31
31
  from wandb.apis import internal, public
32
- from wandb.apis.internal import Api
33
32
  from wandb.apis.public import Api as PublicApi
34
33
  from wandb.errors import CommError, UnsupportedError, UsageError
35
34
  from wandb.errors.links import url_registry
@@ -1814,7 +1813,10 @@ class Run:
1814
1813
  examples = []
1815
1814
  for i in range(3):
1816
1815
  pixels = np.random.randint(
1817
- low=0, high=256, size=(100, 100, 3), dtype=np.uint8
1816
+ low=0,
1817
+ high=256,
1818
+ size=(100, 100, 3),
1819
+ dtype=np.uint8,
1818
1820
  )
1819
1821
  pil_image = PILImage.fromarray(pixels, mode="RGB")
1820
1822
  image = wandb.Image(pil_image, caption=f"random field {i}")
@@ -1831,7 +1833,10 @@ class Run:
1831
1833
  run = wandb.init()
1832
1834
  # axes are (time, channel, height, width)
1833
1835
  frames = np.random.randint(
1834
- low=0, high=256, size=(10, 3, 100, 100), dtype=np.uint8
1836
+ low=0,
1837
+ high=256,
1838
+ size=(10, 3, 100, 100),
1839
+ dtype=np.uint8,
1835
1840
  )
1836
1841
  run.log({"video": wandb.Video(frames, fps=4)})
1837
1842
  ```
@@ -3266,8 +3271,7 @@ class Run:
3266
3271
  is_user_created: bool = False,
3267
3272
  use_after_commit: bool = False,
3268
3273
  ) -> Artifact:
3269
- api = internal.Api()
3270
- if api.settings().get("anonymous") in ["allow", "must"]:
3274
+ if self._settings.anonymous in ["allow", "must"]:
3271
3275
  wandb.termwarn(
3272
3276
  "Artifacts logged anonymously cannot be claimed and expire after 7 days."
3273
3277
  )
@@ -3864,8 +3868,7 @@ class Run:
3864
3868
  f'{printer.emoji("rocket")} View run at {printer.link(run_url)}',
3865
3869
  )
3866
3870
 
3867
- # TODO(settings) use `wandb_settings` (if self.settings.anonymous in ["allow", "must"]:)
3868
- if run_name and Api().api.settings().get("anonymous") in ["allow", "must"]:
3871
+ if run_name and settings.anonymous in ["allow", "must"]:
3869
3872
  printer.display(
3870
3873
  (
3871
3874
  "Do NOT share these links with anyone."
@@ -34,14 +34,12 @@ from pydantic_core import SchemaValidator, core_schema
34
34
 
35
35
  import wandb
36
36
  from wandb import env, termwarn, util
37
- from wandb.apis.internal import Api
38
37
  from wandb.errors import UsageError
39
38
  from wandb.proto import wandb_settings_pb2
40
39
 
41
- from .lib import apikey, credentials, filesystem, ipython
40
+ from .lib import apikey, credentials, ipython
42
41
  from .lib.gitlib import GitRepo
43
42
  from .lib.run_moment import RunMoment
44
- from .lib.runid import generate_id
45
43
 
46
44
 
47
45
  def _path_convert(*args: str) -> str:
@@ -1154,29 +1152,6 @@ class Settings(BaseModel, validate_assignment=True):
1154
1152
 
1155
1153
  return settings_proto
1156
1154
 
1157
- def handle_resume_logic(self):
1158
- """Handle logic for resuming runs."""
1159
- # handle auto resume logic
1160
- if self.resume == "auto":
1161
- if os.path.exists(self.resume_fname):
1162
- with open(self.resume_fname) as f:
1163
- resume_run_id = json.load(f)["run_id"]
1164
- if self.run_id is None:
1165
- self.run_id = resume_run_id
1166
- elif self.run_id != resume_run_id:
1167
- wandb.termwarn(
1168
- "Tried to auto resume run with "
1169
- f"id {resume_run_id} but id {self.run_id} is set.",
1170
- )
1171
- if self.run_id is None:
1172
- self.run_id = generate_id()
1173
-
1174
- # persist run_id in case of failure
1175
- if self.resume == "auto" and self.resume_fname is not None:
1176
- filesystem.mkdir_exists_ok(self.wandb_dir)
1177
- with open(self.resume_fname, "w") as f:
1178
- f.write(json.dumps({"run_id": self.run_id}))
1179
-
1180
1155
  @staticmethod
1181
1156
  def validate_url(url: str) -> None:
1182
1157
  """Validate a URL string."""
@@ -1262,7 +1237,7 @@ class Settings(BaseModel, validate_assignment=True):
1262
1237
  def _get_url_query_string(self) -> str:
1263
1238
  """Construct the query string for project, run, and sweep URLs."""
1264
1239
  # TODO: remove dependency on Api()
1265
- if Api().settings().get("anonymous") not in ["allow", "must"]:
1240
+ if self.anonymous not in ["allow", "must"]:
1266
1241
  return ""
1267
1242
 
1268
1243
  api_key = apikey.api_key(settings=self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wandb
3
- Version: 0.19.2
3
+ Version: 0.19.3
4
4
  Summary: A CLI and library for interacting with the Weights & Biases API.
5
5
  Project-URL: Source, https://github.com/wandb/wandb
6
6
  Project-URL: Bug Reports, https://github.com/wandb/wandb/issues
@@ -1,6 +1,6 @@
1
1
  package_readme.md,sha256=U9047nyMDICgctm1HLm4HfXwFnFKsEn2m77hsYPUZ1I,4298
2
- wandb/__init__.py,sha256=iDFm6Xdx3kjLvr0RB6XXjuZU-HQk3tXRsKJ8_qeSipM,6988
3
- wandb/__init__.pyi,sha256=vZwj1Cmk9HSNo0zj5h084WSFg63X-EabSmgGhm48HIs,46886
2
+ wandb/__init__.py,sha256=5f1_Sih9Sxjo5YN6UOofmcFjW0XnL5FxgWk-saYyMhw,6988
3
+ wandb/__init__.pyi,sha256=__KjZYDXGiHshy_OUrsV7chJrIiOon8DuzRjM6ubHnc,47024
4
4
  wandb/__main__.py,sha256=gripuDgB7J8wMMeJt4CIBRjn1BMSFr5zvsrt585Pnj4,64
5
5
  wandb/_globals.py,sha256=CccwOAls5bxJArYHg12b08ZeKR8Qu9u57GtYWjBH0o0,702
6
6
  wandb/data_types.py,sha256=tjxcQ8padGuGxST192PyEDX_nhU__izHcAK-kaSyevI,2276
@@ -104,7 +104,7 @@ wandb/integration/lightning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
104
104
  wandb/integration/lightning/fabric/__init__.py,sha256=RFhr2VkC0D8b6bAXUMZzcVzqDQaoOozfP_HOogAWi9o,94
105
105
  wandb/integration/lightning/fabric/logger.py,sha256=ev8xFbCohaRp4MvrBn1x_5ypuvLe2FJdUWY7Jjw0ylk,27251
106
106
  wandb/integration/metaflow/__init__.py,sha256=nYn3ubiX9Ay6PFxr7r7F8Ia_2dLImb63rpYDmuDlkkQ,109
107
- wandb/integration/metaflow/metaflow.py,sha256=faj0W4clDGBX9cuoU1fqVeCM7qePwGp5N3A6mdfLYsc,11901
107
+ wandb/integration/metaflow/metaflow.py,sha256=qlzrdkTmT_KTg6sUE3PV8PStuZyFGYEdQzNNNil05jI,11804
108
108
  wandb/integration/openai/__init__.py,sha256=T6x9lIFfw2NzOSi46wi3otY_-DSwyMgnIjMIOIod7iU,66
109
109
  wandb/integration/openai/fine_tuning.py,sha256=w9_F3bLTG72KdNkD2rAPRdrq6rc58EtltFxwedyI690,18555
110
110
  wandb/integration/openai/openai.py,sha256=zGD1kj6yjDP1IfAAYRcltuXD5Bf569CSnMHMf4rDm54,496
@@ -203,14 +203,14 @@ wandb/sdk/__init__.py,sha256=N-GTAC0AzbZF2J8RzB33DTmYk9u-jubllCwvhWrPgsE,813
203
203
  wandb/sdk/wandb_alerts.py,sha256=SwBPBiXRxknMTMGbsVoMMWqWK65UWMcKAdTWZtdwAeo,193
204
204
  wandb/sdk/wandb_config.py,sha256=b7kxQVnIh5HCBZXb2pOGZ4c02xCVlW4IQiAu3N-8Opg,10856
205
205
  wandb/sdk/wandb_helper.py,sha256=IbJ7opO8UkfwCDekSjRYIrGBblUxnTPBfp1EdesfF4U,1824
206
- wandb/sdk/wandb_init.py,sha256=yQ8BthOAFOQaJKLFZhPc2KQxIgbA_60Hcfs60CpG7zA,53887
206
+ wandb/sdk/wandb_init.py,sha256=z19KqQWjmOcnswowWoq4VAHGalTmjLKwz1R-Rm1i-Bo,56484
207
207
  wandb/sdk/wandb_login.py,sha256=DP7nDUGx2UmqGRBrvTmcpvzRBVeRD0qEENtmu4sjDAQ,10966
208
208
  wandb/sdk/wandb_metadata.py,sha256=nT6TUF4Yh-ka3VQGyKd3y9MTEHJUgRVT4ICyfJkbHFo,20111
209
209
  wandb/sdk/wandb_metric.py,sha256=a3GiQXr6H18m81uobYjlJaC8CL8iANzI42qxkxfZsDs,3268
210
210
  wandb/sdk/wandb_require.py,sha256=Y0ib8h27__t7hXos1F2srfsQzVfzH4BB6wq8E1aRbRA,2950
211
211
  wandb/sdk/wandb_require_helpers.py,sha256=ZmKv5aXXHDTTU6nYHMLKW4_pt9X-PlaMtbRJl77kHX8,1331
212
- wandb/sdk/wandb_run.py,sha256=_hH8Pe-lEZE_FiPHYmOrQxdGfs4V2PuFOu0SD5jczlg,155746
213
- wandb/sdk/wandb_settings.py,sha256=jvD7tTJ9J-aQvsmIz8UdVPS2Qd_zpSW3aDP-82mT_Hk,48386
212
+ wandb/sdk/wandb_run.py,sha256=eI6WIi2pmkBkP5aMgscMU9C94PjGVknEYQvVPlC-YDM,155668
213
+ wandb/sdk/wandb_settings.py,sha256=gXZydMDYH8OLcAoK78mA4naRqBA2aKlsIGKn3i4OC0s,47290
214
214
  wandb/sdk/wandb_setup.py,sha256=7j3UBiqm8x7f4JsFPX5jR19wNRSRvf77TIyncd0HpJg,13014
215
215
  wandb/sdk/wandb_summary.py,sha256=yQdOVIPrZaZanhBQ7yuSfPLX0x6dxwkN_KAn4SgjSZU,4536
216
216
  wandb/sdk/wandb_sweep.py,sha256=Sg_JqxVzmjUBvii41azpdr-c6RPwHOBnSha8k7jrRhk,4028
@@ -816,8 +816,8 @@ wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/importlib2.py,sha256=cJIaJ2EQso
816
816
  wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/platform.py,sha256=UORYTNVcUSE2NpFcq9UVLIS-tsS0TS_Qw8akhKxn2eY,1506
817
817
  wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/unicode_paths.py,sha256=UWX8DB97ygkEeSxWQUYCHR4MahNilux7vl5TCTQtPPk,2190
818
818
  wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/win32stat.py,sha256=ZOevOTbSo8NRiIxkuBVGaG4yigWnPoO0goxAi-jsBkM,3828
819
- wandb-0.19.2.dist-info/METADATA,sha256=IpB8Qg0TddJcHZwNDfVMZPAOLEDw10Lx1KyDY944YDM,10282
820
- wandb-0.19.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
821
- wandb-0.19.2.dist-info/entry_points.txt,sha256=v4FCOZ9gW7Pc6KLsmgQqpCiKTrA1wh2XHmNf-NUP1-I,67
822
- wandb-0.19.2.dist-info/licenses/LICENSE,sha256=izOKRJpGOx1PrJiGOKR0HsNdlB5JdH2d0Z4P7a7ssTc,1081
823
- wandb-0.19.2.dist-info/RECORD,,
819
+ wandb-0.19.3.dist-info/METADATA,sha256=AGD2Iwy-cUjmtannnNpN4Nh9wQAjRZw7WgFow2-DvwI,10282
820
+ wandb-0.19.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
821
+ wandb-0.19.3.dist-info/entry_points.txt,sha256=v4FCOZ9gW7Pc6KLsmgQqpCiKTrA1wh2XHmNf-NUP1-I,67
822
+ wandb-0.19.3.dist-info/licenses/LICENSE,sha256=izOKRJpGOx1PrJiGOKR0HsNdlB5JdH2d0Z4P7a7ssTc,1081
823
+ wandb-0.19.3.dist-info/RECORD,,
File without changes