wandb 0.19.9__py3-none-macosx_11_0_arm64.whl → 0.19.10__py3-none-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wandb/__init__.py +1 -1
- wandb/__init__.pyi +4 -1
- wandb/_pydantic/__init__.py +14 -7
- wandb/_pydantic/base.py +44 -9
- wandb/_pydantic/utils.py +66 -0
- wandb/_pydantic/v1_compat.py +78 -56
- wandb/apis/public/__init__.py +2 -2
- wandb/apis/public/api.py +114 -2
- wandb/apis/public/artifacts.py +365 -673
- wandb/apis/public/automations.py +69 -0
- wandb/apis/public/integrations.py +168 -0
- wandb/apis/public/projects.py +29 -0
- wandb/apis/public/utils.py +107 -1
- wandb/automations/__init__.py +81 -0
- wandb/automations/_filters/__init__.py +40 -0
- wandb/automations/_filters/expressions.py +179 -0
- wandb/automations/_filters/operators.py +267 -0
- wandb/automations/_filters/run_metrics.py +183 -0
- wandb/automations/_generated/__init__.py +184 -0
- wandb/automations/_generated/create_filter_trigger.py +21 -0
- wandb/automations/_generated/create_generic_webhook_integration.py +43 -0
- wandb/automations/_generated/delete_trigger.py +19 -0
- wandb/automations/_generated/enums.py +33 -0
- wandb/automations/_generated/fragments.py +343 -0
- wandb/automations/_generated/generic_webhook_integrations_by_entity.py +22 -0
- wandb/automations/_generated/get_triggers.py +24 -0
- wandb/automations/_generated/get_triggers_by_entity.py +24 -0
- wandb/automations/_generated/input_types.py +104 -0
- wandb/automations/_generated/integrations_by_entity.py +22 -0
- wandb/automations/_generated/operations.py +710 -0
- wandb/automations/_generated/slack_integrations_by_entity.py +22 -0
- wandb/automations/_generated/update_filter_trigger.py +21 -0
- wandb/automations/_utils.py +123 -0
- wandb/automations/_validators.py +73 -0
- wandb/automations/actions.py +205 -0
- wandb/automations/automations.py +109 -0
- wandb/automations/events.py +235 -0
- wandb/automations/integrations.py +26 -0
- wandb/automations/scopes.py +76 -0
- wandb/beta/workflows.py +9 -10
- wandb/bin/gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +3 -3
- wandb/integration/keras/keras.py +2 -1
- wandb/integration/langchain/wandb_tracer.py +2 -1
- wandb/jupyter.py +137 -118
- wandb/old/summary.py +0 -2
- wandb/proto/v3/wandb_internal_pb2.py +293 -292
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v4/wandb_internal_pb2.py +292 -292
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v5/wandb_internal_pb2.py +292 -292
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v6/wandb_base_pb2.py +41 -0
- wandb/proto/v6/wandb_internal_pb2.py +393 -0
- wandb/proto/v6/wandb_server_pb2.py +78 -0
- wandb/proto/v6/wandb_settings_pb2.py +58 -0
- wandb/proto/v6/wandb_telemetry_pb2.py +52 -0
- wandb/proto/wandb_base_pb2.py +2 -0
- wandb/proto/wandb_deprecated.py +8 -0
- wandb/proto/wandb_internal_pb2.py +3 -1
- wandb/proto/wandb_server_pb2.py +2 -0
- wandb/proto/wandb_settings_pb2.py +2 -0
- wandb/proto/wandb_telemetry_pb2.py +2 -0
- wandb/sdk/artifacts/_generated/__init__.py +248 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_version_files.py +36 -0
- wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +36 -0
- wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +25 -0
- wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +35 -0
- wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +35 -0
- wandb/sdk/artifacts/_generated/enums.py +17 -0
- wandb/sdk/artifacts/_generated/fragments.py +186 -0
- wandb/sdk/artifacts/_generated/input_types.py +16 -0
- wandb/sdk/artifacts/_generated/move_artifact_collection.py +35 -0
- wandb/sdk/artifacts/_generated/operations.py +510 -0
- wandb/sdk/artifacts/_generated/project_artifact_collection.py +101 -0
- wandb/sdk/artifacts/_generated/project_artifact_collections.py +33 -0
- wandb/sdk/artifacts/_generated/project_artifact_type.py +24 -0
- wandb/sdk/artifacts/_generated/project_artifact_types.py +24 -0
- wandb/sdk/artifacts/_generated/project_artifacts.py +42 -0
- wandb/sdk/artifacts/_generated/run_input_artifacts.py +51 -0
- wandb/sdk/artifacts/_generated/run_output_artifacts.py +51 -0
- wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +35 -0
- wandb/sdk/artifacts/_generated/update_artifact_sequence.py +35 -0
- wandb/sdk/artifacts/_graphql_fragments.py +56 -79
- wandb/sdk/artifacts/artifact.py +40 -13
- wandb/sdk/artifacts/artifact_manifest_entry.py +2 -1
- wandb/sdk/artifacts/storage_handlers/azure_handler.py +1 -0
- wandb/sdk/data_types/base_types/media.py +2 -3
- wandb/sdk/data_types/base_types/wb_value.py +34 -11
- wandb/sdk/data_types/html.py +36 -9
- wandb/sdk/data_types/image.py +12 -12
- wandb/sdk/data_types/table.py +5 -0
- wandb/sdk/data_types/trace_tree.py +2 -0
- wandb/sdk/data_types/utils.py +1 -1
- wandb/sdk/data_types/video.py +14 -26
- wandb/sdk/interface/interface.py +2 -0
- wandb/sdk/internal/profiler.py +6 -5
- wandb/sdk/internal/run.py +13 -6
- wandb/sdk/lib/apikey.py +25 -4
- wandb/sdk/lib/asyncio_compat.py +1 -1
- wandb/sdk/lib/deprecate.py +13 -22
- wandb/sdk/lib/disabled.py +2 -1
- wandb/sdk/lib/printer.py +37 -8
- wandb/sdk/lib/printer_asyncio.py +46 -0
- wandb/sdk/lib/redirect.py +10 -5
- wandb/sdk/service/server_sock.py +19 -14
- wandb/sdk/service/service.py +9 -7
- wandb/sdk/service/streams.py +5 -0
- wandb/sdk/verify/verify.py +6 -3
- wandb/sdk/wandb_init.py +185 -65
- wandb/sdk/wandb_login.py +13 -4
- wandb/sdk/wandb_run.py +382 -286
- wandb/sdk/wandb_settings.py +21 -3
- wandb/sdk/wandb_setup.py +49 -0
- wandb/util.py +29 -29
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/METADATA +5 -5
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/RECORD +125 -72
- wandb/_globals.py +0 -19
- wandb/sdk/internal/_generated/base.py +0 -226
- wandb/sdk/internal/_generated/typing_compat.py +0 -14
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/WHEEL +0 -0
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/entry_points.txt +0 -0
- {wandb-0.19.9.dist-info → wandb-0.19.10.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/service/server_sock.py
CHANGED
@@ -5,6 +5,7 @@ import time
|
|
5
5
|
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional
|
6
6
|
|
7
7
|
import wandb
|
8
|
+
from wandb.proto import wandb_internal_pb2 as pb
|
8
9
|
from wandb.proto import wandb_server_pb2 as spb
|
9
10
|
from wandb.sdk.internal.settings_static import SettingsStatic
|
10
11
|
|
@@ -156,27 +157,31 @@ class SockServerReadThread(threading.Thread):
|
|
156
157
|
inform_attach_response=inform_attach_response,
|
157
158
|
)
|
158
159
|
self._sock_client.send_server_response(response)
|
159
|
-
iface = self._mux.get_stream(stream_id).interface
|
160
|
-
|
161
|
-
assert iface
|
162
160
|
|
163
161
|
def server_record_communicate(self, sreq: "spb.ServerRequest") -> None:
|
164
|
-
|
165
|
-
# encode relay information so the right socket picks up the data
|
166
|
-
record.control.relay_id = self._sock_client._sockid
|
167
|
-
stream_id = record._info.stream_id
|
168
|
-
iface = self._mux.get_stream(stream_id).interface
|
169
|
-
assert iface.record_q
|
170
|
-
iface.record_q.put(record)
|
162
|
+
self._put_record(sreq.record_communicate)
|
171
163
|
|
172
164
|
def server_record_publish(self, sreq: "spb.ServerRequest") -> None:
|
173
|
-
|
165
|
+
self._put_record(sreq.record_publish)
|
166
|
+
|
167
|
+
def _put_record(self, record: "pb.Record") -> None:
|
174
168
|
# encode relay information so the right socket picks up the data
|
175
169
|
record.control.relay_id = self._sock_client._sockid
|
176
170
|
stream_id = record._info.stream_id
|
177
|
-
|
178
|
-
|
179
|
-
|
171
|
+
|
172
|
+
try:
|
173
|
+
iface = self._mux.get_stream(stream_id).interface
|
174
|
+
|
175
|
+
except KeyError:
|
176
|
+
# We should log the error but cannot because it may print to console
|
177
|
+
# due to how logging is set up. This error usually happens if
|
178
|
+
# a record is sent when no run is active, but during this time the
|
179
|
+
# logger prints to the console.
|
180
|
+
pass
|
181
|
+
|
182
|
+
else:
|
183
|
+
assert iface.record_q
|
184
|
+
iface.record_q.put(record)
|
180
185
|
|
181
186
|
def server_inform_finish(self, sreq: "spb.ServerRequest") -> None:
|
182
187
|
request = sreq.inform_finish
|
wandb/sdk/service/service.py
CHANGED
@@ -14,10 +14,10 @@ import tempfile
|
|
14
14
|
import time
|
15
15
|
from typing import TYPE_CHECKING, Any, Dict, Optional
|
16
16
|
|
17
|
-
from wandb import _sentry
|
17
|
+
from wandb import _sentry
|
18
18
|
from wandb.env import core_debug, error_reporting_enabled, is_require_legacy_service
|
19
19
|
from wandb.errors import Error, WandbCoreNotAvailableError
|
20
|
-
from wandb.errors.
|
20
|
+
from wandb.errors.term import termlog, termwarn
|
21
21
|
from wandb.util import get_core_path, get_module
|
22
22
|
|
23
23
|
from . import _startup_debug, port_file
|
@@ -163,13 +163,15 @@ class _Service:
|
|
163
163
|
service_args.extend(["--log-level", "-4"])
|
164
164
|
|
165
165
|
exec_cmd_list = []
|
166
|
-
termlog(
|
167
|
-
"Using wandb-core as the SDK backend. Please refer to "
|
168
|
-
f"{url_registry.url('wandb-core')} for more information.",
|
169
|
-
repeat=False,
|
170
|
-
)
|
171
166
|
else:
|
172
167
|
service_args.extend(["wandb", "service", "--debug"])
|
168
|
+
termwarn(
|
169
|
+
"Using legacy-service, which is deprecated. If this is"
|
170
|
+
" unintentional, you can fix it by ensuring you do not call"
|
171
|
+
" `wandb.require('legacy-service')` and do not set the"
|
172
|
+
" WANDB_X_REQUIRE_LEGACY_SERVICE environment"
|
173
|
+
" variable."
|
174
|
+
)
|
173
175
|
|
174
176
|
service_args += [
|
175
177
|
"--port-filename",
|
wandb/sdk/service/streams.py
CHANGED
@@ -198,6 +198,11 @@ class StreamMux:
|
|
198
198
|
return stream_id in self._streams
|
199
199
|
|
200
200
|
def get_stream(self, stream_id: str) -> StreamRecord:
|
201
|
+
"""Returns the StreamRecord for the ID.
|
202
|
+
|
203
|
+
Raises:
|
204
|
+
KeyError: If a corresponding StreamRecord does not exist.
|
205
|
+
"""
|
201
206
|
with self._streams_lock:
|
202
207
|
stream = self._streams[stream_id]
|
203
208
|
return stream
|
wandb/sdk/verify/verify.py
CHANGED
@@ -132,7 +132,10 @@ def check_run(api: Api) -> bool:
|
|
132
132
|
f.close()
|
133
133
|
|
134
134
|
with wandb.init(
|
135
|
-
id=nice_id("check_run"),
|
135
|
+
id=nice_id("check_run"),
|
136
|
+
reinit=True,
|
137
|
+
config=config,
|
138
|
+
project=PROJECT_NAME,
|
136
139
|
) as run:
|
137
140
|
run_id = run.id
|
138
141
|
entity = run.entity
|
@@ -155,7 +158,7 @@ def check_run(api: Api) -> bool:
|
|
155
158
|
"Failed to log to media. Contact W&B for support."
|
156
159
|
)
|
157
160
|
|
158
|
-
|
161
|
+
run.save(filepath)
|
159
162
|
public_api = wandb.Api()
|
160
163
|
prev_run = public_api.run(f"{entity}/{PROJECT_NAME}/{run_id}")
|
161
164
|
# raise Exception(prev_run.__dict__)
|
@@ -379,7 +382,7 @@ def check_graphql_put(api: Api, host: str) -> Tuple[bool, Optional[str]]:
|
|
379
382
|
project=PROJECT_NAME,
|
380
383
|
config={"test": "put to graphql"},
|
381
384
|
) as run:
|
382
|
-
|
385
|
+
run.save(gql_fp)
|
383
386
|
public_api = wandb.Api()
|
384
387
|
prev_run = public_api.run(f"{run.entity}/{PROJECT_NAME}/{run.id}")
|
385
388
|
if prev_run is None:
|
wandb/sdk/wandb_init.py
CHANGED
@@ -21,7 +21,7 @@ import platform
|
|
21
21
|
import sys
|
22
22
|
import tempfile
|
23
23
|
import time
|
24
|
-
from typing import Any, Iterator, Literal, Sequence
|
24
|
+
from typing import TYPE_CHECKING, Any, Iterable, Iterator, Literal, Protocol, Sequence
|
25
25
|
|
26
26
|
if sys.version_info >= (3, 11):
|
27
27
|
from typing import Self
|
@@ -35,6 +35,7 @@ from wandb.errors import CommError, Error, UsageError
|
|
35
35
|
from wandb.errors.links import url_registry
|
36
36
|
from wandb.errors.util import ProtobufErrorHandler
|
37
37
|
from wandb.integration import sagemaker
|
38
|
+
from wandb.proto.wandb_deprecated import Deprecated
|
38
39
|
from wandb.sdk.lib import ipython as wb_ipython
|
39
40
|
from wandb.sdk.lib import progress, runid, wb_logging
|
40
41
|
from wandb.sdk.lib.paths import StrPath
|
@@ -43,12 +44,15 @@ from wandb.util import _is_artifact_representation
|
|
43
44
|
from . import wandb_login, wandb_setup
|
44
45
|
from .backend.backend import Backend
|
45
46
|
from .lib import SummaryDisabled, filesystem, module, paths, printer, telemetry
|
46
|
-
from .lib.deprecate import
|
47
|
+
from .lib.deprecate import deprecate
|
47
48
|
from .mailbox import wait_with_progress
|
48
49
|
from .wandb_helper import parse_config
|
49
50
|
from .wandb_run import Run, TeardownHook, TeardownStage
|
50
51
|
from .wandb_settings import Settings
|
51
52
|
|
53
|
+
if TYPE_CHECKING:
|
54
|
+
import wandb.jupyter
|
55
|
+
|
52
56
|
|
53
57
|
def _huggingface_version() -> str | None:
|
54
58
|
if "transformers" in sys.modules:
|
@@ -124,6 +128,34 @@ class _ConfigParts:
|
|
124
128
|
"""
|
125
129
|
|
126
130
|
|
131
|
+
class _PrinterCallback(Protocol):
|
132
|
+
"""A callback for displaying messages after a printer is configured.
|
133
|
+
|
134
|
+
This is used for a few messages that may be generated before run settings
|
135
|
+
are computed, which are necessary for creating a printer.
|
136
|
+
"""
|
137
|
+
|
138
|
+
def __call__(self, run_printer: printer.Printer) -> None:
|
139
|
+
"""Display information through the given printer."""
|
140
|
+
|
141
|
+
|
142
|
+
def _noop_printer_callback() -> _PrinterCallback:
|
143
|
+
"""A printer callback that does not print anything."""
|
144
|
+
return lambda _: None
|
145
|
+
|
146
|
+
|
147
|
+
def _concat_printer_callbacks(
|
148
|
+
cbs: Iterable[_PrinterCallback],
|
149
|
+
) -> _PrinterCallback:
|
150
|
+
"""Returns a printer callback that runs the given callbacks in order."""
|
151
|
+
|
152
|
+
def do_callbacks(run_printer: printer.Printer) -> None:
|
153
|
+
for cb in cbs:
|
154
|
+
cb(run_printer)
|
155
|
+
|
156
|
+
return do_callbacks
|
157
|
+
|
158
|
+
|
127
159
|
class _WandbInit:
|
128
160
|
def __init__(
|
129
161
|
self,
|
@@ -143,8 +175,7 @@ class _WandbInit:
|
|
143
175
|
self.backend: Backend | None = None
|
144
176
|
|
145
177
|
self._teardown_hooks: list[TeardownHook] = []
|
146
|
-
self.notebook: wandb.jupyter.Notebook | None = None
|
147
|
-
self.printer = printer.new_printer()
|
178
|
+
self.notebook: wandb.jupyter.Notebook | None = None
|
148
179
|
|
149
180
|
self.deprecated_features_used: dict[str, str] = dict()
|
150
181
|
|
@@ -176,20 +207,21 @@ class _WandbInit:
|
|
176
207
|
|
177
208
|
wandb_login._login(
|
178
209
|
anonymous=run_settings.anonymous,
|
210
|
+
host=run_settings.base_url,
|
179
211
|
force=run_settings.force,
|
180
212
|
_disable_warning=True,
|
181
213
|
_silent=run_settings.quiet or run_settings.silent,
|
182
214
|
)
|
183
215
|
|
184
|
-
def warn_env_vars_change_after_setup(self) ->
|
185
|
-
"""Warn if environment variables
|
216
|
+
def warn_env_vars_change_after_setup(self) -> _PrinterCallback:
|
217
|
+
"""Warn if environment variables changed after `wandb.setup()`.
|
186
218
|
|
187
|
-
|
188
|
-
|
219
|
+
Returns:
|
220
|
+
A callback to print any generated warnings.
|
189
221
|
"""
|
190
222
|
singleton = wandb_setup.singleton()
|
191
223
|
if singleton is None:
|
192
|
-
return
|
224
|
+
return _noop_printer_callback()
|
193
225
|
|
194
226
|
exclude_env_vars = {"WANDB_SERVICE", "WANDB_KUBEFLOW_URL"}
|
195
227
|
# check if environment variables have changed
|
@@ -203,26 +235,36 @@ class _WandbInit:
|
|
203
235
|
for k, v in os.environ.items()
|
204
236
|
if k.startswith("WANDB_") and k not in exclude_env_vars
|
205
237
|
}
|
206
|
-
|
207
|
-
|
208
|
-
|
238
|
+
|
239
|
+
if (
|
240
|
+
set(singleton_env.keys()) == set(os_env.keys()) #
|
241
|
+
and set(singleton_env.values()) == set(os_env.values())
|
242
|
+
):
|
243
|
+
return _noop_printer_callback()
|
244
|
+
|
245
|
+
def print_warning(run_printer: printer.Printer) -> None:
|
209
246
|
line = (
|
210
247
|
"Changes to your `wandb` environment variables will be ignored "
|
211
248
|
"because your `wandb` session has already started. "
|
212
249
|
"For more information on how to modify your settings with "
|
213
250
|
"`wandb.init()` arguments, please refer to "
|
214
|
-
f"{
|
251
|
+
f"{run_printer.link(url_registry.url('wandb-init'), 'the W&B docs')}."
|
215
252
|
)
|
216
|
-
|
253
|
+
run_printer.display(line, level="warn")
|
254
|
+
|
255
|
+
return print_warning
|
217
256
|
|
218
257
|
def clear_run_path_if_sweep_or_launch(
|
219
258
|
self,
|
220
259
|
init_settings: Settings,
|
221
|
-
) ->
|
260
|
+
) -> _PrinterCallback:
|
222
261
|
"""Clear project/entity/run_id keys if in a Sweep or a Launch context.
|
223
262
|
|
224
263
|
Args:
|
225
264
|
init_settings: Settings specified in the call to `wandb.init()`.
|
265
|
+
|
266
|
+
Returns:
|
267
|
+
A callback to print any generated warnings.
|
226
268
|
"""
|
227
269
|
when_doing_thing = ""
|
228
270
|
|
@@ -232,13 +274,12 @@ class _WandbInit:
|
|
232
274
|
when_doing_thing = "when running from a wandb launch context"
|
233
275
|
|
234
276
|
if not when_doing_thing:
|
235
|
-
return
|
277
|
+
return _noop_printer_callback()
|
278
|
+
|
279
|
+
warnings = []
|
236
280
|
|
237
281
|
def warn(key: str, value: str) -> None:
|
238
|
-
|
239
|
-
f"Ignoring {key} {value!r} {when_doing_thing}.",
|
240
|
-
level="warn",
|
241
|
-
)
|
282
|
+
warnings.append(f"Ignoring {key} {value!r} {when_doing_thing}.")
|
242
283
|
|
243
284
|
if init_settings.project is not None:
|
244
285
|
warn("project", init_settings.project)
|
@@ -250,16 +291,26 @@ class _WandbInit:
|
|
250
291
|
warn("run_id", init_settings.run_id)
|
251
292
|
init_settings.run_id = None
|
252
293
|
|
253
|
-
|
254
|
-
|
294
|
+
def print_warnings(run_printer: printer.Printer) -> None:
|
295
|
+
for warning in warnings:
|
296
|
+
run_printer.display(warning, level="warn")
|
297
|
+
|
298
|
+
return print_warnings
|
299
|
+
|
300
|
+
def make_run_settings(
|
301
|
+
self,
|
302
|
+
init_settings: Settings,
|
303
|
+
) -> tuple[Settings, _PrinterCallback]:
|
304
|
+
"""Returns the run's settings and any warnings.
|
255
305
|
|
256
306
|
Args:
|
257
307
|
init_settings: Settings passed to `wandb.init()` or set via
|
258
308
|
keyword arguments.
|
259
309
|
"""
|
260
|
-
|
261
|
-
|
262
|
-
|
310
|
+
warning_callbacks: list[_PrinterCallback] = [
|
311
|
+
self.warn_env_vars_change_after_setup(),
|
312
|
+
self.clear_run_path_if_sweep_or_launch(init_settings),
|
313
|
+
]
|
263
314
|
|
264
315
|
# Inherit global settings.
|
265
316
|
settings = self._wl.settings.model_copy()
|
@@ -305,7 +356,7 @@ class _WandbInit:
|
|
305
356
|
label = runid.generate_id()
|
306
357
|
settings.x_label = f"{prefix}-{label}" if prefix else label
|
307
358
|
|
308
|
-
return settings
|
359
|
+
return settings, _concat_printer_callbacks(warning_callbacks)
|
309
360
|
|
310
361
|
def _load_autoresume_run_id(self, resume_file: pathlib.Path) -> str | None:
|
311
362
|
"""Returns the run_id stored in the auto-resume file, if any.
|
@@ -533,62 +584,73 @@ class _WandbInit:
|
|
533
584
|
except OSError:
|
534
585
|
pass
|
535
586
|
|
536
|
-
def
|
537
|
-
|
538
|
-
|
587
|
+
def _pre_run_cell_hook(self, *args, **kwargs) -> None:
|
588
|
+
"""Hook for the IPython pre_run_cell event.
|
589
|
+
|
590
|
+
This pauses a run, preventing system metrics from being collected
|
591
|
+
the run's runtime from increasing. It also uploads the notebook's code.
|
592
|
+
"""
|
593
|
+
if not self.backend:
|
594
|
+
return
|
539
595
|
|
540
|
-
|
541
|
-
if self.notebook.save_ipynb(): # type: ignore
|
596
|
+
if self.notebook and self.notebook.save_ipynb():
|
542
597
|
assert self.run is not None
|
543
598
|
res = self.run.log_code(root=None)
|
544
|
-
self._logger.info("saved code: %s", res)
|
599
|
+
self._logger.info("saved code: %s", res)
|
600
|
+
|
545
601
|
if self.backend.interface is not None:
|
546
|
-
self._logger.info("pausing backend")
|
602
|
+
self._logger.info("pausing backend")
|
547
603
|
self.backend.interface.publish_pause()
|
548
604
|
|
549
|
-
def
|
550
|
-
|
551
|
-
|
552
|
-
|
605
|
+
def _post_run_cell_hook(self, *args, **kwargs) -> None:
|
606
|
+
"""Hook for the IPython post_run_cell event.
|
607
|
+
|
608
|
+
Resumes collection of system metrics and the run's timer.
|
609
|
+
"""
|
610
|
+
if self.backend is None or self.backend.interface is None:
|
611
|
+
return
|
612
|
+
|
613
|
+
self._logger.info("resuming backend")
|
614
|
+
self.backend.interface.publish_resume()
|
553
615
|
|
554
616
|
def _jupyter_teardown(self) -> None:
|
555
617
|
"""Teardown hooks and display saving, called with wandb.finish."""
|
556
618
|
assert self.notebook
|
557
619
|
ipython = self.notebook.shell
|
558
|
-
|
620
|
+
|
621
|
+
if self.run:
|
622
|
+
self.notebook.save_history(self.run)
|
623
|
+
|
559
624
|
if self.notebook.save_ipynb():
|
560
625
|
assert self.run is not None
|
561
626
|
res = self.run.log_code(root=None)
|
562
|
-
self._logger.info("saved code and history: %s", res)
|
563
|
-
self._logger.info("cleaning up jupyter logic")
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
for hook in ipython.events.callbacks["post_run_cell"]:
|
569
|
-
if "_pause_backend" in hook.__name__:
|
570
|
-
ipython.events.unregister("post_run_cell", hook)
|
627
|
+
self._logger.info("saved code and history: %s", res)
|
628
|
+
self._logger.info("cleaning up jupyter logic")
|
629
|
+
|
630
|
+
ipython.events.unregister("pre_run_cell", self._pre_run_cell_hook)
|
631
|
+
ipython.events.unregister("post_run_cell", self._post_run_cell_hook)
|
632
|
+
|
571
633
|
ipython.display_pub.publish = ipython.display_pub._orig_publish
|
572
634
|
del ipython.display_pub._orig_publish
|
573
635
|
|
574
636
|
def monkeypatch_ipython(self, settings: Settings) -> None:
|
575
637
|
"""Add hooks, and session history saving."""
|
576
|
-
self.notebook = wandb.jupyter.Notebook(settings)
|
638
|
+
self.notebook = wandb.jupyter.Notebook(settings)
|
577
639
|
ipython = self.notebook.shell
|
578
640
|
|
579
641
|
# Monkey patch ipython publish to capture displayed outputs
|
580
642
|
if not hasattr(ipython.display_pub, "_orig_publish"):
|
581
|
-
self._logger.info("configuring jupyter hooks %s", self)
|
643
|
+
self._logger.info("configuring jupyter hooks %s", self)
|
582
644
|
ipython.display_pub._orig_publish = ipython.display_pub.publish
|
583
|
-
# Registering resume and pause hooks
|
584
645
|
|
585
|
-
ipython.events.register("pre_run_cell", self.
|
586
|
-
ipython.events.register("post_run_cell", self.
|
646
|
+
ipython.events.register("pre_run_cell", self._pre_run_cell_hook)
|
647
|
+
ipython.events.register("post_run_cell", self._post_run_cell_hook)
|
648
|
+
|
587
649
|
self._teardown_hooks.append(
|
588
650
|
TeardownHook(self._jupyter_teardown, TeardownStage.EARLY)
|
589
651
|
)
|
590
652
|
|
591
|
-
def publish(data, metadata=None, **kwargs) -> None:
|
653
|
+
def publish(data, metadata=None, **kwargs) -> None:
|
592
654
|
ipython.display_pub._orig_publish(data, metadata=metadata, **kwargs)
|
593
655
|
assert self.notebook is not None
|
594
656
|
self.notebook.save_display(
|
@@ -729,6 +791,10 @@ class _WandbInit:
|
|
729
791
|
):
|
730
792
|
setattr(drun, symbol, lambda *_, **__: None) # type: ignore
|
731
793
|
|
794
|
+
# set properties to None
|
795
|
+
for attr in ("url", "project_url", "sweep_url"):
|
796
|
+
setattr(type(drun), attr, property(lambda _: None))
|
797
|
+
|
732
798
|
class _ChainableNoOp:
|
733
799
|
"""An object that allows chaining arbitrary attributes and method calls."""
|
734
800
|
|
@@ -753,7 +819,7 @@ class _WandbInit:
|
|
753
819
|
def __call__(self, *args: Any, **kwargs: Any) -> _ChainableNoOp:
|
754
820
|
return _ChainableNoOp()
|
755
821
|
|
756
|
-
drun.log_artifact = _ChainableNoOpField() # type: ignore
|
822
|
+
drun.log_artifact = _ChainableNoOpField() # type: ignore
|
757
823
|
# attributes
|
758
824
|
drun._start_time = time.time()
|
759
825
|
drun._starting_step = 0
|
@@ -777,7 +843,12 @@ class _WandbInit:
|
|
777
843
|
)
|
778
844
|
return drun
|
779
845
|
|
780
|
-
def init(
|
846
|
+
def init( # noqa: C901
|
847
|
+
self,
|
848
|
+
settings: Settings,
|
849
|
+
config: _ConfigParts,
|
850
|
+
run_printer: printer.Printer,
|
851
|
+
) -> Run:
|
781
852
|
self._logger.info("calling init triggers")
|
782
853
|
trigger.call("on_init")
|
783
854
|
|
@@ -788,23 +859,36 @@ class _WandbInit:
|
|
788
859
|
f"\nconfig: {config.base_no_artifacts}"
|
789
860
|
)
|
790
861
|
|
791
|
-
if
|
862
|
+
if previous_run := self._wl.most_recent_active_run:
|
792
863
|
if (
|
793
864
|
settings.reinit in (True, "finish_previous")
|
794
865
|
# calling wandb.init() in notebooks finishes previous runs
|
795
866
|
# by default for user convenience.
|
796
867
|
or (settings.reinit == "default" and wb_ipython.in_notebook())
|
797
868
|
):
|
798
|
-
|
799
|
-
|
869
|
+
run_printer.display(
|
870
|
+
"Finishing previous runs because reinit is set"
|
871
|
+
f" to {settings.reinit!r}."
|
872
|
+
)
|
873
|
+
self._wl.finish_all_active_runs()
|
874
|
+
|
875
|
+
elif settings.reinit == "create_new":
|
876
|
+
self._logger.info(
|
877
|
+
"wandb.init() called while a run is active,"
|
878
|
+
" and reinit is set to 'create_new', so continuing"
|
879
|
+
)
|
880
|
+
|
800
881
|
else:
|
801
|
-
|
882
|
+
run_printer.display(
|
883
|
+
"wandb.init() called while a run is active and reinit is"
|
884
|
+
f" set to {settings.reinit!r}, so returning the previous"
|
885
|
+
" run."
|
886
|
+
)
|
802
887
|
|
803
|
-
|
804
|
-
with telemetry.context() as tel:
|
888
|
+
with telemetry.context(run=previous_run) as tel:
|
805
889
|
tel.feature.init_return_run = True
|
806
890
|
|
807
|
-
return
|
891
|
+
return previous_run
|
808
892
|
|
809
893
|
self._logger.info("starting backend")
|
810
894
|
|
@@ -897,6 +981,9 @@ class _WandbInit:
|
|
897
981
|
)
|
898
982
|
tel.feature.shared_mode = True
|
899
983
|
|
984
|
+
if settings.x_label:
|
985
|
+
tel.feature.user_provided_label = True
|
986
|
+
|
900
987
|
tel.env.maybe_mp = _maybe_mp_process(backend)
|
901
988
|
|
902
989
|
if not settings.label_disable:
|
@@ -946,7 +1033,7 @@ class _WandbInit:
|
|
946
1033
|
assert backend.interface
|
947
1034
|
|
948
1035
|
with progress.progress_printer(
|
949
|
-
|
1036
|
+
run_printer,
|
950
1037
|
default_text="Waiting for wandb.init()...",
|
951
1038
|
) as progress_printer:
|
952
1039
|
await progress.loop_printing_operation_stats(
|
@@ -1052,6 +1139,10 @@ class _WandbInit:
|
|
1052
1139
|
run.use_artifact(job_artifact)
|
1053
1140
|
|
1054
1141
|
self.backend = backend
|
1142
|
+
|
1143
|
+
if settings.reinit != "create_new":
|
1144
|
+
_set_global_run(run)
|
1145
|
+
|
1055
1146
|
run._on_start()
|
1056
1147
|
self._logger.info("run started, returning control to user process")
|
1057
1148
|
return run
|
@@ -1128,10 +1219,36 @@ def _attach(
|
|
1128
1219
|
raise UsageError(f"Failed to attach to run: {attach_response.error.message}")
|
1129
1220
|
|
1130
1221
|
run._set_run_obj(attach_response.run)
|
1222
|
+
_set_global_run(run)
|
1131
1223
|
run._on_attach()
|
1132
1224
|
return run
|
1133
1225
|
|
1134
1226
|
|
1227
|
+
def _set_global_run(run: Run) -> None:
|
1228
|
+
"""Set `wandb.run` and point some top-level functions to its methods.
|
1229
|
+
|
1230
|
+
Args:
|
1231
|
+
run: The run to make global.
|
1232
|
+
"""
|
1233
|
+
module.set_global(
|
1234
|
+
run=run,
|
1235
|
+
config=run.config,
|
1236
|
+
log=run.log,
|
1237
|
+
summary=run.summary,
|
1238
|
+
save=run.save,
|
1239
|
+
use_artifact=run.use_artifact,
|
1240
|
+
log_artifact=run.log_artifact,
|
1241
|
+
define_metric=run.define_metric,
|
1242
|
+
alert=run.alert,
|
1243
|
+
watch=run.watch,
|
1244
|
+
unwatch=run.unwatch,
|
1245
|
+
mark_preempting=run.mark_preempting,
|
1246
|
+
log_model=run.log_model,
|
1247
|
+
use_model=run.use_model,
|
1248
|
+
link_model=run.link_model,
|
1249
|
+
)
|
1250
|
+
|
1251
|
+
|
1135
1252
|
def _monkeypatch_openai_gym() -> None:
|
1136
1253
|
"""Patch OpenAI gym to log to the global `wandb.run`."""
|
1137
1254
|
if len(wandb.patched["gym"]) > 0:
|
@@ -1199,6 +1316,7 @@ def init( # noqa: C901
|
|
1199
1316
|
"default",
|
1200
1317
|
"return_previous",
|
1201
1318
|
"finish_previous",
|
1319
|
+
"create_new",
|
1202
1320
|
]
|
1203
1321
|
) = None,
|
1204
1322
|
resume: bool | Literal["allow", "never", "must", "auto"] | None = None,
|
@@ -1476,7 +1594,7 @@ def init( # noqa: C901
|
|
1476
1594
|
wi = _WandbInit(wl, init_telemetry)
|
1477
1595
|
|
1478
1596
|
wi.maybe_login(init_settings)
|
1479
|
-
run_settings = wi.make_run_settings(init_settings)
|
1597
|
+
run_settings, show_warnings = wi.make_run_settings(init_settings)
|
1480
1598
|
|
1481
1599
|
if isinstance(run_settings.reinit, bool):
|
1482
1600
|
wi.deprecated_features_used["run__reinit_bool"] = (
|
@@ -1494,6 +1612,8 @@ def init( # noqa: C901
|
|
1494
1612
|
init_telemetry.feature.offline = True
|
1495
1613
|
|
1496
1614
|
wi.set_run_id(run_settings)
|
1615
|
+
run_printer = printer.new_printer(run_settings)
|
1616
|
+
show_warnings(run_printer)
|
1497
1617
|
|
1498
1618
|
with contextlib.ExitStack() as exit_stack:
|
1499
1619
|
exit_stack.enter_context(wb_logging.log_to_run(run_settings.run_id))
|
@@ -1527,7 +1647,7 @@ def init( # noqa: C901
|
|
1527
1647
|
if run_settings.x_server_side_derived_summary:
|
1528
1648
|
init_telemetry.feature.server_side_derived_summary = True
|
1529
1649
|
|
1530
|
-
return wi.init(run_settings, run_config)
|
1650
|
+
return wi.init(run_settings, run_config, run_printer)
|
1531
1651
|
|
1532
1652
|
except KeyboardInterrupt as e:
|
1533
1653
|
if wl:
|
wandb/sdk/wandb_login.py
CHANGED
@@ -45,6 +45,7 @@ def login(
|
|
45
45
|
force: Optional[bool] = None,
|
46
46
|
timeout: Optional[int] = None,
|
47
47
|
verify: bool = False,
|
48
|
+
referrer: Optional[str] = None,
|
48
49
|
) -> bool:
|
49
50
|
"""Set up W&B login credentials.
|
50
51
|
|
@@ -64,6 +65,7 @@ def login(
|
|
64
65
|
force: (bool, optional) If true, will force a relogin.
|
65
66
|
timeout: (int, optional) Number of seconds to wait for user input.
|
66
67
|
verify: (bool) Verify the credentials with the W&B server.
|
68
|
+
referrer: (string, optional) The referrer to use in the URL login request.
|
67
69
|
|
68
70
|
Returns:
|
69
71
|
bool: if key is configured
|
@@ -81,6 +83,7 @@ def login(
|
|
81
83
|
force=force,
|
82
84
|
timeout=timeout,
|
83
85
|
verify=verify,
|
86
|
+
referrer=referrer,
|
84
87
|
)
|
85
88
|
|
86
89
|
|
@@ -199,7 +202,9 @@ class _WandbLogin:
|
|
199
202
|
if not self._wandb_setup.settings._offline:
|
200
203
|
self._wandb_setup._update_user_settings()
|
201
204
|
|
202
|
-
def _prompt_api_key(
|
205
|
+
def _prompt_api_key(
|
206
|
+
self, referrer: Optional[str] = None
|
207
|
+
) -> Tuple[Optional[str], ApiKeyStatus]:
|
203
208
|
api = Api(self._settings)
|
204
209
|
while True:
|
205
210
|
try:
|
@@ -208,6 +213,7 @@ class _WandbLogin:
|
|
208
213
|
api=api,
|
209
214
|
no_offline=self._settings.force if self._settings else None,
|
210
215
|
no_create=self._settings.force if self._settings else None,
|
216
|
+
referrer=referrer,
|
211
217
|
)
|
212
218
|
except ValueError as e:
|
213
219
|
# invalid key provided, try again
|
@@ -222,9 +228,11 @@ class _WandbLogin:
|
|
222
228
|
return None, ApiKeyStatus.OFFLINE
|
223
229
|
return key, ApiKeyStatus.VALID
|
224
230
|
|
225
|
-
def prompt_api_key(
|
231
|
+
def prompt_api_key(
|
232
|
+
self, referrer: Optional[str] = None
|
233
|
+
) -> Tuple[Optional[str], ApiKeyStatus]:
|
226
234
|
"""Updates the global API key by prompting the user."""
|
227
|
-
key, status = self._prompt_api_key()
|
235
|
+
key, status = self._prompt_api_key(referrer)
|
228
236
|
if status == ApiKeyStatus.NOTTY:
|
229
237
|
directive = (
|
230
238
|
"wandb login [your_api_key]"
|
@@ -262,6 +270,7 @@ def _login(
|
|
262
270
|
force: Optional[bool] = None,
|
263
271
|
timeout: Optional[int] = None,
|
264
272
|
verify: bool = False,
|
273
|
+
referrer: str = "models",
|
265
274
|
_silent: Optional[bool] = None,
|
266
275
|
_disable_warning: Optional[bool] = None,
|
267
276
|
) -> bool:
|
@@ -302,7 +311,7 @@ def _login(
|
|
302
311
|
if key and not relogin:
|
303
312
|
key_is_pre_configured = True
|
304
313
|
else:
|
305
|
-
key, key_status = wlogin.prompt_api_key()
|
314
|
+
key, key_status = wlogin.prompt_api_key(referrer=referrer)
|
306
315
|
|
307
316
|
if verify:
|
308
317
|
wlogin._verify_login(key)
|