wandb 0.13.10__py3-none-any.whl → 0.14.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (228) hide show
  1. wandb/__init__.py +2 -3
  2. wandb/apis/__init__.py +1 -3
  3. wandb/apis/importers/__init__.py +4 -0
  4. wandb/apis/importers/base.py +312 -0
  5. wandb/apis/importers/mlflow.py +113 -0
  6. wandb/apis/internal.py +29 -2
  7. wandb/apis/normalize.py +6 -5
  8. wandb/apis/public.py +163 -180
  9. wandb/apis/reports/_templates.py +6 -12
  10. wandb/apis/reports/report.py +1 -1
  11. wandb/apis/reports/runset.py +1 -3
  12. wandb/apis/reports/util.py +12 -10
  13. wandb/beta/workflows.py +57 -34
  14. wandb/catboost/__init__.py +1 -2
  15. wandb/cli/cli.py +215 -133
  16. wandb/data_types.py +63 -56
  17. wandb/docker/__init__.py +78 -16
  18. wandb/docker/auth.py +21 -22
  19. wandb/env.py +0 -1
  20. wandb/errors/__init__.py +8 -116
  21. wandb/errors/term.py +1 -1
  22. wandb/fastai/__init__.py +1 -2
  23. wandb/filesync/dir_watcher.py +8 -5
  24. wandb/filesync/step_prepare.py +76 -75
  25. wandb/filesync/step_upload.py +1 -2
  26. wandb/integration/catboost/__init__.py +1 -3
  27. wandb/integration/catboost/catboost.py +8 -14
  28. wandb/integration/fastai/__init__.py +7 -13
  29. wandb/integration/gym/__init__.py +35 -4
  30. wandb/integration/keras/__init__.py +3 -3
  31. wandb/integration/keras/callbacks/metrics_logger.py +9 -8
  32. wandb/integration/keras/callbacks/model_checkpoint.py +9 -9
  33. wandb/integration/keras/callbacks/tables_builder.py +31 -19
  34. wandb/integration/kfp/kfp_patch.py +20 -17
  35. wandb/integration/kfp/wandb_logging.py +1 -2
  36. wandb/integration/lightgbm/__init__.py +21 -19
  37. wandb/integration/prodigy/prodigy.py +6 -7
  38. wandb/integration/sacred/__init__.py +9 -12
  39. wandb/integration/sagemaker/__init__.py +1 -3
  40. wandb/integration/sagemaker/auth.py +0 -1
  41. wandb/integration/sagemaker/config.py +1 -1
  42. wandb/integration/sagemaker/resources.py +1 -1
  43. wandb/integration/sb3/sb3.py +8 -4
  44. wandb/integration/tensorboard/__init__.py +1 -3
  45. wandb/integration/tensorboard/log.py +8 -8
  46. wandb/integration/tensorboard/monkeypatch.py +11 -9
  47. wandb/integration/tensorflow/__init__.py +1 -3
  48. wandb/integration/xgboost/__init__.py +4 -6
  49. wandb/integration/yolov8/__init__.py +7 -0
  50. wandb/integration/yolov8/yolov8.py +250 -0
  51. wandb/jupyter.py +31 -35
  52. wandb/lightgbm/__init__.py +1 -2
  53. wandb/old/settings.py +2 -2
  54. wandb/plot/bar.py +1 -2
  55. wandb/plot/confusion_matrix.py +1 -3
  56. wandb/plot/histogram.py +1 -2
  57. wandb/plot/line.py +1 -2
  58. wandb/plot/line_series.py +4 -4
  59. wandb/plot/pr_curve.py +17 -20
  60. wandb/plot/roc_curve.py +1 -3
  61. wandb/plot/scatter.py +1 -2
  62. wandb/proto/v3/wandb_server_pb2.py +85 -39
  63. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  64. wandb/proto/v4/wandb_server_pb2.py +51 -39
  65. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  66. wandb/sdk/__init__.py +1 -3
  67. wandb/sdk/backend/backend.py +1 -1
  68. wandb/sdk/data_types/_dtypes.py +38 -30
  69. wandb/sdk/data_types/base_types/json_metadata.py +1 -3
  70. wandb/sdk/data_types/base_types/media.py +17 -17
  71. wandb/sdk/data_types/base_types/wb_value.py +33 -26
  72. wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +91 -125
  73. wandb/sdk/data_types/helper_types/classes.py +1 -1
  74. wandb/sdk/data_types/helper_types/image_mask.py +12 -12
  75. wandb/sdk/data_types/histogram.py +5 -4
  76. wandb/sdk/data_types/html.py +1 -2
  77. wandb/sdk/data_types/image.py +11 -11
  78. wandb/sdk/data_types/molecule.py +3 -6
  79. wandb/sdk/data_types/object_3d.py +1 -2
  80. wandb/sdk/data_types/plotly.py +1 -2
  81. wandb/sdk/data_types/saved_model.py +10 -8
  82. wandb/sdk/data_types/video.py +1 -1
  83. wandb/sdk/integration_utils/data_logging.py +5 -5
  84. wandb/sdk/interface/artifacts.py +288 -266
  85. wandb/sdk/interface/interface.py +2 -3
  86. wandb/sdk/interface/interface_grpc.py +1 -1
  87. wandb/sdk/interface/interface_queue.py +1 -1
  88. wandb/sdk/interface/interface_relay.py +1 -1
  89. wandb/sdk/interface/interface_shared.py +1 -2
  90. wandb/sdk/interface/interface_sock.py +1 -1
  91. wandb/sdk/interface/message_future.py +1 -1
  92. wandb/sdk/interface/message_future_poll.py +1 -1
  93. wandb/sdk/interface/router.py +1 -1
  94. wandb/sdk/interface/router_queue.py +1 -1
  95. wandb/sdk/interface/router_relay.py +1 -1
  96. wandb/sdk/interface/router_sock.py +1 -1
  97. wandb/sdk/interface/summary_record.py +1 -1
  98. wandb/sdk/internal/artifacts.py +1 -1
  99. wandb/sdk/internal/datastore.py +2 -3
  100. wandb/sdk/internal/file_pusher.py +5 -3
  101. wandb/sdk/internal/file_stream.py +22 -19
  102. wandb/sdk/internal/handler.py +5 -4
  103. wandb/sdk/internal/internal.py +1 -1
  104. wandb/sdk/internal/internal_api.py +115 -55
  105. wandb/sdk/internal/job_builder.py +1 -3
  106. wandb/sdk/internal/profiler.py +1 -1
  107. wandb/sdk/internal/progress.py +4 -6
  108. wandb/sdk/internal/sample.py +1 -3
  109. wandb/sdk/internal/sender.py +28 -16
  110. wandb/sdk/internal/settings_static.py +5 -5
  111. wandb/sdk/internal/system/assets/__init__.py +1 -0
  112. wandb/sdk/internal/system/assets/cpu.py +3 -9
  113. wandb/sdk/internal/system/assets/disk.py +2 -4
  114. wandb/sdk/internal/system/assets/gpu.py +6 -18
  115. wandb/sdk/internal/system/assets/gpu_apple.py +2 -4
  116. wandb/sdk/internal/system/assets/interfaces.py +50 -22
  117. wandb/sdk/internal/system/assets/ipu.py +1 -3
  118. wandb/sdk/internal/system/assets/memory.py +7 -13
  119. wandb/sdk/internal/system/assets/network.py +4 -8
  120. wandb/sdk/internal/system/assets/open_metrics.py +283 -0
  121. wandb/sdk/internal/system/assets/tpu.py +1 -4
  122. wandb/sdk/internal/system/assets/trainium.py +26 -14
  123. wandb/sdk/internal/system/system_info.py +2 -3
  124. wandb/sdk/internal/system/system_monitor.py +52 -20
  125. wandb/sdk/internal/tb_watcher.py +12 -13
  126. wandb/sdk/launch/_project_spec.py +54 -65
  127. wandb/sdk/launch/agent/agent.py +374 -90
  128. wandb/sdk/launch/builder/abstract.py +61 -7
  129. wandb/sdk/launch/builder/build.py +81 -110
  130. wandb/sdk/launch/builder/docker_builder.py +181 -0
  131. wandb/sdk/launch/builder/kaniko_builder.py +419 -0
  132. wandb/sdk/launch/builder/noop.py +31 -12
  133. wandb/sdk/launch/builder/templates/_wandb_bootstrap.py +70 -20
  134. wandb/sdk/launch/environment/abstract.py +28 -0
  135. wandb/sdk/launch/environment/aws_environment.py +276 -0
  136. wandb/sdk/launch/environment/gcp_environment.py +271 -0
  137. wandb/sdk/launch/environment/local_environment.py +65 -0
  138. wandb/sdk/launch/github_reference.py +3 -8
  139. wandb/sdk/launch/launch.py +38 -29
  140. wandb/sdk/launch/launch_add.py +6 -8
  141. wandb/sdk/launch/loader.py +230 -0
  142. wandb/sdk/launch/registry/abstract.py +54 -0
  143. wandb/sdk/launch/registry/elastic_container_registry.py +163 -0
  144. wandb/sdk/launch/registry/google_artifact_registry.py +203 -0
  145. wandb/sdk/launch/registry/local_registry.py +62 -0
  146. wandb/sdk/launch/runner/abstract.py +1 -16
  147. wandb/sdk/launch/runner/{kubernetes.py → kubernetes_runner.py} +83 -95
  148. wandb/sdk/launch/runner/local_container.py +46 -22
  149. wandb/sdk/launch/runner/local_process.py +1 -4
  150. wandb/sdk/launch/runner/{aws.py → sagemaker_runner.py} +53 -212
  151. wandb/sdk/launch/runner/{gcp_vertex.py → vertex_runner.py} +38 -55
  152. wandb/sdk/launch/sweeps/__init__.py +3 -2
  153. wandb/sdk/launch/sweeps/scheduler.py +132 -39
  154. wandb/sdk/launch/sweeps/scheduler_sweep.py +80 -89
  155. wandb/sdk/launch/utils.py +101 -30
  156. wandb/sdk/launch/wandb_reference.py +2 -7
  157. wandb/sdk/lib/_settings_toposort_generate.py +166 -0
  158. wandb/sdk/lib/_settings_toposort_generated.py +201 -0
  159. wandb/sdk/lib/apikey.py +2 -4
  160. wandb/sdk/lib/config_util.py +4 -1
  161. wandb/sdk/lib/console.py +1 -3
  162. wandb/sdk/lib/deprecate.py +3 -3
  163. wandb/sdk/lib/file_stream_utils.py +7 -5
  164. wandb/sdk/lib/filenames.py +1 -1
  165. wandb/sdk/lib/filesystem.py +61 -5
  166. wandb/sdk/lib/git.py +1 -3
  167. wandb/sdk/lib/import_hooks.py +4 -7
  168. wandb/sdk/lib/ipython.py +8 -5
  169. wandb/sdk/lib/lazyloader.py +1 -3
  170. wandb/sdk/lib/mailbox.py +14 -4
  171. wandb/sdk/lib/proto_util.py +10 -5
  172. wandb/sdk/lib/redirect.py +15 -22
  173. wandb/sdk/lib/reporting.py +1 -3
  174. wandb/sdk/lib/retry.py +4 -5
  175. wandb/sdk/lib/runid.py +1 -3
  176. wandb/sdk/lib/server.py +15 -9
  177. wandb/sdk/lib/sock_client.py +1 -1
  178. wandb/sdk/lib/sparkline.py +1 -1
  179. wandb/sdk/lib/wburls.py +1 -1
  180. wandb/sdk/service/port_file.py +1 -2
  181. wandb/sdk/service/service.py +36 -13
  182. wandb/sdk/service/service_base.py +12 -1
  183. wandb/sdk/verify/verify.py +5 -7
  184. wandb/sdk/wandb_artifacts.py +142 -177
  185. wandb/sdk/wandb_config.py +5 -8
  186. wandb/sdk/wandb_helper.py +1 -1
  187. wandb/sdk/wandb_init.py +24 -13
  188. wandb/sdk/wandb_login.py +9 -9
  189. wandb/sdk/wandb_manager.py +39 -4
  190. wandb/sdk/wandb_metric.py +2 -6
  191. wandb/sdk/wandb_require.py +4 -15
  192. wandb/sdk/wandb_require_helpers.py +1 -9
  193. wandb/sdk/wandb_run.py +95 -141
  194. wandb/sdk/wandb_save.py +1 -3
  195. wandb/sdk/wandb_settings.py +149 -54
  196. wandb/sdk/wandb_setup.py +66 -46
  197. wandb/sdk/wandb_summary.py +13 -10
  198. wandb/sdk/wandb_sweep.py +6 -7
  199. wandb/sdk/wandb_watch.py +1 -1
  200. wandb/sklearn/calculate/confusion_matrix.py +1 -1
  201. wandb/sklearn/calculate/learning_curve.py +1 -1
  202. wandb/sklearn/calculate/summary_metrics.py +1 -3
  203. wandb/sklearn/plot/__init__.py +1 -1
  204. wandb/sklearn/plot/classifier.py +27 -18
  205. wandb/sklearn/plot/clusterer.py +4 -5
  206. wandb/sklearn/plot/regressor.py +4 -4
  207. wandb/sklearn/plot/shared.py +2 -2
  208. wandb/sync/__init__.py +1 -3
  209. wandb/sync/sync.py +4 -5
  210. wandb/testing/relay.py +11 -10
  211. wandb/trigger.py +1 -1
  212. wandb/util.py +106 -81
  213. wandb/viz.py +4 -4
  214. wandb/wandb_agent.py +50 -50
  215. wandb/wandb_controller.py +2 -3
  216. wandb/wandb_run.py +1 -2
  217. wandb/wandb_torch.py +1 -1
  218. wandb/xgboost/__init__.py +1 -2
  219. {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/METADATA +6 -2
  220. {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/RECORD +224 -209
  221. {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/WHEEL +1 -1
  222. wandb/sdk/launch/builder/docker.py +0 -80
  223. wandb/sdk/launch/builder/kaniko.py +0 -393
  224. wandb/sdk/launch/builder/loader.py +0 -32
  225. wandb/sdk/launch/runner/loader.py +0 -50
  226. {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/LICENSE +0 -0
  227. {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/entry_points.txt +0 -0
  228. {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,201 @@
1
+ # DO NOT EDIT -- GENERATED BY: `generate-tool.py --generate`
2
+ __all__ = ("SETTINGS_TOPOLOGICALLY_SORTED", "_Setting")
3
+
4
+ import sys
5
+ from typing import Tuple
6
+
7
+ if sys.version_info >= (3, 8):
8
+ from typing import Final, Literal
9
+ else:
10
+ from typing_extensions import Final, Literal
11
+
12
+
13
+ _Setting = Literal[
14
+ "_args",
15
+ "_cli_only_mode",
16
+ "_colab",
17
+ "_config_dict",
18
+ "_console",
19
+ "_cuda",
20
+ "_disable_meta",
21
+ "_disable_service",
22
+ "_disable_stats",
23
+ "_disable_viewer",
24
+ "_except_exit",
25
+ "_executable",
26
+ "_flow_control_custom",
27
+ "_flow_control_disabled",
28
+ "_internal_check_process",
29
+ "_internal_queue_timeout",
30
+ "_jupyter",
31
+ "_jupyter_name",
32
+ "_jupyter_path",
33
+ "_jupyter_root",
34
+ "_kaggle",
35
+ "_live_policy_rate_limit",
36
+ "_live_policy_wait_time",
37
+ "_log_level",
38
+ "_network_buffer",
39
+ "_noop",
40
+ "_offline",
41
+ "_sync",
42
+ "_os",
43
+ "_platform",
44
+ "_python",
45
+ "_runqueue_item_id",
46
+ "_save_requirements",
47
+ "_service_transport",
48
+ "_service_wait",
49
+ "_start_datetime",
50
+ "_start_time",
51
+ "_stats_pid",
52
+ "_stats_sample_rate_seconds",
53
+ "_stats_samples_to_average",
54
+ "_stats_join_assets",
55
+ "_stats_neuron_monitor_config_path",
56
+ "_stats_open_metrics_endpoints",
57
+ "_stats_open_metrics_filters",
58
+ "_tmp_code_dir",
59
+ "_tracelog",
60
+ "_unsaved_keys",
61
+ "_windows",
62
+ "allow_val_change",
63
+ "anonymous",
64
+ "api_key",
65
+ "base_url",
66
+ "code_dir",
67
+ "config_paths",
68
+ "console",
69
+ "deployment",
70
+ "disable_code",
71
+ "disable_git",
72
+ "disable_hints",
73
+ "disable_job_creation",
74
+ "disabled",
75
+ "docker",
76
+ "email",
77
+ "entity",
78
+ "files_dir",
79
+ "force",
80
+ "git_commit",
81
+ "git_remote",
82
+ "git_remote_url",
83
+ "git_root",
84
+ "heartbeat_seconds",
85
+ "host",
86
+ "ignore_globs",
87
+ "init_timeout",
88
+ "is_local",
89
+ "label_disable",
90
+ "launch",
91
+ "launch_config_path",
92
+ "log_dir",
93
+ "log_internal",
94
+ "log_symlink_internal",
95
+ "log_symlink_user",
96
+ "log_user",
97
+ "login_timeout",
98
+ "magic",
99
+ "mode",
100
+ "notebook_name",
101
+ "problem",
102
+ "program",
103
+ "program_relpath",
104
+ "project",
105
+ "project_url",
106
+ "quiet",
107
+ "reinit",
108
+ "relogin",
109
+ "resume",
110
+ "resume_fname",
111
+ "resumed",
112
+ "root_dir",
113
+ "run_group",
114
+ "run_id",
115
+ "run_job_type",
116
+ "run_mode",
117
+ "run_name",
118
+ "run_notes",
119
+ "run_tags",
120
+ "run_url",
121
+ "sagemaker_disable",
122
+ "save_code",
123
+ "settings_system",
124
+ "settings_workspace",
125
+ "show_colors",
126
+ "show_emoji",
127
+ "show_errors",
128
+ "show_info",
129
+ "show_warnings",
130
+ "silent",
131
+ "start_method",
132
+ "strict",
133
+ "summary_errors",
134
+ "summary_timeout",
135
+ "summary_warnings",
136
+ "sweep_id",
137
+ "sweep_param_path",
138
+ "sweep_url",
139
+ "symlink",
140
+ "sync_dir",
141
+ "sync_file",
142
+ "sync_symlink_latest",
143
+ "system_sample",
144
+ "system_sample_seconds",
145
+ "table_raise_on_max_row_limit_exceeded",
146
+ "timespec",
147
+ "tmp_dir",
148
+ "username",
149
+ "wandb_dir",
150
+ ]
151
+
152
+ SETTINGS_TOPOLOGICALLY_SORTED: Final[Tuple[_Setting, ...]] = (
153
+ "_service_wait",
154
+ "_stats_sample_rate_seconds",
155
+ "_stats_samples_to_average",
156
+ "anonymous",
157
+ "api_key",
158
+ "base_url",
159
+ "console",
160
+ "mode",
161
+ "problem",
162
+ "project",
163
+ "start_method",
164
+ "_colab",
165
+ "_console",
166
+ "_jupyter",
167
+ "_kaggle",
168
+ "_noop",
169
+ "disabled",
170
+ "_offline",
171
+ "_network_buffer",
172
+ "_flow_control_disabled",
173
+ "_flow_control_custom",
174
+ "_stats_neuron_monitor_config_path",
175
+ "run_id",
176
+ "run_mode",
177
+ "_start_datetime",
178
+ "timespec",
179
+ "root_dir",
180
+ "wandb_dir",
181
+ "tmp_dir",
182
+ "_tmp_code_dir",
183
+ "_windows",
184
+ "is_local",
185
+ "deployment",
186
+ "files_dir",
187
+ "log_dir",
188
+ "log_internal",
189
+ "log_symlink_internal",
190
+ "log_symlink_user",
191
+ "log_user",
192
+ "project_url",
193
+ "resume_fname",
194
+ "run_url",
195
+ "settings_system",
196
+ "settings_workspace",
197
+ "sweep_url",
198
+ "sync_dir",
199
+ "sync_file",
200
+ "sync_symlink_latest",
201
+ )
wandb/sdk/lib/apikey.py CHANGED
@@ -1,6 +1,4 @@
1
- """
2
- apikey util.
3
- """
1
+ """apikey util."""
4
2
 
5
3
  import os
6
4
  import stat
@@ -151,7 +149,7 @@ def prompt_api_key( # noqa: C901
151
149
 
152
150
 
153
151
  def write_netrc(host, entity, key):
154
- """Add our host and key to .netrc"""
152
+ """Add our host and key to .netrc."""
155
153
  key_prefix, key_suffix = key.split("-", 1) if "-" in key else ("", key)
156
154
  if len(key_suffix) != 40:
157
155
  wandb.termerror(
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import logging
3
3
  import os
4
+ from typing import Any, Dict, Optional
4
5
 
5
6
  import yaml
6
7
 
@@ -93,7 +94,9 @@ def save_config_file_from_dict(config_filename, config_dict):
93
94
  conf_file.write(data)
94
95
 
95
96
 
96
- def dict_from_config_file(filename, must_exist=False):
97
+ def dict_from_config_file(
98
+ filename: str, must_exist: bool = False
99
+ ) -> Optional[Dict[str, Any]]:
97
100
  if not os.path.exists(filename):
98
101
  if must_exist:
99
102
  raise ConfigError("config file %s doesn't exist" % filename)
wandb/sdk/lib/console.py CHANGED
@@ -1,6 +1,4 @@
1
- """
2
- console.
3
- """
1
+ """console."""
4
2
 
5
3
  import os
6
4
 
@@ -21,9 +21,9 @@ def deprecate(
21
21
  warning_message: str,
22
22
  run: Optional["wandb_run.Run"] = None,
23
23
  ) -> None:
24
- """
25
- Warn the user that a feature has been deprecated
26
- and store the information about the event in telemetry.
24
+ """Warn the user that a feature has been deprecated.
25
+
26
+ Also stores the information about the event in telemetry.
27
27
 
28
28
  Args:
29
29
  field_name: The name of the feature that has been deprecated.
@@ -5,14 +5,16 @@ from typing import Any, Dict, Iterable
5
5
  def split_files(
6
6
  files: Dict[str, Any], max_bytes: int = 10 * 1024 * 1024
7
7
  ) -> Iterable[Dict[str, Dict]]:
8
- """
9
- Splits a files dict (see `files` arg) into smaller dicts of at most `MAX_BYTES` size.
10
- This method is used in `FileStreamAPI._send()` to limit the size of post requests sent
11
- to wandb server.
8
+ """Split a file's dict (see `files` arg) into smaller dicts.
9
+
10
+ Each smaller dict will have at most `MAX_BYTES` size.
11
+
12
+ This method is used in `FileStreamAPI._send()` to limit the size of post requests
13
+ sent to wandb server.
12
14
 
13
15
  Arguments:
14
16
  files (dict): `dict` of form {file_name: {'content': ".....", 'offset': 0}}
15
- The key `file_name` can also be mapped to a List [{"offset": int, "content": str}]
17
+ The key `file_name` can also be mapped to a List [{"offset": int, "content": str}]
16
18
  `max_bytes`: max size for chunk in bytes
17
19
  """
18
20
  current_volume: Dict[str, Dict] = {}
@@ -31,7 +31,7 @@ def is_wandb_file(name: str) -> bool:
31
31
  def filtered_dir(
32
32
  root: str, include_fn: Callable[[str], bool], exclude_fn: Callable[[str], bool]
33
33
  ) -> Generator[str, None, None]:
34
- """Simple generator to walk a directory"""
34
+ """Simple generator to walk a directory."""
35
35
  for dirpath, _, files in os.walk(root):
36
36
  for fname in files:
37
37
  file_path = os.path.join(dirpath, fname)
@@ -1,21 +1,32 @@
1
+ import logging
1
2
  import os
3
+ import platform
2
4
  import re
5
+ import shutil
6
+ import stat
3
7
  import threading
4
8
  from typing import BinaryIO, Union
5
9
 
6
- AnyPath = Union[str, bytes, os.PathLike]
10
+ StrPath = Union[str, "os.PathLike[str]"]
7
11
 
12
+ logger = logging.getLogger(__name__)
8
13
 
9
- def mkdir_exists_ok(dir_name: AnyPath) -> None:
14
+ WRITE_PERMISSIONS = stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH | stat.S_IWRITE
15
+
16
+
17
+ def mkdir_exists_ok(dir_name: StrPath) -> None:
10
18
  """Create `dir_name` and any parent directories if they don't exist.
11
19
 
12
20
  Raises:
13
21
  FileExistsError: if `dir_name` exists and is not a directory.
14
22
  PermissionError: if `dir_name` is not writable.
15
23
  """
16
- os.makedirs(dir_name, exist_ok=True)
17
- if not os.access(dir_name, os.W_OK):
18
- raise PermissionError(f"{dir_name!s} is not writable")
24
+ try:
25
+ os.makedirs(dir_name, exist_ok=True)
26
+ except FileExistsError as e:
27
+ raise FileExistsError(f"{dir_name!s} exists and is not a directory") from e
28
+ except PermissionError as e:
29
+ raise PermissionError(f"{dir_name!s} is not writable") from e
19
30
 
20
31
 
21
32
  class WriteSerializingFile:
@@ -68,3 +79,48 @@ class CRDedupedFile(WriteSerializingFile):
68
79
  if self._buff:
69
80
  super().write(self._buff)
70
81
  super().close()
82
+
83
+
84
+ def copy_or_overwrite_changed(source_path: StrPath, target_path: StrPath) -> StrPath:
85
+ """Copy source_path to target_path, unless it already exists with the same mtime.
86
+
87
+ We liberally add write permissions to deal with the case of multiple users needing
88
+ to share the same cache or run directory.
89
+
90
+ Args:
91
+ source_path: The path to the file to copy.
92
+ target_path: The path to copy the file to.
93
+
94
+ Returns:
95
+ The path to the copied file (which may be different from target_path).
96
+ """
97
+ return_type = type(target_path)
98
+
99
+ if platform.system() == "Windows":
100
+ head, tail = os.path.splitdrive(str(target_path))
101
+ if ":" in tail:
102
+ logger.warning("Replacing ':' in %s with '-'", tail)
103
+ target_path = os.path.join(head, tail.replace(":", "-"))
104
+
105
+ need_copy = (
106
+ not os.path.isfile(target_path)
107
+ or os.stat(source_path).st_mtime != os.stat(target_path).st_mtime
108
+ )
109
+
110
+ permissions_plus_write = os.stat(source_path).st_mode | WRITE_PERMISSIONS
111
+ if need_copy:
112
+ mkdir_exists_ok(os.path.dirname(target_path))
113
+ try:
114
+ # Use copy2 to preserve file metadata (including modified time).
115
+ shutil.copy2(source_path, target_path)
116
+ except PermissionError:
117
+ # If the file is read-only try to make it writable.
118
+ try:
119
+ os.chmod(target_path, permissions_plus_write)
120
+ shutil.copy2(source_path, target_path)
121
+ except PermissionError as e:
122
+ raise PermissionError("Unable to overwrite '{target_path!s}'") from e
123
+ # Prevent future permissions issues by universal write permissions now.
124
+ os.chmod(target_path, permissions_plus_write)
125
+
126
+ return return_type(target_path) # type: ignore # 'os.PathLike' is abstract.
wandb/sdk/lib/git.py CHANGED
@@ -137,7 +137,6 @@ class GitRepo:
137
137
  if parsed.port is not None:
138
138
  hostname += ":" + str(parsed.port)
139
139
  if parsed.password is not None:
140
-
141
140
  return urlunparse(parsed._replace(netloc=f"{parsed.username}:@{hostname}"))
142
141
  return urlunparse(parsed._replace(netloc=hostname))
143
142
 
@@ -148,8 +147,7 @@ class GitRepo:
148
147
  return self.repo.git.rev_parse("--show-toplevel")
149
148
 
150
149
  def get_upstream_fork_point(self):
151
- """Get the most recent ancestor of HEAD that occurs on an upstream
152
- branch.
150
+ """Get the most recent ancestor of HEAD that occurs on an upstream branch.
153
151
 
154
152
  First looks at the current branch's tracking branch, if applicable. If
155
153
  that doesn't work, looks at every other branch to find the most recent
@@ -1,11 +1,10 @@
1
- """
1
+ """Implements a post-import hook mechanism.
2
+
3
+ Styled as per PEP-369. Note that it doesn't cope with modules being reloaded.
4
+
2
5
  Note: This file is based on
3
6
  https://github.com/GrahamDumpleton/wrapt/blob/1.12.1/src/wrapt/importer.py
4
7
  (with slight modifications).
5
-
6
- This module implements a post import hook mechanism styled after what is
7
- described in PEP-369. Note that it doesn't cope with modules being reloaded.
8
-
9
8
  """
10
9
 
11
10
  import functools
@@ -92,7 +91,6 @@ def register_post_import_hook(hook: Callable, hook_id: str, name: str) -> None:
92
91
  module = sys.modules.get(name)
93
92
 
94
93
  if module is not None:
95
-
96
94
  _post_import_hooks[name] = {}
97
95
  if hook: # type: ignore
98
96
  hook(module)
@@ -230,7 +228,6 @@ class ImportHookFinder:
230
228
  # Now call back into the import system again.
231
229
 
232
230
  try:
233
-
234
231
  # For Python 3 we need to use find_spec().loader
235
232
  # from the importlib.util module. It doesn't actually
236
233
  # import the target module and only finds the
wandb/sdk/lib/ipython.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import sys
3
+ import warnings
3
4
  from typing import Optional
4
5
 
5
6
  import wandb
@@ -39,7 +40,7 @@ def in_jupyter() -> bool:
39
40
 
40
41
 
41
42
  def display_html(html: str): # type: ignore
42
- """Displays HTML in notebooks, is a noop outside of a jupyter context"""
43
+ """Display HTML in notebooks, is a noop outside of a jupyter context."""
43
44
  if wandb.run and wandb.run._settings.silent:
44
45
  return
45
46
  try:
@@ -51,7 +52,7 @@ def display_html(html: str): # type: ignore
51
52
 
52
53
 
53
54
  def display_widget(widget):
54
- """Displays ipywidgets in notebooks, is a noop outside of a jupyter context"""
55
+ """Display ipywidgets in notebooks, is a noop outside of a jupyter context."""
55
56
  if wandb.run and wandb.run._settings.silent:
56
57
  return
57
58
  try:
@@ -65,7 +66,7 @@ def display_widget(widget):
65
66
 
66
67
 
67
68
  class ProgressWidget:
68
- """A simple wrapper to render a nice progress bar with a label"""
69
+ """A simple wrapper to render a nice progress bar with a label."""
69
70
 
70
71
  def __init__(self, widgets, min, max):
71
72
  self.widgets = widgets
@@ -98,12 +99,14 @@ class ProgressWidget:
98
99
 
99
100
 
100
101
  def jupyter_progress_bar(min: float = 0, max: float = 1.0) -> Optional[ProgressWidget]:
101
- """Returns an ipywidget progress bar or None if we can't import it"""
102
+ """Return an ipywidget progress bar or None if we can't import it."""
102
103
  widgets = wandb.util.get_module("ipywidgets")
103
104
  try:
104
105
  if widgets is None:
105
106
  # TODO: this currently works in iPython but it's deprecated since 4.0
106
- from IPython.html import widgets # type: ignore
107
+ with warnings.catch_warnings():
108
+ warnings.simplefilter("ignore")
109
+ from IPython.html import widgets # type: ignore
107
110
 
108
111
  assert hasattr(widgets, "VBox")
109
112
  assert hasattr(widgets, "Label")
@@ -1,6 +1,4 @@
1
- """
2
- module lazyloader
3
- """
1
+ """module lazyloader."""
4
2
 
5
3
 
6
4
  import importlib
wandb/sdk/lib/mailbox.py CHANGED
@@ -1,6 +1,4 @@
1
- """
2
- mailbox.
3
- """
1
+ """mailbox."""
4
2
 
5
3
  import secrets
6
4
  import string
@@ -8,7 +6,7 @@ import threading
8
6
  import time
9
7
  from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
10
8
 
11
- from wandb.errors import MailboxError
9
+ from wandb.errors import Error
12
10
  from wandb.proto import wandb_internal_pb2 as pb
13
11
 
14
12
  if TYPE_CHECKING:
@@ -22,6 +20,18 @@ def _generate_address(length: int = 12) -> str:
22
20
  return address
23
21
 
24
22
 
23
+ class MailboxError(Error):
24
+ """Generic Mailbox Exception."""
25
+
26
+ pass
27
+
28
+
29
+ class ContextCancelledError(MailboxError):
30
+ """Context cancelled Exception."""
31
+
32
+ pass
33
+
34
+
25
35
  class _MailboxWaitAll:
26
36
  _event: threading.Event
27
37
  _lock: threading.Lock
@@ -72,7 +72,8 @@ def settings_dict_from_pbmap(
72
72
  for k in pbmap:
73
73
  v_obj = pbmap[k]
74
74
  v_type = v_obj.WhichOneof("value_type")
75
- v: Union[int, str, float, None, tuple, datetime] = None
75
+
76
+ v: Union[int, str, float, None, tuple, dict, datetime] = None
76
77
  if v_type == "int_value":
77
78
  v = v_obj.int_value
78
79
  elif v_type == "string_value":
@@ -85,6 +86,13 @@ def settings_dict_from_pbmap(
85
86
  v = None
86
87
  elif v_type == "tuple_value":
87
88
  v = tuple(v_obj.tuple_value.string_values)
89
+ elif v_type == "map_value":
90
+ v = dict(v_obj.map_value.map_values)
91
+ elif v_type == "nested_map_value":
92
+ v = {
93
+ k: dict(vv.map_values)
94
+ for k, vv in dict(v_obj.nested_map_value.nested_map_values).items()
95
+ }
88
96
  elif v_type == "timestamp_value":
89
97
  v = datetime.strptime(v_obj.timestamp_value, "%Y%m%d_%H%M%S")
90
98
  d[k] = v
@@ -94,10 +102,7 @@ def settings_dict_from_pbmap(
94
102
  def message_to_dict(
95
103
  message: "Message",
96
104
  ) -> Dict[str, Any]:
97
- """
98
- Converts a protobuf message into a dictionary.
99
- """
100
-
105
+ """Convert a protobuf message into a dictionary."""
101
106
  from google.protobuf.json_format import MessageToDict
102
107
 
103
108
  return MessageToDict(message, preserving_proto_field_name=True)
wandb/sdk/lib/redirect.py CHANGED
@@ -104,9 +104,7 @@ def _get_char(code):
104
104
 
105
105
 
106
106
  class Char:
107
- """
108
- Class encapsulating a single character, its foreground, background and style attributes
109
- """
107
+ """Class encapsulating a single character, its foreground, background and style attributes."""
110
108
 
111
109
  __slots__ = (
112
110
  "data",
@@ -174,17 +172,17 @@ _defchar = Char()
174
172
 
175
173
 
176
174
  class Cursor:
177
- """
178
- 2D cursor
175
+ """A 2D cursor.
176
+
177
+ Attributes:
178
+ x: x-coordinate.
179
+ y: y-coordinate.
180
+ char: the character to inherit colors and styles from.
179
181
  """
180
182
 
181
183
  __slots__ = ("x", "y", "char")
182
184
 
183
185
  def __init__(self, x=0, y=0, char=None):
184
- """
185
- x, y - 2D coordinates
186
- char - Next character to be written will inherit colors and styles from this character
187
- """
188
186
  if char is None:
189
187
  char = Char()
190
188
  self.x = x
@@ -193,8 +191,9 @@ class Cursor:
193
191
 
194
192
 
195
193
  class TerminalEmulator:
196
- """
197
- An FSM emulating a terminal. Characters are stored in a 2D matrix (buffer) indexed by the cursor.
194
+ """An FSM emulating a terminal.
195
+
196
+ Characters are stored in a 2D matrix (buffer) indexed by the cursor.
198
197
  """
199
198
 
200
199
  _MAX_LINES = 100
@@ -488,8 +487,7 @@ _MIN_CALLBACK_INTERVAL = 2 # seconds
488
487
 
489
488
  class RedirectBase:
490
489
  def __init__(self, src, cbs=()):
491
- """
492
- # Arguments
490
+ """# Arguments.
493
491
 
494
492
  `src`: Source stream to be redirected. "stdout" or "stderr".
495
493
  `cbs`: tuple/list of callbacks. Each callback should take exactly 1 argument (bytes).
@@ -527,9 +525,7 @@ class RedirectBase:
527
525
 
528
526
 
529
527
  class StreamWrapper(RedirectBase):
530
- """
531
- Patches the write method of current sys.stdout/sys.stderr
532
- """
528
+ """Patches the write method of current sys.stdout/sys.stderr."""
533
529
 
534
530
  def __init__(self, src, cbs=()):
535
531
  super().__init__(src=src, cbs=cbs)
@@ -620,8 +616,7 @@ class StreamWrapper(RedirectBase):
620
616
 
621
617
 
622
618
  class StreamRawWrapper(RedirectBase):
623
- """
624
- Patches the write method of current sys.stdout/sys.stderr
619
+ """Patches the write method of current sys.stdout/sys.stderr.
625
620
 
626
621
  Captures data in a raw form rather than using the emulator
627
622
  """
@@ -697,7 +692,7 @@ class _WindowSizeChangeHandler:
697
692
  win_size = fcntl.ioctl(0, termios.TIOCGWINSZ, "\0" * 8)
698
693
  rows, cols, xpix, ypix = struct.unpack("HHHH", win_size)
699
694
  # Note: IOError not subclass of OSError in python 2.x
700
- except OSError: # eg. in MPI we can't do this. # noqa
695
+ except OSError: # eg. in MPI we can't do this.
701
696
  return
702
697
  if cols == 0:
703
698
  return
@@ -710,9 +705,7 @@ _WSCH = _WindowSizeChangeHandler()
710
705
 
711
706
 
712
707
  class Redirect(RedirectBase):
713
- """
714
- Redirects low level file descriptors.
715
- """
708
+ """Redirect low level file descriptors."""
716
709
 
717
710
  def __init__(self, src, cbs=()):
718
711
  super().__init__(src=src, cbs=cbs)
@@ -1,6 +1,4 @@
1
- """
2
- reporting.
3
- """
1
+ """reporting."""
4
2
 
5
3
  import logging
6
4