wandb 0.17.5__py3-none-any.whl → 0.17.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. wandb/__init__.py +5 -16
  2. wandb/agents/pyagent.py +1 -2
  3. wandb/apis/public/api.py +1 -1
  4. wandb/apis/public/jobs.py +5 -0
  5. wandb/bin/nvidia_gpu_stats +0 -0
  6. wandb/cli/cli.py +21 -0
  7. wandb/data_types.py +5 -4
  8. wandb/env.py +6 -0
  9. wandb/integration/kfp/wandb_logging.py +1 -1
  10. wandb/integration/lightning/fabric/logger.py +5 -5
  11. wandb/integration/openai/fine_tuning.py +13 -5
  12. wandb/integration/ultralytics/pose_utils.py +0 -1
  13. wandb/proto/v3/wandb_internal_pb2.py +226 -226
  14. wandb/proto/v3/wandb_settings_pb2.py +1 -1
  15. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  16. wandb/proto/v4/wandb_internal_pb2.py +226 -226
  17. wandb/proto/v4/wandb_settings_pb2.py +1 -1
  18. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  19. wandb/proto/v5/wandb_internal_pb2.py +226 -226
  20. wandb/proto/v5/wandb_settings_pb2.py +1 -1
  21. wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
  22. wandb/proto/wandb_deprecated.py +4 -0
  23. wandb/proto/wandb_internal_pb2.py +6 -0
  24. wandb/sdk/artifacts/artifact.py +6 -1
  25. wandb/sdk/artifacts/artifact_manifest_entry.py +31 -0
  26. wandb/sdk/artifacts/storage_handlers/azure_handler.py +35 -23
  27. wandb/sdk/data_types/_dtypes.py +5 -5
  28. wandb/sdk/data_types/base_types/media.py +3 -1
  29. wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +3 -1
  30. wandb/sdk/data_types/helper_types/image_mask.py +3 -1
  31. wandb/sdk/data_types/image.py +3 -1
  32. wandb/sdk/data_types/object_3d.py +113 -2
  33. wandb/sdk/data_types/saved_model.py +3 -1
  34. wandb/sdk/interface/interface.py +40 -16
  35. wandb/sdk/interface/interface_shared.py +6 -9
  36. wandb/sdk/internal/datastore.py +1 -1
  37. wandb/sdk/internal/handler.py +0 -2
  38. wandb/sdk/internal/internal.py +1 -1
  39. wandb/sdk/internal/job_builder.py +5 -2
  40. wandb/sdk/internal/sender.py +31 -15
  41. wandb/sdk/internal/tb_watcher.py +2 -2
  42. wandb/sdk/internal/update.py +2 -2
  43. wandb/sdk/launch/_launch.py +4 -2
  44. wandb/sdk/launch/_project_spec.py +34 -8
  45. wandb/sdk/launch/agent/agent.py +6 -2
  46. wandb/sdk/launch/agent/run_queue_item_file_saver.py +2 -4
  47. wandb/sdk/launch/builder/build.py +4 -2
  48. wandb/sdk/launch/builder/kaniko_builder.py +13 -5
  49. wandb/sdk/launch/builder/templates/_wandb_bootstrap.py +2 -1
  50. wandb/sdk/launch/create_job.py +2 -0
  51. wandb/sdk/launch/inputs/internal.py +42 -28
  52. wandb/sdk/launch/inputs/schema.py +39 -0
  53. wandb/sdk/launch/runner/kubernetes_runner.py +72 -0
  54. wandb/sdk/launch/runner/local_container.py +13 -10
  55. wandb/sdk/launch/runner/sagemaker_runner.py +3 -5
  56. wandb/sdk/launch/utils.py +2 -0
  57. wandb/sdk/lib/apikey.py +1 -1
  58. wandb/sdk/lib/disabled.py +13 -174
  59. wandb/sdk/service/streams.py +2 -4
  60. wandb/sdk/wandb_config.py +1 -1
  61. wandb/sdk/wandb_init.py +77 -33
  62. wandb/sdk/wandb_login.py +6 -6
  63. wandb/sdk/wandb_run.py +150 -90
  64. wandb/sdk/wandb_settings.py +4 -3
  65. wandb/sdk/wandb_setup.py +66 -3
  66. wandb/sdk/wandb_sweep.py +5 -2
  67. wandb/wandb_agent.py +2 -0
  68. {wandb-0.17.5.dist-info → wandb-0.17.7.dist-info}/METADATA +3 -2
  69. {wandb-0.17.5.dist-info → wandb-0.17.7.dist-info}/RECORD +72 -70
  70. {wandb-0.17.5.dist-info → wandb-0.17.7.dist-info}/WHEEL +0 -0
  71. {wandb-0.17.5.dist-info → wandb-0.17.7.dist-info}/entry_points.txt +0 -0
  72. {wandb-0.17.5.dist-info → wandb-0.17.7.dist-info}/licenses/LICENSE +0 -0
