wandb 0.19.8__py3-none-win_amd64.whl → 0.19.9__py3-none-win_amd64.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 (65) hide show
  1. wandb/__init__.py +5 -1
  2. wandb/__init__.pyi +12 -8
  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.exe +0 -0
  14. wandb/bin/wandb-core +0 -0
  15. wandb/integration/metaflow/metaflow.py +19 -17
  16. wandb/integration/sacred/__init__.py +1 -1
  17. wandb/jupyter.py +18 -15
  18. wandb/proto/v3/wandb_internal_pb2.py +7 -3
  19. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  20. wandb/proto/v3/wandb_telemetry_pb2.py +4 -4
  21. wandb/proto/v4/wandb_internal_pb2.py +3 -3
  22. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  23. wandb/proto/v4/wandb_telemetry_pb2.py +4 -4
  24. wandb/proto/v5/wandb_internal_pb2.py +3 -3
  25. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  26. wandb/proto/v5/wandb_telemetry_pb2.py +4 -4
  27. wandb/proto/wandb_deprecated.py +2 -0
  28. wandb/sdk/artifacts/_graphql_fragments.py +18 -20
  29. wandb/sdk/artifacts/_validators.py +1 -0
  30. wandb/sdk/artifacts/artifact.py +70 -36
  31. wandb/sdk/artifacts/artifact_saver.py +16 -2
  32. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +23 -2
  33. wandb/sdk/data_types/audio.py +1 -3
  34. wandb/sdk/data_types/base_types/media.py +11 -4
  35. wandb/sdk/data_types/image.py +44 -25
  36. wandb/sdk/data_types/molecule.py +1 -5
  37. wandb/sdk/data_types/object_3d.py +2 -1
  38. wandb/sdk/data_types/saved_model.py +7 -9
  39. wandb/sdk/data_types/video.py +1 -4
  40. wandb/{apis/public → sdk/internal}/_generated/__init__.py +0 -6
  41. wandb/sdk/internal/_generated/base.py +226 -0
  42. wandb/{apis/public → sdk/internal}/_generated/server_features_query.py +3 -3
  43. wandb/{apis/public → sdk/internal}/_generated/typing_compat.py +1 -1
  44. wandb/sdk/internal/internal_api.py +138 -47
  45. wandb/sdk/internal/sender.py +2 -0
  46. wandb/sdk/internal/sender_config.py +8 -11
  47. wandb/sdk/internal/settings_static.py +24 -2
  48. wandb/sdk/lib/apikey.py +15 -16
  49. wandb/sdk/lib/run_moment.py +4 -6
  50. wandb/sdk/lib/wb_logging.py +161 -0
  51. wandb/sdk/wandb_config.py +44 -43
  52. wandb/sdk/wandb_init.py +141 -79
  53. wandb/sdk/wandb_metadata.py +107 -91
  54. wandb/sdk/wandb_run.py +152 -44
  55. wandb/sdk/wandb_settings.py +403 -201
  56. wandb/sdk/wandb_setup.py +3 -1
  57. {wandb-0.19.8.dist-info → wandb-0.19.9.dist-info}/METADATA +3 -3
  58. {wandb-0.19.8.dist-info → wandb-0.19.9.dist-info}/RECORD +64 -60
  59. wandb/apis/public/_generated/base.py +0 -128
  60. /wandb/{apis/public → sdk/internal}/_generated/enums.py +0 -0
  61. /wandb/{apis/public → sdk/internal}/_generated/input_types.py +0 -0
  62. /wandb/{apis/public → sdk/internal}/_generated/operations.py +0 -0
  63. {wandb-0.19.8.dist-info → wandb-0.19.9.dist-info}/WHEEL +0 -0
  64. {wandb-0.19.8.dist-info → wandb-0.19.9.dist-info}/entry_points.txt +0 -0
  65. {wandb-0.19.8.dist-info → wandb-0.19.9.dist-info}/licenses/LICENSE +0 -0
@@ -21,11 +21,33 @@ class SettingsStatic(Settings):
21
21
  def _proto_to_dict(self, proto: wandb_settings_pb2.Settings) -> dict:
22
22
  data = {}
23
23
 
