wandb 0.16.3__py3-none-any.whl → 0.16.5__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +2 -2
- wandb/agents/pyagent.py +1 -1
- wandb/apis/importers/__init__.py +1 -4
- wandb/apis/importers/internals/internal.py +386 -0
- wandb/apis/importers/internals/protocols.py +125 -0
- wandb/apis/importers/internals/util.py +78 -0
- wandb/apis/importers/mlflow.py +125 -88
- wandb/apis/importers/validation.py +108 -0
- wandb/apis/importers/wandb.py +1604 -0
- wandb/apis/public/api.py +7 -10
- wandb/apis/public/artifacts.py +38 -0
- wandb/apis/public/files.py +11 -2
- wandb/apis/reports/v2/__init__.py +0 -19
- wandb/apis/reports/v2/expr_parsing.py +0 -1
- wandb/apis/reports/v2/interface.py +15 -18
- wandb/apis/reports/v2/internal.py +12 -45
- wandb/cli/cli.py +52 -55
- wandb/integration/gym/__init__.py +2 -1
- wandb/integration/keras/callbacks/model_checkpoint.py +1 -1
- wandb/integration/keras/keras.py +6 -4
- wandb/integration/kfp/kfp_patch.py +2 -2
- wandb/integration/openai/fine_tuning.py +1 -2
- wandb/integration/ultralytics/callback.py +0 -1
- wandb/proto/v3/wandb_internal_pb2.py +332 -312
- wandb/proto/v3/wandb_settings_pb2.py +13 -3
- wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v4/wandb_internal_pb2.py +316 -312
- wandb/proto/v4/wandb_settings_pb2.py +5 -3
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/sdk/artifacts/artifact.py +75 -31
- wandb/sdk/artifacts/artifact_manifest.py +5 -2
- wandb/sdk/artifacts/artifact_manifest_entry.py +6 -1
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +8 -2
- wandb/sdk/artifacts/artifact_saver.py +19 -47
- wandb/sdk/artifacts/storage_handler.py +2 -1
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +22 -9
- wandb/sdk/artifacts/storage_policy.py +4 -1
- wandb/sdk/data_types/base_types/wb_value.py +1 -1
- wandb/sdk/data_types/image.py +2 -2
- wandb/sdk/interface/interface.py +49 -13
- wandb/sdk/interface/interface_shared.py +17 -11
- wandb/sdk/internal/file_stream.py +20 -1
- wandb/sdk/internal/handler.py +1 -4
- wandb/sdk/internal/internal_api.py +3 -1
- wandb/sdk/internal/job_builder.py +49 -19
- wandb/sdk/internal/profiler.py +1 -1
- wandb/sdk/internal/sender.py +96 -124
- wandb/sdk/internal/sender_config.py +197 -0
- wandb/sdk/internal/settings_static.py +9 -0
- wandb/sdk/internal/system/system_info.py +5 -3
- wandb/sdk/internal/update.py +1 -1
- wandb/sdk/launch/_launch.py +3 -3
- wandb/sdk/launch/_launch_add.py +28 -29
- wandb/sdk/launch/_project_spec.py +148 -136
- wandb/sdk/launch/agent/agent.py +3 -7
- wandb/sdk/launch/agent/config.py +0 -27
- wandb/sdk/launch/builder/build.py +54 -28
- wandb/sdk/launch/builder/docker_builder.py +4 -15
- wandb/sdk/launch/builder/kaniko_builder.py +72 -45
- wandb/sdk/launch/create_job.py +6 -40
- wandb/sdk/launch/loader.py +10 -0
- wandb/sdk/launch/registry/anon.py +29 -0
- wandb/sdk/launch/registry/local_registry.py +4 -1
- wandb/sdk/launch/runner/kubernetes_runner.py +20 -2
- wandb/sdk/launch/runner/local_container.py +15 -10
- wandb/sdk/launch/runner/sagemaker_runner.py +1 -1
- wandb/sdk/launch/sweeps/scheduler.py +11 -3
- wandb/sdk/launch/utils.py +14 -0
- wandb/sdk/lib/__init__.py +2 -5
- wandb/sdk/lib/_settings_toposort_generated.py +4 -1
- wandb/sdk/lib/apikey.py +0 -5
- wandb/sdk/lib/config_util.py +0 -31
- wandb/sdk/lib/filesystem.py +11 -1
- wandb/sdk/lib/run_moment.py +72 -0
- wandb/sdk/service/service.py +7 -2
- wandb/sdk/service/streams.py +1 -6
- wandb/sdk/verify/verify.py +2 -1
- wandb/sdk/wandb_init.py +12 -1
- wandb/sdk/wandb_login.py +43 -26
- wandb/sdk/wandb_run.py +164 -110
- wandb/sdk/wandb_settings.py +58 -16
- wandb/testing/relay.py +5 -6
- wandb/util.py +50 -7
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/METADATA +8 -1
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/RECORD +89 -82
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/WHEEL +1 -1
- wandb/apis/importers/base.py +0 -400
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/LICENSE +0 -0
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/entry_points.txt +0 -0
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/top_level.txt +0 -0
wandb/sdk/lib/config_util.py
CHANGED
@@ -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():
|
wandb/sdk/lib/filesystem.py
CHANGED
@@ -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
|
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)
|
wandb/sdk/service/service.py
CHANGED
@@ -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
|
|
wandb/sdk/service/streams.py
CHANGED
@@ -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
|
)
|
wandb/sdk/verify/verify.py
CHANGED
@@ -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.
|
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
|
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
|
-
|
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(
|
119
|
-
self
|
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
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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(
|
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
|
|