@@ -16,7 +16,9 @@ from typing import Any, Dict, List, Optional
16
16
  import wandb
17
17
  import wandb.data_types
18
18
  from wandb.sdk.launch.errors import LaunchError
19
+ from wandb.sdk.launch.inputs.schema import META_SCHEMA
19
20
  from wandb.sdk.wandb_run import Run
21
+ from wandb.util import get_module
20
22
 
21
23
  from .files import config_path_is_valid, override_file
22
24
 
@@ -129,7 +131,7 @@ def _publish_job_input(
129
131
  )
130
132
 
131
133
 
132
- def _replace_refs_and_allofs(schema: dict, defs: dict) -> dict:
134
+ def _replace_refs_and_allofs(schema: dict, defs: Optional[dict]) -> dict:
133
135
  """Recursively fix JSON schemas with common issues.
134
136
 
135
137
  1. Replaces any instances of $ref with their associated definition in defs
@@ -137,7 +139,7 @@ def _replace_refs_and_allofs(schema: dict, defs: dict) -> dict:
137
139
  See test_internal.py for examples
138
140
  """
139
141
  ret: Dict[str, Any] = {}
140
- if "$ref" in schema:
142
+ if "$ref" in schema and defs:
141
143
  # Reference found, replace it with its definition
142
144
  def_key = schema["$ref"].split("#/$defs/")[1]
143
145
  # Also run recursive replacement in case a ref contains more refs
@@ -170,12 +172,16 @@ def _replace_refs_and_allofs(schema: dict, defs: dict) -> dict:
170
172
  return ret
171
173
 
172
174
 
173
- def _convert_pydantic_model_to_jsonschema(model: Any) -> dict:
174
- schema = model.model_json_schema()
175
- defs = schema.pop("$defs")
176
- if not defs:
177
- return schema
178
- return _replace_refs_and_allofs(schema, defs)
175
+ def _validate_schema(schema: dict) -> None:
176
+ jsonschema = get_module(
177
+ "jsonschema",
178
+ required="Setting job schema requires the jsonschema package. Please install it with `pip install 'wandb[launch]'`.",
179
+ lazy=False,
180
+ )
181
+ validator = jsonschema.Draft202012Validator(META_SCHEMA)
182
+ errs = sorted(validator.iter_errors(schema), key=str)
183
+ if errs:
184
+ wandb.termwarn(f"Schema includes unhandled or invalid configurations:\n{errs}")
179
185
 
180
186
 