24
+ exclude_fields = {
25
+ "model_config",
26
+ "model_fields",
27
+ "model_fields_set",
28
+ "__fields__",
29
+ "__model_fields_set",
30
+ "__pydantic_self__",
31
+ "__pydantic_initialised__",
32
+ }
33
+
34
+ fields = (
35
+ Settings.model_fields
36
+ if hasattr(Settings, "model_fields")
37
+ else Settings.__fields__
38
+ ) # type: ignore [attr-defined]
39
+
40
+ fields = {k: v for k, v in fields.items() if k not in exclude_fields} # type: ignore [union-attr]
41
+
24
42
  forks_specified: list[str] = []
25
- for key in Settings.model_fields: # type: ignore [attr-defined]
43
+ for key in fields:
44
+ # Skip Python-only keys that do not exist on the proto.
45
+ if key in ("reinit",):
46
+ continue
47
+
26
48
  value: Any = None
27
49
 
28
- field_info = Settings.model_fields[key]
50
+ field_info = fields[key]
29
51
  annotation = str(field_info.annotation)
30
52
 
31
53
  if key == "_stats_open_metrics_filters":
wandb/sdk/lib/apikey.py CHANGED
@@ -11,7 +11,7 @@ import textwrap
11
11
  from functools import partial
12
12
 
13
13
  # import Literal
14
- from typing import TYPE_CHECKING, Callable, Dict, Literal, Optional, Union
14
+ from typing import TYPE_CHECKING, Callable, Literal
15
15
  from urllib.parse import urlparse
16
16
 
17
17
  import click
@@ -23,6 +23,9 @@ from wandb.errors import term
23
23
  from wandb.errors.links import url_registry
24
24
  from wandb.util import _is_databricks, isatty, prompt_choices
25
25
 
26
+ if TYPE_CHECKING:
27
+ from wandb.sdk.wandb_settings import Settings
28
+
26
29
  LOGIN_CHOICE_ANON = "Private W&B dashboard, no account required"
27
30
  LOGIN_CHOICE_NEW = "Create a W&B account"
28
31
  LOGIN_CHOICE_EXISTS = "Use an existing W&B account"
@@ -50,18 +53,14 @@ class WriteNetrcError(Exception):
50
53
  Mode = Literal["allow", "must", "never", "false", "true"]
51
54
 
52
55
 
53
- if TYPE_CHECKING:
54
- from wandb.sdk.wandb_settings import Settings
55
-
56
-
57
56
  getpass = partial(click.prompt, hide_input=True, err=True)
58
57
 
59
58
 
60
- def _fixup_anon_mode(default: Optional[Mode]) -> Optional[Mode]:
59
+ def _fixup_anon_mode(default: Mode | None) -> Mode | None:
61
60
  # Convert weird anonymode values from legacy settings files
62
61
  # into one of our expected values.
63
62
  anon_mode = default or "never"
64
- mapping: Dict[Mode, Mode] = {"true": "allow", "false": "never"}
63
+ mapping: dict[Mode, Mode] = {"true": "allow", "false": "never"}
65
64
  return mapping.get(anon_mode, anon_mode)
66
65
 
67
66
 
@@ -85,14 +84,14 @@ def get_netrc_file_path() -> str:
85
84
 
86
85
 
