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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) 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/cli/cli.py +131 -59
  19. wandb/data_types.py +6 -3
  20. wandb/docker/__init__.py +2 -2
  21. wandb/env.py +3 -3
  22. wandb/errors/term.py +10 -2
  23. wandb/filesync/step_checksum.py +1 -4
  24. wandb/filesync/step_prepare.py +4 -24
  25. wandb/filesync/step_upload.py +5 -107
  26. wandb/filesync/upload_job.py +0 -76
  27. wandb/integration/gym/__init__.py +35 -15
  28. wandb/integration/huggingface/resolver.py +2 -2
  29. wandb/integration/keras/callbacks/metrics_logger.py +1 -1
  30. wandb/integration/keras/keras.py +1 -1
  31. wandb/integration/openai/fine_tuning.py +21 -3
  32. wandb/integration/prodigy/prodigy.py +1 -1
  33. wandb/jupyter.py +16 -17
  34. wandb/old/summary.py +1 -1
  35. wandb/plot/confusion_matrix.py +1 -1
  36. wandb/plot/pr_curve.py +2 -1
  37. wandb/plot/roc_curve.py +2 -1
  38. wandb/{plots → plot}/utils.py +13 -25
  39. wandb/proto/v3/wandb_internal_pb2.py +54 -54
  40. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  41. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  42. wandb/proto/v4/wandb_internal_pb2.py +54 -54
  43. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  44. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  45. wandb/proto/v5/wandb_base_pb2.py +30 -0
  46. wandb/proto/v5/wandb_internal_pb2.py +355 -0
  47. wandb/proto/v5/wandb_server_pb2.py +63 -0
  48. wandb/proto/v5/wandb_settings_pb2.py +45 -0
  49. wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
  50. wandb/proto/wandb_base_pb2.py +2 -0
  51. wandb/proto/wandb_deprecated.py +9 -1
  52. wandb/proto/wandb_generate_deprecated.py +34 -0
  53. wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
  54. wandb/proto/wandb_internal_pb2.py +2 -0
  55. wandb/proto/wandb_server_pb2.py +2 -0
  56. wandb/proto/wandb_settings_pb2.py +2 -0
  57. wandb/proto/wandb_telemetry_pb2.py +2 -0
  58. wandb/sdk/artifacts/artifact.py +68 -22
  59. wandb/sdk/artifacts/artifact_manifest.py +1 -1
  60. wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
  61. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
  62. wandb/sdk/artifacts/artifact_saver.py +1 -10
  63. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
  64. wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
  65. wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
  66. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
  67. wandb/sdk/artifacts/storage_policy.py +1 -12
  68. wandb/sdk/data_types/_dtypes.py +8 -8
  69. wandb/sdk/data_types/image.py +2 -2
  70. wandb/sdk/data_types/video.py +5 -3
  71. wandb/sdk/integration_utils/data_logging.py +5 -5
  72. wandb/sdk/interface/interface.py +14 -1
  73. wandb/sdk/interface/interface_shared.py +1 -1
  74. wandb/sdk/internal/file_pusher.py +2 -5
  75. wandb/sdk/internal/file_stream.py +6 -19
  76. wandb/sdk/internal/internal_api.py +148 -136
  77. wandb/sdk/internal/job_builder.py +208 -136
  78. wandb/sdk/internal/progress.py +0 -28
  79. wandb/sdk/internal/sender.py +102 -39
  80. wandb/sdk/internal/settings_static.py +8 -1
  81. wandb/sdk/internal/system/assets/trainium.py +3 -3
  82. wandb/sdk/internal/system/system_info.py +4 -2
  83. wandb/sdk/internal/update.py +1 -1
  84. wandb/sdk/launch/__init__.py +9 -1
  85. wandb/sdk/launch/_launch.py +4 -24
  86. wandb/sdk/launch/_launch_add.py +1 -3
  87. wandb/sdk/launch/_project_spec.py +187 -225
  88. wandb/sdk/launch/agent/agent.py +59 -19
  89. wandb/sdk/launch/agent/config.py +0 -3
  90. wandb/sdk/launch/builder/abstract.py +68 -1
  91. wandb/sdk/launch/builder/build.py +165 -576
  92. wandb/sdk/launch/builder/context_manager.py +235 -0
  93. wandb/sdk/launch/builder/docker_builder.py +7 -23
  94. wandb/sdk/launch/builder/kaniko_builder.py +12 -25
  95. wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
  96. wandb/sdk/launch/create_job.py +51 -45
  97. wandb/sdk/launch/environment/aws_environment.py +26 -1
  98. wandb/sdk/launch/inputs/files.py +148 -0
  99. wandb/sdk/launch/inputs/internal.py +224 -0
  100. wandb/sdk/launch/inputs/manage.py +95 -0
  101. wandb/sdk/launch/registry/google_artifact_registry.py +1 -1
  102. wandb/sdk/launch/runner/abstract.py +2 -2
  103. wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
  104. wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
  105. wandb/sdk/launch/runner/local_container.py +2 -3
  106. wandb/sdk/launch/runner/local_process.py +8 -29
  107. wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
  108. wandb/sdk/launch/runner/vertex_runner.py +8 -7
  109. wandb/sdk/launch/sweeps/scheduler.py +5 -3
  110. wandb/sdk/launch/sweeps/scheduler_sweep.py +1 -1
  111. wandb/sdk/launch/sweeps/utils.py +4 -4
  112. wandb/sdk/launch/utils.py +16 -138
  113. wandb/sdk/lib/_settings_toposort_generated.py +2 -5
  114. wandb/sdk/lib/apikey.py +4 -2
  115. wandb/sdk/lib/config_util.py +3 -3
  116. wandb/sdk/lib/import_hooks.py +1 -1
  117. wandb/sdk/lib/proto_util.py +22 -1
  118. wandb/sdk/lib/redirect.py +20 -15
  119. wandb/sdk/lib/tracelog.py +1 -1
  120. wandb/sdk/service/service.py +2 -1
  121. wandb/sdk/service/streams.py +5 -5
  122. wandb/sdk/wandb_init.py +25 -59
  123. wandb/sdk/wandb_login.py +28 -25
  124. wandb/sdk/wandb_run.py +123 -53
  125. wandb/sdk/wandb_settings.py +33 -64
  126. wandb/sdk/wandb_setup.py +1 -1
  127. wandb/sdk/wandb_watch.py +1 -1
  128. wandb/sklearn/plot/classifier.py +10 -12
  129. wandb/sklearn/plot/clusterer.py +1 -1
  130. wandb/sync/sync.py +2 -2
  131. wandb/testing/relay.py +32 -17
  132. wandb/util.py +36 -37
  133. wandb/wandb_agent.py +3 -3
  134. wandb/wandb_controller.py +5 -4
  135. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/METADATA +8 -10
  136. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/RECORD +139 -161
  137. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/WHEEL +1 -1
  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}/entry_points.txt +0 -0
  173. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/licenses/LICENSE +0 -0
