wandb 0.17.0rc1__py3-none-win_amd64.whl → 0.17.1__py3-none-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. wandb/__init__.py +1 -2
  2. wandb/apis/importers/internals/internal.py +0 -1
  3. wandb/apis/importers/wandb.py +12 -7
  4. wandb/apis/internal.py +0 -3
  5. wandb/apis/public/api.py +213 -79
  6. wandb/apis/public/artifacts.py +335 -100
  7. wandb/apis/public/files.py +9 -9
  8. wandb/apis/public/jobs.py +16 -4
  9. wandb/apis/public/projects.py +26 -28
  10. wandb/apis/public/query_generator.py +1 -1
  11. wandb/apis/public/runs.py +163 -65
  12. wandb/apis/public/sweeps.py +2 -2
  13. wandb/apis/reports/__init__.py +1 -7
  14. wandb/apis/reports/v1/__init__.py +5 -27
  15. wandb/apis/reports/v2/__init__.py +7 -19
  16. wandb/apis/workspaces/__init__.py +8 -0
  17. wandb/beta/workflows.py +8 -3
  18. wandb/bin/wandb-core +0 -0
  19. wandb/cli/cli.py +131 -59
  20. wandb/data_types.py +6 -3
  21. wandb/docker/__init__.py +2 -2
  22. wandb/env.py +3 -3
  23. wandb/errors/term.py +10 -2
  24. wandb/filesync/step_checksum.py +1 -4
  25. wandb/filesync/step_prepare.py +4 -24
  26. wandb/filesync/step_upload.py +5 -107
  27. wandb/filesync/upload_job.py +0 -76
  28. wandb/integration/gym/__init__.py +35 -15
  29. wandb/integration/huggingface/resolver.py +2 -2
  30. wandb/integration/keras/callbacks/metrics_logger.py +1 -1
  31. wandb/integration/keras/keras.py +1 -1
  32. wandb/integration/openai/fine_tuning.py +21 -3
  33. wandb/integration/prodigy/prodigy.py +1 -1
  34. wandb/jupyter.py +16 -17
  35. wandb/old/summary.py +1 -1
  36. wandb/plot/confusion_matrix.py +1 -1
  37. wandb/plot/pr_curve.py +2 -1
  38. wandb/plot/roc_curve.py +2 -1
  39. wandb/{plots → plot}/utils.py +13 -25
  40. wandb/proto/v3/wandb_internal_pb2.py +54 -54
  41. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  42. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  43. wandb/proto/v4/wandb_internal_pb2.py +54 -54
  44. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  45. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  46. wandb/proto/v5/wandb_base_pb2.py +30 -0
  47. wandb/proto/v5/wandb_internal_pb2.py +355 -0
  48. wandb/proto/v5/wandb_server_pb2.py +63 -0
  49. wandb/proto/v5/wandb_settings_pb2.py +45 -0
  50. wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
  51. wandb/proto/wandb_base_pb2.py +2 -0
  52. wandb/proto/wandb_deprecated.py +9 -1
  53. wandb/proto/wandb_generate_deprecated.py +34 -0
  54. wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
  55. wandb/proto/wandb_internal_pb2.py +2 -0
  56. wandb/proto/wandb_server_pb2.py +2 -0
  57. wandb/proto/wandb_settings_pb2.py +2 -0
  58. wandb/proto/wandb_telemetry_pb2.py +2 -0
  59. wandb/sdk/artifacts/artifact.py +68 -22
  60. wandb/sdk/artifacts/artifact_manifest.py +1 -1
  61. wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
  62. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
  63. wandb/sdk/artifacts/artifact_saver.py +1 -10
  64. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
  65. wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
  66. wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
  67. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
  68. wandb/sdk/artifacts/storage_policy.py +1 -12
  69. wandb/sdk/data_types/_dtypes.py +8 -8
  70. wandb/sdk/data_types/image.py +2 -2
  71. wandb/sdk/data_types/video.py +5 -3
  72. wandb/sdk/integration_utils/data_logging.py +5 -5
  73. wandb/sdk/interface/interface.py +14 -1
  74. wandb/sdk/interface/interface_shared.py +1 -1
  75. wandb/sdk/internal/file_pusher.py +2 -5
  76. wandb/sdk/internal/file_stream.py +6 -19
  77. wandb/sdk/internal/internal_api.py +148 -136
  78. wandb/sdk/internal/job_builder.py +208 -136
  79. wandb/sdk/internal/progress.py +0 -28
  80. wandb/sdk/internal/sender.py +102 -39
  81. wandb/sdk/internal/settings_static.py +8 -1
  82. wandb/sdk/internal/system/assets/trainium.py +3 -3
  83. wandb/sdk/internal/system/system_info.py +4 -2
  84. wandb/sdk/internal/update.py +1 -1
  85. wandb/sdk/launch/__init__.py +9 -1
  86. wandb/sdk/launch/_launch.py +4 -24
  87. wandb/sdk/launch/_launch_add.py +1 -3
  88. wandb/sdk/launch/_project_spec.py +187 -225
  89. wandb/sdk/launch/agent/agent.py +59 -19
  90. wandb/sdk/launch/agent/config.py +0 -3
  91. wandb/sdk/launch/builder/abstract.py +68 -1
  92. wandb/sdk/launch/builder/build.py +165 -576
  93. wandb/sdk/launch/builder/context_manager.py +235 -0
  94. wandb/sdk/launch/builder/docker_builder.py +7 -23
  95. wandb/sdk/launch/builder/kaniko_builder.py +12 -25
  96. wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
  97. wandb/sdk/launch/create_job.py +51 -45
  98. wandb/sdk/launch/environment/aws_environment.py +26 -1
  99. wandb/sdk/launch/inputs/files.py +148 -0
  100. wandb/sdk/launch/inputs/internal.py +224 -0
  101. wandb/sdk/launch/inputs/manage.py +95 -0
  102. wandb/sdk/launch/registry/google_artifact_registry.py +1 -1
  103. wandb/sdk/launch/runner/abstract.py +2 -2
  104. wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
  105. wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
  106. wandb/sdk/launch/runner/local_container.py +2 -3
  107. wandb/sdk/launch/runner/local_process.py +8 -29
  108. wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
  109. wandb/sdk/launch/runner/vertex_runner.py +8 -7
  110. wandb/sdk/launch/sweeps/scheduler.py +5 -3
  111. wandb/sdk/launch/sweeps/scheduler_sweep.py +1 -1
  112. wandb/sdk/launch/sweeps/utils.py +4 -4
  113. wandb/sdk/launch/utils.py +16 -138
  114. wandb/sdk/lib/_settings_toposort_generated.py +2 -5
  115. wandb/sdk/lib/apikey.py +4 -2
  116. wandb/sdk/lib/config_util.py +3 -3
  117. wandb/sdk/lib/import_hooks.py +1 -1
  118. wandb/sdk/lib/proto_util.py +22 -1
  119. wandb/sdk/lib/redirect.py +20 -15
  120. wandb/sdk/lib/tracelog.py +1 -1
  121. wandb/sdk/service/service.py +2 -1
  122. wandb/sdk/service/streams.py +5 -5
  123. wandb/sdk/wandb_init.py +25 -59
  124. wandb/sdk/wandb_login.py +28 -25
  125. wandb/sdk/wandb_run.py +123 -53
  126. wandb/sdk/wandb_settings.py +33 -64
  127. wandb/sdk/wandb_setup.py +1 -1
  128. wandb/sdk/wandb_watch.py +1 -1
  129. wandb/sklearn/plot/classifier.py +10 -12
  130. wandb/sklearn/plot/clusterer.py +1 -1
  131. wandb/sync/sync.py +2 -2
  132. wandb/testing/relay.py +32 -17
  133. wandb/util.py +36 -37
  134. wandb/wandb_agent.py +3 -3
  135. wandb/wandb_controller.py +5 -4
  136. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/METADATA +8 -10
  137. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/RECORD +140 -162
  138. wandb/apis/reports/v1/_blocks.py +0 -1406
  139. wandb/apis/reports/v1/_helpers.py +0 -70
  140. wandb/apis/reports/v1/_panels.py +0 -1282
  141. wandb/apis/reports/v1/_templates.py +0 -478
  142. wandb/apis/reports/v1/blocks.py +0 -27
  143. wandb/apis/reports/v1/helpers.py +0 -2
  144. wandb/apis/reports/v1/mutations.py +0 -66
  145. wandb/apis/reports/v1/panels.py +0 -17
  146. wandb/apis/reports/v1/report.py +0 -268
  147. wandb/apis/reports/v1/runset.py +0 -144
  148. wandb/apis/reports/v1/templates.py +0 -7
  149. wandb/apis/reports/v1/util.py +0 -406
  150. wandb/apis/reports/v1/validators.py +0 -131
  151. wandb/apis/reports/v2/blocks.py +0 -25
  152. wandb/apis/reports/v2/expr_parsing.py +0 -257
  153. wandb/apis/reports/v2/gql.py +0 -68
  154. wandb/apis/reports/v2/interface.py +0 -1911
  155. wandb/apis/reports/v2/internal.py +0 -867
  156. wandb/apis/reports/v2/metrics.py +0 -6
  157. wandb/apis/reports/v2/panels.py +0 -15
  158. wandb/catboost/__init__.py +0 -9
  159. wandb/fastai/__init__.py +0 -9
  160. wandb/keras/__init__.py +0 -19
  161. wandb/lightgbm/__init__.py +0 -9
  162. wandb/plots/__init__.py +0 -6
  163. wandb/plots/explain_text.py +0 -36
  164. wandb/plots/heatmap.py +0 -81
  165. wandb/plots/named_entity.py +0 -43
  166. wandb/plots/part_of_speech.py +0 -50
  167. wandb/plots/plot_definitions.py +0 -768
  168. wandb/plots/precision_recall.py +0 -121
  169. wandb/plots/roc.py +0 -103
  170. wandb/sacred/__init__.py +0 -3
  171. wandb/xgboost/__init__.py +0 -9
  172. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/WHEEL +0 -0
  173. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/entry_points.txt +0 -0
  174. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/launch/utils.py CHANGED