181
187
  def handle_config_file_input(
@@ -204,16 +210,20 @@ def handle_config_file_input(
204
210
  path,
205
211
  dest,
206
212
  )
207
- # This supports both an instance of a pydantic BaseModel class (e.g. schema=MySchema(...))
208
- # or the BaseModel class itself (e.g. schema=MySchema)
209
- if hasattr(schema, "model_json_schema") and callable(
210
- schema.model_json_schema # type: ignore
211
- ):
212
- schema = _convert_pydantic_model_to_jsonschema(schema)
213
- if schema and not isinstance(schema, dict):
214
- raise LaunchError(
215
- "schema must be a dict, Pydantic model instance, or Pydantic model class."
216
- )
213
+ if schema:
214
+ # This supports both an instance of a pydantic BaseModel class (e.g. schema=MySchema(...))
215
+ # or the BaseModel class itself (e.g. schema=MySchema)
216
+ if hasattr(schema, "model_json_schema") and callable(
217
+ schema.model_json_schema # type: ignore
218
+ ):
219
+ schema = schema.model_json_schema()
220
+ if not isinstance(schema, dict):
221
+ raise LaunchError(
222
+ "schema must be a dict, Pydantic model instance, or Pydantic model class."
223
+ )
224
+ defs = schema.pop("$defs", None)
225
+ schema = _replace_refs_and_allofs(schema, defs)
226
+ _validate_schema(schema)
217
227
  arguments = JobInputArguments(
218
228
  include=include,
219
229
  exclude=exclude,
@@ -241,16 +251,20 @@ def handle_run_config_input(
241
251
  If there is no active run, the include and exclude paths are staged and sent
242
252
  when a run is created.
243
253
  """
244
- # This supports both an instance of a pydantic BaseModel class (e.g. schema=MySchema(...))
245
- # or the BaseModel class itself (e.g. schema=MySchema)
246
- if hasattr(schema, "model_json_schema") and callable(
247
- schema.model_json_schema # type: ignore
248
- ):
249
- schema = _convert_pydantic_model_to_jsonschema(schema)
250
- if schema and not isinstance(schema, dict):
251
- raise LaunchError(
252
- "schema must be a dict, Pydantic model instance, or Pydantic model class."
253
- )
254
+ if schema:
255
+ # This supports both an instance of a pydantic BaseModel class (e.g. schema=MySchema(...))
256
+ # or the BaseModel class itself (e.g. schema=MySchema)
257
+ if hasattr(schema, "model_json_schema") and callable(
258
+ schema.model_json_schema # type: ignore
259
+ ):
260
+ schema = schema.model_json_schema()
261
+ if not isinstance(schema, dict):
262
+ raise LaunchError(
263
+ "schema must be a dict, Pydantic model instance, or Pydantic model class."
264
+ )
265
+ defs = schema.pop("$defs", None)
266
+ schema = _replace_refs_and_allofs(schema, defs)
267
+ _validate_schema(schema)
254
268
  arguments = JobInputArguments(
255
269
  include=include,
256
270
  exclude=exclude,
@@ -0,0 +1,39 @@
1
+ META_SCHEMA = {
2
+ "type": "object",
3
+ "properties": {
4
+ "type": {
5
+ "type": "string",
6
+ "enum": ["boolean", "integer", "number", "string", "object"],
7
+ },
8
+ "title": {"type": "string"},
9
+ "description": {"type": "string"},
10
+ "enum": {"type": "array", "items": {"type": ["integer", "number", "string"]}},
11
+ "properties": {"type": "object", "patternProperties": {".*": {"$ref": "#"}}},
12
+ "allOf": {"type": "array", "items": {"$ref": "#"}},
13
+ },
14
+ "allOf": [
15
+ {
16
+ "if": {"properties": {"type": {"const": "number"}}},
17
+ "then": {
18
+ "properties": {
19
+ "minimum": {"type": ["integer", "number"]},
20
+ "maximum": {"type": ["integer", "number"]},
21
+ "exclusiveMinimum": {"type": ["integer", "number"]},
22
+ "exclusiveMaximum": {"type": ["integer", "number"]},
23
+ }
24
+ },
25
+ },
26
+ {
27
+ "if": {"properties": {"type": {"const": "integer"}}},
28
+ "then": {
29
+ "properties": {
30
+ "minimum": {"type": "integer"},
31
+ "maximum": {"type": "integer"},
32
+ "exclusiveMinimum": {"type": "integer"},
33
+ "exclusiveMaximum": {"type": "integer"},
34
+ }
35
+ },
36
+ },
37
+ ],
38
+ "unevaluatedProperties": False,
39
+ }
@@ -31,6 +31,7 @@ from wandb.util import get_module
31
31
  from .._project_spec import EntryPoint, LaunchProject
32
32
  from ..errors import LaunchError
33
33
  from ..utils import (
34
+ CODE_MOUNT_DIR,
34
35
  LOG_PREFIX,
35
36
  MAX_ENV_LENGTHS,
36
37
  PROJECT_SYNCHRONOUS,
@@ -66,6 +67,10 @@ API_KEY_SECRET_MAX_RETRIES = 5
66
67
  _logger = logging.getLogger(__name__)
67
68
 
68
69
 
70
+ SOURCE_CODE_PVC_MOUNT_PATH = os.environ.get("WANDB_LAUNCH_CODE_PVC_MOUNT_PATH")
71
+ SOURCE_CODE_PVC_NAME = os.environ.get("WANDB_LAUNCH_CODE_PVC_NAME")
72
+
73
+
69
74
  class KubernetesSubmittedRun(AbstractRun):
70
75
  """Wrapper for a launched run on Kubernetes."""
71
76
 
@@ -468,6 +473,12 @@ class KubernetesRunner(AbstractRunner):
468
473
  "true",
469
474
  )
470
475
 
476
+ if launch_project.job_base_image:
477
+ apply_code_mount_configuration(
478
+ job,
479
+ launch_project,
480
+ )
481
+
471
482
  # Add wandb.ai/agent: current agent label on all pods
472
483
  if LaunchAgent.initialized():
473
484
  add_label_to_pods(
@@ -504,6 +515,22 @@ class KubernetesRunner(AbstractRunner):
504
515
  kubernetes_asyncio, resource_args
505
516
  )
506
517
 
518
+ # If using pvc for code mount, move code there.
519
+ if launch_project.job_base_image is not None:
520
+ if SOURCE_CODE_PVC_NAME is None or SOURCE_CODE_PVC_MOUNT_PATH is None:
521
+ raise LaunchError(
522
+ "WANDB_LAUNCH_SOURCE_CODE_PVC_ environment variables not set. "
523
+ "Unable to mount source code PVC into base image. "
524
+ "Use the `codeMountPvcName` variable in the agent helm chart "
525
+ "to enable base image jobs for this agent. See "
526
+ "https://github.com/wandb/helm-charts/tree/main/charts/launch-agent "
527
+ "for more information."
528
+ )
529
+ code_subdir = launch_project.get_image_source_string()
530
+ launch_project.change_project_dir(
531
+ os.path.join(SOURCE_CODE_PVC_MOUNT_PATH, code_subdir)
532
+ )
533
+
507
534
  # If the user specified an alternate api, we need will execute this
508
535
  # run by creating a custom object.
509
536
  api_version = resource_args.get("apiVersion", "batch/v1")
@@ -542,6 +569,9 @@ class KubernetesRunner(AbstractRunner):
542
569
  LaunchAgent.name()
543
570
  )
544
571
 
572
+ if launch_project.job_base_image:
573
+ apply_code_mount_configuration(resource_args, launch_project)
574
+
545
575
  overrides = {}
546
576
  if launch_project.override_args:
547
577
  overrides["args"] = launch_project.override_args
@@ -889,3 +919,45 @@ def add_entrypoint_args_overrides(manifest: Union[dict, list], overrides: dict)
889
919
  container["args"] = overrides["args"]
890
920
  for value in manifest.values():
891
921
  add_entrypoint_args_overrides(value, overrides)
922
+
923
+
924
+ def apply_code_mount_configuration(
925
+ manifest: Union[Dict, list], project: LaunchProject
926
+ ) -> None:
927
+ """Apply code mount configuration to all containers in a manifest.
928
+
929
+ Recursively traverses the manifest and adds the code mount configuration to
930
+ all containers. Containers are identified by the presence of a "spec" key
931
+ with a "containers" key in the value.
932
+
933
+ Arguments:
934
+ manifest: The manifest to modify.
935
+ project: The launch project.
936
+
937
+ Returns: None.
938
+ """
939
+ assert SOURCE_CODE_PVC_NAME is not None
940
+ source_dir = project.get_image_source_string()
941
+ for pod in yield_pods(manifest):
942
+ for container in yield_containers(pod):
943
+ if "volumeMounts" not in container:
944
+ container["volumeMounts"] = []
945
+ container["volumeMounts"].append(
946
+ {
947
+ "name": "wandb-source-code-volume",
948
+ "mountPath": CODE_MOUNT_DIR,
949
+ "subPath": source_dir,
950
+ }
951
+ )
952
+ container["workingDir"] = CODE_MOUNT_DIR
953
+ spec = pod["spec"]
954
+ if "volumes" not in spec:
955
+ spec["volumes"] = []
956
+ spec["volumes"].append(
957
+ {
958
+ "name": "wandb-source-code-volume",
959
+ "persistentVolumeClaim": {
960
+ "claimName": SOURCE_CODE_PVC_NAME,
961
+ },
962
+ }
963
+ )
@@ -14,6 +14,7 @@ from wandb.sdk.launch.registry.abstract import AbstractRegistry
14
14
  from .._project_spec import LaunchProject
15
15
  from ..errors import LaunchError
16
16
  from ..utils import (
17
+ CODE_MOUNT_DIR,
17
18
  LOG_PREFIX,
18
19
  MAX_ENV_LENGTHS,
19
20
  PROJECT_SYNCHRONOUS,
@@ -121,7 +122,15 @@ class LocalContainerRunner(AbstractRunner):
121
122
  docker_args["network"] = "host"
122
123
  if sys.platform == "linux" or sys.platform == "linux2":
123
124
  docker_args["add-host"] = "host.docker.internal:host-gateway"
124
-
125
+ base_image = launch_project.job_base_image
126
+ if base_image is not None:
127
+ # Mount code into the container and set the working directory.
128
+ if "volume" not in docker_args:
129
+ docker_args["volume"] = []
130
+ docker_args["volume"].append(
131
+ f"{launch_project.project_dir}:{CODE_MOUNT_DIR}"
132
+ )
133
+ docker_args["workdir"] = CODE_MOUNT_DIR
125
134
  return docker_args
126
135
 
127
136
  async def run(
@@ -146,7 +155,7 @@ class LocalContainerRunner(AbstractRunner):
146
155
  elif _is_wandb_dev_uri(self._api.settings("base_url")):
147
156
  env_vars["WANDB_BASE_URL"] = "http://host.docker.internal:9001"
148
157
 
149
- if launch_project.docker_image:
158
+ if launch_project.docker_image or launch_project.job_base_image:
150
159
  try:
151
160
  pull_docker_image(image_uri)
152
161
  except Exception as e:
@@ -156,14 +165,8 @@ class LocalContainerRunner(AbstractRunner):
156
165
  f"Failed to pull docker image {image_uri} with error: {e}"
157
166
  )
158
167
 
159
- assert launch_project.docker_image == image_uri
160
-
161
- entry_cmd = (
162
- launch_project.override_entrypoint.command
163
- if launch_project.override_entrypoint is not None
164
- else None
165
- )
166
-
168
+ entrypoint = launch_project.get_job_entry_point()
169
+ entry_cmd = None if entrypoint is None else entrypoint.command
167
170
  command_str = " ".join(
168
171
  get_docker_command(
169
172
  image_uri,
@@ -221,7 +221,6 @@ class SageMakerRunner(AbstractRunner):
221
221
  await run.wait()
222
222
  return run
223
223
 
224
- launch_project.fill_macros(image_uri)
225
224
  _logger.info("Connecting to sagemaker client")
226
225
  entry_point = (
227
226
  launch_project.override_entrypoint or launch_project.get_job_entry_point()
@@ -296,13 +295,12 @@ def build_sagemaker_args(
296
295
  entry_point: Optional[EntryPoint],
297
296
  args: Optional[List[str]],
298
297
  max_env_length: int,
299
- image_uri: Optional[str] = None,
298
+ image_uri: str,
300
299
  default_output_path: Optional[str] = None,
301
300
  ) -> Dict[str, Any]:
302
301
  sagemaker_args: Dict[str, Any] = {}
303
- given_sagemaker_args: Optional[Dict[str, Any]] = launch_project.resource_args.get(
304
- "sagemaker"
305
- )
302
+ resource_args = launch_project.fill_macros(image_uri)
303
+ given_sagemaker_args: Optional[Dict[str, Any]] = resource_args.get("sagemaker")
306
304
 
307
305
  if given_sagemaker_args is None:
308
306
  raise LaunchError(
wandb/sdk/launch/utils.py CHANGED
@@ -87,6 +87,8 @@ LOG_PREFIX = f"{click.style('launch:', fg='magenta')} "
87
87
  MAX_ENV_LENGTHS: Dict[str, int] = defaultdict(lambda: 32670)
88
88
  MAX_ENV_LENGTHS["SageMakerRunner"] = 512
89
89
 
90
+ CODE_MOUNT_DIR = "/mnt/wandb"
91
+
90
92
 
91
93
  def load_wandb_config() -> Config:
92
94
  """Load wandb config from WANDB_CONFIG environment variable(s).
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/lib/disabled.py CHANGED
@@ -1,178 +1,6 @@
1
- #
1
+ from typing import Any
2
2
 
3
-
4
- class RunDisabled(str):
5
- def __init__(self, *args, **kwargs):
6
- object.__setattr__(self, "___dict", {})
7
-
8
- def __add__(self, other):
9
- return self
10
-
11
- def __sub__(self, other):
12
- return self
13
-
14
- def __mul__(self, other):
15
- return self
16
-
17
- def __truediv__(self, other):
18
- return self
19
-
20
- def __floordiv__(self, other):
21
- return self
22
-
23
- def __mod__(self, other):
24
- return self
25
-
26
- def __pow__(self, other, modulo=None):
27
- return self
28
-
29
- def __lshift__(self, other):
30
- return self
31
-
32
- def __rshift__(self, other):
33
- return self
34
-
35
- def __and__(self, other):
36
- return self
37
-
38
- def __xor__(self, other):
39
- return self
40
-
41
- def __or__(self, other):
42
- return self
43
-
44
- def __iadd__(self, other):
45
- return self
46
-
47
- def __isub__(self, other):
48
- return self
49
-
50
- def __imul__(self, other):
51
- return self
52
-
53
- def __idiv__(self, other):
54
- return self
55
-
56
- def __ifloordiv__(self, other):
57
- return self
58
-
59
- def __imod__(self, other):
60
- return self
61
-
62
- def __ipow__(self, other, modulo=None):
63
- return self
64
-
65
- def __ilshift__(self, other):
66
- return self
67
-
68
- def __irshift__(self, other):
69
- return self
70
-
71
- def __iand__(self, other):
72
- return self
73
-
74
- def __ixor__(self, other):
75
- return self
76
-
77
- def __ior__(self, other):
78
- return self
79
-
80
- def __neg__(self):
81
- return self
82
-
83
- def __pos__(self):
84
- return self
85
-
86
- def __abs__(self):
87
- return self
88
-
89
- def __invert__(self):
90
- return self
91
-
92
- def __complex__(self):
93
- return 1 + 0j
94
-
95
- def __int__(self):
96
- return 1
97
-
98
- def __long__(self):
99
- return 1
100
-
101
- def __float__(self):
102
- return 1.0
103
-
104
- def __oct__(self):
105
- return oct(1)
106
-
107
- def __hex__(self):
108
- return hex(1)
109
-
110
- def __lt__(self, other):
111
- return True
112
-
113
- def __le__(self, other):
114
- return True
115
-
116
- def __eq__(self, other):
117
- return True
118
-
119
- def __ne__(self, other):
120
- return True
121
-
122
- def __gt__(self, other):
123
- return True
124
-
125
- def __ge__(self, other):
126
- return True
127
-
128
- def __getattr__(self, attr):
129
- return self[attr]
130
-
131
- def __getitem__(self, key):
132
- d = object.__getattribute__(self, "___dict")
133
- try:
134
- if key in d:
135
- return d[key]
136
- except TypeError:
137
- key = str(key)
138
- if key in d:
139
- return d[key]
140
- dummy = RunDisabled()
141
- d[key] = dummy
142
- return dummy
143
-
144
- def __setitem__(self, key, value):
145
- object.__getattribute__(self, "___dict")[key] = value
146
-
147
- def __setattr__(self, key, value):
148
- self[key] = value
149
-
150
- def __call__(self, *args, **kwargs):
151
- return RunDisabled()
152
-
153
- def __len__(self):
154
- return 1
155
-
156
- def __str__(self):
157
- return ""
158
-
159
- def __enter__(self):
160
- return self
161
-
162
- def __exit__(self, exc_type, exc_val, exc_tb):
163
- return exc_type is None
164
-
165
- def __repr__(self):
166
- return ""
167
-
168
- def __nonzero__(self):
169
- return True
170
-
171
- def __bool__(self):
172
- return True
173
-
174
- def __getstate__(self):
175
- return 1
3
+ from wandb.sdk.lib import deprecate
176
4
 
177
5
 
178
6
  class SummaryDisabled(dict):
@@ -188,3 +16,14 @@ class SummaryDisabled(dict):
188
16
  val = SummaryDisabled(val)
189
17
  self[key] = val
190
18
  return val
19
+
20
+
21
+ class RunDisabled:
22
+ """Compatibility class for integrations that explicitly check for wandb.RunDisabled."""
23
+
24
+ def __getattr__(self, name: str) -> Any:
25
+ deprecate.deprecate(
26
+ field_name=deprecate.Deprecated.run_disabled,
27
+ warning_message="RunDisabled is deprecated and is a no-op. "
28
+ '`wandb.init(mode="disabled")` now returns and instance of `wandb.sdk.wandb_run.Run`.',
29
+ )
@@ -81,9 +81,7 @@ class StreamRecord:
81
81
  self._wait_thread_active()
82
82
 
83
83
  def _wait_thread_active(self) -> None:
84
- result = self._iface.communicate_status()
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(model’, None, model to run) # name, default, help
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