87
86
  def prompt_api_key( # noqa: C901
88
- settings: "Settings",
89
- api: Optional[InternalApi] = None,
90
- input_callback: Optional[Callable] = None,
91
- browser_callback: Optional[Callable] = None,
87
+ settings: Settings,
88
+ api: InternalApi | None = None,
89
+ input_callback: Callable | None = None,
90
+ browser_callback: Callable | None = None,
92
91
  no_offline: bool = False,
93
92
  no_create: bool = False,
94
93
  local: bool = False,
95
- ) -> Union[str, bool, None]:
94
+ ) -> str | bool | None:
96
95
  """Prompt for api key.
97
96
 
98
97
  Returns:
@@ -276,9 +275,9 @@ def write_netrc(host: str, entity: str, key: str):
276
275
 
277
276
 
278
277
  def write_key(
279
- settings: "Settings",
280
- key: Optional[str],
281
- api: Optional["InternalApi"] = None,
278
+ settings: Settings,
279
+ key: str | None,
280
+ api: InternalApi | None = None,
282
281
  ) -> None:
283
282
  if not key:
284
283
  raise ValueError("No API key specified.")
@@ -298,7 +297,7 @@ def write_key(
298
297
  write_netrc(settings.base_url, "user", key)
299
298
 
300
299
 
301
- def api_key(settings: Optional["Settings"] = None) -> Optional[str]:
300
+ def api_key(settings: Settings | None = None) -> str | None:
302
301
  if settings is None:
303
302
  settings = wandb.setup().settings
304
303
  if settings.api_key:
@@ -1,11 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import Literal, cast
4
+ from typing import Union
5
5
  from urllib import parse
6
6
 
7
- _STEP = Literal["_step"]
8
-
9
7
 
10
8
  @dataclass
11
9
  class RunMoment:
@@ -19,10 +17,10 @@ class RunMoment:
19
17
  run: str
20
18
  """run ID"""
21
19
 
22
- value: int | float
20
+ value: Union[int, float]
23
21
  """Value of the metric."""
24
22
 
25
- metric: _STEP = "_step"
23
+ metric: str = "_step"
26
24
  """Metric to use to determine the moment in the run.
27
25
 
28
26
  Currently, only the metric '_step' is supported.
@@ -81,4 +79,4 @@ class RunMoment:
81
79
  except ValueError as e:
82
80
  raise parse_err from e
83
81
 