@@ -1,4 +1,3 @@
1
- # heavily inspired by https://github.com/mlflow/mlflow/blob/master/mlflow/projects/utils.py
2
1
  import asyncio
3
2
  import json
4
3
  import logging
@@ -16,7 +15,6 @@ import wandb
16
15
  import wandb.docker as docker
17
16
  from wandb import util
18
17
  from wandb.apis.internal import Api
19
- from wandb.errors import CommError
20
18
  from wandb.sdk.launch.errors import LaunchError
21
19
  from wandb.sdk.launch.git_reference import GitReference
22
20
  from wandb.sdk.launch.wandb_reference import WandbReference
@@ -32,12 +30,13 @@ FAILED_PACKAGES_REGEX = re.compile(
32
30
  )
33
31
 
34
32
  if TYPE_CHECKING: # pragma: no cover
35
- from wandb.sdk.artifacts.artifact import Artifact
36
33
  from wandb.sdk.launch.agent.job_status_tracker import JobAndRunStatusTracker
37
34
 
38
35
 
39
36
  # TODO: this should be restricted to just Git repos and not S3 and stuff like that
40
- _GIT_URI_REGEX = re.compile(r"^[^/|^~|^\.].*(git|bitbucket)")
37
+ _GIT_URI_REGEX = re.compile(
38
+ r"^[^/|^~|^\.].*(git|bitbucket|dev\.azure\.com|\.visualstudio\.com)"
39
+ )
41
40
  _VALID_IP_REGEX = r"^https?://[0-9]+(?:\.[0-9]+){3}(:[0-9]+)?"
