wandb 0.17.6__py3-none-win32.whl → 0.17.8__py3-none-win32.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.
- package_readme.md +47 -53
- wandb/__init__.py +10 -19
- wandb/__init__.pyi +964 -0
- wandb/agents/pyagent.py +1 -2
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +21 -0
- wandb/data_types.py +4 -3
- wandb/env.py +13 -0
- wandb/integration/keras/__init__.py +2 -5
- wandb/integration/keras/callbacks/metrics_logger.py +10 -4
- wandb/integration/keras/callbacks/model_checkpoint.py +0 -5
- wandb/integration/keras/keras.py +11 -0
- wandb/integration/kfp/wandb_logging.py +1 -1
- wandb/integration/lightning/fabric/logger.py +1 -1
- wandb/integration/openai/fine_tuning.py +13 -5
- wandb/integration/ultralytics/pose_utils.py +0 -1
- wandb/proto/v3/wandb_internal_pb2.py +24 -24
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v3/wandb_telemetry_pb2.py +12 -12
- wandb/proto/v4/wandb_internal_pb2.py +24 -24
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_telemetry_pb2.py +12 -12
- wandb/proto/v5/wandb_internal_pb2.py +24 -24
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_telemetry_pb2.py +12 -12
- wandb/proto/wandb_deprecated.py +2 -0
- wandb/sdk/artifacts/artifact.py +22 -26
- wandb/sdk/artifacts/artifact_manifest_entry.py +10 -2
- wandb/sdk/artifacts/storage_handlers/gcs_handler.py +31 -0
- wandb/sdk/data_types/_dtypes.py +5 -5
- wandb/sdk/data_types/base_types/media.py +3 -1
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +3 -1
- wandb/sdk/data_types/helper_types/image_mask.py +3 -1
- wandb/sdk/data_types/image.py +3 -1
- wandb/sdk/data_types/saved_model.py +3 -1
- wandb/sdk/data_types/video.py +2 -2
- wandb/sdk/interface/interface.py +17 -16
- wandb/sdk/interface/interface_shared.py +6 -9
- wandb/sdk/internal/datastore.py +1 -1
- wandb/sdk/internal/handler.py +5 -3
- wandb/sdk/internal/internal.py +1 -1
- wandb/sdk/internal/job_builder.py +5 -2
- wandb/sdk/internal/tb_watcher.py +2 -2
- wandb/sdk/internal/update.py +2 -2
- wandb/sdk/launch/builder/kaniko_builder.py +13 -5
- wandb/sdk/launch/create_job.py +2 -0
- wandb/sdk/lib/_settings_toposort_generated.py +1 -0
- wandb/sdk/lib/apikey.py +1 -1
- wandb/sdk/service/service.py +7 -2
- wandb/sdk/service/streams.py +2 -4
- wandb/sdk/wandb_config.py +4 -1
- wandb/sdk/wandb_init.py +59 -8
- wandb/sdk/wandb_manager.py +0 -3
- wandb/sdk/wandb_require.py +22 -1
- wandb/sdk/wandb_run.py +137 -92
- wandb/sdk/wandb_settings.py +26 -2
- wandb/sdk/wandb_setup.py +69 -3
- wandb/sdk/wandb_sweep.py +5 -2
- wandb/testing/relay.py +7 -1
- {wandb-0.17.6.dist-info → wandb-0.17.8.dist-info}/METADATA +48 -54
- {wandb-0.17.6.dist-info → wandb-0.17.8.dist-info}/RECORD +64 -63
- {wandb-0.17.6.dist-info → wandb-0.17.8.dist-info}/WHEEL +0 -0
- {wandb-0.17.6.dist-info → wandb-0.17.8.dist-info}/entry_points.txt +0 -0
- {wandb-0.17.6.dist-info → wandb-0.17.8.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/data_types/_dtypes.py
CHANGED
@@ -56,7 +56,7 @@ class TypeRegistry:
|
|
56
56
|
# but will be ultimately treated as a None. Ignoring type since
|
57
57
|
# mypy does not trust that py_obj is a float by the time it is
|
58
58
|
# passed to isnan.
|
59
|
-
if py_obj.__class__
|
59
|
+
if py_obj.__class__ is float and math.isnan(py_obj): # type: ignore
|
60
60
|
return NoneType()
|
61
61
|
|
62
62
|
# TODO: generalize this to handle other config input types
|
@@ -134,7 +134,7 @@ def _params_obj_to_json_obj(
|
|
134
134
|
artifact: t.Optional["Artifact"] = None,
|
135
135
|
) -> t.Any:
|
136
136
|
"""Helper method."""
|
137
|
-
if params_obj.__class__
|
137
|
+
if params_obj.__class__ is dict:
|
138
138
|
return {
|
139
139
|
key: _params_obj_to_json_obj(params_obj[key], artifact)
|
140
140
|
for key in params_obj
|
@@ -151,7 +151,7 @@ def _json_obj_to_params_obj(
|
|
151
151
|
json_obj: t.Any, artifact: t.Optional["Artifact"] = None
|
152
152
|
) -> t.Any:
|
153
153
|
"""Helper method."""
|
154
|
-
if json_obj.__class__
|
154
|
+
if json_obj.__class__ is dict:
|
155
155
|
if "wb_type" in json_obj:
|
156
156
|
return TypeRegistry.type_from_dict(json_obj, artifact)
|
157
157
|
else:
|
@@ -159,7 +159,7 @@ def _json_obj_to_params_obj(
|
|
159
159
|
key: _json_obj_to_params_obj(json_obj[key], artifact)
|
160
160
|
for key in json_obj
|
161
161
|
}
|
162
|
-
elif json_obj.__class__
|
162
|
+
elif json_obj.__class__ is list:
|
163
163
|
return [_json_obj_to_params_obj(item, artifact) for item in json_obj]
|
164
164
|
else:
|
165
165
|
return json_obj
|
@@ -533,7 +533,7 @@ class UnionType(Type):
|
|
533
533
|
self,
|
534
534
|
allowed_types: t.Optional[t.Sequence[ConvertibleToType]] = None,
|
535
535
|
):
|
536
|
-
assert allowed_types is None or (allowed_types.__class__
|
536
|
+
assert allowed_types is None or (allowed_types.__class__ is list)
|
537
537
|
if allowed_types is None:
|
538
538
|
wb_types = []
|
539
539
|
else:
|
@@ -159,9 +159,11 @@ class Media(WBValue):
|
|
159
159
|
# into Media itself we should get rid of them
|
160
160
|
from wandb import Image
|
161
161
|
from wandb.data_types import Audio
|
162
|
+
from wandb.sdk.wandb_run import Run
|
162
163
|
|
163
164
|
json_obj = {}
|
164
|
-
|
165
|
+
|
166
|
+
if isinstance(run, Run):
|
165
167
|
json_obj.update(
|
166
168
|
{
|
167
169
|
"_type": "file", # TODO(adrian): This isn't (yet) a real media type we support on the frontend.
|
@@ -276,7 +276,9 @@ class BoundingBoxes2D(JSONMetadata):
|
|
276
276
|
return True
|
277
277
|
|
278
278
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
279
|
-
|
279
|
+
from wandb.sdk.wandb_run import Run
|
280
|
+
|
281
|
+
if isinstance(run_or_artifact, Run):
|
280
282
|
return super().to_json(run_or_artifact)
|
281
283
|
elif isinstance(run_or_artifact, wandb.Artifact):
|
282
284
|
# TODO (tim): I would like to log out a proper dictionary representing this object, but don't
|
@@ -191,9 +191,11 @@ class ImageMask(Media):
|
|
191
191
|
)
|
192
192
|
|
193
193
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
194
|
+
from wandb.sdk.wandb_run import Run
|
195
|
+
|
194
196
|
json_dict = super().to_json(run_or_artifact)
|
195
197
|
|
196
|
-
if isinstance(run_or_artifact,
|
198
|
+
if isinstance(run_or_artifact, Run):
|
197
199
|
json_dict["_type"] = self.type_name()
|
198
200
|
return json_dict
|
199
201
|
elif isinstance(run_or_artifact, wandb.Artifact):
|
wandb/sdk/data_types/image.py
CHANGED
@@ -418,6 +418,8 @@ class Image(BatchableMedia):
|
|
418
418
|
)
|
419
419
|
|
420
420
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
421
|
+
from wandb.sdk.wandb_run import Run
|
422
|
+
|
421
423
|
json_dict = super().to_json(run_or_artifact)
|
422
424
|
json_dict["_type"] = Image._log_type
|
423
425
|
json_dict["format"] = self.format
|
@@ -456,7 +458,7 @@ class Image(BatchableMedia):
|
|
456
458
|
"digest": classes_entry.digest,
|
457
459
|
}
|
458
460
|
|
459
|
-
elif not isinstance(run_or_artifact,
|
461
|
+
elif not isinstance(run_or_artifact, Run):
|
460
462
|
raise ValueError("to_json accepts wandb_run.Run or wandb_artifact.Artifact")
|
461
463
|
|
462
464
|
if self._boxes:
|
@@ -148,7 +148,9 @@ class _SavedModel(WBValue, Generic[SavedModelObjType]):
|
|
148
148
|
# bit of tech debt in the other data types which requires the input to `to_json`
|
149
149
|
# to accept a Run or Artifact. However, Run additions should be deprecated in the future.
|
150
150
|
# This check helps ensure we do not add to the debt.
|
151
|
-
|
151
|
+
from wandb.sdk.wandb_run import Run
|
152
|
+
|
153
|
+
if isinstance(run_or_artifact, Run):
|
152
154
|
raise ValueError("SavedModel cannot be added to run - must use artifact")
|
153
155
|
artifact = run_or_artifact
|
154
156
|
json_obj = {
|
wandb/sdk/data_types/video.py
CHANGED
@@ -214,9 +214,9 @@ class Video(BatchableMedia):
|
|
214
214
|
n_rows = 2 ** ((b.bit_length() - 1) // 2)
|
215
215
|
n_cols = video.shape[0] // n_rows
|
216
216
|
|
217
|
-
video =
|
217
|
+
video = video.reshape(n_rows, n_cols, t, c, h, w)
|
218
218
|
video = np.transpose(video, axes=(2, 0, 4, 1, 5, 3))
|
219
|
-
video =
|
219
|
+
video = video.reshape(t, n_rows * h, n_cols * w, c)
|
220
220
|
return video
|
221
221
|
|
222
222
|
@classmethod
|
wandb/sdk/interface/interface.py
CHANGED
@@ -54,18 +54,20 @@ MANIFEST_FILE_SIZE_THRESHOLD = 100_000
|
|
54
54
|
|
55
55
|
GlobStr = NewType("GlobStr", str)
|
56
56
|
|
57
|
-
if
|
58
|
-
from
|
57
|
+
if sys.version_info >= (3, 8):
|
58
|
+
from typing import Literal, TypedDict
|
59
|
+
else:
|
60
|
+
from typing_extensions import Literal, TypedDict
|
61
|
+
|
62
|
+
PolicyName = Literal["now", "live", "end"]
|
59
63
|
|
60
|
-
if sys.version_info >= (3, 8):
|
61
|
-
from typing import Literal, TypedDict
|
62
|
-
else:
|
63
|
-
from typing_extensions import Literal, TypedDict
|
64
64
|
|
65
|
-
|
65
|
+
class FilesDict(TypedDict):
|
66
|
+
files: Iterable[Tuple[GlobStr, PolicyName]]
|
66
67
|
|
67
|
-
|
68
|
-
|
68
|
+
|
69
|
+
if TYPE_CHECKING:
|
70
|
+
from ..wandb_run import Run
|
69
71
|
|
70
72
|
|
71
73
|
logger = logging.getLogger("wandb")
|
@@ -112,15 +114,14 @@ class InterfaceBase:
|
|
112
114
|
def _publish_header(self, header: pb.HeaderRecord) -> None:
|
113
115
|
raise NotImplementedError
|
114
116
|
|
115
|
-
def
|
116
|
-
|
117
|
-
resp = self._communicate_status(status)
|
118
|
-
return resp
|
117
|
+
def deliver_status(self) -> MailboxHandle:
|
118
|
+
return self._deliver_status(pb.StatusRequest())
|
119
119
|
|
120
120
|
@abstractmethod
|
121
|
-
def
|
122
|
-
self,
|
123
|
-
|
121
|
+
def _deliver_status(
|
122
|
+
self,
|
123
|
+
status: pb.StatusRequest,
|
124
|
+
) -> MailboxHandle:
|
124
125
|
raise NotImplementedError
|
125
126
|
|
126
127
|
def _make_config(
|
@@ -299,7 +299,7 @@ class InterfaceShared(InterfaceBase):
|
|
299
299
|
raise NotImplementedError
|
300
300
|
|
301
301
|
def _communicate(
|
302
|
-
self, rec: pb.Record, timeout: Optional[int] =
|
302
|
+
self, rec: pb.Record, timeout: Optional[int] = 30, local: Optional[bool] = None
|
303
303
|
) -> Optional[pb.Result]:
|
304
304
|
return self._communicate_async(rec, local=local).get(timeout=timeout)
|
305
305
|
|
@@ -421,15 +421,12 @@ class InterfaceShared(InterfaceBase):
|
|
421
421
|
rec = self._make_record(alert=proto_alert)
|
422
422
|
self._publish(rec)
|
423
423
|
|
424
|
-
def
|
425
|
-
self,
|
426
|
-
|
424
|
+
def _deliver_status(
|
425
|
+
self,
|
426
|
+
status: pb.StatusRequest,
|
427
|
+
) -> MailboxHandle:
|
427
428
|
req = self._make_request(status=status)
|
428
|
-
|
429
|
-
if resp is None:
|
430
|
-
return None
|
431
|
-
assert resp.response.status_response
|
432
|
-
return resp.response.status_response
|
429
|
+
return self._deliver_record(req)
|
433
430
|
|
434
431
|
def _publish_exit(self, exit_data: pb.RunExitRecord) -> None:
|
435
432
|
rec = self._make_record(exit=exit_data)
|
wandb/sdk/internal/datastore.py
CHANGED
wandb/sdk/internal/handler.py
CHANGED
@@ -660,7 +660,11 @@ class HandleManager:
|
|
660
660
|
self._dispatch_record(record)
|
661
661
|
|
662
662
|
def handle_request_check_version(self, record: Record) -> None:
|
663
|
-
self.
|
663
|
+
if self._settings._offline:
|
664
|
+
result = proto_util._result_from_record(record)
|
665
|
+
self._respond_result(result)
|
666
|
+
else:
|
667
|
+
self._dispatch_record(record)
|
664
668
|
|
665
669
|
def handle_request_attach(self, record: Record) -> None:
|
666
670
|
result = proto_util._result_from_record(record)
|
@@ -745,8 +749,6 @@ class HandleManager:
|
|
745
749
|
self._respond_result(result)
|
746
750
|
|
747
751
|
def handle_request_status(self, record: Record) -> None:
|
748
|
-
# TODO(mempressure): do something better?
|
749
|
-
assert record.control.req_resp
|
750
752
|
result = proto_util._result_from_record(record)
|
751
753
|
self._respond_result(result)
|
752
754
|
|
wandb/sdk/internal/internal.py
CHANGED
@@ -423,15 +423,18 @@ class JobBuilder:
|
|
423
423
|
api: Api,
|
424
424
|
build_context: Optional[str] = None,
|
425
425
|
dockerfile: Optional[str] = None,
|
426
|
+
base_image: Optional[str] = None,
|
426
427
|
) -> Optional[Artifact]:
|
427
428
|
"""Build a job artifact from the current run.
|
428
429
|
|
429
430
|
Arguments:
|
431
|
+
api (Api): The API object to use to create the job artifact.
|
430
432
|
build_context (Optional[str]): Path within the job source code to
|
431
433
|
the image build context. Saved as part of the job for future
|
432
434
|
builds.
|
433
435
|
dockerfile (Optional[str]): Path within the build context the
|
434
436
|
Dockerfile. Saved as part of the job for future builds.
|
437
|
+
base_image (Optional[str]): The base image used to run the job code.
|
435
438
|
|
436
439
|
Returns:
|
437
440
|
Optional[Artifact]: The job artifact if it was successfully built,
|
@@ -467,8 +470,6 @@ class JobBuilder:
|
|
467
470
|
"warn",
|
468
471
|
)
|
469
472
|
return None
|
470
|
-
metadata["dockerfile"] = dockerfile
|
471
|
-
metadata["build_context"] = build_context
|
472
473
|
|
473
474
|
runtime: Optional[str] = metadata.get("python")
|
474
475
|
# can't build a job without a python version
|
@@ -520,6 +521,8 @@ class JobBuilder:
|
|
520
521
|
source["build_context"] = build_context # type: ignore[typeddict-item]
|
521
522
|
if dockerfile:
|
522
523
|
source["dockerfile"] = dockerfile # type: ignore[typeddict-item]
|
524
|
+
if base_image:
|
525
|
+
source["base_image"] = base_image # type: ignore[typeddict-item]
|
523
526
|
|
524
527
|
# Pop any keys that are initialized to None. The current TypedDict
|
525
528
|
# system for source dicts requires all keys to be present, but we
|
wandb/sdk/internal/tb_watcher.py
CHANGED
@@ -123,7 +123,7 @@ class TBWatcher:
|
|
123
123
|
self._force = force
|
124
124
|
# TODO(jhr): do we need locking in this queue?
|
125
125
|
self._watcher_queue = queue.PriorityQueue()
|
126
|
-
wandb.tensorboard.reset_state()
|
126
|
+
wandb.tensorboard.reset_state() # type: ignore
|
127
127
|
|
128
128
|
def _calculate_namespace(self, logdir: str, rootdir: str) -> Optional[str]:
|
129
129
|
namespace: Optional[str]
|
@@ -430,7 +430,7 @@ class TBEventConsumer:
|
|
430
430
|
def _handle_event(
|
431
431
|
self, event: "ProtoEvent", history: Optional["TBHistory"] = None
|
432
432
|
) -> None:
|
433
|
-
wandb.tensorboard._log(
|
433
|
+
wandb.tensorboard._log( # type: ignore
|
434
434
|
event.event,
|
435
435
|
step=event.event.step,
|
436
436
|
namespace=event.namespace,
|
wandb/sdk/internal/update.py
CHANGED
@@ -10,7 +10,7 @@ def _find_available(
|
|
10
10
|
) -> Optional[Tuple[str, bool, bool, bool, Optional[str]]]:
|
11
11
|
from wandb.util import parse_version
|
12
12
|
|
13
|
-
pypi_url =
|
13
|
+
pypi_url = "https://pypi.org/pypi/wandb/json"
|
14
14
|
|
15
15
|
yanked_dict = {}
|
16
16
|
try:
|
@@ -78,7 +78,7 @@ def check_available(current_version: str) -> Optional[Dict[str, Optional[str]]]:
|
|
78
78
|
if not package_info:
|
79
79
|
return None
|
80
80
|
|
81
|
-
wandb_module_name = wandb
|
81
|
+
wandb_module_name = "wandb"
|
82
82
|
|
83
83
|
latest_version, pip_prerelease, deleted, yanked, yanked_reason = package_info
|
84
84
|
upgrade_message = (
|
@@ -63,6 +63,13 @@ else:
|
|
63
63
|
NAMESPACE = "wandb"
|
64
64
|
|
65
65
|
|
66
|
+
def get_pod_name_safe(job: client.V1Job):
|
67
|
+
try:
|
68
|
+
return job.spec.template.metadata.name
|
69
|
+
except AttributeError:
|
70
|
+
return None
|
71
|
+
|
72
|
+
|
66
73
|
async def _wait_for_completion(
|
67
74
|
batch_client: client.BatchV1Api, job_name: str, deadline_secs: Optional[int] = None
|
68
75
|
) -> bool:
|
@@ -319,17 +326,18 @@ class KanikoBuilder(AbstractBuilder):
|
|
319
326
|
await self._create_docker_ecr_config_map(
|
320
327
|
build_job_name, core_v1, repo_uri
|
321
328
|
)
|
322
|
-
await batch_v1.create_namespaced_job(NAMESPACE, build_job)
|
323
|
-
|
329
|
+
k8s_job = await batch_v1.create_namespaced_job(NAMESPACE, build_job)
|
324
330
|
# wait for double the job deadline since it might take time to schedule
|
325
331
|
if not await _wait_for_completion(
|
326
332
|
batch_v1, build_job_name, 3 * _DEFAULT_BUILD_TIMEOUT_SECS
|
327
333
|
):
|
328
334
|
if job_tracker:
|
329
335
|
job_tracker.set_err_stage("build")
|
330
|
-
|
331
|
-
|
332
|
-
|
336
|
+
msg = f"Failed to build image in kaniko for job {run_id}."
|
337
|
+
pod_name = get_pod_name_safe(k8s_job)
|
338
|
+
if pod_name:
|
339
|
+
msg += f" View logs with `kubectl logs -n {NAMESPACE} {pod_name}`."
|
340
|
+
raise Exception(msg)
|
333
341
|
try:
|
334
342
|
pods_from_job = await core_v1.list_namespaced_pod(
|
335
343
|
namespace=NAMESPACE, label_selector=f"job-name={build_job_name}"
|
wandb/sdk/launch/create_job.py
CHANGED
@@ -114,6 +114,7 @@ def _create_job(
|
|
114
114
|
git_hash: Optional[str] = None,
|
115
115
|
build_context: Optional[str] = None,
|
116
116
|
dockerfile: Optional[str] = None,
|
117
|
+
base_image: Optional[str] = None,
|
117
118
|
) -> Tuple[Optional[Artifact], str, List[str]]:
|
118
119
|
wandb.termlog(f"Creating launch job of type: {job_type}...")
|
119
120
|
|
@@ -188,6 +189,7 @@ def _create_job(
|
|
188
189
|
api.api,
|
189
190
|
dockerfile=dockerfile,
|
190
191
|
build_context=build_context,
|
192
|
+
base_image=base_image,
|
191
193
|
)
|
192
194
|
if not artifact:
|
193
195
|
wandb.termerror("JobBuilder failed to build a job")
|
wandb/sdk/lib/apikey.py
CHANGED
@@ -107,7 +107,7 @@ def prompt_api_key( # noqa: C901
|
|
107
107
|
|
108
108
|
if jupyter and "google.colab" in sys.modules:
|
109
109
|
log_string = term.LOG_STRING_NOCOLOR
|
110
|
-
key = wandb.jupyter.attempt_colab_login(app_url)
|
110
|
+
key = wandb.jupyter.attempt_colab_login(app_url) # type: ignore
|
111
111
|
if key is not None:
|
112
112
|
write_key(settings, key, api=api)
|
113
113
|
return key # type: ignore
|
wandb/sdk/service/service.py
CHANGED
@@ -15,7 +15,12 @@ import time
|
|
15
15
|
from typing import TYPE_CHECKING, Any, Dict, Optional
|
16
16
|
|
17
17
|
from wandb import _sentry, termlog
|
18
|
-
from wandb.env import
|
18
|
+
from wandb.env import (
|
19
|
+
core_debug,
|
20
|
+
core_error_reporting_enabled,
|
21
|
+
is_require_core,
|
22
|
+
is_require_legacy_service,
|
23
|
+
)
|
19
24
|
from wandb.errors import Error, WandbCoreNotAvailableError
|
20
25
|
from wandb.sdk.lib.wburls import wburls
|
21
26
|
from wandb.util import get_core_path, get_module
|
@@ -164,7 +169,7 @@ class _Service:
|
|
164
169
|
|
165
170
|
service_args = []
|
166
171
|
|
167
|
-
if is_require_core():
|
172
|
+
if is_require_core() and not is_require_legacy_service():
|
168
173
|
try:
|
169
174
|
core_path = get_core_path()
|
170
175
|
except WandbCoreNotAvailableError as e:
|
wandb/sdk/service/streams.py
CHANGED
@@ -81,9 +81,7 @@ class StreamRecord:
|
|
81
81
|
self._wait_thread_active()
|
82
82
|
|
83
83
|
def _wait_thread_active(self) -> None:
|
84
|
-
|
85
|
-
# TODO: using the default communicate timeout, is that enough? retries?
|
86
|
-
assert result
|
84
|
+
self._iface.deliver_status().wait(timeout=-1)
|
87
85
|
|
88
86
|
def join(self) -> None:
|
89
87
|
self._iface.join()
|
@@ -212,7 +210,7 @@ class StreamMux:
|
|
212
210
|
# run_id = action.stream_id # will want to fix if a streamid != runid
|
213
211
|
settings = action._data
|
214
212
|
thread = StreamThread(
|
215
|
-
target=wandb.wandb_sdk.internal.internal.wandb_internal,
|
213
|
+
target=wandb.wandb_sdk.internal.internal.wandb_internal, # type: ignore
|
216
214
|
kwargs=dict(
|
217
215
|
settings=settings,
|
218
216
|
record_q=stream._record_q,
|
wandb/sdk/wandb_config.py
CHANGED
@@ -61,7 +61,7 @@ class Config:
|
|
61
61
|
|
62
62
|
Using absl flags
|
63
63
|
```
|
64
|
-
flags.DEFINE_string(
|
64
|
+
flags.DEFINE_string("model", None, "model to run") # name, default, help
|
65
65
|
wandb.config.update(flags.FLAGS) # adds all absl flags to config
|
66
66
|
```
|
67
67
|
|
@@ -129,6 +129,9 @@ class Config:
|
|
129
129
|
def __getitem__(self, key):
|
130
130
|
return self._items[key]
|
131
131
|
|
132
|
+
def __iter__(self):
|
133
|
+
return iter(self._items)
|
134
|
+
|
132
135
|
def _check_locked(self, key, ignore_locked=False) -> bool:
|
133
136
|
locked = self._locked.get(key)
|
134
137
|
if locked is not None:
|
wandb/sdk/wandb_init.py
CHANGED
@@ -15,6 +15,7 @@ import os
|
|
15
15
|
import platform
|
16
16
|
import sys
|
17
17
|
import tempfile
|
18
|
+
import time
|
18
19
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union
|
19
20
|
|
20
21
|
import wandb
|
@@ -174,7 +175,9 @@ class _WandbInit:
|
|
174
175
|
# we add this logic to be backward compatible with the old behavior of disable
|
175
176
|
# where it would disable the service if the mode was set to disabled
|
176
177
|
mode = kwargs.get("mode")
|
177
|
-
settings_mode = (kwargs.get("settings") or {}).get("mode")
|
178
|
+
settings_mode = (kwargs.get("settings") or {}).get("mode") or os.environ.get(
|
179
|
+
"WANDB_MODE"
|
180
|
+
)
|
178
181
|
_disable_service = mode == "disabled" or settings_mode == "disabled"
|
179
182
|
setup_settings = {"_disable_service": _disable_service}
|
180
183
|
|
@@ -262,7 +265,7 @@ class _WandbInit:
|
|
262
265
|
|
263
266
|
monitor_gym = kwargs.pop("monitor_gym", None)
|
264
267
|
if monitor_gym and len(wandb.patched["gym"]) == 0:
|
265
|
-
wandb.gym.monitor()
|
268
|
+
wandb.gym.monitor() # type: ignore
|
266
269
|
|
267
270
|
if wandb.patched["tensorboard"]:
|
268
271
|
with telemetry.context(obj=self._init_telemetry_obj) as tel:
|
@@ -271,7 +274,7 @@ class _WandbInit:
|
|
271
274
|
tensorboard = kwargs.pop("tensorboard", None)
|
272
275
|
sync_tensorboard = kwargs.pop("sync_tensorboard", None)
|
273
276
|
if tensorboard or sync_tensorboard and len(wandb.patched["tensorboard"]) == 0:
|
274
|
-
wandb.tensorboard.patch()
|
277
|
+
wandb.tensorboard.patch() # type: ignore
|
275
278
|
with telemetry.context(obj=self._init_telemetry_obj) as tel:
|
276
279
|
tel.feature.tensorboard_sync = True
|
277
280
|
|
@@ -459,7 +462,7 @@ class _WandbInit:
|
|
459
462
|
|
460
463
|
def _jupyter_setup(self, settings: Settings) -> None:
|
461
464
|
"""Add hooks, and session history saving."""
|
462
|
-
self.notebook = wandb.jupyter.Notebook(settings)
|
465
|
+
self.notebook = wandb.jupyter.Notebook(settings) # type: ignore
|
463
466
|
ipython = self.notebook.shell
|
464
467
|
|
465
468
|
# Monkey patch ipython publish to capture displayed outputs
|
@@ -522,17 +525,62 @@ class _WandbInit:
|
|
522
525
|
logger.info(f"Logging internal logs to {settings.log_internal}")
|
523
526
|
|
524
527
|
def _make_run_disabled(self) -> Run:
|
528
|
+
"""Returns a Run-like object where all methods are no-ops.
|
529
|
+
|
530
|
+
This method is used when wandb.init(mode="disabled") is called or WANDB_MODE=disabled
|
531
|
+
is set. It creates a Run object that mimics the behavior of a normal Run but doesn't
|
532
|
+
communicate with the W&B servers.
|
533
|
+
|
534
|
+
The returned Run object has all expected attributes and methods, but they are
|
535
|
+
no-op versions that don't perform any actual logging or communication.
|
536
|
+
"""
|
525
537
|
drun = Run(settings=Settings(mode="disabled", files_dir=tempfile.gettempdir()))
|
526
|
-
|
538
|
+
# config and summary objects
|
539
|
+
drun._config = wandb.sdk.wandb_config.Config()
|
527
540
|
drun._config.update(self.sweep_config)
|
528
541
|
drun._config.update(self.config)
|
529
542
|
drun.summary = SummaryDisabled() # type: ignore
|
543
|
+
# methods
|
530
544
|
drun.log = lambda data, *_, **__: drun.summary.update(data) # type: ignore
|
531
545
|
drun.finish = lambda *_, **__: module.unset_globals() # type: ignore
|
546
|
+
drun.join = drun.finish # type: ignore
|
547
|
+
drun.define_metric = lambda *_, **__: wandb.sdk.wandb_metric.Metric("dummy") # type: ignore
|
548
|
+
drun.save = lambda *_, **__: False # type: ignore
|
549
|
+
for symbol in (
|
550
|
+
"alert",
|
551
|
+
"finish_artifact",
|
552
|
+
"get_project_url",
|
553
|
+
"get_sweep_url",
|
554
|
+
"get_url",
|
555
|
+
"link_artifact",
|
556
|
+
"link_model",
|
557
|
+
"use_artifact",
|
558
|
+
"log_artifact",
|
559
|
+
"log_code",
|
560
|
+
"log_model",
|
561
|
+
"use_model",
|
562
|
+
"mark_preempting",
|
563
|
+
"plot_table",
|
564
|
+
"restore",
|
565
|
+
"status",
|
566
|
+
"watch",
|
567
|
+
"unwatch",
|
568
|
+
"upsert_artifact",
|
569
|
+
):
|
570
|
+
setattr(drun, symbol, lambda *_, **__: None) # type: ignore
|
571
|
+
# attributes
|
532
572
|
drun._step = 0
|
573
|
+
drun._attach_id = None
|
533
574
|
drun._run_obj = None
|
534
575
|
drun._run_id = runid.generate_id()
|
535
576
|
drun._name = "dummy-" + drun.id
|
577
|
+
drun._project = "dummy"
|
578
|
+
drun._entity = "dummy"
|
579
|
+
drun._tags = tuple()
|
580
|
+
drun._notes = None
|
581
|
+
drun._group = None
|
582
|
+
drun._start_time = time.time()
|
583
|
+
drun._starting_step = 0
|
536
584
|
module.set_global(
|
537
585
|
run=drun,
|
538
586
|
config=drun.config,
|
@@ -688,7 +736,10 @@ class _WandbInit:
|
|
688
736
|
tel.feature.flow_control_disabled = True
|
689
737
|
if self.settings._flow_control_custom:
|
690
738
|
tel.feature.flow_control_custom = True
|
691
|
-
if
|
739
|
+
if (
|
740
|
+
self.settings._require_core
|
741
|
+
and not self.settings._require_legacy_service
|
742
|
+
):
|
692
743
|
tel.feature.core = True
|
693
744
|
if self.settings._shared:
|
694
745
|
wandb.termwarn(
|
@@ -868,7 +919,7 @@ def _attach(
|
|
868
919
|
raise UsageError(
|
869
920
|
"Either `attach_id` or `run_id` must be specified or `run` must have `_attach_id`"
|
870
921
|
)
|
871
|
-
wandb._assert_is_user_process()
|
922
|
+
wandb._assert_is_user_process() # type: ignore
|
872
923
|
|
873
924
|
_wl = wandb_setup._setup()
|
874
925
|
assert _wl
|
@@ -1157,7 +1208,7 @@ def init(
|
|
1157
1208
|
Returns:
|
1158
1209
|
A `Run` object.
|
1159
1210
|
"""
|
1160
|
-
wandb._assert_is_user_process()
|
1211
|
+
wandb._assert_is_user_process() # type: ignore
|
1161
1212
|
|
1162
1213
|
kwargs = dict(locals())
|
1163
1214
|
|
wandb/sdk/wandb_manager.py
CHANGED
@@ -13,7 +13,6 @@ import wandb
|
|
13
13
|
from wandb import env, trigger
|
14
14
|
from wandb.errors import Error
|
15
15
|
from wandb.sdk.lib.exit_hooks import ExitHooks
|
16
|
-
from wandb.sdk.lib.import_hooks import unregister_all_post_import_hooks
|
17
16
|
|
18
17
|
if TYPE_CHECKING:
|
19
18
|
from wandb.proto import wandb_settings_pb2
|
@@ -163,8 +162,6 @@ class _Manager:
|
|
163
162
|
This sends a teardown record to the process. An exception is raised if
|
164
163
|
the process has already been shut down.
|
165
164
|
"""
|
166
|
-
unregister_all_post_import_hooks()
|
167
|
-
|
168
165
|
if self._atexit_lambda:
|
169
166
|
atexit.unregister(self._atexit_lambda)
|
170
167
|
self._atexit_lambda = None
|
wandb/sdk/wandb_require.py
CHANGED
@@ -13,7 +13,12 @@ import os
|
|
13
13
|
from typing import Optional, Sequence, Union
|
14
14
|
|
15
15
|
import wandb
|
16
|
-
from wandb.env import
|
16
|
+
from wandb.env import (
|
17
|
+
_REQUIRE_CORE,
|
18
|
+
_REQUIRE_LEGACY_SERVICE,
|
19
|
+
is_require_core,
|
20
|
+
is_require_legacy_service,
|
21
|
+
)
|
17
22
|
from wandb.errors import UnsupportedError
|
18
23
|
from wandb.sdk import wandb_run
|
19
24
|
from wandb.sdk.lib.wburls import wburls
|
@@ -41,8 +46,24 @@ class _Requires:
|
|
41
46
|
self._require_service()
|
42
47
|
|
43
48
|
def require_core(self) -> None:
|
49
|
+
if is_require_legacy_service():
|
50
|
+
raise UnsupportedError(
|
51
|
+
'Cannot use wandb.require("core") because legacy-service'
|
52
|
+
" is already required--did you use"
|
53
|
+
' wandb.require("legacy-service") or set the'
|
54
|
+
" WANDB__REQUIRE_LEGACY_SERVICE environment variable?"
|
55
|
+
)
|
44
56
|
os.environ[_REQUIRE_CORE] = "true"
|
45
57
|
|
58
|
+
def require_legacy_service(self) -> None:
|
59
|
+
if is_require_core():
|
60
|
+
raise UnsupportedError(
|
61
|
+
'Cannot use wandb.require("legacy-service") because core'
|
62
|
+
' is already required--did you use wandb.require("core")'
|
63
|
+
" or set the WANDB__REQUIRE_CORE environment variable?"
|
64
|
+
)
|
65
|
+
os.environ[_REQUIRE_LEGACY_SERVICE] = "true"
|
66
|
+
|
46
67
|
def apply(self) -> None:
|
47
68
|
"""Call require_* method for supported features."""
|
48
69
|
last_message: str = ""
|