84
- return cls(run=run, metric=cast(_STEP, metric), value=num_value)
82
+ return cls(run=run, metric=metric, value=num_value)
@@ -0,0 +1,161 @@
1
+ """Logging configuration for the "wandb" logger.
2
+
3
+ Most log statements in wandb are made in the context of a run and should be
4
+ redirected to that run's log file (usually named 'debug.log'). This module
5
+ provides a context manager to temporarily set the current run ID and registers
6
+ a global handler for the 'wandb' logger that sends log statements to the right
7
+ place.
8
+
9
+ All functions in this module are threadsafe.
10
+
11
+ NOTE: The pytest caplog fixture will fail to capture logs from the wandb logger
12
+ because they are not propagated to the root logger.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import contextlib
18
+ import contextvars
19
+ import logging
20
+ import pathlib
21
+ from typing import Iterator
22
+
23
+
24
+ class _NotRunSpecific:
25
+ """Sentinel for `not_run_specific()`."""
26
+
27
+
28
+ _NOT_RUN_SPECIFIC = _NotRunSpecific()
29
+
30
+
31
+ _run_id: contextvars.ContextVar[str | _NotRunSpecific | None] = contextvars.ContextVar(
32
+ "_run_id",
33
+ default=None,
34
+ )
35
+
36
+ _logger = logging.getLogger("wandb")
37
+
38
+
39
+ def configure_wandb_logger() -> None:
40
+ """Configures the global 'wandb' logger.
41
+
42
+ The wandb logger is not intended to be customized by users. Instead, it is
43
+ used as a mechanism to redirect log messages into wandb run-specific log
44
+ files.
45
+
46
+ This function is idempotent: calling it multiple times has the same effect.
47
+ """
48
+ # Send all DEBUG and above messages to registered handlers.
49
+ #
50
+ # Per-run handlers can set different levels.
51
+ _logger.setLevel(logging.DEBUG)
52
+
53
+ # Do not propagate wandb logs to the root logger, which the user may have
54
+ # configured to point elsewhere. All wandb log messages should go to a run's
55
+ # log file.
56
+ _logger.propagate = False
57
+
58
+ # If no handlers are configured for the 'wandb' logger, don't activate the
59
+ # "lastResort" handler which sends messages to stderr with a level of
60
+ # WARNING by default.
61
+ #
62
+ # This occurs in wandb code that runs outside the context of a Run and
63
+ # not as part of the CLI.
64
+ #
65
+ # Most such code uses the `termlog` / `termwarn` / `termerror` methods
66
+ # to communicate with the user. When that code executes while a run is
67
+ # active, its logger messages go to that run's log file.
68
+ if not _logger.handlers:
69
+ _logger.addHandler(logging.NullHandler())
70
+
71
+
72
+ @contextlib.contextmanager
73
+ def log_to_run(run_id: str | None) -> Iterator[None]:
74
+ """Direct all wandb log messages to the given run.
75
+
76
+ Args:
77
+ id: The current run ID, or None if actions in the context manager are
78
+ not associated to a specific run. In the latter case, log messages
79
+ will go to all runs.
80
+
81
+ Usage:
82
+
83
+ with wb_logging.run_id(...):
84
+ ... # Log messages here go to the specified run's logger.
85
+ """
86
+ token = _run_id.set(run_id)
87
+ try:
88
+ yield
89
+ finally:
90
+ _run_id.reset(token)
91
+
92
+
93
+ @contextlib.contextmanager
94
+ def log_to_all_runs() -> Iterator[None]:
95
+ """Direct wandb log messages to all runs.
96
+
97
+ Unlike `log_to_run(None)`, this indicates an intentional choice.
98
+ This is often convenient to use as a decorator:
99
+
100
+ @wb_logging.log_to_all_runs()
101
+ def my_func():
102
+ ... # Log messages here go to the specified run's logger.
103
+ """
104
+ token = _run_id.set(_NOT_RUN_SPECIFIC)
105
+ try:
106
+ yield
107
+ finally:
108
+ _run_id.reset(token)
109
+
110
+
111
+ def add_file_handler(run_id: str, filepath: pathlib.Path) -> logging.Handler:
112
+ """Direct log messages for a run to a file.
113
+
114
+ Args:
115
+ run_id: The run for which to create a log file.
116
+ filepath: The file to write log messages to.
117
+
118
+ Returns:
119
+ The added handler which can then be configured further or removed
120
+ from the 'wandb' logger directly.
121
+
122
+ The default logging level is INFO.
123
+ """
124
+ handler = logging.FileHandler(filepath)
125
+ handler.setLevel(logging.INFO)
126
+ handler.addFilter(_RunIDFilter(run_id))
127
+ handler.setFormatter(
128
+ logging.Formatter(
129
+ "%(asctime)s %(levelname)-7s %(threadName)-10s:%(process)d"
130
+ " [%(filename)s:%(funcName)s():%(lineno)s]%(run_id_tag)s"
131
+ " %(message)s"
132
+ )
133
+ )
134
+
135
+ _logger.addHandler(handler)
136
+ return handler
137
+
138
+
139
+ class _RunIDFilter(logging.Filter):
140
+ """Filters out messages logged for a different run."""
141
+
142
+ def __init__(self, run_id: str) -> None:
143
+ """Create a _RunIDFilter.
144
+
145
+ Args:
146
+ run_id: Allows messages when the run ID is this or None.
147
+ """
148
+ self._run_id = run_id
149
+
150
+ def filter(self, record: logging.LogRecord) -> bool:
151
+ run_id = _run_id.get()
152
+
153
+ if run_id is None:
154
+ record.run_id_tag = " [no run ID]"
155
+ return True
156
+ elif isinstance(run_id, _NotRunSpecific):
157
+ record.run_id_tag = " [all runs]"
158
+ return True
159
+ else:
160
+ record.run_id_tag = ""
161
+ return run_id == self._run_id
wandb/sdk/wandb_config.py CHANGED
@@ -22,65 +22,63 @@ logger = logging.getLogger("wandb")
22
22
  class Config:
23
23
  """Config object.
24
24
 
25
- Config objects are intended to hold all of the hyperparameters associated with
26
- a wandb run and are saved with the run object when `wandb.init` is called.
25
+ Config objects are intended to hold all of the hyperparameters associated
26
+ with a wandb run and are saved with the run object when `wandb.init` is
27
+ called.
27
28
 
28
- We recommend setting `wandb.config` once at the top of your training experiment or
29
- setting the config as a parameter to init, ie. `wandb.init(config=my_config_dict)`
29
+ We recommend setting the config once when initializing your run by passing
30
+ the `config` parameter to `init`:
30
31
 
31
- You can create a file called `config-defaults.yaml`, and it will automatically be
32
- loaded into `wandb.config`. See https://docs.wandb.com/guides/track/config#file-based-configs.
32
+ ```
33
+ wandb.init(config=my_config_dict)
34
+ ```
35
+
36
+ You can create a file called `config-defaults.yaml`, and it will
37
+ automatically be loaded as each run's config. You can also pass the name
38
+ of the file as the `config` parameter to `init`:
39
+
40
+ ```
41
+ wandb.init(config="my_config.yaml")
42
+ ```
33
43
 