@@ -298,7 +298,6 @@ class SettingsData:
298
298
 
299
299
  _args: Sequence[str]
300
300
  _aws_lambda: bool
301
- _async_upload_concurrency_limit: int
302
301
  _cli_only_mode: bool # Avoid running any code specific for runs
303
302
  _code_path_local: str
304
303
  _colab: bool
@@ -313,7 +312,6 @@ class SettingsData:
313
312
  _disable_update_check: bool # Disable version check
314
313
  _disable_viewer: bool # Prevent early viewer query
315
314
  _disable_machine_info: bool # Disable automatic machine info collection
316
- _except_exit: bool
317
315
  _executable: str
318
316
  _extra_http_headers: Mapping[str, str]
319
317
  # file stream retry client configuration
@@ -390,6 +388,7 @@ class SettingsData:
390
388
  colab_url: str
391
389
  config_paths: Sequence[str]
392
390
  console: str
391
+ console_multipart: bool # whether to produce multipart console log files
393
392
  deployment: str
394
393
  disable_code: bool
395
394
  disable_git: bool
@@ -402,6 +401,7 @@ class SettingsData:
402
401
  files_dir: str
403
402
  force: bool
404
403
  fork_from: Optional[RunMoment]
404
+ resume_from: Optional[RunMoment]
405
405
  git_commit: str
406
406
  git_remote: str
407
407
  git_remote_url: str
@@ -425,7 +425,6 @@ class SettingsData:
425
425
  # magic: Union[str, bool, dict] # never used in code, deprecated
426
426
  mode: str
427
427
  notebook_name: str
428
- problem: str
429
428
  program: str
430
429
  program_abspath: str
431
430
  program_relpath: str
@@ -621,10 +620,6 @@ class Settings(SettingsData):
621
620
  Note that key names must be the same as the class attribute names.
