wandb 0.16.3__py3-none-any.whl → 0.16.5__py3-none-any.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 (90) hide show
  1. wandb/__init__.py +2 -2
  2. wandb/agents/pyagent.py +1 -1
  3. wandb/apis/importers/__init__.py +1 -4
  4. wandb/apis/importers/internals/internal.py +386 -0
  5. wandb/apis/importers/internals/protocols.py +125 -0
  6. wandb/apis/importers/internals/util.py +78 -0
  7. wandb/apis/importers/mlflow.py +125 -88
  8. wandb/apis/importers/validation.py +108 -0
  9. wandb/apis/importers/wandb.py +1604 -0
  10. wandb/apis/public/api.py +7 -10
  11. wandb/apis/public/artifacts.py +38 -0
  12. wandb/apis/public/files.py +11 -2
  13. wandb/apis/reports/v2/__init__.py +0 -19
  14. wandb/apis/reports/v2/expr_parsing.py +0 -1
  15. wandb/apis/reports/v2/interface.py +15 -18
  16. wandb/apis/reports/v2/internal.py +12 -45
  17. wandb/cli/cli.py +52 -55
  18. wandb/integration/gym/__init__.py +2 -1
  19. wandb/integration/keras/callbacks/model_checkpoint.py +1 -1
  20. wandb/integration/keras/keras.py +6 -4
  21. wandb/integration/kfp/kfp_patch.py +2 -2
  22. wandb/integration/openai/fine_tuning.py +1 -2
  23. wandb/integration/ultralytics/callback.py +0 -1
  24. wandb/proto/v3/wandb_internal_pb2.py +332 -312
  25. wandb/proto/v3/wandb_settings_pb2.py +13 -3
  26. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  27. wandb/proto/v4/wandb_internal_pb2.py +316 -312
  28. wandb/proto/v4/wandb_settings_pb2.py +5 -3
  29. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  30. wandb/sdk/artifacts/artifact.py +75 -31
  31. wandb/sdk/artifacts/artifact_manifest.py +5 -2
  32. wandb/sdk/artifacts/artifact_manifest_entry.py +6 -1
  33. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +8 -2
  34. wandb/sdk/artifacts/artifact_saver.py +19 -47
  35. wandb/sdk/artifacts/storage_handler.py +2 -1
  36. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +22 -9
  37. wandb/sdk/artifacts/storage_policy.py +4 -1
  38. wandb/sdk/data_types/base_types/wb_value.py +1 -1
  39. wandb/sdk/data_types/image.py +2 -2
  40. wandb/sdk/interface/interface.py +49 -13
  41. wandb/sdk/interface/interface_shared.py +17 -11
  42. wandb/sdk/internal/file_stream.py +20 -1
  43. wandb/sdk/internal/handler.py +1 -4
  44. wandb/sdk/internal/internal_api.py +3 -1
  45. wandb/sdk/internal/job_builder.py +49 -19
  46. wandb/sdk/internal/profiler.py +1 -1
  47. wandb/sdk/internal/sender.py +96 -124
  48. wandb/sdk/internal/sender_config.py +197 -0
  49. wandb/sdk/internal/settings_static.py +9 -0
  50. wandb/sdk/internal/system/system_info.py +5 -3
  51. wandb/sdk/internal/update.py +1 -1
  52. wandb/sdk/launch/_launch.py +3 -3
  53. wandb/sdk/launch/_launch_add.py +28 -29
  54. wandb/sdk/launch/_project_spec.py +148 -136
  55. wandb/sdk/launch/agent/agent.py +3 -7
  56. wandb/sdk/launch/agent/config.py +0 -27
  57. wandb/sdk/launch/builder/build.py +54 -28
  58. wandb/sdk/launch/builder/docker_builder.py +4 -15
  59. wandb/sdk/launch/builder/kaniko_builder.py +72 -45
  60. wandb/sdk/launch/create_job.py +6 -40
  61. wandb/sdk/launch/loader.py +10 -0
  62. wandb/sdk/launch/registry/anon.py +29 -0
  63. wandb/sdk/launch/registry/local_registry.py +4 -1
  64. wandb/sdk/launch/runner/kubernetes_runner.py +20 -2
  65. wandb/sdk/launch/runner/local_container.py +15 -10
  66. wandb/sdk/launch/runner/sagemaker_runner.py +1 -1
  67. wandb/sdk/launch/sweeps/scheduler.py +11 -3
  68. wandb/sdk/launch/utils.py +14 -0
  69. wandb/sdk/lib/__init__.py +2 -5
  70. wandb/sdk/lib/_settings_toposort_generated.py +4 -1
  71. wandb/sdk/lib/apikey.py +0 -5
  72. wandb/sdk/lib/config_util.py +0 -31
  73. wandb/sdk/lib/filesystem.py +11 -1
  74. wandb/sdk/lib/run_moment.py +72 -0
  75. wandb/sdk/service/service.py +7 -2
  76. wandb/sdk/service/streams.py +1 -6
  77. wandb/sdk/verify/verify.py +2 -1
  78. wandb/sdk/wandb_init.py +12 -1
  79. wandb/sdk/wandb_login.py +43 -26
  80. wandb/sdk/wandb_run.py +164 -110
  81. wandb/sdk/wandb_settings.py +58 -16
  82. wandb/testing/relay.py +5 -6
  83. wandb/util.py +50 -7
  84. {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/METADATA +8 -1
  85. {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/RECORD +89 -82
  86. {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/WHEEL +1 -1
  87. wandb/apis/importers/base.py +0 -400
  88. {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/LICENSE +0 -0
  89. {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/entry_points.txt +0 -0
  90. {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/top_level.txt +0 -0
@@ -25,37 +25,6 @@ def dict_from_proto_list(obj_list):
25
25
  return d
26
26
 
27
27
 
28
- def update_from_proto(config_dict, config_proto):
29
- for item in config_proto.update:
30
- key_list = item.nested_key or (item.key,)
31
- assert key_list, "key or nested key must be set"
32
- target = config_dict
33
- # recurse down the dictionary structure:
34
- for prop in key_list[:-1]:
35
- if not target.get(prop):
36
- target[prop] = {}
37
- target = target[prop]
38
- # use the last element of the key to write the leaf:
39
- target[key_list[-1]] = json.loads(item.value_json)
40
- for item in config_proto.remove:
41
- key_list = item.nested_key or (item.key,)
42
- assert key_list, "key or nested key must be set"
43
- target = config_dict
44
- # recurse down the dictionary structure:
45
- for prop in key_list[:-1]:
46
- target = target[prop]
47
- # use the last element of the key to write the leaf:
48
- del target[key_list[-1]]
49
- # TODO(jhr): should we delete empty parents?
50
-
51
-
52
- def dict_add_value_dict(config_dict):
53
- d = dict()
54
- for k, v in config_dict.items():
55
- d[k] = dict(desc=None, value=v)
56
- return d
57
-
58
-
59
28
  def dict_strip_value_dict(config_dict):
60
29
  d = dict()
61
30
  for k, v in config_dict.items():
@@ -227,7 +227,17 @@ def safe_open(
227
227
 
228
228
 
229
229
  def safe_copy(source_path: StrPath, target_path: StrPath) -> StrPath:
230
- """Copy a file, ensuring any changes only apply atomically once finished."""
230
+ """Copy a file atomically.
231
+
232
+ Copying is not usually atomic, and on operating systems that allow multiple
233
+ writers to the same file, the result can get corrupted. If two writers copy
234
+ to the same file, the contents can become interleaved.
235
+
236
+ We mitigate the issue somewhat by copying to a temporary file first and
237
+ then renaming. Renaming is atomic: if process 1 renames file A to X and
238
+ process 2 renames file B to X, then X will either contain the contents
239
+ of A or the contents of B, not some mixture of both.
240
+ """
231
241
  # TODO (hugh): check that there is enough free space.
232
242
  output_path = Path(target_path).resolve()
233
243
  output_path.parent.mkdir(parents=True, exist_ok=True)
@@ -0,0 +1,72 @@
1
+ from dataclasses import dataclass
2
+ from typing import Literal, Union, cast
3
+ from urllib import parse
4
+
5
+ _STEP = Literal["_step"]
6
+
7
+
8
+ @dataclass
9
+ class RunMoment:
10
+ """A moment in a run."""
11
+
12
+ run: str # run name
13
+
14
+ # currently, the _step value to fork from. in future, this will be optional
15
+ value: Union[int, float]
16
+
17
+ # only step for now, in future this will be relaxed to be any metric
18
+ metric: _STEP = "_step"
19
+
20
+ def __post_init__(self):
21
+ if self.metric != "_step":
22
+ raise ValueError(
23
+ f"Only the metric '_step' is supported, got '{self.metric}'."
24
+ )
25
+ if not isinstance(self.value, (int, float)):
26
+ raise ValueError(
27
+ f"Only int or float values are supported, got '{self.value}'."
28
+ )
29
+ if not isinstance(self.run, str):
30
+ raise ValueError(f"Only string run names are supported, got '{self.run}'.")
31
+
32
+ @classmethod
33
+ def from_uri(cls, uri: str) -> "RunMoment":
34
+ parsable = "runmoment://" + uri
35
+ parse_err = ValueError(
36
+ f"Could not parse passed run moment string '{uri}', "
37
+ f"expected format '<run>?<metric>=<numeric_value>'. "
38
+ f"Currently, only the metric '_step' is supported. "
39
+ f"Example: 'ans3bsax?_step=123'."
40
+ )
41
+
42
+ try:
43
+ parsed = parse.urlparse(parsable)
44
+ except ValueError as e:
45
+ raise parse_err from e
46
+
47
+ if parsed.scheme != "runmoment":
48
+ raise parse_err
49
+
50
+ # extract run, metric, value from parsed
51
+ if not parsed.netloc:
52
+ raise parse_err
53
+
54
+ run = parsed.netloc
55
+
56
+ if parsed.path or parsed.params or parsed.fragment:
57
+ raise parse_err
58
+
59
+ query = parse.parse_qs(parsed.query)
60
+ if len(query) != 1:
61
+ raise parse_err
62
+
63
+ metric = list(query.keys())[0]
64
+ if metric != "_step":
65
+ raise parse_err
66
+ value: str = query[metric][0]
67
+ try:
68
+ num_value = int(value) if value.isdigit() else float(value)
69
+ except ValueError as e:
70
+ raise parse_err from e
71
+
72
+ return cls(run=run, metric=cast(_STEP, metric), value=num_value)
@@ -171,6 +171,12 @@ class _Service:
171
171
  service_args.extend([core_path])
172
172
  if not error_reporting_enabled():
173
173
  service_args.append("--no-observability")
174
+ if os.environ.get("WANDB_CORE_DEBUG", False):
175
+ service_args.append("--debug")
176
+ trace_filename = os.environ.get("_WANDB_TRACE")
177
+ if trace_filename is not None:
178
+ service_args.extend(["--trace", trace_filename])
179
+
174
180
  exec_cmd_list = []
175
181
  # TODO: remove this after the wandb-core GA release
176
182
  wandb_core = get_module("wandb_core")
@@ -180,14 +186,13 @@ class _Service:
180
186
  repeat=False,
181
187
  )
182
188
  else:
183
- service_args.extend(["wandb", "service"])
189
+ service_args.extend(["wandb", "service", "--debug"])
184
190
 
185
191
  service_args += [
186
192
  "--port-filename",
187
193
  fname,
188
194
  "--pid",
189
195
  pid,
190
- "--debug",
191
196
  ]
192
197
  service_args.append("--serve-sock")
193
198
 
@@ -5,6 +5,7 @@ StreamRecord: All the external state for the internal thread (queues, etc)
5
5
  StreamAction: Lightweight record for stream ops for thread safety
6
6
  StreamMux: Container for dictionary of stream threads per runid
7
7
  """
8
+
8
9
  import functools
9
10
  import multiprocessing
10
11
  import queue
@@ -327,7 +328,6 @@ class StreamMux:
327
328
  result = internal_messages_handle.wait(timeout=-1)
328
329
  assert result
329
330
  internal_messages_response = result.response.internal_messages_response
330
- job_info_handle = stream.interface.deliver_request_job_info()
331
331
 
332
332
  # wait for them, it's ok to do this serially but this can be improved
333
333
  result = poll_exit_handle.wait(timeout=-1)
@@ -346,17 +346,12 @@ class StreamMux:
346
346
  assert result
347
347
  final_summary = result.response.get_summary_response
348
348
 
349
- result = job_info_handle.wait(timeout=-1)
350
- assert result
351
- job_info = result.response.job_info_response
352
-
353
349
  Run._footer(
354
350
  sampled_history=sampled_history,
355
351
  final_summary=final_summary,
356
352
  poll_exit_response=poll_exit_response,
357
353
  server_info_response=server_info_response,
358
354
  internal_messages_response=internal_messages_response,
359
- job_info=job_info,
360
355
  settings=stream._settings, # type: ignore
361
356
  printer=printer,
362
357
  )
@@ -8,7 +8,6 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
8
8
 
9
9
  import click
10
10
  import requests
11
- from pkg_resources import parse_version
12
11
  from wandb_gql import gql
13
12
 
14
13
  import wandb
@@ -469,6 +468,8 @@ def check_wandb_version(api: Api) -> None:
469
468
  min_cli_version = server_info.get("cliVersionInfo", {}).get(
470
469
  "min_cli_version", "0.0.1"
471
470
  )
471
+ from wandb.util import parse_version
472
+
472
473
  if parse_version(wandb.__version__) < parse_version(min_cli_version):
473
474
  fail_string = "wandb version out of date, please run pip install --upgrade wandb=={}".format(
474
475
  max_cli_version
wandb/sdk/wandb_init.py CHANGED
@@ -7,6 +7,7 @@ your evaluation script, and each step would be tracked as a run in W&B.
7
7
  For more on using `wandb.init()`, including code snippets, check out our
8
8
  [guide and FAQs](https://docs.wandb.ai/guides/track/launch).
9
9
  """
10
+
10
11
  import copy
11
12
  import json
12
13
  import logging
@@ -828,7 +829,7 @@ class _WandbInit:
828
829
  and self.settings.launch_config_path
829
830
  and os.path.exists(self.settings.launch_config_path)
830
831
  ):
831
- run._save(self.settings.launch_config_path)
832
+ run.save(self.settings.launch_config_path)
832
833
  # put artifacts in run config here
833
834
  # since doing so earlier will cause an error
834
835
  # as the run is not upserted
@@ -961,6 +962,7 @@ def init(
961
962
  monitor_gym: Optional[bool] = None,
962
963
  save_code: Optional[bool] = None,
963
964
  id: Optional[str] = None,
965
+ fork_from: Optional[str] = None,
964
966
  settings: Union[Settings, Dict[str, Any], None] = None,
965
967
  ) -> Union[Run, RunDisabled, None]:
966
968
  r"""Start a new run to track and log to W&B.
@@ -1122,6 +1124,10 @@ def init(
1122
1124
  for saving hyperparameters to compare across runs. The ID cannot
1123
1125
  contain the following special characters: `/\#?%:`.
1124
1126
  See [our guide to resuming runs](https://docs.wandb.com/guides/runs/resuming).
1127
+ fork_from: (str, optional) A string with the format <run_id>?_step=<step> describing
1128
+ a moment in a previous run to fork a new run from. Creates a new run that picks up
1129
+ logging history from the specified run at the specified moment. The target run must
1130
+ be in the current project.
1125
1131
 
1126
1132
  Examples:
1127
1133
  ### Set where the run is logged
@@ -1167,6 +1173,11 @@ def init(
1167
1173
  error_seen = None
1168
1174
  except_exit = None
1169
1175
  run: Optional[Union[Run, RunDisabled]] = None
1176
+
1177
+ # convert fork_from into a version that can be passed to settings
1178
+ if fork_from is not None and resume is not None:
1179
+ raise ValueError("Cannot specify both `fork_from` and `resume`")
1180
+
1170
1181
  try:
1171
1182
  wi = _WandbInit()
1172
1183
  wi.setup(kwargs)
wandb/sdk/wandb_login.py CHANGED
@@ -22,7 +22,7 @@ from wandb.old.settings import Settings as OldSettings
22
22
  from ..apis import InternalApi
23
23
  from .internal.internal_api import Api
24
24
  from .lib import apikey
25
- from .wandb_settings import Settings, Source
25
+ from .wandb_settings import Settings
26
26
 
27
27
 
28
28
  def _handle_host_wandb_setting(host: Optional[str], cloud: bool = False) -> None:
@@ -80,11 +80,17 @@ def login(
80
80
  _handle_host_wandb_setting(host)
81
81
  if wandb.setup()._settings._noop:
82
82
  return True
83
- kwargs = dict(locals())
84
- _verify = kwargs.pop("verify", False)
85
- configured = _login(**kwargs)
86
83
 
87
- if _verify:
84
+ configured = _login(
85
+ anonymous=anonymous,
86
+ key=key,
87
+ relogin=relogin,
88
+ host=host,
89
+ force=force,
90
+ timeout=timeout,
91
+ )
92
+
93
+ if verify:
88
94
  from . import wandb_setup
89
95
 
90
96
  singleton = wandb_setup._WandbSetup._instance
@@ -115,22 +121,32 @@ class _WandbLogin:
115
121
  self._key = None
116
122
  self._relogin = None
117
123
 
118
- def setup(self, kwargs):
119
- self.kwargs = kwargs
124
+ def setup(
125
+ self,
126
+ *,
127
+ anonymous: Optional[Literal["must", "allow", "never"]] = None,
128
+ key: Optional[str] = None,
129
+ relogin: Optional[bool] = None,
130
+ host: Optional[str] = None,
131
+ force: Optional[bool] = None,
132
+ timeout: Optional[int] = None,
133
+ ):
134
+ self._relogin = relogin
120
135
 
121
136
  # built up login settings
122
137
  login_settings: Settings = wandb.Settings()
123
- settings_param = kwargs.pop("_settings", None)
124
- # note that this case does not come up anywhere except for the tests
125
- if settings_param is not None:
126
- if isinstance(settings_param, Settings):
127
- login_settings._apply_settings(settings_param)
128
- elif isinstance(settings_param, dict):
129
- login_settings.update(settings_param, source=Source.LOGIN)
130
- _logger = wandb.setup()._get_logger()
131
- # Do not save relogin into settings as we just want to relogin once
132
- self._relogin = kwargs.pop("relogin", None)
133
- login_settings._apply_login(kwargs, _logger=_logger)
138
+ logger = wandb.setup()._get_logger()
139
+
140
+ login_settings._apply_login(
141
+ {
142
+ "anonymous": anonymous,
143
+ "key": key,
144
+ "host": host,
145
+ "force": force,
146
+ "timeout": timeout,
147
+ },
148
+ _logger=logger,
149
+ )
134
150
 
135
151
  # make sure they are applied globally
136
152
  self._wl = wandb.setup(settings=login_settings)
@@ -259,6 +275,7 @@ class _WandbLogin:
259
275
 
260
276
 
261
277
  def _login(
278
+ *,
262
279
  anonymous: Optional[Literal["must", "allow", "never"]] = None,
263
280
  key: Optional[str] = None,
264
281
  relogin: Optional[bool] = None,
@@ -270,9 +287,6 @@ def _login(
270
287
  _disable_warning: Optional[bool] = None,
271
288
  _entity: Optional[str] = None,
272
289
  ):
273
- kwargs = dict(locals())
274
- _disable_warning = kwargs.pop("_disable_warning", None)
275
-
276
290
  if wandb.run is not None:
277
291
  if not _disable_warning:
278
292
  wandb.termwarn("Calling wandb.login() after wandb.init() has no effect.")
@@ -280,20 +294,24 @@ def _login(
280
294
 
281
295
  wlogin = _WandbLogin()
282
296
 
283
- _backend = kwargs.pop("_backend", None)
284
297
  if _backend:
285
298
  wlogin.set_backend(_backend)
286
299
 
287
- _silent = kwargs.pop("_silent", None)
288
300
  if _silent:
289
301
  wlogin.set_silent(_silent)
290
302
 
291
- _entity = kwargs.pop("_entity", None)
292
303
  if _entity:
293
304
  wlogin.set_entity(_entity)
294
305
 
295
306
  # configure login object
296
- wlogin.setup(kwargs)
307
+ wlogin.setup(
308
+ anonymous=anonymous,
309
+ key=key,
310
+ relogin=relogin,
311
+ host=host,
312
+ force=force,
313
+ timeout=timeout,
314
+ )
297
315
 
298
316
  if wlogin._settings._offline:
299
317
  return False
@@ -306,7 +324,6 @@ def _login(
306
324
  # perform a login
307
325
  logged_in = wlogin.login()
308
326
 
309
- key = kwargs.get("key")
310
327
  if key:
311
328
  wlogin.configure_api_key(key)
312
329