34
- You can also load a config YAML file with your custom name and pass the filename
35
- into `wandb.init(config="special_config.yaml")`.
36
44
  See https://docs.wandb.com/guides/track/config#file-based-configs.
37
45
 
38
46
  Examples:
39
47
  Basic usage
40
48
  ```
41
- wandb.config.epochs = 4
42
- wandb.init()
43
- for x in range(wandb.config.epochs):
44
- # train
45
- ```
46
-
47
- Using wandb.init to set config
48
- ```
49
- wandb.init(config={"epochs": 4, "batch_size": 32})
50
- for x in range(wandb.config.epochs):
51
- # train
49
+ with wandb.init(config={"epochs": 4}) as run:
50
+ for x in range(run.config.epochs):
51
+ # train
52
52
  ```
53
53
 
54
- Nested configs
54
+ Nested values
55
55
  ```
56
- wandb.config['train']['epochs'] = 4
57
- wandb.init()
58
- for x in range(wandb.config['train']['epochs']):
59
- # train
56
+ with wandb.init(config={"train": {"epochs": 4}}) as run:
57
+ for x in range(run.config["train"]["epochs"]):
58
+ # train
60
59
  ```
61
60
 
62
61
  Using absl flags
63
62
  ```
64
63
  flags.DEFINE_string("model", None, "model to run") # name, default, help
65
- wandb.config.update(flags.FLAGS) # adds all absl flags to config
64
+ with wandb.init() as run:
65
+ run.config.update(flags.FLAGS) # adds all absl flags to config
66
66
  ```
67
67
 
68
68
  Argparse flags
69
69
  ```python
70
- wandb.init()
71
- wandb.config.epochs = 4
72
-
73
- parser = argparse.ArgumentParser()
74
- parser.add_argument(
75
- "-b",
76
- "--batch-size",
77
- type=int,
78
- default=8,
79
- metavar="N",
80
- help="input batch size for training (default: 8)",
81
- )
82
- args = parser.parse_args()
83
- wandb.config.update(args)
70
+ with wandb.init(config={"epochs": 4}) as run:
71
+ parser = argparse.ArgumentParser()
72
+ parser.add_argument(
73
+ "-b",
74
+ "--batch-size",
75
+ type=int,
76
+ default=8,
77
+ metavar="N",
78
+ help="input batch size for training (default: 8)",
79
+ )
80
+ args = parser.parse_args()
81
+ run.config.update(args)
84
82
  ```
85
83
 
86
84
  Using TensorFlow flags (deprecated in tensorflow v2)
@@ -88,7 +86,9 @@ class Config:
88
86
  flags = tf.app.flags
89
87
  flags.DEFINE_string("data_dir", "/tmp/data")
90
88
  flags.DEFINE_integer("batch_size", 128, "Batch size.")
91
- wandb.config.update(flags.FLAGS) # adds all of the tensorflow flags to config
89
+
90
+ with wandb.init() as run:
91
+ run.config.update(flags.FLAGS)
92
92
  ```
93
93
  """
94
94
 
@@ -298,7 +298,8 @@ class Config:
298
298
  # best if we don't allow nested artifacts until we can lock nested keys in the config
299
299
  if isinstance(v, dict) and check_dict_contains_nested_artifact(v, nested):
300
300
  raise ValueError(
301
- "Instances of wandb.Artifact can only be top level keys in wandb.config"
301
+ "Instances of wandb.Artifact can only be top level keys in"
302
+ " a run's config"
302
303
  )
303
304
 
304
305
 
@@ -307,10 +308,10 @@ class ConfigStatic:
307
308
  object.__setattr__(self, "__dict__", dict(config))
308
309
 
309
310
  def __setattr__(self, name, value):
310
- raise AttributeError("Error: wandb.run.config_static is a readonly object")
311
+ raise AttributeError("Error: run.config_static is a readonly object")
311
312
 
312
313
  def __setitem__(self, key, val):
313
- raise AttributeError("Error: wandb.run.config_static is a readonly object")
314
+ raise AttributeError("Error: run.config_static is a readonly object")
314
315
 
315
316
  def keys(self):
316
317
  return self.__dict__.keys()