622
621
  """
623
622
  props: Dict[str, Dict[str, Any]] = dict(
624
- _async_upload_concurrency_limit={
625
- "preprocessor": int,
626
- "validator": self._validate__async_upload_concurrency_limit,
627
- },
628
623
  _aws_lambda={
629
624
  "hook": lambda _: is_aws_lambda(),
630
625
  "auto_hook": True,
@@ -660,19 +655,14 @@ class Settings(SettingsData):
660
655
  _disable_update_check={"preprocessor": _str_as_bool},
661
656
  _disable_viewer={"preprocessor": _str_as_bool},
662
657
  _extra_http_headers={"preprocessor": _str_as_json},
663
- # Retry filestream requests for 2 hours before dropping chunk (how do we recover?)
664
- # retry_count = seconds_in_2_hours / max_retry_time + num_retries_until_max_60_sec
665
- # = 7200 / 60 + ceil(log2(60/2))
666
- # = 120 + 5
667
- _file_stream_retry_max={"value": 125, "preprocessor": int},
668
- _file_stream_retry_wait_min_seconds={"value": 2, "preprocessor": float},
669
- _file_stream_retry_wait_max_seconds={"value": 60, "preprocessor": float},
670
- # A 3 minute timeout for all filestream post requests
671
- _file_stream_timeout_seconds={"value": 180, "preprocessor": float},
672
- _file_transfer_retry_max={"value": 20, "preprocessor": int},
673
- _file_transfer_retry_wait_min_seconds={"value": 2, "preprocessor": float},
674
- _file_transfer_retry_wait_max_seconds={"value": 60, "preprocessor": float},
675
- _file_transfer_timeout_seconds={"value": 0, "preprocessor": float},
658
+ _file_stream_retry_max={"preprocessor": int},
659
+ _file_stream_retry_wait_min_seconds={"preprocessor": float},
660
+ _file_stream_retry_wait_max_seconds={"preprocessor": float},
661
+ _file_stream_timeout_seconds={"preprocessor": float},
662
+ _file_transfer_retry_max={"preprocessor": int},
663
+ _file_transfer_retry_wait_min_seconds={"preprocessor": float},
664
+ _file_transfer_retry_wait_max_seconds={"preprocessor": float},
665
+ _file_transfer_timeout_seconds={"preprocessor": float},
676
666
  _flow_control_disabled={
677
667
  "hook": lambda _: self._network_buffer == 0,
678
668
  "auto_hook": True,
@@ -681,10 +671,10 @@ class Settings(SettingsData):
681
671
  "hook": lambda _: bool(self._network_buffer),
682
672
  "auto_hook": True,
683
673
  },
684
- _graphql_retry_max={"value": 20, "preprocessor": int},
685
- _graphql_retry_wait_min_seconds={"value": 2, "preprocessor": float},
686
- _graphql_retry_wait_max_seconds={"value": 60, "preprocessor": float},
687
- _graphql_timeout_seconds={"value": 30.0, "preprocessor": float},
674
+ _graphql_retry_max={"preprocessor": int},
675
+ _graphql_retry_wait_min_seconds={"preprocessor": float},
676
+ _graphql_retry_wait_max_seconds={"preprocessor": float},
677
+ _graphql_timeout_seconds={"preprocessor": float},
688
678
  _internal_check_process={"value": 8, "preprocessor": float},
689
679
  _internal_queue_timeout={"value": 2, "preprocessor": float},
690
680
  _ipython={
@@ -787,6 +777,7 @@ class Settings(SettingsData):
787
777
  "hook": lambda x: self._convert_console(x),
788
778
  "auto_hook": True,
789
779
  },
780
+ console_multipart={"value": False, "preprocessor": _str_as_bool},
790
781
  deployment={
791
782
  "hook": lambda _: "local" if self.is_local else "cloud",
792
783
  "auto_hook": True,
@@ -819,6 +810,10 @@ class Settings(SettingsData):
819
810
  "value": None,
820
811
  "preprocessor": _runmoment_preprocessor,
821
812
  },
813
+ resume_from={
814
+ "value": None,
815
+ "preprocessor": _runmoment_preprocessor,
816
+ },
822
817
  git_remote={"value": "origin"},
823
818
  heartbeat_seconds={"value": 30},
824
819
  ignore_globs={
@@ -862,7 +857,6 @@ class Settings(SettingsData):
862
857
  },
863
858
  login_timeout={"preprocessor": lambda x: float(x)},
864
859
  mode={"value": "online", "validator": self._validate_mode},
865
- problem={"value": "fatal", "validator": self._validate_problem},
866
860
  program={
867
861
  "hook": lambda x: self._get_program(x),
868
862
  },
@@ -1025,13 +1019,6 @@ class Settings(SettingsData):
1025
1019
  raise UsageError(f"Settings field `console`: {value!r} not in {choices}")
1026
1020
  return True
1027
1021
 
1028
- @staticmethod
1029
- def _validate_problem(value: str) -> bool:
1030
- choices: Set[str] = {"fatal", "warn", "silent"}
1031
- if value not in choices:
1032
- raise UsageError(f"Settings field `problem`: {value!r} not in {choices}")
1033
- return True
1034
-
1035
1022
  @staticmethod
1036
1023
  def _validate_anonymous(value: str) -> bool:
1037
1024
  choices: Set[str] = {"allow", "must", "never", "false", "true"}
@@ -1179,35 +1166,6 @@ class Settings(SettingsData):
1179
1166
  raise UsageError("_stats_samples_to_average must be between 1 and 30")
1180
1167
  return True
1181
1168
 
1182
- @staticmethod
1183
- def _validate__async_upload_concurrency_limit(value: int) -> bool:
1184
- if value <= 0:
1185
- raise UsageError("_async_upload_concurrency_limit must be positive")
1186
-
1187
- try:
1188
- import resource # not always available on Windows
1189
-
1190
- file_limit = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
1191
- except Exception:
1192
- # Couldn't get the open-file-limit for some reason,
1193
- # probably very platform-specific. Not a problem,
1194
- # we just won't use it to cap the concurrency.
1195
- pass
1196
- else:
1197
- if value > file_limit:
1198
- wandb.termwarn(
1199
- (
1200
- "_async_upload_concurrency_limit setting of"
1201
- f" {value} exceeds this process's limit"
1202
- f" on open files ({file_limit}); may cause file-upload failures."
1203
- " Try decreasing _async_upload_concurrency_limit,"
1204
- " or increasing your file limit with `ulimit -n`."
1205
- ),
1206
- repeat=False,
1207
- )
1208
-
1209
- return True
1210
-
1211
1169
  @staticmethod
1212
1170
  def _validate_job_source(value: str) -> bool:
1213
1171
  valid_sources = ["repo", "artifact", "image"]
@@ -1783,9 +1741,6 @@ class Settings(SettingsData):
1783
1741
  settings["_args"] = sys.argv[1:]
1784
1742
  settings["_os"] = platform.platform(aliased=True)
1785
1743
  settings["_python"] = platform.python_version()
1786
- # hack to make sure we don't hang on windows
1787
- if self._windows and self._except_exit is None:
1788
- settings["_except_exit"] = True # type: ignore
1789
1744
 
1790
1745
  if _logger is not None:
1791
1746
  _logger.info(
@@ -1896,7 +1851,20 @@ class Settings(SettingsData):
1896
1851
 
1897
1852
  # update settings
1898
1853
  self.update(init_settings, source=Source.INIT)
1854
+ self._handle_rewind_logic()
1855
+ self._handle_resume_logic()
1856
+
1857
+ def _handle_rewind_logic(self) -> None:
1858
+ if self.resume_from is None:
1859
+ return
1860
+
1861
+ if self.run_id is not None:
1862
+ wandb.termwarn(
1863
+ "You cannot specify both run_id and resume_from. " "Ignoring run_id."
1864
+ )
1865
+ self.update({"run_id": self.resume_from.run}, source=Source.INIT)
1899
1866
 
1867
+ def _handle_resume_logic(self) -> None:
1900
1868
  # handle auto resume logic
1901
1869
  if self.resume == "auto":
1902
1870
  if os.path.exists(self.resume_fname):
@@ -1909,6 +1877,7 @@ class Settings(SettingsData):
1909
1877
  "Tried to auto resume run with "
1910
1878
  f"id {resume_run_id} but id {self.run_id} is set.",
1911
1879
  )
1880
+
1912
1881
  self.update({"run_id": self.run_id or generate_id()}, source=Source.INIT)
1913
1882
  # persist our run id in case of failure
1914
1883
  # check None for mypy
wandb/sdk/wandb_setup.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #
2
2
  """Setup wandb session.
