wandb 0.21.1__py3-none-win_amd64.whl → 0.21.3__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.
- wandb/__init__.py +1 -1
- wandb/__init__.pyi +1 -1
- wandb/apis/public/api.py +1 -2
- wandb/apis/public/artifacts.py +3 -5
- wandb/apis/public/registries/_utils.py +14 -16
- wandb/apis/public/registries/registries_search.py +176 -289
- wandb/apis/public/reports.py +13 -10
- wandb/automations/_generated/delete_automation.py +1 -3
- wandb/automations/_generated/enums.py +13 -11
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +47 -2
- wandb/integration/metaflow/data_pandas.py +2 -2
- wandb/integration/metaflow/data_pytorch.py +75 -0
- wandb/integration/metaflow/data_sklearn.py +76 -0
- wandb/integration/metaflow/metaflow.py +16 -87
- wandb/integration/weave/__init__.py +6 -0
- wandb/integration/weave/interface.py +49 -0
- wandb/integration/weave/weave.py +63 -0
- wandb/proto/v3/wandb_internal_pb2.py +3 -2
- wandb/proto/v4/wandb_internal_pb2.py +2 -2
- wandb/proto/v5/wandb_internal_pb2.py +2 -2
- wandb/proto/v6/wandb_internal_pb2.py +2 -2
- wandb/sdk/artifacts/_factories.py +17 -0
- wandb/sdk/artifacts/_generated/__init__.py +221 -13
- wandb/sdk/artifacts/_generated/artifact_by_id.py +17 -0
- wandb/sdk/artifacts/_generated/artifact_by_name.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_created_by.py +47 -0
- wandb/sdk/artifacts/_generated/artifact_file_urls.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_type.py +31 -0
- wandb/sdk/artifacts/_generated/artifact_used_by.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +26 -0
- wandb/sdk/artifacts/_generated/delete_artifact.py +28 -0
- wandb/sdk/artifacts/_generated/enums.py +5 -0
- wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +38 -0
- wandb/sdk/artifacts/_generated/fetch_registries.py +32 -0
- wandb/sdk/artifacts/_generated/fragments.py +279 -41
- wandb/sdk/artifacts/_generated/link_artifact.py +6 -0
- wandb/sdk/artifacts/_generated/operations.py +654 -51
- wandb/sdk/artifacts/_generated/registry_collections.py +34 -0
- wandb/sdk/artifacts/_generated/registry_versions.py +34 -0
- wandb/sdk/artifacts/_generated/unlink_artifact.py +25 -0
- wandb/sdk/artifacts/_graphql_fragments.py +3 -86
- wandb/sdk/artifacts/_validators.py +6 -4
- wandb/sdk/artifacts/artifact.py +410 -547
- wandb/sdk/artifacts/artifact_file_cache.py +11 -7
- wandb/sdk/artifacts/artifact_manifest.py +10 -9
- wandb/sdk/artifacts/artifact_manifest_entry.py +15 -18
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +5 -3
- wandb/sdk/artifacts/storage_handlers/gcs_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/http_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +1 -1
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +1 -1
- wandb/sdk/data_types/video.py +2 -2
- wandb/sdk/interface/interface_queue.py +1 -4
- wandb/sdk/interface/interface_shared.py +26 -37
- wandb/sdk/interface/interface_sock.py +24 -14
- wandb/sdk/internal/settings_static.py +2 -3
- wandb/sdk/launch/create_job.py +12 -1
- wandb/sdk/launch/inputs/internal.py +25 -24
- wandb/sdk/launch/inputs/schema.py +31 -1
- wandb/sdk/launch/runner/kubernetes_runner.py +24 -29
- wandb/sdk/lib/asyncio_compat.py +16 -16
- wandb/sdk/lib/asyncio_manager.py +252 -0
- wandb/sdk/lib/hashutil.py +13 -4
- wandb/sdk/lib/paths.py +23 -21
- wandb/sdk/lib/printer.py +2 -2
- wandb/sdk/lib/printer_asyncio.py +3 -1
- wandb/sdk/lib/retry.py +185 -78
- wandb/sdk/lib/service/service_client.py +106 -0
- wandb/sdk/lib/service/service_connection.py +20 -26
- wandb/sdk/lib/service/service_token.py +30 -13
- wandb/sdk/mailbox/mailbox.py +13 -5
- wandb/sdk/mailbox/mailbox_handle.py +22 -13
- wandb/sdk/mailbox/response_handle.py +42 -106
- wandb/sdk/mailbox/wait_with_progress.py +7 -42
- wandb/sdk/wandb_init.py +11 -25
- wandb/sdk/wandb_login.py +1 -1
- wandb/sdk/wandb_run.py +92 -56
- wandb/sdk/wandb_settings.py +45 -32
- wandb/sdk/wandb_setup.py +176 -96
- wandb/util.py +1 -1
- {wandb-0.21.1.dist-info → wandb-0.21.3.dist-info}/METADATA +2 -2
- {wandb-0.21.1.dist-info → wandb-0.21.3.dist-info}/RECORD +88 -72
- wandb/sdk/interface/interface_relay.py +0 -38
- wandb/sdk/interface/router.py +0 -89
- wandb/sdk/interface/router_queue.py +0 -43
- wandb/sdk/interface/router_relay.py +0 -50
- wandb/sdk/interface/router_sock.py +0 -32
- wandb/sdk/lib/sock_client.py +0 -232
- {wandb-0.21.1.dist-info → wandb-0.21.3.dist-info}/WHEEL +0 -0
- {wandb-0.21.1.dist-info → wandb-0.21.3.dist-info}/entry_points.txt +0 -0
- {wandb-0.21.1.dist-info → wandb-0.21.3.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/wandb_setup.py
CHANGED
@@ -28,12 +28,13 @@ import logging
|
|
28
28
|
import os
|
29
29
|
import pathlib
|
30
30
|
import sys
|
31
|
+
import threading
|
31
32
|
from typing import TYPE_CHECKING, Any, Union
|
32
33
|
|
33
34
|
import wandb
|
34
35
|
import wandb.integration.sagemaker as sagemaker
|
35
36
|
from wandb.env import CONFIG_DIR
|
36
|
-
from wandb.sdk.lib import import_hooks, wb_logging
|
37
|
+
from wandb.sdk.lib import asyncio_manager, import_hooks, wb_logging
|
37
38
|
|
38
39
|
from . import wandb_settings
|
39
40
|
from .lib import config_util, server
|
@@ -88,19 +89,16 @@ Logger = Union[logging.Logger, _EarlyLogger]
|
|
88
89
|
class _WandbSetup:
|
89
90
|
"""W&B library singleton."""
|
90
91
|
|
91
|
-
def __init__(
|
92
|
-
self
|
93
|
-
|
94
|
-
|
95
|
-
environ: dict | None = None,
|
96
|
-
) -> None:
|
92
|
+
def __init__(self, pid: int) -> None:
|
93
|
+
self._asyncer = asyncio_manager.AsyncioManager()
|
94
|
+
self._asyncer.start()
|
95
|
+
|
97
96
|
self._connection: ServiceConnection | None = None
|
98
97
|
|
99
98
|
self._active_runs: list[wandb_run.Run] = []
|
99
|
+
self._active_runs_lock = threading.Lock()
|
100
100
|
|
101
|
-
self._environ = environ or dict(os.environ)
|
102
101
|
self._sweep_config: dict | None = None
|
103
|
-
self._config: dict | None = None
|
104
102
|
self._server: server.Server | None = None
|
105
103
|
self._pid = pid
|
106
104
|
|
@@ -108,11 +106,13 @@ class _WandbSetup:
|
|
108
106
|
# and logging is ready
|
109
107
|
self._logger: Logger = _EarlyLogger()
|
110
108
|
|
111
|
-
self._settings =
|
109
|
+
self._settings: Settings | None = None
|
110
|
+
self._settings_environ: dict[str, str] | None = None
|
112
111
|
|
113
|
-
|
114
|
-
|
115
|
-
|
112
|
+
@property
|
113
|
+
def asyncer(self) -> asyncio_manager.AsyncioManager:
|
114
|
+
"""The internal asyncio thread used by wandb."""
|
115
|
+
return self._asyncer
|
116
116
|
|
117
117
|
def add_active_run(self, run: wandb_run.Run) -> None:
|
118
118
|
"""Append a run to the active runs list.
|
@@ -122,8 +122,9 @@ class _WandbSetup:
|
|
122
122
|
Args:
|
123
123
|
run: A newly initialized run.
|
124
124
|
"""
|
125
|
-
|
126
|
-
self._active_runs
|
125
|
+
with self._active_runs_lock:
|
126
|
+
if run not in self._active_runs:
|
127
|
+
self._active_runs.append(run)
|
127
128
|
|
128
129
|
def remove_active_run(self, run: wandb_run.Run) -> None:
|
129
130
|
"""Remove the run from the active runs list.
|
@@ -134,17 +135,19 @@ class _WandbSetup:
|
|
134
135
|
run: A run that is finished or crashed.
|
135
136
|
"""
|
136
137
|
try:
|
137
|
-
self.
|
138
|
+
with self._active_runs_lock:
|
139
|
+
self._active_runs.remove(run)
|
138
140
|
except ValueError:
|
139
141
|
pass # Removing a run multiple times is not an error.
|
140
142
|
|
141
143
|
@property
|
142
144
|
def most_recent_active_run(self) -> wandb_run.Run | None:
|
143
145
|
"""The most recently initialized run that is not yet finished."""
|
144
|
-
|
145
|
-
|
146
|
+
with self._active_runs_lock:
|
147
|
+
if not self._active_runs:
|
148
|
+
return None
|
146
149
|
|
147
|
-
|
150
|
+
return self._active_runs[-1]
|
148
151
|
|
149
152
|
def finish_all_active_runs(self) -> None:
|
150
153
|
"""Finish all unfinished runs.
|
@@ -156,74 +159,131 @@ class _WandbSetup:
|
|
156
159
|
default and only behavior, it does not seem worth optimizing.
|
157
160
|
"""
|
158
161
|
# Take a snapshot as each call to `finish()` modifies `_active_runs`.
|
159
|
-
|
162
|
+
with self._active_runs_lock:
|
163
|
+
runs_copy = list(self._active_runs)
|
164
|
+
|
160
165
|
for run in runs_copy:
|
161
166
|
run.finish()
|
162
167
|
|
163
|
-
def
|
168
|
+
def did_environment_change(self) -> bool:
|
169
|
+
"""Check if os.environ has changed since settings were initialized."""
|
170
|
+
if not self._settings_environ:
|
171
|
+
return False
|
172
|
+
|
173
|
+
exclude_env_vars = {"WANDB_SERVICE", "WANDB_KUBEFLOW_URL"}
|
174
|
+
singleton_env = {
|
175
|
+
k: v
|
176
|
+
for k, v in self._settings_environ.items()
|
177
|
+
if k.startswith("WANDB_") and k not in exclude_env_vars
|
178
|
+
}
|
179
|
+
os_env = {
|
180
|
+
k: v
|
181
|
+
for k, v in os.environ.items()
|
182
|
+
if k.startswith("WANDB_") and k not in exclude_env_vars
|
183
|
+
}
|
184
|
+
|
185
|
+
return (
|
186
|
+
set(singleton_env.keys()) != set(os_env.keys()) #
|
187
|
+
or set(singleton_env.values()) != set(os_env.values())
|
188
|
+
)
|
189
|
+
|
190
|
+
def _load_settings(
|
164
191
|
self,
|
165
|
-
|
166
|
-
|
167
|
-
|
192
|
+
*,
|
193
|
+
system_settings_path: str | None,
|
194
|
+
disable_sagemaker: bool,
|
195
|
+
overrides: Settings | None = None,
|
196
|
+
) -> None:
|
197
|
+
"""Load settings from environment variables, config files, etc.
|
198
|
+
|
199
|
+
Args:
|
200
|
+
system_settings_path: Location of system settings file to use.
|
201
|
+
If not provided, reads the WANDB_CONFIG_DIR environment
|
202
|
+
variable or uses the default location.
|
203
|
+
disable_sagemaker: If true, skips modifying settings based on
|
204
|
+
SageMaker.
|
205
|
+
overrides: Additional settings to apply to the global settings.
|
206
|
+
"""
|
207
|
+
self._settings = wandb_settings.Settings()
|
168
208
|
|
169
209
|
# the pid of the process to monitor for system stats
|
170
210
|
pid = os.getpid()
|
171
211
|
self._logger.info(f"Current SDK version is {wandb.__version__}")
|
172
212
|
self._logger.info(f"Configure stats pid to {pid}")
|
173
|
-
|
213
|
+
self._settings.x_stats_pid = pid
|
174
214
|
|
175
|
-
if
|
176
|
-
|
215
|
+
if system_settings_path:
|
216
|
+
self._settings.settings_system = system_settings_path
|
177
217
|
elif config_dir_str := os.getenv(CONFIG_DIR, None):
|
178
218
|
config_dir = pathlib.Path(config_dir_str).expanduser()
|
179
|
-
|
219
|
+
self._settings.settings_system = str(config_dir / "settings")
|
180
220
|
else:
|
181
|
-
|
221
|
+
self._settings.settings_system = str(
|
182
222
|
pathlib.Path("~", ".config", "wandb", "settings").expanduser()
|
183
223
|
)
|
184
224
|
|
185
225
|
# load settings from the system config
|
186
|
-
if
|
187
|
-
self._logger.info(
|
188
|
-
|
226
|
+
if self._settings.settings_system:
|
227
|
+
self._logger.info(
|
228
|
+
f"Loading settings from {self._settings.settings_system}",
|
229
|
+
)
|
230
|
+
self._settings.update_from_system_config_file()
|
189
231
|
|
190
232
|
# load settings from the workspace config
|
191
|
-
if
|
192
|
-
self._logger.info(
|
193
|
-
|
233
|
+
if self._settings.settings_workspace:
|
234
|
+
self._logger.info(
|
235
|
+
f"Loading settings from {self._settings.settings_workspace}",
|
236
|
+
)
|
237
|
+
self._settings.update_from_workspace_config_file()
|
194
238
|
|
195
239
|
# load settings from the environment variables
|
196
240
|
self._logger.info("Loading settings from environment variables")
|
197
|
-
|
241
|
+
self._settings_environ = os.environ.copy()
|
242
|
+
self._settings.update_from_env_vars(self._settings_environ)
|
198
243
|
|
199
244
|
# infer settings from the system environment
|
200
|
-
|
245
|
+
self._settings.update_from_system_environment()
|
201
246
|
|
202
247
|
# load SageMaker settings
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
248
|
+
if (
|
249
|
+
not self._settings.sagemaker_disable
|
250
|
+
and not disable_sagemaker
|
251
|
+
and sagemaker.is_using_sagemaker()
|
252
|
+
):
|
207
253
|
self._logger.info("Loading SageMaker settings")
|
208
|
-
sagemaker.set_global_settings(
|
254
|
+
sagemaker.set_global_settings(self._settings)
|
209
255
|
|
210
256
|
# load settings from the passed init/setup settings
|
211
|
-
if
|
212
|
-
|
257
|
+
if overrides:
|
258
|
+
self._settings.update_from_settings(overrides)
|
213
259
|
|
214
|
-
|
260
|
+
wandb.termsetup(self._settings, None)
|
215
261
|
|
216
|
-
def _update(self, settings: Settings | None
|
217
|
-
if
|
218
|
-
return
|
219
|
-
self._settings.update_from_settings(settings)
|
262
|
+
def _update(self, settings: Settings | None) -> None:
|
263
|
+
"""Update settings, initializing them if necessary.
|
220
264
|
|
221
|
-
|
265
|
+
Args:
|
266
|
+
settings: Overrides to apply, if any.
|
267
|
+
"""
|
268
|
+
if not self._settings:
|
269
|
+
system_settings_path = settings.settings_system if settings else None
|
270
|
+
disable_sagemaker = settings.sagemaker_disable if settings else False
|
271
|
+
self._load_settings(
|
272
|
+
system_settings_path=system_settings_path,
|
273
|
+
disable_sagemaker=disable_sagemaker,
|
274
|
+
overrides=settings,
|
275
|
+
)
|
276
|
+
|
277
|
+
# This is 'elif' because load_settings already applies overrides.
|
278
|
+
elif settings:
|
279
|
+
self._settings.update_from_settings(settings)
|
280
|
+
|
281
|
+
def update_user_settings(self) -> None:
|
222
282
|
# Get rid of cached results to force a refresh.
|
223
283
|
self._server = None
|
224
284
|
user_settings = self._load_user_settings()
|
225
285
|
if user_settings is not None:
|
226
|
-
self.
|
286
|
+
self.settings.update_from_dict(user_settings)
|
227
287
|
|
228
288
|
def _early_logger_flush(self, new_logger: Logger) -> None:
|
229
289
|
if self._logger is new_logger:
|
@@ -238,6 +298,22 @@ class _WandbSetup:
|
|
238
298
|
|
239
299
|
@property
|
240
300
|
def settings(self) -> wandb_settings.Settings:
|
301
|
+
"""The global wandb settings.
|
302
|
+
|
303
|
+
Initializes settings if they have not yet been loaded.
|
304
|
+
"""
|
305
|
+
if not self._settings:
|
306
|
+
self._load_settings(
|
307
|
+
system_settings_path=None,
|
308
|
+
disable_sagemaker=False,
|
309
|
+
)
|
310
|
+
assert self._settings
|
311
|
+
|
312
|
+
return self._settings
|
313
|
+
|
314
|
+
@property
|
315
|
+
def settings_if_loaded(self) -> wandb_settings.Settings | None:
|
316
|
+
"""The global wandb settings, or None if not yet loaded."""
|
241
317
|
return self._settings
|
242
318
|
|
243
319
|
def _get_entity(self) -> str | None:
|
@@ -262,7 +338,7 @@ class _WandbSetup:
|
|
262
338
|
@property
|
263
339
|
def viewer(self) -> dict[str, Any]:
|
264
340
|
if self._server is None:
|
265
|
-
self._server = server.Server(settings=self.
|
341
|
+
self._server = server.Server(settings=self.settings)
|
266
342
|
|
267
343
|
return self._server.viewer
|
268
344
|
|
@@ -282,36 +358,36 @@ class _WandbSetup:
|
|
282
358
|
|
283
359
|
return user_settings
|
284
360
|
|
285
|
-
|
286
|
-
|
361
|
+
@property
|
362
|
+
def config(self) -> dict:
|
363
|
+
sweep_path = self.settings.sweep_param_path
|
287
364
|
if sweep_path:
|
288
365
|
self._sweep_config = config_util.dict_from_config_file(
|
289
366
|
sweep_path, must_exist=True
|
290
367
|
)
|
291
368
|
|
369
|
+
config = {}
|
370
|
+
|
292
371
|
# if config_paths was set, read in config dict
|
293
|
-
if self.
|
372
|
+
if self.settings.config_paths:
|
294
373
|
# TODO(jhr): handle load errors, handle list of files
|
295
|
-
for config_path in self.
|
374
|
+
for config_path in self.settings.config_paths:
|
296
375
|
config_dict = config_util.dict_from_config_file(config_path)
|
297
|
-
if config_dict
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
else:
|
302
|
-
self._config = config_dict
|
376
|
+
if config_dict:
|
377
|
+
config.update(config_dict)
|
378
|
+
|
379
|
+
return config
|
303
380
|
|
304
381
|
def _teardown(self, exit_code: int | None = None) -> None:
|
305
382
|
import_hooks.unregister_all_post_import_hooks()
|
306
383
|
|
307
|
-
if
|
308
|
-
|
384
|
+
if self._connection:
|
385
|
+
internal_exit_code = self._connection.teardown(exit_code or 0)
|
386
|
+
else:
|
387
|
+
internal_exit_code = None
|
309
388
|
|
310
|
-
|
311
|
-
connection = self._connection
|
312
|
-
self._connection = None
|
389
|
+
self._asyncer.join()
|
313
390
|
|
314
|
-
internal_exit_code = connection.teardown(exit_code or 0)
|
315
391
|
if internal_exit_code not in (None, 0):
|
316
392
|
sys.exit(internal_exit_code)
|
317
393
|
|
@@ -322,7 +398,10 @@ class _WandbSetup:
|
|
322
398
|
|
323
399
|
from wandb.sdk.lib.service import service_connection
|
324
400
|
|
325
|
-
self._connection = service_connection.connect_to_service(
|
401
|
+
self._connection = service_connection.connect_to_service(
|
402
|
+
self._asyncer,
|
403
|
+
self.settings,
|
404
|
+
)
|
326
405
|
return self._connection
|
327
406
|
|
328
407
|
def assert_service(self) -> ServiceConnection:
|
@@ -343,6 +422,8 @@ _singleton: _WandbSetup | None = None
|
|
343
422
|
The value is invalid and must not be used if `os.getpid() != _singleton._pid`.
|
344
423
|
"""
|
345
424
|
|
425
|
+
_singleton_lock = threading.Lock()
|
426
|
+
|
346
427
|
|
347
428
|
def singleton() -> _WandbSetup:
|
348
429
|
"""The W&B singleton for the current process.
|
@@ -351,29 +432,14 @@ def singleton() -> _WandbSetup:
|
|
351
432
|
process) creates the singleton, and all subsequent calls return it
|
352
433
|
until teardown(). This does not start the service process.
|
353
434
|
"""
|
354
|
-
return _setup(start_service=False)
|
355
|
-
|
356
|
-
|
357
|
-
def singleton_if_setup() -> _WandbSetup | None:
|
358
|
-
"""The W&B singleton for the current process or None if it isn't set up.
|
359
|
-
|
360
|
-
Always prefer singleton() over this function.
|
361
|
-
|
362
|
-
Unlike singleton(), this never creates the singleton and therefore never
|
363
|
-
initializes global settings from the environment. This is useful only
|
364
|
-
during tests, which may modify the environment after having imported wandb
|
365
|
-
and called certain functions.
|
366
|
-
"""
|
367
|
-
if _singleton and _singleton._pid == os.getpid():
|
368
|
-
return _singleton
|
369
|
-
else:
|
370
|
-
return None
|
435
|
+
return _setup(start_service=False, load_settings=False)
|
371
436
|
|
372
437
|
|
373
438
|
@wb_logging.log_to_all_runs()
|
374
439
|
def _setup(
|
375
440
|
settings: Settings | None = None,
|
376
441
|
start_service: bool = True,
|
442
|
+
load_settings: bool = True,
|
377
443
|
) -> _WandbSetup:
|
378
444
|
"""Set up library context.
|
379
445
|
|
@@ -384,18 +450,31 @@ def _setup(
|
|
384
450
|
NOTE: A service process will only be started if allowed by the
|
385
451
|
global settings (after the given updates). The service will not
|
386
452
|
start up if the mode resolves to "disabled".
|
453
|
+
load_settings: Whether to load settings from the environment
|
454
|
+
if creating a new singleton. If False, then settings and
|
455
|
+
start_service must be None.
|
387
456
|
"""
|
388
457
|
global _singleton
|
389
458
|
|
459
|
+
if not load_settings and settings:
|
460
|
+
raise ValueError("Cannot pass settings if load_settings is False.")
|
461
|
+
if not load_settings and start_service:
|
462
|
+
raise ValueError("Cannot use start_service if load_settings is False.")
|
463
|
+
|
390
464
|
pid = os.getpid()
|
465
|
+
with _singleton_lock:
|
466
|
+
if _singleton and _singleton._pid == pid:
|
467
|
+
current_singleton = _singleton
|
468
|
+
else:
|
469
|
+
current_singleton = _WandbSetup(pid=pid)
|
470
|
+
|
471
|
+
if load_settings:
|
472
|
+
current_singleton._update(settings)
|
391
473
|
|
392
|
-
|
393
|
-
|
394
|
-
else:
|
395
|
-
_singleton = _WandbSetup(settings=settings, pid=pid)
|
474
|
+
if start_service and not current_singleton.settings._noop:
|
475
|
+
current_singleton.ensure_service()
|
396
476
|
|
397
|
-
|
398
|
-
_singleton.ensure_service()
|
477
|
+
_singleton = current_singleton
|
399
478
|
|
400
479
|
return _singleton
|
401
480
|
|
@@ -473,8 +552,9 @@ def teardown(exit_code: int | None = None) -> None:
|
|
473
552
|
"""
|
474
553
|
global _singleton
|
475
554
|
|
476
|
-
|
477
|
-
|
555
|
+
with _singleton_lock:
|
556
|
+
orig_singleton = _singleton
|
557
|
+
_singleton = None
|
478
558
|
|
479
|
-
|
480
|
-
|
559
|
+
if orig_singleton:
|
560
|
+
orig_singleton._teardown(exit_code=exit_code)
|
wandb/util.py
CHANGED
@@ -702,7 +702,7 @@ def json_friendly_val(val: Any) -> Any:
|
|
702
702
|
return converted
|
703
703
|
if is_dataclass(val) and not isinstance(val, type):
|
704
704
|
converted = asdict(val)
|
705
|
-
return converted
|
705
|
+
return json_friendly_val(converted)
|
706
706
|
else:
|
707
707
|
if val.__class__.__module__ not in ("builtins", "__builtin__"):
|
708
708
|
val = str(val)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: wandb
|
3
|
-
Version: 0.21.
|
3
|
+
Version: 0.21.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
|
@@ -47,7 +47,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
47
47
|
Classifier: Topic :: System :: Logging
|
48
48
|
Classifier: Topic :: System :: Monitoring
|
49
49
|
Requires-Python: >=3.8
|
50
|
-
Requires-Dist: click
|
50
|
+
Requires-Dist: click>=8.0.1
|
51
51
|
Requires-Dist: eval-type-backport; python_version < '3.10'
|
52
52
|
Requires-Dist: gitpython!=3.1.29,>=1.0.0
|
53
53
|
Requires-Dist: packaging
|