42
41
  _VALID_PIP_PACKAGE_REGEX = r"^[a-zA-Z0-9_.-]+$"
43
42
  _VALID_WANDB_REGEX = r"^https?://(api.)?wandb"
@@ -75,6 +74,7 @@ AZURE_BLOB_REGEX = re.compile(
75
74
  r"^https://([^\.]+)\.blob\.core\.windows\.net/([^/]+)/?(.*)$"
76
75
  )
77
76
 
77
+ ARN_PARTITION_RE = re.compile(r"^arn:([^:]+):[^:]*:[^:]*:[^:]*:[^:]*$")
78
78
 
79
79
  PROJECT_SYNCHRONOUS = "SYNCHRONOUS"
80
80
 
@@ -316,16 +316,13 @@ def construct_launch_spec(
316
316
 
317
317
 
318
318
  def validate_launch_spec_source(launch_spec: Dict[str, Any]) -> None:
319
- uri = launch_spec.get("uri")
320
319
  job = launch_spec.get("job")
321
320
  docker_image = launch_spec.get("docker", {}).get("docker_image")
322
-
323
- if not bool(uri) and not bool(job) and not bool(docker_image):
324
- raise LaunchError("Must specify a uri, job or docker image")
325
- elif bool(uri) and bool(docker_image):
326
- raise LaunchError("Found both uri and docker-image, only one can be set")
327
- elif sum(map(bool, [uri, job, docker_image])) > 1:
328
- raise LaunchError("Must specify exactly one of uri, job or image")
321
+ if bool(job) == bool(docker_image):
322
+ raise LaunchError(
323
+ "Exactly one of job or docker_image must be specified in the launch "
324
+ "spec."
325
+ )
329
326
 
330
327
 
331
328
  def parse_wandb_uri(uri: str) -> Tuple[str, str, str]:
@@ -336,77 +333,6 @@ def parse_wandb_uri(uri: str) -> Tuple[str, str, str]:
336
333
  return (ref.entity, ref.project, ref.run_id)
337
334
 
338
335
 
339
- def is_bare_wandb_uri(uri: str) -> bool:
340
- """Check that a wandb uri is valid.
341
-
342
- URI must be in the format
343
- `/<entity>/<project>/runs/<run_name>[other stuff]`
344
- or
345
- `/<entity>/<project>/artifacts/job/<job_name>[other stuff]`.
346
- """
347
- _logger.info(f"Checking if uri {uri} is bare...")
348
- return uri.startswith("/") and WandbReference.is_uri_job_or_run(uri)
349
-
350
-
351
- def fetch_wandb_project_run_info(
352
- entity: str, project: str, run_name: str, api: Api
353
- ) -> Any:
354
- _logger.info("Fetching run info...")
355
- try:
356
- result = api.get_run_info(entity, project, run_name)
357
- except CommError:
358
- result = None
359
- if result is None:
360
- raise LaunchError(
361
- f"Run info is invalid or doesn't exist for {api.settings('base_url')}/{entity}/{project}/runs/{run_name}"
362
- )
363
- if result.get("codePath") is None:
364
- # TODO: we don't currently expose codePath in the runInfo endpoint, this downloads
365
- # it from wandb-metadata.json if we can.
366
- metadata = api.download_url(
367
- project, "wandb-metadata.json", run=run_name, entity=entity
368
- )
369
- if metadata is not None:
370
- _, response = api.download_file(metadata["url"])
371
- data = response.json()
372
- result["codePath"] = data.get("codePath")
373
- result["cudaVersion"] = data.get("cuda", None)
374
-
375
- return result
376
-
377
-
378
- def download_entry_point(
379
- entity: str, project: str, run_name: str, api: Api, entry_point: str, dir: str
380
- ) -> bool:
381
- metadata = api.download_url(
382
- project, f"code/{entry_point}", run=run_name, entity=entity
383
- )
384
- if metadata is not None:
385
- _, response = api.download_file(metadata["url"])
386
- with util.fsync_open(os.path.join(dir, entry_point), "wb") as file:
387
- for data in response.iter_content(chunk_size=1024):
388
- file.write(data)
389
- return True
390
- return False
391
-
392
-
393
- def download_wandb_python_deps(
394
- entity: str, project: str, run_name: str, api: Api, dir: str
395
- ) -> Optional[str]:
396
- reqs = api.download_url(project, "requirements.txt", run=run_name, entity=entity)
397
- if reqs is not None:
398
- _logger.info("Downloading python dependencies")
399
- _, response = api.download_file(reqs["url"])
400
-
401
- with util.fsync_open(
402
- os.path.join(dir, "requirements.frozen.txt"), "wb"
403
- ) as file:
404
- for data in response.iter_content(chunk_size=1024):
405
- file.write(data)
406
- return "requirements.frozen.txt"
407
- return None
408
-
409
-
410
336
  def get_local_python_deps(
411
337
  dir: str, filename: str = "requirements.local.txt"
412
338
  ) -> Optional[str]:
@@ -498,19 +424,6 @@ def validate_wandb_python_deps(
498
424
  _logger.warning("Unable to validate local python dependencies")
499
425
 
500
426
 
501
- def fetch_project_diff(
502
- entity: str, project: str, run_name: str, api: Api
503
- ) -> Optional[str]:
504
- """Fetches project diff from wandb servers."""
505
- _logger.info("Searching for diff.patch")
506
- patch = None
507
- try:
508
- (_, _, patch, _) = api.run_config(project, run_name, entity)
509
- except CommError:
510
- pass
511
- return patch
512
-
513
-
514
427
  def apply_patch(patch_string: str, dst_dir: str) -> None:
515
428
  """Applies a patch file to a directory."""
516
429
  _logger.info("Applying diff.patch")
@@ -531,17 +444,6 @@ def apply_patch(patch_string: str, dst_dir: str) -> None:
531
444
  raise wandb.Error("Failed to apply diff.patch associated with run.")
532
445
 
533
446
 
534
- def _make_refspec_from_version(version: Optional[str]) -> List[str]:
535
- """Create a refspec that checks for the existence of origin/main and the version."""
536
- if version:
537
- return [f"+{version}"]
538
-
539
- return [
540
- "+refs/heads/main*:refs/remotes/origin/main*",
541
- "+refs/heads/master*:refs/remotes/origin/master*",
542
- ]
543
-
544
-
545
447
  def _fetch_git_repo(dst_dir: str, uri: str, version: Optional[str]) -> Optional[str]:
546
448
  """Clones the git repo at ``uri`` into ``dst_dir``.
547
449
 
@@ -561,13 +463,6 @@ def _fetch_git_repo(dst_dir: str, uri: str, version: Optional[str]) -> Optional[
561
463
  return version
562
464
 
563
465
 
564
- def merge_parameters(
565
- higher_priority_params: Dict[str, Any], lower_priority_params: Dict[str, Any]
566
- ) -> Dict[str, Any]:
567
- """Merge the contents of two dicts, keeping values from higher_priority_params if there are conflicts."""
568
- return {**lower_priority_params, **higher_priority_params}
569
-
570
-
571
466
  def convert_jupyter_notebook_to_script(fname: str, project_dir: str) -> str:
572
467
  nbconvert = wandb.util.get_module(
573
468
  "nbconvert", "nbformat and nbconvert are required to use launch with notebooks"
@@ -597,25 +492,6 @@ def convert_jupyter_notebook_to_script(fname: str, project_dir: str) -> str:
597
492
  return new_name
598
493
 
599
494
 
600
- def check_and_download_code_artifacts(
601
- entity: str, project: str, run_name: str, internal_api: Api, project_dir: str
602
- ) -> Optional["Artifact"]:
603
- _logger.info("Checking for code artifacts")
604
- public_api = wandb.PublicApi(
605
- overrides={"base_url": internal_api.settings("base_url")}
606
- )
607
-
608
- run = public_api.run(f"{entity}/{project}/{run_name}")
609
- run_artifacts = run.logged_artifacts()
610
-
611
- for artifact in run_artifacts:
612
- if hasattr(artifact, "type") and artifact.type == "code":
613
- artifact.download(project_dir)
614
- return artifact # type: ignore
615
-
616
- return None
617
-
618
-
619
495
  def to_camel_case(maybe_snake_str: str) -> str:
620
496
  if "_" not in maybe_snake_str:
621
497
  return maybe_snake_str
@@ -623,11 +499,6 @@ def to_camel_case(maybe_snake_str: str) -> str:
623
499
  return "".join(x.title() if x else "_" for x in components)
624
500
 
625
501
 
626
- def run_shell(args: List[str]) -> Tuple[str, str]:
627
- out = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
628
- return out.stdout.decode("utf-8").strip(), out.stderr.decode("utf-8").strip()
629
-
630
-
631
502
  def validate_build_and_registry_configs(
632
503
  build_config: Dict[str, Any], registry_config: Dict[str, Any]
633
504
  ) -> None:
@@ -864,3 +735,10 @@ def get_entrypoint_file(entrypoint: List[str]) -> Optional[str]:
864
735
  if len(entrypoint) < 2:
865
736
  return None
866
737
  return entrypoint[1]
738
+
739
+
740
+ def get_current_python_version() -> Tuple[str, str]:
741
+ full_version = sys.version.split()[0].split(".")
742
+ major = full_version[0]
743
+ version = ".".join(full_version[:2]) if len(full_version) >= 2 else major + ".0"
744
+ return version, major
@@ -13,7 +13,6 @@ else:
13
13
  _Setting = Literal[
14
14
  "_args",
15
15
  "_aws_lambda",
16
- "_async_upload_concurrency_limit",
17
16
  "_cli_only_mode",
18
17
  "_code_path_local",
19
18
  "_colab",
@@ -25,7 +24,6 @@ _Setting = Literal[
25
24
  "_disable_update_check",
26
25
  "_disable_viewer",
27
26
  "_disable_machine_info",
28
- "_except_exit",
29
27
  "_executable",
30
28
  "_extra_http_headers",
31
29
  "_file_stream_retry_max",
@@ -92,6 +90,7 @@ _Setting = Literal[
92
90
  "colab_url",
93
91
  "config_paths",
94
92
  "console",
93
+ "console_multipart",
95
94
  "deployment",
96
95
  "disable_code",
97
96
  "disable_git",
@@ -104,6 +103,7 @@ _Setting = Literal[
104
103
  "files_dir",
105
104
  "force",
106
105
  "fork_from",
106
+ "resume_from",
107
107
  "git_commit",
108
108
  "git_remote",
109
109
  "git_remote_url",
@@ -126,7 +126,6 @@ _Setting = Literal[
126
126
  "login_timeout",
127
127
  "mode",
128
128
  "notebook_name",
129
- "problem",
130
129
  "program",
131
130
  "program_abspath",
132
131
  "program_relpath",
@@ -179,7 +178,6 @@ _Setting = Literal[
179
178
  ]
180
179
 
181
180
  SETTINGS_TOPOLOGICALLY_SORTED: Final[Tuple[_Setting, ...]] = (
182
- "_async_upload_concurrency_limit",
183
181
  "_service_wait",
184
182
  "_stats_sample_rate_seconds",
185
183
  "_stats_samples_to_average",
@@ -189,7 +187,6 @@ SETTINGS_TOPOLOGICALLY_SORTED: Final[Tuple[_Setting, ...]] = (
189
187
  "console",
190
188
  "job_source",
191
189
  "mode",
192
- "problem",
193
190
  "project",
194
191
  "run_id",
195
192
  "start_method",
wandb/sdk/lib/apikey.py CHANGED
@@ -202,7 +202,7 @@ def write_netrc(host: str, entity: str, key: str) -> Optional[bool]:
202
202
  elif skip:
203
203
  skip -= 1
204
204
  else:
205
- f.write("%s\n" % line)
205
+ f.write("{}\n".format(line))
206
206
  f.write(
207
207
  textwrap.dedent(
208
208
  """\
@@ -236,7 +236,9 @@ def write_key(
236
236
  _, suffix = key.split("-", 1) if "-" in key else ("", key)
237
237
 
238
238
  if len(suffix) != 40:
239
- raise ValueError("API key must be 40 characters long, yours was %s" % len(key))
239
+ raise ValueError(
240
+ "API key must be 40 characters long, yours was {}".format(len(key))
241
+ )
240
242
 
241
243
  if anonymous:
242
244
  api.set_setting("anonymous", "true", globally=True, persist=True)
@@ -66,13 +66,13 @@ def dict_from_config_file(
66
66
  ) -> Optional[Dict[str, Any]]:
67
67
  if not os.path.exists(filename):
68
68
  if must_exist:
69
- raise ConfigError("config file %s doesn't exist" % filename)
70
- logger.debug("no default config file found in %s" % filename)
69
+ raise ConfigError("config file {} doesn't exist".format(filename))
70
+ logger.debug("no default config file found in {}".format(filename))
71
71
  return None
72
72
  try:
73
73
  conf_file = open(filename)
74
74
  except OSError:
75
- raise ConfigError("Couldn't read config file: %s" % filename)
75
+ raise ConfigError("Couldn't read config file: {}".format(filename))
76
76
  try:
77
77
  loaded = load_yaml(conf_file)
78
78
  except yaml.parser.ParserError:
@@ -143,7 +143,7 @@ class _ImportHookChainedLoader:
143
143
  # None, so handle None as well. The module may not support attribute
144
144
  # assignment, in which case we simply skip it. Note that we also deal
145
145
  # with __loader__ not existing at all. This is to future proof things
146
- # due to proposal to remove the attribue as described in the GitHub
146
+ # due to proposal to remove the attribute as described in the GitHub
147
147
  # issue at https://github.com/python/cpython/issues/77458. Also prior
148
148
  # to Python 3.3, the __loader__ attribute was only set if a custom
149
149
  # module loader was used. It isn't clear whether the attribute still
@@ -12,7 +12,28 @@ if TYPE_CHECKING: # pragma: no cover
12
12
 
13
13
 
14
14
  def dict_from_proto_list(obj_list: "RepeatedCompositeFieldContainer") -> Dict[str, Any]:
15
- return {item.key: json.loads(item.value_json) for item in obj_list}
15
+ result: Dict[str, Any] = {}
16
+
17
+ for item in obj_list:
18
+ # Start from the root of the result dict
19
+ current_level = result
20
+
21
+ if len(item.nested_key) > 0:
22
+ keys = list(item.nested_key)
23
+ else:
24
+ keys = [item.key]
25
+
26
+ for key in keys[:-1]:
27
+ if key not in current_level:
28
+ current_level[key] = {}
29
+ # Move the reference deeper into the nested dictionary
30
+ current_level = current_level[key]
31
+
32
+ # Set the value at the final key location, parsing JSON from the value_json field
33
+ final_key = keys[-1]
34
+ current_level[final_key] = json.loads(item.value_json)
35
+
36
+ return result
16
37
 
17
38
 
18
39
  def _result_from_record(record: "pb.Record") -> "pb.Result":
wandb/sdk/lib/redirect.py CHANGED
@@ -224,7 +224,7 @@ class TerminalEmulator:
224
224
  def carriage_return(self):
225
225
  self.cursor.x = 0
226
226
 
227
- def cursor_postion(self, line, column):
227
+ def cursor_position(self, line, column):
228
228
  self.cursor.x = min(column, 1) - 1
229
229
  self.cursor.y = min(line, 1) - 1
230
230
 
@@ -393,25 +393,30 @@ class TerminalEmulator:
393
393
  p = (int(p[0]), 1)
394
394
  else:
395
395
  p = (1, 1)
396
- self.cursor_postion(*p)
396
+ self.cursor_position(*p)
397
397
  except Exception:
398
398
  pass
399
399
 
400
400
  def _get_line(self, n):
401
401
  line = self.buffer[n]
402
402
  line_len = self._get_line_len(n)
403
- # We have to loop through each character in the line and check if foreground, background and
404
- # other attributes (italics, bold, underline, etc) of the ith character are different from those of the
405
- # (i-1)th character. If different, the appropriate ascii character for switching the color/attribute
406
- # should be appended to the output string before appending the actual character. This loop and subsequent
407
- # checks can be expensive, especially because 99% of terminal output use default colors and formatting. Even
408
- # in outputs that do contain colors and styles, its unlikely that they will change on a per character basis.
409
-
410
- # So instead we create a character list without any ascii codes (`out`), and a list of all the foregrounds
411
- # in the line (`fgs`) on which we call np.diff() and np.where() to find the indices where the foreground change,
412
- # and insert the ascii characters in the output list (`out`) on those indices. All of this is the done ony if
413
- # there are more than 1 foreground color in the line in the first place (`if len(set(fgs)) > 1 else None`).
414
- # Same logic is repeated for background colors and other attributes.
403
+ # We have to loop through each character in the line and check if foreground,
404
+ # background and other attributes (italics, bold, underline, etc) of the ith
405
+ # character are different from those of the (i-1)th character. If different, the
406
+ # appropriate ascii character for switching the color/attribute should be
407
+ # appended to the output string before appending the actual character. This loop
408
+ # and subsequent checks can be expensive, especially because 99% of terminal
409
+ # output use default colors and formatting. Even in outputs that do contain
410
+ # colors and styles, its unlikely that they will change on a per character
411
+ # basis.
412
+
413
+ # So instead we create a character list without any ascii codes (`out`), and a
414
+ # list of all the foregrounds in the line (`fgs`) on which we call np.diff() and
415
+ # np.where() to find the indices where the foreground change, and insert the
416
+ # ascii characters in the output list (`out`) on those indices. All of this is
417
+ # the done only if there are more than 1 foreground color in the line in the
418
+ # first place (`if len(set(fgs)) > 1 else None`). Same logic is repeated for
419
+ # background colors and other attributes.
415
420
 
416
421
  out = [line[i].data for i in range(line_len)]
417
422
 
@@ -499,7 +504,7 @@ class RedirectBase:
499
504
 
500
505
  @property
501
506
  def src_stream(self):
502
- return getattr(sys, "__%s__" % self.src)
507
+ return getattr(sys, "__{}__".format(self.src))
503
508
 
504
509
  @property
505
510
  def src_fd(self):
wandb/sdk/lib/tracelog.py CHANGED
@@ -6,7 +6,7 @@ Functions:
6
6
  log_message_send - message sent to socket
7
7
  log_message_recv - message received from socket
8
8
  log_message_process - message processed by thread
9
- log_message_link - message linked to another mesage
9
+ log_message_link - message linked to another message
10
10
  log_message_assert - message encountered problem
11
11
 
12
12
  """
@@ -110,7 +110,8 @@ class _Service:
110
110
  f"The wandb service process exited with {proc.returncode}. "
111
111
  "Ensure that `sys.executable` is a valid python interpreter. "
112
112
  "You can override it with the `_executable` setting "
113
- "or with the `WANDB__EXECUTABLE` environment variable.",
113
+ "or with the `WANDB__EXECUTABLE` environment variable."
114
+ f"\n{context}",
114
115
  context=context,
115
116
  )
116
117
  if not os.path.isfile(fname):
@@ -319,8 +319,8 @@ class StreamMux:
319
319
  # These could be done in parallel in the future
320
320
  for _sid, stream in started_streams.items():
321
321
  # dispatch all our final requests
322
- poll_exit_handle = stream.interface.deliver_poll_exit()
323
322
  server_info_handle = stream.interface.deliver_request_server_info()
323
+ poll_exit_handle = stream.interface.deliver_poll_exit()
324
324
  final_summary_handle = stream.interface.deliver_get_summary()
325
325
  sampled_history_handle = stream.interface.deliver_request_sampled_history()
326
326
  internal_messages_handle = stream.interface.deliver_internal_messages()
@@ -330,14 +330,14 @@ class StreamMux:
330
330
  internal_messages_response = result.response.internal_messages_response
331
331
 
332
332
  # wait for them, it's ok to do this serially but this can be improved
333
- result = poll_exit_handle.wait(timeout=-1)
334
- assert result
335
- poll_exit_response = result.response.poll_exit_response
336
-
337
333
  result = server_info_handle.wait(timeout=-1)
338
334
  assert result
339
335
  server_info_response = result.response.server_info_response
340
336
 
337
+ result = poll_exit_handle.wait(timeout=-1)
338
+ assert result
339
+ poll_exit_response = result.response.poll_exit_response
340
+
341
341
  result = sampled_history_handle.wait(timeout=-1)
342
342
  assert result
343
343
  sampled_history = result.response.sampled_history_response
wandb/sdk/wandb_init.py CHANGED
@@ -15,7 +15,6 @@ import os
15
15
  import platform
16
16
  import sys
17
17
  import tempfile
18
- import traceback
19
18
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union
20
19
 
21
20
  import wandb
@@ -555,7 +554,7 @@ class _WandbInit:
555
554
  percent_done = handle.percent_done
556
555
  self.printer.progress_update(line, percent_done=percent_done)
557
556
 
558
- def init(self) -> Union[Run, RunDisabled, None]: # noqa: C901
557
+ def init(self) -> Union[Run, RunDisabled]: # noqa: C901
559
558
  if logger is None:
560
559
  raise RuntimeError("Logger not initialized")
561
560
  logger.info("calling init triggers")
@@ -654,9 +653,6 @@ class _WandbInit:
654
653
  if self.settings.launch:
655
654
  tel.feature.launch = True
656
655
 
657
- if self.settings._async_upload_concurrency_limit:
658
- tel.feature.async_uploads = True
659
-
660
656
  for module_name in telemetry.list_telemetry_imports(only_imported=True):
661
657
  setattr(tel.imports_init, module_name, True)
662
658
 
@@ -843,13 +839,6 @@ class _WandbInit:
843
839
  return run
844
840
 
845
841
 
846
- def getcaller() -> None:
847
- if not logger:
848
- return None
849
- src, line, func, stack = logger.findCaller(stack_info=True)
850
- print("Problem at:", src, line, func)
851
-
852
-
853
842
  def _attach(
854
843
  attach_id: Optional[str] = None,
855
844
  run_id: Optional[str] = None,
@@ -957,8 +946,9 @@ def init(
957
946
  save_code: Optional[bool] = None,
958
947
  id: Optional[str] = None,
959
948
  fork_from: Optional[str] = None,
949
+ resume_from: Optional[str] = None,
960
950
  settings: Union[Settings, Dict[str, Any], None] = None,
961
- ) -> Union[Run, RunDisabled, None]:
951
+ ) -> Union[Run, RunDisabled]:
962
952
  r"""Start a new run to track and log to W&B.
963
953
 
964
954
  In an ML training pipeline, you could add `wandb.init()`
@@ -1006,7 +996,7 @@ def init(
1006
996
  there, so make sure to create your account or team in the UI before
1007
997
  starting to log runs.
1008
998
  If you don't specify an entity, the run will be sent to your default
1009
- entity, which is usually your username. Change your default entity
999
+ entity. Change your default entity
1010
1000
  in [your settings](https://wandb.ai/settings) under "default location
1011
1001
  to create new projects".
1012
1002
  config: (dict, argparse, absl.flags, str, optional)
@@ -1164,57 +1154,33 @@ def init(
1164
1154
  wandb._assert_is_user_process()
1165
1155
 
1166
1156
  kwargs = dict(locals())
1167
- error_seen = None
1168
- except_exit = None
1169
- run: Optional[Union[Run, RunDisabled]] = None
1170
1157
 
1171
- # convert fork_from into a version that can be passed to settings
1172
- if fork_from is not None and resume is not None:
1173
- raise ValueError("Cannot specify both `fork_from` and `resume`")
1158
+ num_resume_options_set = (
1159
+ (fork_from is not None) # wrap
1160
+ + (resume is not None)
1161
+ + (resume_from is not None)
1162
+ )
1163
+ if num_resume_options_set > 1:
1164
+ raise ValueError(
1165
+ "You cannot specify more than one of `fork_from`, `resume`, or `resume_from`"
1166
+ )
1174
1167
 
1175
1168
  try:
1176
1169
  wi = _WandbInit()
1177
1170
  wi.setup(kwargs)
1178
- assert wi.settings
1179
- except_exit = wi.settings._except_exit
1180
- try:
1181
- run = wi.init()
1182
- except_exit = wi.settings._except_exit
1183
- except (KeyboardInterrupt, Exception) as e:
1184
- if not isinstance(e, KeyboardInterrupt):
1185
- wandb._sentry.exception(e)
1186
- if not (
1187
- wandb.wandb_agent._is_running() and isinstance(e, KeyboardInterrupt)
1188
- ):
1189
- getcaller()
1190
- assert logger
1191
- if wi.settings.problem == "fatal":
1192
- raise
1193
- if wi.settings.problem == "warn":
1194
- pass
1195
- # TODO(jhr): figure out how to make this RunDummy
1196
- run = None
1197
- except Error as e:
1198
- if logger is not None:
1199
- logger.exception(str(e))
1200
- raise e
1171
+ return wi.init()
1172
+
1201
1173
  except KeyboardInterrupt as e:
1202
- assert logger
1203
- logger.warning("interrupted", exc_info=e)
1204
- raise e
1174
+ if logger is not None:
1175
+ logger.warning("interrupted", exc_info=e)
1176
+
1177
+ raise
1178
+
1205
1179
  except Exception as e:
1206
- error_seen = e
1207
- traceback.print_exc()
1208
- assert logger
1209
- logger.error("error", exc_info=e)
1180
+ if logger is not None:
1181
+ logger.exception("error in wandb.init()", exc_info=e)
1182
+
1210
1183
  # Need to build delay into this sentry capture because our exit hooks
1211
1184
  # mess with sentry's ability to send out errors before the program ends.
1212
- wandb._sentry.exception(e)
1213
- # reraise(*sys.exc_info())
1214
- finally:
1215
- if error_seen:
1216
- if except_exit:
1217
- wandb.termerror("Abnormal program exit")
1218
- os._exit(1)
1219
- raise Error("An unexpected error occurred") from error_seen
1220
- return run
1185
+ wandb._sentry.reraise(e)
1186
+ raise AssertionError() # unreachable