3
3
 
4
- This module configures a wandb session which can extend to mutiple wandb runs.
4
+ This module configures a wandb session which can extend to multiple wandb runs.
5
5
 
6
6
  Functions:
7
7
  setup(): Configure wandb session.
wandb/sdk/wandb_watch.py CHANGED
@@ -117,7 +117,7 @@ def unwatch(models=None):
117
117
  models = (models,)
118
118
  for model in models:
119
119
  if not hasattr(model, "_wandb_hook_names"):
120
- wandb.termwarn("%s model has not been watched" % model)
120
+ wandb.termwarn("{} model has not been watched".format(model))
121
121
  else:
122
122
  for name in model._wandb_hook_names:
123
123
  wandb.run._torch.unhook(name)
@@ -6,7 +6,7 @@ import numpy as np
6
6
  from sklearn import naive_bayes
7
7
 
8
8
  import wandb
9
- import wandb.plots
9
+ import wandb.plot
10
10
  from wandb.sklearn import calculate, utils
11
11
 
12
12
  from . import shared
@@ -33,9 +33,9 @@ def classifier(
33
33
 
34
34
  The following plots are generated:
35
35
  feature importances, confusion matrix, summary metrics,
36
- class propotions, calibration curve, roc curve, precision-recall curve.
36
+ class proportions, calibration curve, roc curve, precision-recall curve.
37
37
 
38
- Should only be called with a fitted classifer (otherwise an error is thrown).
38
+ Should only be called with a fitted classifier (otherwise an error is thrown).
39
39
 
40
40
  Arguments:
41
41
  model: (classifier) Takes in a fitted classifier.
@@ -45,7 +45,7 @@ def classifier(
45
45
  y_test: (arr) Test set labels.
46
46
  y_pred: (arr) Test set predictions by the model passed.
47
47
  y_probas: (arr) Test set predicted probabilities by the model passed.
48
- labels: (list) Named labels for target varible (y). Makes plots easier to
48
+ labels: (list) Named labels for target variable (y). Makes plots easier to
49
49
  read by replacing target values with corresponding index.
50
50
  For example if `labels=['dog', 'cat', 'owl']` all 0s are
51
51
  replaced by dog, 1s by cat.
@@ -134,9 +134,7 @@ def roc(
134
134
  wandb.sklearn.plot_roc(y_true, y_probas, labels)
135
135
  ```
136
136
  """
137
- roc_chart = wandb.plots.roc.roc(
138
- y_true, y_probas, labels, plot_micro, plot_macro, classes_to_plot
139
- )
137
+ roc_chart = wandb.plot.roc_curve(y_true, y_probas, labels, classes_to_plot)
140
138
  wandb.log({"roc": roc_chart})
141
139
 
142
140
 
@@ -213,8 +211,8 @@ def precision_recall(
213
211
  wandb.sklearn.plot_precision_recall(y_true, y_probas, labels)
214
212
  ```
215
213
  """
216
- precision_recall_chart = wandb.plots.precision_recall(
217
- y_true, y_probas, labels, plot_micro, classes_to_plot
214
+ precision_recall_chart = wandb.plot.pr_curve(
215
+ y_true, y_probas, labels, classes_to_plot
218
216
  )
219
217
 
220
218
  wandb.log({"precision_recall": precision_recall_chart})
@@ -225,7 +223,7 @@ def feature_importances(
225
223
  ):
226
224
  """Log a plot depicting the relative importance of each feature for a classifier's decisions.
227
225
 
228
- Should only be called with a fitted classifer (otherwise an error is thrown).
226
+ Should only be called with a fitted classifier (otherwise an error is thrown).
229
227
  Only works with classifiers that have a feature_importances_ attribute, like trees.
230
228
 
231
229
  Arguments:
@@ -252,7 +250,7 @@ def feature_importances(
252
250
 
253
251
 
254
252
  def class_proportions(y_train=None, y_test=None, labels=None):
255
- """Plot the distribution of target classses in training and test sets.
253
+ """Plot the distribution of target classes in training and test sets.
256
254
 
257
255
  Useful for detecting imbalanced classes.
258
256
 
@@ -296,7 +294,7 @@ def calibration_curve(clf=None, X=None, y=None, clf_name="Classifier"):
296
294
  if so which calibration (sigmoid or isotonic) might help fix this.
297
295
  For more details, see https://scikit-learn.org/stable/auto_examples/calibration/plot_calibration_curve.html.
298
296
 
299
- Should only be called with a fitted classifer (otherwise an error is thrown).
297
+ Should only be called with a fitted classifier (otherwise an error is thrown).
300
298
 
301
299
  Please note this function fits variations of the model on the training set when called.
302
300
 
@@ -25,7 +25,7 @@ def clusterer(model, X_train, cluster_labels, labels=None, model_name="Clusterer
25
25
  X_train: (arr) Training set features.
26
26
  cluster_labels: (list) Names for cluster labels. Makes plots easier to read
27
27
  by replacing cluster indexes with corresponding names.
28
- labels: (list) Named labels for target varible (y). Makes plots easier to
28
+ labels: (list) Named labels for target variable (y). Makes plots easier to
29
29
  read by replacing target values with corresponding index.
30
30
  For example if `labels=['dog', 'cat', 'owl']` all 0s are
31
31
  replaced by dog, 1s by cat.
wandb/sync/sync.py CHANGED
@@ -163,7 +163,7 @@ class SyncThread(threading.Thread):
163
163
  url_quote(proto_run.project),
164
164
  url_quote(proto_run.run_id),
165
165
  )
166
- print("Syncing: %s ..." % url)
166
+ print("Syncing: {} ...".format(url))
167
167
  sys.stdout.flush()
168
168
  # using a handler here automatically handles the step
169
169
  # logic, adds summaries to the run, and handles different
@@ -312,7 +312,7 @@ class SyncThread(threading.Thread):
312
312
  url_quote(r.project),
313
313
  url_quote(r.run_id),
314
314
  )
315
- print("Syncing: %s ... " % url, end="")
315
+ print("Syncing: {} ... ".format(url), end="")
316
316
  sys.stdout.flush()
317
317
  shown = True
318
318
  sm.finish()
wandb/testing/relay.py CHANGED
@@ -691,7 +691,7 @@ class RelayServer:
691
691
  def relay(
692
692
  self,
693
693
  request: "flask.Request",
694
- ) -> Union["responses.Response", "requests.Response"]:
694
+ ) -> Union["responses.Response", "requests.Response", None]:
695
695
  # replace the relay url with the real backend url (self.base_url)
696
696
  url = (
697
697
  urllib.parse.urlparse(request.url)
@@ -720,22 +720,29 @@ class RelayServer:
720
720
  # where are we in the application pattern?
721
721
  should_apply = injected_response.application_pattern.should_apply()
722
722
  # check if an injected response matches the request
723
- if injected_response == prepared_relayed_request:
724
- if self.verbose:
725
- print("*****************")
726
- print("INJECTING RESPONSE:")
727
- print(injected_response.to_dict())
728
- print("*****************")
729
- # rotate the injection pattern
730
- injected_response.application_pattern.next()
731
- # TODO: allow access to the request object when making the mocked response
732
- if should_apply:
733
- with responses.RequestsMock() as mocked_responses:
734
- # do the actual injection
735
- mocked_responses.add(**injected_response.to_dict())
736
- relayed_response = self.session.send(prepared_relayed_request)
737
-
738
- return relayed_response
723
+ if injected_response != prepared_relayed_request or not should_apply:
724
+ continue
725
+
726
+ if self.verbose:
727
+ print("*****************")
728
+ print("INJECTING RESPONSE:")
729
+ print(injected_response.to_dict())
730
+ print("*****************")
731
+ # rotate the injection pattern
732
+ injected_response.application_pattern.next()
733
+
734
+ # TODO: allow access to the request object when making the mocked response
735
+ with responses.RequestsMock() as mocked_responses:
736
+ # do the actual injection
737
+ resp = injected_response.to_dict()
738
+
739
+ if isinstance(resp["body"], ConnectionResetError):
740
+ return None
741
+
742
+ mocked_responses.add(**resp)
743
+ relayed_response = self.session.send(prepared_relayed_request)
744
+
745
+ return relayed_response
739
746
 
740
747
  # normal case: no injected response matches the request
741
748
  relayed_response = self.session.send(prepared_relayed_request)
@@ -802,8 +809,16 @@ class RelayServer:
802
809
 
803
810
  def file_stream(self, path) -> Mapping[str, str]:
804
811
  request = flask.request
812
+
805
813
  with Timer() as timer:
806
814
  relayed_response = self.relay(request)
815
+
816
+ # simulate connection reset by peer
817
+ if relayed_response is None:
818
+ connection = request.environ["werkzeug.socket"] # Get the socket object
819
+ connection.shutdown(socket.SHUT_RDWR)
820
+ connection.close()
821
+
807
822
  if self.verbose:
808
823
  print("*****************")
809
824
  print("FILE STREAM REQUEST:")
wandb/util.py CHANGED
@@ -44,7 +44,6 @@ from typing import (
44
44
  Mapping,
45
45
  Optional,
46
46
  Sequence,
47
- Set,
48
47
  TextIO,
49
48
  Tuple,
50
49
  TypeVar,
@@ -544,50 +543,41 @@ def _numpy_generic_convert(obj: Any) -> Any:
544
543
  return obj
545
544
 
546
545
 
547
- def _find_all_matching_keys(
546
+ def _sanitize_numpy_keys(
548
547
  d: Dict,
549
- match_fn: Callable[[Any], bool],
550
- visited: Optional[Set[int]] = None,
551
- key_path: Tuple[Any, ...] = (),
552
- ) -> Generator[Tuple[Tuple[Any, ...], Any], None, None]:
553
- """Recursively find all keys that satisfies a match function.
548
+ visited: Optional[Dict[int, Dict]] = None,
549
+ ) -> Tuple[Dict, bool]:
550
+ """Returns a dictionary where all NumPy keys are converted.
554
551
 
555
552
  Args:
556
- d: The dict to search.
557
- match_fn: The function to determine if the key is a match.
558
- visited: Keep track of visited nodes so we dont recurse forever.
559
- key_path: Keep track of all the keys to get to the current node.
553
+ d: The dictionary to sanitize.
560
554
 
561
- Yields:
562
- (key_path, key): The location where the key was found, and the key
555
+ Returns:
556
+ A sanitized dictionary, and a boolean indicating whether anything was
557
+ changed.
563
558
  """
559
+ out: Dict[Any, Any] = dict()
560
+ converted = False
561
+
562
+ # Work with recursive dictionaries: if a dictionary has already been
563
+ # converted, reuse its converted value to retain the recursive structure
564
+ # of the input.
564
565
  if visited is None:
565
- visited = set()
566
- me = id(d)
567
- if me not in visited:
568
- visited.add(me)
569
- for key, value in d.items():
570
- if match_fn(key):
571
- yield key_path, key
572
- if isinstance(value, dict):
573
- yield from _find_all_matching_keys(
574
- value,
575
- match_fn,
576
- visited=visited,
577
- key_path=tuple(list(key_path) + [key]),
578
- )
566
+ visited = {id(d): out}
567
+ elif id(d) in visited:
568
+ return visited[id(d)], False
569
+ visited[id(d)] = out
579
570
 
571
+ for key, value in d.items():
572
+ if isinstance(value, dict):
573
+ value, converted_value = _sanitize_numpy_keys(value, visited)
574
+ converted |= converted_value
575
+ if isinstance(key, np.generic):
576
+ key = _numpy_generic_convert(key)
577
+ converted = True
578
+ out[key] = value
580
579
 
581
- def _sanitize_numpy_keys(d: Dict) -> Tuple[Dict, bool]:
582
- np_keys = list(_find_all_matching_keys(d, lambda k: isinstance(k, np.generic)))
583
- if not np_keys:
584
- return d, False
585
- for key_path, key in np_keys:
586
- ptr = d
587
- for k in key_path:
588
- ptr = ptr[k]
589
- ptr[_numpy_generic_convert(key)] = ptr.pop(key)
590
- return d, True
580
+ return out, converted
591
581
 
592
582
 
593
583
  def json_friendly( # noqa: C901
@@ -1923,3 +1913,12 @@ def get_core_path() -> str:
1923
1913
  )
1924
1914
 
1925
1915
  return str(bin_path)
1916
+
1917
+
1918
+ class NonOctalStringDumper(yaml.Dumper):
1919
+ """Prevents strings containing non-octal values like "008" and "009" from being converted to numbers in in the yaml string saved as the sweep config."""
1920
+
1921
+ def represent_scalar(self, tag, value, style=None):
1922
+ if tag == "tag:yaml.org,2002:str" and value.startswith("0") and len(value) > 1:
1923
+ return super().represent_scalar(tag, value, style="'")
1924
+ return super().represent_scalar(tag, value, style)
wandb/wandb_agent.py CHANGED
@@ -329,7 +329,7 @@ class Agent:
329
329
  elif command_type == "resume":
330
330
  result = self._command_run(command)
331
331
  else:
332
- raise AgentError("No such command: %s" % command_type)
332
+ raise AgentError("No such command: {}".format(command_type))
333
333
  response["result"] = result
334
334
  except Exception:
335
335
  logger.exception("Exception while processing command: %s", command)
@@ -417,7 +417,7 @@ class Agent:
417
417
  command_list += [c]
418
418
  logger.info(
419
419
  "About to run command: {}".format(
420
- " ".join('"%s"' % c if " " in c else c for c in command_list)
420
+ " ".join('"{}"'.format(c) if " " in c else c for c in command_list)
421
421
  )
422
422
  )
423
423
  proc = AgentProcess(command=command_list, env=env)
@@ -468,7 +468,7 @@ class AgentApi:
468
468
 
469
469
  def command(self, command):
470
470
  command["origin"] = "local"
471
- command["id"] = "local-%s" % self._command_id
471
+ command["id"] = "local-{}".format(self._command_id)
472
472
  self._command_id += 1
473
473
  resp_queue = self._multiproc_manager.Queue()
474
474
  command["resp_queue"] = resp_queue
wandb/wandb_controller.py CHANGED
@@ -20,7 +20,7 @@ Example:
20
20
  tuner = wandb.controller()
21
21
  tuner.configure(sweep_config)
22
22
  tuner.create()
23
- # (3) create by constructing progamatic sweep configuration
23
+ # (3) create by constructing programmatic sweep configuration
24
24
  tuner = wandb.controller()
25
25
  tuner.configure_search('random')
26
26
  tuner.configure_program('train-dummy.py')
@@ -127,7 +127,7 @@ class _WandbController:
127
127
  """
128
128
 
129
129
  def __init__(self, sweep_id_or_config=None, entity=None, project=None):
130
- # sweep id configured in constuctor
130
+ # sweep id configured in constructor
131
131
  self._sweep_id: Optional[str] = None
132
132
 
133
133
  # configured parameters
@@ -455,8 +455,9 @@ class _WandbController:
455
455
  rr["history"] = [json.loads(d) for d in rr["history"]]
456
456
  else:
457
457
  raise ValueError(
458
- "Invalid history value: expected list of json strings: %s"
459
- % rr["history"]
458
+ "Invalid history value: expected list of json strings: {}".format(
459
+ rr["history"]
460
+ )
460
461
  )
461
462
  if "sampledHistory" in rr:
462
463
  sampled_history = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: wandb
3
- Version: 0.17.0rc1
3
+ Version: 0.17.1
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
@@ -46,14 +46,14 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
46
46
  Classifier: Topic :: System :: Logging
47
47
  Classifier: Topic :: System :: Monitoring
48
48
  Requires-Python: >=3.7
49
- Requires-Dist: appdirs>=1.4.3
50
49
  Requires-Dist: click!=8.0.0,>=7.1
51
50
  Requires-Dist: docker-pycreds>=0.4.0
52
51
  Requires-Dist: gitpython!=3.1.29,>=1.0.0
53
- Requires-Dist: protobuf!=4.21.0,<5,>=3.12.0; python_version < '3.9' and sys_platform == 'linux'
54
- Requires-Dist: protobuf!=4.21.0,<5,>=3.15.0; python_version == '3.9' and sys_platform == 'linux'
55
- Requires-Dist: protobuf!=4.21.0,<5,>=3.19.0; python_version > '3.9' and sys_platform == 'linux'
56
- Requires-Dist: protobuf!=4.21.0,<5,>=3.19.0; sys_platform != 'linux'
52
+ Requires-Dist: platformdirs
53
+ Requires-Dist: protobuf!=4.21.0,<6,>=3.12.0; python_version < '3.9' and sys_platform == 'linux'
54
+ Requires-Dist: protobuf!=4.21.0,<6,>=3.15.0; python_version == '3.9' and sys_platform == 'linux'
55
+ Requires-Dist: protobuf!=4.21.0,<6,>=3.19.0; python_version > '3.9' and sys_platform == 'linux'
56
+ Requires-Dist: protobuf!=4.21.0,<6,>=3.19.0; sys_platform != 'linux'
57
57
  Requires-Dist: psutil>=5.0.0
58
58
  Requires-Dist: pyyaml
59
59
  Requires-Dist: requests<3,>=2.0.0
@@ -61,8 +61,6 @@ Requires-Dist: sentry-sdk>=1.0.0
61
61
  Requires-Dist: setproctitle
62
62
  Requires-Dist: setuptools
63
63
  Requires-Dist: typing-extensions; python_version < '3.10'
64
- Provides-Extra: async
65
- Requires-Dist: httpx>=0.23.0; extra == 'async'
66
64
  Provides-Extra: aws
67
65
  Requires-Dist: boto3; extra == 'aws'
68
66
  Provides-Extra: azure
@@ -116,10 +114,10 @@ Provides-Extra: models
116
114
  Requires-Dist: cloudpickle; extra == 'models'
117
115
  Provides-Extra: perf
118
116
  Requires-Dist: orjson; extra == 'perf'
119
- Provides-Extra: reports
120
- Requires-Dist: pydantic>=2.0.0; extra == 'reports'
121
117
  Provides-Extra: sweeps
122
118
  Requires-Dist: sweeps>=0.2.0; extra == 'sweeps'
119
+ Provides-Extra: workspaces
120
+ Requires-Dist: wandb-workspaces; extra == 'workspaces'
123
121
  Description-Content-Type: text/markdown
124
122
 
125
123
  <div align="center">